]> gcc.gnu.org Git - gcc.git/blame - gcc/f/com.c
hackshell.tpl: Fix mis-applied patch.
[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
216#define FFECOM_FASTER_ARRAY_REFS 0 /* Generates faster code? */
217
218#if FFECOM_targetCURRENT == FFECOM_targetGCC
219
220/* tree.h declares a bunch of stuff that it expects the front end to
221 define. Here are the definitions, which in the C front end are
222 found in the file c-decl.c. */
223
224tree integer_zero_node;
225tree integer_one_node;
226tree null_pointer_node;
227tree error_mark_node;
228tree void_type_node;
229tree integer_type_node;
230tree unsigned_type_node;
231tree char_type_node;
232tree current_function_decl;
233
c7e4ee3a
CB
234/* ~~gcc/tree.h *should* declare this, because toplev.c and dwarfout.c
235 reference it. */
5ff904cd
JL
236
237char *language_string = "GNU F77";
238
77f77701
DB
239/* Stream for reading from the input file. */
240FILE *finput;
241
5ff904cd
JL
242/* These definitions parallel those in c-decl.c so that code from that
243 module can be used pretty much as is. Much of these defs aren't
244 otherwise used, i.e. by g77 code per se, except some of them are used
245 to build some of them that are. The ones that are global (i.e. not
246 "static") are those that ste.c and such might use (directly
247 or by using com macros that reference them in their definitions). */
248
249static tree short_integer_type_node;
250tree long_integer_type_node;
251static tree long_long_integer_type_node;
252
253static tree short_unsigned_type_node;
254static tree long_unsigned_type_node;
255static tree long_long_unsigned_type_node;
256
257static tree unsigned_char_type_node;
258static tree signed_char_type_node;
259
260static tree float_type_node;
261static tree double_type_node;
262static tree complex_float_type_node;
263tree complex_double_type_node;
264static tree long_double_type_node;
265static tree complex_integer_type_node;
266static tree complex_long_double_type_node;
267
268tree string_type_node;
269
270static tree double_ftype_double;
271static tree float_ftype_float;
272static tree ldouble_ftype_ldouble;
273
274/* The rest of these are inventions for g77, though there might be
275 similar things in the C front end. As they are found, these
276 inventions should be renamed to be canonical. Note that only
277 the ones currently required to be global are so. */
278
279static tree ffecom_tree_fun_type_void;
280static tree ffecom_tree_ptr_to_fun_type_void;
281
282tree ffecom_integer_type_node; /* Abbrev for _tree_type[blah][blah]. */
283tree ffecom_integer_zero_node; /* Like *_*_* with g77's integer type. */
284tree ffecom_integer_one_node; /* " */
285tree ffecom_tree_type[FFEINFO_basictype][FFEINFO_kindtype];
286
287/* _fun_type things are the f2c-specific versions. For -fno-f2c,
288 just use build_function_type and build_pointer_type on the
289 appropriate _tree_type array element. */
290
291static tree ffecom_tree_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
292static tree ffecom_tree_ptr_to_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
293static tree ffecom_tree_subr_type;
294static tree ffecom_tree_ptr_to_subr_type;
295static tree ffecom_tree_blockdata_type;
296
297static tree ffecom_tree_xargc_;
298
299ffecomSymbol ffecom_symbol_null_
300=
301{
302 NULL_TREE,
303 NULL_TREE,
304 NULL_TREE,
0816ebdd
KG
305 NULL_TREE,
306 false
5ff904cd
JL
307};
308ffeinfoKindtype ffecom_pointer_kind_ = FFEINFO_basictypeNONE;
309ffeinfoKindtype ffecom_label_kind_ = FFEINFO_basictypeNONE;
310
311int ffecom_f2c_typecode_[FFEINFO_basictype][FFEINFO_kindtype];
312tree ffecom_f2c_integer_type_node;
313tree ffecom_f2c_ptr_to_integer_type_node;
314tree ffecom_f2c_address_type_node;
315tree ffecom_f2c_real_type_node;
316tree ffecom_f2c_ptr_to_real_type_node;
317tree ffecom_f2c_doublereal_type_node;
318tree ffecom_f2c_complex_type_node;
319tree ffecom_f2c_doublecomplex_type_node;
320tree ffecom_f2c_longint_type_node;
321tree ffecom_f2c_logical_type_node;
322tree ffecom_f2c_flag_type_node;
323tree ffecom_f2c_ftnlen_type_node;
324tree ffecom_f2c_ftnlen_zero_node;
325tree ffecom_f2c_ftnlen_one_node;
326tree ffecom_f2c_ftnlen_two_node;
327tree ffecom_f2c_ptr_to_ftnlen_type_node;
328tree ffecom_f2c_ftnint_type_node;
329tree ffecom_f2c_ptr_to_ftnint_type_node;
330#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
331
332/* Simple definitions and enumerations. */
333
334#ifndef FFECOM_sizeMAXSTACKITEM
335#define FFECOM_sizeMAXSTACKITEM 32*1024 /* Keep user-declared things
336 larger than this # bytes
337 off stack if possible. */
338#endif
339
340/* For systems that have large enough stacks, they should define
341 this to 0, and here, for ease of use later on, we just undefine
342 it if it is 0. */
343
344#if FFECOM_sizeMAXSTACKITEM == 0
345#undef FFECOM_sizeMAXSTACKITEM
346#endif
347
348typedef enum
349 {
350 FFECOM_rttypeVOID_,
6d433196 351 FFECOM_rttypeVOIDSTAR_, /* C's `void *' type. */
795232f7
JL
352 FFECOM_rttypeFTNINT_, /* f2c's `ftnint' type. */
353 FFECOM_rttypeINTEGER_, /* f2c's `integer' type. */
354 FFECOM_rttypeLONGINT_, /* f2c's `longint' type. */
355 FFECOM_rttypeLOGICAL_, /* f2c's `logical' type. */
356 FFECOM_rttypeREAL_F2C_, /* f2c's `real' returned as `double'. */
357 FFECOM_rttypeREAL_GNU_, /* `real' returned as such. */
5ff904cd 358 FFECOM_rttypeCOMPLEX_F2C_, /* f2c's `complex' returned via 1st arg. */
795232f7 359 FFECOM_rttypeCOMPLEX_GNU_, /* f2c's `complex' returned directly. */
5ff904cd 360 FFECOM_rttypeDOUBLE_, /* C's `double' type. */
795232f7 361 FFECOM_rttypeDOUBLEREAL_, /* f2c's `doublereal' type. */
5ff904cd 362 FFECOM_rttypeDBLCMPLX_F2C_, /* f2c's `doublecomplex' returned via 1st arg. */
795232f7 363 FFECOM_rttypeDBLCMPLX_GNU_, /* f2c's `doublecomplex' returned directly. */
5ff904cd
JL
364 FFECOM_rttypeCHARACTER_, /* f2c `char *'/`ftnlen' pair. */
365 FFECOM_rttype_
366 } ffecomRttype_;
367
368/* Internal typedefs. */
369
370#if FFECOM_targetCURRENT == FFECOM_targetGCC
371typedef struct _ffecom_concat_list_ ffecomConcatList_;
5ff904cd
JL
372#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
373
374/* Private include files. */
375
376
377/* Internal structure definitions. */
378
379#if FFECOM_targetCURRENT == FFECOM_targetGCC
380struct _ffecom_concat_list_
381 {
382 ffebld *exprs;
383 int count;
384 int max;
385 ffetargetCharacterSize minlen;
386 ffetargetCharacterSize maxlen;
387 };
5ff904cd
JL
388#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
389
390/* Static functions (internal). */
391
392#if FFECOM_targetCURRENT == FFECOM_targetGCC
26f096f9 393static tree ffecom_arglist_expr_ (const char *argstring, ffebld args);
5ff904cd
JL
394static tree ffecom_widest_expr_type_ (ffebld list);
395static bool ffecom_overlap_ (tree dest_decl, tree dest_offset,
396 tree dest_size, tree source_tree,
397 ffebld source, bool scalar_arg);
398static bool ffecom_args_overlapping_ (tree dest_tree, ffebld dest,
399 tree args, tree callee_commons,
400 bool scalar_args);
26f096f9 401static tree ffecom_build_f2c_string_ (int i, const char *s);
5ff904cd
JL
402static tree ffecom_call_ (tree fn, ffeinfoKindtype kt,
403 bool is_f2c_complex, tree type,
404 tree args, tree dest_tree,
405 ffebld dest, bool *dest_used,
c7e4ee3a 406 tree callee_commons, bool scalar_args, tree hook);
5ff904cd
JL
407static tree ffecom_call_binop_ (tree fn, ffeinfoKindtype kt,
408 bool is_f2c_complex, tree type,
409 ffebld left, ffebld right,
410 tree dest_tree, ffebld dest,
411 bool *dest_used, tree callee_commons,
c7e4ee3a 412 bool scalar_args, tree hook);
86fc7a6c
CB
413static void ffecom_char_args_x_ (tree *xitem, tree *length,
414 ffebld expr, bool with_null);
5ff904cd
JL
415static tree ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy);
416static tree ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s);
417static ffecomConcatList_
418 ffecom_concat_list_gather_ (ffecomConcatList_ catlist,
419 ffebld expr,
420 ffetargetCharacterSize max);
421static void ffecom_concat_list_kill_ (ffecomConcatList_ catlist);
422static ffecomConcatList_ ffecom_concat_list_new_ (ffebld expr,
423 ffetargetCharacterSize max);
26f096f9
KG
424static void ffecom_debug_kludge_ (tree aggr, const char *aggr_type,
425 ffesymbol member, tree member_type,
426 ffetargetOffset offset);
5ff904cd 427static void ffecom_do_entry_ (ffesymbol fn, int entrynum);
092a4ef8
RH
428static tree ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
429 bool *dest_used, bool assignp, bool widenp);
5ff904cd
JL
430static tree ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
431 ffebld dest, bool *dest_used);
c7e4ee3a 432static tree ffecom_expr_power_integer_ (ffebld expr);
5ff904cd 433static void ffecom_expr_transform_ (ffebld expr);
26f096f9 434static void ffecom_f2c_make_type_ (tree *type, int tcode, const char *name);
5ff904cd
JL
435static void ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
436 int code);
437static ffeglobal ffecom_finish_global_ (ffeglobal global);
438static ffesymbol ffecom_finish_symbol_transform_ (ffesymbol s);
26f096f9 439static tree ffecom_get_appended_identifier_ (char us, const char *text);
5ff904cd 440static tree ffecom_get_external_identifier_ (ffesymbol s);
26f096f9 441static tree ffecom_get_identifier_ (const char *text);
5ff904cd
JL
442static tree ffecom_gen_sfuncdef_ (ffesymbol s,
443 ffeinfoBasictype bt,
444 ffeinfoKindtype kt);
26f096f9 445static const char *ffecom_gfrt_args_ (ffecomGfrt ix);
5ff904cd
JL
446static tree ffecom_gfrt_tree_ (ffecomGfrt ix);
447static tree ffecom_init_zero_ (tree decl);
448static tree ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
449 tree *maybe_tree);
450static tree ffecom_intrinsic_len_ (ffebld expr);
451static void ffecom_let_char_ (tree dest_tree,
452 tree dest_length,
453 ffetargetCharacterSize dest_size,
454 ffebld source);
455static void ffecom_make_gfrt_ (ffecomGfrt ix);
456static void ffecom_member_phase1_ (ffestorag mst, ffestorag st);
457#ifdef SOMEONE_GETS_DEBUG_SUPPORT_WORKING
458static void ffecom_member_phase2_ (ffestorag mst, ffestorag st);
459#endif
c7e4ee3a
CB
460static void ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size,
461 ffebld source);
5ff904cd
JL
462static void ffecom_push_dummy_decls_ (ffebld dumlist,
463 bool stmtfunc);
464static void ffecom_start_progunit_ (void);
465static ffesymbol ffecom_sym_transform_ (ffesymbol s);
466static ffesymbol ffecom_sym_transform_assign_ (ffesymbol s);
467static void ffecom_transform_common_ (ffesymbol s);
468static void ffecom_transform_equiv_ (ffestorag st);
469static tree ffecom_transform_namelist_ (ffesymbol s);
470static void ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
471 tree t);
472static void ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
473 tree *size, tree tree);
474static tree ffecom_tree_divide_ (tree tree_type, tree left, tree right,
475 tree dest_tree, ffebld dest,
c7e4ee3a 476 bool *dest_used, tree hook);
5ff904cd
JL
477static tree ffecom_type_localvar_ (ffesymbol s,
478 ffeinfoBasictype bt,
479 ffeinfoKindtype kt);
480static tree ffecom_type_namelist_ (void);
481#if 0
482static tree ffecom_type_permanent_copy_ (tree t);
483#endif
484static tree ffecom_type_vardesc_ (void);
485static tree ffecom_vardesc_ (ffebld expr);
486static tree ffecom_vardesc_array_ (ffesymbol s);
487static tree ffecom_vardesc_dims_ (ffesymbol s);
26f096f9
KG
488static tree ffecom_convert_narrow_ (tree type, tree expr);
489static tree ffecom_convert_widen_ (tree type, tree expr);
5ff904cd
JL
490#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
491
492/* These are static functions that parallel those found in the C front
493 end and thus have the same names. */
494
495#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a 496static tree bison_rule_compstmt_ (void);
5ff904cd 497static void bison_rule_pushlevel_ (void);
26f096f9 498static tree builtin_function (const char *name, tree type,
5ff904cd 499 enum built_in_function function_code,
26f096f9 500 const char *library_name);
c7e4ee3a 501static void delete_block (tree block);
5ff904cd
JL
502static int duplicate_decls (tree newdecl, tree olddecl);
503static void finish_decl (tree decl, tree init, bool is_top_level);
504static void finish_function (int nested);
8f87a563 505static char *lang_printable_name (tree decl, int v);
5ff904cd
JL
506static tree lookup_name_current_level (tree name);
507static struct binding_level *make_binding_level (void);
508static void pop_f_function_context (void);
509static void push_f_function_context (void);
510static void push_parm_decl (tree parm);
511static tree pushdecl_top_level (tree decl);
c7e4ee3a 512static int kept_level_p (void);
5ff904cd
JL
513static tree storedecls (tree decls);
514static void store_parm_decls (int is_main_program);
515static tree start_decl (tree decl, bool is_top_level);
516static void start_function (tree name, tree type, int nested, int public);
517#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
518#if FFECOM_GCC_INCLUDE
519static void ffecom_file_ (char *name);
520static void ffecom_initialize_char_syntax_ (void);
521static void ffecom_close_include_ (FILE *f);
522static int ffecom_decode_include_option_ (char *spec);
523static FILE *ffecom_open_include_ (char *name, ffewhereLine l,
524 ffewhereColumn c);
525#endif /* FFECOM_GCC_INCLUDE */
526
527/* Static objects accessed by functions in this module. */
528
529static ffesymbol ffecom_primary_entry_ = NULL;
530static ffesymbol ffecom_nested_entry_ = NULL;
531static ffeinfoKind ffecom_primary_entry_kind_;
532static bool ffecom_primary_entry_is_proc_;
533#if FFECOM_targetCURRENT == FFECOM_targetGCC
534static tree ffecom_outer_function_decl_;
535static tree ffecom_previous_function_decl_;
536static tree ffecom_which_entrypoint_decl_;
5ff904cd
JL
537static tree ffecom_float_zero_ = NULL_TREE;
538static tree ffecom_float_half_ = NULL_TREE;
539static tree ffecom_double_zero_ = NULL_TREE;
540static tree ffecom_double_half_ = NULL_TREE;
541static tree ffecom_func_result_;/* For functions. */
542static tree ffecom_func_length_;/* For CHARACTER fns. */
543static ffebld ffecom_list_blockdata_;
544static ffebld ffecom_list_common_;
545static ffebld ffecom_master_arglist_;
546static ffeinfoBasictype ffecom_master_bt_;
547static ffeinfoKindtype ffecom_master_kt_;
548static ffetargetCharacterSize ffecom_master_size_;
549static int ffecom_num_fns_ = 0;
550static int ffecom_num_entrypoints_ = 0;
551static bool ffecom_is_altreturning_ = FALSE;
552static tree ffecom_multi_type_node_;
553static tree ffecom_multi_retval_;
554static tree
555 ffecom_multi_fields_[FFEINFO_basictype][FFEINFO_kindtype];
556static bool ffecom_member_namelisted_; /* _member_phase1_ namelisted? */
557static bool ffecom_doing_entry_ = FALSE;
558static bool ffecom_transform_only_dummies_ = FALSE;
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
631/* NOTE: g77 currently doesn't use these; see setting of sizetype and
632 change that if you need to. -- jcb 09/01/91. */
633
5ff904cd
JL
634#define ffecom_concat_list_count_(catlist) ((catlist).count)
635#define ffecom_concat_list_expr_(catlist,i) ((catlist).exprs[(i)])
636#define ffecom_concat_list_maxlen_(catlist) ((catlist).maxlen)
637#define ffecom_concat_list_minlen_(catlist) ((catlist).minlen)
638
86fc7a6c
CB
639#define ffecom_char_args_(i,l,e) ffecom_char_args_x_((i),(l),(e),FALSE)
640#define ffecom_char_args_with_null_(i,l,e) ffecom_char_args_x_((i),(l),(e),TRUE)
641
5ff904cd
JL
642/* For each binding contour we allocate a binding_level structure
643 * which records the names defined in that contour.
644 * Contours include:
645 * 0) the global one
646 * 1) one for each function definition,
647 * where internal declarations of the parameters appear.
648 *
649 * The current meaning of a name can be found by searching the levels from
650 * the current one out to the global one.
651 */
652
653/* Note that the information in the `names' component of the global contour
654 is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
655
656struct binding_level
657 {
c7e4ee3a
CB
658 /* A chain of _DECL nodes for all variables, constants, functions,
659 and typedef types. These are in the reverse of the order supplied.
660 */
5ff904cd
JL
661 tree names;
662
c7e4ee3a
CB
663 /* For each level (except not the global one),
664 a chain of BLOCK nodes for all the levels
665 that were entered and exited one level down. */
5ff904cd
JL
666 tree blocks;
667
c7e4ee3a
CB
668 /* The BLOCK node for this level, if one has been preallocated.
669 If 0, the BLOCK is allocated (if needed) when the level is popped. */
5ff904cd
JL
670 tree this_block;
671
672 /* The binding level which this one is contained in (inherits from). */
673 struct binding_level *level_chain;
c7e4ee3a
CB
674
675 /* 0: no ffecom_prepare_* functions called at this level yet;
676 1: ffecom_prepare* functions called, except not ffecom_prepare_end;
677 2: ffecom_prepare_end called. */
678 int prep_state;
5ff904cd
JL
679 };
680
681#define NULL_BINDING_LEVEL (struct binding_level *) NULL
682
683/* The binding level currently in effect. */
684
685static struct binding_level *current_binding_level;
686
687/* A chain of binding_level structures awaiting reuse. */
688
689static struct binding_level *free_binding_level;
690
691/* The outermost binding level, for names of file scope.
692 This is created when the compiler is started and exists
693 through the entire run. */
694
695static struct binding_level *global_binding_level;
696
697/* Binding level structures are initialized by copying this one. */
698
699static struct binding_level clear_binding_level
700=
c7e4ee3a 701{NULL, NULL, NULL, NULL_BINDING_LEVEL, 0};
5ff904cd
JL
702
703/* Language-dependent contents of an identifier. */
704
705struct lang_identifier
706 {
707 struct tree_identifier ignore;
708 tree global_value, local_value, label_value;
709 bool invented;
710 };
711
712/* Macros for access to language-specific slots in an identifier. */
713/* Each of these slots contains a DECL node or null. */
714
715/* This represents the value which the identifier has in the
716 file-scope namespace. */
717#define IDENTIFIER_GLOBAL_VALUE(NODE) \
718 (((struct lang_identifier *)(NODE))->global_value)
719/* This represents the value which the identifier has in the current
720 scope. */
721#define IDENTIFIER_LOCAL_VALUE(NODE) \
722 (((struct lang_identifier *)(NODE))->local_value)
723/* This represents the value which the identifier has as a label in
724 the current label scope. */
725#define IDENTIFIER_LABEL_VALUE(NODE) \
726 (((struct lang_identifier *)(NODE))->label_value)
727/* This is nonzero if the identifier was "made up" by g77 code. */
728#define IDENTIFIER_INVENTED(NODE) \
729 (((struct lang_identifier *)(NODE))->invented)
730
731/* In identifiers, C uses the following fields in a special way:
732 TREE_PUBLIC to record that there was a previous local extern decl.
733 TREE_USED to record that such a decl was used.
734 TREE_ADDRESSABLE to record that the address of such a decl was used. */
735
736/* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
737 that have names. Here so we can clear out their names' definitions
738 at the end of the function. */
739
740static tree named_labels;
741
742/* A list of LABEL_DECLs from outer contexts that are currently shadowed. */
743
744static tree shadowed_labels;
745
746#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
747\f
6b55276e
CB
748/* Return the subscript expression, modified to do range-checking.
749
750 `array' is the array to be checked against.
751 `element' is the subscript expression to check.
752 `dim' is the dimension number (starting at 0).
753 `total_dims' is the total number of dimensions (0 for CHARACTER substring).
754*/
755
756static tree
757ffecom_subscript_check_ (tree array, tree element, int dim, int total_dims,
758 char *array_name)
759{
760 tree low = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
761 tree high = TYPE_MAX_VALUE (TYPE_DOMAIN (array));
762 tree cond;
763 tree die;
764 tree args;
765
766 if (element == error_mark_node)
767 return element;
768
769 element = ffecom_save_tree (element);
770 cond = ffecom_2 (LE_EXPR, integer_type_node,
771 low,
772 element);
773 if (high)
774 {
775 cond = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
776 cond,
777 ffecom_2 (LE_EXPR, integer_type_node,
778 element,
779 high));
780 }
781
782 {
783 int len;
784 char *proc;
785 char *var;
786 tree arg3;
787 tree arg2;
788 tree arg1;
789 tree arg4;
790
791 switch (total_dims)
792 {
793 case 0:
794 var = xmalloc (strlen (array_name) + 20);
795 sprintf (&var[0], "%s[%s-substring]",
796 array_name,
797 dim ? "end" : "start");
798 len = strlen (var) + 1;
799 break;
800
801 case 1:
802 len = strlen (array_name) + 1;
803 var = array_name;
804 break;
805
806 default:
807 var = xmalloc (strlen (array_name) + 40);
808 sprintf (&var[0], "%s[subscript-%d-of-%d]",
809 array_name,
810 dim + 1, total_dims);
811 len = strlen (var) + 1;
812 break;
813 }
814
815 arg1 = build_string (len, var);
816
817 if (total_dims != 1)
818 free (var);
819
820 TREE_TYPE (arg1)
821 = build_type_variant (build_array_type (char_type_node,
822 build_range_type
823 (integer_type_node,
824 integer_one_node,
825 build_int_2 (len, 0))),
826 1, 0);
827 TREE_CONSTANT (arg1) = 1;
828 TREE_STATIC (arg1) = 1;
829 arg1 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg1)),
830 arg1);
831
832 /* s_rnge adds one to the element to print it, so bias against
833 that -- want to print a faithful *subscript* value. */
834 arg2 = convert (ffecom_f2c_ftnint_type_node,
835 ffecom_2 (MINUS_EXPR,
836 TREE_TYPE (element),
837 element,
838 convert (TREE_TYPE (element),
839 integer_one_node)));
840
841 proc = xmalloc ((len = strlen (input_filename)
842 + IDENTIFIER_LENGTH (DECL_NAME (current_function_decl))
843 + 2));
844
845 sprintf (&proc[0], "%s/%s",
846 input_filename,
847 IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
848 arg3 = build_string (len, proc);
849
850 free (proc);
851
852 TREE_TYPE (arg3)
853 = build_type_variant (build_array_type (char_type_node,
854 build_range_type
855 (integer_type_node,
856 integer_one_node,
857 build_int_2 (len, 0))),
858 1, 0);
859 TREE_CONSTANT (arg3) = 1;
860 TREE_STATIC (arg3) = 1;
861 arg3 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg3)),
862 arg3);
863
864 arg4 = convert (ffecom_f2c_ftnint_type_node,
865 build_int_2 (lineno, 0));
866
867 arg1 = build_tree_list (NULL_TREE, arg1);
868 arg2 = build_tree_list (NULL_TREE, arg2);
869 arg3 = build_tree_list (NULL_TREE, arg3);
870 arg4 = build_tree_list (NULL_TREE, arg4);
871 TREE_CHAIN (arg3) = arg4;
872 TREE_CHAIN (arg2) = arg3;
873 TREE_CHAIN (arg1) = arg2;
874
875 args = arg1;
876 }
877 die = ffecom_call_gfrt (FFECOM_gfrtRANGE,
878 args, NULL_TREE);
879 TREE_SIDE_EFFECTS (die) = 1;
880
881 element = ffecom_3 (COND_EXPR,
882 TREE_TYPE (element),
883 cond,
884 element,
885 die);
886
887 return element;
888}
889
890/* Return the computed element of an array reference.
891
892 `item' is the array or a pointer to the array. It must be a pointer
893 to the array if ffe_is_flat_arrays ().
894 `expr' is the original opARRAYREF expression.
895 `want_ptr' is non-zero if `item' is a pointer to the element, instead of
896 the element itself, is to be returned. */
897
898static tree
899ffecom_arrayref_ (tree item, ffebld expr, int want_ptr)
900{
901 ffebld dims[FFECOM_dimensionsMAX];
902 int i;
903 int total_dims;
904 int flatten = 0 /* ~~~ ffe_is_flat_arrays () */;
905 int need_ptr = want_ptr || flatten;
906 tree array;
907 tree element;
908 char *array_name;
909
910 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER)
911 array_name = ffesymbol_text (ffebld_symter (ffebld_left (expr)));
912 else
913 array_name = "[expr?]";
914
915 /* Build up ARRAY_REFs in reverse order (since we're column major
916 here in Fortran land). */
917
918 for (i = 0, expr = ffebld_right (expr);
919 expr != NULL;
920 expr = ffebld_trail (expr))
921 dims[i++] = ffebld_head (expr);
922
923 total_dims = i;
924
925 if (need_ptr)
926 {
927 for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
928 i >= 0;
929 --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
930 {
931 element = ffecom_expr (dims[i]);
932 if (ffe_is_subscript_check ())
933 element = ffecom_subscript_check_ (array, element, i, total_dims,
934 array_name);
935 item = ffecom_2 (PLUS_EXPR,
936 build_pointer_type (TREE_TYPE (array)),
937 item,
938 size_binop (MULT_EXPR,
939 size_in_bytes (TREE_TYPE (array)),
940 convert (sizetype,
941 fold (build (MINUS_EXPR,
942 TREE_TYPE (TYPE_MIN_VALUE (TYPE_DOMAIN (array))),
943 element,
944 TYPE_MIN_VALUE (TYPE_DOMAIN (array)))))));
945 }
946 if (! want_ptr)
947 {
948 item = ffecom_1 (INDIRECT_REF,
949 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
950 item);
951 }
952 }
953 else
954 {
955 for (--i;
956 i >= 0;
957 --i)
958 {
959 array = TYPE_MAIN_VARIANT (TREE_TYPE (item));
960
961 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
962 if (ffe_is_subscript_check ())
963 element = ffecom_subscript_check_ (array, element, i, total_dims,
964 array_name);
965 item = ffecom_2 (ARRAY_REF,
966 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
967 item,
968 element);
969 }
970 }
971
972 return item;
973}
974
5ff904cd
JL
975/* This is like gcc's stabilize_reference -- in fact, most of the code
976 comes from that -- but it handles the situation where the reference
977 is going to have its subparts picked at, and it shouldn't change
978 (or trigger extra invocations of functions in the subtrees) due to
979 this. save_expr is a bit overzealous, because we don't need the
980 entire thing calculated and saved like a temp. So, for DECLs, no
981 change is needed, because these are stable aggregates, and ARRAY_REF
982 and such might well be stable too, but for things like calculations,
983 we do need to calculate a snapshot of a value before picking at it. */
984
985#if FFECOM_targetCURRENT == FFECOM_targetGCC
986static tree
987ffecom_stabilize_aggregate_ (tree ref)
988{
989 tree result;
990 enum tree_code code = TREE_CODE (ref);
991
992 switch (code)
993 {
994 case VAR_DECL:
995 case PARM_DECL:
996 case RESULT_DECL:
997 /* No action is needed in this case. */
998 return ref;
999
1000 case NOP_EXPR:
1001 case CONVERT_EXPR:
1002 case FLOAT_EXPR:
1003 case FIX_TRUNC_EXPR:
1004 case FIX_FLOOR_EXPR:
1005 case FIX_ROUND_EXPR:
1006 case FIX_CEIL_EXPR:
1007 result = build_nt (code, stabilize_reference (TREE_OPERAND (ref, 0)));
1008 break;
1009
1010 case INDIRECT_REF:
1011 result = build_nt (INDIRECT_REF,
1012 stabilize_reference_1 (TREE_OPERAND (ref, 0)));
1013 break;
1014
1015 case COMPONENT_REF:
1016 result = build_nt (COMPONENT_REF,
1017 stabilize_reference (TREE_OPERAND (ref, 0)),
1018 TREE_OPERAND (ref, 1));
1019 break;
1020
1021 case BIT_FIELD_REF:
1022 result = build_nt (BIT_FIELD_REF,
1023 stabilize_reference (TREE_OPERAND (ref, 0)),
1024 stabilize_reference_1 (TREE_OPERAND (ref, 1)),
1025 stabilize_reference_1 (TREE_OPERAND (ref, 2)));
1026 break;
1027
1028 case ARRAY_REF:
1029 result = build_nt (ARRAY_REF,
1030 stabilize_reference (TREE_OPERAND (ref, 0)),
1031 stabilize_reference_1 (TREE_OPERAND (ref, 1)));
1032 break;
1033
1034 case COMPOUND_EXPR:
1035 result = build_nt (COMPOUND_EXPR,
1036 stabilize_reference_1 (TREE_OPERAND (ref, 0)),
1037 stabilize_reference (TREE_OPERAND (ref, 1)));
1038 break;
1039
1040 case RTL_EXPR:
1041 result = build1 (INDIRECT_REF, TREE_TYPE (ref),
1042 save_expr (build1 (ADDR_EXPR,
1043 build_pointer_type (TREE_TYPE (ref)),
1044 ref)));
1045 break;
1046
1047
1048 default:
1049 return save_expr (ref);
1050
1051 case ERROR_MARK:
1052 return error_mark_node;
1053 }
1054
1055 TREE_TYPE (result) = TREE_TYPE (ref);
1056 TREE_READONLY (result) = TREE_READONLY (ref);
1057 TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (ref);
1058 TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (ref);
1059 TREE_RAISES (result) = TREE_RAISES (ref);
1060
1061 return result;
1062}
1063#endif
1064
1065/* A rip-off of gcc's convert.c convert_to_complex function,
1066 reworked to handle complex implemented as C structures
1067 (RECORD_TYPE with two fields, real and imaginary `r' and `i'). */
1068
1069#if FFECOM_targetCURRENT == FFECOM_targetGCC
1070static tree
1071ffecom_convert_to_complex_ (tree type, tree expr)
1072{
1073 register enum tree_code form = TREE_CODE (TREE_TYPE (expr));
1074 tree subtype;
1075
1076 assert (TREE_CODE (type) == RECORD_TYPE);
1077
1078 subtype = TREE_TYPE (TYPE_FIELDS (type));
1079
1080 if (form == REAL_TYPE || form == INTEGER_TYPE || form == ENUMERAL_TYPE)
1081 {
1082 expr = convert (subtype, expr);
1083 return ffecom_2 (COMPLEX_EXPR, type, expr,
1084 convert (subtype, integer_zero_node));
1085 }
1086
1087 if (form == RECORD_TYPE)
1088 {
1089 tree elt_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr)));
1090 if (TYPE_MAIN_VARIANT (elt_type) == TYPE_MAIN_VARIANT (subtype))
1091 return expr;
1092 else
1093 {
1094 expr = save_expr (expr);
1095 return ffecom_2 (COMPLEX_EXPR,
1096 type,
1097 convert (subtype,
1098 ffecom_1 (REALPART_EXPR,
1099 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1100 expr)),
1101 convert (subtype,
1102 ffecom_1 (IMAGPART_EXPR,
1103 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1104 expr)));
1105 }
1106 }
1107
1108 if (form == POINTER_TYPE || form == REFERENCE_TYPE)
1109 error ("pointer value used where a complex was expected");
1110 else
1111 error ("aggregate value used where a complex was expected");
1112
1113 return ffecom_2 (COMPLEX_EXPR, type,
1114 convert (subtype, integer_zero_node),
1115 convert (subtype, integer_zero_node));
1116}
1117#endif
1118
1119/* Like gcc's convert(), but crashes if widening might happen. */
1120
1121#if FFECOM_targetCURRENT == FFECOM_targetGCC
1122static tree
1123ffecom_convert_narrow_ (type, expr)
1124 tree type, expr;
1125{
1126 register tree e = expr;
1127 register enum tree_code code = TREE_CODE (type);
1128
1129 if (type == TREE_TYPE (e)
1130 || TREE_CODE (e) == ERROR_MARK)
1131 return e;
1132 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1133 return fold (build1 (NOP_EXPR, type, e));
1134 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1135 || code == ERROR_MARK)
1136 return error_mark_node;
1137 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1138 {
1139 assert ("void value not ignored as it ought to be" == NULL);
1140 return error_mark_node;
1141 }
1142 assert (code != VOID_TYPE);
1143 if ((code != RECORD_TYPE)
1144 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1145 assert ("converting COMPLEX to REAL" == NULL);
1146 assert (code != ENUMERAL_TYPE);
1147 if (code == INTEGER_TYPE)
1148 {
a74de6ea
CB
1149 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1150 && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)))
1151 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1152 && (TYPE_PRECISION (type)
1153 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
5ff904cd
JL
1154 return fold (convert_to_integer (type, e));
1155 }
1156 if (code == POINTER_TYPE)
1157 {
1158 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1159 return fold (convert_to_pointer (type, e));
1160 }
1161 if (code == REAL_TYPE)
1162 {
1163 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1164 assert (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)));
1165 return fold (convert_to_real (type, e));
1166 }
1167 if (code == COMPLEX_TYPE)
1168 {
1169 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1170 assert (TYPE_PRECISION (TREE_TYPE (type)) <= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1171 return fold (convert_to_complex (type, e));
1172 }
1173 if (code == RECORD_TYPE)
1174 {
1175 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
270fc4e8
CB
1176 /* Check that at least the first field name agrees. */
1177 assert (DECL_NAME (TYPE_FIELDS (type))
1178 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
5ff904cd
JL
1179 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1180 <= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
270fc4e8
CB
1181 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1182 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1183 return e;
5ff904cd
JL
1184 return fold (ffecom_convert_to_complex_ (type, e));
1185 }
1186
1187 assert ("conversion to non-scalar type requested" == NULL);
1188 return error_mark_node;
1189}
1190#endif
1191
1192/* Like gcc's convert(), but crashes if narrowing might happen. */
1193
1194#if FFECOM_targetCURRENT == FFECOM_targetGCC
1195static tree
1196ffecom_convert_widen_ (type, expr)
1197 tree type, expr;
1198{
1199 register tree e = expr;
1200 register enum tree_code code = TREE_CODE (type);
1201
1202 if (type == TREE_TYPE (e)
1203 || TREE_CODE (e) == ERROR_MARK)
1204 return e;
1205 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1206 return fold (build1 (NOP_EXPR, type, e));
1207 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1208 || code == ERROR_MARK)
1209 return error_mark_node;
1210 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1211 {
1212 assert ("void value not ignored as it ought to be" == NULL);
1213 return error_mark_node;
1214 }
1215 assert (code != VOID_TYPE);
1216 if ((code != RECORD_TYPE)
1217 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1218 assert ("narrowing COMPLEX to REAL" == NULL);
1219 assert (code != ENUMERAL_TYPE);
1220 if (code == INTEGER_TYPE)
1221 {
a74de6ea
CB
1222 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1223 && TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)))
1224 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1225 && (TYPE_PRECISION (type)
1226 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
5ff904cd
JL
1227 return fold (convert_to_integer (type, e));
1228 }
1229 if (code == POINTER_TYPE)
1230 {
1231 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1232 return fold (convert_to_pointer (type, e));
1233 }
1234 if (code == REAL_TYPE)
1235 {
1236 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1237 assert (TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)));
1238 return fold (convert_to_real (type, e));
1239 }
1240 if (code == COMPLEX_TYPE)
1241 {
1242 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1243 assert (TYPE_PRECISION (TREE_TYPE (type)) >= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1244 return fold (convert_to_complex (type, e));
1245 }
1246 if (code == RECORD_TYPE)
1247 {
1248 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
270fc4e8
CB
1249 /* Check that at least the first field name agrees. */
1250 assert (DECL_NAME (TYPE_FIELDS (type))
1251 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
5ff904cd
JL
1252 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1253 >= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
270fc4e8
CB
1254 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1255 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1256 return e;
5ff904cd
JL
1257 return fold (ffecom_convert_to_complex_ (type, e));
1258 }
1259
1260 assert ("conversion to non-scalar type requested" == NULL);
1261 return error_mark_node;
1262}
1263#endif
1264
1265/* Handles making a COMPLEX type, either the standard
1266 (but buggy?) gbe way, or the safer (but less elegant?)
1267 f2c way. */
1268
1269#if FFECOM_targetCURRENT == FFECOM_targetGCC
1270static tree
1271ffecom_make_complex_type_ (tree subtype)
1272{
1273 tree type;
1274 tree realfield;
1275 tree imagfield;
1276
1277 if (ffe_is_emulate_complex ())
1278 {
1279 type = make_node (RECORD_TYPE);
1280 realfield = ffecom_decl_field (type, NULL_TREE, "r", subtype);
1281 imagfield = ffecom_decl_field (type, realfield, "i", subtype);
1282 TYPE_FIELDS (type) = realfield;
1283 layout_type (type);
1284 }
1285 else
1286 {
1287 type = make_node (COMPLEX_TYPE);
1288 TREE_TYPE (type) = subtype;
1289 layout_type (type);
1290 }
1291
1292 return type;
1293}
1294#endif
1295
1296/* Chooses either the gbe or the f2c way to build a
1297 complex constant. */
1298
1299#if FFECOM_targetCURRENT == FFECOM_targetGCC
1300static tree
1301ffecom_build_complex_constant_ (tree type, tree realpart, tree imagpart)
1302{
1303 tree bothparts;
1304
1305 if (ffe_is_emulate_complex ())
1306 {
1307 bothparts = build_tree_list (TYPE_FIELDS (type), realpart);
1308 TREE_CHAIN (bothparts) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), imagpart);
1309 bothparts = build (CONSTRUCTOR, type, NULL_TREE, bothparts);
1310 }
1311 else
1312 {
1313 bothparts = build_complex (type, realpart, imagpart);
1314 }
1315
1316 return bothparts;
1317}
1318#endif
1319
1320#if FFECOM_targetCURRENT == FFECOM_targetGCC
1321static tree
26f096f9 1322ffecom_arglist_expr_ (const char *c, ffebld expr)
5ff904cd
JL
1323{
1324 tree list;
1325 tree *plist = &list;
1326 tree trail = NULL_TREE; /* Append char length args here. */
1327 tree *ptrail = &trail;
1328 tree length;
1329 ffebld exprh;
1330 tree item;
1331 bool ptr = FALSE;
1332 tree wanted = NULL_TREE;
e2fa159e
JL
1333 static char zed[] = "0";
1334
1335 if (c == NULL)
1336 c = &zed[0];
5ff904cd
JL
1337
1338 while (expr != NULL)
1339 {
1340 if (*c != '\0')
1341 {
1342 ptr = FALSE;
1343 if (*c == '&')
1344 {
1345 ptr = TRUE;
1346 ++c;
1347 }
1348 switch (*(c++))
1349 {
1350 case '\0':
1351 ptr = TRUE;
1352 wanted = NULL_TREE;
1353 break;
1354
1355 case 'a':
1356 assert (ptr);
1357 wanted = NULL_TREE;
1358 break;
1359
1360 case 'c':
1361 wanted = ffecom_f2c_complex_type_node;
1362 break;
1363
1364 case 'd':
1365 wanted = ffecom_f2c_doublereal_type_node;
1366 break;
1367
1368 case 'e':
1369 wanted = ffecom_f2c_doublecomplex_type_node;
1370 break;
1371
1372 case 'f':
1373 wanted = ffecom_f2c_real_type_node;
1374 break;
1375
1376 case 'i':
1377 wanted = ffecom_f2c_integer_type_node;
1378 break;
1379
1380 case 'j':
1381 wanted = ffecom_f2c_longint_type_node;
1382 break;
1383
1384 default:
1385 assert ("bad argstring code" == NULL);
1386 wanted = NULL_TREE;
1387 break;
1388 }
1389 }
1390
1391 exprh = ffebld_head (expr);
1392 if (exprh == NULL)
1393 wanted = NULL_TREE;
1394
1395 if ((wanted == NULL_TREE)
1396 || (ptr
1397 && (TYPE_MODE
1398 (ffecom_tree_type[ffeinfo_basictype (ffebld_info (exprh))]
1399 [ffeinfo_kindtype (ffebld_info (exprh))])
1400 == TYPE_MODE (wanted))))
1401 *plist
1402 = build_tree_list (NULL_TREE,
1403 ffecom_arg_ptr_to_expr (exprh,
1404 &length));
1405 else
1406 {
1407 item = ffecom_arg_expr (exprh, &length);
1408 item = ffecom_convert_widen_ (wanted, item);
1409 if (ptr)
1410 {
1411 item = ffecom_1 (ADDR_EXPR,
1412 build_pointer_type (TREE_TYPE (item)),
1413 item);
1414 }
1415 *plist
1416 = build_tree_list (NULL_TREE,
1417 item);
1418 }
1419
1420 plist = &TREE_CHAIN (*plist);
1421 expr = ffebld_trail (expr);
1422 if (length != NULL_TREE)
1423 {
1424 *ptrail = build_tree_list (NULL_TREE, length);
1425 ptrail = &TREE_CHAIN (*ptrail);
1426 }
1427 }
1428
e2fa159e
JL
1429 /* We've run out of args in the call; if the implementation expects
1430 more, supply null pointers for them, which the implementation can
1431 check to see if an arg was omitted. */
1432
1433 while (*c != '\0' && *c != '0')
1434 {
1435 if (*c == '&')
1436 ++c;
1437 else
1438 assert ("missing arg to run-time routine!" == NULL);
1439
1440 switch (*(c++))
1441 {
1442 case '\0':
1443 case 'a':
1444 case 'c':
1445 case 'd':
1446 case 'e':
1447 case 'f':
1448 case 'i':
1449 case 'j':
1450 break;
1451
1452 default:
1453 assert ("bad arg string code" == NULL);
1454 break;
1455 }
1456 *plist
1457 = build_tree_list (NULL_TREE,
1458 null_pointer_node);
1459 plist = &TREE_CHAIN (*plist);
1460 }
1461
5ff904cd
JL
1462 *plist = trail;
1463
1464 return list;
1465}
1466#endif
1467
1468#if FFECOM_targetCURRENT == FFECOM_targetGCC
1469static tree
1470ffecom_widest_expr_type_ (ffebld list)
1471{
1472 ffebld item;
1473 ffebld widest = NULL;
1474 ffetype type;
1475 ffetype widest_type = NULL;
1476 tree t;
1477
1478 for (; list != NULL; list = ffebld_trail (list))
1479 {
1480 item = ffebld_head (list);
1481 if (item == NULL)
1482 continue;
1483 if ((widest != NULL)
1484 && (ffeinfo_basictype (ffebld_info (item))
1485 != ffeinfo_basictype (ffebld_info (widest))))
1486 continue;
1487 type = ffeinfo_type (ffeinfo_basictype (ffebld_info (item)),
1488 ffeinfo_kindtype (ffebld_info (item)));
1489 if ((widest == FFEINFO_kindtypeNONE)
1490 || (ffetype_size (type)
1491 > ffetype_size (widest_type)))
1492 {
1493 widest = item;
1494 widest_type = type;
1495 }
1496 }
1497
1498 assert (widest != NULL);
1499 t = ffecom_tree_type[ffeinfo_basictype (ffebld_info (widest))]
1500 [ffeinfo_kindtype (ffebld_info (widest))];
1501 assert (t != NULL_TREE);
1502 return t;
1503}
1504#endif
1505
d6cd84e0
CB
1506/* Check whether a partial overlap between two expressions is possible.
1507
1508 Can *starting* to write a portion of expr1 change the value
1509 computed (perhaps already, *partially*) by expr2?
1510
1511 Currently, this is a concern only for a COMPLEX expr1. But if it
1512 isn't in COMMON or local EQUIVALENCE, since we don't support
1513 aliasing of arguments, it isn't a concern. */
1514
1515static bool
1516ffecom_possible_partial_overlap_ (ffebld expr1, ffebld expr2)
1517{
1518 ffesymbol sym;
1519 ffestorag st;
1520
1521 switch (ffebld_op (expr1))
1522 {
1523 case FFEBLD_opSYMTER:
1524 sym = ffebld_symter (expr1);
1525 break;
1526
1527 case FFEBLD_opARRAYREF:
1528 if (ffebld_op (ffebld_left (expr1)) != FFEBLD_opSYMTER)
1529 return FALSE;
1530 sym = ffebld_symter (ffebld_left (expr1));
1531 break;
1532
1533 default:
1534 return FALSE;
1535 }
1536
1537 if (ffesymbol_where (sym) != FFEINFO_whereCOMMON
1538 && (ffesymbol_where (sym) != FFEINFO_whereLOCAL
1539 || ! (st = ffesymbol_storage (sym))
1540 || ! ffestorag_parent (st)))
1541 return FALSE;
1542
1543 /* It's in COMMON or local EQUIVALENCE. */
1544
1545 return TRUE;
1546}
1547
5ff904cd
JL
1548/* Check whether dest and source might overlap. ffebld versions of these
1549 might or might not be passed, will be NULL if not.
1550
1551 The test is really whether source_tree is modifiable and, if modified,
1552 might overlap destination such that the value(s) in the destination might
1553 change before it is finally modified. dest_* are the canonized
1554 destination itself. */
1555
1556#if FFECOM_targetCURRENT == FFECOM_targetGCC
1557static bool
1558ffecom_overlap_ (tree dest_decl, tree dest_offset, tree dest_size,
1559 tree source_tree, ffebld source UNUSED,
1560 bool scalar_arg)
1561{
1562 tree source_decl;
1563 tree source_offset;
1564 tree source_size;
1565 tree t;
1566
1567 if (source_tree == NULL_TREE)
1568 return FALSE;
1569
1570 switch (TREE_CODE (source_tree))
1571 {
1572 case ERROR_MARK:
1573 case IDENTIFIER_NODE:
1574 case INTEGER_CST:
1575 case REAL_CST:
1576 case COMPLEX_CST:
1577 case STRING_CST:
1578 case CONST_DECL:
1579 case VAR_DECL:
1580 case RESULT_DECL:
1581 case FIELD_DECL:
1582 case MINUS_EXPR:
1583 case MULT_EXPR:
1584 case TRUNC_DIV_EXPR:
1585 case CEIL_DIV_EXPR:
1586 case FLOOR_DIV_EXPR:
1587 case ROUND_DIV_EXPR:
1588 case TRUNC_MOD_EXPR:
1589 case CEIL_MOD_EXPR:
1590 case FLOOR_MOD_EXPR:
1591 case ROUND_MOD_EXPR:
1592 case RDIV_EXPR:
1593 case EXACT_DIV_EXPR:
1594 case FIX_TRUNC_EXPR:
1595 case FIX_CEIL_EXPR:
1596 case FIX_FLOOR_EXPR:
1597 case FIX_ROUND_EXPR:
1598 case FLOAT_EXPR:
1599 case EXPON_EXPR:
1600 case NEGATE_EXPR:
1601 case MIN_EXPR:
1602 case MAX_EXPR:
1603 case ABS_EXPR:
1604 case FFS_EXPR:
1605 case LSHIFT_EXPR:
1606 case RSHIFT_EXPR:
1607 case LROTATE_EXPR:
1608 case RROTATE_EXPR:
1609 case BIT_IOR_EXPR:
1610 case BIT_XOR_EXPR:
1611 case BIT_AND_EXPR:
1612 case BIT_ANDTC_EXPR:
1613 case BIT_NOT_EXPR:
1614 case TRUTH_ANDIF_EXPR:
1615 case TRUTH_ORIF_EXPR:
1616 case TRUTH_AND_EXPR:
1617 case TRUTH_OR_EXPR:
1618 case TRUTH_XOR_EXPR:
1619 case TRUTH_NOT_EXPR:
1620 case LT_EXPR:
1621 case LE_EXPR:
1622 case GT_EXPR:
1623 case GE_EXPR:
1624 case EQ_EXPR:
1625 case NE_EXPR:
1626 case COMPLEX_EXPR:
1627 case CONJ_EXPR:
1628 case REALPART_EXPR:
1629 case IMAGPART_EXPR:
1630 case LABEL_EXPR:
1631 case COMPONENT_REF:
1632 return FALSE;
1633
1634 case COMPOUND_EXPR:
1635 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1636 TREE_OPERAND (source_tree, 1), NULL,
1637 scalar_arg);
1638
1639 case MODIFY_EXPR:
1640 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1641 TREE_OPERAND (source_tree, 0), NULL,
1642 scalar_arg);
1643
1644 case CONVERT_EXPR:
1645 case NOP_EXPR:
1646 case NON_LVALUE_EXPR:
1647 case PLUS_EXPR:
1648 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1649 return TRUE;
1650
1651 ffecom_tree_canonize_ptr_ (&source_decl, &source_offset,
1652 source_tree);
1653 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1654 break;
1655
1656 case COND_EXPR:
1657 return
1658 ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1659 TREE_OPERAND (source_tree, 1), NULL,
1660 scalar_arg)
1661 || ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1662 TREE_OPERAND (source_tree, 2), NULL,
1663 scalar_arg);
1664
1665
1666 case ADDR_EXPR:
1667 ffecom_tree_canonize_ref_ (&source_decl, &source_offset,
1668 &source_size,
1669 TREE_OPERAND (source_tree, 0));
1670 break;
1671
1672 case PARM_DECL:
1673 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1674 return TRUE;
1675
1676 source_decl = source_tree;
1677 source_offset = size_zero_node;
1678 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1679 break;
1680
1681 case SAVE_EXPR:
1682 case REFERENCE_EXPR:
1683 case PREDECREMENT_EXPR:
1684 case PREINCREMENT_EXPR:
1685 case POSTDECREMENT_EXPR:
1686 case POSTINCREMENT_EXPR:
1687 case INDIRECT_REF:
1688 case ARRAY_REF:
1689 case CALL_EXPR:
1690 default:
1691 return TRUE;
1692 }
1693
1694 /* Come here when source_decl, source_offset, and source_size filled
1695 in appropriately. */
1696
1697 if (source_decl == NULL_TREE)
1698 return FALSE; /* No decl involved, so no overlap. */
1699
1700 if (source_decl != dest_decl)
1701 return FALSE; /* Different decl, no overlap. */
1702
1703 if (TREE_CODE (dest_size) == ERROR_MARK)
1704 return TRUE; /* Assignment into entire assumed-size
1705 array? Shouldn't happen.... */
1706
1707 t = ffecom_2 (LE_EXPR, integer_type_node,
1708 ffecom_2 (PLUS_EXPR, TREE_TYPE (dest_offset),
1709 dest_offset,
1710 convert (TREE_TYPE (dest_offset),
1711 dest_size)),
1712 convert (TREE_TYPE (dest_offset),
1713 source_offset));
1714
1715 if (integer_onep (t))
1716 return FALSE; /* Destination precedes source. */
1717
1718 if (!scalar_arg
1719 || (source_size == NULL_TREE)
1720 || (TREE_CODE (source_size) == ERROR_MARK)
1721 || integer_zerop (source_size))
1722 return TRUE; /* No way to tell if dest follows source. */
1723
1724 t = ffecom_2 (LE_EXPR, integer_type_node,
1725 ffecom_2 (PLUS_EXPR, TREE_TYPE (source_offset),
1726 source_offset,
1727 convert (TREE_TYPE (source_offset),
1728 source_size)),
1729 convert (TREE_TYPE (source_offset),
1730 dest_offset));
1731
1732 if (integer_onep (t))
1733 return FALSE; /* Destination follows source. */
1734
1735 return TRUE; /* Destination and source overlap. */
1736}
1737#endif
1738
1739/* Check whether dest might overlap any of a list of arguments or is
1740 in a COMMON area the callee might know about (and thus modify). */
1741
1742#if FFECOM_targetCURRENT == FFECOM_targetGCC
1743static bool
1744ffecom_args_overlapping_ (tree dest_tree, ffebld dest UNUSED,
1745 tree args, tree callee_commons,
1746 bool scalar_args)
1747{
1748 tree arg;
1749 tree dest_decl;
1750 tree dest_offset;
1751 tree dest_size;
1752
1753 ffecom_tree_canonize_ref_ (&dest_decl, &dest_offset, &dest_size,
1754 dest_tree);
1755
1756 if (dest_decl == NULL_TREE)
1757 return FALSE; /* Seems unlikely! */
1758
1759 /* If the decl cannot be determined reliably, or if its in COMMON
1760 and the callee isn't known to not futz with COMMON via other
1761 means, overlap might happen. */
1762
1763 if ((TREE_CODE (dest_decl) == ERROR_MARK)
1764 || ((callee_commons != NULL_TREE)
1765 && TREE_PUBLIC (dest_decl)))
1766 return TRUE;
1767
1768 for (; args != NULL_TREE; args = TREE_CHAIN (args))
1769 {
1770 if (((arg = TREE_VALUE (args)) != NULL_TREE)
1771 && ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1772 arg, NULL, scalar_args))
1773 return TRUE;
1774 }
1775
1776 return FALSE;
1777}
1778#endif
1779
1780/* Build a string for a variable name as used by NAMELIST. This means that
1781 if we're using the f2c library, we build an uppercase string, since
1782 f2c does this. */
1783
1784#if FFECOM_targetCURRENT == FFECOM_targetGCC
1785static tree
26f096f9 1786ffecom_build_f2c_string_ (int i, const char *s)
5ff904cd
JL
1787{
1788 if (!ffe_is_f2c_library ())
1789 return build_string (i, s);
1790
1791 {
1792 char *tmp;
26f096f9 1793 const char *p;
5ff904cd
JL
1794 char *q;
1795 char space[34];
1796 tree t;
1797
1798 if (((size_t) i) > ARRAY_SIZE (space))
1799 tmp = malloc_new_ks (malloc_pool_image (), "f2c_string", i);
1800 else
1801 tmp = &space[0];
1802
1803 for (p = s, q = tmp; *p != '\0'; ++p, ++q)
1804 *q = ffesrc_toupper (*p);
1805 *q = '\0';
1806
1807 t = build_string (i, tmp);
1808
1809 if (((size_t) i) > ARRAY_SIZE (space))
1810 malloc_kill_ks (malloc_pool_image (), tmp, i);
1811
1812 return t;
1813 }
1814}
1815
1816#endif
1817/* Returns CALL_EXPR or equivalent with given type (pass NULL_TREE for
1818 type to just get whatever the function returns), handling the
1819 f2c value-returning convention, if required, by prepending
1820 to the arglist a pointer to a temporary to receive the return value. */
1821
1822#if FFECOM_targetCURRENT == FFECOM_targetGCC
1823static tree
1824ffecom_call_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1825 tree type, tree args, tree dest_tree,
1826 ffebld dest, bool *dest_used, tree callee_commons,
c7e4ee3a 1827 bool scalar_args, tree hook)
5ff904cd
JL
1828{
1829 tree item;
1830 tree tempvar;
1831
1832 if (dest_used != NULL)
1833 *dest_used = FALSE;
1834
1835 if (is_f2c_complex)
1836 {
1837 if ((dest_used == NULL)
1838 || (dest == NULL)
1839 || (ffeinfo_basictype (ffebld_info (dest))
1840 != FFEINFO_basictypeCOMPLEX)
1841 || (ffeinfo_kindtype (ffebld_info (dest)) != kt)
1842 || ((type != NULL_TREE) && (TREE_TYPE (dest_tree) != type))
1843 || ffecom_args_overlapping_ (dest_tree, dest, args,
1844 callee_commons,
1845 scalar_args))
1846 {
c7e4ee3a
CB
1847#ifdef HOHO
1848 tempvar = ffecom_make_tempvar (ffecom_tree_type
5ff904cd
JL
1849 [FFEINFO_basictypeCOMPLEX][kt],
1850 FFETARGET_charactersizeNONE,
c7e4ee3a
CB
1851 -1);
1852#else
1853 tempvar = hook;
1854 assert (tempvar);
1855#endif
5ff904cd
JL
1856 }
1857 else
1858 {
1859 *dest_used = TRUE;
1860 tempvar = dest_tree;
1861 type = NULL_TREE;
1862 }
1863
1864 item
1865 = build_tree_list (NULL_TREE,
1866 ffecom_1 (ADDR_EXPR,
c7e4ee3a 1867 build_pointer_type (TREE_TYPE (tempvar)),
5ff904cd
JL
1868 tempvar));
1869 TREE_CHAIN (item) = args;
1870
1871 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1872 item, NULL_TREE);
1873
1874 if (tempvar != dest_tree)
1875 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item, tempvar);
1876 }
1877 else
1878 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1879 args, NULL_TREE);
1880
1881 if ((type != NULL_TREE) && (TREE_TYPE (item) != type))
1882 item = ffecom_convert_narrow_ (type, item);
1883
1884 return item;
1885}
1886#endif
1887
1888/* Given two arguments, transform them and make a call to the given
1889 function via ffecom_call_. */
1890
1891#if FFECOM_targetCURRENT == FFECOM_targetGCC
1892static tree
1893ffecom_call_binop_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1894 tree type, ffebld left, ffebld right,
1895 tree dest_tree, ffebld dest, bool *dest_used,
c7e4ee3a 1896 tree callee_commons, bool scalar_args, tree hook)
5ff904cd
JL
1897{
1898 tree left_tree;
1899 tree right_tree;
1900 tree left_length;
1901 tree right_length;
1902
5ff904cd
JL
1903 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
1904 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
5ff904cd
JL
1905
1906 left_tree = build_tree_list (NULL_TREE, left_tree);
1907 right_tree = build_tree_list (NULL_TREE, right_tree);
1908 TREE_CHAIN (left_tree) = right_tree;
1909
1910 if (left_length != NULL_TREE)
1911 {
1912 left_length = build_tree_list (NULL_TREE, left_length);
1913 TREE_CHAIN (right_tree) = left_length;
1914 }
1915
1916 if (right_length != NULL_TREE)
1917 {
1918 right_length = build_tree_list (NULL_TREE, right_length);
1919 if (left_length != NULL_TREE)
1920 TREE_CHAIN (left_length) = right_length;
1921 else
1922 TREE_CHAIN (right_tree) = right_length;
1923 }
1924
1925 return ffecom_call_ (fn, kt, is_f2c_complex, type, left_tree,
1926 dest_tree, dest, dest_used, callee_commons,
c7e4ee3a 1927 scalar_args, hook);
5ff904cd
JL
1928}
1929#endif
1930
c7e4ee3a 1931/* Return ptr/length args for char subexpression
5ff904cd
JL
1932
1933 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
1934 subexpressions by constructing the appropriate trees for the ptr-to-
1935 character-text and length-of-character-text arguments in a calling
86fc7a6c
CB
1936 sequence.
1937
1938 Note that if with_null is TRUE, and the expression is an opCONTER,
1939 a null byte is appended to the string. */
5ff904cd
JL
1940
1941#if FFECOM_targetCURRENT == FFECOM_targetGCC
1942static void
86fc7a6c 1943ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
5ff904cd
JL
1944{
1945 tree item;
1946 tree high;
1947 ffetargetCharacter1 val;
86fc7a6c 1948 ffetargetCharacterSize newlen;
5ff904cd
JL
1949
1950 switch (ffebld_op (expr))
1951 {
1952 case FFEBLD_opCONTER:
1953 val = ffebld_constant_character1 (ffebld_conter (expr));
86fc7a6c
CB
1954 newlen = ffetarget_length_character1 (val);
1955 if (with_null)
1956 {
c7e4ee3a 1957 /* Begin FFETARGET-NULL-KLUDGE. */
86fc7a6c 1958 if (newlen != 0)
c7e4ee3a 1959 ++newlen;
86fc7a6c
CB
1960 }
1961 *length = build_int_2 (newlen, 0);
5ff904cd 1962 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
86fc7a6c 1963 high = build_int_2 (newlen, 0);
5ff904cd 1964 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
c7e4ee3a 1965 item = build_string (newlen,
5ff904cd 1966 ffetarget_text_character1 (val));
c7e4ee3a 1967 /* End FFETARGET-NULL-KLUDGE. */
5ff904cd
JL
1968 TREE_TYPE (item)
1969 = build_type_variant
1970 (build_array_type
1971 (char_type_node,
1972 build_range_type
1973 (ffecom_f2c_ftnlen_type_node,
1974 ffecom_f2c_ftnlen_one_node,
1975 high)),
1976 1, 0);
1977 TREE_CONSTANT (item) = 1;
1978 TREE_STATIC (item) = 1;
1979 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
1980 item);
1981 break;
1982
1983 case FFEBLD_opSYMTER:
1984 {
1985 ffesymbol s = ffebld_symter (expr);
1986
1987 item = ffesymbol_hook (s).decl_tree;
1988 if (item == NULL_TREE)
1989 {
1990 s = ffecom_sym_transform_ (s);
1991 item = ffesymbol_hook (s).decl_tree;
1992 }
1993 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
1994 {
1995 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
1996 *length = ffesymbol_hook (s).length_tree;
1997 else
1998 {
1999 *length = build_int_2 (ffesymbol_size (s), 0);
2000 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2001 }
2002 }
2003 else if (item == error_mark_node)
2004 *length = error_mark_node;
c7e4ee3a
CB
2005 else
2006 /* FFEINFO_kindFUNCTION. */
5ff904cd
JL
2007 *length = NULL_TREE;
2008 if (!ffesymbol_hook (s).addr
2009 && (item != error_mark_node))
2010 item = ffecom_1 (ADDR_EXPR,
2011 build_pointer_type (TREE_TYPE (item)),
2012 item);
2013 }
2014 break;
2015
2016 case FFEBLD_opARRAYREF:
2017 {
5ff904cd 2018 ffecom_char_args_ (&item, length, ffebld_left (expr));
5ff904cd
JL
2019
2020 if (item == error_mark_node || *length == error_mark_node)
2021 {
2022 item = *length = error_mark_node;
2023 break;
2024 }
2025
6b55276e 2026 item = ffecom_arrayref_ (item, expr, 1);
5ff904cd
JL
2027 }
2028 break;
2029
2030 case FFEBLD_opSUBSTR:
2031 {
2032 ffebld start;
2033 ffebld end;
2034 ffebld thing = ffebld_right (expr);
2035 tree start_tree;
2036 tree end_tree;
6b55276e
CB
2037 char *char_name;
2038 ffebld left_symter;
2039 tree array;
5ff904cd
JL
2040
2041 assert (ffebld_op (thing) == FFEBLD_opITEM);
2042 start = ffebld_head (thing);
2043 thing = ffebld_trail (thing);
2044 assert (ffebld_trail (thing) == NULL);
2045 end = ffebld_head (thing);
2046
6b55276e
CB
2047 /* Determine name for pretty-printing range-check errors. */
2048 for (left_symter = ffebld_left (expr);
2049 left_symter && ffebld_op (left_symter) == FFEBLD_opARRAYREF;
2050 left_symter = ffebld_left (left_symter))
2051 ;
2052 if (ffebld_op (left_symter) == FFEBLD_opSYMTER)
2053 char_name = ffesymbol_text (ffebld_symter (left_symter));
2054 else
2055 char_name = "[expr?]";
2056
5ff904cd 2057 ffecom_char_args_ (&item, length, ffebld_left (expr));
5ff904cd
JL
2058
2059 if (item == error_mark_node || *length == error_mark_node)
2060 {
2061 item = *length = error_mark_node;
2062 break;
2063 }
2064
6b55276e
CB
2065 array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
2066
5ff904cd
JL
2067 if (start == NULL)
2068 {
2069 if (end == NULL)
2070 ;
2071 else
2072 {
6b55276e
CB
2073 end_tree = ffecom_expr (end);
2074 if (ffe_is_subscript_check ())
2075 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2076 char_name);
5ff904cd 2077 end_tree = convert (ffecom_f2c_ftnlen_type_node,
6b55276e 2078 end_tree);
5ff904cd
JL
2079
2080 if (end_tree == error_mark_node)
2081 {
2082 item = *length = error_mark_node;
2083 break;
2084 }
2085
2086 *length = end_tree;
2087 }
2088 }
2089 else
2090 {
6b55276e
CB
2091 start_tree = ffecom_expr (start);
2092 if (ffe_is_subscript_check ())
2093 start_tree = ffecom_subscript_check_ (array, start_tree, 0, 0,
2094 char_name);
5ff904cd 2095 start_tree = convert (ffecom_f2c_ftnlen_type_node,
6b55276e 2096 start_tree);
5ff904cd
JL
2097
2098 if (start_tree == error_mark_node)
2099 {
2100 item = *length = error_mark_node;
2101 break;
2102 }
2103
2104 start_tree = ffecom_save_tree (start_tree);
2105
2106 item = ffecom_2 (PLUS_EXPR, TREE_TYPE (item),
2107 item,
2108 ffecom_2 (MINUS_EXPR,
2109 TREE_TYPE (start_tree),
2110 start_tree,
2111 ffecom_f2c_ftnlen_one_node));
2112
2113 if (end == NULL)
2114 {
2115 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2116 ffecom_f2c_ftnlen_one_node,
2117 ffecom_2 (MINUS_EXPR,
2118 ffecom_f2c_ftnlen_type_node,
2119 *length,
2120 start_tree));
2121 }
2122 else
2123 {
6b55276e
CB
2124 end_tree = ffecom_expr (end);
2125 if (ffe_is_subscript_check ())
2126 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2127 char_name);
5ff904cd 2128 end_tree = convert (ffecom_f2c_ftnlen_type_node,
6b55276e 2129 end_tree);
5ff904cd
JL
2130
2131 if (end_tree == error_mark_node)
2132 {
2133 item = *length = error_mark_node;
2134 break;
2135 }
2136
2137 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2138 ffecom_f2c_ftnlen_one_node,
2139 ffecom_2 (MINUS_EXPR,
2140 ffecom_f2c_ftnlen_type_node,
2141 end_tree, start_tree));
2142 }
2143 }
2144 }
2145 break;
2146
2147 case FFEBLD_opFUNCREF:
2148 {
2149 ffesymbol s = ffebld_symter (ffebld_left (expr));
2150 tree tempvar;
2151 tree args;
2152 ffetargetCharacterSize size = ffeinfo_size (ffebld_info (expr));
2153 ffecomGfrt ix;
2154
2155 if (size == FFETARGET_charactersizeNONE)
c7e4ee3a
CB
2156 /* ~~Kludge alert! This should someday be fixed. */
2157 size = 24;
5ff904cd
JL
2158
2159 *length = build_int_2 (size, 0);
2160 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2161
2162 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
2163 == FFEINFO_whereINTRINSIC)
2164 {
2165 if (size == 1)
c7e4ee3a
CB
2166 {
2167 /* Invocation of an intrinsic returning CHARACTER*1. */
5ff904cd
JL
2168 item = ffecom_expr_intrinsic_ (expr, NULL_TREE,
2169 NULL, NULL);
2170 break;
2171 }
2172 ix = ffeintrin_gfrt_direct (ffebld_symter_implementation (ffebld_left (expr)));
2173 assert (ix != FFECOM_gfrt);
2174 item = ffecom_gfrt_tree_ (ix);
2175 }
2176 else
2177 {
2178 ix = FFECOM_gfrt;
2179 item = ffesymbol_hook (s).decl_tree;
2180 if (item == NULL_TREE)
2181 {
2182 s = ffecom_sym_transform_ (s);
2183 item = ffesymbol_hook (s).decl_tree;
2184 }
2185 if (item == error_mark_node)
2186 {
2187 item = *length = error_mark_node;
2188 break;
2189 }
2190
2191 if (!ffesymbol_hook (s).addr)
2192 item = ffecom_1_fn (item);
2193 }
2194
c7e4ee3a 2195#ifdef HOHO
5ff904cd 2196 tempvar = ffecom_push_tempvar (char_type_node, size, -1, TRUE);
c7e4ee3a
CB
2197#else
2198 tempvar = ffebld_nonter_hook (expr);
2199 assert (tempvar);
2200#endif
5ff904cd
JL
2201 tempvar = ffecom_1 (ADDR_EXPR,
2202 build_pointer_type (TREE_TYPE (tempvar)),
2203 tempvar);
2204
5ff904cd
JL
2205 args = build_tree_list (NULL_TREE, tempvar);
2206
2207 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT) /* Sfunc args by value. */
2208 TREE_CHAIN (args) = ffecom_list_expr (ffebld_right (expr));
2209 else
2210 {
2211 TREE_CHAIN (args) = build_tree_list (NULL_TREE, *length);
2212 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
2213 {
2214 TREE_CHAIN (TREE_CHAIN (args))
2215 = ffecom_arglist_expr_ (ffecom_gfrt_args_ (ix),
2216 ffebld_right (expr));
2217 }
2218 else
2219 {
2220 TREE_CHAIN (TREE_CHAIN (args))
2221 = ffecom_list_ptr_to_expr (ffebld_right (expr));
2222 }
2223 }
2224
2225 item = ffecom_3s (CALL_EXPR,
2226 TREE_TYPE (TREE_TYPE (TREE_TYPE (item))),
2227 item, args, NULL_TREE);
2228 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item,
2229 tempvar);
5ff904cd
JL
2230 }
2231 break;
2232
2233 case FFEBLD_opCONVERT:
2234
5ff904cd 2235 ffecom_char_args_ (&item, length, ffebld_left (expr));
5ff904cd
JL
2236
2237 if (item == error_mark_node || *length == error_mark_node)
2238 {
2239 item = *length = error_mark_node;
2240 break;
2241 }
2242
2243 if ((ffebld_size_known (ffebld_left (expr))
2244 == FFETARGET_charactersizeNONE)
2245 || (ffebld_size_known (ffebld_left (expr)) < (ffebld_size (expr))))
2246 { /* Possible blank-padding needed, copy into
2247 temporary. */
2248 tree tempvar;
2249 tree args;
2250 tree newlen;
2251
c7e4ee3a
CB
2252#ifdef HOHO
2253 tempvar = ffecom_make_tempvar (char_type_node,
2254 ffebld_size (expr), -1);
2255#else
2256 tempvar = ffebld_nonter_hook (expr);
2257 assert (tempvar);
2258#endif
5ff904cd
JL
2259 tempvar = ffecom_1 (ADDR_EXPR,
2260 build_pointer_type (TREE_TYPE (tempvar)),
2261 tempvar);
2262
2263 newlen = build_int_2 (ffebld_size (expr), 0);
2264 TREE_TYPE (newlen) = ffecom_f2c_ftnlen_type_node;
2265
2266 args = build_tree_list (NULL_TREE, tempvar);
2267 TREE_CHAIN (args) = build_tree_list (NULL_TREE, item);
2268 TREE_CHAIN (TREE_CHAIN (args)) = build_tree_list (NULL_TREE, newlen);
2269 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (args)))
2270 = build_tree_list (NULL_TREE, *length);
2271
c7e4ee3a 2272 item = ffecom_call_gfrt (FFECOM_gfrtCOPY, args, NULL_TREE);
5ff904cd
JL
2273 TREE_SIDE_EFFECTS (item) = 1;
2274 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), fold (item),
2275 tempvar);
2276 *length = newlen;
2277 }
2278 else
2279 { /* Just truncate the length. */
2280 *length = build_int_2 (ffebld_size (expr), 0);
2281 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2282 }
2283 break;
2284
2285 default:
2286 assert ("bad op for single char arg expr" == NULL);
2287 item = NULL_TREE;
2288 break;
2289 }
2290
2291 *xitem = item;
2292}
2293#endif
2294
2295/* Check the size of the type to be sure it doesn't overflow the
2296 "portable" capacities of the compiler back end. `dummy' types
2297 can generally overflow the normal sizes as long as the computations
2298 themselves don't overflow. A particular target of the back end
2299 must still enforce its size requirements, though, and the back
2300 end takes care of this in stor-layout.c. */
2301
2302#if FFECOM_targetCURRENT == FFECOM_targetGCC
2303static tree
2304ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy)
2305{
2306 if (TREE_CODE (type) == ERROR_MARK)
2307 return type;
2308
2309 if (TYPE_SIZE (type) == NULL_TREE)
2310 return type;
2311
2312 if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
2313 return type;
2314
2315 if ((tree_int_cst_sgn (TYPE_SIZE (type)) < 0)
2b0c2df0
CB
2316 || (!dummy && (((TREE_INT_CST_HIGH (TYPE_SIZE (type)) != 0))
2317 || TREE_OVERFLOW (TYPE_SIZE (type)))))
5ff904cd
JL
2318 {
2319 ffebad_start (FFEBAD_ARRAY_LARGE);
2320 ffebad_string (ffesymbol_text (s));
2321 ffebad_here (0, ffesymbol_where_line (s), ffesymbol_where_column (s));
2322 ffebad_finish ();
2323
2324 return error_mark_node;
2325 }
2326
2327 return type;
2328}
2329#endif
2330
2331/* Builds a length argument (PARM_DECL). Also wraps type in an array type
2332 where the dimension info is (1:size) where <size> is ffesymbol_size(s) if
2333 known, length_arg if not known (FFETARGET_charactersizeNONE). */
2334
2335#if FFECOM_targetCURRENT == FFECOM_targetGCC
2336static tree
2337ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s)
2338{
2339 ffetargetCharacterSize sz = ffesymbol_size (s);
2340 tree highval;
2341 tree tlen;
2342 tree type = *xtype;
2343
2344 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
2345 tlen = NULL_TREE; /* A statement function, no length passed. */
2346 else
2347 {
2348 if (ffesymbol_where (s) == FFEINFO_whereDUMMY)
2349 tlen = ffecom_get_invented_identifier ("__g77_length_%s",
c7e4ee3a 2350 ffesymbol_text (s), -1);
5ff904cd
JL
2351 else
2352 tlen = ffecom_get_invented_identifier ("__g77_%s",
c7e4ee3a 2353 "length", -1);
5ff904cd
JL
2354 tlen = build_decl (PARM_DECL, tlen, ffecom_f2c_ftnlen_type_node);
2355#if BUILT_FOR_270
2356 DECL_ARTIFICIAL (tlen) = 1;
2357#endif
2358 }
2359
2360 if (sz == FFETARGET_charactersizeNONE)
2361 {
2362 assert (tlen != NULL_TREE);
2b0c2df0 2363 highval = variable_size (tlen);
5ff904cd
JL
2364 }
2365 else
2366 {
2367 highval = build_int_2 (sz, 0);
2368 TREE_TYPE (highval) = ffecom_f2c_ftnlen_type_node;
2369 }
2370
2371 type = build_array_type (type,
2372 build_range_type (ffecom_f2c_ftnlen_type_node,
2373 ffecom_f2c_ftnlen_one_node,
2374 highval));
2375
2376 *xtype = type;
2377 return tlen;
2378}
2379
2380#endif
2381/* ffecom_concat_list_gather_ -- Gather list of concatenated string exprs
2382
2383 ffecomConcatList_ catlist;
2384 ffebld expr; // expr of CHARACTER basictype.
2385 ffetargetCharacterSize max; // max chars to gather or _...NONE if no max
2386 catlist = ffecom_concat_list_gather_(catlist,expr,max);
2387
2388 Scans expr for character subexpressions, updates and returns catlist
2389 accordingly. */
2390
2391#if FFECOM_targetCURRENT == FFECOM_targetGCC
2392static ffecomConcatList_
2393ffecom_concat_list_gather_ (ffecomConcatList_ catlist, ffebld expr,
2394 ffetargetCharacterSize max)
2395{
2396 ffetargetCharacterSize sz;
2397
2398recurse: /* :::::::::::::::::::: */
2399
2400 if (expr == NULL)
2401 return catlist;
2402
2403 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen >= max))
2404 return catlist; /* Don't append any more items. */
2405
2406 switch (ffebld_op (expr))
2407 {
2408 case FFEBLD_opCONTER:
2409 case FFEBLD_opSYMTER:
2410 case FFEBLD_opARRAYREF:
2411 case FFEBLD_opFUNCREF:
2412 case FFEBLD_opSUBSTR:
2413 case FFEBLD_opCONVERT: /* Callers should strip this off beforehand
2414 if they don't need to preserve it. */
2415 if (catlist.count == catlist.max)
2416 { /* Make a (larger) list. */
2417 ffebld *newx;
2418 int newmax;
2419
2420 newmax = (catlist.max == 0) ? 8 : catlist.max * 2;
2421 newx = malloc_new_ks (malloc_pool_image (), "catlist",
2422 newmax * sizeof (newx[0]));
2423 if (catlist.max != 0)
2424 {
2425 memcpy (newx, catlist.exprs, catlist.max * sizeof (newx[0]));
2426 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2427 catlist.max * sizeof (newx[0]));
2428 }
2429 catlist.max = newmax;
2430 catlist.exprs = newx;
2431 }
2432 if ((sz = ffebld_size_known (expr)) != FFETARGET_charactersizeNONE)
2433 catlist.minlen += sz;
2434 else
2435 ++catlist.minlen; /* Not true for F90; can be 0 length. */
2436 if ((sz = ffebld_size_max (expr)) == FFETARGET_charactersizeNONE)
2437 catlist.maxlen = sz;
2438 else
2439 catlist.maxlen += sz;
2440 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen > max))
2441 { /* This item overlaps (or is beyond) the end
2442 of the destination. */
2443 switch (ffebld_op (expr))
2444 {
2445 case FFEBLD_opCONTER:
2446 case FFEBLD_opSYMTER:
2447 case FFEBLD_opARRAYREF:
2448 case FFEBLD_opFUNCREF:
2449 case FFEBLD_opSUBSTR:
c7e4ee3a
CB
2450 /* ~~Do useful truncations here. */
2451 break;
5ff904cd
JL
2452
2453 default:
2454 assert ("op changed or inconsistent switches!" == NULL);
2455 break;
2456 }
2457 }
2458 catlist.exprs[catlist.count++] = expr;
2459 return catlist;
2460
2461 case FFEBLD_opPAREN:
2462 expr = ffebld_left (expr);
2463 goto recurse; /* :::::::::::::::::::: */
2464
2465 case FFEBLD_opCONCATENATE:
2466 catlist = ffecom_concat_list_gather_ (catlist, ffebld_left (expr), max);
2467 expr = ffebld_right (expr);
2468 goto recurse; /* :::::::::::::::::::: */
2469
2470#if 0 /* Breaks passing small actual arg to larger
2471 dummy arg of sfunc */
2472 case FFEBLD_opCONVERT:
2473 expr = ffebld_left (expr);
2474 {
2475 ffetargetCharacterSize cmax;
2476
2477 cmax = catlist.len + ffebld_size_known (expr);
2478
2479 if ((max == FFETARGET_charactersizeNONE) || (max > cmax))
2480 max = cmax;
2481 }
2482 goto recurse; /* :::::::::::::::::::: */
2483#endif
2484
2485 case FFEBLD_opANY:
2486 return catlist;
2487
2488 default:
2489 assert ("bad op in _gather_" == NULL);
2490 return catlist;
2491 }
2492}
2493
2494#endif
2495/* ffecom_concat_list_kill_ -- Kill list of concatenated string exprs
2496
2497 ffecomConcatList_ catlist;
2498 ffecom_concat_list_kill_(catlist);
2499
2500 Anything allocated within the list info is deallocated. */
2501
2502#if FFECOM_targetCURRENT == FFECOM_targetGCC
2503static void
2504ffecom_concat_list_kill_ (ffecomConcatList_ catlist)
2505{
2506 if (catlist.max != 0)
2507 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2508 catlist.max * sizeof (catlist.exprs[0]));
2509}
2510
2511#endif
c7e4ee3a 2512/* Make list of concatenated string exprs.
5ff904cd
JL
2513
2514 Returns a flattened list of concatenated subexpressions given a
2515 tree of such expressions. */
2516
2517#if FFECOM_targetCURRENT == FFECOM_targetGCC
2518static ffecomConcatList_
2519ffecom_concat_list_new_ (ffebld expr, ffetargetCharacterSize max)
2520{
2521 ffecomConcatList_ catlist;
2522
2523 catlist.maxlen = catlist.minlen = catlist.max = catlist.count = 0;
2524 return ffecom_concat_list_gather_ (catlist, expr, max);
2525}
2526
2527#endif
2528
2529/* Provide some kind of useful info on member of aggregate area,
2530 since current g77/gcc technology does not provide debug info
2531 on these members. */
2532
2533#if FFECOM_targetCURRENT == FFECOM_targetGCC
2534static void
26f096f9 2535ffecom_debug_kludge_ (tree aggr, const char *aggr_type, ffesymbol member,
5ff904cd
JL
2536 tree member_type UNUSED, ffetargetOffset offset)
2537{
2538 tree value;
2539 tree decl;
2540 int len;
2541 char *buff;
2542 char space[120];
2543#if 0
2544 tree type_id;
2545
2546 for (type_id = member_type;
2547 TREE_CODE (type_id) != IDENTIFIER_NODE;
2548 )
2549 {
2550 switch (TREE_CODE (type_id))
2551 {
2552 case INTEGER_TYPE:
2553 case REAL_TYPE:
2554 type_id = TYPE_NAME (type_id);
2555 break;
2556
2557 case ARRAY_TYPE:
2558 case COMPLEX_TYPE:
2559 type_id = TREE_TYPE (type_id);
2560 break;
2561
2562 default:
2563 assert ("no IDENTIFIER_NODE for type!" == NULL);
2564 type_id = error_mark_node;
2565 break;
2566 }
2567 }
2568#endif
2569
2570 if (ffecom_transform_only_dummies_
2571 || !ffe_is_debug_kludge ())
2572 return; /* Can't do this yet, maybe later. */
2573
2574 len = 60
2575 + strlen (aggr_type)
2576 + IDENTIFIER_LENGTH (DECL_NAME (aggr));
2577#if 0
2578 + IDENTIFIER_LENGTH (type_id);
2579#endif
2580
2581 if (((size_t) len) >= ARRAY_SIZE (space))
2582 buff = malloc_new_ks (malloc_pool_image (), "debug_kludge", len + 1);
2583 else
2584 buff = &space[0];
2585
2586 sprintf (&buff[0], "At (%s) `%s' plus %ld bytes",
2587 aggr_type,
2588 IDENTIFIER_POINTER (DECL_NAME (aggr)),
2589 (long int) offset);
2590
2591 value = build_string (len, buff);
2592 TREE_TYPE (value)
2593 = build_type_variant (build_array_type (char_type_node,
2594 build_range_type
2595 (integer_type_node,
2596 integer_one_node,
2597 build_int_2 (strlen (buff), 0))),
2598 1, 0);
2599 decl = build_decl (VAR_DECL,
2600 ffecom_get_identifier_ (ffesymbol_text (member)),
2601 TREE_TYPE (value));
2602 TREE_CONSTANT (decl) = 1;
2603 TREE_STATIC (decl) = 1;
2604 DECL_INITIAL (decl) = error_mark_node;
2605 DECL_IN_SYSTEM_HEADER (decl) = 1; /* Don't let -Wunused complain. */
2606 decl = start_decl (decl, FALSE);
2607 finish_decl (decl, value, FALSE);
2608
2609 if (buff != &space[0])
2610 malloc_kill_ks (malloc_pool_image (), buff, len + 1);
2611}
2612#endif
2613
2614/* ffecom_do_entry_ -- Do compilation of a particular entrypoint
2615
2616 ffesymbol fn; // the SUBROUTINE, FUNCTION, or ENTRY symbol itself
2617 int i; // entry# for this entrypoint (used by master fn)
2618 ffecom_do_entrypoint_(s,i);
2619
2620 Makes a public entry point that calls our private master fn (already
2621 compiled). */
2622
2623#if FFECOM_targetCURRENT == FFECOM_targetGCC
2624static void
2625ffecom_do_entry_ (ffesymbol fn, int entrynum)
2626{
2627 ffebld item;
2628 tree type; /* Type of function. */
2629 tree multi_retval; /* Var holding return value (union). */
2630 tree result; /* Var holding result. */
2631 ffeinfoBasictype bt;
2632 ffeinfoKindtype kt;
2633 ffeglobal g;
2634 ffeglobalType gt;
2635 bool charfunc; /* All entry points return same type
2636 CHARACTER. */
2637 bool cmplxfunc; /* Use f2c way of returning COMPLEX. */
2638 bool multi; /* Master fn has multiple return types. */
2639 bool altreturning = FALSE; /* This entry point has alternate returns. */
2640 int yes;
44d2eabc
JL
2641 int old_lineno = lineno;
2642 char *old_input_filename = input_filename;
2643
2644 input_filename = ffesymbol_where_filename (fn);
2645 lineno = ffesymbol_where_filelinenum (fn);
5ff904cd
JL
2646
2647 /* c-parse.y indeed does call suspend_momentary and not only ignores the
2648 return value, but also never calls resume_momentary, when starting an
2649 outer function (see "fndef:", "setspecs:", and so on). So g77 does the
2650 same thing. It shouldn't be a problem since start_function calls
2651 temporary_allocation, but it might be necessary. If it causes a problem
2652 here, then maybe there's a bug lurking in gcc. NOTE: This identical
2653 comment appears twice in thist file. */
2654
2655 suspend_momentary ();
2656
2657 ffecom_doing_entry_ = TRUE; /* Don't bother with array dimensions. */
2658
2659 switch (ffecom_primary_entry_kind_)
2660 {
2661 case FFEINFO_kindFUNCTION:
2662
2663 /* Determine actual return type for function. */
2664
2665 gt = FFEGLOBAL_typeFUNC;
2666 bt = ffesymbol_basictype (fn);
2667 kt = ffesymbol_kindtype (fn);
2668 if (bt == FFEINFO_basictypeNONE)
2669 {
2670 ffeimplic_establish_symbol (fn);
2671 if (ffesymbol_funcresult (fn) != NULL)
2672 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
2673 bt = ffesymbol_basictype (fn);
2674 kt = ffesymbol_kindtype (fn);
2675 }
2676
2677 if (bt == FFEINFO_basictypeCHARACTER)
2678 charfunc = TRUE, cmplxfunc = FALSE;
2679 else if ((bt == FFEINFO_basictypeCOMPLEX)
2680 && ffesymbol_is_f2c (fn))
2681 charfunc = FALSE, cmplxfunc = TRUE;
2682 else
2683 charfunc = cmplxfunc = FALSE;
2684
2685 if (charfunc)
2686 type = ffecom_tree_fun_type_void;
2687 else if (ffesymbol_is_f2c (fn))
2688 type = ffecom_tree_fun_type[bt][kt];
2689 else
2690 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
2691
2692 if ((type == NULL_TREE)
2693 || (TREE_TYPE (type) == NULL_TREE))
2694 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
2695
2696 multi = (ffecom_master_bt_ == FFEINFO_basictypeNONE);
2697 break;
2698
2699 case FFEINFO_kindSUBROUTINE:
2700 gt = FFEGLOBAL_typeSUBR;
2701 bt = FFEINFO_basictypeNONE;
2702 kt = FFEINFO_kindtypeNONE;
2703 if (ffecom_is_altreturning_)
2704 { /* Am _I_ altreturning? */
2705 for (item = ffesymbol_dummyargs (fn);
2706 item != NULL;
2707 item = ffebld_trail (item))
2708 {
2709 if (ffebld_op (ffebld_head (item)) == FFEBLD_opSTAR)
2710 {
2711 altreturning = TRUE;
2712 break;
2713 }
2714 }
2715 if (altreturning)
2716 type = ffecom_tree_subr_type;
2717 else
2718 type = ffecom_tree_fun_type_void;
2719 }
2720 else
2721 type = ffecom_tree_fun_type_void;
2722 charfunc = FALSE;
2723 cmplxfunc = FALSE;
2724 multi = FALSE;
2725 break;
2726
2727 default:
2728 assert ("say what??" == NULL);
2729 /* Fall through. */
2730 case FFEINFO_kindANY:
2731 gt = FFEGLOBAL_typeANY;
2732 bt = FFEINFO_basictypeNONE;
2733 kt = FFEINFO_kindtypeNONE;
2734 type = error_mark_node;
2735 charfunc = FALSE;
2736 cmplxfunc = FALSE;
2737 multi = FALSE;
2738 break;
2739 }
2740
2741 /* build_decl uses the current lineno and input_filename to set the decl
2742 source info. So, I've putzed with ffestd and ffeste code to update that
2743 source info to point to the appropriate statement just before calling
2744 ffecom_do_entrypoint (which calls this fn). */
2745
2746 start_function (ffecom_get_external_identifier_ (fn),
2747 type,
2748 0, /* nested/inline */
2749 1); /* TREE_PUBLIC */
2750
2751 if (((g = ffesymbol_global (fn)) != NULL)
2752 && ((ffeglobal_type (g) == gt)
2753 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
2754 {
2755 ffeglobal_set_hook (g, current_function_decl);
2756 }
2757
2758 /* Reset args in master arg list so they get retransitioned. */
2759
2760 for (item = ffecom_master_arglist_;
2761 item != NULL;
2762 item = ffebld_trail (item))
2763 {
2764 ffebld arg;
2765 ffesymbol s;
2766
2767 arg = ffebld_head (item);
2768 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2769 continue; /* Alternate return or some such thing. */
2770 s = ffebld_symter (arg);
2771 ffesymbol_hook (s).decl_tree = NULL_TREE;
2772 ffesymbol_hook (s).length_tree = NULL_TREE;
2773 }
2774
2775 /* Build dummy arg list for this entry point. */
2776
2777 yes = suspend_momentary ();
2778
2779 if (charfunc || cmplxfunc)
2780 { /* Prepend arg for where result goes. */
2781 tree type;
2782 tree length;
2783
2784 if (charfunc)
2785 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
2786 else
2787 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
2788
2789 result = ffecom_get_invented_identifier ("__g77_%s",
c7e4ee3a 2790 "result", -1);
5ff904cd
JL
2791
2792 /* Make length arg _and_ enhance type info for CHAR arg itself. */
2793
2794 if (charfunc)
2795 length = ffecom_char_enhance_arg_ (&type, fn);
2796 else
2797 length = NULL_TREE; /* Not ref'd if !charfunc. */
2798
2799 type = build_pointer_type (type);
2800 result = build_decl (PARM_DECL, result, type);
2801
2802 push_parm_decl (result);
2803 ffecom_func_result_ = result;
2804
2805 if (charfunc)
2806 {
2807 push_parm_decl (length);
2808 ffecom_func_length_ = length;
2809 }
2810 }
2811 else
2812 result = DECL_RESULT (current_function_decl);
2813
2814 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (fn), FALSE);
2815
2816 resume_momentary (yes);
2817
2818 store_parm_decls (0);
2819
c7e4ee3a
CB
2820 ffecom_start_compstmt ();
2821 /* Disallow temp vars at this level. */
2822 current_binding_level->prep_state = 2;
5ff904cd
JL
2823
2824 /* Make local var to hold return type for multi-type master fn. */
2825
2826 if (multi)
2827 {
2828 yes = suspend_momentary ();
2829
2830 multi_retval = ffecom_get_invented_identifier ("__g77_%s",
c7e4ee3a 2831 "multi_retval", -1);
5ff904cd
JL
2832 multi_retval = build_decl (VAR_DECL, multi_retval,
2833 ffecom_multi_type_node_);
2834 multi_retval = start_decl (multi_retval, FALSE);
2835 finish_decl (multi_retval, NULL_TREE, FALSE);
2836
2837 resume_momentary (yes);
2838 }
2839 else
2840 multi_retval = NULL_TREE; /* Not actually ref'd if !multi. */
2841
2842 /* Here we emit the actual code for the entry point. */
2843
2844 {
2845 ffebld list;
2846 ffebld arg;
2847 ffesymbol s;
2848 tree arglist = NULL_TREE;
2849 tree *plist = &arglist;
2850 tree prepend;
2851 tree call;
2852 tree actarg;
2853 tree master_fn;
2854
2855 /* Prepare actual arg list based on master arg list. */
2856
2857 for (list = ffecom_master_arglist_;
2858 list != NULL;
2859 list = ffebld_trail (list))
2860 {
2861 arg = ffebld_head (list);
2862 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2863 continue;
2864 s = ffebld_symter (arg);
702edf1d
CB
2865 if (ffesymbol_hook (s).decl_tree == NULL_TREE
2866 || ffesymbol_hook (s).decl_tree == error_mark_node)
5ff904cd
JL
2867 actarg = null_pointer_node; /* We don't have this arg. */
2868 else
2869 actarg = ffesymbol_hook (s).decl_tree;
2870 *plist = build_tree_list (NULL_TREE, actarg);
2871 plist = &TREE_CHAIN (*plist);
2872 }
2873
2874 /* This code appends the length arguments for character
2875 variables/arrays. */
2876
2877 for (list = ffecom_master_arglist_;
2878 list != NULL;
2879 list = ffebld_trail (list))
2880 {
2881 arg = ffebld_head (list);
2882 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2883 continue;
2884 s = ffebld_symter (arg);
2885 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
2886 continue; /* Only looking for CHARACTER arguments. */
2887 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
2888 continue; /* Only looking for variables and arrays. */
702edf1d
CB
2889 if (ffesymbol_hook (s).length_tree == NULL_TREE
2890 || ffesymbol_hook (s).length_tree == error_mark_node)
5ff904cd
JL
2891 actarg = ffecom_f2c_ftnlen_zero_node; /* We don't have this arg. */
2892 else
2893 actarg = ffesymbol_hook (s).length_tree;
2894 *plist = build_tree_list (NULL_TREE, actarg);
2895 plist = &TREE_CHAIN (*plist);
2896 }
2897
2898 /* Prepend character-value return info to actual arg list. */
2899
2900 if (charfunc)
2901 {
2902 prepend = build_tree_list (NULL_TREE, ffecom_func_result_);
2903 TREE_CHAIN (prepend)
2904 = build_tree_list (NULL_TREE, ffecom_func_length_);
2905 TREE_CHAIN (TREE_CHAIN (prepend)) = arglist;
2906 arglist = prepend;
2907 }
2908
2909 /* Prepend multi-type return value to actual arg list. */
2910
2911 if (multi)
2912 {
2913 prepend
2914 = build_tree_list (NULL_TREE,
2915 ffecom_1 (ADDR_EXPR,
2916 build_pointer_type (TREE_TYPE (multi_retval)),
2917 multi_retval));
2918 TREE_CHAIN (prepend) = arglist;
2919 arglist = prepend;
2920 }
2921
2922 /* Prepend my entry-point number to the actual arg list. */
2923
2924 prepend = build_tree_list (NULL_TREE, build_int_2 (entrynum, 0));
2925 TREE_CHAIN (prepend) = arglist;
2926 arglist = prepend;
2927
2928 /* Build the call to the master function. */
2929
2930 master_fn = ffecom_1_fn (ffecom_previous_function_decl_);
2931 call = ffecom_3s (CALL_EXPR,
2932 TREE_TYPE (TREE_TYPE (TREE_TYPE (master_fn))),
2933 master_fn, arglist, NULL_TREE);
2934
2935 /* Decide whether the master function is a function or subroutine, and
2936 handle the return value for my entry point. */
2937
2938 if (charfunc || ((ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
2939 && !altreturning))
2940 {
2941 expand_expr_stmt (call);
2942 expand_null_return ();
2943 }
2944 else if (multi && cmplxfunc)
2945 {
2946 expand_expr_stmt (call);
2947 result
2948 = ffecom_1 (INDIRECT_REF,
2949 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
2950 result);
2951 result = ffecom_modify (NULL_TREE, result,
2952 ffecom_2 (COMPONENT_REF, TREE_TYPE (result),
2953 multi_retval,
2954 ffecom_multi_fields_[bt][kt]));
2955 expand_expr_stmt (result);
2956 expand_null_return ();
2957 }
2958 else if (multi)
2959 {
2960 expand_expr_stmt (call);
2961 result
2962 = ffecom_modify (NULL_TREE, result,
2963 convert (TREE_TYPE (result),
2964 ffecom_2 (COMPONENT_REF,
2965 ffecom_tree_type[bt][kt],
2966 multi_retval,
2967 ffecom_multi_fields_[bt][kt])));
2968 expand_return (result);
2969 }
2970 else if (cmplxfunc)
2971 {
2972 result
2973 = ffecom_1 (INDIRECT_REF,
2974 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
2975 result);
2976 result = ffecom_modify (NULL_TREE, result, call);
2977 expand_expr_stmt (result);
2978 expand_null_return ();
2979 }
2980 else
2981 {
2982 result = ffecom_modify (NULL_TREE,
2983 result,
2984 convert (TREE_TYPE (result),
2985 call));
2986 expand_return (result);
2987 }
2988
2989 clear_momentary ();
2990 }
2991
c7e4ee3a 2992 ffecom_end_compstmt ();
5ff904cd
JL
2993
2994 finish_function (0);
2995
44d2eabc
JL
2996 lineno = old_lineno;
2997 input_filename = old_input_filename;
2998
5ff904cd
JL
2999 ffecom_doing_entry_ = FALSE;
3000}
3001
3002#endif
3003/* Transform expr into gcc tree with possible destination
3004
3005 Recursive descent on expr while making corresponding tree nodes and
3006 attaching type info and such. If destination supplied and compatible
3007 with temporary that would be made in certain cases, temporary isn't
092a4ef8 3008 made, destination used instead, and dest_used flag set TRUE. */
5ff904cd
JL
3009
3010#if FFECOM_targetCURRENT == FFECOM_targetGCC
3011static tree
092a4ef8
RH
3012ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
3013 bool *dest_used, bool assignp, bool widenp)
5ff904cd
JL
3014{
3015 tree item;
3016 tree list;
3017 tree args;
3018 ffeinfoBasictype bt;
3019 ffeinfoKindtype kt;
3020 tree t;
5ff904cd 3021 tree dt; /* decl_tree for an ffesymbol. */
092a4ef8 3022 tree tree_type, tree_type_x;
af752698 3023 tree left, right;
5ff904cd
JL
3024 ffesymbol s;
3025 enum tree_code code;
3026
3027 assert (expr != NULL);
3028
3029 if (dest_used != NULL)
3030 *dest_used = FALSE;
3031
3032 bt = ffeinfo_basictype (ffebld_info (expr));
3033 kt = ffeinfo_kindtype (ffebld_info (expr));
af752698 3034 tree_type = ffecom_tree_type[bt][kt];
5ff904cd 3035
092a4ef8
RH
3036 /* Widen integral arithmetic as desired while preserving signedness. */
3037 tree_type_x = NULL_TREE;
3038 if (widenp && tree_type
3039 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
3040 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
3041 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
3042
5ff904cd
JL
3043 switch (ffebld_op (expr))
3044 {
3045 case FFEBLD_opACCTER:
5ff904cd
JL
3046 {
3047 ffebitCount i;
3048 ffebit bits = ffebld_accter_bits (expr);
3049 ffetargetOffset source_offset = 0;
a6fa6420 3050 ffetargetOffset dest_offset = ffebld_accter_pad (expr);
5ff904cd
JL
3051 tree purpose;
3052
a6fa6420
CB
3053 assert (dest_offset == 0
3054 || (bt == FFEINFO_basictypeCHARACTER
3055 && kt == FFEINFO_kindtypeCHARACTER1));
5ff904cd
JL
3056
3057 list = item = NULL;
3058 for (;;)
3059 {
3060 ffebldConstantUnion cu;
3061 ffebitCount length;
3062 bool value;
3063 ffebldConstantArray ca = ffebld_accter (expr);
3064
3065 ffebit_test (bits, source_offset, &value, &length);
3066 if (length == 0)
3067 break;
3068
3069 if (value)
3070 {
3071 for (i = 0; i < length; ++i)
3072 {
3073 cu = ffebld_constantarray_get (ca, bt, kt,
3074 source_offset + i);
3075
3076 t = ffecom_constantunion (&cu, bt, kt, tree_type);
3077
a6fa6420
CB
3078 if (i == 0
3079 && dest_offset != 0)
3080 purpose = build_int_2 (dest_offset, 0);
5ff904cd
JL
3081 else
3082 purpose = NULL_TREE;
3083
3084 if (list == NULL_TREE)
3085 list = item = build_tree_list (purpose, t);
3086 else
3087 {
3088 TREE_CHAIN (item) = build_tree_list (purpose, t);
3089 item = TREE_CHAIN (item);
3090 }
3091 }
3092 }
3093 source_offset += length;
a6fa6420 3094 dest_offset += length;
5ff904cd
JL
3095 }
3096 }
3097
a6fa6420
CB
3098 item = build_int_2 ((ffebld_accter_size (expr)
3099 + ffebld_accter_pad (expr)) - 1, 0);
5ff904cd
JL
3100 ffebit_kill (ffebld_accter_bits (expr));
3101 TREE_TYPE (item) = ffecom_integer_type_node;
3102 item
3103 = build_array_type
3104 (tree_type,
3105 build_range_type (ffecom_integer_type_node,
3106 ffecom_integer_zero_node,
3107 item));
3108 list = build (CONSTRUCTOR, item, NULL_TREE, list);
3109 TREE_CONSTANT (list) = 1;
3110 TREE_STATIC (list) = 1;
3111 return list;
3112
3113 case FFEBLD_opARRTER:
5ff904cd
JL
3114 {
3115 ffetargetOffset i;
3116
a6fa6420
CB
3117 list = NULL_TREE;
3118 if (ffebld_arrter_pad (expr) == 0)
3119 item = NULL_TREE;
3120 else
3121 {
3122 assert (bt == FFEINFO_basictypeCHARACTER
3123 && kt == FFEINFO_kindtypeCHARACTER1);
3124
3125 /* Becomes PURPOSE first time through loop. */
3126 item = build_int_2 (ffebld_arrter_pad (expr), 0);
3127 }
3128
5ff904cd
JL
3129 for (i = 0; i < ffebld_arrter_size (expr); ++i)
3130 {
3131 ffebldConstantUnion cu
3132 = ffebld_constantarray_get (ffebld_arrter (expr), bt, kt, i);
3133
3134 t = ffecom_constantunion (&cu, bt, kt, tree_type);
3135
3136 if (list == NULL_TREE)
a6fa6420
CB
3137 /* Assume item is PURPOSE first time through loop. */
3138 list = item = build_tree_list (item, t);
5ff904cd
JL
3139 else
3140 {
3141 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
3142 item = TREE_CHAIN (item);
3143 }
3144 }
3145 }
3146
a6fa6420
CB
3147 item = build_int_2 ((ffebld_arrter_size (expr)
3148 + ffebld_arrter_pad (expr)) - 1, 0);
5ff904cd
JL
3149 TREE_TYPE (item) = ffecom_integer_type_node;
3150 item
3151 = build_array_type
3152 (tree_type,
3153 build_range_type (ffecom_integer_type_node,
a6fa6420 3154 ffecom_integer_zero_node,
5ff904cd
JL
3155 item));
3156 list = build (CONSTRUCTOR, item, NULL_TREE, list);
3157 TREE_CONSTANT (list) = 1;
3158 TREE_STATIC (list) = 1;
3159 return list;
3160
3161 case FFEBLD_opCONTER:
c264f113 3162 assert (ffebld_conter_pad (expr) == 0);
5ff904cd
JL
3163 item
3164 = ffecom_constantunion (&ffebld_constant_union (ffebld_conter (expr)),
3165 bt, kt, tree_type);
3166 return item;
3167
3168 case FFEBLD_opSYMTER:
3169 if ((ffebld_symter_generic (expr) != FFEINTRIN_genNONE)
3170 || (ffebld_symter_specific (expr) != FFEINTRIN_specNONE))
3171 return ffecom_ptr_to_expr (expr); /* Same as %REF(intrinsic). */
3172 s = ffebld_symter (expr);
3173 t = ffesymbol_hook (s).decl_tree;
3174
3175 if (assignp)
3176 { /* ASSIGN'ed-label expr. */
3177 if (ffe_is_ugly_assign ())
3178 {
3179 /* User explicitly wants ASSIGN'ed variables to be at the same
3180 memory address as the variables when used in non-ASSIGN
3181 contexts. That can make old, arcane, non-standard code
3182 work, but don't try to do it when a pointer wouldn't fit
3183 in the normal variable (take other approach, and warn,
3184 instead). */
3185
3186 if (t == NULL_TREE)
3187 {
3188 s = ffecom_sym_transform_ (s);
3189 t = ffesymbol_hook (s).decl_tree;
3190 assert (t != NULL_TREE);
3191 }
3192
3193 if (t == error_mark_node)
3194 return t;
3195
3196 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (t)))
3197 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
3198 {
3199 if (ffesymbol_hook (s).addr)
3200 t = ffecom_1 (INDIRECT_REF,
3201 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3202 return t;
3203 }
3204
3205 if (ffesymbol_hook (s).assign_tree == NULL_TREE)
3206 {
3207 ffebad_start_msg ("ASSIGN'ed label cannot fit into `%A' at %0 -- using wider sibling",
3208 FFEBAD_severityWARNING);
3209 ffebad_string (ffesymbol_text (s));
3210 ffebad_here (0, ffesymbol_where_line (s),
3211 ffesymbol_where_column (s));
3212 ffebad_finish ();
3213 }
3214 }
3215
3216 /* Don't use the normal variable's tree for ASSIGN, though mark
3217 it as in the system header (housekeeping). Use an explicit,
3218 specially created sibling that is known to be wide enough
3219 to hold pointers to labels. */
3220
3221 if (t != NULL_TREE
3222 && TREE_CODE (t) == VAR_DECL)
3223 DECL_IN_SYSTEM_HEADER (t) = 1; /* Don't let -Wunused complain. */
3224
3225 t = ffesymbol_hook (s).assign_tree;
3226 if (t == NULL_TREE)
3227 {
3228 s = ffecom_sym_transform_assign_ (s);
3229 t = ffesymbol_hook (s).assign_tree;
3230 assert (t != NULL_TREE);
3231 }
3232 }
3233 else
3234 {
3235 if (t == NULL_TREE)
3236 {
3237 s = ffecom_sym_transform_ (s);
3238 t = ffesymbol_hook (s).decl_tree;
3239 assert (t != NULL_TREE);
3240 }
3241 if (ffesymbol_hook (s).addr)
3242 t = ffecom_1 (INDIRECT_REF,
3243 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3244 }
3245 return t;
3246
3247 case FFEBLD_opARRAYREF:
3248 {
6b55276e
CB
3249 if (0 /* ~~~~~ ffe_is_flat_arrays () */)
3250 t = ffecom_ptr_to_expr (ffebld_left (expr));
3251 else
3252 t = ffecom_expr (ffebld_left (expr));
5ff904cd 3253
5ff904cd
JL
3254 if (t == error_mark_node)
3255 return t;
3256
3257 if ((ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereFLEETING)
3258 && !mark_addressable (t))
3259 return error_mark_node; /* Make sure non-const ref is to
3260 non-reg. */
3261
6b55276e 3262 t = ffecom_arrayref_ (t, expr, 0);
5ff904cd
JL
3263
3264 return t;
3265 }
3266
3267 case FFEBLD_opUPLUS:
092a4ef8 3268 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
af752698 3269 return ffecom_1 (NOP_EXPR, tree_type, left);
5ff904cd 3270
c7e4ee3a
CB
3271 case FFEBLD_opPAREN:
3272 /* ~~~Make sure Fortran rules respected here */
092a4ef8 3273 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
af752698 3274 return ffecom_1 (NOP_EXPR, tree_type, left);
5ff904cd
JL
3275
3276 case FFEBLD_opUMINUS:
092a4ef8 3277 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3278 if (tree_type_x)
3279 {
3280 tree_type = tree_type_x;
3281 left = convert (tree_type, left);
3282 }
3283 return ffecom_1 (NEGATE_EXPR, tree_type, left);
5ff904cd
JL
3284
3285 case FFEBLD_opADD:
092a4ef8
RH
3286 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3287 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3288 if (tree_type_x)
3289 {
3290 tree_type = tree_type_x;
3291 left = convert (tree_type, left);
3292 right = convert (tree_type, right);
3293 }
3294 return ffecom_2 (PLUS_EXPR, tree_type, left, right);
5ff904cd
JL
3295
3296 case FFEBLD_opSUBTRACT:
092a4ef8
RH
3297 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3298 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3299 if (tree_type_x)
3300 {
3301 tree_type = tree_type_x;
3302 left = convert (tree_type, left);
3303 right = convert (tree_type, right);
3304 }
3305 return ffecom_2 (MINUS_EXPR, tree_type, left, right);
5ff904cd
JL
3306
3307 case FFEBLD_opMULTIPLY:
092a4ef8
RH
3308 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3309 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3310 if (tree_type_x)
3311 {
3312 tree_type = tree_type_x;
3313 left = convert (tree_type, left);
3314 right = convert (tree_type, right);
3315 }
3316 return ffecom_2 (MULT_EXPR, tree_type, left, right);
5ff904cd
JL
3317
3318 case FFEBLD_opDIVIDE:
092a4ef8
RH
3319 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3320 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3321 if (tree_type_x)
3322 {
3323 tree_type = tree_type_x;
3324 left = convert (tree_type, left);
3325 right = convert (tree_type, right);
3326 }
3327 return ffecom_tree_divide_ (tree_type, left, right,
c7e4ee3a
CB
3328 dest_tree, dest, dest_used,
3329 ffebld_nonter_hook (expr));
5ff904cd
JL
3330
3331 case FFEBLD_opPOWER:
5ff904cd
JL
3332 {
3333 ffebld left = ffebld_left (expr);
3334 ffebld right = ffebld_right (expr);
3335 ffecomGfrt code;
3336 ffeinfoKindtype rtkt;
270fc4e8 3337 ffeinfoKindtype ltkt;
5ff904cd
JL
3338
3339 switch (ffeinfo_basictype (ffebld_info (right)))
3340 {
3341 case FFEINFO_basictypeINTEGER:
3342 if (1 || optimize)
3343 {
c7e4ee3a 3344 item = ffecom_expr_power_integer_ (expr);
5ff904cd
JL
3345 if (item != NULL_TREE)
3346 return item;
3347 }
3348
3349 rtkt = FFEINFO_kindtypeINTEGER1;
3350 switch (ffeinfo_basictype (ffebld_info (left)))
3351 {
3352 case FFEINFO_basictypeINTEGER:
3353 if ((ffeinfo_kindtype (ffebld_info (left))
3354 == FFEINFO_kindtypeINTEGER4)
3355 || (ffeinfo_kindtype (ffebld_info (right))
3356 == FFEINFO_kindtypeINTEGER4))
3357 {
3358 code = FFECOM_gfrtPOW_QQ;
270fc4e8 3359 ltkt = FFEINFO_kindtypeINTEGER4;
5ff904cd
JL
3360 rtkt = FFEINFO_kindtypeINTEGER4;
3361 }
3362 else
6a047254
CB
3363 {
3364 code = FFECOM_gfrtPOW_II;
3365 ltkt = FFEINFO_kindtypeINTEGER1;
3366 }
5ff904cd
JL
3367 break;
3368
3369 case FFEINFO_basictypeREAL:
3370 if (ffeinfo_kindtype (ffebld_info (left))
3371 == FFEINFO_kindtypeREAL1)
6a047254
CB
3372 {
3373 code = FFECOM_gfrtPOW_RI;
3374 ltkt = FFEINFO_kindtypeREAL1;
3375 }
5ff904cd 3376 else
6a047254
CB
3377 {
3378 code = FFECOM_gfrtPOW_DI;
3379 ltkt = FFEINFO_kindtypeREAL2;
3380 }
5ff904cd
JL
3381 break;
3382
3383 case FFEINFO_basictypeCOMPLEX:
3384 if (ffeinfo_kindtype (ffebld_info (left))
3385 == FFEINFO_kindtypeREAL1)
6a047254
CB
3386 {
3387 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
3388 ltkt = FFEINFO_kindtypeREAL1;
3389 }
5ff904cd 3390 else
6a047254
CB
3391 {
3392 code = FFECOM_gfrtPOW_ZI; /* Overlapping result okay. */
3393 ltkt = FFEINFO_kindtypeREAL2;
3394 }
5ff904cd
JL
3395 break;
3396
3397 default:
3398 assert ("bad pow_*i" == NULL);
3399 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
6a047254 3400 ltkt = FFEINFO_kindtypeREAL1;
5ff904cd
JL
3401 break;
3402 }
270fc4e8 3403 if (ffeinfo_kindtype (ffebld_info (left)) != ltkt)
5ff904cd 3404 left = ffeexpr_convert (left, NULL, NULL,
6a047254 3405 ffeinfo_basictype (ffebld_info (left)),
270fc4e8 3406 ltkt, 0,
5ff904cd
JL
3407 FFETARGET_charactersizeNONE,
3408 FFEEXPR_contextLET);
3409 if (ffeinfo_kindtype (ffebld_info (right)) != rtkt)
3410 right = ffeexpr_convert (right, NULL, NULL,
3411 FFEINFO_basictypeINTEGER,
3412 rtkt, 0,
3413 FFETARGET_charactersizeNONE,
3414 FFEEXPR_contextLET);
3415 break;
3416
3417 case FFEINFO_basictypeREAL:
3418 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3419 left = ffeexpr_convert (left, NULL, NULL, FFEINFO_basictypeREAL,
3420 FFEINFO_kindtypeREALDOUBLE, 0,
3421 FFETARGET_charactersizeNONE,
3422 FFEEXPR_contextLET);
3423 if (ffeinfo_kindtype (ffebld_info (right))
3424 == FFEINFO_kindtypeREAL1)
3425 right = ffeexpr_convert (right, NULL, NULL,
3426 FFEINFO_basictypeREAL,
3427 FFEINFO_kindtypeREALDOUBLE, 0,
3428 FFETARGET_charactersizeNONE,
3429 FFEEXPR_contextLET);
3430 code = FFECOM_gfrtPOW_DD;
3431 break;
3432
3433 case FFEINFO_basictypeCOMPLEX:
3434 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3435 left = ffeexpr_convert (left, NULL, NULL,
3436 FFEINFO_basictypeCOMPLEX,
3437 FFEINFO_kindtypeREALDOUBLE, 0,
3438 FFETARGET_charactersizeNONE,
3439 FFEEXPR_contextLET);
3440 if (ffeinfo_kindtype (ffebld_info (right))
3441 == FFEINFO_kindtypeREAL1)
3442 right = ffeexpr_convert (right, NULL, NULL,
3443 FFEINFO_basictypeCOMPLEX,
3444 FFEINFO_kindtypeREALDOUBLE, 0,
3445 FFETARGET_charactersizeNONE,
3446 FFEEXPR_contextLET);
3447 code = FFECOM_gfrtPOW_ZZ; /* Overlapping result okay. */
3448 break;
3449
3450 default:
3451 assert ("bad pow_x*" == NULL);
3452 code = FFECOM_gfrtPOW_II;
3453 break;
3454 }
3455 return ffecom_call_binop_ (ffecom_gfrt_tree_ (code),
3456 ffecom_gfrt_kindtype (code),
3457 (ffe_is_f2c_library ()
3458 && ffecom_gfrt_complex_[code]),
3459 tree_type, left, right,
3460 dest_tree, dest, dest_used,
c7e4ee3a
CB
3461 NULL_TREE, FALSE,
3462 ffebld_nonter_hook (expr));
5ff904cd
JL
3463 }
3464
3465 case FFEBLD_opNOT:
5ff904cd
JL
3466 switch (bt)
3467 {
3468 case FFEINFO_basictypeLOGICAL:
83ffecd2 3469 item = ffecom_truth_value_invert (ffecom_expr (ffebld_left (expr)));
5ff904cd
JL
3470 return convert (tree_type, item);
3471
3472 case FFEINFO_basictypeINTEGER:
3473 return ffecom_1 (BIT_NOT_EXPR, tree_type,
3474 ffecom_expr (ffebld_left (expr)));
3475
3476 default:
3477 assert ("NOT bad basictype" == NULL);
3478 /* Fall through. */
3479 case FFEINFO_basictypeANY:
3480 return error_mark_node;
3481 }
3482 break;
3483
3484 case FFEBLD_opFUNCREF:
3485 assert (ffeinfo_basictype (ffebld_info (expr))
3486 != FFEINFO_basictypeCHARACTER);
3487 /* Fall through. */
3488 case FFEBLD_opSUBRREF:
5ff904cd
JL
3489 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
3490 == FFEINFO_whereINTRINSIC)
3491 { /* Invocation of an intrinsic. */
3492 item = ffecom_expr_intrinsic_ (expr, dest_tree, dest,
3493 dest_used);
3494 return item;
3495 }
3496 s = ffebld_symter (ffebld_left (expr));
3497 dt = ffesymbol_hook (s).decl_tree;
3498 if (dt == NULL_TREE)
3499 {
3500 s = ffecom_sym_transform_ (s);
3501 dt = ffesymbol_hook (s).decl_tree;
3502 }
3503 if (dt == error_mark_node)
3504 return dt;
3505
3506 if (ffesymbol_hook (s).addr)
3507 item = dt;
3508 else
3509 item = ffecom_1_fn (dt);
3510
5ff904cd
JL
3511 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
3512 args = ffecom_list_expr (ffebld_right (expr));
3513 else
3514 args = ffecom_list_ptr_to_expr (ffebld_right (expr));
5ff904cd 3515
702edf1d
CB
3516 if (args == error_mark_node)
3517 return error_mark_node;
3518
5ff904cd
JL
3519 item = ffecom_call_ (item, kt,
3520 ffesymbol_is_f2c (s)
3521 && (bt == FFEINFO_basictypeCOMPLEX)
3522 && (ffesymbol_where (s)
3523 != FFEINFO_whereCONSTANT),
3524 tree_type,
3525 args,
3526 dest_tree, dest, dest_used,
c7e4ee3a
CB
3527 error_mark_node, FALSE,
3528 ffebld_nonter_hook (expr));
5ff904cd
JL
3529 TREE_SIDE_EFFECTS (item) = 1;
3530 return item;
3531
3532 case FFEBLD_opAND:
5ff904cd
JL
3533 switch (bt)
3534 {
3535 case FFEINFO_basictypeLOGICAL:
3536 item
3537 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3538 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3539 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3540 return convert (tree_type, item);
3541
3542 case FFEINFO_basictypeINTEGER:
3543 return ffecom_2 (BIT_AND_EXPR, tree_type,
3544 ffecom_expr (ffebld_left (expr)),
3545 ffecom_expr (ffebld_right (expr)));
3546
3547 default:
3548 assert ("AND bad basictype" == NULL);
3549 /* Fall through. */
3550 case FFEINFO_basictypeANY:
3551 return error_mark_node;
3552 }
3553 break;
3554
3555 case FFEBLD_opOR:
5ff904cd
JL
3556 switch (bt)
3557 {
3558 case FFEINFO_basictypeLOGICAL:
3559 item
3560 = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
3561 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3562 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3563 return convert (tree_type, item);
3564
3565 case FFEINFO_basictypeINTEGER:
3566 return ffecom_2 (BIT_IOR_EXPR, tree_type,
3567 ffecom_expr (ffebld_left (expr)),
3568 ffecom_expr (ffebld_right (expr)));
3569
3570 default:
3571 assert ("OR bad basictype" == NULL);
3572 /* Fall through. */
3573 case FFEINFO_basictypeANY:
3574 return error_mark_node;
3575 }
3576 break;
3577
3578 case FFEBLD_opXOR:
3579 case FFEBLD_opNEQV:
5ff904cd
JL
3580 switch (bt)
3581 {
3582 case FFEINFO_basictypeLOGICAL:
3583 item
3584 = ffecom_2 (NE_EXPR, integer_type_node,
3585 ffecom_expr (ffebld_left (expr)),
3586 ffecom_expr (ffebld_right (expr)));
3587 return convert (tree_type, ffecom_truth_value (item));
3588
3589 case FFEINFO_basictypeINTEGER:
3590 return ffecom_2 (BIT_XOR_EXPR, tree_type,
3591 ffecom_expr (ffebld_left (expr)),
3592 ffecom_expr (ffebld_right (expr)));
3593
3594 default:
3595 assert ("XOR/NEQV bad basictype" == NULL);
3596 /* Fall through. */
3597 case FFEINFO_basictypeANY:
3598 return error_mark_node;
3599 }
3600 break;
3601
3602 case FFEBLD_opEQV:
5ff904cd
JL
3603 switch (bt)
3604 {
3605 case FFEINFO_basictypeLOGICAL:
3606 item
3607 = ffecom_2 (EQ_EXPR, integer_type_node,
3608 ffecom_expr (ffebld_left (expr)),
3609 ffecom_expr (ffebld_right (expr)));
3610 return convert (tree_type, ffecom_truth_value (item));
3611
3612 case FFEINFO_basictypeINTEGER:
3613 return
3614 ffecom_1 (BIT_NOT_EXPR, tree_type,
3615 ffecom_2 (BIT_XOR_EXPR, tree_type,
3616 ffecom_expr (ffebld_left (expr)),
3617 ffecom_expr (ffebld_right (expr))));
3618
3619 default:
3620 assert ("EQV bad basictype" == NULL);
3621 /* Fall through. */
3622 case FFEINFO_basictypeANY:
3623 return error_mark_node;
3624 }
3625 break;
3626
3627 case FFEBLD_opCONVERT:
3628 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opANY)
3629 return error_mark_node;
3630
5ff904cd
JL
3631 switch (bt)
3632 {
3633 case FFEINFO_basictypeLOGICAL:
3634 case FFEINFO_basictypeINTEGER:
3635 case FFEINFO_basictypeREAL:
3636 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3637
3638 case FFEINFO_basictypeCOMPLEX:
3639 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3640 {
3641 case FFEINFO_basictypeINTEGER:
3642 case FFEINFO_basictypeLOGICAL:
3643 case FFEINFO_basictypeREAL:
3644 item = ffecom_expr (ffebld_left (expr));
3645 if (item == error_mark_node)
3646 return error_mark_node;
3647 /* convert() takes care of converting to the subtype first,
3648 at least in gcc-2.7.2. */
3649 item = convert (tree_type, item);
3650 return item;
3651
3652 case FFEINFO_basictypeCOMPLEX:
3653 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3654
3655 default:
3656 assert ("CONVERT COMPLEX bad basictype" == NULL);
3657 /* Fall through. */
3658 case FFEINFO_basictypeANY:
3659 return error_mark_node;
3660 }
3661 break;
3662
3663 default:
3664 assert ("CONVERT bad basictype" == NULL);
3665 /* Fall through. */
3666 case FFEINFO_basictypeANY:
3667 return error_mark_node;
3668 }
3669 break;
3670
3671 case FFEBLD_opLT:
3672 code = LT_EXPR;
3673 goto relational; /* :::::::::::::::::::: */
3674
3675 case FFEBLD_opLE:
3676 code = LE_EXPR;
3677 goto relational; /* :::::::::::::::::::: */
3678
3679 case FFEBLD_opEQ:
3680 code = EQ_EXPR;
3681 goto relational; /* :::::::::::::::::::: */
3682
3683 case FFEBLD_opNE:
3684 code = NE_EXPR;
3685 goto relational; /* :::::::::::::::::::: */
3686
3687 case FFEBLD_opGT:
3688 code = GT_EXPR;
3689 goto relational; /* :::::::::::::::::::: */
3690
3691 case FFEBLD_opGE:
3692 code = GE_EXPR;
3693
3694 relational: /* :::::::::::::::::::: */
5ff904cd
JL
3695 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3696 {
3697 case FFEINFO_basictypeLOGICAL:
3698 case FFEINFO_basictypeINTEGER:
3699 case FFEINFO_basictypeREAL:
3700 item = ffecom_2 (code, integer_type_node,
3701 ffecom_expr (ffebld_left (expr)),
3702 ffecom_expr (ffebld_right (expr)));
3703 return convert (tree_type, item);
3704
3705 case FFEINFO_basictypeCOMPLEX:
3706 assert (code == EQ_EXPR || code == NE_EXPR);
3707 {
3708 tree real_type;
3709 tree arg1 = ffecom_expr (ffebld_left (expr));
3710 tree arg2 = ffecom_expr (ffebld_right (expr));
3711
3712 if (arg1 == error_mark_node || arg2 == error_mark_node)
3713 return error_mark_node;
3714
3715 arg1 = ffecom_save_tree (arg1);
3716 arg2 = ffecom_save_tree (arg2);
3717
3718 if (TREE_CODE (TREE_TYPE (arg1)) == COMPLEX_TYPE)
3719 {
3720 real_type = TREE_TYPE (TREE_TYPE (arg1));
3721 assert (real_type == TREE_TYPE (TREE_TYPE (arg2)));
3722 }
3723 else
3724 {
3725 real_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg1)));
3726 assert (real_type == TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg2))));
3727 }
3728
3729 item
3730 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3731 ffecom_2 (EQ_EXPR, integer_type_node,
3732 ffecom_1 (REALPART_EXPR, real_type, arg1),
3733 ffecom_1 (REALPART_EXPR, real_type, arg2)),
3734 ffecom_2 (EQ_EXPR, integer_type_node,
3735 ffecom_1 (IMAGPART_EXPR, real_type, arg1),
3736 ffecom_1 (IMAGPART_EXPR, real_type,
3737 arg2)));
3738 if (code == EQ_EXPR)
3739 item = ffecom_truth_value (item);
3740 else
3741 item = ffecom_truth_value_invert (item);
3742 return convert (tree_type, item);
3743 }
3744
3745 case FFEINFO_basictypeCHARACTER:
5ff904cd
JL
3746 {
3747 ffebld left = ffebld_left (expr);
3748 ffebld right = ffebld_right (expr);
3749 tree left_tree;
3750 tree right_tree;
3751 tree left_length;
3752 tree right_length;
3753
3754 /* f2c run-time functions do the implicit blank-padding for us,
3755 so we don't usually have to implement blank-padding ourselves.
3756 (The exception is when we pass an argument to a separately
3757 compiled statement function -- if we know the arg is not the
3758 same length as the dummy, we must truncate or extend it. If
3759 we "inline" statement functions, that necessity goes away as
3760 well.)
3761
3762 Strip off the CONVERT operators that blank-pad. (Truncation by
3763 CONVERT shouldn't happen here, but it can happen in
3764 assignments.) */
3765
3766 while (ffebld_op (left) == FFEBLD_opCONVERT)
3767 left = ffebld_left (left);
3768 while (ffebld_op (right) == FFEBLD_opCONVERT)
3769 right = ffebld_left (right);
3770
3771 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
3772 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
3773
3774 if (left_tree == error_mark_node || left_length == error_mark_node
3775 || right_tree == error_mark_node
3776 || right_length == error_mark_node)
c7e4ee3a 3777 return error_mark_node;
5ff904cd
JL
3778
3779 if ((ffebld_size_known (left) == 1)
3780 && (ffebld_size_known (right) == 1))
3781 {
3782 left_tree
3783 = ffecom_1 (INDIRECT_REF,
3784 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3785 left_tree);
3786 right_tree
3787 = ffecom_1 (INDIRECT_REF,
3788 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3789 right_tree);
3790
3791 item
3792 = ffecom_2 (code, integer_type_node,
3793 ffecom_2 (ARRAY_REF,
3794 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3795 left_tree,
3796 integer_one_node),
3797 ffecom_2 (ARRAY_REF,
3798 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3799 right_tree,
3800 integer_one_node));
3801 }
3802 else
3803 {
3804 item = build_tree_list (NULL_TREE, left_tree);
3805 TREE_CHAIN (item) = build_tree_list (NULL_TREE, right_tree);
3806 TREE_CHAIN (TREE_CHAIN (item)) = build_tree_list (NULL_TREE,
3807 left_length);
3808 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
3809 = build_tree_list (NULL_TREE, right_length);
c7e4ee3a 3810 item = ffecom_call_gfrt (FFECOM_gfrtCMP, item, NULL_TREE);
5ff904cd
JL
3811 item = ffecom_2 (code, integer_type_node,
3812 item,
3813 convert (TREE_TYPE (item),
3814 integer_zero_node));
3815 }
3816 item = convert (tree_type, item);
3817 }
3818
5ff904cd
JL
3819 return item;
3820
3821 default:
3822 assert ("relational bad basictype" == NULL);
3823 /* Fall through. */
3824 case FFEINFO_basictypeANY:
3825 return error_mark_node;
3826 }
3827 break;
3828
3829 case FFEBLD_opPERCENT_LOC:
5ff904cd
JL
3830 item = ffecom_arg_ptr_to_expr (ffebld_left (expr), &list);
3831 return convert (tree_type, item);
3832
3833 case FFEBLD_opITEM:
3834 case FFEBLD_opSTAR:
3835 case FFEBLD_opBOUNDS:
3836 case FFEBLD_opREPEAT:
3837 case FFEBLD_opLABTER:
3838 case FFEBLD_opLABTOK:
3839 case FFEBLD_opIMPDO:
3840 case FFEBLD_opCONCATENATE:
3841 case FFEBLD_opSUBSTR:
3842 default:
3843 assert ("bad op" == NULL);
3844 /* Fall through. */
3845 case FFEBLD_opANY:
3846 return error_mark_node;
3847 }
3848
3849#if 1
3850 assert ("didn't think anything got here anymore!!" == NULL);
3851#else
3852 switch (ffebld_arity (expr))
3853 {
3854 case 2:
3855 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3856 TREE_OPERAND (item, 1) = ffecom_expr (ffebld_right (expr));
3857 if (TREE_OPERAND (item, 0) == error_mark_node
3858 || TREE_OPERAND (item, 1) == error_mark_node)
3859 return error_mark_node;
3860 break;
3861
3862 case 1:
3863 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3864 if (TREE_OPERAND (item, 0) == error_mark_node)
3865 return error_mark_node;
3866 break;
3867
3868 default:
3869 break;
3870 }
3871
3872 return fold (item);
3873#endif
3874}
3875
3876#endif
3877/* Returns the tree that does the intrinsic invocation.
3878
3879 Note: this function applies only to intrinsics returning
3880 CHARACTER*1 or non-CHARACTER results, and to intrinsic
3881 subroutines. */
3882
3883#if FFECOM_targetCURRENT == FFECOM_targetGCC
3884static tree
3885ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
3886 ffebld dest, bool *dest_used)
3887{
3888 tree expr_tree;
3889 tree saved_expr1; /* For those who need it. */
3890 tree saved_expr2; /* For those who need it. */
3891 ffeinfoBasictype bt;
3892 ffeinfoKindtype kt;
3893 tree tree_type;
3894 tree arg1_type;
3895 tree real_type; /* REAL type corresponding to COMPLEX. */
3896 tree tempvar;
3897 ffebld list = ffebld_right (expr); /* List of (some) args. */
3898 ffebld arg1; /* For handy reference. */
3899 ffebld arg2;
3900 ffebld arg3;
3901 ffeintrinImp codegen_imp;
3902 ffecomGfrt gfrt;
3903
3904 assert (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER);
3905
3906 if (dest_used != NULL)
3907 *dest_used = FALSE;
3908
3909 bt = ffeinfo_basictype (ffebld_info (expr));
3910 kt = ffeinfo_kindtype (ffebld_info (expr));
3911 tree_type = ffecom_tree_type[bt][kt];
3912
3913 if (list != NULL)
3914 {
3915 arg1 = ffebld_head (list);
3916 if (arg1 != NULL && ffebld_op (arg1) == FFEBLD_opANY)
3917 return error_mark_node;
3918 if ((list = ffebld_trail (list)) != NULL)
3919 {
3920 arg2 = ffebld_head (list);
3921 if (arg2 != NULL && ffebld_op (arg2) == FFEBLD_opANY)
3922 return error_mark_node;
3923 if ((list = ffebld_trail (list)) != NULL)
3924 {
3925 arg3 = ffebld_head (list);
3926 if (arg3 != NULL && ffebld_op (arg3) == FFEBLD_opANY)
3927 return error_mark_node;
3928 }
3929 else
3930 arg3 = NULL;
3931 }
3932 else
3933 arg2 = arg3 = NULL;
3934 }
3935 else
3936 arg1 = arg2 = arg3 = NULL;
3937
3938 /* <list> ends up at the opITEM of the 3rd arg, or NULL if there are < 3
3939 args. This is used by the MAX/MIN expansions. */
3940
3941 if (arg1 != NULL)
3942 arg1_type = ffecom_tree_type
3943 [ffeinfo_basictype (ffebld_info (arg1))]
3944 [ffeinfo_kindtype (ffebld_info (arg1))];
3945 else
3946 arg1_type = NULL_TREE; /* Really not needed, but might catch bugs
3947 here. */
3948
3949 /* There are several ways for each of the cases in the following switch
3950 statements to exit (from simplest to use to most complicated):
3951
3952 break; (when expr_tree == NULL)
3953
3954 A standard call is made to the specific intrinsic just as if it had been
3955 passed in as a dummy procedure and called as any old procedure. This
3956 method can produce slower code but in some cases it's the easiest way for
3957 now. However, if a (presumably faster) direct call is available,
3958 that is used, so this is the easiest way in many more cases now.
3959
3960 gfrt = FFECOM_gfrtWHATEVER;
3961 break;
3962
3963 gfrt contains the gfrt index of a library function to call, passing the
3964 argument(s) by value rather than by reference. Used when a more
3965 careful choice of library function is needed than that provided
3966 by the vanilla `break;'.
3967
3968 return expr_tree;
3969
3970 The expr_tree has been completely set up and is ready to be returned
3971 as is. No further actions are taken. Use this when the tree is not
3972 in the simple form for one of the arity_n labels. */
3973
3974 /* For info on how the switch statement cases were written, see the files
3975 enclosed in comments below the switch statement. */
3976
3977 codegen_imp = ffebld_symter_implementation (ffebld_left (expr));
3978 gfrt = ffeintrin_gfrt_direct (codegen_imp);
3979 if (gfrt == FFECOM_gfrt)
3980 gfrt = ffeintrin_gfrt_indirect (codegen_imp);
3981
3982 switch (codegen_imp)
3983 {
3984 case FFEINTRIN_impABS:
3985 case FFEINTRIN_impCABS:
3986 case FFEINTRIN_impCDABS:
3987 case FFEINTRIN_impDABS:
3988 case FFEINTRIN_impIABS:
3989 if (ffeinfo_basictype (ffebld_info (arg1))
3990 == FFEINFO_basictypeCOMPLEX)
3991 {
3992 if (kt == FFEINFO_kindtypeREAL1)
3993 gfrt = FFECOM_gfrtCABS;
3994 else if (kt == FFEINFO_kindtypeREAL2)
3995 gfrt = FFECOM_gfrtCDABS;
3996 break;
3997 }
3998 return ffecom_1 (ABS_EXPR, tree_type,
3999 convert (tree_type, ffecom_expr (arg1)));
4000
4001 case FFEINTRIN_impACOS:
4002 case FFEINTRIN_impDACOS:
4003 break;
4004
4005 case FFEINTRIN_impAIMAG:
4006 case FFEINTRIN_impDIMAG:
4007 case FFEINTRIN_impIMAGPART:
4008 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4009 arg1_type = TREE_TYPE (arg1_type);
4010 else
4011 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4012
4013 return
4014 convert (tree_type,
4015 ffecom_1 (IMAGPART_EXPR, arg1_type,
4016 ffecom_expr (arg1)));
4017
4018 case FFEINTRIN_impAINT:
4019 case FFEINTRIN_impDINT:
c7e4ee3a
CB
4020#if 0
4021 /* ~~Someday implement FIX_TRUNC_EXPR yielding same type as arg. */
5ff904cd
JL
4022 return ffecom_1 (FIX_TRUNC_EXPR, tree_type, ffecom_expr (arg1));
4023#else /* in the meantime, must use floor to avoid range problems with ints */
4024 /* r__1 = r1 >= 0 ? floor(r1) : -floor(-r1); */
4025 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4026 return
4027 convert (tree_type,
4028 ffecom_3 (COND_EXPR, double_type_node,
4029 ffecom_truth_value
4030 (ffecom_2 (GE_EXPR, integer_type_node,
4031 saved_expr1,
4032 convert (arg1_type,
4033 ffecom_float_zero_))),
4034 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4035 build_tree_list (NULL_TREE,
4036 convert (double_type_node,
c7e4ee3a
CB
4037 saved_expr1)),
4038 NULL_TREE),
5ff904cd
JL
4039 ffecom_1 (NEGATE_EXPR, double_type_node,
4040 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4041 build_tree_list (NULL_TREE,
4042 convert (double_type_node,
4043 ffecom_1 (NEGATE_EXPR,
4044 arg1_type,
c7e4ee3a
CB
4045 saved_expr1))),
4046 NULL_TREE)
5ff904cd
JL
4047 ))
4048 );
4049#endif
4050
4051 case FFEINTRIN_impANINT:
4052 case FFEINTRIN_impDNINT:
4053#if 0 /* This way of doing it won't handle real
4054 numbers of large magnitudes. */
4055 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4056 expr_tree = convert (tree_type,
4057 convert (integer_type_node,
4058 ffecom_3 (COND_EXPR, tree_type,
4059 ffecom_truth_value
4060 (ffecom_2 (GE_EXPR,
4061 integer_type_node,
4062 saved_expr1,
4063 ffecom_float_zero_)),
4064 ffecom_2 (PLUS_EXPR,
4065 tree_type,
4066 saved_expr1,
4067 ffecom_float_half_),
4068 ffecom_2 (MINUS_EXPR,
4069 tree_type,
4070 saved_expr1,
4071 ffecom_float_half_))));
4072 return expr_tree;
4073#else /* So we instead call floor. */
4074 /* r__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1) */
4075 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4076 return
4077 convert (tree_type,
4078 ffecom_3 (COND_EXPR, double_type_node,
4079 ffecom_truth_value
4080 (ffecom_2 (GE_EXPR, integer_type_node,
4081 saved_expr1,
4082 convert (arg1_type,
4083 ffecom_float_zero_))),
4084 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4085 build_tree_list (NULL_TREE,
4086 convert (double_type_node,
4087 ffecom_2 (PLUS_EXPR,
4088 arg1_type,
4089 saved_expr1,
4090 convert (arg1_type,
c7e4ee3a
CB
4091 ffecom_float_half_)))),
4092 NULL_TREE),
5ff904cd
JL
4093 ffecom_1 (NEGATE_EXPR, double_type_node,
4094 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4095 build_tree_list (NULL_TREE,
4096 convert (double_type_node,
4097 ffecom_2 (MINUS_EXPR,
4098 arg1_type,
4099 convert (arg1_type,
4100 ffecom_float_half_),
c7e4ee3a
CB
4101 saved_expr1))),
4102 NULL_TREE))
5ff904cd
JL
4103 )
4104 );
4105#endif
4106
4107 case FFEINTRIN_impASIN:
4108 case FFEINTRIN_impDASIN:
4109 case FFEINTRIN_impATAN:
4110 case FFEINTRIN_impDATAN:
4111 case FFEINTRIN_impATAN2:
4112 case FFEINTRIN_impDATAN2:
4113 break;
4114
4115 case FFEINTRIN_impCHAR:
4116 case FFEINTRIN_impACHAR:
c7e4ee3a
CB
4117#ifdef HOHO
4118 tempvar = ffecom_make_tempvar (char_type_node, 1, -1);
4119#else
4120 tempvar = ffebld_nonter_hook (expr);
4121 assert (tempvar);
4122#endif
5ff904cd
JL
4123 {
4124 tree tmv = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (tempvar)));
4125
4126 expr_tree = ffecom_modify (tmv,
4127 ffecom_2 (ARRAY_REF, tmv, tempvar,
4128 integer_one_node),
4129 convert (tmv, ffecom_expr (arg1)));
4130 }
4131 expr_tree = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar),
4132 expr_tree,
4133 tempvar);
4134 expr_tree = ffecom_1 (ADDR_EXPR,
4135 build_pointer_type (TREE_TYPE (expr_tree)),
4136 expr_tree);
4137 return expr_tree;
4138
4139 case FFEINTRIN_impCMPLX:
4140 case FFEINTRIN_impDCMPLX:
4141 if (arg2 == NULL)
4142 return
4143 convert (tree_type, ffecom_expr (arg1));
4144
4145 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4146 return
4147 ffecom_2 (COMPLEX_EXPR, tree_type,
4148 convert (real_type, ffecom_expr (arg1)),
4149 convert (real_type,
4150 ffecom_expr (arg2)));
4151
4152 case FFEINTRIN_impCOMPLEX:
4153 return
4154 ffecom_2 (COMPLEX_EXPR, tree_type,
4155 ffecom_expr (arg1),
4156 ffecom_expr (arg2));
4157
4158 case FFEINTRIN_impCONJG:
4159 case FFEINTRIN_impDCONJG:
4160 {
4161 tree arg1_tree;
4162
4163 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4164 arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4165 return
4166 ffecom_2 (COMPLEX_EXPR, tree_type,
4167 ffecom_1 (REALPART_EXPR, real_type, arg1_tree),
4168 ffecom_1 (NEGATE_EXPR, real_type,
4169 ffecom_1 (IMAGPART_EXPR, real_type, arg1_tree)));
4170 }
4171
4172 case FFEINTRIN_impCOS:
4173 case FFEINTRIN_impCCOS:
4174 case FFEINTRIN_impCDCOS:
4175 case FFEINTRIN_impDCOS:
4176 if (bt == FFEINFO_basictypeCOMPLEX)
4177 {
4178 if (kt == FFEINFO_kindtypeREAL1)
4179 gfrt = FFECOM_gfrtCCOS; /* Overlapping result okay. */
4180 else if (kt == FFEINFO_kindtypeREAL2)
4181 gfrt = FFECOM_gfrtCDCOS; /* Overlapping result okay. */
4182 }
4183 break;
4184
4185 case FFEINTRIN_impCOSH:
4186 case FFEINTRIN_impDCOSH:
4187 break;
4188
4189 case FFEINTRIN_impDBLE:
4190 case FFEINTRIN_impDFLOAT:
4191 case FFEINTRIN_impDREAL:
4192 case FFEINTRIN_impFLOAT:
4193 case FFEINTRIN_impIDINT:
4194 case FFEINTRIN_impIFIX:
4195 case FFEINTRIN_impINT2:
4196 case FFEINTRIN_impINT8:
4197 case FFEINTRIN_impINT:
4198 case FFEINTRIN_impLONG:
4199 case FFEINTRIN_impREAL:
4200 case FFEINTRIN_impSHORT:
4201 case FFEINTRIN_impSNGL:
4202 return convert (tree_type, ffecom_expr (arg1));
4203
4204 case FFEINTRIN_impDIM:
4205 case FFEINTRIN_impDDIM:
4206 case FFEINTRIN_impIDIM:
4207 saved_expr1 = ffecom_save_tree (convert (tree_type,
4208 ffecom_expr (arg1)));
4209 saved_expr2 = ffecom_save_tree (convert (tree_type,
4210 ffecom_expr (arg2)));
4211 return
4212 ffecom_3 (COND_EXPR, tree_type,
4213 ffecom_truth_value
4214 (ffecom_2 (GT_EXPR, integer_type_node,
4215 saved_expr1,
4216 saved_expr2)),
4217 ffecom_2 (MINUS_EXPR, tree_type,
4218 saved_expr1,
4219 saved_expr2),
4220 convert (tree_type, ffecom_float_zero_));
4221
4222 case FFEINTRIN_impDPROD:
4223 return
4224 ffecom_2 (MULT_EXPR, tree_type,
4225 convert (tree_type, ffecom_expr (arg1)),
4226 convert (tree_type, ffecom_expr (arg2)));
4227
4228 case FFEINTRIN_impEXP:
4229 case FFEINTRIN_impCDEXP:
4230 case FFEINTRIN_impCEXP:
4231 case FFEINTRIN_impDEXP:
4232 if (bt == FFEINFO_basictypeCOMPLEX)
4233 {
4234 if (kt == FFEINFO_kindtypeREAL1)
4235 gfrt = FFECOM_gfrtCEXP; /* Overlapping result okay. */
4236 else if (kt == FFEINFO_kindtypeREAL2)
4237 gfrt = FFECOM_gfrtCDEXP; /* Overlapping result okay. */
4238 }
4239 break;
4240
4241 case FFEINTRIN_impICHAR:
4242 case FFEINTRIN_impIACHAR:
4243#if 0 /* The simple approach. */
4244 ffecom_char_args_ (&expr_tree, &saved_expr1 /* Ignored */ , arg1);
4245 expr_tree
4246 = ffecom_1 (INDIRECT_REF,
4247 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4248 expr_tree);
4249 expr_tree
4250 = ffecom_2 (ARRAY_REF,
4251 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4252 expr_tree,
4253 integer_one_node);
4254 return convert (tree_type, expr_tree);
4255#else /* The more interesting (and more optimal) approach. */
4256 expr_tree = ffecom_intrinsic_ichar_ (tree_type, arg1, &saved_expr1);
4257 expr_tree = ffecom_3 (COND_EXPR, tree_type,
4258 saved_expr1,
4259 expr_tree,
4260 convert (tree_type, integer_zero_node));
4261 return expr_tree;
4262#endif
4263
4264 case FFEINTRIN_impINDEX:
4265 break;
4266
4267 case FFEINTRIN_impLEN:
4268#if 0
4269 break; /* The simple approach. */
4270#else
4271 return ffecom_intrinsic_len_ (arg1); /* The more optimal approach. */
4272#endif
4273
4274 case FFEINTRIN_impLGE:
4275 case FFEINTRIN_impLGT:
4276 case FFEINTRIN_impLLE:
4277 case FFEINTRIN_impLLT:
4278 break;
4279
4280 case FFEINTRIN_impLOG:
4281 case FFEINTRIN_impALOG:
4282 case FFEINTRIN_impCDLOG:
4283 case FFEINTRIN_impCLOG:
4284 case FFEINTRIN_impDLOG:
4285 if (bt == FFEINFO_basictypeCOMPLEX)
4286 {
4287 if (kt == FFEINFO_kindtypeREAL1)
4288 gfrt = FFECOM_gfrtCLOG; /* Overlapping result okay. */
4289 else if (kt == FFEINFO_kindtypeREAL2)
4290 gfrt = FFECOM_gfrtCDLOG; /* Overlapping result okay. */
4291 }
4292 break;
4293
4294 case FFEINTRIN_impLOG10:
4295 case FFEINTRIN_impALOG10:
4296 case FFEINTRIN_impDLOG10:
4297 if (gfrt != FFECOM_gfrt)
4298 break; /* Already picked one, stick with it. */
4299
4300 if (kt == FFEINFO_kindtypeREAL1)
4301 gfrt = FFECOM_gfrtALOG10;
4302 else if (kt == FFEINFO_kindtypeREAL2)
4303 gfrt = FFECOM_gfrtDLOG10;
4304 break;
4305
4306 case FFEINTRIN_impMAX:
4307 case FFEINTRIN_impAMAX0:
4308 case FFEINTRIN_impAMAX1:
4309 case FFEINTRIN_impDMAX1:
4310 case FFEINTRIN_impMAX0:
4311 case FFEINTRIN_impMAX1:
4312 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4313 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4314 else
4315 arg1_type = tree_type;
4316 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4317 convert (arg1_type, ffecom_expr (arg1)),
4318 convert (arg1_type, ffecom_expr (arg2)));
4319 for (; list != NULL; list = ffebld_trail (list))
4320 {
4321 if ((ffebld_head (list) == NULL)
4322 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4323 continue;
4324 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4325 expr_tree,
4326 convert (arg1_type,
4327 ffecom_expr (ffebld_head (list))));
4328 }
4329 return convert (tree_type, expr_tree);
4330
4331 case FFEINTRIN_impMIN:
4332 case FFEINTRIN_impAMIN0:
4333 case FFEINTRIN_impAMIN1:
4334 case FFEINTRIN_impDMIN1:
4335 case FFEINTRIN_impMIN0:
4336 case FFEINTRIN_impMIN1:
4337 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4338 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4339 else
4340 arg1_type = tree_type;
4341 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4342 convert (arg1_type, ffecom_expr (arg1)),
4343 convert (arg1_type, ffecom_expr (arg2)));
4344 for (; list != NULL; list = ffebld_trail (list))
4345 {
4346 if ((ffebld_head (list) == NULL)
4347 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4348 continue;
4349 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4350 expr_tree,
4351 convert (arg1_type,
4352 ffecom_expr (ffebld_head (list))));
4353 }
4354 return convert (tree_type, expr_tree);
4355
4356 case FFEINTRIN_impMOD:
4357 case FFEINTRIN_impAMOD:
4358 case FFEINTRIN_impDMOD:
4359 if (bt != FFEINFO_basictypeREAL)
4360 return ffecom_2 (TRUNC_MOD_EXPR, tree_type,
4361 convert (tree_type, ffecom_expr (arg1)),
4362 convert (tree_type, ffecom_expr (arg2)));
4363
4364 if (kt == FFEINFO_kindtypeREAL1)
4365 gfrt = FFECOM_gfrtAMOD;
4366 else if (kt == FFEINFO_kindtypeREAL2)
4367 gfrt = FFECOM_gfrtDMOD;
4368 break;
4369
4370 case FFEINTRIN_impNINT:
4371 case FFEINTRIN_impIDNINT:
c7e4ee3a
CB
4372#if 0
4373 /* ~~Ideally FIX_ROUND_EXPR would be implemented, but it ain't yet. */
5ff904cd
JL
4374 return ffecom_1 (FIX_ROUND_EXPR, tree_type, ffecom_expr (arg1));
4375#else
4376 /* i__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1); */
4377 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4378 return
4379 convert (ffecom_integer_type_node,
4380 ffecom_3 (COND_EXPR, arg1_type,
4381 ffecom_truth_value
4382 (ffecom_2 (GE_EXPR, integer_type_node,
4383 saved_expr1,
4384 convert (arg1_type,
4385 ffecom_float_zero_))),
4386 ffecom_2 (PLUS_EXPR, arg1_type,
4387 saved_expr1,
4388 convert (arg1_type,
4389 ffecom_float_half_)),
4390 ffecom_2 (MINUS_EXPR, arg1_type,
4391 saved_expr1,
4392 convert (arg1_type,
4393 ffecom_float_half_))));
4394#endif
4395
4396 case FFEINTRIN_impSIGN:
4397 case FFEINTRIN_impDSIGN:
4398 case FFEINTRIN_impISIGN:
4399 {
4400 tree arg2_tree = ffecom_expr (arg2);
4401
4402 saved_expr1
4403 = ffecom_save_tree
4404 (ffecom_1 (ABS_EXPR, tree_type,
4405 convert (tree_type,
4406 ffecom_expr (arg1))));
4407 expr_tree
4408 = ffecom_3 (COND_EXPR, tree_type,
4409 ffecom_truth_value
4410 (ffecom_2 (GE_EXPR, integer_type_node,
4411 arg2_tree,
4412 convert (TREE_TYPE (arg2_tree),
4413 integer_zero_node))),
4414 saved_expr1,
4415 ffecom_1 (NEGATE_EXPR, tree_type, saved_expr1));
4416 /* Make sure SAVE_EXPRs get referenced early enough. */
4417 expr_tree
4418 = ffecom_2 (COMPOUND_EXPR, tree_type,
4419 convert (void_type_node, saved_expr1),
4420 expr_tree);
4421 }
4422 return expr_tree;
4423
4424 case FFEINTRIN_impSIN:
4425 case FFEINTRIN_impCDSIN:
4426 case FFEINTRIN_impCSIN:
4427 case FFEINTRIN_impDSIN:
4428 if (bt == FFEINFO_basictypeCOMPLEX)
4429 {
4430 if (kt == FFEINFO_kindtypeREAL1)
4431 gfrt = FFECOM_gfrtCSIN; /* Overlapping result okay. */
4432 else if (kt == FFEINFO_kindtypeREAL2)
4433 gfrt = FFECOM_gfrtCDSIN; /* Overlapping result okay. */
4434 }
4435 break;
4436
4437 case FFEINTRIN_impSINH:
4438 case FFEINTRIN_impDSINH:
4439 break;
4440
4441 case FFEINTRIN_impSQRT:
4442 case FFEINTRIN_impCDSQRT:
4443 case FFEINTRIN_impCSQRT:
4444 case FFEINTRIN_impDSQRT:
4445 if (bt == FFEINFO_basictypeCOMPLEX)
4446 {
4447 if (kt == FFEINFO_kindtypeREAL1)
4448 gfrt = FFECOM_gfrtCSQRT; /* Overlapping result okay. */
4449 else if (kt == FFEINFO_kindtypeREAL2)
4450 gfrt = FFECOM_gfrtCDSQRT; /* Overlapping result okay. */
4451 }
4452 break;
4453
4454 case FFEINTRIN_impTAN:
4455 case FFEINTRIN_impDTAN:
4456 case FFEINTRIN_impTANH:
4457 case FFEINTRIN_impDTANH:
4458 break;
4459
4460 case FFEINTRIN_impREALPART:
4461 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4462 arg1_type = TREE_TYPE (arg1_type);
4463 else
4464 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4465
4466 return
4467 convert (tree_type,
4468 ffecom_1 (REALPART_EXPR, arg1_type,
4469 ffecom_expr (arg1)));
4470
4471 case FFEINTRIN_impIAND:
4472 case FFEINTRIN_impAND:
4473 return ffecom_2 (BIT_AND_EXPR, tree_type,
4474 convert (tree_type,
4475 ffecom_expr (arg1)),
4476 convert (tree_type,
4477 ffecom_expr (arg2)));
4478
4479 case FFEINTRIN_impIOR:
4480 case FFEINTRIN_impOR:
4481 return ffecom_2 (BIT_IOR_EXPR, tree_type,
4482 convert (tree_type,
4483 ffecom_expr (arg1)),
4484 convert (tree_type,
4485 ffecom_expr (arg2)));
4486
4487 case FFEINTRIN_impIEOR:
4488 case FFEINTRIN_impXOR:
4489 return ffecom_2 (BIT_XOR_EXPR, tree_type,
4490 convert (tree_type,
4491 ffecom_expr (arg1)),
4492 convert (tree_type,
4493 ffecom_expr (arg2)));
4494
4495 case FFEINTRIN_impLSHIFT:
4496 return ffecom_2 (LSHIFT_EXPR, tree_type,
4497 ffecom_expr (arg1),
4498 convert (integer_type_node,
4499 ffecom_expr (arg2)));
4500
4501 case FFEINTRIN_impRSHIFT:
4502 return ffecom_2 (RSHIFT_EXPR, tree_type,
4503 ffecom_expr (arg1),
4504 convert (integer_type_node,
4505 ffecom_expr (arg2)));
4506
4507 case FFEINTRIN_impNOT:
4508 return ffecom_1 (BIT_NOT_EXPR, tree_type, ffecom_expr (arg1));
4509
4510 case FFEINTRIN_impBIT_SIZE:
4511 return convert (tree_type, TYPE_SIZE (arg1_type));
4512
4513 case FFEINTRIN_impBTEST:
4514 {
4515 ffetargetLogical1 true;
4516 ffetargetLogical1 false;
4517 tree true_tree;
4518 tree false_tree;
4519
4520 ffetarget_logical1 (&true, TRUE);
4521 ffetarget_logical1 (&false, FALSE);
4522 if (true == 1)
4523 true_tree = convert (tree_type, integer_one_node);
4524 else
4525 true_tree = convert (tree_type, build_int_2 (true, 0));
4526 if (false == 0)
4527 false_tree = convert (tree_type, integer_zero_node);
4528 else
4529 false_tree = convert (tree_type, build_int_2 (false, 0));
4530
4531 return
4532 ffecom_3 (COND_EXPR, tree_type,
4533 ffecom_truth_value
4534 (ffecom_2 (EQ_EXPR, integer_type_node,
4535 ffecom_2 (BIT_AND_EXPR, arg1_type,
4536 ffecom_expr (arg1),
4537 ffecom_2 (LSHIFT_EXPR, arg1_type,
4538 convert (arg1_type,
4539 integer_one_node),
4540 convert (integer_type_node,
4541 ffecom_expr (arg2)))),
4542 convert (arg1_type,
4543 integer_zero_node))),
4544 false_tree,
4545 true_tree);
4546 }
4547
4548 case FFEINTRIN_impIBCLR:
4549 return
4550 ffecom_2 (BIT_AND_EXPR, tree_type,
4551 ffecom_expr (arg1),
4552 ffecom_1 (BIT_NOT_EXPR, tree_type,
4553 ffecom_2 (LSHIFT_EXPR, tree_type,
4554 convert (tree_type,
4555 integer_one_node),
4556 convert (integer_type_node,
4557 ffecom_expr (arg2)))));
4558
4559 case FFEINTRIN_impIBITS:
4560 {
4561 tree arg3_tree = ffecom_save_tree (convert (integer_type_node,
4562 ffecom_expr (arg3)));
4563 tree uns_type
4564 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4565
4566 expr_tree
4567 = ffecom_2 (BIT_AND_EXPR, tree_type,
4568 ffecom_2 (RSHIFT_EXPR, tree_type,
4569 ffecom_expr (arg1),
4570 convert (integer_type_node,
4571 ffecom_expr (arg2))),
4572 convert (tree_type,
4573 ffecom_2 (RSHIFT_EXPR, uns_type,
4574 ffecom_1 (BIT_NOT_EXPR,
4575 uns_type,
4576 convert (uns_type,
4577 integer_zero_node)),
4578 ffecom_2 (MINUS_EXPR,
4579 integer_type_node,
4580 TYPE_SIZE (uns_type),
4581 arg3_tree))));
4582#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4583 expr_tree
4584 = ffecom_3 (COND_EXPR, tree_type,
4585 ffecom_truth_value
4586 (ffecom_2 (NE_EXPR, integer_type_node,
4587 arg3_tree,
4588 integer_zero_node)),
4589 expr_tree,
4590 convert (tree_type, integer_zero_node));
4591#endif
4592 }
4593 return expr_tree;
4594
4595 case FFEINTRIN_impIBSET:
4596 return
4597 ffecom_2 (BIT_IOR_EXPR, tree_type,
4598 ffecom_expr (arg1),
4599 ffecom_2 (LSHIFT_EXPR, tree_type,
4600 convert (tree_type, integer_one_node),
4601 convert (integer_type_node,
4602 ffecom_expr (arg2))));
4603
4604 case FFEINTRIN_impISHFT:
4605 {
4606 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4607 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4608 ffecom_expr (arg2)));
4609 tree uns_type
4610 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4611
4612 expr_tree
4613 = ffecom_3 (COND_EXPR, tree_type,
4614 ffecom_truth_value
4615 (ffecom_2 (GE_EXPR, integer_type_node,
4616 arg2_tree,
4617 integer_zero_node)),
4618 ffecom_2 (LSHIFT_EXPR, tree_type,
4619 arg1_tree,
4620 arg2_tree),
4621 convert (tree_type,
4622 ffecom_2 (RSHIFT_EXPR, uns_type,
4623 convert (uns_type, arg1_tree),
4624 ffecom_1 (NEGATE_EXPR,
4625 integer_type_node,
4626 arg2_tree))));
4627#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4628 expr_tree
4629 = ffecom_3 (COND_EXPR, tree_type,
4630 ffecom_truth_value
4631 (ffecom_2 (NE_EXPR, integer_type_node,
4632 arg2_tree,
4633 TYPE_SIZE (uns_type))),
4634 expr_tree,
4635 convert (tree_type, integer_zero_node));
4636#endif
4637 /* Make sure SAVE_EXPRs get referenced early enough. */
4638 expr_tree
4639 = ffecom_2 (COMPOUND_EXPR, tree_type,
4640 convert (void_type_node, arg1_tree),
4641 ffecom_2 (COMPOUND_EXPR, tree_type,
4642 convert (void_type_node, arg2_tree),
4643 expr_tree));
4644 }
4645 return expr_tree;
4646
4647 case FFEINTRIN_impISHFTC:
4648 {
4649 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4650 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4651 ffecom_expr (arg2)));
4652 tree arg3_tree = (arg3 == NULL) ? TYPE_SIZE (tree_type)
4653 : ffecom_save_tree (convert (integer_type_node, ffecom_expr (arg3)));
4654 tree shift_neg;
4655 tree shift_pos;
4656 tree mask_arg1;
4657 tree masked_arg1;
4658 tree uns_type
4659 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4660
4661 mask_arg1
4662 = ffecom_2 (LSHIFT_EXPR, tree_type,
4663 ffecom_1 (BIT_NOT_EXPR, tree_type,
4664 convert (tree_type, integer_zero_node)),
4665 arg3_tree);
4666#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4667 mask_arg1
4668 = ffecom_3 (COND_EXPR, tree_type,
4669 ffecom_truth_value
4670 (ffecom_2 (NE_EXPR, integer_type_node,
4671 arg3_tree,
4672 TYPE_SIZE (uns_type))),
4673 mask_arg1,
4674 convert (tree_type, integer_zero_node));
4675#endif
4676 mask_arg1 = ffecom_save_tree (mask_arg1);
4677 masked_arg1
4678 = ffecom_2 (BIT_AND_EXPR, tree_type,
4679 arg1_tree,
4680 ffecom_1 (BIT_NOT_EXPR, tree_type,
4681 mask_arg1));
4682 masked_arg1 = ffecom_save_tree (masked_arg1);
4683 shift_neg
4684 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4685 convert (tree_type,
4686 ffecom_2 (RSHIFT_EXPR, uns_type,
4687 convert (uns_type, masked_arg1),
4688 ffecom_1 (NEGATE_EXPR,
4689 integer_type_node,
4690 arg2_tree))),
4691 ffecom_2 (LSHIFT_EXPR, tree_type,
4692 arg1_tree,
4693 ffecom_2 (PLUS_EXPR, integer_type_node,
4694 arg2_tree,
4695 arg3_tree)));
4696 shift_pos
4697 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4698 ffecom_2 (LSHIFT_EXPR, tree_type,
4699 arg1_tree,
4700 arg2_tree),
4701 convert (tree_type,
4702 ffecom_2 (RSHIFT_EXPR, uns_type,
4703 convert (uns_type, masked_arg1),
4704 ffecom_2 (MINUS_EXPR,
4705 integer_type_node,
4706 arg3_tree,
4707 arg2_tree))));
4708 expr_tree
4709 = ffecom_3 (COND_EXPR, tree_type,
4710 ffecom_truth_value
4711 (ffecom_2 (LT_EXPR, integer_type_node,
4712 arg2_tree,
4713 integer_zero_node)),
4714 shift_neg,
4715 shift_pos);
4716 expr_tree
4717 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4718 ffecom_2 (BIT_AND_EXPR, tree_type,
4719 mask_arg1,
4720 arg1_tree),
4721 ffecom_2 (BIT_AND_EXPR, tree_type,
4722 ffecom_1 (BIT_NOT_EXPR, tree_type,
4723 mask_arg1),
4724 expr_tree));
4725 expr_tree
4726 = ffecom_3 (COND_EXPR, tree_type,
4727 ffecom_truth_value
4728 (ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
4729 ffecom_2 (EQ_EXPR, integer_type_node,
4730 ffecom_1 (ABS_EXPR,
4731 integer_type_node,
4732 arg2_tree),
4733 arg3_tree),
4734 ffecom_2 (EQ_EXPR, integer_type_node,
4735 arg2_tree,
4736 integer_zero_node))),
4737 arg1_tree,
4738 expr_tree);
4739 /* Make sure SAVE_EXPRs get referenced early enough. */
4740 expr_tree
4741 = ffecom_2 (COMPOUND_EXPR, tree_type,
4742 convert (void_type_node, arg1_tree),
4743 ffecom_2 (COMPOUND_EXPR, tree_type,
4744 convert (void_type_node, arg2_tree),
4745 ffecom_2 (COMPOUND_EXPR, tree_type,
4746 convert (void_type_node,
4747 mask_arg1),
4748 ffecom_2 (COMPOUND_EXPR, tree_type,
4749 convert (void_type_node,
4750 masked_arg1),
4751 expr_tree))));
4752 expr_tree
4753 = ffecom_2 (COMPOUND_EXPR, tree_type,
4754 convert (void_type_node,
4755 arg3_tree),
4756 expr_tree);
4757 }
4758 return expr_tree;
4759
4760 case FFEINTRIN_impLOC:
4761 {
4762 tree arg1_tree = ffecom_expr (arg1);
4763
4764 expr_tree
4765 = convert (tree_type,
4766 ffecom_1 (ADDR_EXPR,
4767 build_pointer_type (TREE_TYPE (arg1_tree)),
4768 arg1_tree));
4769 }
4770 return expr_tree;
4771
4772 case FFEINTRIN_impMVBITS:
4773 {
4774 tree arg1_tree;
4775 tree arg2_tree;
4776 tree arg3_tree;
4777 ffebld arg4 = ffebld_head (ffebld_trail (list));
4778 tree arg4_tree;
4779 tree arg4_type;
4780 ffebld arg5 = ffebld_head (ffebld_trail (ffebld_trail (list)));
4781 tree arg5_tree;
4782 tree prep_arg1;
4783 tree prep_arg4;
4784 tree arg5_plus_arg3;
4785
5ff904cd
JL
4786 arg2_tree = convert (integer_type_node,
4787 ffecom_expr (arg2));
4788 arg3_tree = ffecom_save_tree (convert (integer_type_node,
4789 ffecom_expr (arg3)));
c7e4ee3a 4790 arg4_tree = ffecom_expr_rw (NULL_TREE, arg4);
5ff904cd
JL
4791 arg4_type = TREE_TYPE (arg4_tree);
4792
4793 arg1_tree = ffecom_save_tree (convert (arg4_type,
4794 ffecom_expr (arg1)));
4795
4796 arg5_tree = ffecom_save_tree (convert (integer_type_node,
4797 ffecom_expr (arg5)));
4798
5ff904cd
JL
4799 prep_arg1
4800 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4801 ffecom_2 (BIT_AND_EXPR, arg4_type,
4802 ffecom_2 (RSHIFT_EXPR, arg4_type,
4803 arg1_tree,
4804 arg2_tree),
4805 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4806 ffecom_2 (LSHIFT_EXPR, arg4_type,
4807 ffecom_1 (BIT_NOT_EXPR,
4808 arg4_type,
4809 convert
4810 (arg4_type,
4811 integer_zero_node)),
4812 arg3_tree))),
4813 arg5_tree);
4814 arg5_plus_arg3
4815 = ffecom_save_tree (ffecom_2 (PLUS_EXPR, arg4_type,
4816 arg5_tree,
4817 arg3_tree));
4818 prep_arg4
4819 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4820 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4821 convert (arg4_type,
4822 integer_zero_node)),
4823 arg5_plus_arg3);
4824#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4825 prep_arg4
4826 = ffecom_3 (COND_EXPR, arg4_type,
4827 ffecom_truth_value
4828 (ffecom_2 (NE_EXPR, integer_type_node,
4829 arg5_plus_arg3,
4830 convert (TREE_TYPE (arg5_plus_arg3),
4831 TYPE_SIZE (arg4_type)))),
4832 prep_arg4,
4833 convert (arg4_type, integer_zero_node));
4834#endif
4835 prep_arg4
4836 = ffecom_2 (BIT_AND_EXPR, arg4_type,
4837 arg4_tree,
4838 ffecom_2 (BIT_IOR_EXPR, arg4_type,
4839 prep_arg4,
4840 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4841 ffecom_2 (LSHIFT_EXPR, arg4_type,
4842 ffecom_1 (BIT_NOT_EXPR,
4843 arg4_type,
4844 convert
4845 (arg4_type,
4846 integer_zero_node)),
4847 arg5_tree))));
4848 prep_arg1
4849 = ffecom_2 (BIT_IOR_EXPR, arg4_type,
4850 prep_arg1,
4851 prep_arg4);
4852#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4853 prep_arg1
4854 = ffecom_3 (COND_EXPR, arg4_type,
4855 ffecom_truth_value
4856 (ffecom_2 (NE_EXPR, integer_type_node,
4857 arg3_tree,
4858 convert (TREE_TYPE (arg3_tree),
4859 integer_zero_node))),
4860 prep_arg1,
4861 arg4_tree);
4862 prep_arg1
4863 = ffecom_3 (COND_EXPR, arg4_type,
4864 ffecom_truth_value
4865 (ffecom_2 (NE_EXPR, integer_type_node,
4866 arg3_tree,
4867 convert (TREE_TYPE (arg3_tree),
4868 TYPE_SIZE (arg4_type)))),
4869 prep_arg1,
4870 arg1_tree);
4871#endif
4872 expr_tree
4873 = ffecom_2s (MODIFY_EXPR, void_type_node,
4874 arg4_tree,
4875 prep_arg1);
4876 /* Make sure SAVE_EXPRs get referenced early enough. */
4877 expr_tree
4878 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4879 arg1_tree,
4880 ffecom_2 (COMPOUND_EXPR, void_type_node,
4881 arg3_tree,
4882 ffecom_2 (COMPOUND_EXPR, void_type_node,
4883 arg5_tree,
4884 ffecom_2 (COMPOUND_EXPR, void_type_node,
4885 arg5_plus_arg3,
4886 expr_tree))));
4887 expr_tree
4888 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4889 arg4_tree,
4890 expr_tree);
4891
4892 }
4893 return expr_tree;
4894
4895 case FFEINTRIN_impDERF:
4896 case FFEINTRIN_impERF:
4897 case FFEINTRIN_impDERFC:
4898 case FFEINTRIN_impERFC:
4899 break;
4900
4901 case FFEINTRIN_impIARGC:
4902 /* extern int xargc; i__1 = xargc - 1; */
4903 expr_tree = ffecom_2 (MINUS_EXPR, TREE_TYPE (ffecom_tree_xargc_),
4904 ffecom_tree_xargc_,
4905 convert (TREE_TYPE (ffecom_tree_xargc_),
4906 integer_one_node));
4907 return expr_tree;
4908
4909 case FFEINTRIN_impSIGNAL_func:
4910 case FFEINTRIN_impSIGNAL_subr:
4911 {
4912 tree arg1_tree;
4913 tree arg2_tree;
4914 tree arg3_tree;
4915
5ff904cd
JL
4916 arg1_tree = convert (ffecom_f2c_integer_type_node,
4917 ffecom_expr (arg1));
4918 arg1_tree = ffecom_1 (ADDR_EXPR,
4919 build_pointer_type (TREE_TYPE (arg1_tree)),
4920 arg1_tree);
4921
4922 /* Pass procedure as a pointer to it, anything else by value. */
4923 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4924 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4925 else
4926 arg2_tree = ffecom_ptr_to_expr (arg2);
4927 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4928 arg2_tree);
4929
4930 if (arg3 != NULL)
c7e4ee3a 4931 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
4932 else
4933 arg3_tree = NULL_TREE;
4934
5ff904cd
JL
4935 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4936 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4937 TREE_CHAIN (arg1_tree) = arg2_tree;
4938
4939 expr_tree
4940 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4941 ffecom_gfrt_kindtype (gfrt),
4942 FALSE,
4943 ((codegen_imp == FFEINTRIN_impSIGNAL_subr) ?
4944 NULL_TREE :
4945 tree_type),
4946 arg1_tree,
c7e4ee3a
CB
4947 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4948 ffebld_nonter_hook (expr));
5ff904cd
JL
4949
4950 if (arg3_tree != NULL_TREE)
4951 expr_tree
4952 = ffecom_modify (NULL_TREE, arg3_tree,
4953 convert (TREE_TYPE (arg3_tree),
4954 expr_tree));
4955 }
4956 return expr_tree;
4957
4958 case FFEINTRIN_impALARM:
4959 {
4960 tree arg1_tree;
4961 tree arg2_tree;
4962 tree arg3_tree;
4963
5ff904cd
JL
4964 arg1_tree = convert (ffecom_f2c_integer_type_node,
4965 ffecom_expr (arg1));
4966 arg1_tree = ffecom_1 (ADDR_EXPR,
4967 build_pointer_type (TREE_TYPE (arg1_tree)),
4968 arg1_tree);
4969
4970 /* Pass procedure as a pointer to it, anything else by value. */
4971 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4972 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4973 else
4974 arg2_tree = ffecom_ptr_to_expr (arg2);
4975 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4976 arg2_tree);
4977
4978 if (arg3 != NULL)
c7e4ee3a 4979 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
4980 else
4981 arg3_tree = NULL_TREE;
4982
5ff904cd
JL
4983 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4984 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4985 TREE_CHAIN (arg1_tree) = arg2_tree;
4986
4987 expr_tree
4988 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4989 ffecom_gfrt_kindtype (gfrt),
4990 FALSE,
4991 NULL_TREE,
4992 arg1_tree,
c7e4ee3a
CB
4993 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4994 ffebld_nonter_hook (expr));
5ff904cd
JL
4995
4996 if (arg3_tree != NULL_TREE)
4997 expr_tree
4998 = ffecom_modify (NULL_TREE, arg3_tree,
4999 convert (TREE_TYPE (arg3_tree),
5000 expr_tree));
5001 }
5002 return expr_tree;
5003
5004 case FFEINTRIN_impCHDIR_subr:
5005 case FFEINTRIN_impFDATE_subr:
5006 case FFEINTRIN_impFGET_subr:
5007 case FFEINTRIN_impFPUT_subr:
5008 case FFEINTRIN_impGETCWD_subr:
5009 case FFEINTRIN_impHOSTNM_subr:
5010 case FFEINTRIN_impSYSTEM_subr:
5011 case FFEINTRIN_impUNLINK_subr:
5012 {
5013 tree arg1_len = integer_zero_node;
5014 tree arg1_tree;
5015 tree arg2_tree;
5016
5ff904cd
JL
5017 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5018
5019 if (arg2 != NULL)
c7e4ee3a 5020 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
5ff904cd
JL
5021 else
5022 arg2_tree = NULL_TREE;
5023
5ff904cd
JL
5024 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5025 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5026 TREE_CHAIN (arg1_tree) = arg1_len;
5027
5028 expr_tree
5029 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5030 ffecom_gfrt_kindtype (gfrt),
5031 FALSE,
5032 NULL_TREE,
5033 arg1_tree,
c7e4ee3a
CB
5034 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5035 ffebld_nonter_hook (expr));
5ff904cd
JL
5036
5037 if (arg2_tree != NULL_TREE)
5038 expr_tree
5039 = ffecom_modify (NULL_TREE, arg2_tree,
5040 convert (TREE_TYPE (arg2_tree),
5041 expr_tree));
5042 }
5043 return expr_tree;
5044
5045 case FFEINTRIN_impEXIT:
5046 if (arg1 != NULL)
5047 break;
5048
5049 expr_tree = build_tree_list (NULL_TREE,
5050 ffecom_1 (ADDR_EXPR,
5051 build_pointer_type
5052 (ffecom_integer_type_node),
5053 integer_zero_node));
5054
5055 return
5056 ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5057 ffecom_gfrt_kindtype (gfrt),
5058 FALSE,
5059 void_type_node,
5060 expr_tree,
c7e4ee3a
CB
5061 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5062 ffebld_nonter_hook (expr));
5ff904cd
JL
5063
5064 case FFEINTRIN_impFLUSH:
5065 if (arg1 == NULL)
5066 gfrt = FFECOM_gfrtFLUSH;
5067 else
5068 gfrt = FFECOM_gfrtFLUSH1;
5069 break;
5070
5071 case FFEINTRIN_impCHMOD_subr:
5072 case FFEINTRIN_impLINK_subr:
5073 case FFEINTRIN_impRENAME_subr:
5074 case FFEINTRIN_impSYMLNK_subr:
5075 {
5076 tree arg1_len = integer_zero_node;
5077 tree arg1_tree;
5078 tree arg2_len = integer_zero_node;
5079 tree arg2_tree;
5080 tree arg3_tree;
5081
5ff904cd
JL
5082 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5083 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
5084 if (arg3 != NULL)
c7e4ee3a 5085 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5086 else
5087 arg3_tree = NULL_TREE;
5088
5ff904cd
JL
5089 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5090 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5091 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5092 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5093 TREE_CHAIN (arg1_tree) = arg2_tree;
5094 TREE_CHAIN (arg2_tree) = arg1_len;
5095 TREE_CHAIN (arg1_len) = arg2_len;
5096 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5097 ffecom_gfrt_kindtype (gfrt),
5098 FALSE,
5099 NULL_TREE,
5100 arg1_tree,
c7e4ee3a
CB
5101 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5102 ffebld_nonter_hook (expr));
5ff904cd
JL
5103 if (arg3_tree != NULL_TREE)
5104 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5105 convert (TREE_TYPE (arg3_tree),
5106 expr_tree));
5107 }
5108 return expr_tree;
5109
5110 case FFEINTRIN_impLSTAT_subr:
5111 case FFEINTRIN_impSTAT_subr:
5112 {
5113 tree arg1_len = integer_zero_node;
5114 tree arg1_tree;
5115 tree arg2_tree;
5116 tree arg3_tree;
5117
5ff904cd
JL
5118 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5119
5120 arg2_tree = ffecom_ptr_to_expr (arg2);
5121
5122 if (arg3 != NULL)
c7e4ee3a 5123 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5124 else
5125 arg3_tree = NULL_TREE;
5126
5ff904cd
JL
5127 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5128 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5129 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5130 TREE_CHAIN (arg1_tree) = arg2_tree;
5131 TREE_CHAIN (arg2_tree) = arg1_len;
5132 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5133 ffecom_gfrt_kindtype (gfrt),
5134 FALSE,
5135 NULL_TREE,
5136 arg1_tree,
c7e4ee3a
CB
5137 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5138 ffebld_nonter_hook (expr));
5ff904cd
JL
5139 if (arg3_tree != NULL_TREE)
5140 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5141 convert (TREE_TYPE (arg3_tree),
5142 expr_tree));
5143 }
5144 return expr_tree;
5145
5146 case FFEINTRIN_impFGETC_subr:
5147 case FFEINTRIN_impFPUTC_subr:
5148 {
5149 tree arg1_tree;
5150 tree arg2_tree;
5151 tree arg2_len = integer_zero_node;
5152 tree arg3_tree;
5153
5ff904cd
JL
5154 arg1_tree = convert (ffecom_f2c_integer_type_node,
5155 ffecom_expr (arg1));
5156 arg1_tree = ffecom_1 (ADDR_EXPR,
5157 build_pointer_type (TREE_TYPE (arg1_tree)),
5158 arg1_tree);
5159
5160 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
c7e4ee3a 5161 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5162
5163 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5164 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5165 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5166 TREE_CHAIN (arg1_tree) = arg2_tree;
5167 TREE_CHAIN (arg2_tree) = arg2_len;
5168
5169 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5170 ffecom_gfrt_kindtype (gfrt),
5171 FALSE,
5172 NULL_TREE,
5173 arg1_tree,
c7e4ee3a
CB
5174 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5175 ffebld_nonter_hook (expr));
5ff904cd
JL
5176 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5177 convert (TREE_TYPE (arg3_tree),
5178 expr_tree));
5179 }
5180 return expr_tree;
5181
5182 case FFEINTRIN_impFSTAT_subr:
5183 {
5184 tree arg1_tree;
5185 tree arg2_tree;
5186 tree arg3_tree;
5187
5ff904cd
JL
5188 arg1_tree = convert (ffecom_f2c_integer_type_node,
5189 ffecom_expr (arg1));
5190 arg1_tree = ffecom_1 (ADDR_EXPR,
5191 build_pointer_type (TREE_TYPE (arg1_tree)),
5192 arg1_tree);
5193
5194 arg2_tree = convert (ffecom_f2c_ptr_to_integer_type_node,
5195 ffecom_ptr_to_expr (arg2));
5196
5197 if (arg3 == NULL)
5198 arg3_tree = NULL_TREE;
5199 else
c7e4ee3a 5200 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5201
5202 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5203 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5204 TREE_CHAIN (arg1_tree) = arg2_tree;
5205 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5206 ffecom_gfrt_kindtype (gfrt),
5207 FALSE,
5208 NULL_TREE,
5209 arg1_tree,
c7e4ee3a
CB
5210 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5211 ffebld_nonter_hook (expr));
5ff904cd
JL
5212 if (arg3_tree != NULL_TREE) {
5213 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5214 convert (TREE_TYPE (arg3_tree),
5215 expr_tree));
5216 }
5217 }
5218 return expr_tree;
5219
5220 case FFEINTRIN_impKILL_subr:
5221 {
5222 tree arg1_tree;
5223 tree arg2_tree;
5224 tree arg3_tree;
5225
5ff904cd
JL
5226 arg1_tree = convert (ffecom_f2c_integer_type_node,
5227 ffecom_expr (arg1));
5228 arg1_tree = ffecom_1 (ADDR_EXPR,
5229 build_pointer_type (TREE_TYPE (arg1_tree)),
5230 arg1_tree);
5231
5232 arg2_tree = convert (ffecom_f2c_integer_type_node,
5233 ffecom_expr (arg2));
5234 arg2_tree = ffecom_1 (ADDR_EXPR,
5235 build_pointer_type (TREE_TYPE (arg2_tree)),
5236 arg2_tree);
5237
5238 if (arg3 == NULL)
5239 arg3_tree = NULL_TREE;
5240 else
c7e4ee3a 5241 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5242
5243 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5244 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5245 TREE_CHAIN (arg1_tree) = arg2_tree;
5246 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5247 ffecom_gfrt_kindtype (gfrt),
5248 FALSE,
5249 NULL_TREE,
5250 arg1_tree,
c7e4ee3a
CB
5251 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5252 ffebld_nonter_hook (expr));
5ff904cd
JL
5253 if (arg3_tree != NULL_TREE) {
5254 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5255 convert (TREE_TYPE (arg3_tree),
5256 expr_tree));
5257 }
5258 }
5259 return expr_tree;
5260
5261 case FFEINTRIN_impCTIME_subr:
5262 case FFEINTRIN_impTTYNAM_subr:
5263 {
5264 tree arg1_len = integer_zero_node;
5265 tree arg1_tree;
5266 tree arg2_tree;
5267
2b0bdd9a 5268 arg1_tree = ffecom_arg_ptr_to_expr (arg2, &arg1_len);
5ff904cd 5269
c56f65d6 5270 arg2_tree = convert (((codegen_imp == FFEINTRIN_impCTIME_subr) ?
5ff904cd
JL
5271 ffecom_f2c_longint_type_node :
5272 ffecom_f2c_integer_type_node),
2b0bdd9a 5273 ffecom_expr (arg1));
5ff904cd
JL
5274 arg2_tree = ffecom_1 (ADDR_EXPR,
5275 build_pointer_type (TREE_TYPE (arg2_tree)),
5276 arg2_tree);
5277
5ff904cd
JL
5278 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5279 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5280 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5281 TREE_CHAIN (arg1_len) = arg2_tree;
5282 TREE_CHAIN (arg1_tree) = arg1_len;
5283
5284 expr_tree
5285 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5286 ffecom_gfrt_kindtype (gfrt),
5287 FALSE,
5288 NULL_TREE,
5289 arg1_tree,
c7e4ee3a
CB
5290 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5291 ffebld_nonter_hook (expr));
2b0bdd9a 5292 TREE_SIDE_EFFECTS (expr_tree) = 1;
5ff904cd
JL
5293 }
5294 return expr_tree;
5295
5296 case FFEINTRIN_impIRAND:
5297 case FFEINTRIN_impRAND:
5298 /* Arg defaults to 0 (normal random case) */
5299 {
5300 tree arg1_tree;
5301
5302 if (arg1 == NULL)
5303 arg1_tree = ffecom_integer_zero_node;
5304 else
5305 arg1_tree = ffecom_expr (arg1);
5306 arg1_tree = convert (ffecom_f2c_integer_type_node,
5307 arg1_tree);
5308 arg1_tree = ffecom_1 (ADDR_EXPR,
5309 build_pointer_type (TREE_TYPE (arg1_tree)),
5310 arg1_tree);
5311 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5312
5313 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5314 ffecom_gfrt_kindtype (gfrt),
5315 FALSE,
5316 ((codegen_imp == FFEINTRIN_impIRAND) ?
5317 ffecom_f2c_integer_type_node :
de7f278a 5318 ffecom_f2c_real_type_node),
5ff904cd
JL
5319 arg1_tree,
5320 dest_tree, dest, dest_used,
c7e4ee3a
CB
5321 NULL_TREE, TRUE,
5322 ffebld_nonter_hook (expr));
5ff904cd
JL
5323 }
5324 return expr_tree;
5325
5326 case FFEINTRIN_impFTELL_subr:
5327 case FFEINTRIN_impUMASK_subr:
5328 {
5329 tree arg1_tree;
5330 tree arg2_tree;
5331
5ff904cd
JL
5332 arg1_tree = convert (ffecom_f2c_integer_type_node,
5333 ffecom_expr (arg1));
5334 arg1_tree = ffecom_1 (ADDR_EXPR,
5335 build_pointer_type (TREE_TYPE (arg1_tree)),
5336 arg1_tree);
5337
5338 if (arg2 == NULL)
5339 arg2_tree = NULL_TREE;
5340 else
c7e4ee3a 5341 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
5ff904cd
JL
5342
5343 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5344 ffecom_gfrt_kindtype (gfrt),
5345 FALSE,
5346 NULL_TREE,
5347 build_tree_list (NULL_TREE, arg1_tree),
5348 NULL_TREE, NULL, NULL, NULL_TREE,
c7e4ee3a
CB
5349 TRUE,
5350 ffebld_nonter_hook (expr));
5ff904cd
JL
5351 if (arg2_tree != NULL_TREE) {
5352 expr_tree = ffecom_modify (NULL_TREE, arg2_tree,
5353 convert (TREE_TYPE (arg2_tree),
5354 expr_tree));
5355 }
5356 }
5357 return expr_tree;
5358
5359 case FFEINTRIN_impCPU_TIME:
5360 case FFEINTRIN_impSECOND_subr:
5361 {
5362 tree arg1_tree;
5363
c7e4ee3a 5364 arg1_tree = ffecom_expr_w (NULL_TREE, arg1);
5ff904cd
JL
5365
5366 expr_tree
5367 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5368 ffecom_gfrt_kindtype (gfrt),
5369 FALSE,
5370 NULL_TREE,
5371 NULL_TREE,
c7e4ee3a
CB
5372 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5373 ffebld_nonter_hook (expr));
5ff904cd
JL
5374
5375 expr_tree
5376 = ffecom_modify (NULL_TREE, arg1_tree,
5377 convert (TREE_TYPE (arg1_tree),
5378 expr_tree));
5379 }
5380 return expr_tree;
5381
5382 case FFEINTRIN_impDTIME_subr:
5383 case FFEINTRIN_impETIME_subr:
5384 {
5385 tree arg1_tree;
2b0bdd9a 5386 tree result_tree;
5ff904cd 5387
2b0bdd9a 5388 result_tree = ffecom_expr_w (NULL_TREE, arg2);
5ff904cd 5389
2b0bdd9a 5390 arg1_tree = ffecom_ptr_to_expr (arg1);
5ff904cd 5391
5ff904cd
JL
5392 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5393 ffecom_gfrt_kindtype (gfrt),
5394 FALSE,
5395 NULL_TREE,
2b0bdd9a 5396 build_tree_list (NULL_TREE, arg1_tree),
5ff904cd 5397 NULL_TREE, NULL, NULL, NULL_TREE,
c7e4ee3a
CB
5398 TRUE,
5399 ffebld_nonter_hook (expr));
2b0bdd9a
CB
5400 expr_tree = ffecom_modify (NULL_TREE, result_tree,
5401 convert (TREE_TYPE (result_tree),
5ff904cd
JL
5402 expr_tree));
5403 }
5404 return expr_tree;
5405
c7e4ee3a 5406 /* Straightforward calls of libf2c routines: */
5ff904cd
JL
5407 case FFEINTRIN_impABORT:
5408 case FFEINTRIN_impACCESS:
5409 case FFEINTRIN_impBESJ0:
5410 case FFEINTRIN_impBESJ1:
5411 case FFEINTRIN_impBESJN:
5412 case FFEINTRIN_impBESY0:
5413 case FFEINTRIN_impBESY1:
5414 case FFEINTRIN_impBESYN:
5415 case FFEINTRIN_impCHDIR_func:
5416 case FFEINTRIN_impCHMOD_func:
5417 case FFEINTRIN_impDATE:
9e8e701d 5418 case FFEINTRIN_impDATE_AND_TIME:
5ff904cd
JL
5419 case FFEINTRIN_impDBESJ0:
5420 case FFEINTRIN_impDBESJ1:
5421 case FFEINTRIN_impDBESJN:
5422 case FFEINTRIN_impDBESY0:
5423 case FFEINTRIN_impDBESY1:
5424 case FFEINTRIN_impDBESYN:
5425 case FFEINTRIN_impDTIME_func:
5426 case FFEINTRIN_impETIME_func:
5427 case FFEINTRIN_impFGETC_func:
5428 case FFEINTRIN_impFGET_func:
5429 case FFEINTRIN_impFNUM:
5430 case FFEINTRIN_impFPUTC_func:
5431 case FFEINTRIN_impFPUT_func:
5432 case FFEINTRIN_impFSEEK:
5433 case FFEINTRIN_impFSTAT_func:
5434 case FFEINTRIN_impFTELL_func:
5435 case FFEINTRIN_impGERROR:
5436 case FFEINTRIN_impGETARG:
5437 case FFEINTRIN_impGETCWD_func:
5438 case FFEINTRIN_impGETENV:
5439 case FFEINTRIN_impGETGID:
5440 case FFEINTRIN_impGETLOG:
5441 case FFEINTRIN_impGETPID:
5442 case FFEINTRIN_impGETUID:
5443 case FFEINTRIN_impGMTIME:
5444 case FFEINTRIN_impHOSTNM_func:
5445 case FFEINTRIN_impIDATE_unix:
5446 case FFEINTRIN_impIDATE_vxt:
5447 case FFEINTRIN_impIERRNO:
5448 case FFEINTRIN_impISATTY:
5449 case FFEINTRIN_impITIME:
5450 case FFEINTRIN_impKILL_func:
5451 case FFEINTRIN_impLINK_func:
5452 case FFEINTRIN_impLNBLNK:
5453 case FFEINTRIN_impLSTAT_func:
5454 case FFEINTRIN_impLTIME:
5455 case FFEINTRIN_impMCLOCK8:
5456 case FFEINTRIN_impMCLOCK:
5457 case FFEINTRIN_impPERROR:
5458 case FFEINTRIN_impRENAME_func:
5459 case FFEINTRIN_impSECNDS:
5460 case FFEINTRIN_impSECOND_func:
5461 case FFEINTRIN_impSLEEP:
5462 case FFEINTRIN_impSRAND:
5463 case FFEINTRIN_impSTAT_func:
5464 case FFEINTRIN_impSYMLNK_func:
5465 case FFEINTRIN_impSYSTEM_CLOCK:
5466 case FFEINTRIN_impSYSTEM_func:
5467 case FFEINTRIN_impTIME8:
5468 case FFEINTRIN_impTIME_unix:
5469 case FFEINTRIN_impTIME_vxt:
5470 case FFEINTRIN_impUMASK_func:
5471 case FFEINTRIN_impUNLINK_func:
5472 break;
5473
5474 case FFEINTRIN_impCTIME_func: /* CHARACTER functions not handled here. */
5475 case FFEINTRIN_impFDATE_func: /* CHARACTER functions not handled here. */
5476 case FFEINTRIN_impTTYNAM_func: /* CHARACTER functions not handled here. */
5477 case FFEINTRIN_impNONE:
5478 case FFEINTRIN_imp: /* Hush up gcc warning. */
5479 fprintf (stderr, "No %s implementation.\n",
5480 ffeintrin_name_implementation (ffebld_symter_implementation (ffebld_left (expr))));
5481 assert ("unimplemented intrinsic" == NULL);
5482 return error_mark_node;
5483 }
5484
5485 assert (gfrt != FFECOM_gfrt); /* Must have an implementation! */
5486
5ff904cd
JL
5487 expr_tree = ffecom_arglist_expr_ (ffecom_gfrt_args_ (gfrt),
5488 ffebld_right (expr));
5ff904cd
JL
5489
5490 return ffecom_call_ (ffecom_gfrt_tree_ (gfrt), ffecom_gfrt_kindtype (gfrt),
5491 (ffe_is_f2c_library () && ffecom_gfrt_complex_[gfrt]),
5492 tree_type,
5493 expr_tree, dest_tree, dest, dest_used,
c7e4ee3a
CB
5494 NULL_TREE, TRUE,
5495 ffebld_nonter_hook (expr));
5ff904cd 5496
c7e4ee3a
CB
5497 /* See bottom of this file for f2c transforms used to determine
5498 many of the above implementations. The info seems to confuse
5499 Emacs's C mode indentation, which is why it's been moved to
5500 the bottom of this source file. */
5501}
5ff904cd 5502
c7e4ee3a
CB
5503#endif
5504/* For power (exponentiation) where right-hand operand is type INTEGER,
5505 generate in-line code to do it the fast way (which, if the operand
5506 is a constant, might just mean a series of multiplies). */
5ff904cd 5507
c7e4ee3a
CB
5508#if FFECOM_targetCURRENT == FFECOM_targetGCC
5509static tree
5510ffecom_expr_power_integer_ (ffebld expr)
5511{
5512 tree l = ffecom_expr (ffebld_left (expr));
5513 tree r = ffecom_expr (ffebld_right (expr));
5514 tree ltype = TREE_TYPE (l);
5515 tree rtype = TREE_TYPE (r);
5516 tree result = NULL_TREE;
5ff904cd 5517
c7e4ee3a
CB
5518 if (l == error_mark_node
5519 || r == error_mark_node)
5520 return error_mark_node;
5ff904cd 5521
c7e4ee3a
CB
5522 if (TREE_CODE (r) == INTEGER_CST)
5523 {
5524 int sgn = tree_int_cst_sgn (r);
5ff904cd 5525
c7e4ee3a
CB
5526 if (sgn == 0)
5527 return convert (ltype, integer_one_node);
5ff904cd 5528
c7e4ee3a
CB
5529 if ((TREE_CODE (ltype) == INTEGER_TYPE)
5530 && (sgn < 0))
5531 {
5532 /* Reciprocal of integer is either 0, -1, or 1, so after
5533 calculating that (which we leave to the back end to do
5534 or not do optimally), don't bother with any multiplying. */
5ff904cd 5535
c7e4ee3a
CB
5536 result = ffecom_tree_divide_ (ltype,
5537 convert (ltype, integer_one_node),
5538 l,
5539 NULL_TREE, NULL, NULL, NULL_TREE);
5540 r = ffecom_1 (NEGATE_EXPR,
5541 rtype,
5542 r);
5543 if ((TREE_INT_CST_LOW (r) & 1) == 0)
5544 result = ffecom_1 (ABS_EXPR, rtype,
5545 result);
5546 }
5ff904cd 5547
c7e4ee3a
CB
5548 /* Generate appropriate series of multiplies, preceded
5549 by divide if the exponent is negative. */
5ff904cd 5550
c7e4ee3a 5551 l = save_expr (l);
5ff904cd 5552
c7e4ee3a
CB
5553 if (sgn < 0)
5554 {
5555 l = ffecom_tree_divide_ (ltype,
5556 convert (ltype, integer_one_node),
5557 l,
5558 NULL_TREE, NULL, NULL,
5559 ffebld_nonter_hook (expr));
5560 r = ffecom_1 (NEGATE_EXPR, rtype, r);
5561 assert (TREE_CODE (r) == INTEGER_CST);
5ff904cd 5562
c7e4ee3a
CB
5563 if (tree_int_cst_sgn (r) < 0)
5564 { /* The "most negative" number. */
5565 r = ffecom_1 (NEGATE_EXPR, rtype,
5566 ffecom_2 (RSHIFT_EXPR, rtype,
5567 r,
5568 integer_one_node));
5569 l = save_expr (l);
5570 l = ffecom_2 (MULT_EXPR, ltype,
5571 l,
5572 l);
5573 }
5574 }
5ff904cd 5575
c7e4ee3a
CB
5576 for (;;)
5577 {
5578 if (TREE_INT_CST_LOW (r) & 1)
5579 {
5580 if (result == NULL_TREE)
5581 result = l;
5582 else
5583 result = ffecom_2 (MULT_EXPR, ltype,
5584 result,
5585 l);
5586 }
5ff904cd 5587
c7e4ee3a
CB
5588 r = ffecom_2 (RSHIFT_EXPR, rtype,
5589 r,
5590 integer_one_node);
5591 if (integer_zerop (r))
5592 break;
5593 assert (TREE_CODE (r) == INTEGER_CST);
5ff904cd 5594
c7e4ee3a
CB
5595 l = save_expr (l);
5596 l = ffecom_2 (MULT_EXPR, ltype,
5597 l,
5598 l);
5599 }
5600 return result;
5601 }
5ff904cd 5602
c7e4ee3a
CB
5603 /* Though rhs isn't a constant, in-line code cannot be expanded
5604 while transforming dummies
5605 because the back end cannot be easily convinced to generate
5606 stores (MODIFY_EXPR), handle temporaries, and so on before
5607 all the appropriate rtx's have been generated for things like
5608 dummy args referenced in rhs -- which doesn't happen until
5609 store_parm_decls() is called (expand_function_start, I believe,
5610 does the actual rtx-stuffing of PARM_DECLs).
5ff904cd 5611
c7e4ee3a
CB
5612 So, in this case, let the caller generate the call to the
5613 run-time-library function to evaluate the power for us. */
5ff904cd 5614
c7e4ee3a
CB
5615 if (ffecom_transform_only_dummies_)
5616 return NULL_TREE;
5ff904cd 5617
c7e4ee3a
CB
5618 /* Right-hand operand not a constant, expand in-line code to figure
5619 out how to do the multiplies, &c.
5ff904cd 5620
c7e4ee3a
CB
5621 The returned expression is expressed this way in GNU C, where l and
5622 r are the "inputs":
5ff904cd 5623
c7e4ee3a
CB
5624 ({ typeof (r) rtmp = r;
5625 typeof (l) ltmp = l;
5626 typeof (l) result;
5ff904cd 5627
c7e4ee3a
CB
5628 if (rtmp == 0)
5629 result = 1;
5630 else
5631 {
5632 if ((basetypeof (l) == basetypeof (int))
5633 && (rtmp < 0))
5634 {
5635 result = ((typeof (l)) 1) / ltmp;
5636 if ((ltmp < 0) && (((-rtmp) & 1) == 0))
5637 result = -result;
5638 }
5639 else
5640 {
5641 result = 1;
5642 if ((basetypeof (l) != basetypeof (int))
5643 && (rtmp < 0))
5644 {
5645 ltmp = ((typeof (l)) 1) / ltmp;
5646 rtmp = -rtmp;
5647 if (rtmp < 0)
5648 {
5649 rtmp = -(rtmp >> 1);
5650 ltmp *= ltmp;
5651 }
5652 }
5653 for (;;)
5654 {
5655 if (rtmp & 1)
5656 result *= ltmp;
5657 if ((rtmp >>= 1) == 0)
5658 break;
5659 ltmp *= ltmp;
5660 }
5661 }
5662 }
5663 result;
5664 })
5ff904cd 5665
c7e4ee3a
CB
5666 Note that some of the above is compile-time collapsable, such as
5667 the first part of the if statements that checks the base type of
5668 l against int. The if statements are phrased that way to suggest
5669 an easy way to generate the if/else constructs here, knowing that
5670 the back end should (and probably does) eliminate the resulting
5671 dead code (either the int case or the non-int case), something
5672 it couldn't do without the redundant phrasing, requiring explicit
5673 dead-code elimination here, which would be kind of difficult to
5674 read. */
5ff904cd 5675
c7e4ee3a
CB
5676 {
5677 tree rtmp;
5678 tree ltmp;
5679 tree divide;
5680 tree basetypeof_l_is_int;
5681 tree se;
5682 tree t;
5ff904cd 5683
c7e4ee3a
CB
5684 basetypeof_l_is_int
5685 = build_int_2 ((TREE_CODE (ltype) == INTEGER_TYPE), 0);
5ff904cd 5686
c7e4ee3a 5687 se = expand_start_stmt_expr ();
5ff904cd 5688
c7e4ee3a
CB
5689 ffecom_start_compstmt ();
5690
5691#ifndef HAHA
5692 rtmp = ffecom_make_tempvar ("power_r", rtype,
5693 FFETARGET_charactersizeNONE, -1);
5694 ltmp = ffecom_make_tempvar ("power_l", ltype,
5695 FFETARGET_charactersizeNONE, -1);
5696 result = ffecom_make_tempvar ("power_res", ltype,
5697 FFETARGET_charactersizeNONE, -1);
5698 if (TREE_CODE (ltype) == COMPLEX_TYPE
5699 || TREE_CODE (ltype) == RECORD_TYPE)
5700 divide = ffecom_make_tempvar ("power_div", ltype,
5701 FFETARGET_charactersizeNONE, -1);
5702 else
5703 divide = NULL_TREE;
5704#else /* HAHA */
5705 {
5706 tree hook;
5707
5708 hook = ffebld_nonter_hook (expr);
5709 assert (hook);
5710 assert (TREE_CODE (hook) == TREE_VEC);
5711 assert (TREE_VEC_LENGTH (hook) == 4);
5712 rtmp = TREE_VEC_ELT (hook, 0);
5713 ltmp = TREE_VEC_ELT (hook, 1);
5714 result = TREE_VEC_ELT (hook, 2);
5715 divide = TREE_VEC_ELT (hook, 3);
5716 if (TREE_CODE (ltype) == COMPLEX_TYPE
5717 || TREE_CODE (ltype) == RECORD_TYPE)
5718 assert (divide);
5719 else
5720 assert (! divide);
5721 }
5722#endif /* HAHA */
5ff904cd 5723
c7e4ee3a
CB
5724 expand_expr_stmt (ffecom_modify (void_type_node,
5725 rtmp,
5726 r));
5727 expand_expr_stmt (ffecom_modify (void_type_node,
5728 ltmp,
5729 l));
5730 expand_start_cond (ffecom_truth_value
5731 (ffecom_2 (EQ_EXPR, integer_type_node,
5732 rtmp,
5733 convert (rtype, integer_zero_node))),
5734 0);
5735 expand_expr_stmt (ffecom_modify (void_type_node,
5736 result,
5737 convert (ltype, integer_one_node)));
5738 expand_start_else ();
5739 if (! integer_zerop (basetypeof_l_is_int))
5740 {
5741 expand_start_cond (ffecom_2 (LT_EXPR, integer_type_node,
5742 rtmp,
5743 convert (rtype,
5744 integer_zero_node)),
5745 0);
5746 expand_expr_stmt (ffecom_modify (void_type_node,
5747 result,
5748 ffecom_tree_divide_
5749 (ltype,
5750 convert (ltype, integer_one_node),
5751 ltmp,
5752 NULL_TREE, NULL, NULL,
5753 divide)));
5754 expand_start_cond (ffecom_truth_value
5755 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5756 ffecom_2 (LT_EXPR, integer_type_node,
5757 ltmp,
5758 convert (ltype,
5759 integer_zero_node)),
5760 ffecom_2 (EQ_EXPR, integer_type_node,
5761 ffecom_2 (BIT_AND_EXPR,
5762 rtype,
5763 ffecom_1 (NEGATE_EXPR,
5764 rtype,
5765 rtmp),
5766 convert (rtype,
5767 integer_one_node)),
5768 convert (rtype,
5769 integer_zero_node)))),
5770 0);
5771 expand_expr_stmt (ffecom_modify (void_type_node,
5772 result,
5773 ffecom_1 (NEGATE_EXPR,
5774 ltype,
5775 result)));
5776 expand_end_cond ();
5777 expand_start_else ();
5778 }
5779 expand_expr_stmt (ffecom_modify (void_type_node,
5780 result,
5781 convert (ltype, integer_one_node)));
5782 expand_start_cond (ffecom_truth_value
5783 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5784 ffecom_truth_value_invert
5785 (basetypeof_l_is_int),
5786 ffecom_2 (LT_EXPR, integer_type_node,
5787 rtmp,
5788 convert (rtype,
5789 integer_zero_node)))),
5790 0);
5791 expand_expr_stmt (ffecom_modify (void_type_node,
5792 ltmp,
5793 ffecom_tree_divide_
5794 (ltype,
5795 convert (ltype, integer_one_node),
5796 ltmp,
5797 NULL_TREE, NULL, NULL,
5798 divide)));
5799 expand_expr_stmt (ffecom_modify (void_type_node,
5800 rtmp,
5801 ffecom_1 (NEGATE_EXPR, rtype,
5802 rtmp)));
5803 expand_start_cond (ffecom_truth_value
5804 (ffecom_2 (LT_EXPR, integer_type_node,
5805 rtmp,
5806 convert (rtype, integer_zero_node))),
5807 0);
5808 expand_expr_stmt (ffecom_modify (void_type_node,
5809 rtmp,
5810 ffecom_1 (NEGATE_EXPR, rtype,
5811 ffecom_2 (RSHIFT_EXPR,
5812 rtype,
5813 rtmp,
5814 integer_one_node))));
5815 expand_expr_stmt (ffecom_modify (void_type_node,
5816 ltmp,
5817 ffecom_2 (MULT_EXPR, ltype,
5818 ltmp,
5819 ltmp)));
5820 expand_end_cond ();
5821 expand_end_cond ();
5822 expand_start_loop (1);
5823 expand_start_cond (ffecom_truth_value
5824 (ffecom_2 (BIT_AND_EXPR, rtype,
5825 rtmp,
5826 convert (rtype, integer_one_node))),
5827 0);
5828 expand_expr_stmt (ffecom_modify (void_type_node,
5829 result,
5830 ffecom_2 (MULT_EXPR, ltype,
5831 result,
5832 ltmp)));
5833 expand_end_cond ();
5834 expand_exit_loop_if_false (NULL,
5835 ffecom_truth_value
5836 (ffecom_modify (rtype,
5837 rtmp,
5838 ffecom_2 (RSHIFT_EXPR,
5839 rtype,
5840 rtmp,
5841 integer_one_node))));
5842 expand_expr_stmt (ffecom_modify (void_type_node,
5843 ltmp,
5844 ffecom_2 (MULT_EXPR, ltype,
5845 ltmp,
5846 ltmp)));
5847 expand_end_loop ();
5848 expand_end_cond ();
5849 if (!integer_zerop (basetypeof_l_is_int))
5850 expand_end_cond ();
5851 expand_expr_stmt (result);
5ff904cd 5852
c7e4ee3a 5853 t = ffecom_end_compstmt ();
5ff904cd 5854
c7e4ee3a 5855 result = expand_end_stmt_expr (se);
5ff904cd 5856
c7e4ee3a 5857 /* This code comes from c-parse.in, after its expand_end_stmt_expr. */
5ff904cd 5858
c7e4ee3a
CB
5859 if (TREE_CODE (t) == BLOCK)
5860 {
5861 /* Make a BIND_EXPR for the BLOCK already made. */
5862 result = build (BIND_EXPR, TREE_TYPE (result),
5863 NULL_TREE, result, t);
5864 /* Remove the block from the tree at this point.
5865 It gets put back at the proper place
5866 when the BIND_EXPR is expanded. */
5867 delete_block (t);
5868 }
5869 else
5870 result = t;
5871 }
5ff904cd 5872
c7e4ee3a
CB
5873 return result;
5874}
5ff904cd 5875
c7e4ee3a
CB
5876#endif
5877/* ffecom_expr_transform_ -- Transform symbols in expr
5ff904cd 5878
c7e4ee3a
CB
5879 ffebld expr; // FFE expression.
5880 ffecom_expr_transform_ (expr);
5ff904cd 5881
c7e4ee3a 5882 Recursive descent on expr while transforming any untransformed SYMTERs. */
5ff904cd 5883
c7e4ee3a
CB
5884#if FFECOM_targetCURRENT == FFECOM_targetGCC
5885static void
5886ffecom_expr_transform_ (ffebld expr)
5887{
5888 tree t;
5889 ffesymbol s;
5ff904cd 5890
c7e4ee3a 5891tail_recurse: /* :::::::::::::::::::: */
5ff904cd 5892
c7e4ee3a
CB
5893 if (expr == NULL)
5894 return;
5ff904cd 5895
c7e4ee3a
CB
5896 switch (ffebld_op (expr))
5897 {
5898 case FFEBLD_opSYMTER:
5899 s = ffebld_symter (expr);
5900 t = ffesymbol_hook (s).decl_tree;
5901 if ((t == NULL_TREE)
5902 && ((ffesymbol_kind (s) != FFEINFO_kindNONE)
5903 || ((ffesymbol_where (s) != FFEINFO_whereNONE)
5904 && (ffesymbol_where (s) != FFEINFO_whereINTRINSIC))))
5905 {
5906 s = ffecom_sym_transform_ (s);
5907 t = ffesymbol_hook (s).decl_tree; /* Sfunc expr non-dummy,
5908 DIMENSION expr? */
5909 }
5910 break; /* Ok if (t == NULL) here. */
5ff904cd 5911
c7e4ee3a
CB
5912 case FFEBLD_opITEM:
5913 ffecom_expr_transform_ (ffebld_head (expr));
5914 expr = ffebld_trail (expr);
5915 goto tail_recurse; /* :::::::::::::::::::: */
5ff904cd 5916
c7e4ee3a
CB
5917 default:
5918 break;
5919 }
5ff904cd 5920
c7e4ee3a
CB
5921 switch (ffebld_arity (expr))
5922 {
5923 case 2:
5924 ffecom_expr_transform_ (ffebld_left (expr));
5925 expr = ffebld_right (expr);
5926 goto tail_recurse; /* :::::::::::::::::::: */
5ff904cd 5927
c7e4ee3a
CB
5928 case 1:
5929 expr = ffebld_left (expr);
5930 goto tail_recurse; /* :::::::::::::::::::: */
5ff904cd 5931
c7e4ee3a
CB
5932 default:
5933 break;
5934 }
5ff904cd 5935
c7e4ee3a
CB
5936 return;
5937}
5ff904cd 5938
c7e4ee3a
CB
5939#endif
5940/* Make a type based on info in live f2c.h file. */
5ff904cd 5941
c7e4ee3a
CB
5942#if FFECOM_targetCURRENT == FFECOM_targetGCC
5943static void
5944ffecom_f2c_make_type_ (tree *type, int tcode, const char *name)
5945{
5946 switch (tcode)
5947 {
5948 case FFECOM_f2ccodeCHAR:
5949 *type = make_signed_type (CHAR_TYPE_SIZE);
5950 break;
5ff904cd 5951
c7e4ee3a
CB
5952 case FFECOM_f2ccodeSHORT:
5953 *type = make_signed_type (SHORT_TYPE_SIZE);
5954 break;
5ff904cd 5955
c7e4ee3a
CB
5956 case FFECOM_f2ccodeINT:
5957 *type = make_signed_type (INT_TYPE_SIZE);
5958 break;
5ff904cd 5959
c7e4ee3a
CB
5960 case FFECOM_f2ccodeLONG:
5961 *type = make_signed_type (LONG_TYPE_SIZE);
5962 break;
5ff904cd 5963
c7e4ee3a
CB
5964 case FFECOM_f2ccodeLONGLONG:
5965 *type = make_signed_type (LONG_LONG_TYPE_SIZE);
5966 break;
5ff904cd 5967
c7e4ee3a
CB
5968 case FFECOM_f2ccodeCHARPTR:
5969 *type = build_pointer_type (DEFAULT_SIGNED_CHAR
5970 ? signed_char_type_node
5971 : unsigned_char_type_node);
5972 break;
5ff904cd 5973
c7e4ee3a
CB
5974 case FFECOM_f2ccodeFLOAT:
5975 *type = make_node (REAL_TYPE);
5976 TYPE_PRECISION (*type) = FLOAT_TYPE_SIZE;
5977 layout_type (*type);
5978 break;
5979
5980 case FFECOM_f2ccodeDOUBLE:
5981 *type = make_node (REAL_TYPE);
5982 TYPE_PRECISION (*type) = DOUBLE_TYPE_SIZE;
5983 layout_type (*type);
5984 break;
5985
5986 case FFECOM_f2ccodeLONGDOUBLE:
5987 *type = make_node (REAL_TYPE);
5988 TYPE_PRECISION (*type) = LONG_DOUBLE_TYPE_SIZE;
5989 layout_type (*type);
5990 break;
5ff904cd 5991
c7e4ee3a
CB
5992 case FFECOM_f2ccodeTWOREALS:
5993 *type = ffecom_make_complex_type_ (ffecom_f2c_real_type_node);
5994 break;
5ff904cd 5995
c7e4ee3a
CB
5996 case FFECOM_f2ccodeTWODOUBLEREALS:
5997 *type = ffecom_make_complex_type_ (ffecom_f2c_doublereal_type_node);
5998 break;
5ff904cd 5999
c7e4ee3a
CB
6000 default:
6001 assert ("unexpected FFECOM_f2ccodeXYZZY!" == NULL);
6002 *type = error_mark_node;
6003 return;
6004 }
5ff904cd 6005
c7e4ee3a
CB
6006 pushdecl (build_decl (TYPE_DECL,
6007 ffecom_get_invented_identifier ("__g77_f2c_%s",
6008 name, -1),
6009 *type));
6010}
5ff904cd 6011
c7e4ee3a
CB
6012#endif
6013#if FFECOM_targetCURRENT == FFECOM_targetGCC
6014/* Set the f2c list-directed-I/O code for whatever (integral) type has the
6015 given size. */
5ff904cd 6016
c7e4ee3a
CB
6017static void
6018ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
6019 int code)
6020{
6021 int j;
6022 tree t;
5ff904cd 6023
c7e4ee3a
CB
6024 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
6025 if (((t = ffecom_tree_type[bt][j]) != NULL_TREE)
6026 && (TREE_INT_CST_LOW (TYPE_SIZE (t)) == size))
6027 {
6028 assert (code != -1);
6029 ffecom_f2c_typecode_[bt][j] = code;
6030 code = -1;
6031 }
6032}
5ff904cd 6033
c7e4ee3a
CB
6034#endif
6035/* Finish up globals after doing all program units in file
5ff904cd 6036
c7e4ee3a 6037 Need to handle only uninitialized COMMON areas. */
5ff904cd 6038
c7e4ee3a
CB
6039#if FFECOM_targetCURRENT == FFECOM_targetGCC
6040static ffeglobal
6041ffecom_finish_global_ (ffeglobal global)
6042{
6043 tree cbtype;
6044 tree cbt;
6045 tree size;
5ff904cd 6046
c7e4ee3a
CB
6047 if (ffeglobal_type (global) != FFEGLOBAL_typeCOMMON)
6048 return global;
5ff904cd 6049
c7e4ee3a
CB
6050 if (ffeglobal_common_init (global))
6051 return global;
5ff904cd 6052
c7e4ee3a
CB
6053 cbt = ffeglobal_hook (global);
6054 if ((cbt == NULL_TREE)
6055 || !ffeglobal_common_have_size (global))
6056 return global; /* No need to make common, never ref'd. */
5ff904cd 6057
c7e4ee3a 6058 suspend_momentary ();
5ff904cd 6059
c7e4ee3a 6060 DECL_EXTERNAL (cbt) = 0;
5ff904cd 6061
c7e4ee3a 6062 /* Give the array a size now. */
5ff904cd 6063
c7e4ee3a
CB
6064 size = build_int_2 ((ffeglobal_common_size (global)
6065 + ffeglobal_common_pad (global)) - 1,
6066 0);
5ff904cd 6067
c7e4ee3a
CB
6068 cbtype = TREE_TYPE (cbt);
6069 TYPE_DOMAIN (cbtype) = build_range_type (integer_type_node,
6070 integer_zero_node,
6071 size);
6072 if (!TREE_TYPE (size))
6073 TREE_TYPE (size) = TYPE_DOMAIN (cbtype);
6074 layout_type (cbtype);
5ff904cd 6075
c7e4ee3a
CB
6076 cbt = start_decl (cbt, FALSE);
6077 assert (cbt == ffeglobal_hook (global));
5ff904cd 6078
c7e4ee3a 6079 finish_decl (cbt, NULL_TREE, FALSE);
5ff904cd 6080
c7e4ee3a
CB
6081 return global;
6082}
5ff904cd 6083
c7e4ee3a
CB
6084#endif
6085/* Finish up any untransformed symbols. */
5ff904cd 6086
c7e4ee3a
CB
6087#if FFECOM_targetCURRENT == FFECOM_targetGCC
6088static ffesymbol
6089ffecom_finish_symbol_transform_ (ffesymbol s)
5ff904cd 6090{
c7e4ee3a
CB
6091 if ((s == NULL) || (TREE_CODE (current_function_decl) == ERROR_MARK))
6092 return s;
5ff904cd 6093
c7e4ee3a
CB
6094 /* It's easy to know to transform an untransformed symbol, to make sure
6095 we put out debugging info for it. But COMMON variables, unlike
6096 EQUIVALENCE ones, aren't given declarations in addition to the
6097 tree expressions that specify offsets, because COMMON variables
6098 can be referenced in the outer scope where only dummy arguments
6099 (PARM_DECLs) should really be seen. To be safe, just don't do any
6100 VAR_DECLs for COMMON variables when we transform them for real
6101 use, and therefore we do all the VAR_DECL creating here. */
5ff904cd 6102
c7e4ee3a
CB
6103 if (ffesymbol_hook (s).decl_tree == NULL_TREE)
6104 {
6105 if (ffesymbol_kind (s) != FFEINFO_kindNONE
6106 || (ffesymbol_where (s) != FFEINFO_whereNONE
6107 && ffesymbol_where (s) != FFEINFO_whereINTRINSIC
6108 && ffesymbol_where (s) != FFEINFO_whereDUMMY))
6109 /* Not transformed, and not CHARACTER*(*), and not a dummy
6110 argument, which can happen only if the entry point names
6111 it "rides in on" are all invalidated for other reasons. */
6112 s = ffecom_sym_transform_ (s);
6113 }
5ff904cd 6114
c7e4ee3a
CB
6115 if ((ffesymbol_where (s) == FFEINFO_whereCOMMON)
6116 && (ffesymbol_hook (s).decl_tree != error_mark_node))
6117 {
6118#ifdef SOMEONE_GETS_DEBUG_SUPPORT_WORKING
6119 int yes = suspend_momentary ();
5ff904cd 6120
c7e4ee3a
CB
6121 /* This isn't working, at least for dbxout. The .s file looks
6122 okay to me (burley), but in gdb 4.9 at least, the variables
6123 appear to reside somewhere outside of the common area, so
6124 it doesn't make sense to mislead anyone by generating the info
6125 on those variables until this is fixed. NOTE: Same problem
6126 with EQUIVALENCE, sadly...see similar #if later. */
6127 ffecom_member_phase2_ (ffesymbol_storage (ffesymbol_common (s)),
6128 ffesymbol_storage (s));
5ff904cd 6129
c7e4ee3a
CB
6130 resume_momentary (yes);
6131#endif
5ff904cd
JL
6132 }
6133
c7e4ee3a
CB
6134 return s;
6135}
5ff904cd 6136
c7e4ee3a
CB
6137#endif
6138/* Append underscore(s) to name before calling get_identifier. "us"
6139 is nonzero if the name already contains an underscore and thus
6140 needs two underscores appended. */
5ff904cd 6141
c7e4ee3a
CB
6142#if FFECOM_targetCURRENT == FFECOM_targetGCC
6143static tree
6144ffecom_get_appended_identifier_ (char us, const char *name)
6145{
6146 int i;
6147 char *newname;
6148 tree id;
5ff904cd 6149
c7e4ee3a
CB
6150 newname = xmalloc ((i = strlen (name)) + 1
6151 + ffe_is_underscoring ()
6152 + us);
6153 memcpy (newname, name, i);
6154 newname[i] = '_';
6155 newname[i + us] = '_';
6156 newname[i + 1 + us] = '\0';
6157 id = get_identifier (newname);
5ff904cd 6158
c7e4ee3a 6159 free (newname);
5ff904cd 6160
c7e4ee3a
CB
6161 return id;
6162}
5ff904cd 6163
c7e4ee3a
CB
6164#endif
6165/* Decide whether to append underscore to name before calling
6166 get_identifier. */
5ff904cd 6167
c7e4ee3a
CB
6168#if FFECOM_targetCURRENT == FFECOM_targetGCC
6169static tree
6170ffecom_get_external_identifier_ (ffesymbol s)
6171{
6172 char us;
6173 const char *name = ffesymbol_text (s);
5ff904cd 6174
c7e4ee3a 6175 /* If name is a built-in name, just return it as is. */
5ff904cd 6176
c7e4ee3a
CB
6177 if (!ffe_is_underscoring ()
6178 || (strcmp (name, FFETARGET_nameBLANK_COMMON) == 0)
6179#if FFETARGET_isENFORCED_MAIN_NAME
6180 || (strcmp (name, FFETARGET_nameENFORCED_NAME) == 0)
6181#else
6182 || (strcmp (name, FFETARGET_nameUNNAMED_MAIN) == 0)
6183#endif
6184 || (strcmp (name, FFETARGET_nameUNNAMED_BLOCK_DATA) == 0))
6185 return get_identifier (name);
5ff904cd 6186
c7e4ee3a
CB
6187 us = ffe_is_second_underscore ()
6188 ? (strchr (name, '_') != NULL)
6189 : 0;
5ff904cd 6190
c7e4ee3a
CB
6191 return ffecom_get_appended_identifier_ (us, name);
6192}
5ff904cd 6193
c7e4ee3a
CB
6194#endif
6195/* Decide whether to append underscore to internal name before calling
6196 get_identifier.
6197
6198 This is for non-external, top-function-context names only. Transform
6199 identifier so it doesn't conflict with the transformed result
6200 of using a _different_ external name. E.g. if "CALL FOO" is
6201 transformed into "FOO_();", then the variable in "FOO_ = 3"
6202 must be transformed into something that does not conflict, since
6203 these two things should be independent.
5ff904cd 6204
c7e4ee3a
CB
6205 The transformation is as follows. If the name does not contain
6206 an underscore, there is no possible conflict, so just return.
6207 If the name does contain an underscore, then transform it just
6208 like we transform an external identifier. */
5ff904cd 6209
c7e4ee3a
CB
6210#if FFECOM_targetCURRENT == FFECOM_targetGCC
6211static tree
6212ffecom_get_identifier_ (const char *name)
6213{
6214 /* If name does not contain an underscore, just return it as is. */
6215
6216 if (!ffe_is_underscoring ()
6217 || (strchr (name, '_') == NULL))
6218 return get_identifier (name);
6219
6220 return ffecom_get_appended_identifier_ (ffe_is_second_underscore (),
6221 name);
5ff904cd
JL
6222}
6223
6224#endif
c7e4ee3a 6225/* ffecom_gen_sfuncdef_ -- Generate definition of statement function
5ff904cd 6226
c7e4ee3a
CB
6227 tree t;
6228 ffesymbol s; // kindFUNCTION, whereIMMEDIATE.
6229 t = ffecom_gen_sfuncdef_(s,ffesymbol_basictype(s),
6230 ffesymbol_kindtype(s));
5ff904cd 6231
c7e4ee3a
CB
6232 Call after setting up containing function and getting trees for all
6233 other symbols. */
5ff904cd
JL
6234
6235#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
6236static tree
6237ffecom_gen_sfuncdef_ (ffesymbol s, ffeinfoBasictype bt, ffeinfoKindtype kt)
5ff904cd 6238{
c7e4ee3a
CB
6239 ffebld expr = ffesymbol_sfexpr (s);
6240 tree type;
6241 tree func;
6242 tree result;
6243 bool charfunc = (bt == FFEINFO_basictypeCHARACTER);
6244 static bool recurse = FALSE;
6245 int yes;
6246 int old_lineno = lineno;
6247 char *old_input_filename = input_filename;
5ff904cd 6248
c7e4ee3a 6249 ffecom_nested_entry_ = s;
5ff904cd 6250
c7e4ee3a
CB
6251 /* For now, we don't have a handy pointer to where the sfunc is actually
6252 defined, though that should be easy to add to an ffesymbol. (The
6253 token/where info available might well point to the place where the type
6254 of the sfunc is declared, especially if that precedes the place where
6255 the sfunc itself is defined, which is typically the case.) We should
6256 put out a null pointer rather than point somewhere wrong, but I want to
6257 see how it works at this point. */
5ff904cd 6258
c7e4ee3a
CB
6259 input_filename = ffesymbol_where_filename (s);
6260 lineno = ffesymbol_where_filelinenum (s);
5ff904cd 6261
c7e4ee3a
CB
6262 /* Pretransform the expression so any newly discovered things belong to the
6263 outer program unit, not to the statement function. */
5ff904cd 6264
c7e4ee3a 6265 ffecom_expr_transform_ (expr);
5ff904cd 6266
c7e4ee3a
CB
6267 /* Make sure no recursive invocation of this fn (a specific case of failing
6268 to pretransform an sfunc's expression, i.e. where its expression
6269 references another untransformed sfunc) happens. */
6270
6271 assert (!recurse);
6272 recurse = TRUE;
6273
6274 yes = suspend_momentary ();
6275
6276 push_f_function_context ();
6277
6278 if (charfunc)
6279 type = void_type_node;
6280 else
5ff904cd 6281 {
c7e4ee3a
CB
6282 type = ffecom_tree_type[bt][kt];
6283 if (type == NULL_TREE)
6284 type = integer_type_node; /* _sym_exec_transition reports
6285 error. */
6286 }
5ff904cd 6287
c7e4ee3a
CB
6288 start_function (ffecom_get_identifier_ (ffesymbol_text (s)),
6289 build_function_type (type, NULL_TREE),
6290 1, /* nested/inline */
6291 0); /* TREE_PUBLIC */
5ff904cd 6292
c7e4ee3a
CB
6293 /* We don't worry about COMPLEX return values here, because this is
6294 entirely internal to our code, and gcc has the ability to return COMPLEX
6295 directly as a value. */
6296
6297 yes = suspend_momentary ();
6298
6299 if (charfunc)
6300 { /* Prepend arg for where result goes. */
6301 tree type;
6302
6303 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
6304
6305 result = ffecom_get_invented_identifier ("__g77_%s",
6306 "result", -1);
6307
6308 ffecom_char_enhance_arg_ (&type, s); /* Ignore returned length. */
6309
6310 type = build_pointer_type (type);
6311 result = build_decl (PARM_DECL, result, type);
6312
6313 push_parm_decl (result);
5ff904cd 6314 }
c7e4ee3a
CB
6315 else
6316 result = NULL_TREE; /* Not ref'd if !charfunc. */
5ff904cd 6317
c7e4ee3a 6318 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (s), TRUE);
5ff904cd 6319
c7e4ee3a 6320 resume_momentary (yes);
5ff904cd 6321
c7e4ee3a
CB
6322 store_parm_decls (0);
6323
6324 ffecom_start_compstmt ();
6325
6326 if (expr != NULL)
5ff904cd 6327 {
c7e4ee3a
CB
6328 if (charfunc)
6329 {
6330 ffetargetCharacterSize sz = ffesymbol_size (s);
6331 tree result_length;
5ff904cd 6332
c7e4ee3a
CB
6333 result_length = build_int_2 (sz, 0);
6334 TREE_TYPE (result_length) = ffecom_f2c_ftnlen_type_node;
5ff904cd 6335
c7e4ee3a 6336 ffecom_prepare_let_char_ (sz, expr);
5ff904cd 6337
c7e4ee3a 6338 ffecom_prepare_end ();
5ff904cd 6339
c7e4ee3a
CB
6340 ffecom_let_char_ (result, result_length, sz, expr);
6341 expand_null_return ();
6342 }
6343 else
6344 {
6345 ffecom_prepare_expr (expr);
5ff904cd 6346
c7e4ee3a 6347 ffecom_prepare_end ();
5ff904cd 6348
c7e4ee3a
CB
6349 expand_return (ffecom_modify (NULL_TREE,
6350 DECL_RESULT (current_function_decl),
6351 ffecom_expr (expr)));
6352 }
5ff904cd 6353
c7e4ee3a
CB
6354 clear_momentary ();
6355 }
5ff904cd 6356
c7e4ee3a 6357 ffecom_end_compstmt ();
5ff904cd 6358
c7e4ee3a
CB
6359 func = current_function_decl;
6360 finish_function (1);
5ff904cd 6361
c7e4ee3a 6362 pop_f_function_context ();
5ff904cd 6363
c7e4ee3a 6364 resume_momentary (yes);
5ff904cd 6365
c7e4ee3a
CB
6366 recurse = FALSE;
6367
6368 lineno = old_lineno;
6369 input_filename = old_input_filename;
6370
6371 ffecom_nested_entry_ = NULL;
6372
6373 return func;
5ff904cd
JL
6374}
6375
6376#endif
5ff904cd 6377
c7e4ee3a
CB
6378#if FFECOM_targetCURRENT == FFECOM_targetGCC
6379static const char *
6380ffecom_gfrt_args_ (ffecomGfrt ix)
5ff904cd 6381{
c7e4ee3a
CB
6382 return ffecom_gfrt_argstring_[ix];
6383}
5ff904cd 6384
c7e4ee3a
CB
6385#endif
6386#if FFECOM_targetCURRENT == FFECOM_targetGCC
6387static tree
6388ffecom_gfrt_tree_ (ffecomGfrt ix)
6389{
6390 if (ffecom_gfrt_[ix] == NULL_TREE)
6391 ffecom_make_gfrt_ (ix);
6392
6393 return ffecom_1 (ADDR_EXPR,
6394 build_pointer_type (TREE_TYPE (ffecom_gfrt_[ix])),
6395 ffecom_gfrt_[ix]);
5ff904cd
JL
6396}
6397
6398#endif
c7e4ee3a 6399/* Return initialize-to-zero expression for this VAR_DECL. */
5ff904cd
JL
6400
6401#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
6402static tree
6403ffecom_init_zero_ (tree decl)
5ff904cd 6404{
c7e4ee3a
CB
6405 tree init;
6406 int incremental = TREE_STATIC (decl);
6407 tree type = TREE_TYPE (decl);
5ff904cd 6408
c7e4ee3a
CB
6409 if (incremental)
6410 {
6411 int momentary = suspend_momentary ();
6412 push_obstacks_nochange ();
6413 if (TREE_PERMANENT (decl))
6414 end_temporary_allocation ();
6415 make_decl_rtl (decl, NULL, TREE_PUBLIC (decl) ? 1 : 0);
6416 assemble_variable (decl, TREE_PUBLIC (decl) ? 1 : 0, 0, 1);
6417 pop_obstacks ();
6418 resume_momentary (momentary);
6419 }
5ff904cd 6420
c7e4ee3a 6421 push_momentary ();
5ff904cd 6422
c7e4ee3a
CB
6423 if ((TREE_CODE (type) != ARRAY_TYPE)
6424 && (TREE_CODE (type) != RECORD_TYPE)
6425 && (TREE_CODE (type) != UNION_TYPE)
6426 && !incremental)
6427 init = convert (type, integer_zero_node);
6428 else if (!incremental)
6429 {
6430 int momentary = suspend_momentary ();
5ff904cd 6431
c7e4ee3a
CB
6432 init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
6433 TREE_CONSTANT (init) = 1;
6434 TREE_STATIC (init) = 1;
5ff904cd 6435
c7e4ee3a
CB
6436 resume_momentary (momentary);
6437 }
6438 else
6439 {
6440 int momentary = suspend_momentary ();
5ff904cd 6441
c7e4ee3a
CB
6442 assemble_zeros (int_size_in_bytes (type));
6443 init = error_mark_node;
5ff904cd 6444
c7e4ee3a
CB
6445 resume_momentary (momentary);
6446 }
5ff904cd 6447
c7e4ee3a 6448 pop_momentary_nofree ();
5ff904cd 6449
c7e4ee3a 6450 return init;
5ff904cd
JL
6451}
6452
6453#endif
5ff904cd 6454#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
6455static tree
6456ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
6457 tree *maybe_tree)
5ff904cd 6458{
c7e4ee3a
CB
6459 tree expr_tree;
6460 tree length_tree;
5ff904cd 6461
c7e4ee3a 6462 switch (ffebld_op (arg))
6829256f 6463 {
c7e4ee3a
CB
6464 case FFEBLD_opCONTER: /* For F90, check 0-length. */
6465 if (ffetarget_length_character1
6466 (ffebld_constant_character1
6467 (ffebld_conter (arg))) == 0)
6468 {
6469 *maybe_tree = integer_zero_node;
6470 return convert (tree_type, integer_zero_node);
6471 }
5ff904cd 6472
c7e4ee3a
CB
6473 *maybe_tree = integer_one_node;
6474 expr_tree = build_int_2 (*ffetarget_text_character1
6475 (ffebld_constant_character1
6476 (ffebld_conter (arg))),
6477 0);
6478 TREE_TYPE (expr_tree) = tree_type;
6479 return expr_tree;
5ff904cd 6480
c7e4ee3a
CB
6481 case FFEBLD_opSYMTER:
6482 case FFEBLD_opARRAYREF:
6483 case FFEBLD_opFUNCREF:
6484 case FFEBLD_opSUBSTR:
6485 ffecom_char_args_ (&expr_tree, &length_tree, arg);
5ff904cd 6486
c7e4ee3a
CB
6487 if ((expr_tree == error_mark_node)
6488 || (length_tree == error_mark_node))
6489 {
6490 *maybe_tree = error_mark_node;
6491 return error_mark_node;
6492 }
5ff904cd 6493
c7e4ee3a
CB
6494 if (integer_zerop (length_tree))
6495 {
6496 *maybe_tree = integer_zero_node;
6497 return convert (tree_type, integer_zero_node);
6498 }
6499
6500 expr_tree
6501 = ffecom_1 (INDIRECT_REF,
6502 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6503 expr_tree);
6504 expr_tree
6505 = ffecom_2 (ARRAY_REF,
6506 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6507 expr_tree,
6508 integer_one_node);
6509 expr_tree = convert (tree_type, expr_tree);
6510
6511 if (TREE_CODE (length_tree) == INTEGER_CST)
6512 *maybe_tree = integer_one_node;
6513 else /* Must check length at run time. */
6514 *maybe_tree
6515 = ffecom_truth_value
6516 (ffecom_2 (GT_EXPR, integer_type_node,
6517 length_tree,
6518 ffecom_f2c_ftnlen_zero_node));
6519 return expr_tree;
6520
6521 case FFEBLD_opPAREN:
6522 case FFEBLD_opCONVERT:
6523 if (ffeinfo_size (ffebld_info (arg)) == 0)
6524 {
6525 *maybe_tree = integer_zero_node;
6526 return convert (tree_type, integer_zero_node);
6527 }
6528 return ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6529 maybe_tree);
6530
6531 case FFEBLD_opCONCATENATE:
6532 {
6533 tree maybe_left;
6534 tree maybe_right;
6535 tree expr_left;
6536 tree expr_right;
6537
6538 expr_left = ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6539 &maybe_left);
6540 expr_right = ffecom_intrinsic_ichar_ (tree_type, ffebld_right (arg),
6541 &maybe_right);
6542 *maybe_tree = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
6543 maybe_left,
6544 maybe_right);
6545 expr_tree = ffecom_3 (COND_EXPR, tree_type,
6546 maybe_left,
6547 expr_left,
6548 expr_right);
6549 return expr_tree;
6550 }
6551
6552 default:
6553 assert ("bad op in ICHAR" == NULL);
6554 return error_mark_node;
6555 }
5ff904cd
JL
6556}
6557
6558#endif
c7e4ee3a
CB
6559/* ffecom_intrinsic_len_ -- Return length info for char arg (LEN())
6560
6561 tree length_arg;
6562 ffebld expr;
6563 length_arg = ffecom_intrinsic_len_ (expr);
6564
6565 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
6566 subexpressions by constructing the appropriate tree for the
6567 length-of-character-text argument in a calling sequence. */
5ff904cd
JL
6568
6569#if FFECOM_targetCURRENT == FFECOM_targetGCC
6570static tree
c7e4ee3a 6571ffecom_intrinsic_len_ (ffebld expr)
5ff904cd 6572{
c7e4ee3a
CB
6573 ffetargetCharacter1 val;
6574 tree length;
6575
6576 switch (ffebld_op (expr))
6577 {
6578 case FFEBLD_opCONTER:
6579 val = ffebld_constant_character1 (ffebld_conter (expr));
6580 length = build_int_2 (ffetarget_length_character1 (val), 0);
6581 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6582 break;
6583
6584 case FFEBLD_opSYMTER:
6585 {
6586 ffesymbol s = ffebld_symter (expr);
6587 tree item;
6588
6589 item = ffesymbol_hook (s).decl_tree;
6590 if (item == NULL_TREE)
6591 {
6592 s = ffecom_sym_transform_ (s);
6593 item = ffesymbol_hook (s).decl_tree;
6594 }
6595 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
6596 {
6597 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
6598 length = ffesymbol_hook (s).length_tree;
6599 else
6600 {
6601 length = build_int_2 (ffesymbol_size (s), 0);
6602 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6603 }
6604 }
6605 else if (item == error_mark_node)
6606 length = error_mark_node;
6607 else /* FFEINFO_kindFUNCTION: */
6608 length = NULL_TREE;
6609 }
6610 break;
5ff904cd 6611
c7e4ee3a
CB
6612 case FFEBLD_opARRAYREF:
6613 length = ffecom_intrinsic_len_ (ffebld_left (expr));
6614 break;
5ff904cd 6615
c7e4ee3a
CB
6616 case FFEBLD_opSUBSTR:
6617 {
6618 ffebld start;
6619 ffebld end;
6620 ffebld thing = ffebld_right (expr);
6621 tree start_tree;
6622 tree end_tree;
5ff904cd 6623
c7e4ee3a
CB
6624 assert (ffebld_op (thing) == FFEBLD_opITEM);
6625 start = ffebld_head (thing);
6626 thing = ffebld_trail (thing);
6627 assert (ffebld_trail (thing) == NULL);
6628 end = ffebld_head (thing);
5ff904cd 6629
c7e4ee3a 6630 length = ffecom_intrinsic_len_ (ffebld_left (expr));
5ff904cd 6631
c7e4ee3a
CB
6632 if (length == error_mark_node)
6633 break;
5ff904cd 6634
c7e4ee3a
CB
6635 if (start == NULL)
6636 {
6637 if (end == NULL)
6638 ;
6639 else
6640 {
6641 length = convert (ffecom_f2c_ftnlen_type_node,
6642 ffecom_expr (end));
6643 }
6644 }
6645 else
6646 {
6647 start_tree = convert (ffecom_f2c_ftnlen_type_node,
6648 ffecom_expr (start));
5ff904cd 6649
c7e4ee3a
CB
6650 if (start_tree == error_mark_node)
6651 {
6652 length = error_mark_node;
6653 break;
6654 }
5ff904cd 6655
c7e4ee3a
CB
6656 if (end == NULL)
6657 {
6658 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6659 ffecom_f2c_ftnlen_one_node,
6660 ffecom_2 (MINUS_EXPR,
6661 ffecom_f2c_ftnlen_type_node,
6662 length,
6663 start_tree));
6664 }
6665 else
6666 {
6667 end_tree = convert (ffecom_f2c_ftnlen_type_node,
6668 ffecom_expr (end));
5ff904cd 6669
c7e4ee3a
CB
6670 if (end_tree == error_mark_node)
6671 {
6672 length = error_mark_node;
6673 break;
6674 }
5ff904cd 6675
c7e4ee3a
CB
6676 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6677 ffecom_f2c_ftnlen_one_node,
6678 ffecom_2 (MINUS_EXPR,
6679 ffecom_f2c_ftnlen_type_node,
6680 end_tree, start_tree));
6681 }
6682 }
6683 }
6684 break;
5ff904cd 6685
c7e4ee3a
CB
6686 case FFEBLD_opCONCATENATE:
6687 length
6688 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6689 ffecom_intrinsic_len_ (ffebld_left (expr)),
6690 ffecom_intrinsic_len_ (ffebld_right (expr)));
6691 break;
5ff904cd 6692
c7e4ee3a
CB
6693 case FFEBLD_opFUNCREF:
6694 case FFEBLD_opCONVERT:
6695 length = build_int_2 (ffebld_size (expr), 0);
6696 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6697 break;
5ff904cd 6698
c7e4ee3a
CB
6699 default:
6700 assert ("bad op for single char arg expr" == NULL);
6701 length = ffecom_f2c_ftnlen_zero_node;
6702 break;
6703 }
5ff904cd 6704
c7e4ee3a 6705 assert (length != NULL_TREE);
5ff904cd 6706
c7e4ee3a 6707 return length;
5ff904cd
JL
6708}
6709
6710#endif
c7e4ee3a 6711/* Handle CHARACTER assignments.
5ff904cd 6712
c7e4ee3a
CB
6713 Generates code to do the assignment. Used by ordinary assignment
6714 statement handler ffecom_let_stmt and by statement-function
6715 handler to generate code for a statement function. */
5ff904cd
JL
6716
6717#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
6718static void
6719ffecom_let_char_ (tree dest_tree, tree dest_length,
6720 ffetargetCharacterSize dest_size, ffebld source)
5ff904cd 6721{
c7e4ee3a
CB
6722 ffecomConcatList_ catlist;
6723 tree source_length;
6724 tree source_tree;
6725 tree expr_tree;
5ff904cd 6726
c7e4ee3a
CB
6727 if ((dest_tree == error_mark_node)
6728 || (dest_length == error_mark_node))
6729 return;
5ff904cd 6730
c7e4ee3a
CB
6731 assert (dest_tree != NULL_TREE);
6732 assert (dest_length != NULL_TREE);
5ff904cd 6733
c7e4ee3a
CB
6734 /* Source might be an opCONVERT, which just means it is a different size
6735 than the destination. Since the underlying implementation here handles
6736 that (directly or via the s_copy or s_cat run-time-library functions),
6737 we don't need the "convenience" of an opCONVERT that tells us to
6738 truncate or blank-pad, particularly since the resulting implementation
6739 would probably be slower than otherwise. */
5ff904cd 6740
c7e4ee3a
CB
6741 while (ffebld_op (source) == FFEBLD_opCONVERT)
6742 source = ffebld_left (source);
5ff904cd 6743
c7e4ee3a
CB
6744 catlist = ffecom_concat_list_new_ (source, dest_size);
6745 switch (ffecom_concat_list_count_ (catlist))
6746 {
6747 case 0: /* Shouldn't happen, but in case it does... */
6748 ffecom_concat_list_kill_ (catlist);
6749 source_tree = null_pointer_node;
6750 source_length = ffecom_f2c_ftnlen_zero_node;
6751 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6752 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6753 TREE_CHAIN (TREE_CHAIN (expr_tree))
6754 = build_tree_list (NULL_TREE, dest_length);
6755 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6756 = build_tree_list (NULL_TREE, source_length);
5ff904cd 6757
c7e4ee3a
CB
6758 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6759 TREE_SIDE_EFFECTS (expr_tree) = 1;
5ff904cd 6760
c7e4ee3a 6761 expand_expr_stmt (expr_tree);
5ff904cd 6762
c7e4ee3a 6763 return;
5ff904cd 6764
c7e4ee3a
CB
6765 case 1: /* The (fairly) easy case. */
6766 ffecom_char_args_ (&source_tree, &source_length,
6767 ffecom_concat_list_expr_ (catlist, 0));
6768 ffecom_concat_list_kill_ (catlist);
6769 assert (source_tree != NULL_TREE);
6770 assert (source_length != NULL_TREE);
6771
6772 if ((source_tree == error_mark_node)
6773 || (source_length == error_mark_node))
6774 return;
6775
6776 if (dest_size == 1)
6777 {
6778 dest_tree
6779 = ffecom_1 (INDIRECT_REF,
6780 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6781 (dest_tree))),
6782 dest_tree);
6783 dest_tree
6784 = ffecom_2 (ARRAY_REF,
6785 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6786 (dest_tree))),
6787 dest_tree,
6788 integer_one_node);
6789 source_tree
6790 = ffecom_1 (INDIRECT_REF,
6791 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6792 (source_tree))),
6793 source_tree);
6794 source_tree
6795 = ffecom_2 (ARRAY_REF,
6796 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6797 (source_tree))),
6798 source_tree,
6799 integer_one_node);
5ff904cd 6800
c7e4ee3a 6801 expr_tree = ffecom_modify (void_type_node, dest_tree, source_tree);
5ff904cd 6802
c7e4ee3a 6803 expand_expr_stmt (expr_tree);
5ff904cd 6804
c7e4ee3a
CB
6805 return;
6806 }
5ff904cd 6807
c7e4ee3a
CB
6808 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6809 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6810 TREE_CHAIN (TREE_CHAIN (expr_tree))
6811 = build_tree_list (NULL_TREE, dest_length);
6812 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6813 = build_tree_list (NULL_TREE, source_length);
5ff904cd 6814
c7e4ee3a
CB
6815 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6816 TREE_SIDE_EFFECTS (expr_tree) = 1;
5ff904cd 6817
c7e4ee3a 6818 expand_expr_stmt (expr_tree);
5ff904cd 6819
c7e4ee3a 6820 return;
5ff904cd 6821
c7e4ee3a
CB
6822 default: /* Must actually concatenate things. */
6823 break;
6824 }
5ff904cd 6825
c7e4ee3a 6826 /* Heavy-duty concatenation. */
5ff904cd 6827
c7e4ee3a
CB
6828 {
6829 int count = ffecom_concat_list_count_ (catlist);
6830 int i;
6831 tree lengths;
6832 tree items;
6833 tree length_array;
6834 tree item_array;
6835 tree citem;
6836 tree clength;
5ff904cd 6837
c7e4ee3a
CB
6838#ifdef HOHO
6839 length_array
6840 = lengths
6841 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
6842 FFETARGET_charactersizeNONE, count, TRUE);
6843 item_array = items = ffecom_push_tempvar (ffecom_f2c_address_type_node,
6844 FFETARGET_charactersizeNONE,
6845 count, TRUE);
6846#else
6847 {
6848 tree hook;
6849
6850 hook = ffebld_nonter_hook (source);
6851 assert (hook);
6852 assert (TREE_CODE (hook) == TREE_VEC);
6853 assert (TREE_VEC_LENGTH (hook) == 2);
6854 length_array = lengths = TREE_VEC_ELT (hook, 0);
6855 item_array = items = TREE_VEC_ELT (hook, 1);
5ff904cd 6856 }
c7e4ee3a 6857#endif
5ff904cd 6858
c7e4ee3a
CB
6859 for (i = 0; i < count; ++i)
6860 {
6861 ffecom_char_args_ (&citem, &clength,
6862 ffecom_concat_list_expr_ (catlist, i));
6863 if ((citem == error_mark_node)
6864 || (clength == error_mark_node))
6865 {
6866 ffecom_concat_list_kill_ (catlist);
6867 return;
6868 }
5ff904cd 6869
c7e4ee3a
CB
6870 items
6871 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
6872 ffecom_modify (void_type_node,
6873 ffecom_2 (ARRAY_REF,
6874 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
6875 item_array,
6876 build_int_2 (i, 0)),
6877 citem),
6878 items);
6879 lengths
6880 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
6881 ffecom_modify (void_type_node,
6882 ffecom_2 (ARRAY_REF,
6883 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
6884 length_array,
6885 build_int_2 (i, 0)),
6886 clength),
6887 lengths);
6888 }
5ff904cd 6889
c7e4ee3a
CB
6890 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6891 TREE_CHAIN (expr_tree)
6892 = build_tree_list (NULL_TREE,
6893 ffecom_1 (ADDR_EXPR,
6894 build_pointer_type (TREE_TYPE (items)),
6895 items));
6896 TREE_CHAIN (TREE_CHAIN (expr_tree))
6897 = build_tree_list (NULL_TREE,
6898 ffecom_1 (ADDR_EXPR,
6899 build_pointer_type (TREE_TYPE (lengths)),
6900 lengths));
6901 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6902 = build_tree_list
6903 (NULL_TREE,
6904 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
6905 convert (ffecom_f2c_ftnlen_type_node,
6906 build_int_2 (count, 0))));
6907 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree))))
6908 = build_tree_list (NULL_TREE, dest_length);
5ff904cd 6909
c7e4ee3a
CB
6910 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCAT, expr_tree, NULL_TREE);
6911 TREE_SIDE_EFFECTS (expr_tree) = 1;
5ff904cd 6912
c7e4ee3a
CB
6913 expand_expr_stmt (expr_tree);
6914 }
5ff904cd 6915
c7e4ee3a
CB
6916 ffecom_concat_list_kill_ (catlist);
6917}
5ff904cd 6918
c7e4ee3a
CB
6919#endif
6920/* ffecom_make_gfrt_ -- Make initial info for run-time routine
5ff904cd 6921
c7e4ee3a
CB
6922 ffecomGfrt ix;
6923 ffecom_make_gfrt_(ix);
5ff904cd 6924
c7e4ee3a
CB
6925 Assumes gfrt_[ix] is NULL_TREE, and replaces it with the FUNCTION_DECL
6926 for the indicated run-time routine (ix). */
5ff904cd 6927
c7e4ee3a
CB
6928#if FFECOM_targetCURRENT == FFECOM_targetGCC
6929static void
6930ffecom_make_gfrt_ (ffecomGfrt ix)
6931{
6932 tree t;
6933 tree ttype;
5ff904cd 6934
c7e4ee3a
CB
6935 push_obstacks_nochange ();
6936 end_temporary_allocation ();
5ff904cd 6937
c7e4ee3a
CB
6938 switch (ffecom_gfrt_type_[ix])
6939 {
6940 case FFECOM_rttypeVOID_:
6941 ttype = void_type_node;
6942 break;
5ff904cd 6943
c7e4ee3a
CB
6944 case FFECOM_rttypeVOIDSTAR_:
6945 ttype = TREE_TYPE (null_pointer_node); /* `void *'. */
6946 break;
5ff904cd 6947
c7e4ee3a
CB
6948 case FFECOM_rttypeFTNINT_:
6949 ttype = ffecom_f2c_ftnint_type_node;
6950 break;
5ff904cd 6951
c7e4ee3a
CB
6952 case FFECOM_rttypeINTEGER_:
6953 ttype = ffecom_f2c_integer_type_node;
6954 break;
5ff904cd 6955
c7e4ee3a
CB
6956 case FFECOM_rttypeLONGINT_:
6957 ttype = ffecom_f2c_longint_type_node;
6958 break;
5ff904cd 6959
c7e4ee3a
CB
6960 case FFECOM_rttypeLOGICAL_:
6961 ttype = ffecom_f2c_logical_type_node;
6962 break;
5ff904cd 6963
c7e4ee3a
CB
6964 case FFECOM_rttypeREAL_F2C_:
6965 ttype = double_type_node;
6966 break;
5ff904cd 6967
c7e4ee3a
CB
6968 case FFECOM_rttypeREAL_GNU_:
6969 ttype = float_type_node;
6970 break;
5ff904cd 6971
c7e4ee3a
CB
6972 case FFECOM_rttypeCOMPLEX_F2C_:
6973 ttype = void_type_node;
6974 break;
5ff904cd 6975
c7e4ee3a
CB
6976 case FFECOM_rttypeCOMPLEX_GNU_:
6977 ttype = ffecom_f2c_complex_type_node;
6978 break;
5ff904cd 6979
c7e4ee3a
CB
6980 case FFECOM_rttypeDOUBLE_:
6981 ttype = double_type_node;
6982 break;
5ff904cd 6983
c7e4ee3a
CB
6984 case FFECOM_rttypeDOUBLEREAL_:
6985 ttype = ffecom_f2c_doublereal_type_node;
6986 break;
5ff904cd 6987
c7e4ee3a
CB
6988 case FFECOM_rttypeDBLCMPLX_F2C_:
6989 ttype = void_type_node;
6990 break;
5ff904cd 6991
c7e4ee3a
CB
6992 case FFECOM_rttypeDBLCMPLX_GNU_:
6993 ttype = ffecom_f2c_doublecomplex_type_node;
6994 break;
5ff904cd 6995
c7e4ee3a
CB
6996 case FFECOM_rttypeCHARACTER_:
6997 ttype = void_type_node;
6998 break;
6999
7000 default:
7001 ttype = NULL;
7002 assert ("bad rttype" == NULL);
7003 break;
5ff904cd 7004 }
5ff904cd 7005
c7e4ee3a
CB
7006 ttype = build_function_type (ttype, NULL_TREE);
7007 t = build_decl (FUNCTION_DECL,
7008 get_identifier (ffecom_gfrt_name_[ix]),
7009 ttype);
7010 DECL_EXTERNAL (t) = 1;
7011 TREE_PUBLIC (t) = 1;
7012 TREE_THIS_VOLATILE (t) = ffecom_gfrt_volatile_[ix] ? 1 : 0;
5ff904cd 7013
c7e4ee3a 7014 t = start_decl (t, TRUE);
5ff904cd 7015
c7e4ee3a 7016 finish_decl (t, NULL_TREE, TRUE);
5ff904cd 7017
c7e4ee3a
CB
7018 resume_temporary_allocation ();
7019 pop_obstacks ();
7020
7021 ffecom_gfrt_[ix] = t;
5ff904cd
JL
7022}
7023
7024#endif
c7e4ee3a
CB
7025/* Phase 1 pass over each member of a COMMON/EQUIVALENCE group. */
7026
5ff904cd 7027#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
7028static void
7029ffecom_member_phase1_ (ffestorag mst UNUSED, ffestorag st)
5ff904cd 7030{
c7e4ee3a 7031 ffesymbol s = ffestorag_symbol (st);
5ff904cd 7032
c7e4ee3a
CB
7033 if (ffesymbol_namelisted (s))
7034 ffecom_member_namelisted_ = TRUE;
7035}
5ff904cd 7036
c7e4ee3a
CB
7037#endif
7038/* Phase 2 pass over each member of a COMMON/EQUIVALENCE group. Declare
7039 the member so debugger will see it. Otherwise nobody should be
7040 referencing the member. */
5ff904cd 7041
c7e4ee3a
CB
7042#if FFECOM_targetCURRENT == FFECOM_targetGCC
7043#ifdef SOMEONE_GETS_DEBUG_SUPPORT_WORKING
7044static void
7045ffecom_member_phase2_ (ffestorag mst, ffestorag st)
7046{
7047 ffesymbol s;
7048 tree t;
7049 tree mt;
7050 tree type;
5ff904cd 7051
c7e4ee3a
CB
7052 if ((mst == NULL)
7053 || ((mt = ffestorag_hook (mst)) == NULL)
7054 || (mt == error_mark_node))
7055 return;
5ff904cd 7056
c7e4ee3a
CB
7057 if ((st == NULL)
7058 || ((s = ffestorag_symbol (st)) == NULL))
7059 return;
5ff904cd 7060
c7e4ee3a
CB
7061 type = ffecom_type_localvar_ (s,
7062 ffesymbol_basictype (s),
7063 ffesymbol_kindtype (s));
7064 if (type == error_mark_node)
7065 return;
5ff904cd 7066
c7e4ee3a
CB
7067 t = build_decl (VAR_DECL,
7068 ffecom_get_identifier_ (ffesymbol_text (s)),
7069 type);
5ff904cd 7070
c7e4ee3a
CB
7071 TREE_STATIC (t) = TREE_STATIC (mt);
7072 DECL_INITIAL (t) = NULL_TREE;
7073 TREE_ASM_WRITTEN (t) = 1;
5ff904cd 7074
c7e4ee3a
CB
7075 DECL_RTL (t)
7076 = gen_rtx (MEM, TYPE_MODE (type),
7077 plus_constant (XEXP (DECL_RTL (mt), 0),
7078 ffestorag_modulo (mst)
7079 + ffestorag_offset (st)
7080 - ffestorag_offset (mst)));
5ff904cd 7081
c7e4ee3a 7082 t = start_decl (t, FALSE);
5ff904cd 7083
c7e4ee3a 7084 finish_decl (t, NULL_TREE, FALSE);
5ff904cd
JL
7085}
7086
7087#endif
c7e4ee3a
CB
7088#endif
7089/* Prepare source expression for assignment into a destination perhaps known
7090 to be of a specific size. */
5ff904cd 7091
c7e4ee3a
CB
7092static void
7093ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size, ffebld source)
5ff904cd 7094{
c7e4ee3a
CB
7095 ffecomConcatList_ catlist;
7096 int count;
7097 int i;
7098 tree ltmp;
7099 tree itmp;
7100 tree tempvar = NULL_TREE;
5ff904cd 7101
c7e4ee3a
CB
7102 while (ffebld_op (source) == FFEBLD_opCONVERT)
7103 source = ffebld_left (source);
5ff904cd 7104
c7e4ee3a
CB
7105 catlist = ffecom_concat_list_new_ (source, dest_size);
7106 count = ffecom_concat_list_count_ (catlist);
5ff904cd 7107
c7e4ee3a
CB
7108 if (count >= 2)
7109 {
7110 ltmp
7111 = ffecom_make_tempvar ("let_char_len", ffecom_f2c_ftnlen_type_node,
7112 FFETARGET_charactersizeNONE, count);
7113 itmp
7114 = ffecom_make_tempvar ("let_char_item", ffecom_f2c_address_type_node,
7115 FFETARGET_charactersizeNONE, count);
7116
7117 tempvar = make_tree_vec (2);
7118 TREE_VEC_ELT (tempvar, 0) = ltmp;
7119 TREE_VEC_ELT (tempvar, 1) = itmp;
7120 }
5ff904cd 7121
c7e4ee3a
CB
7122 for (i = 0; i < count; ++i)
7123 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist, i));
5ff904cd 7124
c7e4ee3a 7125 ffecom_concat_list_kill_ (catlist);
5ff904cd 7126
c7e4ee3a
CB
7127 if (tempvar)
7128 {
7129 ffebld_nonter_set_hook (source, tempvar);
7130 current_binding_level->prep_state = 1;
7131 }
7132}
5ff904cd 7133
c7e4ee3a 7134/* ffecom_push_dummy_decls_ -- Transform dummy args, push parm decls in order
5ff904cd 7135
c7e4ee3a
CB
7136 Ignores STAR (alternate-return) dummies. All other get exec-transitioned
7137 (which generates their trees) and then their trees get push_parm_decl'd.
5ff904cd 7138
c7e4ee3a
CB
7139 The second arg is TRUE if the dummies are for a statement function, in
7140 which case lengths are not pushed for character arguments (since they are
7141 always known by both the caller and the callee, though the code allows
7142 for someday permitting CHAR*(*) stmtfunc dummies). */
5ff904cd 7143
c7e4ee3a
CB
7144#if FFECOM_targetCURRENT == FFECOM_targetGCC
7145static void
7146ffecom_push_dummy_decls_ (ffebld dummy_list, bool stmtfunc)
7147{
7148 ffebld dummy;
7149 ffebld dumlist;
7150 ffesymbol s;
7151 tree parm;
5ff904cd 7152
c7e4ee3a 7153 ffecom_transform_only_dummies_ = TRUE;
5ff904cd 7154
c7e4ee3a 7155 /* First push the parms corresponding to actual dummy "contents". */
5ff904cd 7156
c7e4ee3a
CB
7157 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7158 {
7159 dummy = ffebld_head (dumlist);
7160 switch (ffebld_op (dummy))
7161 {
7162 case FFEBLD_opSTAR:
7163 case FFEBLD_opANY:
7164 continue; /* Forget alternate returns. */
5ff904cd 7165
c7e4ee3a
CB
7166 default:
7167 break;
7168 }
7169 assert (ffebld_op (dummy) == FFEBLD_opSYMTER);
7170 s = ffebld_symter (dummy);
7171 parm = ffesymbol_hook (s).decl_tree;
7172 if (parm == NULL_TREE)
7173 {
7174 s = ffecom_sym_transform_ (s);
7175 parm = ffesymbol_hook (s).decl_tree;
7176 assert (parm != NULL_TREE);
7177 }
7178 if (parm != error_mark_node)
7179 push_parm_decl (parm);
5ff904cd
JL
7180 }
7181
c7e4ee3a 7182 /* Then, for CHARACTER dummies, push the parms giving their lengths. */
5ff904cd 7183
c7e4ee3a
CB
7184 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7185 {
7186 dummy = ffebld_head (dumlist);
7187 switch (ffebld_op (dummy))
7188 {
7189 case FFEBLD_opSTAR:
7190 case FFEBLD_opANY:
7191 continue; /* Forget alternate returns, they mean
7192 NOTHING! */
7193
7194 default:
7195 break;
7196 }
7197 s = ffebld_symter (dummy);
7198 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
7199 continue; /* Only looking for CHARACTER arguments. */
7200 if (stmtfunc && (ffesymbol_size (s) != FFETARGET_charactersizeNONE))
7201 continue; /* Stmtfunc arg with known size needs no
7202 length param. */
7203 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
7204 continue; /* Only looking for variables and arrays. */
7205 parm = ffesymbol_hook (s).length_tree;
7206 assert (parm != NULL_TREE);
7207 if (parm != error_mark_node)
7208 push_parm_decl (parm);
7209 }
7210
7211 ffecom_transform_only_dummies_ = FALSE;
5ff904cd
JL
7212}
7213
7214#endif
c7e4ee3a 7215/* ffecom_start_progunit_ -- Beginning of program unit
5ff904cd 7216
c7e4ee3a
CB
7217 Does GNU back end stuff necessary to teach it about the start of its
7218 equivalent of a Fortran program unit. */
5ff904cd
JL
7219
7220#if FFECOM_targetCURRENT == FFECOM_targetGCC
7221static void
c7e4ee3a 7222ffecom_start_progunit_ ()
5ff904cd 7223{
c7e4ee3a
CB
7224 ffesymbol fn = ffecom_primary_entry_;
7225 ffebld arglist;
7226 tree id; /* Identifier (name) of function. */
7227 tree type; /* Type of function. */
7228 tree result; /* Result of function. */
7229 ffeinfoBasictype bt;
7230 ffeinfoKindtype kt;
7231 ffeglobal g;
7232 ffeglobalType gt;
7233 ffeglobalType egt = FFEGLOBAL_type;
7234 bool charfunc;
7235 bool cmplxfunc;
7236 bool altentries = (ffecom_num_entrypoints_ != 0);
7237 bool multi
7238 = altentries
7239 && (ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
7240 && (ffecom_master_bt_ == FFEINFO_basictypeNONE);
7241 bool main_program = FALSE;
7242 int old_lineno = lineno;
7243 char *old_input_filename = input_filename;
7244 int yes;
5ff904cd 7245
c7e4ee3a
CB
7246 assert (fn != NULL);
7247 assert (ffesymbol_hook (fn).decl_tree == NULL_TREE);
5ff904cd 7248
c7e4ee3a
CB
7249 input_filename = ffesymbol_where_filename (fn);
7250 lineno = ffesymbol_where_filelinenum (fn);
5ff904cd 7251
c7e4ee3a
CB
7252 /* c-parse.y indeed does call suspend_momentary and not only ignores the
7253 return value, but also never calls resume_momentary, when starting an
7254 outer function (see "fndef:", "setspecs:", and so on). So g77 does the
7255 same thing. It shouldn't be a problem since start_function calls
7256 temporary_allocation, but it might be necessary. If it causes a problem
7257 here, then maybe there's a bug lurking in gcc. NOTE: This identical
7258 comment appears twice in thist file. */
7259
7260 suspend_momentary ();
7261
7262 switch (ffecom_primary_entry_kind_)
7263 {
7264 case FFEINFO_kindPROGRAM:
7265 main_program = TRUE;
7266 gt = FFEGLOBAL_typeMAIN;
7267 bt = FFEINFO_basictypeNONE;
7268 kt = FFEINFO_kindtypeNONE;
7269 type = ffecom_tree_fun_type_void;
7270 charfunc = FALSE;
7271 cmplxfunc = FALSE;
7272 break;
7273
7274 case FFEINFO_kindBLOCKDATA:
7275 gt = FFEGLOBAL_typeBDATA;
7276 bt = FFEINFO_basictypeNONE;
7277 kt = FFEINFO_kindtypeNONE;
7278 type = ffecom_tree_fun_type_void;
7279 charfunc = FALSE;
7280 cmplxfunc = FALSE;
7281 break;
7282
7283 case FFEINFO_kindFUNCTION:
7284 gt = FFEGLOBAL_typeFUNC;
7285 egt = FFEGLOBAL_typeEXT;
7286 bt = ffesymbol_basictype (fn);
7287 kt = ffesymbol_kindtype (fn);
7288 if (bt == FFEINFO_basictypeNONE)
7289 {
7290 ffeimplic_establish_symbol (fn);
7291 if (ffesymbol_funcresult (fn) != NULL)
7292 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
7293 bt = ffesymbol_basictype (fn);
7294 kt = ffesymbol_kindtype (fn);
7295 }
7296
7297 if (multi)
7298 charfunc = cmplxfunc = FALSE;
7299 else if (bt == FFEINFO_basictypeCHARACTER)
7300 charfunc = TRUE, cmplxfunc = FALSE;
7301 else if ((bt == FFEINFO_basictypeCOMPLEX)
7302 && ffesymbol_is_f2c (fn)
7303 && !altentries)
7304 charfunc = FALSE, cmplxfunc = TRUE;
7305 else
7306 charfunc = cmplxfunc = FALSE;
7307
7308 if (multi || charfunc)
7309 type = ffecom_tree_fun_type_void;
7310 else if (ffesymbol_is_f2c (fn) && !altentries)
7311 type = ffecom_tree_fun_type[bt][kt];
7312 else
7313 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
7314
7315 if ((type == NULL_TREE)
7316 || (TREE_TYPE (type) == NULL_TREE))
7317 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
7318 break;
7319
7320 case FFEINFO_kindSUBROUTINE:
7321 gt = FFEGLOBAL_typeSUBR;
7322 egt = FFEGLOBAL_typeEXT;
7323 bt = FFEINFO_basictypeNONE;
7324 kt = FFEINFO_kindtypeNONE;
7325 if (ffecom_is_altreturning_)
7326 type = ffecom_tree_subr_type;
7327 else
7328 type = ffecom_tree_fun_type_void;
7329 charfunc = FALSE;
7330 cmplxfunc = FALSE;
7331 break;
5ff904cd 7332
c7e4ee3a
CB
7333 default:
7334 assert ("say what??" == NULL);
7335 /* Fall through. */
7336 case FFEINFO_kindANY:
7337 gt = FFEGLOBAL_typeANY;
7338 bt = FFEINFO_basictypeNONE;
7339 kt = FFEINFO_kindtypeNONE;
7340 type = error_mark_node;
7341 charfunc = FALSE;
7342 cmplxfunc = FALSE;
7343 break;
7344 }
5ff904cd 7345
c7e4ee3a 7346 if (altentries)
5ff904cd 7347 {
c7e4ee3a
CB
7348 id = ffecom_get_invented_identifier ("__g77_masterfun_%s",
7349 ffesymbol_text (fn),
7350 -1);
7351 }
7352#if FFETARGET_isENFORCED_MAIN
7353 else if (main_program)
7354 id = get_identifier (FFETARGET_nameENFORCED_MAIN_NAME);
7355#endif
7356 else
7357 id = ffecom_get_external_identifier_ (fn);
5ff904cd 7358
c7e4ee3a
CB
7359 start_function (id,
7360 type,
7361 0, /* nested/inline */
7362 !altentries); /* TREE_PUBLIC */
5ff904cd 7363
c7e4ee3a 7364 TREE_USED (current_function_decl) = 1; /* Avoid spurious warning if altentries. */
5ff904cd 7365
c7e4ee3a
CB
7366 if (!altentries
7367 && ((g = ffesymbol_global (fn)) != NULL)
7368 && ((ffeglobal_type (g) == gt)
7369 || (ffeglobal_type (g) == egt)))
7370 {
7371 ffeglobal_set_hook (g, current_function_decl);
7372 }
5ff904cd 7373
c7e4ee3a 7374 yes = suspend_momentary ();
5ff904cd 7375
c7e4ee3a
CB
7376 /* Arg handling needs exec-transitioned ffesymbols to work with. But
7377 exec-transitioning needs current_function_decl to be filled in. So we
7378 do these things in two phases. */
5ff904cd 7379
c7e4ee3a
CB
7380 if (altentries)
7381 { /* 1st arg identifies which entrypoint. */
7382 ffecom_which_entrypoint_decl_
7383 = build_decl (PARM_DECL,
7384 ffecom_get_invented_identifier ("__g77_%s",
7385 "which_entrypoint",
7386 -1),
7387 integer_type_node);
7388 push_parm_decl (ffecom_which_entrypoint_decl_);
7389 }
5ff904cd 7390
c7e4ee3a
CB
7391 if (charfunc
7392 || cmplxfunc
7393 || multi)
7394 { /* Arg for result (return value). */
7395 tree type;
7396 tree length;
5ff904cd 7397
c7e4ee3a
CB
7398 if (charfunc)
7399 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
7400 else if (cmplxfunc)
7401 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
7402 else
7403 type = ffecom_multi_type_node_;
5ff904cd 7404
c7e4ee3a
CB
7405 result = ffecom_get_invented_identifier ("__g77_%s",
7406 "result", -1);
5ff904cd 7407
c7e4ee3a 7408 /* Make length arg _and_ enhance type info for CHAR arg itself. */
5ff904cd 7409
c7e4ee3a
CB
7410 if (charfunc)
7411 length = ffecom_char_enhance_arg_ (&type, fn);
7412 else
7413 length = NULL_TREE; /* Not ref'd if !charfunc. */
5ff904cd 7414
c7e4ee3a
CB
7415 type = build_pointer_type (type);
7416 result = build_decl (PARM_DECL, result, type);
5ff904cd 7417
c7e4ee3a
CB
7418 push_parm_decl (result);
7419 if (multi)
7420 ffecom_multi_retval_ = result;
7421 else
7422 ffecom_func_result_ = result;
5ff904cd 7423
c7e4ee3a
CB
7424 if (charfunc)
7425 {
7426 push_parm_decl (length);
7427 ffecom_func_length_ = length;
7428 }
5ff904cd
JL
7429 }
7430
c7e4ee3a
CB
7431 if (ffecom_primary_entry_is_proc_)
7432 {
7433 if (altentries)
7434 arglist = ffecom_master_arglist_;
7435 else
7436 arglist = ffesymbol_dummyargs (fn);
7437 ffecom_push_dummy_decls_ (arglist, FALSE);
7438 }
5ff904cd 7439
c7e4ee3a 7440 resume_momentary (yes);
5ff904cd 7441
c7e4ee3a
CB
7442 if (TREE_CODE (current_function_decl) != ERROR_MARK)
7443 store_parm_decls (main_program ? 1 : 0);
5ff904cd 7444
c7e4ee3a
CB
7445 ffecom_start_compstmt ();
7446 /* Disallow temp vars at this level. */
7447 current_binding_level->prep_state = 2;
5ff904cd 7448
c7e4ee3a
CB
7449 lineno = old_lineno;
7450 input_filename = old_input_filename;
5ff904cd 7451
c7e4ee3a
CB
7452 /* This handles any symbols still untransformed, in case -g specified.
7453 This used to be done in ffecom_finish_progunit, but it turns out to
7454 be necessary to do it here so that statement functions are
7455 expanded before code. But don't bother for BLOCK DATA. */
5ff904cd 7456
c7e4ee3a
CB
7457 if (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
7458 ffesymbol_drive (ffecom_finish_symbol_transform_);
5ff904cd
JL
7459}
7460
7461#endif
c7e4ee3a 7462/* ffecom_sym_transform_ -- Transform FFE sym into backend sym
5ff904cd 7463
c7e4ee3a
CB
7464 ffesymbol s;
7465 ffecom_sym_transform_(s);
7466
7467 The ffesymbol_hook info for s is updated with appropriate backend info
7468 on the symbol. */
7469
7470#if FFECOM_targetCURRENT == FFECOM_targetGCC
7471static ffesymbol
7472ffecom_sym_transform_ (ffesymbol s)
7473{
7474 tree t; /* Transformed thingy. */
7475 tree tlen; /* Length if CHAR*(*). */
7476 bool addr; /* Is t the address of the thingy? */
7477 ffeinfoBasictype bt;
7478 ffeinfoKindtype kt;
7479 ffeglobal g;
7480 int yes;
7481 int old_lineno = lineno;
7482 char *old_input_filename = input_filename;
5ff904cd 7483
c7e4ee3a
CB
7484 /* Must ensure special ASSIGN variables are declared at top of outermost
7485 block, else they'll end up in the innermost block when their first
7486 ASSIGN is seen, which leaves them out of scope when they're the
7487 subject of a GOTO or I/O statement.
5ff904cd 7488
c7e4ee3a
CB
7489 We make this variable even if -fugly-assign. Just let it go unused,
7490 in case it turns out there are cases where we really want to use this
7491 variable anyway (e.g. ASSIGN to INTEGER*2 variable). */
5ff904cd 7492
c7e4ee3a
CB
7493 if (! ffecom_transform_only_dummies_
7494 && ffesymbol_assigned (s)
7495 && ! ffesymbol_hook (s).assign_tree)
7496 s = ffecom_sym_transform_assign_ (s);
5ff904cd 7497
c7e4ee3a 7498 if (ffesymbol_sfdummyparent (s) == NULL)
5ff904cd 7499 {
c7e4ee3a
CB
7500 input_filename = ffesymbol_where_filename (s);
7501 lineno = ffesymbol_where_filelinenum (s);
7502 }
7503 else
7504 {
7505 ffesymbol sf = ffesymbol_sfdummyparent (s);
5ff904cd 7506
c7e4ee3a
CB
7507 input_filename = ffesymbol_where_filename (sf);
7508 lineno = ffesymbol_where_filelinenum (sf);
7509 }
6d433196 7510
c7e4ee3a
CB
7511 bt = ffeinfo_basictype (ffebld_info (s));
7512 kt = ffeinfo_kindtype (ffebld_info (s));
5ff904cd 7513
c7e4ee3a
CB
7514 t = NULL_TREE;
7515 tlen = NULL_TREE;
7516 addr = FALSE;
5ff904cd 7517
c7e4ee3a
CB
7518 switch (ffesymbol_kind (s))
7519 {
7520 case FFEINFO_kindNONE:
7521 switch (ffesymbol_where (s))
7522 {
7523 case FFEINFO_whereDUMMY: /* Subroutine or function. */
7524 assert (ffecom_transform_only_dummies_);
5ff904cd 7525
c7e4ee3a
CB
7526 /* Before 0.4, this could be ENTITY/DUMMY, but see
7527 ffestu_sym_end_transition -- no longer true (in particular, if
7528 it could be an ENTITY, it _will_ be made one, so that
7529 possibility won't come through here). So we never make length
7530 arg for CHARACTER type. */
5ff904cd 7531
c7e4ee3a
CB
7532 t = build_decl (PARM_DECL,
7533 ffecom_get_identifier_ (ffesymbol_text (s)),
7534 ffecom_tree_ptr_to_subr_type);
7535#if BUILT_FOR_270
7536 DECL_ARTIFICIAL (t) = 1;
7537#endif
7538 addr = TRUE;
7539 break;
5ff904cd 7540
c7e4ee3a
CB
7541 case FFEINFO_whereGLOBAL: /* Subroutine or function. */
7542 assert (!ffecom_transform_only_dummies_);
5ff904cd 7543
c7e4ee3a
CB
7544 if (((g = ffesymbol_global (s)) != NULL)
7545 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7546 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7547 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
7548 && (ffeglobal_hook (g) != NULL_TREE)
7549 && ffe_is_globals ())
7550 {
7551 t = ffeglobal_hook (g);
7552 break;
7553 }
5ff904cd 7554
c7e4ee3a
CB
7555 push_obstacks_nochange ();
7556 end_temporary_allocation ();
5ff904cd 7557
c7e4ee3a
CB
7558 t = build_decl (FUNCTION_DECL,
7559 ffecom_get_external_identifier_ (s),
7560 ffecom_tree_subr_type); /* Assume subr. */
7561 DECL_EXTERNAL (t) = 1;
7562 TREE_PUBLIC (t) = 1;
5ff904cd 7563
c7e4ee3a
CB
7564 t = start_decl (t, FALSE);
7565 finish_decl (t, NULL_TREE, FALSE);
795232f7 7566
c7e4ee3a
CB
7567 if ((g != NULL)
7568 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7569 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7570 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
7571 ffeglobal_set_hook (g, t);
5ff904cd 7572
c7e4ee3a
CB
7573 resume_temporary_allocation ();
7574 pop_obstacks ();
5ff904cd 7575
c7e4ee3a 7576 break;
5ff904cd 7577
c7e4ee3a
CB
7578 default:
7579 assert ("NONE where unexpected" == NULL);
7580 /* Fall through. */
7581 case FFEINFO_whereANY:
7582 break;
7583 }
5ff904cd 7584 break;
5ff904cd 7585
c7e4ee3a
CB
7586 case FFEINFO_kindENTITY:
7587 switch (ffeinfo_where (ffesymbol_info (s)))
7588 {
5ff904cd 7589
c7e4ee3a
CB
7590 case FFEINFO_whereCONSTANT:
7591 /* ~~Debugging info needed? */
7592 assert (!ffecom_transform_only_dummies_);
7593 t = error_mark_node; /* Shouldn't ever see this in expr. */
7594 break;
5ff904cd 7595
c7e4ee3a
CB
7596 case FFEINFO_whereLOCAL:
7597 assert (!ffecom_transform_only_dummies_);
5ff904cd 7598
c7e4ee3a
CB
7599 {
7600 ffestorag st = ffesymbol_storage (s);
7601 tree type;
5ff904cd 7602
c7e4ee3a
CB
7603 if ((st != NULL)
7604 && (ffestorag_size (st) == 0))
7605 {
7606 t = error_mark_node;
7607 break;
7608 }
5ff904cd 7609
c7e4ee3a
CB
7610 yes = suspend_momentary ();
7611 type = ffecom_type_localvar_ (s, bt, kt);
7612 resume_momentary (yes);
5ff904cd 7613
c7e4ee3a
CB
7614 if (type == error_mark_node)
7615 {
7616 t = error_mark_node;
7617 break;
7618 }
5ff904cd 7619
c7e4ee3a
CB
7620 if ((st != NULL)
7621 && (ffestorag_parent (st) != NULL))
7622 { /* Child of EQUIVALENCE parent. */
7623 ffestorag est;
7624 tree et;
7625 int yes;
7626 ffetargetOffset offset;
5ff904cd 7627
c7e4ee3a
CB
7628 est = ffestorag_parent (st);
7629 ffecom_transform_equiv_ (est);
5ff904cd 7630
c7e4ee3a
CB
7631 et = ffestorag_hook (est);
7632 assert (et != NULL_TREE);
5ff904cd 7633
c7e4ee3a
CB
7634 if (! TREE_STATIC (et))
7635 put_var_into_stack (et);
5ff904cd 7636
c7e4ee3a 7637 yes = suspend_momentary ();
5ff904cd 7638
c7e4ee3a
CB
7639 offset = ffestorag_modulo (est)
7640 + ffestorag_offset (ffesymbol_storage (s))
7641 - ffestorag_offset (est);
5ff904cd 7642
c7e4ee3a 7643 ffecom_debug_kludge_ (et, "EQUIVALENCE", s, type, offset);
5ff904cd 7644
c7e4ee3a 7645 /* (t_type *) (((char *) &et) + offset) */
5ff904cd 7646
c7e4ee3a
CB
7647 t = convert (string_type_node, /* (char *) */
7648 ffecom_1 (ADDR_EXPR,
7649 build_pointer_type (TREE_TYPE (et)),
7650 et));
7651 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
7652 t,
7653 build_int_2 (offset, 0));
7654 t = convert (build_pointer_type (type),
7655 t);
d50108c7 7656 TREE_CONSTANT (t) = staticp (et);
5ff904cd 7657
c7e4ee3a 7658 addr = TRUE;
5ff904cd 7659
c7e4ee3a
CB
7660 resume_momentary (yes);
7661 }
7662 else
7663 {
7664 tree initexpr;
7665 bool init = ffesymbol_is_init (s);
5ff904cd 7666
c7e4ee3a 7667 yes = suspend_momentary ();
5ff904cd 7668
c7e4ee3a
CB
7669 t = build_decl (VAR_DECL,
7670 ffecom_get_identifier_ (ffesymbol_text (s)),
7671 type);
5ff904cd 7672
c7e4ee3a
CB
7673 if (init
7674 || ffesymbol_namelisted (s)
7675#ifdef FFECOM_sizeMAXSTACKITEM
7676 || ((st != NULL)
7677 && (ffestorag_size (st) > FFECOM_sizeMAXSTACKITEM))
7678#endif
7679 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
7680 && (ffecom_primary_entry_kind_
7681 != FFEINFO_kindBLOCKDATA)
7682 && (ffesymbol_is_save (s) || ffe_is_saveall ())))
7683 TREE_STATIC (t) = !ffesymbol_attr (s, FFESYMBOL_attrADJUSTABLE);
7684 else
7685 TREE_STATIC (t) = 0; /* No need to make static. */
5ff904cd 7686
c7e4ee3a
CB
7687 if (init || ffe_is_init_local_zero ())
7688 DECL_INITIAL (t) = error_mark_node;
5ff904cd 7689
c7e4ee3a
CB
7690 /* Keep -Wunused from complaining about var if it
7691 is used as sfunc arg or DATA implied-DO. */
7692 if (ffesymbol_attrs (s) & FFESYMBOL_attrsSFARG)
7693 DECL_IN_SYSTEM_HEADER (t) = 1;
5ff904cd 7694
c7e4ee3a 7695 t = start_decl (t, FALSE);
5ff904cd 7696
c7e4ee3a
CB
7697 if (init)
7698 {
7699 if (ffesymbol_init (s) != NULL)
7700 initexpr = ffecom_expr (ffesymbol_init (s));
7701 else
7702 initexpr = ffecom_init_zero_ (t);
7703 }
7704 else if (ffe_is_init_local_zero ())
7705 initexpr = ffecom_init_zero_ (t);
7706 else
7707 initexpr = NULL_TREE; /* Not ref'd if !init. */
5ff904cd 7708
c7e4ee3a 7709 finish_decl (t, initexpr, FALSE);
5ff904cd 7710
c7e4ee3a
CB
7711 if ((st != NULL) && (DECL_SIZE (t) != error_mark_node))
7712 {
7713 tree size_tree;
5ff904cd 7714
c7e4ee3a
CB
7715 size_tree = size_binop (CEIL_DIV_EXPR,
7716 DECL_SIZE (t),
7717 size_int (BITS_PER_UNIT));
7718 assert (TREE_INT_CST_HIGH (size_tree) == 0);
7719 assert (TREE_INT_CST_LOW (size_tree) == ffestorag_size (st));
7720 }
5ff904cd 7721
c7e4ee3a
CB
7722 resume_momentary (yes);
7723 }
7724 }
5ff904cd 7725 break;
5ff904cd 7726
c7e4ee3a
CB
7727 case FFEINFO_whereRESULT:
7728 assert (!ffecom_transform_only_dummies_);
5ff904cd 7729
c7e4ee3a
CB
7730 if (bt == FFEINFO_basictypeCHARACTER)
7731 { /* Result is already in list of dummies, use
7732 it (& length). */
7733 t = ffecom_func_result_;
7734 tlen = ffecom_func_length_;
7735 addr = TRUE;
7736 break;
7737 }
7738 if ((ffecom_num_entrypoints_ == 0)
7739 && (bt == FFEINFO_basictypeCOMPLEX)
7740 && (ffesymbol_is_f2c (ffecom_primary_entry_)))
7741 { /* Result is already in list of dummies, use
7742 it. */
7743 t = ffecom_func_result_;
7744 addr = TRUE;
7745 break;
7746 }
7747 if (ffecom_func_result_ != NULL_TREE)
7748 {
7749 t = ffecom_func_result_;
7750 break;
7751 }
7752 if ((ffecom_num_entrypoints_ != 0)
7753 && (ffecom_master_bt_ == FFEINFO_basictypeNONE))
7754 {
7755 yes = suspend_momentary ();
5ff904cd 7756
c7e4ee3a
CB
7757 assert (ffecom_multi_retval_ != NULL_TREE);
7758 t = ffecom_1 (INDIRECT_REF, ffecom_multi_type_node_,
7759 ffecom_multi_retval_);
7760 t = ffecom_2 (COMPONENT_REF, ffecom_tree_type[bt][kt],
7761 t, ffecom_multi_fields_[bt][kt]);
5ff904cd 7762
c7e4ee3a
CB
7763 resume_momentary (yes);
7764 break;
7765 }
5ff904cd 7766
c7e4ee3a 7767 yes = suspend_momentary ();
5ff904cd 7768
c7e4ee3a
CB
7769 t = build_decl (VAR_DECL,
7770 ffecom_get_identifier_ (ffesymbol_text (s)),
7771 ffecom_tree_type[bt][kt]);
7772 TREE_STATIC (t) = 0; /* Put result on stack. */
7773 t = start_decl (t, FALSE);
7774 finish_decl (t, NULL_TREE, FALSE);
5ff904cd 7775
c7e4ee3a 7776 ffecom_func_result_ = t;
5ff904cd 7777
c7e4ee3a
CB
7778 resume_momentary (yes);
7779 break;
5ff904cd 7780
c7e4ee3a
CB
7781 case FFEINFO_whereDUMMY:
7782 {
7783 tree type;
7784 ffebld dl;
7785 ffebld dim;
7786 tree low;
7787 tree high;
7788 tree old_sizes;
7789 bool adjustable = FALSE; /* Conditionally adjustable? */
5ff904cd 7790
c7e4ee3a
CB
7791 type = ffecom_tree_type[bt][kt];
7792 if (ffesymbol_sfdummyparent (s) != NULL)
7793 {
7794 if (current_function_decl == ffecom_outer_function_decl_)
7795 { /* Exec transition before sfunc
7796 context; get it later. */
7797 break;
7798 }
7799 t = ffecom_get_identifier_ (ffesymbol_text
7800 (ffesymbol_sfdummyparent (s)));
7801 }
7802 else
7803 t = ffecom_get_identifier_ (ffesymbol_text (s));
5ff904cd 7804
c7e4ee3a 7805 assert (ffecom_transform_only_dummies_);
5ff904cd 7806
c7e4ee3a
CB
7807 old_sizes = get_pending_sizes ();
7808 put_pending_sizes (old_sizes);
5ff904cd 7809
c7e4ee3a
CB
7810 if (bt == FFEINFO_basictypeCHARACTER)
7811 tlen = ffecom_char_enhance_arg_ (&type, s);
7812 type = ffecom_check_size_overflow_ (s, type, TRUE);
5ff904cd 7813
c7e4ee3a
CB
7814 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
7815 {
7816 if (type == error_mark_node)
7817 break;
5ff904cd 7818
c7e4ee3a
CB
7819 dim = ffebld_head (dl);
7820 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
7821 if ((ffebld_left (dim) == NULL) || ffecom_doing_entry_)
7822 low = ffecom_integer_one_node;
7823 else
7824 low = ffecom_expr (ffebld_left (dim));
7825 assert (ffebld_right (dim) != NULL);
7826 if ((ffebld_op (ffebld_right (dim)) == FFEBLD_opSTAR)
7827 || ffecom_doing_entry_)
7828 {
7829 /* Used to just do high=low. But for ffecom_tree_
7830 canonize_ref_, it probably is important to correctly
7831 assess the size. E.g. given COMPLEX C(*),CFUNC and
7832 C(2)=CFUNC(C), overlap can happen, while it can't
7833 for, say, C(1)=CFUNC(C(2)). */
7834 /* Even more recently used to set to INT_MAX, but that
7835 broke when some overflow checking went into the back
7836 end. Now we just leave the upper bound unspecified. */
7837 high = NULL;
7838 }
7839 else
7840 high = ffecom_expr (ffebld_right (dim));
5ff904cd 7841
c7e4ee3a
CB
7842 /* Determine whether array is conditionally adjustable,
7843 to decide whether back-end magic is needed.
5ff904cd 7844
c7e4ee3a
CB
7845 Normally the front end uses the back-end function
7846 variable_size to wrap SAVE_EXPR's around expressions
7847 affecting the size/shape of an array so that the
7848 size/shape info doesn't change during execution
7849 of the compiled code even though variables and
7850 functions referenced in those expressions might.
5ff904cd 7851
c7e4ee3a
CB
7852 variable_size also makes sure those saved expressions
7853 get evaluated immediately upon entry to the
7854 compiled procedure -- the front end normally doesn't
7855 have to worry about that.
3cf0cea4 7856
c7e4ee3a
CB
7857 However, there is a problem with this that affects
7858 g77's implementation of entry points, and that is
7859 that it is _not_ true that each invocation of the
7860 compiled procedure is permitted to evaluate
7861 array size/shape info -- because it is possible
7862 that, for some invocations, that info is invalid (in
7863 which case it is "promised" -- i.e. a violation of
7864 the Fortran standard -- that the compiled code
7865 won't reference the array or its size/shape
7866 during that particular invocation).
5ff904cd 7867
c7e4ee3a 7868 To phrase this in C terms, consider this gcc function:
5ff904cd 7869
c7e4ee3a
CB
7870 void foo (int *n, float (*a)[*n])
7871 {
7872 // a is "pointer to array ...", fyi.
7873 }
5ff904cd 7874
c7e4ee3a
CB
7875 Suppose that, for some invocations, it is permitted
7876 for a caller of foo to do this:
5ff904cd 7877
c7e4ee3a 7878 foo (NULL, NULL);
5ff904cd 7879
c7e4ee3a
CB
7880 Now the _written_ code for foo can take such a call
7881 into account by either testing explicitly for whether
7882 (a == NULL) || (n == NULL) -- presumably it is
7883 not permitted to reference *a in various fashions
7884 if (n == NULL) I suppose -- or it can avoid it by
7885 looking at other info (other arguments, static/global
7886 data, etc.).
5ff904cd 7887
c7e4ee3a
CB
7888 However, this won't work in gcc 2.5.8 because it'll
7889 automatically emit the code to save the "*n"
7890 expression, which'll yield a NULL dereference for
7891 the "foo (NULL, NULL)" call, something the code
7892 for foo cannot prevent.
5ff904cd 7893
c7e4ee3a
CB
7894 g77 definitely needs to avoid executing such
7895 code anytime the pointer to the adjustable array
7896 is NULL, because even if its bounds expressions
7897 don't have any references to possible "absent"
7898 variables like "*n" -- say all variable references
7899 are to COMMON variables, i.e. global (though in C,
7900 local static could actually make sense) -- the
7901 expressions could yield other run-time problems
7902 for allowably "dead" values in those variables.
5ff904cd 7903
c7e4ee3a
CB
7904 For example, let's consider a more complicated
7905 version of foo:
5ff904cd 7906
c7e4ee3a
CB
7907 extern int i;
7908 extern int j;
5ff904cd 7909
c7e4ee3a
CB
7910 void foo (float (*a)[i/j])
7911 {
7912 ...
7913 }
5ff904cd 7914
c7e4ee3a
CB
7915 The above is (essentially) quite valid for Fortran
7916 but, again, for a call like "foo (NULL);", it is
7917 permitted for i and j to be undefined when the
7918 call is made. If j happened to be zero, for
7919 example, emitting the code to evaluate "i/j"
7920 could result in a run-time error.
5ff904cd 7921
c7e4ee3a
CB
7922 Offhand, though I don't have my F77 or F90
7923 standards handy, it might even be valid for a
7924 bounds expression to contain a function reference,
7925 in which case I doubt it is permitted for an
7926 implementation to invoke that function in the
7927 Fortran case involved here (invocation of an
7928 alternate ENTRY point that doesn't have the adjustable
7929 array as one of its arguments).
5ff904cd 7930
c7e4ee3a
CB
7931 So, the code that the compiler would normally emit
7932 to preevaluate the size/shape info for an
7933 adjustable array _must not_ be executed at run time
7934 in certain cases. Specifically, for Fortran,
7935 the case is when the pointer to the adjustable
7936 array == NULL. (For gnu-ish C, it might be nice
7937 for the source code itself to specify an expression
7938 that, if TRUE, inhibits execution of the code. Or
7939 reverse the sense for elegance.)
5ff904cd 7940
c7e4ee3a
CB
7941 (Note that g77 could use a different test than NULL,
7942 actually, since it happens to always pass an
7943 integer to the called function that specifies which
7944 entry point is being invoked. Hmm, this might
7945 solve the next problem.)
7946
7947 One way a user could, I suppose, write "foo" so
7948 it works is to insert COND_EXPR's for the
7949 size/shape info so the dangerous stuff isn't
7950 actually done, as in:
7951
7952 void foo (int *n, float (*a)[(a == NULL) ? 0 : *n])
7953 {
7954 ...
7955 }
5ff904cd 7956
c7e4ee3a
CB
7957 The next problem is that the front end needs to
7958 be able to tell the back end about the array's
7959 decl _before_ it tells it about the conditional
7960 expression to inhibit evaluation of size/shape info,
7961 as shown above.
5ff904cd 7962
c7e4ee3a
CB
7963 To solve this, the front end needs to be able
7964 to give the back end the expression to inhibit
7965 generation of the preevaluation code _after_
7966 it makes the decl for the adjustable array.
5ff904cd 7967
c7e4ee3a
CB
7968 Until then, the above example using the COND_EXPR
7969 doesn't pass muster with gcc because the "(a == NULL)"
7970 part has a reference to "a", which is still
7971 undefined at that point.
5ff904cd 7972
c7e4ee3a
CB
7973 g77 will therefore use a different mechanism in the
7974 meantime. */
5ff904cd 7975
c7e4ee3a
CB
7976 if (!adjustable
7977 && ((TREE_CODE (low) != INTEGER_CST)
7978 || (high && TREE_CODE (high) != INTEGER_CST)))
7979 adjustable = TRUE;
5ff904cd 7980
c7e4ee3a
CB
7981#if 0 /* Old approach -- see below. */
7982 if (TREE_CODE (low) != INTEGER_CST)
7983 low = ffecom_3 (COND_EXPR, integer_type_node,
7984 ffecom_adjarray_passed_ (s),
7985 low,
7986 ffecom_integer_zero_node);
5ff904cd 7987
c7e4ee3a
CB
7988 if (high && TREE_CODE (high) != INTEGER_CST)
7989 high = ffecom_3 (COND_EXPR, integer_type_node,
7990 ffecom_adjarray_passed_ (s),
7991 high,
7992 ffecom_integer_zero_node);
7993#endif
5ff904cd 7994
c7e4ee3a
CB
7995 /* ~~~gcc/stor-layout.c (layout_type) should do this,
7996 probably. Fixes 950302-1.f. */
5ff904cd 7997
c7e4ee3a
CB
7998 if (TREE_CODE (low) != INTEGER_CST)
7999 low = variable_size (low);
5ff904cd 8000
c7e4ee3a
CB
8001 /* ~~~Similarly, this fixes dumb0.f. The C front end
8002 does this, which is why dumb0.c would work. */
5ff904cd 8003
c7e4ee3a
CB
8004 if (high && TREE_CODE (high) != INTEGER_CST)
8005 high = variable_size (high);
5ff904cd 8006
c7e4ee3a
CB
8007 type
8008 = build_array_type
8009 (type,
8010 build_range_type (ffecom_integer_type_node,
8011 low, high));
8012 type = ffecom_check_size_overflow_ (s, type, TRUE);
8013 }
5ff904cd 8014
c7e4ee3a
CB
8015 if (type == error_mark_node)
8016 {
8017 t = error_mark_node;
8018 break;
8019 }
5ff904cd 8020
c7e4ee3a
CB
8021 if ((ffesymbol_sfdummyparent (s) == NULL)
8022 || (ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER))
8023 {
8024 type = build_pointer_type (type);
8025 addr = TRUE;
8026 }
5ff904cd 8027
c7e4ee3a 8028 t = build_decl (PARM_DECL, t, type);
5ff904cd 8029#if BUILT_FOR_270
c7e4ee3a 8030 DECL_ARTIFICIAL (t) = 1;
5ff904cd 8031#endif
5ff904cd 8032
c7e4ee3a
CB
8033 /* If this arg is present in every entry point's list of
8034 dummy args, then we're done. */
5ff904cd 8035
c7e4ee3a
CB
8036 if (ffesymbol_numentries (s)
8037 == (ffecom_num_entrypoints_ + 1))
5ff904cd 8038 break;
5ff904cd 8039
c7e4ee3a 8040#if 1
5ff904cd 8041
c7e4ee3a
CB
8042 /* If variable_size in stor-layout has been called during
8043 the above, then get_pending_sizes should have the
8044 yet-to-be-evaluated saved expressions pending.
8045 Make the whole lot of them get emitted, conditionally
8046 on whether the array decl ("t" above) is not NULL. */
5ff904cd 8047
c7e4ee3a
CB
8048 {
8049 tree sizes = get_pending_sizes ();
8050 tree tem;
5ff904cd 8051
c7e4ee3a
CB
8052 for (tem = sizes;
8053 tem != old_sizes;
8054 tem = TREE_CHAIN (tem))
8055 {
8056 tree temv = TREE_VALUE (tem);
5ff904cd 8057
c7e4ee3a
CB
8058 if (sizes == tem)
8059 sizes = temv;
8060 else
8061 sizes
8062 = ffecom_2 (COMPOUND_EXPR,
8063 TREE_TYPE (sizes),
8064 temv,
8065 sizes);
8066 }
5ff904cd 8067
c7e4ee3a
CB
8068 if (sizes != tem)
8069 {
8070 sizes
8071 = ffecom_3 (COND_EXPR,
8072 TREE_TYPE (sizes),
8073 ffecom_2 (NE_EXPR,
8074 integer_type_node,
8075 t,
8076 null_pointer_node),
8077 sizes,
8078 convert (TREE_TYPE (sizes),
8079 integer_zero_node));
8080 sizes = ffecom_save_tree (sizes);
5ff904cd 8081
c7e4ee3a
CB
8082 sizes
8083 = tree_cons (NULL_TREE, sizes, tem);
8084 }
5ff904cd 8085
c7e4ee3a
CB
8086 if (sizes)
8087 put_pending_sizes (sizes);
8088 }
5ff904cd 8089
c7e4ee3a
CB
8090#else
8091#if 0
8092 if (adjustable
8093 && (ffesymbol_numentries (s)
8094 != ffecom_num_entrypoints_ + 1))
8095 DECL_SOMETHING (t)
8096 = ffecom_2 (NE_EXPR, integer_type_node,
8097 t,
8098 null_pointer_node);
8099#else
8100#if 0
8101 if (adjustable
8102 && (ffesymbol_numentries (s)
8103 != ffecom_num_entrypoints_ + 1))
8104 {
8105 ffebad_start (FFEBAD_MISSING_ADJARRAY_UNSUPPORTED);
8106 ffebad_here (0, ffesymbol_where_line (s),
8107 ffesymbol_where_column (s));
8108 ffebad_string (ffesymbol_text (s));
8109 ffebad_finish ();
8110 }
8111#endif
8112#endif
8113#endif
8114 }
5ff904cd
JL
8115 break;
8116
c7e4ee3a 8117 case FFEINFO_whereCOMMON:
5ff904cd 8118 {
c7e4ee3a
CB
8119 ffesymbol cs;
8120 ffeglobal cg;
8121 tree ct;
5ff904cd
JL
8122 ffestorag st = ffesymbol_storage (s);
8123 tree type;
c7e4ee3a 8124 int yes;
5ff904cd 8125
c7e4ee3a
CB
8126 cs = ffesymbol_common (s); /* The COMMON area itself. */
8127 if (st != NULL) /* Else not laid out. */
5ff904cd 8128 {
c7e4ee3a
CB
8129 ffecom_transform_common_ (cs);
8130 st = ffesymbol_storage (s);
5ff904cd
JL
8131 }
8132
c7e4ee3a 8133 yes = suspend_momentary ();
5ff904cd 8134
c7e4ee3a 8135 type = ffecom_type_localvar_ (s, bt, kt);
5ff904cd 8136
c7e4ee3a
CB
8137 cg = ffesymbol_global (cs); /* The global COMMON info. */
8138 if ((cg == NULL)
8139 || (ffeglobal_type (cg) != FFEGLOBAL_typeCOMMON))
8140 ct = NULL_TREE;
8141 else
8142 ct = ffeglobal_hook (cg); /* The common area's tree. */
5ff904cd 8143
c7e4ee3a
CB
8144 if ((ct == NULL_TREE)
8145 || (st == NULL)
8146 || (type == error_mark_node))
8147 t = error_mark_node;
8148 else
8149 {
8150 ffetargetOffset offset;
8151 ffestorag cst;
5ff904cd 8152
c7e4ee3a
CB
8153 cst = ffestorag_parent (st);
8154 assert (cst == ffesymbol_storage (cs));
5ff904cd 8155
c7e4ee3a
CB
8156 offset = ffestorag_modulo (cst)
8157 + ffestorag_offset (st)
8158 - ffestorag_offset (cst);
5ff904cd 8159
c7e4ee3a 8160 ffecom_debug_kludge_ (ct, "COMMON", s, type, offset);
5ff904cd 8161
c7e4ee3a 8162 /* (t_type *) (((char *) &ct) + offset) */
5ff904cd
JL
8163
8164 t = convert (string_type_node, /* (char *) */
8165 ffecom_1 (ADDR_EXPR,
c7e4ee3a
CB
8166 build_pointer_type (TREE_TYPE (ct)),
8167 ct));
5ff904cd
JL
8168 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
8169 t,
8170 build_int_2 (offset, 0));
8171 t = convert (build_pointer_type (type),
8172 t);
d50108c7 8173 TREE_CONSTANT (t) = 1;
5ff904cd
JL
8174
8175 addr = TRUE;
5ff904cd 8176 }
5ff904cd 8177
c7e4ee3a
CB
8178 resume_momentary (yes);
8179 }
8180 break;
5ff904cd 8181
c7e4ee3a
CB
8182 case FFEINFO_whereIMMEDIATE:
8183 case FFEINFO_whereGLOBAL:
8184 case FFEINFO_whereFLEETING:
8185 case FFEINFO_whereFLEETING_CADDR:
8186 case FFEINFO_whereFLEETING_IADDR:
8187 case FFEINFO_whereINTRINSIC:
8188 case FFEINFO_whereCONSTANT_SUBOBJECT:
8189 default:
8190 assert ("ENTITY where unheard of" == NULL);
8191 /* Fall through. */
8192 case FFEINFO_whereANY:
8193 t = error_mark_node;
8194 break;
8195 }
8196 break;
5ff904cd 8197
c7e4ee3a
CB
8198 case FFEINFO_kindFUNCTION:
8199 switch (ffeinfo_where (ffesymbol_info (s)))
8200 {
8201 case FFEINFO_whereLOCAL: /* Me. */
8202 assert (!ffecom_transform_only_dummies_);
8203 t = current_function_decl;
5ff904cd
JL
8204 break;
8205
c7e4ee3a 8206 case FFEINFO_whereGLOBAL:
5ff904cd
JL
8207 assert (!ffecom_transform_only_dummies_);
8208
c7e4ee3a
CB
8209 if (((g = ffesymbol_global (s)) != NULL)
8210 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8211 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8212 && (ffeglobal_hook (g) != NULL_TREE)
8213 && ffe_is_globals ())
5ff904cd 8214 {
c7e4ee3a 8215 t = ffeglobal_hook (g);
5ff904cd
JL
8216 break;
8217 }
5ff904cd 8218
c7e4ee3a
CB
8219 push_obstacks_nochange ();
8220 end_temporary_allocation ();
5ff904cd 8221
c7e4ee3a
CB
8222 if (ffesymbol_is_f2c (s)
8223 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8224 t = ffecom_tree_fun_type[bt][kt];
8225 else
8226 t = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
5ff904cd 8227
c7e4ee3a
CB
8228 t = build_decl (FUNCTION_DECL,
8229 ffecom_get_external_identifier_ (s),
8230 t);
8231 DECL_EXTERNAL (t) = 1;
8232 TREE_PUBLIC (t) = 1;
5ff904cd 8233
5ff904cd
JL
8234 t = start_decl (t, FALSE);
8235 finish_decl (t, NULL_TREE, FALSE);
8236
c7e4ee3a
CB
8237 if ((g != NULL)
8238 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8239 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8240 ffeglobal_set_hook (g, t);
8241
8242 resume_temporary_allocation ();
8243 pop_obstacks ();
5ff904cd 8244
5ff904cd
JL
8245 break;
8246
8247 case FFEINFO_whereDUMMY:
c7e4ee3a 8248 assert (ffecom_transform_only_dummies_);
5ff904cd 8249
c7e4ee3a
CB
8250 if (ffesymbol_is_f2c (s)
8251 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8252 t = ffecom_tree_ptr_to_fun_type[bt][kt];
8253 else
8254 t = build_pointer_type
8255 (build_function_type (ffecom_tree_type[bt][kt], NULL_TREE));
8256
8257 t = build_decl (PARM_DECL,
8258 ffecom_get_identifier_ (ffesymbol_text (s)),
8259 t);
8260#if BUILT_FOR_270
8261 DECL_ARTIFICIAL (t) = 1;
8262#endif
8263 addr = TRUE;
8264 break;
8265
8266 case FFEINFO_whereCONSTANT: /* Statement function. */
8267 assert (!ffecom_transform_only_dummies_);
8268 t = ffecom_gen_sfuncdef_ (s, bt, kt);
8269 break;
8270
8271 case FFEINFO_whereINTRINSIC:
8272 assert (!ffecom_transform_only_dummies_);
8273 break; /* Let actual references generate their
8274 decls. */
8275
8276 default:
8277 assert ("FUNCTION where unheard of" == NULL);
8278 /* Fall through. */
8279 case FFEINFO_whereANY:
8280 t = error_mark_node;
8281 break;
8282 }
8283 break;
8284
8285 case FFEINFO_kindSUBROUTINE:
8286 switch (ffeinfo_where (ffesymbol_info (s)))
8287 {
8288 case FFEINFO_whereLOCAL: /* Me. */
8289 assert (!ffecom_transform_only_dummies_);
8290 t = current_function_decl;
8291 break;
5ff904cd 8292
c7e4ee3a
CB
8293 case FFEINFO_whereGLOBAL:
8294 assert (!ffecom_transform_only_dummies_);
5ff904cd 8295
c7e4ee3a
CB
8296 if (((g = ffesymbol_global (s)) != NULL)
8297 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8298 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8299 && (ffeglobal_hook (g) != NULL_TREE)
8300 && ffe_is_globals ())
8301 {
8302 t = ffeglobal_hook (g);
8303 break;
8304 }
5ff904cd 8305
c7e4ee3a
CB
8306 push_obstacks_nochange ();
8307 end_temporary_allocation ();
5ff904cd 8308
c7e4ee3a
CB
8309 t = build_decl (FUNCTION_DECL,
8310 ffecom_get_external_identifier_ (s),
8311 ffecom_tree_subr_type);
8312 DECL_EXTERNAL (t) = 1;
8313 TREE_PUBLIC (t) = 1;
5ff904cd 8314
c7e4ee3a
CB
8315 t = start_decl (t, FALSE);
8316 finish_decl (t, NULL_TREE, FALSE);
5ff904cd 8317
c7e4ee3a
CB
8318 if ((g != NULL)
8319 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8320 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8321 ffeglobal_set_hook (g, t);
5ff904cd 8322
c7e4ee3a
CB
8323 resume_temporary_allocation ();
8324 pop_obstacks ();
5ff904cd 8325
c7e4ee3a 8326 break;
5ff904cd 8327
c7e4ee3a
CB
8328 case FFEINFO_whereDUMMY:
8329 assert (ffecom_transform_only_dummies_);
5ff904cd 8330
c7e4ee3a
CB
8331 t = build_decl (PARM_DECL,
8332 ffecom_get_identifier_ (ffesymbol_text (s)),
8333 ffecom_tree_ptr_to_subr_type);
8334#if BUILT_FOR_270
8335 DECL_ARTIFICIAL (t) = 1;
8336#endif
8337 addr = TRUE;
8338 break;
5ff904cd 8339
c7e4ee3a
CB
8340 case FFEINFO_whereINTRINSIC:
8341 assert (!ffecom_transform_only_dummies_);
8342 break; /* Let actual references generate their
8343 decls. */
5ff904cd 8344
c7e4ee3a
CB
8345 default:
8346 assert ("SUBROUTINE where unheard of" == NULL);
8347 /* Fall through. */
8348 case FFEINFO_whereANY:
8349 t = error_mark_node;
8350 break;
8351 }
8352 break;
5ff904cd 8353
c7e4ee3a
CB
8354 case FFEINFO_kindPROGRAM:
8355 switch (ffeinfo_where (ffesymbol_info (s)))
8356 {
8357 case FFEINFO_whereLOCAL: /* Me. */
8358 assert (!ffecom_transform_only_dummies_);
8359 t = current_function_decl;
8360 break;
5ff904cd 8361
c7e4ee3a
CB
8362 case FFEINFO_whereCOMMON:
8363 case FFEINFO_whereDUMMY:
8364 case FFEINFO_whereGLOBAL:
8365 case FFEINFO_whereRESULT:
8366 case FFEINFO_whereFLEETING:
8367 case FFEINFO_whereFLEETING_CADDR:
8368 case FFEINFO_whereFLEETING_IADDR:
8369 case FFEINFO_whereIMMEDIATE:
8370 case FFEINFO_whereINTRINSIC:
8371 case FFEINFO_whereCONSTANT:
8372 case FFEINFO_whereCONSTANT_SUBOBJECT:
8373 default:
8374 assert ("PROGRAM where unheard of" == NULL);
8375 /* Fall through. */
8376 case FFEINFO_whereANY:
8377 t = error_mark_node;
8378 break;
8379 }
8380 break;
5ff904cd 8381
c7e4ee3a
CB
8382 case FFEINFO_kindBLOCKDATA:
8383 switch (ffeinfo_where (ffesymbol_info (s)))
8384 {
8385 case FFEINFO_whereLOCAL: /* Me. */
8386 assert (!ffecom_transform_only_dummies_);
8387 t = current_function_decl;
8388 break;
5ff904cd 8389
c7e4ee3a
CB
8390 case FFEINFO_whereGLOBAL:
8391 assert (!ffecom_transform_only_dummies_);
5ff904cd 8392
c7e4ee3a
CB
8393 push_obstacks_nochange ();
8394 end_temporary_allocation ();
5ff904cd 8395
c7e4ee3a
CB
8396 t = build_decl (FUNCTION_DECL,
8397 ffecom_get_external_identifier_ (s),
8398 ffecom_tree_blockdata_type);
8399 DECL_EXTERNAL (t) = 1;
8400 TREE_PUBLIC (t) = 1;
5ff904cd 8401
c7e4ee3a
CB
8402 t = start_decl (t, FALSE);
8403 finish_decl (t, NULL_TREE, FALSE);
5ff904cd 8404
c7e4ee3a
CB
8405 resume_temporary_allocation ();
8406 pop_obstacks ();
5ff904cd 8407
c7e4ee3a 8408 break;
5ff904cd 8409
c7e4ee3a
CB
8410 case FFEINFO_whereCOMMON:
8411 case FFEINFO_whereDUMMY:
8412 case FFEINFO_whereRESULT:
8413 case FFEINFO_whereFLEETING:
8414 case FFEINFO_whereFLEETING_CADDR:
8415 case FFEINFO_whereFLEETING_IADDR:
8416 case FFEINFO_whereIMMEDIATE:
8417 case FFEINFO_whereINTRINSIC:
8418 case FFEINFO_whereCONSTANT:
8419 case FFEINFO_whereCONSTANT_SUBOBJECT:
8420 default:
8421 assert ("BLOCKDATA where unheard of" == NULL);
8422 /* Fall through. */
8423 case FFEINFO_whereANY:
8424 t = error_mark_node;
8425 break;
8426 }
8427 break;
5ff904cd 8428
c7e4ee3a
CB
8429 case FFEINFO_kindCOMMON:
8430 switch (ffeinfo_where (ffesymbol_info (s)))
8431 {
8432 case FFEINFO_whereLOCAL:
8433 assert (!ffecom_transform_only_dummies_);
8434 ffecom_transform_common_ (s);
8435 break;
8436
8437 case FFEINFO_whereNONE:
8438 case FFEINFO_whereCOMMON:
8439 case FFEINFO_whereDUMMY:
8440 case FFEINFO_whereGLOBAL:
8441 case FFEINFO_whereRESULT:
8442 case FFEINFO_whereFLEETING:
8443 case FFEINFO_whereFLEETING_CADDR:
8444 case FFEINFO_whereFLEETING_IADDR:
8445 case FFEINFO_whereIMMEDIATE:
8446 case FFEINFO_whereINTRINSIC:
8447 case FFEINFO_whereCONSTANT:
8448 case FFEINFO_whereCONSTANT_SUBOBJECT:
8449 default:
8450 assert ("COMMON where unheard of" == NULL);
8451 /* Fall through. */
8452 case FFEINFO_whereANY:
8453 t = error_mark_node;
8454 break;
8455 }
8456 break;
5ff904cd 8457
c7e4ee3a
CB
8458 case FFEINFO_kindCONSTRUCT:
8459 switch (ffeinfo_where (ffesymbol_info (s)))
8460 {
8461 case FFEINFO_whereLOCAL:
8462 assert (!ffecom_transform_only_dummies_);
8463 break;
5ff904cd 8464
c7e4ee3a
CB
8465 case FFEINFO_whereNONE:
8466 case FFEINFO_whereCOMMON:
8467 case FFEINFO_whereDUMMY:
8468 case FFEINFO_whereGLOBAL:
8469 case FFEINFO_whereRESULT:
8470 case FFEINFO_whereFLEETING:
8471 case FFEINFO_whereFLEETING_CADDR:
8472 case FFEINFO_whereFLEETING_IADDR:
8473 case FFEINFO_whereIMMEDIATE:
8474 case FFEINFO_whereINTRINSIC:
8475 case FFEINFO_whereCONSTANT:
8476 case FFEINFO_whereCONSTANT_SUBOBJECT:
8477 default:
8478 assert ("CONSTRUCT where unheard of" == NULL);
8479 /* Fall through. */
8480 case FFEINFO_whereANY:
8481 t = error_mark_node;
8482 break;
8483 }
8484 break;
5ff904cd 8485
c7e4ee3a
CB
8486 case FFEINFO_kindNAMELIST:
8487 switch (ffeinfo_where (ffesymbol_info (s)))
8488 {
8489 case FFEINFO_whereLOCAL:
8490 assert (!ffecom_transform_only_dummies_);
8491 t = ffecom_transform_namelist_ (s);
8492 break;
5ff904cd 8493
c7e4ee3a
CB
8494 case FFEINFO_whereNONE:
8495 case FFEINFO_whereCOMMON:
8496 case FFEINFO_whereDUMMY:
8497 case FFEINFO_whereGLOBAL:
8498 case FFEINFO_whereRESULT:
8499 case FFEINFO_whereFLEETING:
8500 case FFEINFO_whereFLEETING_CADDR:
8501 case FFEINFO_whereFLEETING_IADDR:
8502 case FFEINFO_whereIMMEDIATE:
8503 case FFEINFO_whereINTRINSIC:
8504 case FFEINFO_whereCONSTANT:
8505 case FFEINFO_whereCONSTANT_SUBOBJECT:
8506 default:
8507 assert ("NAMELIST where unheard of" == NULL);
8508 /* Fall through. */
8509 case FFEINFO_whereANY:
8510 t = error_mark_node;
8511 break;
8512 }
8513 break;
5ff904cd 8514
c7e4ee3a
CB
8515 default:
8516 assert ("kind unheard of" == NULL);
8517 /* Fall through. */
8518 case FFEINFO_kindANY:
8519 t = error_mark_node;
8520 break;
8521 }
5ff904cd 8522
c7e4ee3a
CB
8523 ffesymbol_hook (s).decl_tree = t;
8524 ffesymbol_hook (s).length_tree = tlen;
8525 ffesymbol_hook (s).addr = addr;
5ff904cd 8526
c7e4ee3a
CB
8527 lineno = old_lineno;
8528 input_filename = old_input_filename;
5ff904cd 8529
c7e4ee3a
CB
8530 return s;
8531}
5ff904cd 8532
5ff904cd 8533#endif
c7e4ee3a 8534/* Transform into ASSIGNable symbol.
5ff904cd 8535
c7e4ee3a
CB
8536 Symbol has already been transformed, but for whatever reason, the
8537 resulting decl_tree has been deemed not usable for an ASSIGN target.
8538 (E.g. it isn't wide enough to hold a pointer.) So, here we invent
8539 another local symbol of type void * and stuff that in the assign_tree
8540 argument. The F77/F90 standards allow this implementation. */
5ff904cd 8541
c7e4ee3a
CB
8542#if FFECOM_targetCURRENT == FFECOM_targetGCC
8543static ffesymbol
8544ffecom_sym_transform_assign_ (ffesymbol s)
8545{
8546 tree t; /* Transformed thingy. */
8547 int yes;
8548 int old_lineno = lineno;
8549 char *old_input_filename = input_filename;
5ff904cd 8550
c7e4ee3a
CB
8551 if (ffesymbol_sfdummyparent (s) == NULL)
8552 {
8553 input_filename = ffesymbol_where_filename (s);
8554 lineno = ffesymbol_where_filelinenum (s);
8555 }
8556 else
8557 {
8558 ffesymbol sf = ffesymbol_sfdummyparent (s);
5ff904cd 8559
c7e4ee3a
CB
8560 input_filename = ffesymbol_where_filename (sf);
8561 lineno = ffesymbol_where_filelinenum (sf);
8562 }
5ff904cd 8563
c7e4ee3a 8564 assert (!ffecom_transform_only_dummies_);
5ff904cd 8565
c7e4ee3a 8566 yes = suspend_momentary ();
5ff904cd 8567
c7e4ee3a
CB
8568 t = build_decl (VAR_DECL,
8569 ffecom_get_invented_identifier ("__g77_ASSIGN_%s",
8570 ffesymbol_text (s),
8571 -1),
8572 TREE_TYPE (null_pointer_node));
5ff904cd 8573
c7e4ee3a
CB
8574 switch (ffesymbol_where (s))
8575 {
8576 case FFEINFO_whereLOCAL:
8577 /* Unlike for regular vars, SAVE status is easy to determine for
8578 ASSIGNed vars, since there's no initialization, there's no
8579 effective storage association (so "SAVE J" does not apply to
8580 K even given "EQUIVALENCE (J,K)"), there's no size issue
8581 to worry about, etc. */
8582 if ((ffesymbol_is_save (s) || ffe_is_saveall ())
8583 && (ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8584 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA))
8585 TREE_STATIC (t) = 1; /* SAVEd in proc, make static. */
8586 else
8587 TREE_STATIC (t) = 0; /* No need to make static. */
8588 break;
5ff904cd 8589
c7e4ee3a
CB
8590 case FFEINFO_whereCOMMON:
8591 TREE_STATIC (t) = 1; /* Assume COMMONs always SAVEd. */
8592 break;
5ff904cd 8593
c7e4ee3a
CB
8594 case FFEINFO_whereDUMMY:
8595 /* Note that twinning a DUMMY means the caller won't see
8596 the ASSIGNed value. But both F77 and F90 allow implementations
8597 to do this, i.e. disallow Fortran code that would try and
8598 take advantage of actually putting a label into a variable
8599 via a dummy argument (or any other storage association, for
8600 that matter). */
8601 TREE_STATIC (t) = 0;
8602 break;
5ff904cd 8603
c7e4ee3a
CB
8604 default:
8605 TREE_STATIC (t) = 0;
8606 break;
8607 }
5ff904cd 8608
c7e4ee3a
CB
8609 t = start_decl (t, FALSE);
8610 finish_decl (t, NULL_TREE, FALSE);
5ff904cd 8611
c7e4ee3a 8612 resume_momentary (yes);
5ff904cd 8613
c7e4ee3a 8614 ffesymbol_hook (s).assign_tree = t;
5ff904cd 8615
c7e4ee3a
CB
8616 lineno = old_lineno;
8617 input_filename = old_input_filename;
5ff904cd 8618
c7e4ee3a
CB
8619 return s;
8620}
5ff904cd 8621
c7e4ee3a
CB
8622#endif
8623/* Implement COMMON area in back end.
5ff904cd 8624
c7e4ee3a
CB
8625 Because COMMON-based variables can be referenced in the dimension
8626 expressions of dummy (adjustable) arrays, and because dummies
8627 (in the gcc back end) need to be put in the outer binding level
8628 of a function (which has two binding levels, the outer holding
8629 the dummies and the inner holding the other vars), special care
8630 must be taken to handle COMMON areas.
5ff904cd 8631
c7e4ee3a
CB
8632 The current strategy is basically to always tell the back end about
8633 the COMMON area as a top-level external reference to just a block
8634 of storage of the master type of that area (e.g. integer, real,
8635 character, whatever -- not a structure). As a distinct action,
8636 if initial values are provided, tell the back end about the area
8637 as a top-level non-external (initialized) area and remember not to
8638 allow further initialization or expansion of the area. Meanwhile,
8639 if no initialization happens at all, tell the back end about
8640 the largest size we've seen declared so the space does get reserved.
8641 (This function doesn't handle all that stuff, but it does some
8642 of the important things.)
5ff904cd 8643
c7e4ee3a
CB
8644 Meanwhile, for COMMON variables themselves, just keep creating
8645 references like *((float *) (&common_area + offset)) each time
8646 we reference the variable. In other words, don't make a VAR_DECL
8647 or any kind of component reference (like we used to do before 0.4),
8648 though we might do that as well just for debugging purposes (and
8649 stuff the rtl with the appropriate offset expression). */
5ff904cd 8650
c7e4ee3a
CB
8651#if FFECOM_targetCURRENT == FFECOM_targetGCC
8652static void
8653ffecom_transform_common_ (ffesymbol s)
8654{
8655 ffestorag st = ffesymbol_storage (s);
8656 ffeglobal g = ffesymbol_global (s);
8657 tree cbt;
8658 tree cbtype;
8659 tree init;
8660 tree high;
8661 bool is_init = ffestorag_is_init (st);
5ff904cd 8662
c7e4ee3a 8663 assert (st != NULL);
5ff904cd 8664
c7e4ee3a
CB
8665 if ((g == NULL)
8666 || (ffeglobal_type (g) != FFEGLOBAL_typeCOMMON))
8667 return;
5ff904cd 8668
c7e4ee3a 8669 /* First update the size of the area in global terms. */
5ff904cd 8670
c7e4ee3a 8671 ffeglobal_size_common (s, ffestorag_size (st));
5ff904cd 8672
c7e4ee3a
CB
8673 if (!ffeglobal_common_init (g))
8674 is_init = FALSE; /* No explicit init, don't let erroneous joins init. */
5ff904cd 8675
c7e4ee3a 8676 cbt = ffeglobal_hook (g);
5ff904cd 8677
c7e4ee3a
CB
8678 /* If we already have declared this common block for a previous program
8679 unit, and either we already initialized it or we don't have new
8680 initialization for it, just return what we have without changing it. */
5ff904cd 8681
c7e4ee3a
CB
8682 if ((cbt != NULL_TREE)
8683 && (!is_init
8684 || !DECL_EXTERNAL (cbt)))
8685 return;
5ff904cd 8686
c7e4ee3a 8687 /* Process inits. */
5ff904cd 8688
c7e4ee3a
CB
8689 if (is_init)
8690 {
8691 if (ffestorag_init (st) != NULL)
5ff904cd 8692 {
c7e4ee3a 8693 ffebld sexp;
5ff904cd 8694
c7e4ee3a
CB
8695 /* Set the padding for the expression, so ffecom_expr
8696 knows to insert that many zeros. */
8697 switch (ffebld_op (sexp = ffestorag_init (st)))
5ff904cd 8698 {
c7e4ee3a
CB
8699 case FFEBLD_opCONTER:
8700 ffebld_conter_set_pad (sexp, ffestorag_modulo (st));
5ff904cd 8701 break;
5ff904cd 8702
c7e4ee3a
CB
8703 case FFEBLD_opARRTER:
8704 ffebld_arrter_set_pad (sexp, ffestorag_modulo (st));
8705 break;
5ff904cd 8706
c7e4ee3a
CB
8707 case FFEBLD_opACCTER:
8708 ffebld_accter_set_pad (sexp, ffestorag_modulo (st));
8709 break;
5ff904cd 8710
c7e4ee3a
CB
8711 default:
8712 assert ("bad op for cmn init (pad)" == NULL);
8713 break;
8714 }
5ff904cd 8715
c7e4ee3a
CB
8716 init = ffecom_expr (sexp);
8717 if (init == error_mark_node)
8718 { /* Hopefully the back end complained! */
8719 init = NULL_TREE;
8720 if (cbt != NULL_TREE)
8721 return;
8722 }
8723 }
8724 else
8725 init = error_mark_node;
8726 }
8727 else
8728 init = NULL_TREE;
5ff904cd 8729
c7e4ee3a
CB
8730 push_obstacks_nochange ();
8731 end_temporary_allocation ();
5ff904cd 8732
c7e4ee3a 8733 /* cbtype must be permanently allocated! */
5ff904cd 8734
c7e4ee3a
CB
8735 /* Allocate the MAX of the areas so far, seen filewide. */
8736 high = build_int_2 ((ffeglobal_common_size (g)
8737 + ffeglobal_common_pad (g)) - 1, 0);
8738 TREE_TYPE (high) = ffecom_integer_type_node;
5ff904cd 8739
c7e4ee3a
CB
8740 if (init)
8741 cbtype = build_array_type (char_type_node,
8742 build_range_type (integer_type_node,
8743 integer_zero_node,
8744 high));
8745 else
8746 cbtype = build_array_type (char_type_node, NULL_TREE);
5ff904cd 8747
c7e4ee3a
CB
8748 if (cbt == NULL_TREE)
8749 {
8750 cbt
8751 = build_decl (VAR_DECL,
8752 ffecom_get_external_identifier_ (s),
8753 cbtype);
8754 TREE_STATIC (cbt) = 1;
8755 TREE_PUBLIC (cbt) = 1;
8756 }
8757 else
8758 {
8759 assert (is_init);
8760 TREE_TYPE (cbt) = cbtype;
8761 }
8762 DECL_EXTERNAL (cbt) = init ? 0 : 1;
8763 DECL_INITIAL (cbt) = init ? error_mark_node : NULL_TREE;
5ff904cd 8764
c7e4ee3a
CB
8765 cbt = start_decl (cbt, TRUE);
8766 if (ffeglobal_hook (g) != NULL)
8767 assert (cbt == ffeglobal_hook (g));
5ff904cd 8768
c7e4ee3a 8769 assert (!init || !DECL_EXTERNAL (cbt));
5ff904cd 8770
c7e4ee3a
CB
8771 /* Make sure that any type can live in COMMON and be referenced
8772 without getting a bus error. We could pick the most restrictive
8773 alignment of all entities actually placed in the COMMON, but
8774 this seems easy enough. */
5ff904cd 8775
c7e4ee3a 8776 DECL_ALIGN (cbt) = BIGGEST_ALIGNMENT;
5ff904cd 8777
c7e4ee3a
CB
8778 if (is_init && (ffestorag_init (st) == NULL))
8779 init = ffecom_init_zero_ (cbt);
5ff904cd 8780
c7e4ee3a 8781 finish_decl (cbt, init, TRUE);
5ff904cd 8782
c7e4ee3a
CB
8783 if (is_init)
8784 ffestorag_set_init (st, ffebld_new_any ());
5ff904cd 8785
c7e4ee3a
CB
8786 if (init)
8787 {
8788 tree size_tree;
5ff904cd 8789
c7e4ee3a
CB
8790 assert (DECL_SIZE (cbt) != NULL_TREE);
8791 assert (TREE_CODE (DECL_SIZE (cbt)) == INTEGER_CST);
8792 size_tree = size_binop (CEIL_DIV_EXPR,
8793 DECL_SIZE (cbt),
8794 size_int (BITS_PER_UNIT));
8795 assert (TREE_INT_CST_HIGH (size_tree) == 0);
8796 assert (TREE_INT_CST_LOW (size_tree)
8797 == ffeglobal_common_size (g) + ffeglobal_common_pad (g));
8798 }
5ff904cd 8799
c7e4ee3a 8800 ffeglobal_set_hook (g, cbt);
5ff904cd 8801
c7e4ee3a 8802 ffestorag_set_hook (st, cbt);
5ff904cd 8803
c7e4ee3a
CB
8804 resume_temporary_allocation ();
8805 pop_obstacks ();
8806}
5ff904cd 8807
c7e4ee3a
CB
8808#endif
8809/* Make master area for local EQUIVALENCE. */
5ff904cd 8810
c7e4ee3a
CB
8811#if FFECOM_targetCURRENT == FFECOM_targetGCC
8812static void
8813ffecom_transform_equiv_ (ffestorag eqst)
8814{
8815 tree eqt;
8816 tree eqtype;
8817 tree init;
8818 tree high;
8819 bool is_init = ffestorag_is_init (eqst);
8820 int yes;
5ff904cd 8821
c7e4ee3a 8822 assert (eqst != NULL);
5ff904cd 8823
c7e4ee3a 8824 eqt = ffestorag_hook (eqst);
5ff904cd 8825
c7e4ee3a
CB
8826 if (eqt != NULL_TREE)
8827 return;
5ff904cd 8828
c7e4ee3a
CB
8829 /* Process inits. */
8830
8831 if (is_init)
8832 {
8833 if (ffestorag_init (eqst) != NULL)
5ff904cd 8834 {
c7e4ee3a 8835 ffebld sexp;
5ff904cd 8836
c7e4ee3a
CB
8837 /* Set the padding for the expression, so ffecom_expr
8838 knows to insert that many zeros. */
8839 switch (ffebld_op (sexp = ffestorag_init (eqst)))
8840 {
8841 case FFEBLD_opCONTER:
8842 ffebld_conter_set_pad (sexp, ffestorag_modulo (eqst));
8843 break;
5ff904cd 8844
c7e4ee3a
CB
8845 case FFEBLD_opARRTER:
8846 ffebld_arrter_set_pad (sexp, ffestorag_modulo (eqst));
8847 break;
5ff904cd 8848
c7e4ee3a
CB
8849 case FFEBLD_opACCTER:
8850 ffebld_accter_set_pad (sexp, ffestorag_modulo (eqst));
8851 break;
5ff904cd 8852
c7e4ee3a
CB
8853 default:
8854 assert ("bad op for eqv init (pad)" == NULL);
8855 break;
8856 }
5ff904cd 8857
c7e4ee3a
CB
8858 init = ffecom_expr (sexp);
8859 if (init == error_mark_node)
8860 init = NULL_TREE; /* Hopefully the back end complained! */
8861 }
8862 else
8863 init = error_mark_node;
8864 }
8865 else if (ffe_is_init_local_zero ())
8866 init = error_mark_node;
8867 else
8868 init = NULL_TREE;
5ff904cd 8869
c7e4ee3a
CB
8870 ffecom_member_namelisted_ = FALSE;
8871 ffestorag_drive (ffestorag_list_equivs (eqst),
8872 &ffecom_member_phase1_,
8873 eqst);
5ff904cd 8874
c7e4ee3a 8875 yes = suspend_momentary ();
5ff904cd 8876
c7e4ee3a
CB
8877 high = build_int_2 ((ffestorag_size (eqst)
8878 + ffestorag_modulo (eqst)) - 1, 0);
8879 TREE_TYPE (high) = ffecom_integer_type_node;
5ff904cd 8880
c7e4ee3a
CB
8881 eqtype = build_array_type (char_type_node,
8882 build_range_type (ffecom_integer_type_node,
8883 ffecom_integer_zero_node,
8884 high));
8885
8886 eqt = build_decl (VAR_DECL,
8887 ffecom_get_invented_identifier ("__g77_equiv_%s",
8888 ffesymbol_text
8889 (ffestorag_symbol
8890 (eqst)),
8891 -1),
8892 eqtype);
8893 DECL_EXTERNAL (eqt) = 0;
8894 if (is_init
8895 || ffecom_member_namelisted_
8896#ifdef FFECOM_sizeMAXSTACKITEM
8897 || (ffestorag_size (eqst) > FFECOM_sizeMAXSTACKITEM)
8898#endif
8899 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8900 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
8901 && (ffestorag_is_save (eqst) || ffe_is_saveall ())))
8902 TREE_STATIC (eqt) = 1;
8903 else
8904 TREE_STATIC (eqt) = 0;
8905 TREE_PUBLIC (eqt) = 0;
8906 DECL_CONTEXT (eqt) = current_function_decl;
8907 if (init)
8908 DECL_INITIAL (eqt) = error_mark_node;
8909 else
8910 DECL_INITIAL (eqt) = NULL_TREE;
5ff904cd 8911
c7e4ee3a 8912 eqt = start_decl (eqt, FALSE);
5ff904cd 8913
c7e4ee3a
CB
8914 /* Make sure that any type can live in EQUIVALENCE and be referenced
8915 without getting a bus error. We could pick the most restrictive
8916 alignment of all entities actually placed in the EQUIVALENCE, but
8917 this seems easy enough. */
5ff904cd 8918
c7e4ee3a 8919 DECL_ALIGN (eqt) = BIGGEST_ALIGNMENT;
5ff904cd 8920
c7e4ee3a
CB
8921 if ((!is_init && ffe_is_init_local_zero ())
8922 || (is_init && (ffestorag_init (eqst) == NULL)))
8923 init = ffecom_init_zero_ (eqt);
5ff904cd 8924
c7e4ee3a 8925 finish_decl (eqt, init, FALSE);
5ff904cd 8926
c7e4ee3a
CB
8927 if (is_init)
8928 ffestorag_set_init (eqst, ffebld_new_any ());
5ff904cd 8929
c7e4ee3a
CB
8930 {
8931 tree size_tree;
5ff904cd 8932
c7e4ee3a
CB
8933 size_tree = size_binop (CEIL_DIV_EXPR,
8934 DECL_SIZE (eqt),
8935 size_int (BITS_PER_UNIT));
8936 assert (TREE_INT_CST_HIGH (size_tree) == 0);
8937 assert (TREE_INT_CST_LOW (size_tree)
8938 == ffestorag_size (eqst) + ffestorag_modulo (eqst));
8939 }
5ff904cd 8940
c7e4ee3a 8941 ffestorag_set_hook (eqst, eqt);
5ff904cd 8942
c7e4ee3a
CB
8943#ifdef SOMEONE_GETS_DEBUG_SUPPORT_WORKING
8944 ffestorag_drive (ffestorag_list_equivs (eqst),
8945 &ffecom_member_phase2_,
8946 eqst);
8947#endif
8948
8949 resume_momentary (yes);
5ff904cd
JL
8950}
8951
8952#endif
c7e4ee3a 8953/* Implement NAMELIST in back end. See f2c/format.c for more info. */
5ff904cd
JL
8954
8955#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
8956static tree
8957ffecom_transform_namelist_ (ffesymbol s)
5ff904cd 8958{
c7e4ee3a
CB
8959 tree nmlt;
8960 tree nmltype = ffecom_type_namelist_ ();
8961 tree nmlinits;
8962 tree nameinit;
8963 tree varsinit;
8964 tree nvarsinit;
8965 tree field;
8966 tree high;
5ff904cd 8967 int yes;
c7e4ee3a
CB
8968 int i;
8969 static int mynumber = 0;
5ff904cd 8970
c7e4ee3a 8971 yes = suspend_momentary ();
5ff904cd 8972
c7e4ee3a
CB
8973 nmlt = build_decl (VAR_DECL,
8974 ffecom_get_invented_identifier ("__g77_namelist_%d",
8975 NULL, mynumber++),
8976 nmltype);
8977 TREE_STATIC (nmlt) = 1;
8978 DECL_INITIAL (nmlt) = error_mark_node;
5ff904cd 8979
c7e4ee3a 8980 nmlt = start_decl (nmlt, FALSE);
5ff904cd 8981
c7e4ee3a 8982 /* Process inits. */
5ff904cd 8983
c7e4ee3a 8984 i = strlen (ffesymbol_text (s));
5ff904cd 8985
c7e4ee3a
CB
8986 high = build_int_2 (i, 0);
8987 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
8988
8989 nameinit = ffecom_build_f2c_string_ (i + 1,
8990 ffesymbol_text (s));
8991 TREE_TYPE (nameinit)
8992 = build_type_variant
8993 (build_array_type
8994 (char_type_node,
8995 build_range_type (ffecom_f2c_ftnlen_type_node,
8996 ffecom_f2c_ftnlen_one_node,
8997 high)),
8998 1, 0);
8999 TREE_CONSTANT (nameinit) = 1;
9000 TREE_STATIC (nameinit) = 1;
9001 nameinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (nameinit)),
9002 nameinit);
9003
9004 varsinit = ffecom_vardesc_array_ (s);
9005 varsinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (varsinit)),
9006 varsinit);
9007 TREE_CONSTANT (varsinit) = 1;
9008 TREE_STATIC (varsinit) = 1;
9009
9010 {
9011 ffebld b;
9012
9013 for (i = 0, b = ffesymbol_namelist (s); b != NULL; b = ffebld_trail (b))
9014 ++i;
9015 }
9016 nvarsinit = build_int_2 (i, 0);
9017 TREE_TYPE (nvarsinit) = integer_type_node;
9018 TREE_CONSTANT (nvarsinit) = 1;
9019 TREE_STATIC (nvarsinit) = 1;
9020
9021 nmlinits = build_tree_list ((field = TYPE_FIELDS (nmltype)), nameinit);
9022 TREE_CHAIN (nmlinits) = build_tree_list ((field = TREE_CHAIN (field)),
9023 varsinit);
9024 TREE_CHAIN (TREE_CHAIN (nmlinits))
9025 = build_tree_list ((field = TREE_CHAIN (field)), nvarsinit);
9026
9027 nmlinits = build (CONSTRUCTOR, nmltype, NULL_TREE, nmlinits);
9028 TREE_CONSTANT (nmlinits) = 1;
9029 TREE_STATIC (nmlinits) = 1;
9030
9031 finish_decl (nmlt, nmlinits, FALSE);
9032
9033 nmlt = ffecom_1 (ADDR_EXPR, build_pointer_type (nmltype), nmlt);
9034
9035 resume_momentary (yes);
9036
9037 return nmlt;
9038}
9039
9040#endif
9041
9042/* A subroutine of ffecom_tree_canonize_ref_. The incoming tree is
9043 analyzed on the assumption it is calculating a pointer to be
9044 indirected through. It must return the proper decl and offset,
9045 taking into account different units of measurements for offsets. */
9046
9047#if FFECOM_targetCURRENT == FFECOM_targetGCC
9048static void
9049ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
9050 tree t)
9051{
9052 switch (TREE_CODE (t))
9053 {
9054 case NOP_EXPR:
9055 case CONVERT_EXPR:
9056 case NON_LVALUE_EXPR:
9057 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
5ff904cd
JL
9058 break;
9059
c7e4ee3a
CB
9060 case PLUS_EXPR:
9061 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
9062 if ((*decl == NULL_TREE)
9063 || (*decl == error_mark_node))
9064 break;
9065
9066 if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST)
9067 {
9068 /* An offset into COMMON. */
9069 *offset = size_binop (PLUS_EXPR,
9070 *offset,
9071 TREE_OPERAND (t, 1));
9072 /* Convert offset (presumably in bytes) into canonical units
9073 (presumably bits). */
9074 *offset = size_binop (MULT_EXPR,
9075 TYPE_SIZE (TREE_TYPE (TREE_TYPE (t))),
9076 *offset);
9077 break;
9078 }
9079 /* Not a COMMON reference, so an unrecognized pattern. */
9080 *decl = error_mark_node;
5ff904cd
JL
9081 break;
9082
c7e4ee3a
CB
9083 case PARM_DECL:
9084 *decl = t;
9085 *offset = bitsize_int (0L, 0L);
5ff904cd
JL
9086 break;
9087
c7e4ee3a
CB
9088 case ADDR_EXPR:
9089 if (TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL)
9090 {
9091 /* A reference to COMMON. */
9092 *decl = TREE_OPERAND (t, 0);
9093 *offset = bitsize_int (0L, 0L);
9094 break;
9095 }
9096 /* Fall through. */
5ff904cd 9097 default:
c7e4ee3a
CB
9098 /* Not a COMMON reference, so an unrecognized pattern. */
9099 *decl = error_mark_node;
5ff904cd
JL
9100 break;
9101 }
c7e4ee3a
CB
9102}
9103#endif
5ff904cd 9104
c7e4ee3a
CB
9105/* Given a tree that is possibly intended for use as an lvalue, return
9106 information representing a canonical view of that tree as a decl, an
9107 offset into that decl, and a size for the lvalue.
5ff904cd 9108
c7e4ee3a
CB
9109 If there's no applicable decl, NULL_TREE is returned for the decl,
9110 and the other fields are left undefined.
5ff904cd 9111
c7e4ee3a
CB
9112 If the tree doesn't fit the recognizable forms, an ERROR_MARK node
9113 is returned for the decl, and the other fields are left undefined.
5ff904cd 9114
c7e4ee3a
CB
9115 Otherwise, the decl returned currently is either a VAR_DECL or a
9116 PARM_DECL.
5ff904cd 9117
c7e4ee3a
CB
9118 The offset returned is always valid, but of course not necessarily
9119 a constant, and not necessarily converted into the appropriate
9120 type, leaving that up to the caller (so as to avoid that overhead
9121 if the decls being looked at are different anyway).
5ff904cd 9122
c7e4ee3a
CB
9123 If the size cannot be determined (e.g. an adjustable array),
9124 an ERROR_MARK node is returned for the size. Otherwise, the
9125 size returned is valid, not necessarily a constant, and not
9126 necessarily converted into the appropriate type as with the
9127 offset.
5ff904cd 9128
c7e4ee3a
CB
9129 Note that the offset and size expressions are expressed in the
9130 base storage units (usually bits) rather than in the units of
9131 the type of the decl, because two decls with different types
9132 might overlap but with apparently non-overlapping array offsets,
9133 whereas converting the array offsets to consistant offsets will
9134 reveal the overlap. */
5ff904cd
JL
9135
9136#if FFECOM_targetCURRENT == FFECOM_targetGCC
9137static void
c7e4ee3a
CB
9138ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
9139 tree *size, tree t)
5ff904cd 9140{
c7e4ee3a
CB
9141 /* The default path is to report a nonexistant decl. */
9142 *decl = NULL_TREE;
5ff904cd 9143
c7e4ee3a 9144 if (t == NULL_TREE)
5ff904cd
JL
9145 return;
9146
c7e4ee3a
CB
9147 switch (TREE_CODE (t))
9148 {
9149 case ERROR_MARK:
9150 case IDENTIFIER_NODE:
9151 case INTEGER_CST:
9152 case REAL_CST:
9153 case COMPLEX_CST:
9154 case STRING_CST:
9155 case CONST_DECL:
9156 case PLUS_EXPR:
9157 case MINUS_EXPR:
9158 case MULT_EXPR:
9159 case TRUNC_DIV_EXPR:
9160 case CEIL_DIV_EXPR:
9161 case FLOOR_DIV_EXPR:
9162 case ROUND_DIV_EXPR:
9163 case TRUNC_MOD_EXPR:
9164 case CEIL_MOD_EXPR:
9165 case FLOOR_MOD_EXPR:
9166 case ROUND_MOD_EXPR:
9167 case RDIV_EXPR:
9168 case EXACT_DIV_EXPR:
9169 case FIX_TRUNC_EXPR:
9170 case FIX_CEIL_EXPR:
9171 case FIX_FLOOR_EXPR:
9172 case FIX_ROUND_EXPR:
9173 case FLOAT_EXPR:
9174 case EXPON_EXPR:
9175 case NEGATE_EXPR:
9176 case MIN_EXPR:
9177 case MAX_EXPR:
9178 case ABS_EXPR:
9179 case FFS_EXPR:
9180 case LSHIFT_EXPR:
9181 case RSHIFT_EXPR:
9182 case LROTATE_EXPR:
9183 case RROTATE_EXPR:
9184 case BIT_IOR_EXPR:
9185 case BIT_XOR_EXPR:
9186 case BIT_AND_EXPR:
9187 case BIT_ANDTC_EXPR:
9188 case BIT_NOT_EXPR:
9189 case TRUTH_ANDIF_EXPR:
9190 case TRUTH_ORIF_EXPR:
9191 case TRUTH_AND_EXPR:
9192 case TRUTH_OR_EXPR:
9193 case TRUTH_XOR_EXPR:
9194 case TRUTH_NOT_EXPR:
9195 case LT_EXPR:
9196 case LE_EXPR:
9197 case GT_EXPR:
9198 case GE_EXPR:
9199 case EQ_EXPR:
9200 case NE_EXPR:
9201 case COMPLEX_EXPR:
9202 case CONJ_EXPR:
9203 case REALPART_EXPR:
9204 case IMAGPART_EXPR:
9205 case LABEL_EXPR:
9206 case COMPONENT_REF:
9207 case COMPOUND_EXPR:
9208 case ADDR_EXPR:
9209 return;
5ff904cd 9210
c7e4ee3a
CB
9211 case VAR_DECL:
9212 case PARM_DECL:
9213 *decl = t;
9214 *offset = bitsize_int (0L, 0L);
9215 *size = TYPE_SIZE (TREE_TYPE (t));
9216 return;
5ff904cd 9217
c7e4ee3a
CB
9218 case ARRAY_REF:
9219 {
9220 tree array = TREE_OPERAND (t, 0);
9221 tree element = TREE_OPERAND (t, 1);
9222 tree init_offset;
9223
9224 if ((array == NULL_TREE)
9225 || (element == NULL_TREE))
9226 {
9227 *decl = error_mark_node;
9228 return;
9229 }
9230
9231 ffecom_tree_canonize_ref_ (decl, &init_offset, size,
9232 array);
9233 if ((*decl == NULL_TREE)
9234 || (*decl == error_mark_node))
9235 return;
9236
9237 *offset = size_binop (MULT_EXPR,
9238 TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))),
9239 size_binop (MINUS_EXPR,
9240 element,
9241 TYPE_MIN_VALUE
9242 (TYPE_DOMAIN
9243 (TREE_TYPE (array)))));
9244
9245 *offset = size_binop (PLUS_EXPR,
9246 init_offset,
9247 *offset);
9248
9249 *size = TYPE_SIZE (TREE_TYPE (t));
9250 return;
9251 }
9252
9253 case INDIRECT_REF:
9254
9255 /* Most of this code is to handle references to COMMON. And so
9256 far that is useful only for calling library functions, since
9257 external (user) functions might reference common areas. But
9258 even calling an external function, it's worthwhile to decode
9259 COMMON references because if not storing into COMMON, we don't
9260 want COMMON-based arguments to gratuitously force use of a
9261 temporary. */
9262
9263 *size = TYPE_SIZE (TREE_TYPE (t));
5ff904cd 9264
c7e4ee3a
CB
9265 ffecom_tree_canonize_ptr_ (decl, offset,
9266 TREE_OPERAND (t, 0));
5ff904cd 9267
c7e4ee3a 9268 return;
5ff904cd 9269
c7e4ee3a
CB
9270 case CONVERT_EXPR:
9271 case NOP_EXPR:
9272 case MODIFY_EXPR:
9273 case NON_LVALUE_EXPR:
9274 case RESULT_DECL:
9275 case FIELD_DECL:
9276 case COND_EXPR: /* More cases than we can handle. */
9277 case SAVE_EXPR:
9278 case REFERENCE_EXPR:
9279 case PREDECREMENT_EXPR:
9280 case PREINCREMENT_EXPR:
9281 case POSTDECREMENT_EXPR:
9282 case POSTINCREMENT_EXPR:
9283 case CALL_EXPR:
9284 default:
9285 *decl = error_mark_node;
9286 return;
9287 }
9288}
9289#endif
5ff904cd 9290
c7e4ee3a 9291/* Do divide operation appropriate to type of operands. */
5ff904cd 9292
c7e4ee3a
CB
9293#if FFECOM_targetCURRENT == FFECOM_targetGCC
9294static tree
9295ffecom_tree_divide_ (tree tree_type, tree left, tree right,
9296 tree dest_tree, ffebld dest, bool *dest_used,
9297 tree hook)
9298{
9299 if ((left == error_mark_node)
9300 || (right == error_mark_node))
9301 return error_mark_node;
a6fa6420 9302
c7e4ee3a
CB
9303 switch (TREE_CODE (tree_type))
9304 {
9305 case INTEGER_TYPE:
9306 return ffecom_2 (TRUNC_DIV_EXPR, tree_type,
9307 left,
9308 right);
a6fa6420 9309
c7e4ee3a
CB
9310 case COMPLEX_TYPE:
9311 {
9312 ffecomGfrt ix;
a6fa6420 9313
c7e4ee3a
CB
9314 if (TREE_TYPE (tree_type)
9315 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9316 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9317 else
9318 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
a6fa6420 9319
c7e4ee3a
CB
9320 left = ffecom_1 (ADDR_EXPR,
9321 build_pointer_type (TREE_TYPE (left)),
9322 left);
9323 left = build_tree_list (NULL_TREE, left);
9324 right = ffecom_1 (ADDR_EXPR,
9325 build_pointer_type (TREE_TYPE (right)),
9326 right);
9327 right = build_tree_list (NULL_TREE, right);
9328 TREE_CHAIN (left) = right;
a6fa6420 9329
c7e4ee3a
CB
9330 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9331 ffecom_gfrt_kindtype (ix),
9332 ffe_is_f2c_library (),
9333 tree_type,
9334 left,
9335 dest_tree, dest, dest_used,
9336 NULL_TREE, TRUE, hook);
9337 }
9338 break;
5ff904cd 9339
c7e4ee3a
CB
9340 case RECORD_TYPE:
9341 {
9342 ffecomGfrt ix;
5ff904cd 9343
c7e4ee3a
CB
9344 if (TREE_TYPE (TYPE_FIELDS (tree_type))
9345 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9346 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9347 else
9348 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
5ff904cd 9349
c7e4ee3a
CB
9350 left = ffecom_1 (ADDR_EXPR,
9351 build_pointer_type (TREE_TYPE (left)),
9352 left);
9353 left = build_tree_list (NULL_TREE, left);
9354 right = ffecom_1 (ADDR_EXPR,
9355 build_pointer_type (TREE_TYPE (right)),
9356 right);
9357 right = build_tree_list (NULL_TREE, right);
9358 TREE_CHAIN (left) = right;
a6fa6420 9359
c7e4ee3a
CB
9360 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9361 ffecom_gfrt_kindtype (ix),
9362 ffe_is_f2c_library (),
9363 tree_type,
9364 left,
9365 dest_tree, dest, dest_used,
9366 NULL_TREE, TRUE, hook);
9367 }
9368 break;
5ff904cd 9369
c7e4ee3a
CB
9370 default:
9371 return ffecom_2 (RDIV_EXPR, tree_type,
9372 left,
9373 right);
5ff904cd 9374 }
c7e4ee3a 9375}
5ff904cd 9376
c7e4ee3a
CB
9377#endif
9378/* Build type info for non-dummy variable. */
5ff904cd 9379
c7e4ee3a
CB
9380#if FFECOM_targetCURRENT == FFECOM_targetGCC
9381static tree
9382ffecom_type_localvar_ (ffesymbol s, ffeinfoBasictype bt,
9383 ffeinfoKindtype kt)
9384{
9385 tree type;
9386 ffebld dl;
9387 ffebld dim;
9388 tree lowt;
9389 tree hight;
5ff904cd 9390
c7e4ee3a
CB
9391 type = ffecom_tree_type[bt][kt];
9392 if (bt == FFEINFO_basictypeCHARACTER)
9393 {
9394 hight = build_int_2 (ffesymbol_size (s), 0);
9395 TREE_TYPE (hight) = ffecom_f2c_ftnlen_type_node;
5ff904cd 9396
c7e4ee3a
CB
9397 type
9398 = build_array_type
9399 (type,
9400 build_range_type (ffecom_f2c_ftnlen_type_node,
9401 ffecom_f2c_ftnlen_one_node,
9402 hight));
9403 type = ffecom_check_size_overflow_ (s, type, FALSE);
9404 }
5ff904cd 9405
c7e4ee3a
CB
9406 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
9407 {
9408 if (type == error_mark_node)
9409 break;
5ff904cd 9410
c7e4ee3a
CB
9411 dim = ffebld_head (dl);
9412 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
5ff904cd 9413
c7e4ee3a
CB
9414 if (ffebld_left (dim) == NULL)
9415 lowt = integer_one_node;
9416 else
9417 lowt = ffecom_expr (ffebld_left (dim));
5ff904cd 9418
c7e4ee3a
CB
9419 if (TREE_CODE (lowt) != INTEGER_CST)
9420 lowt = variable_size (lowt);
5ff904cd 9421
c7e4ee3a
CB
9422 assert (ffebld_right (dim) != NULL);
9423 hight = ffecom_expr (ffebld_right (dim));
5ff904cd 9424
c7e4ee3a
CB
9425 if (TREE_CODE (hight) != INTEGER_CST)
9426 hight = variable_size (hight);
5ff904cd 9427
c7e4ee3a
CB
9428 type = build_array_type (type,
9429 build_range_type (ffecom_integer_type_node,
9430 lowt, hight));
9431 type = ffecom_check_size_overflow_ (s, type, FALSE);
9432 }
5ff904cd 9433
c7e4ee3a 9434 return type;
5ff904cd
JL
9435}
9436
9437#endif
c7e4ee3a 9438/* Build Namelist type. */
5ff904cd 9439
c7e4ee3a
CB
9440#if FFECOM_targetCURRENT == FFECOM_targetGCC
9441static tree
9442ffecom_type_namelist_ ()
9443{
9444 static tree type = NULL_TREE;
5ff904cd 9445
c7e4ee3a
CB
9446 if (type == NULL_TREE)
9447 {
9448 static tree namefield, varsfield, nvarsfield;
9449 tree vardesctype;
5ff904cd 9450
c7e4ee3a 9451 vardesctype = ffecom_type_vardesc_ ();
5ff904cd 9452
c7e4ee3a
CB
9453 push_obstacks_nochange ();
9454 end_temporary_allocation ();
a6fa6420 9455
c7e4ee3a 9456 type = make_node (RECORD_TYPE);
a6fa6420 9457
c7e4ee3a 9458 vardesctype = build_pointer_type (build_pointer_type (vardesctype));
a6fa6420 9459
c7e4ee3a
CB
9460 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9461 string_type_node);
9462 varsfield = ffecom_decl_field (type, namefield, "vars", vardesctype);
9463 nvarsfield = ffecom_decl_field (type, varsfield, "nvars",
9464 integer_type_node);
a6fa6420 9465
c7e4ee3a
CB
9466 TYPE_FIELDS (type) = namefield;
9467 layout_type (type);
a6fa6420 9468
c7e4ee3a
CB
9469 resume_temporary_allocation ();
9470 pop_obstacks ();
5ff904cd 9471 }
5ff904cd 9472
c7e4ee3a
CB
9473 return type;
9474}
5ff904cd 9475
c7e4ee3a 9476#endif
5ff904cd 9477
c7e4ee3a
CB
9478/* Make a copy of a type, assuming caller has switched to the permanent
9479 obstacks and that the type is for an aggregate (array) initializer. */
5ff904cd 9480
c7e4ee3a
CB
9481#if FFECOM_targetCURRENT == FFECOM_targetGCC && 0 /* Not used now. */
9482static tree
9483ffecom_type_permanent_copy_ (tree t)
9484{
9485 tree domain;
9486 tree max;
5ff904cd 9487
c7e4ee3a 9488 assert (TREE_TYPE (t) != NULL_TREE);
5ff904cd 9489
c7e4ee3a 9490 domain = TYPE_DOMAIN (t);
5ff904cd 9491
c7e4ee3a
CB
9492 assert (TREE_CODE (t) == ARRAY_TYPE);
9493 assert (TREE_PERMANENT (TREE_TYPE (t)));
9494 assert (TREE_PERMANENT (TREE_TYPE (domain)));
9495 assert (TREE_PERMANENT (TYPE_MIN_VALUE (domain)));
5ff904cd 9496
c7e4ee3a
CB
9497 max = TYPE_MAX_VALUE (domain);
9498 if (!TREE_PERMANENT (max))
9499 {
9500 assert (TREE_CODE (max) == INTEGER_CST);
5ff904cd 9501
c7e4ee3a
CB
9502 max = build_int_2 (TREE_INT_CST_LOW (max), TREE_INT_CST_HIGH (max));
9503 TREE_TYPE (max) = TREE_TYPE (TYPE_MIN_VALUE (domain));
9504 }
5ff904cd 9505
c7e4ee3a
CB
9506 return build_array_type (TREE_TYPE (t),
9507 build_range_type (TREE_TYPE (domain),
9508 TYPE_MIN_VALUE (domain),
9509 max));
9510}
9511#endif
5ff904cd 9512
c7e4ee3a 9513/* Build Vardesc type. */
5ff904cd 9514
c7e4ee3a
CB
9515#if FFECOM_targetCURRENT == FFECOM_targetGCC
9516static tree
9517ffecom_type_vardesc_ ()
9518{
9519 static tree type = NULL_TREE;
9520 static tree namefield, addrfield, dimsfield, typefield;
5ff904cd 9521
c7e4ee3a
CB
9522 if (type == NULL_TREE)
9523 {
9524 push_obstacks_nochange ();
9525 end_temporary_allocation ();
5ff904cd 9526
c7e4ee3a 9527 type = make_node (RECORD_TYPE);
5ff904cd 9528
c7e4ee3a
CB
9529 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9530 string_type_node);
9531 addrfield = ffecom_decl_field (type, namefield, "addr",
9532 string_type_node);
9533 dimsfield = ffecom_decl_field (type, addrfield, "dims",
9534 ffecom_f2c_ptr_to_ftnlen_type_node);
9535 typefield = ffecom_decl_field (type, dimsfield, "type",
9536 integer_type_node);
5ff904cd 9537
c7e4ee3a
CB
9538 TYPE_FIELDS (type) = namefield;
9539 layout_type (type);
9540
9541 resume_temporary_allocation ();
9542 pop_obstacks ();
9543 }
9544
9545 return type;
5ff904cd
JL
9546}
9547
9548#endif
5ff904cd
JL
9549
9550#if FFECOM_targetCURRENT == FFECOM_targetGCC
9551static tree
c7e4ee3a 9552ffecom_vardesc_ (ffebld expr)
5ff904cd 9553{
c7e4ee3a 9554 ffesymbol s;
5ff904cd 9555
c7e4ee3a
CB
9556 assert (ffebld_op (expr) == FFEBLD_opSYMTER);
9557 s = ffebld_symter (expr);
5ff904cd 9558
c7e4ee3a
CB
9559 if (ffesymbol_hook (s).vardesc_tree == NULL_TREE)
9560 {
9561 int i;
9562 tree vardesctype = ffecom_type_vardesc_ ();
9563 tree var;
9564 tree nameinit;
9565 tree dimsinit;
9566 tree addrinit;
9567 tree typeinit;
9568 tree field;
9569 tree varinits;
9570 int yes;
9571 static int mynumber = 0;
5ff904cd 9572
c7e4ee3a 9573 yes = suspend_momentary ();
5ff904cd 9574
c7e4ee3a
CB
9575 var = build_decl (VAR_DECL,
9576 ffecom_get_invented_identifier ("__g77_vardesc_%d",
9577 NULL, mynumber++),
9578 vardesctype);
9579 TREE_STATIC (var) = 1;
9580 DECL_INITIAL (var) = error_mark_node;
5ff904cd 9581
c7e4ee3a 9582 var = start_decl (var, FALSE);
5ff904cd 9583
c7e4ee3a 9584 /* Process inits. */
5ff904cd 9585
c7e4ee3a
CB
9586 nameinit = ffecom_build_f2c_string_ ((i = strlen (ffesymbol_text (s)))
9587 + 1,
9588 ffesymbol_text (s));
9589 TREE_TYPE (nameinit)
9590 = build_type_variant
9591 (build_array_type
9592 (char_type_node,
9593 build_range_type (integer_type_node,
9594 integer_one_node,
9595 build_int_2 (i, 0))),
9596 1, 0);
9597 TREE_CONSTANT (nameinit) = 1;
9598 TREE_STATIC (nameinit) = 1;
9599 nameinit = ffecom_1 (ADDR_EXPR,
9600 build_pointer_type (TREE_TYPE (nameinit)),
9601 nameinit);
5ff904cd 9602
c7e4ee3a 9603 addrinit = ffecom_arg_ptr_to_expr (expr, &typeinit);
5ff904cd 9604
c7e4ee3a 9605 dimsinit = ffecom_vardesc_dims_ (s);
5ff904cd 9606
c7e4ee3a
CB
9607 if (typeinit == NULL_TREE)
9608 {
9609 ffeinfoBasictype bt = ffesymbol_basictype (s);
9610 ffeinfoKindtype kt = ffesymbol_kindtype (s);
9611 int tc = ffecom_f2c_typecode (bt, kt);
5ff904cd 9612
c7e4ee3a
CB
9613 assert (tc != -1);
9614 typeinit = build_int_2 (tc, (tc < 0) ? -1 : 0);
9615 }
9616 else
9617 typeinit = ffecom_1 (NEGATE_EXPR, TREE_TYPE (typeinit), typeinit);
5ff904cd 9618
c7e4ee3a
CB
9619 varinits = build_tree_list ((field = TYPE_FIELDS (vardesctype)),
9620 nameinit);
9621 TREE_CHAIN (varinits) = build_tree_list ((field = TREE_CHAIN (field)),
9622 addrinit);
9623 TREE_CHAIN (TREE_CHAIN (varinits))
9624 = build_tree_list ((field = TREE_CHAIN (field)), dimsinit);
9625 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (varinits)))
9626 = build_tree_list ((field = TREE_CHAIN (field)), typeinit);
5ff904cd 9627
c7e4ee3a
CB
9628 varinits = build (CONSTRUCTOR, vardesctype, NULL_TREE, varinits);
9629 TREE_CONSTANT (varinits) = 1;
9630 TREE_STATIC (varinits) = 1;
5ff904cd 9631
c7e4ee3a 9632 finish_decl (var, varinits, FALSE);
5ff904cd 9633
c7e4ee3a 9634 var = ffecom_1 (ADDR_EXPR, build_pointer_type (vardesctype), var);
5ff904cd 9635
c7e4ee3a 9636 resume_momentary (yes);
5ff904cd 9637
c7e4ee3a
CB
9638 ffesymbol_hook (s).vardesc_tree = var;
9639 }
5ff904cd 9640
c7e4ee3a
CB
9641 return ffesymbol_hook (s).vardesc_tree;
9642}
5ff904cd 9643
c7e4ee3a 9644#endif
5ff904cd 9645#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
9646static tree
9647ffecom_vardesc_array_ (ffesymbol s)
5ff904cd 9648{
c7e4ee3a
CB
9649 ffebld b;
9650 tree list;
9651 tree item = NULL_TREE;
9652 tree var;
9653 int i;
9654 int yes;
9655 static int mynumber = 0;
5ff904cd 9656
c7e4ee3a
CB
9657 for (i = 0, list = NULL_TREE, b = ffesymbol_namelist (s);
9658 b != NULL;
9659 b = ffebld_trail (b), ++i)
9660 {
9661 tree t;
5ff904cd 9662
c7e4ee3a 9663 t = ffecom_vardesc_ (ffebld_head (b));
5ff904cd 9664
c7e4ee3a
CB
9665 if (list == NULL_TREE)
9666 list = item = build_tree_list (NULL_TREE, t);
9667 else
5ff904cd 9668 {
c7e4ee3a
CB
9669 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9670 item = TREE_CHAIN (item);
5ff904cd 9671 }
5ff904cd 9672 }
5ff904cd 9673
c7e4ee3a 9674 yes = suspend_momentary ();
5ff904cd 9675
c7e4ee3a
CB
9676 item = build_array_type (build_pointer_type (ffecom_type_vardesc_ ()),
9677 build_range_type (integer_type_node,
9678 integer_one_node,
9679 build_int_2 (i, 0)));
9680 list = build (CONSTRUCTOR, item, NULL_TREE, list);
9681 TREE_CONSTANT (list) = 1;
9682 TREE_STATIC (list) = 1;
5ff904cd 9683
c7e4ee3a
CB
9684 var = ffecom_get_invented_identifier ("__g77_vardesc_array_%d", NULL,
9685 mynumber++);
9686 var = build_decl (VAR_DECL, var, item);
9687 TREE_STATIC (var) = 1;
9688 DECL_INITIAL (var) = error_mark_node;
9689 var = start_decl (var, FALSE);
9690 finish_decl (var, list, FALSE);
5ff904cd 9691
c7e4ee3a 9692 resume_momentary (yes);
5ff904cd 9693
c7e4ee3a
CB
9694 return var;
9695}
5ff904cd 9696
c7e4ee3a
CB
9697#endif
9698#if FFECOM_targetCURRENT == FFECOM_targetGCC
9699static tree
9700ffecom_vardesc_dims_ (ffesymbol s)
9701{
9702 if (ffesymbol_dims (s) == NULL)
9703 return convert (ffecom_f2c_ptr_to_ftnlen_type_node,
9704 integer_zero_node);
5ff904cd 9705
c7e4ee3a
CB
9706 {
9707 ffebld b;
9708 ffebld e;
9709 tree list;
9710 tree backlist;
9711 tree item = NULL_TREE;
9712 tree var;
9713 int yes;
9714 tree numdim;
9715 tree numelem;
9716 tree baseoff = NULL_TREE;
9717 static int mynumber = 0;
9718
9719 numdim = build_int_2 ((int) ffesymbol_rank (s), 0);
9720 TREE_TYPE (numdim) = ffecom_f2c_ftnlen_type_node;
9721
9722 numelem = ffecom_expr (ffesymbol_arraysize (s));
9723 TREE_TYPE (numelem) = ffecom_f2c_ftnlen_type_node;
9724
9725 list = NULL_TREE;
9726 backlist = NULL_TREE;
9727 for (b = ffesymbol_dims (s), e = ffesymbol_extents (s);
9728 b != NULL;
9729 b = ffebld_trail (b), e = ffebld_trail (e))
5ff904cd 9730 {
c7e4ee3a
CB
9731 tree t;
9732 tree low;
9733 tree back;
5ff904cd 9734
c7e4ee3a
CB
9735 if (ffebld_trail (b) == NULL)
9736 t = NULL_TREE;
9737 else
5ff904cd 9738 {
c7e4ee3a
CB
9739 t = convert (ffecom_f2c_ftnlen_type_node,
9740 ffecom_expr (ffebld_head (e)));
5ff904cd 9741
c7e4ee3a
CB
9742 if (list == NULL_TREE)
9743 list = item = build_tree_list (NULL_TREE, t);
9744 else
9745 {
9746 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9747 item = TREE_CHAIN (item);
9748 }
9749 }
5ff904cd 9750
c7e4ee3a
CB
9751 if (ffebld_left (ffebld_head (b)) == NULL)
9752 low = ffecom_integer_one_node;
9753 else
9754 low = ffecom_expr (ffebld_left (ffebld_head (b)));
9755 low = convert (ffecom_f2c_ftnlen_type_node, low);
5ff904cd 9756
c7e4ee3a
CB
9757 back = build_tree_list (low, t);
9758 TREE_CHAIN (back) = backlist;
9759 backlist = back;
9760 }
5ff904cd 9761
c7e4ee3a
CB
9762 for (item = backlist; item != NULL_TREE; item = TREE_CHAIN (item))
9763 {
9764 if (TREE_VALUE (item) == NULL_TREE)
9765 baseoff = TREE_PURPOSE (item);
9766 else
9767 baseoff = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
9768 TREE_PURPOSE (item),
9769 ffecom_2 (MULT_EXPR,
9770 ffecom_f2c_ftnlen_type_node,
9771 TREE_VALUE (item),
9772 baseoff));
5ff904cd
JL
9773 }
9774
c7e4ee3a 9775 /* backlist now dead, along with all TREE_PURPOSEs on it. */
5ff904cd 9776
c7e4ee3a
CB
9777 baseoff = build_tree_list (NULL_TREE, baseoff);
9778 TREE_CHAIN (baseoff) = list;
5ff904cd 9779
c7e4ee3a
CB
9780 numelem = build_tree_list (NULL_TREE, numelem);
9781 TREE_CHAIN (numelem) = baseoff;
5ff904cd 9782
c7e4ee3a
CB
9783 numdim = build_tree_list (NULL_TREE, numdim);
9784 TREE_CHAIN (numdim) = numelem;
5ff904cd 9785
c7e4ee3a 9786 yes = suspend_momentary ();
5ff904cd 9787
c7e4ee3a
CB
9788 item = build_array_type (ffecom_f2c_ftnlen_type_node,
9789 build_range_type (integer_type_node,
9790 integer_zero_node,
9791 build_int_2
9792 ((int) ffesymbol_rank (s)
9793 + 2, 0)));
9794 list = build (CONSTRUCTOR, item, NULL_TREE, numdim);
9795 TREE_CONSTANT (list) = 1;
9796 TREE_STATIC (list) = 1;
9797
9798 var = ffecom_get_invented_identifier ("__g77_dims_%d", NULL,
9799 mynumber++);
9800 var = build_decl (VAR_DECL, var, item);
9801 TREE_STATIC (var) = 1;
9802 DECL_INITIAL (var) = error_mark_node;
9803 var = start_decl (var, FALSE);
9804 finish_decl (var, list, FALSE);
9805
9806 var = ffecom_1 (ADDR_EXPR, build_pointer_type (item), var);
9807
9808 resume_momentary (yes);
9809
9810 return var;
9811 }
5ff904cd 9812}
c7e4ee3a 9813
5ff904cd 9814#endif
c7e4ee3a
CB
9815/* Essentially does a "fold (build1 (code, type, node))" while checking
9816 for certain housekeeping things.
5ff904cd 9817
c7e4ee3a
CB
9818 NOTE: for building an ADDR_EXPR around a FUNCTION_DECL, use
9819 ffecom_1_fn instead. */
5ff904cd
JL
9820
9821#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
9822tree
9823ffecom_1 (enum tree_code code, tree type, tree node)
5ff904cd 9824{
c7e4ee3a
CB
9825 tree item;
9826
9827 if ((node == error_mark_node)
9828 || (type == error_mark_node))
5ff904cd
JL
9829 return error_mark_node;
9830
c7e4ee3a 9831 if (code == ADDR_EXPR)
5ff904cd 9832 {
c7e4ee3a
CB
9833 if (!mark_addressable (node))
9834 assert ("can't mark_addressable this node!" == NULL);
9835 }
5ff904cd 9836
c7e4ee3a
CB
9837 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
9838 {
9839 tree realtype;
5ff904cd 9840
c7e4ee3a
CB
9841 case REALPART_EXPR:
9842 item = build (COMPONENT_REF, type, node, TYPE_FIELDS (TREE_TYPE (node)));
5ff904cd
JL
9843 break;
9844
c7e4ee3a
CB
9845 case IMAGPART_EXPR:
9846 item = build (COMPONENT_REF, type, node, TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (node))));
9847 break;
5ff904cd 9848
5ff904cd 9849
c7e4ee3a
CB
9850 case NEGATE_EXPR:
9851 if (TREE_CODE (type) != RECORD_TYPE)
9852 {
9853 item = build1 (code, type, node);
9854 break;
9855 }
9856 node = ffecom_stabilize_aggregate_ (node);
9857 realtype = TREE_TYPE (TYPE_FIELDS (type));
9858 item =
9859 ffecom_2 (COMPLEX_EXPR, type,
9860 ffecom_1 (NEGATE_EXPR, realtype,
9861 ffecom_1 (REALPART_EXPR, realtype,
9862 node)),
9863 ffecom_1 (NEGATE_EXPR, realtype,
9864 ffecom_1 (IMAGPART_EXPR, realtype,
9865 node)));
5ff904cd
JL
9866 break;
9867
9868 default:
c7e4ee3a
CB
9869 item = build1 (code, type, node);
9870 break;
5ff904cd 9871 }
5ff904cd 9872
c7e4ee3a
CB
9873 if (TREE_SIDE_EFFECTS (node))
9874 TREE_SIDE_EFFECTS (item) = 1;
9875 if ((code == ADDR_EXPR) && staticp (node))
9876 TREE_CONSTANT (item) = 1;
9877 return fold (item);
9878}
5ff904cd 9879#endif
5ff904cd 9880
c7e4ee3a
CB
9881/* Like ffecom_1 (ADDR_EXPR, TREE_TYPE (node), node), except
9882 handles TREE_CODE (node) == FUNCTION_DECL. In particular,
9883 does not set TREE_ADDRESSABLE (because calling an inline
9884 function does not mean the function needs to be separately
9885 compiled). */
5ff904cd
JL
9886
9887#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
9888tree
9889ffecom_1_fn (tree node)
5ff904cd 9890{
c7e4ee3a 9891 tree item;
5ff904cd 9892 tree type;
5ff904cd 9893
c7e4ee3a
CB
9894 if (node == error_mark_node)
9895 return error_mark_node;
5ff904cd 9896
c7e4ee3a
CB
9897 type = build_type_variant (TREE_TYPE (node),
9898 TREE_READONLY (node),
9899 TREE_THIS_VOLATILE (node));
9900 item = build1 (ADDR_EXPR,
9901 build_pointer_type (type), node);
9902 if (TREE_SIDE_EFFECTS (node))
9903 TREE_SIDE_EFFECTS (item) = 1;
9904 if (staticp (node))
9905 TREE_CONSTANT (item) = 1;
9906 return fold (item);
5ff904cd 9907}
5ff904cd 9908#endif
c7e4ee3a
CB
9909
9910/* Essentially does a "fold (build (code, type, node1, node2))" while
9911 checking for certain housekeeping things. */
5ff904cd
JL
9912
9913#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
9914tree
9915ffecom_2 (enum tree_code code, tree type, tree node1,
9916 tree node2)
5ff904cd 9917{
c7e4ee3a 9918 tree item;
5ff904cd 9919
c7e4ee3a
CB
9920 if ((node1 == error_mark_node)
9921 || (node2 == error_mark_node)
9922 || (type == error_mark_node))
9923 return error_mark_node;
9924
9925 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
5ff904cd 9926 {
c7e4ee3a 9927 tree a, b, c, d, realtype;
5ff904cd 9928
c7e4ee3a
CB
9929 case CONJ_EXPR:
9930 assert ("no CONJ_EXPR support yet" == NULL);
9931 return error_mark_node;
5ff904cd 9932
c7e4ee3a
CB
9933 case COMPLEX_EXPR:
9934 item = build_tree_list (TYPE_FIELDS (type), node1);
9935 TREE_CHAIN (item) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), node2);
9936 item = build (CONSTRUCTOR, type, NULL_TREE, item);
9937 break;
5ff904cd 9938
c7e4ee3a
CB
9939 case PLUS_EXPR:
9940 if (TREE_CODE (type) != RECORD_TYPE)
9941 {
9942 item = build (code, type, node1, node2);
9943 break;
9944 }
9945 node1 = ffecom_stabilize_aggregate_ (node1);
9946 node2 = ffecom_stabilize_aggregate_ (node2);
9947 realtype = TREE_TYPE (TYPE_FIELDS (type));
9948 item =
9949 ffecom_2 (COMPLEX_EXPR, type,
9950 ffecom_2 (PLUS_EXPR, realtype,
9951 ffecom_1 (REALPART_EXPR, realtype,
9952 node1),
9953 ffecom_1 (REALPART_EXPR, realtype,
9954 node2)),
9955 ffecom_2 (PLUS_EXPR, realtype,
9956 ffecom_1 (IMAGPART_EXPR, realtype,
9957 node1),
9958 ffecom_1 (IMAGPART_EXPR, realtype,
9959 node2)));
9960 break;
5ff904cd 9961
c7e4ee3a
CB
9962 case MINUS_EXPR:
9963 if (TREE_CODE (type) != RECORD_TYPE)
9964 {
9965 item = build (code, type, node1, node2);
9966 break;
9967 }
9968 node1 = ffecom_stabilize_aggregate_ (node1);
9969 node2 = ffecom_stabilize_aggregate_ (node2);
9970 realtype = TREE_TYPE (TYPE_FIELDS (type));
9971 item =
9972 ffecom_2 (COMPLEX_EXPR, type,
9973 ffecom_2 (MINUS_EXPR, realtype,
9974 ffecom_1 (REALPART_EXPR, realtype,
9975 node1),
9976 ffecom_1 (REALPART_EXPR, realtype,
9977 node2)),
9978 ffecom_2 (MINUS_EXPR, realtype,
9979 ffecom_1 (IMAGPART_EXPR, realtype,
9980 node1),
9981 ffecom_1 (IMAGPART_EXPR, realtype,
9982 node2)));
9983 break;
5ff904cd 9984
c7e4ee3a
CB
9985 case MULT_EXPR:
9986 if (TREE_CODE (type) != RECORD_TYPE)
9987 {
9988 item = build (code, type, node1, node2);
9989 break;
9990 }
9991 node1 = ffecom_stabilize_aggregate_ (node1);
9992 node2 = ffecom_stabilize_aggregate_ (node2);
9993 realtype = TREE_TYPE (TYPE_FIELDS (type));
9994 a = save_expr (ffecom_1 (REALPART_EXPR, realtype,
9995 node1));
9996 b = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
9997 node1));
9998 c = save_expr (ffecom_1 (REALPART_EXPR, realtype,
9999 node2));
10000 d = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
10001 node2));
10002 item =
10003 ffecom_2 (COMPLEX_EXPR, type,
10004 ffecom_2 (MINUS_EXPR, realtype,
10005 ffecom_2 (MULT_EXPR, realtype,
10006 a,
10007 c),
10008 ffecom_2 (MULT_EXPR, realtype,
10009 b,
10010 d)),
10011 ffecom_2 (PLUS_EXPR, realtype,
10012 ffecom_2 (MULT_EXPR, realtype,
10013 a,
10014 d),
10015 ffecom_2 (MULT_EXPR, realtype,
10016 c,
10017 b)));
10018 break;
5ff904cd 10019
c7e4ee3a
CB
10020 case EQ_EXPR:
10021 if ((TREE_CODE (node1) != RECORD_TYPE)
10022 && (TREE_CODE (node2) != RECORD_TYPE))
10023 {
10024 item = build (code, type, node1, node2);
10025 break;
10026 }
10027 assert (TREE_CODE (node1) == RECORD_TYPE);
10028 assert (TREE_CODE (node2) == RECORD_TYPE);
10029 node1 = ffecom_stabilize_aggregate_ (node1);
10030 node2 = ffecom_stabilize_aggregate_ (node2);
10031 realtype = TREE_TYPE (TYPE_FIELDS (type));
10032 item =
10033 ffecom_2 (TRUTH_ANDIF_EXPR, type,
10034 ffecom_2 (code, type,
10035 ffecom_1 (REALPART_EXPR, realtype,
10036 node1),
10037 ffecom_1 (REALPART_EXPR, realtype,
10038 node2)),
10039 ffecom_2 (code, type,
10040 ffecom_1 (IMAGPART_EXPR, realtype,
10041 node1),
10042 ffecom_1 (IMAGPART_EXPR, realtype,
10043 node2)));
10044 break;
10045
10046 case NE_EXPR:
10047 if ((TREE_CODE (node1) != RECORD_TYPE)
10048 && (TREE_CODE (node2) != RECORD_TYPE))
10049 {
10050 item = build (code, type, node1, node2);
10051 break;
10052 }
10053 assert (TREE_CODE (node1) == RECORD_TYPE);
10054 assert (TREE_CODE (node2) == RECORD_TYPE);
10055 node1 = ffecom_stabilize_aggregate_ (node1);
10056 node2 = ffecom_stabilize_aggregate_ (node2);
10057 realtype = TREE_TYPE (TYPE_FIELDS (type));
10058 item =
10059 ffecom_2 (TRUTH_ORIF_EXPR, type,
10060 ffecom_2 (code, type,
10061 ffecom_1 (REALPART_EXPR, realtype,
10062 node1),
10063 ffecom_1 (REALPART_EXPR, realtype,
10064 node2)),
10065 ffecom_2 (code, type,
10066 ffecom_1 (IMAGPART_EXPR, realtype,
10067 node1),
10068 ffecom_1 (IMAGPART_EXPR, realtype,
10069 node2)));
10070 break;
5ff904cd 10071
c7e4ee3a
CB
10072 default:
10073 item = build (code, type, node1, node2);
10074 break;
5ff904cd
JL
10075 }
10076
c7e4ee3a
CB
10077 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2))
10078 TREE_SIDE_EFFECTS (item) = 1;
10079 return fold (item);
5ff904cd
JL
10080}
10081
10082#endif
c7e4ee3a 10083/* ffecom_2pass_advise_entrypoint -- Advise that there's this entrypoint
5ff904cd 10084
c7e4ee3a
CB
10085 ffesymbol s; // the ENTRY point itself
10086 if (ffecom_2pass_advise_entrypoint(s))
10087 // the ENTRY point has been accepted
5ff904cd 10088
c7e4ee3a
CB
10089 Does whatever compiler needs to do when it learns about the entrypoint,
10090 like determine the return type of the master function, count the
10091 number of entrypoints, etc. Returns FALSE if the return type is
10092 not compatible with the return type(s) of other entrypoint(s).
5ff904cd 10093
c7e4ee3a
CB
10094 NOTE: for every call to this fn that returns TRUE, _do_entrypoint must
10095 later (after _finish_progunit) be called with the same entrypoint(s)
10096 as passed to this fn for which TRUE was returned.
5ff904cd 10097
c7e4ee3a
CB
10098 03-Jan-92 JCB 2.0
10099 Return FALSE if the return type conflicts with previous entrypoints. */
5ff904cd
JL
10100
10101#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
10102bool
10103ffecom_2pass_advise_entrypoint (ffesymbol entry)
5ff904cd 10104{
c7e4ee3a
CB
10105 ffebld list; /* opITEM. */
10106 ffebld mlist; /* opITEM. */
10107 ffebld plist; /* opITEM. */
10108 ffebld arg; /* ffebld_head(opITEM). */
10109 ffebld item; /* opITEM. */
10110 ffesymbol s; /* ffebld_symter(arg). */
10111 ffeinfoBasictype bt = ffesymbol_basictype (entry);
10112 ffeinfoKindtype kt = ffesymbol_kindtype (entry);
10113 ffetargetCharacterSize size = ffesymbol_size (entry);
10114 bool ok;
5ff904cd 10115
c7e4ee3a
CB
10116 if (ffecom_num_entrypoints_ == 0)
10117 { /* First entrypoint, make list of main
10118 arglist's dummies. */
10119 assert (ffecom_primary_entry_ != NULL);
5ff904cd 10120
c7e4ee3a
CB
10121 ffecom_master_bt_ = ffesymbol_basictype (ffecom_primary_entry_);
10122 ffecom_master_kt_ = ffesymbol_kindtype (ffecom_primary_entry_);
10123 ffecom_master_size_ = ffesymbol_size (ffecom_primary_entry_);
5ff904cd 10124
c7e4ee3a
CB
10125 for (plist = NULL, list = ffesymbol_dummyargs (ffecom_primary_entry_);
10126 list != NULL;
10127 list = ffebld_trail (list))
10128 {
10129 arg = ffebld_head (list);
10130 if (ffebld_op (arg) != FFEBLD_opSYMTER)
10131 continue; /* Alternate return or some such thing. */
10132 item = ffebld_new_item (arg, NULL);
10133 if (plist == NULL)
10134 ffecom_master_arglist_ = item;
10135 else
10136 ffebld_set_trail (plist, item);
10137 plist = item;
10138 }
5ff904cd
JL
10139 }
10140
c7e4ee3a
CB
10141 /* If necessary, scan entry arglist for alternate returns. Do this scan
10142 apparently redundantly (it's done below to UNIONize the arglists) so
10143 that we don't complain about RETURN 1 if an offending ENTRY is the only
10144 one with an alternate return. */
5ff904cd 10145
c7e4ee3a 10146 if (!ffecom_is_altreturning_)
5ff904cd 10147 {
c7e4ee3a
CB
10148 for (list = ffesymbol_dummyargs (entry);
10149 list != NULL;
10150 list = ffebld_trail (list))
10151 {
10152 arg = ffebld_head (list);
10153 if (ffebld_op (arg) == FFEBLD_opSTAR)
10154 {
10155 ffecom_is_altreturning_ = TRUE;
10156 break;
10157 }
10158 }
10159 }
5ff904cd 10160
c7e4ee3a 10161 /* Now check type compatibility. */
5ff904cd 10162
c7e4ee3a
CB
10163 switch (ffecom_master_bt_)
10164 {
10165 case FFEINFO_basictypeNONE:
10166 ok = (bt != FFEINFO_basictypeCHARACTER);
10167 break;
5ff904cd 10168
c7e4ee3a
CB
10169 case FFEINFO_basictypeCHARACTER:
10170 ok
10171 = (bt == FFEINFO_basictypeCHARACTER)
10172 && (kt == ffecom_master_kt_)
10173 && (size == ffecom_master_size_);
10174 break;
5ff904cd 10175
c7e4ee3a
CB
10176 case FFEINFO_basictypeANY:
10177 return FALSE; /* Just don't bother. */
5ff904cd 10178
c7e4ee3a
CB
10179 default:
10180 if (bt == FFEINFO_basictypeCHARACTER)
5ff904cd 10181 {
c7e4ee3a
CB
10182 ok = FALSE;
10183 break;
5ff904cd 10184 }
c7e4ee3a
CB
10185 ok = TRUE;
10186 if ((bt != ffecom_master_bt_) || (kt != ffecom_master_kt_))
10187 {
10188 ffecom_master_bt_ = FFEINFO_basictypeNONE;
10189 ffecom_master_kt_ = FFEINFO_kindtypeNONE;
10190 }
10191 break;
10192 }
5ff904cd 10193
c7e4ee3a
CB
10194 if (!ok)
10195 {
10196 ffebad_start (FFEBAD_ENTRY_CONFLICTS);
10197 ffest_ffebad_here_current_stmt (0);
10198 ffebad_finish ();
10199 return FALSE; /* Can't handle entrypoint. */
10200 }
5ff904cd 10201
c7e4ee3a 10202 /* Entrypoint type compatible with previous types. */
5ff904cd 10203
c7e4ee3a 10204 ++ffecom_num_entrypoints_;
5ff904cd 10205
c7e4ee3a
CB
10206 /* Master-arg-list = UNION(Master-arg-list,entry-arg-list). */
10207
10208 for (list = ffesymbol_dummyargs (entry);
10209 list != NULL;
10210 list = ffebld_trail (list))
10211 {
10212 arg = ffebld_head (list);
10213 if (ffebld_op (arg) != FFEBLD_opSYMTER)
10214 continue; /* Alternate return or some such thing. */
10215 s = ffebld_symter (arg);
10216 for (plist = NULL, mlist = ffecom_master_arglist_;
10217 mlist != NULL;
10218 plist = mlist, mlist = ffebld_trail (mlist))
10219 { /* plist points to previous item for easy
10220 appending of arg. */
10221 if (ffebld_symter (ffebld_head (mlist)) == s)
10222 break; /* Already have this arg in the master list. */
10223 }
10224 if (mlist != NULL)
10225 continue; /* Already have this arg in the master list. */
5ff904cd 10226
c7e4ee3a 10227 /* Append this arg to the master list. */
5ff904cd 10228
c7e4ee3a
CB
10229 item = ffebld_new_item (arg, NULL);
10230 if (plist == NULL)
10231 ffecom_master_arglist_ = item;
10232 else
10233 ffebld_set_trail (plist, item);
5ff904cd
JL
10234 }
10235
c7e4ee3a 10236 return TRUE;
5ff904cd
JL
10237}
10238
10239#endif
c7e4ee3a
CB
10240/* ffecom_2pass_do_entrypoint -- Do compilation of entrypoint
10241
10242 ffesymbol s; // the ENTRY point itself
10243 ffecom_2pass_do_entrypoint(s);
10244
10245 Does whatever compiler needs to do to make the entrypoint actually
10246 happen. Must be called for each entrypoint after
10247 ffecom_finish_progunit is called. */
10248
5ff904cd 10249#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
10250void
10251ffecom_2pass_do_entrypoint (ffesymbol entry)
5ff904cd 10252{
c7e4ee3a
CB
10253 static int mfn_num = 0;
10254 static int ent_num;
5ff904cd 10255
c7e4ee3a
CB
10256 if (mfn_num != ffecom_num_fns_)
10257 { /* First entrypoint for this program unit. */
10258 ent_num = 1;
10259 mfn_num = ffecom_num_fns_;
10260 ffecom_do_entry_ (ffecom_primary_entry_, 0);
10261 }
10262 else
10263 ++ent_num;
5ff904cd 10264
c7e4ee3a 10265 --ffecom_num_entrypoints_;
5ff904cd 10266
c7e4ee3a
CB
10267 ffecom_do_entry_ (entry, ent_num);
10268}
5ff904cd 10269
c7e4ee3a 10270#endif
5ff904cd 10271
c7e4ee3a
CB
10272/* Essentially does a "fold (build (code, type, node1, node2))" while
10273 checking for certain housekeeping things. Always sets
10274 TREE_SIDE_EFFECTS. */
5ff904cd 10275
c7e4ee3a
CB
10276#if FFECOM_targetCURRENT == FFECOM_targetGCC
10277tree
10278ffecom_2s (enum tree_code code, tree type, tree node1,
10279 tree node2)
10280{
10281 tree item;
5ff904cd 10282
c7e4ee3a
CB
10283 if ((node1 == error_mark_node)
10284 || (node2 == error_mark_node)
10285 || (type == error_mark_node))
10286 return error_mark_node;
5ff904cd 10287
c7e4ee3a
CB
10288 item = build (code, type, node1, node2);
10289 TREE_SIDE_EFFECTS (item) = 1;
10290 return fold (item);
5ff904cd
JL
10291}
10292
10293#endif
c7e4ee3a
CB
10294/* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10295 checking for certain housekeeping things. */
10296
5ff904cd 10297#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
10298tree
10299ffecom_3 (enum tree_code code, tree type, tree node1,
10300 tree node2, tree node3)
5ff904cd 10301{
c7e4ee3a 10302 tree item;
5ff904cd 10303
c7e4ee3a
CB
10304 if ((node1 == error_mark_node)
10305 || (node2 == error_mark_node)
10306 || (node3 == error_mark_node)
10307 || (type == error_mark_node))
10308 return error_mark_node;
5ff904cd 10309
c7e4ee3a
CB
10310 item = build (code, type, node1, node2, node3);
10311 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2)
10312 || (node3 != NULL_TREE && TREE_SIDE_EFFECTS (node3)))
10313 TREE_SIDE_EFFECTS (item) = 1;
10314 return fold (item);
10315}
5ff904cd 10316
c7e4ee3a
CB
10317#endif
10318/* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10319 checking for certain housekeeping things. Always sets
10320 TREE_SIDE_EFFECTS. */
5ff904cd 10321
c7e4ee3a
CB
10322#if FFECOM_targetCURRENT == FFECOM_targetGCC
10323tree
10324ffecom_3s (enum tree_code code, tree type, tree node1,
10325 tree node2, tree node3)
10326{
10327 tree item;
5ff904cd 10328
c7e4ee3a
CB
10329 if ((node1 == error_mark_node)
10330 || (node2 == error_mark_node)
10331 || (node3 == error_mark_node)
10332 || (type == error_mark_node))
10333 return error_mark_node;
5ff904cd 10334
c7e4ee3a
CB
10335 item = build (code, type, node1, node2, node3);
10336 TREE_SIDE_EFFECTS (item) = 1;
10337 return fold (item);
10338}
5ff904cd 10339
c7e4ee3a 10340#endif
5ff904cd 10341
c7e4ee3a 10342/* ffecom_arg_expr -- Transform argument expr into gcc tree
5ff904cd 10343
c7e4ee3a 10344 See use by ffecom_list_expr.
5ff904cd 10345
c7e4ee3a
CB
10346 If expression is NULL, returns an integer zero tree. If it is not
10347 a CHARACTER expression, returns whatever ffecom_expr
10348 returns and sets the length return value to NULL_TREE. Otherwise
10349 generates code to evaluate the character expression, returns the proper
10350 pointer to the result, but does NOT set the length return value to a tree
10351 that specifies the length of the result. (In other words, the length
10352 variable is always set to NULL_TREE, because a length is never passed.)
5ff904cd 10353
c7e4ee3a
CB
10354 21-Dec-91 JCB 1.1
10355 Don't set returned length, since nobody needs it (yet; someday if
10356 we allow CHARACTER*(*) dummies to statement functions, we'll need
10357 it). */
5ff904cd 10358
c7e4ee3a
CB
10359#if FFECOM_targetCURRENT == FFECOM_targetGCC
10360tree
10361ffecom_arg_expr (ffebld expr, tree *length)
10362{
10363 tree ign;
5ff904cd 10364
c7e4ee3a 10365 *length = NULL_TREE;
5ff904cd 10366
c7e4ee3a
CB
10367 if (expr == NULL)
10368 return integer_zero_node;
5ff904cd 10369
c7e4ee3a
CB
10370 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10371 return ffecom_expr (expr);
5ff904cd 10372
c7e4ee3a
CB
10373 return ffecom_arg_ptr_to_expr (expr, &ign);
10374}
10375
10376#endif
10377/* Transform expression into constant argument-pointer-to-expression tree.
10378
10379 If the expression can be transformed into a argument-pointer-to-expression
10380 tree that is constant, that is done, and the tree returned. Else
10381 NULL_TREE is returned.
5ff904cd 10382
c7e4ee3a
CB
10383 That way, a caller can attempt to provide compile-time initialization
10384 of a variable and, if that fails, *then* choose to start a new block
10385 and resort to using temporaries, as appropriate. */
5ff904cd 10386
c7e4ee3a
CB
10387tree
10388ffecom_arg_ptr_to_const_expr (ffebld expr, tree *length)
10389{
10390 if (! expr)
10391 return integer_zero_node;
5ff904cd 10392
c7e4ee3a
CB
10393 if (ffebld_op (expr) == FFEBLD_opANY)
10394 {
10395 if (length)
10396 *length = error_mark_node;
10397 return error_mark_node;
10398 }
10399
10400 if (ffebld_arity (expr) == 0
10401 && (ffebld_op (expr) != FFEBLD_opSYMTER
10402 || ffebld_where (expr) == FFEINFO_whereCOMMON
10403 || ffebld_where (expr) == FFEINFO_whereGLOBAL
10404 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
10405 {
10406 tree t;
10407
10408 t = ffecom_arg_ptr_to_expr (expr, length);
10409 assert (TREE_CONSTANT (t));
10410 assert (! length || TREE_CONSTANT (*length));
10411 return t;
10412 }
10413
10414 if (length
10415 && ffebld_size (expr) != FFETARGET_charactersizeNONE)
10416 *length = build_int_2 (ffebld_size (expr), 0);
10417 else if (length)
10418 *length = NULL_TREE;
10419 return NULL_TREE;
5ff904cd
JL
10420}
10421
c7e4ee3a 10422/* ffecom_arg_ptr_to_expr -- Transform argument expr into gcc tree
5ff904cd 10423
c7e4ee3a
CB
10424 See use by ffecom_list_ptr_to_expr.
10425
10426 If expression is NULL, returns an integer zero tree. If it is not
10427 a CHARACTER expression, returns whatever ffecom_ptr_to_expr
10428 returns and sets the length return value to NULL_TREE. Otherwise
10429 generates code to evaluate the character expression, returns the proper
10430 pointer to the result, AND sets the length return value to a tree that
10431 specifies the length of the result.
10432
10433 If the length argument is NULL, this is a slightly special
10434 case of building a FORMAT expression, that is, an expression that
10435 will be used at run time without regard to length. For the current
10436 implementation, which uses the libf2c library, this means it is nice
10437 to append a null byte to the end of the expression, where feasible,
10438 to make sure any diagnostic about the FORMAT string terminates at
10439 some useful point.
10440
10441 For now, treat %REF(char-expr) as the same as char-expr with a NULL
10442 length argument. This might even be seen as a feature, if a null
10443 byte can always be appended. */
5ff904cd
JL
10444
10445#if FFECOM_targetCURRENT == FFECOM_targetGCC
10446tree
c7e4ee3a 10447ffecom_arg_ptr_to_expr (ffebld expr, tree *length)
5ff904cd
JL
10448{
10449 tree item;
c7e4ee3a
CB
10450 tree ign_length;
10451 ffecomConcatList_ catlist;
5ff904cd 10452
c7e4ee3a
CB
10453 if (length != NULL)
10454 *length = NULL_TREE;
5ff904cd 10455
c7e4ee3a
CB
10456 if (expr == NULL)
10457 return integer_zero_node;
5ff904cd 10458
c7e4ee3a 10459 switch (ffebld_op (expr))
5ff904cd 10460 {
c7e4ee3a
CB
10461 case FFEBLD_opPERCENT_VAL:
10462 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10463 return ffecom_expr (ffebld_left (expr));
10464 {
10465 tree temp_exp;
10466 tree temp_length;
5ff904cd 10467
c7e4ee3a
CB
10468 temp_exp = ffecom_arg_ptr_to_expr (ffebld_left (expr), &temp_length);
10469 if (temp_exp == error_mark_node)
10470 return error_mark_node;
5ff904cd 10471
c7e4ee3a
CB
10472 return ffecom_1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (temp_exp)),
10473 temp_exp);
10474 }
5ff904cd 10475
c7e4ee3a
CB
10476 case FFEBLD_opPERCENT_REF:
10477 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10478 return ffecom_ptr_to_expr (ffebld_left (expr));
10479 if (length != NULL)
10480 {
10481 ign_length = NULL_TREE;
10482 length = &ign_length;
10483 }
10484 expr = ffebld_left (expr);
10485 break;
5ff904cd 10486
c7e4ee3a
CB
10487 case FFEBLD_opPERCENT_DESCR:
10488 switch (ffeinfo_basictype (ffebld_info (expr)))
5ff904cd 10489 {
c7e4ee3a
CB
10490#ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10491 case FFEINFO_basictypeHOLLERITH:
10492#endif
10493 case FFEINFO_basictypeCHARACTER:
10494 break; /* Passed by descriptor anyway. */
10495
10496 default:
10497 item = ffecom_ptr_to_expr (expr);
10498 if (item != error_mark_node)
10499 *length = TYPE_SIZE (TREE_TYPE (TREE_TYPE (item)));
5ff904cd
JL
10500 break;
10501 }
5ff904cd
JL
10502 break;
10503
10504 default:
5ff904cd
JL
10505 break;
10506 }
10507
c7e4ee3a
CB
10508#ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10509 if ((ffeinfo_basictype (ffebld_info (expr)) == FFEINFO_basictypeHOLLERITH)
10510 && (length != NULL))
10511 { /* Pass Hollerith by descriptor. */
10512 ffetargetHollerith h;
10513
10514 assert (ffebld_op (expr) == FFEBLD_opCONTER);
10515 h = ffebld_cu_val_hollerith (ffebld_constant_union
10516 (ffebld_conter (expr)));
10517 *length
10518 = build_int_2 (h.length, 0);
10519 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10520 }
10521#endif
10522
10523 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10524 return ffecom_ptr_to_expr (expr);
10525
10526 assert (ffeinfo_kindtype (ffebld_info (expr))
10527 == FFEINFO_kindtypeCHARACTER1);
10528
10529 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
10530 switch (ffecom_concat_list_count_ (catlist))
10531 {
10532 case 0: /* Shouldn't happen, but in case it does... */
10533 if (length != NULL)
10534 {
10535 *length = ffecom_f2c_ftnlen_zero_node;
10536 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10537 }
10538 ffecom_concat_list_kill_ (catlist);
10539 return null_pointer_node;
10540
10541 case 1: /* The (fairly) easy case. */
10542 if (length == NULL)
10543 ffecom_char_args_with_null_ (&item, &ign_length,
10544 ffecom_concat_list_expr_ (catlist, 0));
10545 else
10546 ffecom_char_args_ (&item, length,
10547 ffecom_concat_list_expr_ (catlist, 0));
10548 ffecom_concat_list_kill_ (catlist);
10549 assert (item != NULL_TREE);
10550 return item;
10551
10552 default: /* Must actually concatenate things. */
10553 break;
10554 }
10555
10556 {
10557 int count = ffecom_concat_list_count_ (catlist);
10558 int i;
10559 tree lengths;
10560 tree items;
10561 tree length_array;
10562 tree item_array;
10563 tree citem;
10564 tree clength;
10565 tree temporary;
10566 tree num;
10567 tree known_length;
10568 ffetargetCharacterSize sz;
10569
10570 sz = ffecom_concat_list_maxlen_ (catlist);
10571 /* ~~Kludge! */
10572 assert (sz != FFETARGET_charactersizeNONE);
10573
10574#ifdef HOHO
10575 length_array
10576 = lengths
10577 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
10578 FFETARGET_charactersizeNONE, count, TRUE);
10579 item_array
10580 = items
10581 = ffecom_push_tempvar (ffecom_f2c_address_type_node,
10582 FFETARGET_charactersizeNONE, count, TRUE);
10583 temporary = ffecom_push_tempvar (char_type_node,
10584 sz, -1, TRUE);
10585#else
10586 {
10587 tree hook;
10588
10589 hook = ffebld_nonter_hook (expr);
10590 assert (hook);
10591 assert (TREE_CODE (hook) == TREE_VEC);
10592 assert (TREE_VEC_LENGTH (hook) == 3);
10593 length_array = lengths = TREE_VEC_ELT (hook, 0);
10594 item_array = items = TREE_VEC_ELT (hook, 1);
10595 temporary = TREE_VEC_ELT (hook, 2);
10596 }
10597#endif
10598
10599 known_length = ffecom_f2c_ftnlen_zero_node;
10600
10601 for (i = 0; i < count; ++i)
10602 {
10603 if ((i == count)
10604 && (length == NULL))
10605 ffecom_char_args_with_null_ (&citem, &clength,
10606 ffecom_concat_list_expr_ (catlist, i));
10607 else
10608 ffecom_char_args_ (&citem, &clength,
10609 ffecom_concat_list_expr_ (catlist, i));
10610 if ((citem == error_mark_node)
10611 || (clength == error_mark_node))
10612 {
10613 ffecom_concat_list_kill_ (catlist);
10614 *length = error_mark_node;
10615 return error_mark_node;
10616 }
10617
10618 items
10619 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
10620 ffecom_modify (void_type_node,
10621 ffecom_2 (ARRAY_REF,
10622 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
10623 item_array,
10624 build_int_2 (i, 0)),
10625 citem),
10626 items);
10627 clength = ffecom_save_tree (clength);
10628 if (length != NULL)
10629 known_length
10630 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
10631 known_length,
10632 clength);
10633 lengths
10634 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
10635 ffecom_modify (void_type_node,
10636 ffecom_2 (ARRAY_REF,
10637 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
10638 length_array,
10639 build_int_2 (i, 0)),
10640 clength),
10641 lengths);
10642 }
10643
10644 temporary = ffecom_1 (ADDR_EXPR,
10645 build_pointer_type (TREE_TYPE (temporary)),
10646 temporary);
10647
10648 item = build_tree_list (NULL_TREE, temporary);
10649 TREE_CHAIN (item)
10650 = build_tree_list (NULL_TREE,
10651 ffecom_1 (ADDR_EXPR,
10652 build_pointer_type (TREE_TYPE (items)),
10653 items));
10654 TREE_CHAIN (TREE_CHAIN (item))
10655 = build_tree_list (NULL_TREE,
10656 ffecom_1 (ADDR_EXPR,
10657 build_pointer_type (TREE_TYPE (lengths)),
10658 lengths));
10659 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
10660 = build_tree_list
10661 (NULL_TREE,
10662 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
10663 convert (ffecom_f2c_ftnlen_type_node,
10664 build_int_2 (count, 0))));
10665 num = build_int_2 (sz, 0);
10666 TREE_TYPE (num) = ffecom_f2c_ftnlen_type_node;
10667 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item))))
10668 = build_tree_list (NULL_TREE, num);
10669
10670 item = ffecom_call_gfrt (FFECOM_gfrtCAT, item, NULL_TREE);
5ff904cd 10671 TREE_SIDE_EFFECTS (item) = 1;
c7e4ee3a
CB
10672 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (temporary),
10673 item,
10674 temporary);
10675
10676 if (length != NULL)
10677 *length = known_length;
10678 }
10679
10680 ffecom_concat_list_kill_ (catlist);
10681 assert (item != NULL_TREE);
10682 return item;
5ff904cd 10683}
c7e4ee3a 10684
5ff904cd 10685#endif
c7e4ee3a 10686/* Generate call to run-time function.
5ff904cd 10687
c7e4ee3a
CB
10688 The first arg is the GNU Fortran Run-Time function index, the second
10689 arg is the list of arguments to pass to it. Returned is the expression
10690 (WITHOUT TREE_SIDE_EFFECTS set!) that makes the call and returns the
10691 result (which may be void). */
5ff904cd
JL
10692
10693#if FFECOM_targetCURRENT == FFECOM_targetGCC
10694tree
c7e4ee3a 10695ffecom_call_gfrt (ffecomGfrt ix, tree args, tree hook)
5ff904cd 10696{
c7e4ee3a
CB
10697 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
10698 ffecom_gfrt_kindtype (ix),
10699 ffe_is_f2c_library () && ffecom_gfrt_complex_[ix],
10700 NULL_TREE, args, NULL_TREE, NULL,
10701 NULL, NULL_TREE, TRUE, hook);
5ff904cd
JL
10702}
10703#endif
10704
c7e4ee3a 10705/* Transform constant-union to tree. */
5ff904cd
JL
10706
10707#if FFECOM_targetCURRENT == FFECOM_targetGCC
10708tree
c7e4ee3a
CB
10709ffecom_constantunion (ffebldConstantUnion *cu, ffeinfoBasictype bt,
10710 ffeinfoKindtype kt, tree tree_type)
5ff904cd
JL
10711{
10712 tree item;
10713
c7e4ee3a 10714 switch (bt)
5ff904cd 10715 {
c7e4ee3a
CB
10716 case FFEINFO_basictypeINTEGER:
10717 {
10718 int val;
5ff904cd 10719
c7e4ee3a
CB
10720 switch (kt)
10721 {
10722#if FFETARGET_okINTEGER1
10723 case FFEINFO_kindtypeINTEGER1:
10724 val = ffebld_cu_val_integer1 (*cu);
10725 break;
10726#endif
5ff904cd 10727
c7e4ee3a
CB
10728#if FFETARGET_okINTEGER2
10729 case FFEINFO_kindtypeINTEGER2:
10730 val = ffebld_cu_val_integer2 (*cu);
10731 break;
10732#endif
5ff904cd 10733
c7e4ee3a
CB
10734#if FFETARGET_okINTEGER3
10735 case FFEINFO_kindtypeINTEGER3:
10736 val = ffebld_cu_val_integer3 (*cu);
10737 break;
10738#endif
5ff904cd 10739
c7e4ee3a
CB
10740#if FFETARGET_okINTEGER4
10741 case FFEINFO_kindtypeINTEGER4:
10742 val = ffebld_cu_val_integer4 (*cu);
10743 break;
10744#endif
5ff904cd 10745
c7e4ee3a
CB
10746 default:
10747 assert ("bad INTEGER constant kind type" == NULL);
10748 /* Fall through. */
10749 case FFEINFO_kindtypeANY:
10750 return error_mark_node;
10751 }
10752 item = build_int_2 (val, (val < 0) ? -1 : 0);
10753 TREE_TYPE (item) = tree_type;
10754 }
5ff904cd 10755 break;
5ff904cd 10756
c7e4ee3a
CB
10757 case FFEINFO_basictypeLOGICAL:
10758 {
10759 int val;
5ff904cd 10760
c7e4ee3a
CB
10761 switch (kt)
10762 {
10763#if FFETARGET_okLOGICAL1
10764 case FFEINFO_kindtypeLOGICAL1:
10765 val = ffebld_cu_val_logical1 (*cu);
10766 break;
5ff904cd 10767#endif
5ff904cd 10768
c7e4ee3a
CB
10769#if FFETARGET_okLOGICAL2
10770 case FFEINFO_kindtypeLOGICAL2:
10771 val = ffebld_cu_val_logical2 (*cu);
10772 break;
10773#endif
5ff904cd 10774
c7e4ee3a
CB
10775#if FFETARGET_okLOGICAL3
10776 case FFEINFO_kindtypeLOGICAL3:
10777 val = ffebld_cu_val_logical3 (*cu);
10778 break;
10779#endif
5ff904cd 10780
c7e4ee3a
CB
10781#if FFETARGET_okLOGICAL4
10782 case FFEINFO_kindtypeLOGICAL4:
10783 val = ffebld_cu_val_logical4 (*cu);
10784 break;
10785#endif
5ff904cd 10786
c7e4ee3a
CB
10787 default:
10788 assert ("bad LOGICAL constant kind type" == NULL);
10789 /* Fall through. */
10790 case FFEINFO_kindtypeANY:
10791 return error_mark_node;
10792 }
10793 item = build_int_2 (val, (val < 0) ? -1 : 0);
10794 TREE_TYPE (item) = tree_type;
10795 }
10796 break;
5ff904cd 10797
c7e4ee3a
CB
10798 case FFEINFO_basictypeREAL:
10799 {
10800 REAL_VALUE_TYPE val;
5ff904cd 10801
c7e4ee3a
CB
10802 switch (kt)
10803 {
10804#if FFETARGET_okREAL1
10805 case FFEINFO_kindtypeREAL1:
10806 val = ffetarget_value_real1 (ffebld_cu_val_real1 (*cu));
10807 break;
10808#endif
5ff904cd 10809
c7e4ee3a
CB
10810#if FFETARGET_okREAL2
10811 case FFEINFO_kindtypeREAL2:
10812 val = ffetarget_value_real2 (ffebld_cu_val_real2 (*cu));
10813 break;
10814#endif
5ff904cd 10815
c7e4ee3a
CB
10816#if FFETARGET_okREAL3
10817 case FFEINFO_kindtypeREAL3:
10818 val = ffetarget_value_real3 (ffebld_cu_val_real3 (*cu));
10819 break;
10820#endif
5ff904cd 10821
c7e4ee3a
CB
10822#if FFETARGET_okREAL4
10823 case FFEINFO_kindtypeREAL4:
10824 val = ffetarget_value_real4 (ffebld_cu_val_real4 (*cu));
10825 break;
10826#endif
5ff904cd 10827
c7e4ee3a
CB
10828 default:
10829 assert ("bad REAL constant kind type" == NULL);
10830 /* Fall through. */
10831 case FFEINFO_kindtypeANY:
10832 return error_mark_node;
10833 }
10834 item = build_real (tree_type, val);
10835 }
5ff904cd
JL
10836 break;
10837
c7e4ee3a
CB
10838 case FFEINFO_basictypeCOMPLEX:
10839 {
10840 REAL_VALUE_TYPE real;
10841 REAL_VALUE_TYPE imag;
10842 tree el_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
5ff904cd 10843
c7e4ee3a
CB
10844 switch (kt)
10845 {
10846#if FFETARGET_okCOMPLEX1
10847 case FFEINFO_kindtypeREAL1:
10848 real = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).real);
10849 imag = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).imaginary);
10850 break;
10851#endif
5ff904cd 10852
c7e4ee3a
CB
10853#if FFETARGET_okCOMPLEX2
10854 case FFEINFO_kindtypeREAL2:
10855 real = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).real);
10856 imag = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).imaginary);
10857 break;
10858#endif
5ff904cd 10859
c7e4ee3a
CB
10860#if FFETARGET_okCOMPLEX3
10861 case FFEINFO_kindtypeREAL3:
10862 real = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).real);
10863 imag = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).imaginary);
10864 break;
10865#endif
5ff904cd 10866
c7e4ee3a
CB
10867#if FFETARGET_okCOMPLEX4
10868 case FFEINFO_kindtypeREAL4:
10869 real = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).real);
10870 imag = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).imaginary);
10871 break;
10872#endif
5ff904cd 10873
c7e4ee3a
CB
10874 default:
10875 assert ("bad REAL constant kind type" == NULL);
10876 /* Fall through. */
10877 case FFEINFO_kindtypeANY:
10878 return error_mark_node;
10879 }
10880 item = ffecom_build_complex_constant_ (tree_type,
10881 build_real (el_type, real),
10882 build_real (el_type, imag));
10883 }
10884 break;
5ff904cd 10885
c7e4ee3a
CB
10886 case FFEINFO_basictypeCHARACTER:
10887 { /* Happens only in DATA and similar contexts. */
10888 ffetargetCharacter1 val;
5ff904cd 10889
c7e4ee3a
CB
10890 switch (kt)
10891 {
10892#if FFETARGET_okCHARACTER1
10893 case FFEINFO_kindtypeLOGICAL1:
10894 val = ffebld_cu_val_character1 (*cu);
10895 break;
10896#endif
10897
10898 default:
10899 assert ("bad CHARACTER constant kind type" == NULL);
10900 /* Fall through. */
10901 case FFEINFO_kindtypeANY:
10902 return error_mark_node;
10903 }
10904 item = build_string (ffetarget_length_character1 (val),
10905 ffetarget_text_character1 (val));
10906 TREE_TYPE (item)
10907 = build_type_variant (build_array_type (char_type_node,
10908 build_range_type
10909 (integer_type_node,
10910 integer_one_node,
10911 build_int_2
10912 (ffetarget_length_character1
10913 (val), 0))),
10914 1, 0);
10915 }
10916 break;
5ff904cd 10917
c7e4ee3a
CB
10918 case FFEINFO_basictypeHOLLERITH:
10919 {
10920 ffetargetHollerith h;
5ff904cd 10921
c7e4ee3a 10922 h = ffebld_cu_val_hollerith (*cu);
5ff904cd 10923
c7e4ee3a
CB
10924 /* If not at least as wide as default INTEGER, widen it. */
10925 if (h.length >= FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE)
10926 item = build_string (h.length, h.text);
10927 else
10928 {
10929 char str[FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE];
5ff904cd 10930
c7e4ee3a
CB
10931 memcpy (str, h.text, h.length);
10932 memset (&str[h.length], ' ',
10933 FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE
10934 - h.length);
10935 item = build_string (FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE,
10936 str);
10937 }
10938 TREE_TYPE (item)
10939 = build_type_variant (build_array_type (char_type_node,
10940 build_range_type
10941 (integer_type_node,
10942 integer_one_node,
10943 build_int_2
10944 (h.length, 0))),
10945 1, 0);
10946 }
10947 break;
5ff904cd 10948
c7e4ee3a
CB
10949 case FFEINFO_basictypeTYPELESS:
10950 {
10951 ffetargetInteger1 ival;
10952 ffetargetTypeless tless;
10953 ffebad error;
5ff904cd 10954
c7e4ee3a
CB
10955 tless = ffebld_cu_val_typeless (*cu);
10956 error = ffetarget_convert_integer1_typeless (&ival, tless);
10957 assert (error == FFEBAD);
5ff904cd 10958
c7e4ee3a
CB
10959 item = build_int_2 ((int) ival, 0);
10960 }
10961 break;
5ff904cd 10962
c7e4ee3a
CB
10963 default:
10964 assert ("not yet on constant type" == NULL);
10965 /* Fall through. */
10966 case FFEINFO_basictypeANY:
10967 return error_mark_node;
5ff904cd 10968 }
5ff904cd 10969
c7e4ee3a 10970 TREE_CONSTANT (item) = 1;
5ff904cd 10971
c7e4ee3a 10972 return item;
5ff904cd
JL
10973}
10974
10975#endif
10976
c7e4ee3a
CB
10977/* Transform expression into constant tree.
10978
10979 If the expression can be transformed into a tree that is constant,
10980 that is done, and the tree returned. Else NULL_TREE is returned.
10981
10982 That way, a caller can attempt to provide compile-time initialization
10983 of a variable and, if that fails, *then* choose to start a new block
10984 and resort to using temporaries, as appropriate. */
5ff904cd 10985
5ff904cd 10986tree
c7e4ee3a 10987ffecom_const_expr (ffebld expr)
5ff904cd 10988{
c7e4ee3a
CB
10989 if (! expr)
10990 return integer_zero_node;
5ff904cd 10991
c7e4ee3a 10992 if (ffebld_op (expr) == FFEBLD_opANY)
5ff904cd
JL
10993 return error_mark_node;
10994
c7e4ee3a
CB
10995 if (ffebld_arity (expr) == 0
10996 && (ffebld_op (expr) != FFEBLD_opSYMTER
10997#if NEWCOMMON
10998 /* ~~Enable once common/equivalence is handled properly? */
10999 || ffebld_where (expr) == FFEINFO_whereCOMMON
5ff904cd 11000#endif
c7e4ee3a
CB
11001 || ffebld_where (expr) == FFEINFO_whereGLOBAL
11002 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
11003 {
11004 tree t;
5ff904cd 11005
c7e4ee3a
CB
11006 t = ffecom_expr (expr);
11007 assert (TREE_CONSTANT (t));
11008 return t;
11009 }
5ff904cd 11010
c7e4ee3a 11011 return NULL_TREE;
5ff904cd
JL
11012}
11013
c7e4ee3a 11014/* Handy way to make a field in a struct/union. */
5ff904cd
JL
11015
11016#if FFECOM_targetCURRENT == FFECOM_targetGCC
11017tree
c7e4ee3a
CB
11018ffecom_decl_field (tree context, tree prevfield,
11019 const char *name, tree type)
5ff904cd 11020{
c7e4ee3a 11021 tree field;
5ff904cd 11022
c7e4ee3a
CB
11023 field = build_decl (FIELD_DECL, get_identifier (name), type);
11024 DECL_CONTEXT (field) = context;
11025 DECL_FRAME_SIZE (field) = 0;
11026 if (prevfield != NULL_TREE)
11027 TREE_CHAIN (prevfield) = field;
5ff904cd 11028
c7e4ee3a 11029 return field;
5ff904cd
JL
11030}
11031
11032#endif
5ff904cd 11033
c7e4ee3a
CB
11034void
11035ffecom_close_include (FILE *f)
11036{
11037#if FFECOM_GCC_INCLUDE
11038 ffecom_close_include_ (f);
11039#endif
11040}
5ff904cd 11041
c7e4ee3a
CB
11042int
11043ffecom_decode_include_option (char *spec)
11044{
11045#if FFECOM_GCC_INCLUDE
11046 return ffecom_decode_include_option_ (spec);
11047#else
11048 return 1;
11049#endif
11050}
5ff904cd 11051
c7e4ee3a 11052/* End a compound statement (block). */
5ff904cd
JL
11053
11054#if FFECOM_targetCURRENT == FFECOM_targetGCC
11055tree
c7e4ee3a 11056ffecom_end_compstmt (void)
5ff904cd 11057{
c7e4ee3a
CB
11058 return bison_rule_compstmt_ ();
11059}
11060#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
5ff904cd 11061
c7e4ee3a 11062/* ffecom_end_transition -- Perform end transition on all symbols
5ff904cd 11063
c7e4ee3a 11064 ffecom_end_transition();
5ff904cd 11065
c7e4ee3a 11066 Calls ffecom_sym_end_transition for each global and local symbol. */
5ff904cd 11067
c7e4ee3a
CB
11068void
11069ffecom_end_transition ()
11070{
11071#if FFECOM_targetCURRENT == FFECOM_targetGCC
11072 ffebld item;
5ff904cd 11073#endif
5ff904cd 11074
c7e4ee3a
CB
11075 if (ffe_is_ffedebug ())
11076 fprintf (dmpout, "; end_stmt_transition\n");
86fc7a6c 11077
c7e4ee3a
CB
11078#if FFECOM_targetCURRENT == FFECOM_targetGCC
11079 ffecom_list_blockdata_ = NULL;
11080 ffecom_list_common_ = NULL;
11081#endif
86fc7a6c 11082
c7e4ee3a
CB
11083 ffesymbol_drive (ffecom_sym_end_transition);
11084 if (ffe_is_ffedebug ())
11085 {
11086 ffestorag_report ();
11087#if FFECOM_targetCURRENT == FFECOM_targetFFE
11088 ffesymbol_report_all ();
11089#endif
11090 }
5ff904cd
JL
11091
11092#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
11093 ffecom_start_progunit_ ();
11094
11095 for (item = ffecom_list_blockdata_;
11096 item != NULL;
11097 item = ffebld_trail (item))
11098 {
11099 ffebld callee;
11100 ffesymbol s;
11101 tree dt;
11102 tree t;
11103 tree var;
11104 int yes;
11105 static int number = 0;
11106
11107 callee = ffebld_head (item);
11108 s = ffebld_symter (callee);
11109 t = ffesymbol_hook (s).decl_tree;
11110 if (t == NULL_TREE)
11111 {
11112 s = ffecom_sym_transform_ (s);
11113 t = ffesymbol_hook (s).decl_tree;
11114 }
5ff904cd 11115
c7e4ee3a 11116 yes = suspend_momentary ();
5ff904cd 11117
c7e4ee3a 11118 dt = build_pointer_type (TREE_TYPE (t));
5ff904cd 11119
c7e4ee3a
CB
11120 var = build_decl (VAR_DECL,
11121 ffecom_get_invented_identifier ("__g77_forceload_%d",
11122 NULL, number++),
11123 dt);
11124 DECL_EXTERNAL (var) = 0;
11125 TREE_STATIC (var) = 1;
11126 TREE_PUBLIC (var) = 0;
11127 DECL_INITIAL (var) = error_mark_node;
11128 TREE_USED (var) = 1;
5ff904cd 11129
c7e4ee3a 11130 var = start_decl (var, FALSE);
702edf1d 11131
c7e4ee3a 11132 t = ffecom_1 (ADDR_EXPR, dt, t);
5ff904cd 11133
c7e4ee3a 11134 finish_decl (var, t, FALSE);
5ff904cd 11135
c7e4ee3a
CB
11136 resume_momentary (yes);
11137 }
11138
11139 /* This handles any COMMON areas that weren't referenced but have, for
11140 example, important initial data. */
11141
11142 for (item = ffecom_list_common_;
11143 item != NULL;
11144 item = ffebld_trail (item))
11145 ffecom_transform_common_ (ffebld_symter (ffebld_head (item)));
11146
11147 ffecom_list_common_ = NULL;
5ff904cd 11148#endif
c7e4ee3a 11149}
5ff904cd 11150
c7e4ee3a 11151/* ffecom_exec_transition -- Perform exec transition on all symbols
5ff904cd 11152
c7e4ee3a 11153 ffecom_exec_transition();
5ff904cd 11154
c7e4ee3a
CB
11155 Calls ffecom_sym_exec_transition for each global and local symbol.
11156 Make sure error updating not inhibited. */
5ff904cd 11157
c7e4ee3a
CB
11158void
11159ffecom_exec_transition ()
11160{
11161 bool inhibited;
5ff904cd 11162
c7e4ee3a
CB
11163 if (ffe_is_ffedebug ())
11164 fprintf (dmpout, "; exec_stmt_transition\n");
5ff904cd 11165
c7e4ee3a
CB
11166 inhibited = ffebad_inhibit ();
11167 ffebad_set_inhibit (FALSE);
5ff904cd 11168
c7e4ee3a
CB
11169 ffesymbol_drive (ffecom_sym_exec_transition); /* Don't retract! */
11170 ffeequiv_exec_transition (); /* Handle all pending EQUIVALENCEs. */
11171 if (ffe_is_ffedebug ())
5ff904cd 11172 {
c7e4ee3a
CB
11173 ffestorag_report ();
11174#if FFECOM_targetCURRENT == FFECOM_targetFFE
11175 ffesymbol_report_all ();
11176#endif
11177 }
5ff904cd 11178
c7e4ee3a
CB
11179 if (inhibited)
11180 ffebad_set_inhibit (TRUE);
11181}
5ff904cd 11182
c7e4ee3a 11183/* Handle assignment statement.
5ff904cd 11184
c7e4ee3a
CB
11185 Convert dest and source using ffecom_expr, then join them
11186 with an ASSIGN op and pass the whole thing to expand_expr_stmt. */
5ff904cd 11187
c7e4ee3a
CB
11188#if FFECOM_targetCURRENT == FFECOM_targetGCC
11189void
11190ffecom_expand_let_stmt (ffebld dest, ffebld source)
11191{
11192 tree dest_tree;
11193 tree dest_length;
11194 tree source_tree;
11195 tree expr_tree;
5ff904cd 11196
c7e4ee3a
CB
11197 if (ffeinfo_basictype (ffebld_info (dest)) != FFEINFO_basictypeCHARACTER)
11198 {
11199 bool dest_used;
d6cd84e0 11200 tree assign_temp;
5ff904cd 11201
c7e4ee3a
CB
11202 /* This attempts to replicate the test below, but must not be
11203 true when the test below is false. (Always err on the side
11204 of creating unused temporaries, to avoid ICEs.) */
11205 if (ffebld_op (dest) != FFEBLD_opSYMTER
11206 || ((dest_tree = ffesymbol_hook (ffebld_symter (dest)).decl_tree)
11207 && (TREE_CODE (dest_tree) != VAR_DECL
11208 || TREE_ADDRESSABLE (dest_tree))))
11209 {
11210 ffecom_prepare_expr_ (source, dest);
11211 dest_used = TRUE;
11212 }
11213 else
11214 {
11215 ffecom_prepare_expr_ (source, NULL);
11216 dest_used = FALSE;
11217 }
5ff904cd 11218
c7e4ee3a 11219 ffecom_prepare_expr_w (NULL_TREE, dest);
5ff904cd 11220
d6cd84e0
CB
11221 /* For COMPLEX assignment like C1=C2, if partial overlap is possible,
11222 create a temporary through which the assignment is to take place,
11223 since MODIFY_EXPR doesn't handle partial overlap properly. */
11224 if (ffebld_basictype (dest) == FFEINFO_basictypeCOMPLEX
11225 && ffecom_possible_partial_overlap_ (dest, source))
11226 {
11227 assign_temp = ffecom_make_tempvar ("complex_let",
11228 ffecom_tree_type
11229 [ffebld_basictype (dest)]
11230 [ffebld_kindtype (dest)],
11231 FFETARGET_charactersizeNONE,
11232 -1);
11233 }
11234 else
11235 assign_temp = NULL_TREE;
11236
c7e4ee3a 11237 ffecom_prepare_end ();
5ff904cd 11238
c7e4ee3a
CB
11239 dest_tree = ffecom_expr_w (NULL_TREE, dest);
11240 if (dest_tree == error_mark_node)
11241 return;
5ff904cd 11242
c7e4ee3a
CB
11243 if ((TREE_CODE (dest_tree) != VAR_DECL)
11244 || TREE_ADDRESSABLE (dest_tree))
11245 source_tree = ffecom_expr_ (source, dest_tree, dest, &dest_used,
11246 FALSE, FALSE);
11247 else
11248 {
11249 assert (! dest_used);
11250 dest_used = FALSE;
11251 source_tree = ffecom_expr (source);
11252 }
11253 if (source_tree == error_mark_node)
11254 return;
5ff904cd 11255
c7e4ee3a
CB
11256 if (dest_used)
11257 expr_tree = source_tree;
d6cd84e0
CB
11258 else if (assign_temp)
11259 {
11260#ifdef MOVE_EXPR
11261 /* The back end understands a conceptual move (evaluate source;
11262 store into dest), so use that, in case it can determine
11263 that it is going to use, say, two registers as temporaries
11264 anyway. So don't use the temp (and someday avoid generating
11265 it, once this code starts triggering regularly). */
11266 expr_tree = ffecom_2s (MOVE_EXPR, void_type_node,
11267 dest_tree,
11268 source_tree);
11269#else
11270 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11271 assign_temp,
11272 source_tree);
11273 expand_expr_stmt (expr_tree);
11274 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11275 dest_tree,
11276 assign_temp);
11277#endif
11278 }
c7e4ee3a
CB
11279 else
11280 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11281 dest_tree,
11282 source_tree);
5ff904cd 11283
c7e4ee3a
CB
11284 expand_expr_stmt (expr_tree);
11285 return;
11286 }
5ff904cd 11287
c7e4ee3a
CB
11288 ffecom_prepare_let_char_ (ffebld_size_known (dest), source);
11289 ffecom_prepare_expr_w (NULL_TREE, dest);
11290
11291 ffecom_prepare_end ();
11292
11293 ffecom_char_args_ (&dest_tree, &dest_length, dest);
11294 ffecom_let_char_ (dest_tree, dest_length, ffebld_size_known (dest),
11295 source);
5ff904cd
JL
11296}
11297
11298#endif
c7e4ee3a 11299/* ffecom_expr -- Transform expr into gcc tree
5ff904cd 11300
c7e4ee3a
CB
11301 tree t;
11302 ffebld expr; // FFE expression.
11303 tree = ffecom_expr(expr);
5ff904cd 11304
c7e4ee3a
CB
11305 Recursive descent on expr while making corresponding tree nodes and
11306 attaching type info and such. */
5ff904cd
JL
11307
11308#if FFECOM_targetCURRENT == FFECOM_targetGCC
11309tree
c7e4ee3a 11310ffecom_expr (ffebld expr)
5ff904cd 11311{
c7e4ee3a 11312 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, FALSE, FALSE);
5ff904cd 11313}
c7e4ee3a 11314
5ff904cd 11315#endif
c7e4ee3a 11316/* Like ffecom_expr, but return tree usable for assigned GOTO or FORMAT. */
5ff904cd 11317
c7e4ee3a
CB
11318#if FFECOM_targetCURRENT == FFECOM_targetGCC
11319tree
11320ffecom_expr_assign (ffebld expr)
11321{
11322 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
11323}
5ff904cd 11324
c7e4ee3a
CB
11325#endif
11326/* Like ffecom_expr_rw, but return tree usable for ASSIGN. */
5ff904cd
JL
11327
11328#if FFECOM_targetCURRENT == FFECOM_targetGCC
11329tree
c7e4ee3a 11330ffecom_expr_assign_w (ffebld expr)
5ff904cd 11331{
c7e4ee3a
CB
11332 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
11333}
5ff904cd 11334
5ff904cd 11335#endif
c7e4ee3a
CB
11336/* Transform expr for use as into read/write tree and stabilize the
11337 reference. Not for use on CHARACTER expressions.
5ff904cd 11338
c7e4ee3a
CB
11339 Recursive descent on expr while making corresponding tree nodes and
11340 attaching type info and such. */
5ff904cd 11341
c7e4ee3a
CB
11342#if FFECOM_targetCURRENT == FFECOM_targetGCC
11343tree
11344ffecom_expr_rw (tree type, ffebld expr)
11345{
11346 assert (expr != NULL);
11347 /* Different target types not yet supported. */
11348 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
11349
11350 return stabilize_reference (ffecom_expr (expr));
11351}
5ff904cd 11352
5ff904cd 11353#endif
c7e4ee3a
CB
11354/* Transform expr for use as into write tree and stabilize the
11355 reference. Not for use on CHARACTER expressions.
5ff904cd 11356
c7e4ee3a
CB
11357 Recursive descent on expr while making corresponding tree nodes and
11358 attaching type info and such. */
5ff904cd 11359
c7e4ee3a
CB
11360#if FFECOM_targetCURRENT == FFECOM_targetGCC
11361tree
11362ffecom_expr_w (tree type, ffebld expr)
11363{
11364 assert (expr != NULL);
11365 /* Different target types not yet supported. */
11366 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
11367
11368 return stabilize_reference (ffecom_expr (expr));
11369}
5ff904cd 11370
5ff904cd 11371#endif
c7e4ee3a
CB
11372/* Do global stuff. */
11373
11374#if FFECOM_targetCURRENT == FFECOM_targetGCC
11375void
11376ffecom_finish_compile ()
11377{
11378 assert (ffecom_outer_function_decl_ == NULL_TREE);
11379 assert (current_function_decl == NULL_TREE);
11380
11381 ffeglobal_drive (ffecom_finish_global_);
11382}
5ff904cd 11383
5ff904cd 11384#endif
c7e4ee3a
CB
11385/* Public entry point for front end to access finish_decl. */
11386
11387#if FFECOM_targetCURRENT == FFECOM_targetGCC
11388void
11389ffecom_finish_decl (tree decl, tree init, bool is_top_level)
11390{
11391 assert (!is_top_level);
11392 finish_decl (decl, init, FALSE);
11393}
5ff904cd 11394
5ff904cd 11395#endif
c7e4ee3a
CB
11396/* Finish a program unit. */
11397
11398#if FFECOM_targetCURRENT == FFECOM_targetGCC
11399void
11400ffecom_finish_progunit ()
11401{
11402 ffecom_end_compstmt ();
11403
11404 ffecom_previous_function_decl_ = current_function_decl;
11405 ffecom_which_entrypoint_decl_ = NULL_TREE;
11406
11407 finish_function (0);
11408}
5ff904cd 11409
5ff904cd 11410#endif
c7e4ee3a
CB
11411/* Wrapper for get_identifier. pattern is sprintf-like, assumed to contain
11412 one %s if text is not NULL, assumed to contain one %d if number is
11413 not -1. If both are assumed, the %s is assumed to precede the %d. */
11414
11415#if FFECOM_targetCURRENT == FFECOM_targetGCC
11416tree
11417ffecom_get_invented_identifier (const char *pattern, const char *text,
11418 int number)
11419{
11420 tree decl;
11421 char *nam;
11422 mallocSize lenlen;
11423 char space[66];
11424
11425 lenlen = 0;
11426 if (text)
11427 lenlen += strlen (text);
11428 if (number != -1)
11429 lenlen += 20;
11430 if (text || number != -1)
11431 {
11432 lenlen += strlen (pattern);
11433 if (lenlen > ARRAY_SIZE (space))
11434 nam = malloc_new_ks (malloc_pool_image (), pattern, lenlen);
11435 else
11436 nam = &space[0];
11437 }
11438 else
11439 {
11440 lenlen = 0;
11441 nam = (char *) pattern;
11442 }
11443
11444 if (text == NULL)
11445 {
11446 if (number != -1)
11447 sprintf (&nam[0], pattern, number);
11448 }
11449 else
11450 {
11451 if (number == -1)
11452 sprintf (&nam[0], pattern, text);
11453 else
11454 sprintf (&nam[0], pattern, text, number);
11455 }
11456
11457 decl = get_identifier (nam);
11458
11459 if (lenlen > ARRAY_SIZE (space))
11460 malloc_kill_ks (malloc_pool_image (), nam, lenlen);
11461
11462 IDENTIFIER_INVENTED (decl) = 1;
11463
11464 return decl;
11465}
11466
11467ffeinfoBasictype
11468ffecom_gfrt_basictype (ffecomGfrt gfrt)
11469{
11470 assert (gfrt < FFECOM_gfrt);
11471
11472 switch (ffecom_gfrt_type_[gfrt])
11473 {
11474 case FFECOM_rttypeVOID_:
11475 case FFECOM_rttypeVOIDSTAR_:
11476 return FFEINFO_basictypeNONE;
11477
11478 case FFECOM_rttypeFTNINT_:
11479 return FFEINFO_basictypeINTEGER;
11480
11481 case FFECOM_rttypeINTEGER_:
11482 return FFEINFO_basictypeINTEGER;
11483
11484 case FFECOM_rttypeLONGINT_:
11485 return FFEINFO_basictypeINTEGER;
11486
11487 case FFECOM_rttypeLOGICAL_:
11488 return FFEINFO_basictypeLOGICAL;
11489
11490 case FFECOM_rttypeREAL_F2C_:
11491 case FFECOM_rttypeREAL_GNU_:
11492 return FFEINFO_basictypeREAL;
11493
11494 case FFECOM_rttypeCOMPLEX_F2C_:
11495 case FFECOM_rttypeCOMPLEX_GNU_:
11496 return FFEINFO_basictypeCOMPLEX;
11497
11498 case FFECOM_rttypeDOUBLE_:
11499 case FFECOM_rttypeDOUBLEREAL_:
11500 return FFEINFO_basictypeREAL;
11501
11502 case FFECOM_rttypeDBLCMPLX_F2C_:
11503 case FFECOM_rttypeDBLCMPLX_GNU_:
11504 return FFEINFO_basictypeCOMPLEX;
11505
11506 case FFECOM_rttypeCHARACTER_:
11507 return FFEINFO_basictypeCHARACTER;
11508
11509 default:
11510 return FFEINFO_basictypeANY;
11511 }
11512}
11513
11514ffeinfoKindtype
11515ffecom_gfrt_kindtype (ffecomGfrt gfrt)
11516{
11517 assert (gfrt < FFECOM_gfrt);
11518
11519 switch (ffecom_gfrt_type_[gfrt])
11520 {
11521 case FFECOM_rttypeVOID_:
11522 case FFECOM_rttypeVOIDSTAR_:
11523 return FFEINFO_kindtypeNONE;
5ff904cd 11524
c7e4ee3a
CB
11525 case FFECOM_rttypeFTNINT_:
11526 return FFEINFO_kindtypeINTEGER1;
5ff904cd 11527
c7e4ee3a
CB
11528 case FFECOM_rttypeINTEGER_:
11529 return FFEINFO_kindtypeINTEGER1;
5ff904cd 11530
c7e4ee3a
CB
11531 case FFECOM_rttypeLONGINT_:
11532 return FFEINFO_kindtypeINTEGER4;
5ff904cd 11533
c7e4ee3a
CB
11534 case FFECOM_rttypeLOGICAL_:
11535 return FFEINFO_kindtypeLOGICAL1;
5ff904cd 11536
c7e4ee3a
CB
11537 case FFECOM_rttypeREAL_F2C_:
11538 case FFECOM_rttypeREAL_GNU_:
11539 return FFEINFO_kindtypeREAL1;
5ff904cd 11540
c7e4ee3a
CB
11541 case FFECOM_rttypeCOMPLEX_F2C_:
11542 case FFECOM_rttypeCOMPLEX_GNU_:
11543 return FFEINFO_kindtypeREAL1;
5ff904cd 11544
c7e4ee3a
CB
11545 case FFECOM_rttypeDOUBLE_:
11546 case FFECOM_rttypeDOUBLEREAL_:
11547 return FFEINFO_kindtypeREAL2;
5ff904cd 11548
c7e4ee3a
CB
11549 case FFECOM_rttypeDBLCMPLX_F2C_:
11550 case FFECOM_rttypeDBLCMPLX_GNU_:
11551 return FFEINFO_kindtypeREAL2;
5ff904cd 11552
c7e4ee3a
CB
11553 case FFECOM_rttypeCHARACTER_:
11554 return FFEINFO_kindtypeCHARACTER1;
5ff904cd 11555
c7e4ee3a
CB
11556 default:
11557 return FFEINFO_kindtypeANY;
11558 }
11559}
5ff904cd 11560
c7e4ee3a
CB
11561void
11562ffecom_init_0 ()
11563{
11564 tree endlink;
11565 int i;
11566 int j;
11567 tree t;
11568 tree field;
11569 ffetype type;
11570 ffetype base_type;
5ff904cd 11571
c7e4ee3a
CB
11572 /* This block of code comes from the now-obsolete cktyps.c. It checks
11573 whether the compiler environment is buggy in known ways, some of which
11574 would, if not explicitly checked here, result in subtle bugs in g77. */
5ff904cd 11575
c7e4ee3a
CB
11576 if (ffe_is_do_internal_checks ())
11577 {
11578 static char names[][12]
11579 =
11580 {"bar", "bletch", "foo", "foobar"};
11581 char *name;
11582 unsigned long ul;
11583 double fl;
5ff904cd 11584
c7e4ee3a
CB
11585 name = bsearch ("foo", &names[0], ARRAY_SIZE (names), sizeof (names[0]),
11586 (int (*)()) strcmp);
11587 if (name != (char *) &names[2])
11588 {
11589 assert ("bsearch doesn't work, #define FFEPROJ_BSEARCH 0 in proj.h"
11590 == NULL);
11591 abort ();
11592 }
5ff904cd 11593
c7e4ee3a
CB
11594 ul = strtoul ("123456789", NULL, 10);
11595 if (ul != 123456789L)
11596 {
11597 assert ("strtoul doesn't have enough range, #define FFEPROJ_STRTOUL 0\
11598 in proj.h" == NULL);
11599 abort ();
11600 }
5ff904cd 11601
c7e4ee3a
CB
11602 fl = atof ("56.789");
11603 if ((fl < 56.788) || (fl > 56.79))
11604 {
11605 assert ("atof not type double, fix your #include <stdio.h>"
11606 == NULL);
11607 abort ();
11608 }
11609 }
5ff904cd 11610
c7e4ee3a
CB
11611 /* Set the sizetype before we do anything else. This _should_ be the
11612 first type we create. */
5ff904cd 11613
c7e4ee3a
CB
11614 t = make_unsigned_type (POINTER_SIZE);
11615 assert (t == sizetype);
5ff904cd 11616
c7e4ee3a
CB
11617#if FFECOM_GCC_INCLUDE
11618 ffecom_initialize_char_syntax_ ();
11619#endif
5ff904cd 11620
c7e4ee3a
CB
11621 ffecom_outer_function_decl_ = NULL_TREE;
11622 current_function_decl = NULL_TREE;
11623 named_labels = NULL_TREE;
11624 current_binding_level = NULL_BINDING_LEVEL;
11625 free_binding_level = NULL_BINDING_LEVEL;
11626 /* Make the binding_level structure for global names. */
11627 pushlevel (0);
11628 global_binding_level = current_binding_level;
11629 current_binding_level->prep_state = 2;
5ff904cd 11630
c7e4ee3a 11631 /* Define `int' and `char' first so that dbx will output them first. */
5ff904cd 11632
c7e4ee3a
CB
11633 integer_type_node = make_signed_type (INT_TYPE_SIZE);
11634 pushdecl (build_decl (TYPE_DECL, get_identifier ("int"),
11635 integer_type_node));
5ff904cd 11636
c7e4ee3a
CB
11637 char_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
11638 pushdecl (build_decl (TYPE_DECL, get_identifier ("char"),
11639 char_type_node));
5ff904cd 11640
c7e4ee3a
CB
11641 long_integer_type_node = make_signed_type (LONG_TYPE_SIZE);
11642 pushdecl (build_decl (TYPE_DECL, get_identifier ("long int"),
11643 long_integer_type_node));
5ff904cd 11644
c7e4ee3a
CB
11645 unsigned_type_node = make_unsigned_type (INT_TYPE_SIZE);
11646 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned int"),
11647 unsigned_type_node));
5ff904cd 11648
c7e4ee3a
CB
11649 long_unsigned_type_node = make_unsigned_type (LONG_TYPE_SIZE);
11650 pushdecl (build_decl (TYPE_DECL, get_identifier ("long unsigned int"),
11651 long_unsigned_type_node));
5ff904cd 11652
c7e4ee3a
CB
11653 long_long_integer_type_node = make_signed_type (LONG_LONG_TYPE_SIZE);
11654 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long int"),
11655 long_long_integer_type_node));
5ff904cd 11656
c7e4ee3a
CB
11657 long_long_unsigned_type_node = make_unsigned_type (LONG_LONG_TYPE_SIZE);
11658 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"),
11659 long_long_unsigned_type_node));
5ff904cd 11660
c7e4ee3a
CB
11661 error_mark_node = make_node (ERROR_MARK);
11662 TREE_TYPE (error_mark_node) = error_mark_node;
5ff904cd 11663
c7e4ee3a
CB
11664 short_integer_type_node = make_signed_type (SHORT_TYPE_SIZE);
11665 pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"),
11666 short_integer_type_node));
5ff904cd 11667
c7e4ee3a
CB
11668 short_unsigned_type_node = make_unsigned_type (SHORT_TYPE_SIZE);
11669 pushdecl (build_decl (TYPE_DECL, get_identifier ("short unsigned int"),
11670 short_unsigned_type_node));
5ff904cd 11671
c7e4ee3a
CB
11672 /* Define both `signed char' and `unsigned char'. */
11673 signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE);
11674 pushdecl (build_decl (TYPE_DECL, get_identifier ("signed char"),
11675 signed_char_type_node));
5ff904cd 11676
c7e4ee3a
CB
11677 unsigned_char_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
11678 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned char"),
11679 unsigned_char_type_node));
5ff904cd 11680
c7e4ee3a
CB
11681 float_type_node = make_node (REAL_TYPE);
11682 TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE;
11683 layout_type (float_type_node);
11684 pushdecl (build_decl (TYPE_DECL, get_identifier ("float"),
11685 float_type_node));
5ff904cd 11686
c7e4ee3a
CB
11687 double_type_node = make_node (REAL_TYPE);
11688 TYPE_PRECISION (double_type_node) = DOUBLE_TYPE_SIZE;
11689 layout_type (double_type_node);
11690 pushdecl (build_decl (TYPE_DECL, get_identifier ("double"),
11691 double_type_node));
5ff904cd 11692
c7e4ee3a
CB
11693 long_double_type_node = make_node (REAL_TYPE);
11694 TYPE_PRECISION (long_double_type_node) = LONG_DOUBLE_TYPE_SIZE;
11695 layout_type (long_double_type_node);
11696 pushdecl (build_decl (TYPE_DECL, get_identifier ("long double"),
11697 long_double_type_node));
5ff904cd 11698
c7e4ee3a
CB
11699 complex_integer_type_node = ffecom_make_complex_type_ (integer_type_node);
11700 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"),
11701 complex_integer_type_node));
5ff904cd 11702
c7e4ee3a
CB
11703 complex_float_type_node = ffecom_make_complex_type_ (float_type_node);
11704 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"),
11705 complex_float_type_node));
5ff904cd 11706
c7e4ee3a
CB
11707 complex_double_type_node = ffecom_make_complex_type_ (double_type_node);
11708 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"),
11709 complex_double_type_node));
5ff904cd 11710
c7e4ee3a
CB
11711 complex_long_double_type_node = ffecom_make_complex_type_ (long_double_type_node);
11712 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"),
11713 complex_long_double_type_node));
5ff904cd 11714
c7e4ee3a
CB
11715 integer_zero_node = build_int_2 (0, 0);
11716 TREE_TYPE (integer_zero_node) = integer_type_node;
11717 integer_one_node = build_int_2 (1, 0);
11718 TREE_TYPE (integer_one_node) = integer_type_node;
5ff904cd 11719
c7e4ee3a
CB
11720 size_zero_node = build_int_2 (0, 0);
11721 TREE_TYPE (size_zero_node) = sizetype;
11722 size_one_node = build_int_2 (1, 0);
11723 TREE_TYPE (size_one_node) = sizetype;
5ff904cd 11724
c7e4ee3a
CB
11725 void_type_node = make_node (VOID_TYPE);
11726 pushdecl (build_decl (TYPE_DECL, get_identifier ("void"),
11727 void_type_node));
11728 layout_type (void_type_node); /* Uses integer_zero_node */
11729 /* We are not going to have real types in C with less than byte alignment,
11730 so we might as well not have any types that claim to have it. */
11731 TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
5ff904cd 11732
c7e4ee3a
CB
11733 null_pointer_node = build_int_2 (0, 0);
11734 TREE_TYPE (null_pointer_node) = build_pointer_type (void_type_node);
11735 layout_type (TREE_TYPE (null_pointer_node));
5ff904cd 11736
c7e4ee3a 11737 string_type_node = build_pointer_type (char_type_node);
5ff904cd 11738
c7e4ee3a
CB
11739 ffecom_tree_fun_type_void
11740 = build_function_type (void_type_node, NULL_TREE);
5ff904cd 11741
c7e4ee3a
CB
11742 ffecom_tree_ptr_to_fun_type_void
11743 = build_pointer_type (ffecom_tree_fun_type_void);
5ff904cd 11744
c7e4ee3a 11745 endlink = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
5ff904cd 11746
c7e4ee3a
CB
11747 float_ftype_float
11748 = build_function_type (float_type_node,
11749 tree_cons (NULL_TREE, float_type_node, endlink));
5ff904cd 11750
c7e4ee3a
CB
11751 double_ftype_double
11752 = build_function_type (double_type_node,
11753 tree_cons (NULL_TREE, double_type_node, endlink));
5ff904cd 11754
c7e4ee3a
CB
11755 ldouble_ftype_ldouble
11756 = build_function_type (long_double_type_node,
11757 tree_cons (NULL_TREE, long_double_type_node,
11758 endlink));
5ff904cd 11759
c7e4ee3a
CB
11760 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11761 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11762 {
11763 ffecom_tree_type[i][j] = NULL_TREE;
11764 ffecom_tree_fun_type[i][j] = NULL_TREE;
11765 ffecom_tree_ptr_to_fun_type[i][j] = NULL_TREE;
11766 ffecom_f2c_typecode_[i][j] = -1;
11767 }
5ff904cd 11768
c7e4ee3a
CB
11769 /* Set up standard g77 types. Note that INTEGER and LOGICAL are set
11770 to size FLOAT_TYPE_SIZE because they have to be the same size as
11771 REAL, which also is FLOAT_TYPE_SIZE, according to the standard.
11772 Compiler options and other such stuff that change the ways these
11773 types are set should not affect this particular setup. */
5ff904cd 11774
c7e4ee3a
CB
11775 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1]
11776 = t = make_signed_type (FLOAT_TYPE_SIZE);
11777 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer"),
11778 t));
11779 type = ffetype_new ();
11780 base_type = type;
11781 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER1,
11782 type);
11783 ffetype_set_ams (type,
11784 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11785 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11786 ffetype_set_star (base_type,
11787 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11788 type);
11789 ffetype_set_kind (base_type, 1, type);
11790 assert (ffetype_size (type) == sizeof (ffetargetInteger1));
5ff904cd 11791
c7e4ee3a
CB
11792 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER1]
11793 = t = make_unsigned_type (FLOAT_TYPE_SIZE); /* HOLLERITH means unsigned. */
11794 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned"),
11795 t));
5ff904cd 11796
c7e4ee3a
CB
11797 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER2]
11798 = t = make_signed_type (CHAR_TYPE_SIZE);
11799 pushdecl (build_decl (TYPE_DECL, get_identifier ("byte"),
11800 t));
11801 type = ffetype_new ();
11802 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER2,
11803 type);
11804 ffetype_set_ams (type,
11805 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11806 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11807 ffetype_set_star (base_type,
11808 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11809 type);
11810 ffetype_set_kind (base_type, 3, type);
11811 assert (ffetype_size (type) == sizeof (ffetargetInteger2));
5ff904cd 11812
c7e4ee3a
CB
11813 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER2]
11814 = t = make_unsigned_type (CHAR_TYPE_SIZE);
11815 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned byte"),
11816 t));
11817
11818 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER3]
11819 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11820 pushdecl (build_decl (TYPE_DECL, get_identifier ("word"),
11821 t));
11822 type = ffetype_new ();
11823 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER3,
11824 type);
11825 ffetype_set_ams (type,
11826 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11827 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11828 ffetype_set_star (base_type,
11829 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11830 type);
11831 ffetype_set_kind (base_type, 6, type);
11832 assert (ffetype_size (type) == sizeof (ffetargetInteger3));
5ff904cd 11833
c7e4ee3a
CB
11834 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER3]
11835 = t = make_unsigned_type (CHAR_TYPE_SIZE * 2);
11836 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned word"),
11837 t));
5ff904cd 11838
c7e4ee3a
CB
11839 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER4]
11840 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11841 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer4"),
11842 t));
11843 type = ffetype_new ();
11844 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER4,
11845 type);
11846 ffetype_set_ams (type,
11847 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11848 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11849 ffetype_set_star (base_type,
11850 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11851 type);
11852 ffetype_set_kind (base_type, 2, type);
11853 assert (ffetype_size (type) == sizeof (ffetargetInteger4));
5ff904cd 11854
c7e4ee3a
CB
11855 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER4]
11856 = t = make_unsigned_type (FLOAT_TYPE_SIZE * 2);
11857 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned4"),
11858 t));
5ff904cd 11859
c7e4ee3a
CB
11860#if 0
11861 if (ffe_is_do_internal_checks ()
11862 && LONG_TYPE_SIZE != FLOAT_TYPE_SIZE
11863 && LONG_TYPE_SIZE != CHAR_TYPE_SIZE
11864 && LONG_TYPE_SIZE != SHORT_TYPE_SIZE
11865 && LONG_TYPE_SIZE != LONG_LONG_TYPE_SIZE)
5ff904cd 11866 {
c7e4ee3a
CB
11867 fprintf (stderr, "Sorry, no g77 support for LONG_TYPE_SIZE (%d bits) yet.\n",
11868 LONG_TYPE_SIZE);
5ff904cd 11869 }
c7e4ee3a 11870#endif
5ff904cd 11871
c7e4ee3a
CB
11872 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL1]
11873 = t = make_signed_type (FLOAT_TYPE_SIZE);
11874 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical"),
11875 t));
11876 type = ffetype_new ();
11877 base_type = type;
11878 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL1,
11879 type);
11880 ffetype_set_ams (type,
11881 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11882 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11883 ffetype_set_star (base_type,
11884 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11885 type);
11886 ffetype_set_kind (base_type, 1, type);
11887 assert (ffetype_size (type) == sizeof (ffetargetLogical1));
5ff904cd 11888
c7e4ee3a
CB
11889 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL2]
11890 = t = make_signed_type (CHAR_TYPE_SIZE);
11891 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical2"),
11892 t));
11893 type = ffetype_new ();
11894 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL2,
11895 type);
11896 ffetype_set_ams (type,
11897 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11898 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11899 ffetype_set_star (base_type,
11900 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11901 type);
11902 ffetype_set_kind (base_type, 3, type);
11903 assert (ffetype_size (type) == sizeof (ffetargetLogical2));
5ff904cd 11904
c7e4ee3a
CB
11905 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL3]
11906 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11907 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical3"),
11908 t));
11909 type = ffetype_new ();
11910 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL3,
11911 type);
11912 ffetype_set_ams (type,
11913 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11914 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11915 ffetype_set_star (base_type,
11916 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11917 type);
11918 ffetype_set_kind (base_type, 6, type);
11919 assert (ffetype_size (type) == sizeof (ffetargetLogical3));
5ff904cd 11920
c7e4ee3a
CB
11921 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL4]
11922 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11923 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical4"),
11924 t));
11925 type = ffetype_new ();
11926 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL4,
11927 type);
11928 ffetype_set_ams (type,
11929 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11930 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11931 ffetype_set_star (base_type,
11932 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11933 type);
11934 ffetype_set_kind (base_type, 2, type);
11935 assert (ffetype_size (type) == sizeof (ffetargetLogical4));
5ff904cd 11936
c7e4ee3a
CB
11937 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
11938 = t = make_node (REAL_TYPE);
11939 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE;
11940 pushdecl (build_decl (TYPE_DECL, get_identifier ("real"),
11941 t));
11942 layout_type (t);
11943 type = ffetype_new ();
11944 base_type = type;
11945 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREAL1,
11946 type);
11947 ffetype_set_ams (type,
11948 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11949 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11950 ffetype_set_star (base_type,
11951 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11952 type);
11953 ffetype_set_kind (base_type, 1, type);
11954 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
11955 = FFETARGET_f2cTYREAL;
11956 assert (ffetype_size (type) == sizeof (ffetargetReal1));
5ff904cd 11957
c7e4ee3a
CB
11958 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREALDOUBLE]
11959 = t = make_node (REAL_TYPE);
11960 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE * 2; /* Always twice REAL. */
11961 pushdecl (build_decl (TYPE_DECL, get_identifier ("double precision"),
11962 t));
11963 layout_type (t);
11964 type = ffetype_new ();
11965 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREALDOUBLE,
11966 type);
11967 ffetype_set_ams (type,
11968 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11969 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11970 ffetype_set_star (base_type,
11971 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11972 type);
11973 ffetype_set_kind (base_type, 2, type);
11974 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]
11975 = FFETARGET_f2cTYDREAL;
11976 assert (ffetype_size (type) == sizeof (ffetargetReal2));
5ff904cd 11977
c7e4ee3a
CB
11978 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
11979 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]);
11980 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex"),
11981 t));
11982 type = ffetype_new ();
11983 base_type = type;
11984 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREAL1,
11985 type);
11986 ffetype_set_ams (type,
11987 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11988 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11989 ffetype_set_star (base_type,
11990 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11991 type);
11992 ffetype_set_kind (base_type, 1, type);
11993 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
11994 = FFETARGET_f2cTYCOMPLEX;
11995 assert (ffetype_size (type) == sizeof (ffetargetComplex1));
5ff904cd 11996
c7e4ee3a
CB
11997 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREALDOUBLE]
11998 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]);
11999 pushdecl (build_decl (TYPE_DECL, get_identifier ("double complex"),
12000 t));
12001 type = ffetype_new ();
12002 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREALDOUBLE,
12003 type);
12004 ffetype_set_ams (type,
12005 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12006 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12007 ffetype_set_star (base_type,
12008 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12009 type);
12010 ffetype_set_kind (base_type, 2,
12011 type);
12012 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL2]
12013 = FFETARGET_f2cTYDCOMPLEX;
12014 assert (ffetype_size (type) == sizeof (ffetargetComplex2));
5ff904cd 12015
c7e4ee3a 12016 /* Make function and ptr-to-function types for non-CHARACTER types. */
5ff904cd 12017
c7e4ee3a
CB
12018 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
12019 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
12020 {
12021 if ((t = ffecom_tree_type[i][j]) != NULL_TREE)
12022 {
12023 if (i == FFEINFO_basictypeINTEGER)
12024 {
12025 /* Figure out the smallest INTEGER type that can hold
12026 a pointer on this machine. */
12027 if (GET_MODE_SIZE (TYPE_MODE (t))
12028 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
12029 {
12030 if ((ffecom_pointer_kind_ == FFEINFO_kindtypeNONE)
12031 || (GET_MODE_SIZE (TYPE_MODE (ffecom_tree_type[i][ffecom_pointer_kind_]))
12032 > GET_MODE_SIZE (TYPE_MODE (t))))
12033 ffecom_pointer_kind_ = j;
12034 }
12035 }
12036 else if (i == FFEINFO_basictypeCOMPLEX)
12037 t = void_type_node;
12038 /* For f2c compatibility, REAL functions are really
12039 implemented as DOUBLE PRECISION. */
12040 else if ((i == FFEINFO_basictypeREAL)
12041 && (j == FFEINFO_kindtypeREAL1))
12042 t = ffecom_tree_type
12043 [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2];
5ff904cd 12044
c7e4ee3a
CB
12045 t = ffecom_tree_fun_type[i][j] = build_function_type (t,
12046 NULL_TREE);
12047 ffecom_tree_ptr_to_fun_type[i][j] = build_pointer_type (t);
12048 }
12049 }
5ff904cd 12050
c7e4ee3a 12051 /* Set up pointer types. */
5ff904cd 12052
c7e4ee3a
CB
12053 if (ffecom_pointer_kind_ == FFEINFO_basictypeNONE)
12054 fatal ("no INTEGER type can hold a pointer on this configuration");
12055 else if (0 && ffe_is_do_internal_checks ())
12056 fprintf (stderr, "Pointer type kt=%d\n", ffecom_pointer_kind_);
12057 ffetype_set_kind (ffeinfo_type (FFEINFO_basictypeINTEGER,
12058 FFEINFO_kindtypeINTEGERDEFAULT),
12059 7,
12060 ffeinfo_type (FFEINFO_basictypeINTEGER,
12061 ffecom_pointer_kind_));
5ff904cd 12062
c7e4ee3a
CB
12063 if (ffe_is_ugly_assign ())
12064 ffecom_label_kind_ = ffecom_pointer_kind_; /* Require ASSIGN etc to this. */
12065 else
12066 ffecom_label_kind_ = FFEINFO_kindtypeINTEGERDEFAULT;
12067 if (0 && ffe_is_do_internal_checks ())
12068 fprintf (stderr, "Label type kt=%d\n", ffecom_label_kind_);
5ff904cd 12069
c7e4ee3a
CB
12070 ffecom_integer_type_node
12071 = ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1];
12072 ffecom_integer_zero_node = convert (ffecom_integer_type_node,
12073 integer_zero_node);
12074 ffecom_integer_one_node = convert (ffecom_integer_type_node,
12075 integer_one_node);
5ff904cd 12076
c7e4ee3a
CB
12077 /* Yes, the "FLOAT_TYPE_SIZE" references below are intentional.
12078 Turns out that by TYLONG, runtime/libI77/lio.h really means
12079 "whatever size an ftnint is". For consistency and sanity,
12080 com.h and runtime/f2c.h.in agree that flag, ftnint, and ftlen
12081 all are INTEGER, which we also make out of whatever back-end
12082 integer type is FLOAT_TYPE_SIZE bits wide. This change, from
12083 LONG_TYPE_SIZE, for TYLONG and TYLOGICAL, was necessary to
12084 accommodate machines like the Alpha. Note that this suggests
12085 f2c and libf2c are missing a distinction perhaps needed on
12086 some machines between "int" and "long int". -- burley 0.5.5 950215 */
5ff904cd 12087
c7e4ee3a
CB
12088 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, FLOAT_TYPE_SIZE,
12089 FFETARGET_f2cTYLONG);
12090 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, SHORT_TYPE_SIZE,
12091 FFETARGET_f2cTYSHORT);
12092 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, CHAR_TYPE_SIZE,
12093 FFETARGET_f2cTYINT1);
12094 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, LONG_LONG_TYPE_SIZE,
12095 FFETARGET_f2cTYQUAD);
12096 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, FLOAT_TYPE_SIZE,
12097 FFETARGET_f2cTYLOGICAL);
12098 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, SHORT_TYPE_SIZE,
12099 FFETARGET_f2cTYLOGICAL2);
12100 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, CHAR_TYPE_SIZE,
12101 FFETARGET_f2cTYLOGICAL1);
12102 /* ~~~Not really such a type in libf2c, e.g. I/O support? */
12103 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, LONG_LONG_TYPE_SIZE,
12104 FFETARGET_f2cTYQUAD);
5ff904cd 12105
c7e4ee3a
CB
12106 /* CHARACTER stuff is all special-cased, so it is not handled in the above
12107 loop. CHARACTER items are built as arrays of unsigned char. */
5ff904cd 12108
c7e4ee3a
CB
12109 ffecom_tree_type[FFEINFO_basictypeCHARACTER]
12110 [FFEINFO_kindtypeCHARACTER1] = t = char_type_node;
12111 type = ffetype_new ();
12112 base_type = type;
12113 ffeinfo_set_type (FFEINFO_basictypeCHARACTER,
12114 FFEINFO_kindtypeCHARACTER1,
12115 type);
12116 ffetype_set_ams (type,
12117 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12118 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12119 ffetype_set_kind (base_type, 1, type);
12120 assert (ffetype_size (type)
12121 == sizeof (((ffetargetCharacter1) { 0, NULL }).text[0]));
5ff904cd 12122
c7e4ee3a
CB
12123 ffecom_tree_fun_type[FFEINFO_basictypeCHARACTER]
12124 [FFEINFO_kindtypeCHARACTER1] = ffecom_tree_fun_type_void;
12125 ffecom_tree_ptr_to_fun_type[FFEINFO_basictypeCHARACTER]
12126 [FFEINFO_kindtypeCHARACTER1]
12127 = ffecom_tree_ptr_to_fun_type_void;
12128 ffecom_f2c_typecode_[FFEINFO_basictypeCHARACTER][FFEINFO_kindtypeCHARACTER1]
12129 = FFETARGET_f2cTYCHAR;
5ff904cd 12130
c7e4ee3a
CB
12131 ffecom_f2c_typecode_[FFEINFO_basictypeANY][FFEINFO_kindtypeANY]
12132 = 0;
5ff904cd 12133
c7e4ee3a 12134 /* Make multi-return-value type and fields. */
5ff904cd 12135
c7e4ee3a 12136 ffecom_multi_type_node_ = make_node (UNION_TYPE);
5ff904cd 12137
c7e4ee3a 12138 field = NULL_TREE;
5ff904cd 12139
c7e4ee3a
CB
12140 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
12141 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
12142 {
12143 char name[30];
5ff904cd 12144
c7e4ee3a
CB
12145 if (ffecom_tree_type[i][j] == NULL_TREE)
12146 continue; /* Not supported. */
12147 sprintf (&name[0], "bt_%s_kt_%s",
12148 ffeinfo_basictype_string ((ffeinfoBasictype) i),
12149 ffeinfo_kindtype_string ((ffeinfoKindtype) j));
12150 ffecom_multi_fields_[i][j] = build_decl (FIELD_DECL,
12151 get_identifier (name),
12152 ffecom_tree_type[i][j]);
12153 DECL_CONTEXT (ffecom_multi_fields_[i][j])
12154 = ffecom_multi_type_node_;
12155 DECL_FRAME_SIZE (ffecom_multi_fields_[i][j]) = 0;
12156 TREE_CHAIN (ffecom_multi_fields_[i][j]) = field;
12157 field = ffecom_multi_fields_[i][j];
12158 }
5ff904cd 12159
c7e4ee3a
CB
12160 TYPE_FIELDS (ffecom_multi_type_node_) = field;
12161 layout_type (ffecom_multi_type_node_);
5ff904cd 12162
c7e4ee3a
CB
12163 /* Subroutines usually return integer because they might have alternate
12164 returns. */
5ff904cd 12165
c7e4ee3a
CB
12166 ffecom_tree_subr_type
12167 = build_function_type (integer_type_node, NULL_TREE);
12168 ffecom_tree_ptr_to_subr_type
12169 = build_pointer_type (ffecom_tree_subr_type);
12170 ffecom_tree_blockdata_type
12171 = build_function_type (void_type_node, NULL_TREE);
5ff904cd 12172
c7e4ee3a
CB
12173 builtin_function ("__builtin_sqrtf", float_ftype_float,
12174 BUILT_IN_FSQRT, "sqrtf");
12175 builtin_function ("__builtin_fsqrt", double_ftype_double,
12176 BUILT_IN_FSQRT, "sqrt");
12177 builtin_function ("__builtin_sqrtl", ldouble_ftype_ldouble,
12178 BUILT_IN_FSQRT, "sqrtl");
12179 builtin_function ("__builtin_sinf", float_ftype_float,
12180 BUILT_IN_SIN, "sinf");
12181 builtin_function ("__builtin_sin", double_ftype_double,
12182 BUILT_IN_SIN, "sin");
12183 builtin_function ("__builtin_sinl", ldouble_ftype_ldouble,
12184 BUILT_IN_SIN, "sinl");
12185 builtin_function ("__builtin_cosf", float_ftype_float,
12186 BUILT_IN_COS, "cosf");
12187 builtin_function ("__builtin_cos", double_ftype_double,
12188 BUILT_IN_COS, "cos");
12189 builtin_function ("__builtin_cosl", ldouble_ftype_ldouble,
12190 BUILT_IN_COS, "cosl");
5ff904cd 12191
c7e4ee3a
CB
12192#if BUILT_FOR_270
12193 pedantic_lvalues = FALSE;
5ff904cd 12194#endif
5ff904cd 12195
c7e4ee3a
CB
12196 ffecom_f2c_make_type_ (&ffecom_f2c_integer_type_node,
12197 FFECOM_f2cINTEGER,
12198 "integer");
12199 ffecom_f2c_make_type_ (&ffecom_f2c_address_type_node,
12200 FFECOM_f2cADDRESS,
12201 "address");
12202 ffecom_f2c_make_type_ (&ffecom_f2c_real_type_node,
12203 FFECOM_f2cREAL,
12204 "real");
12205 ffecom_f2c_make_type_ (&ffecom_f2c_doublereal_type_node,
12206 FFECOM_f2cDOUBLEREAL,
12207 "doublereal");
12208 ffecom_f2c_make_type_ (&ffecom_f2c_complex_type_node,
12209 FFECOM_f2cCOMPLEX,
12210 "complex");
12211 ffecom_f2c_make_type_ (&ffecom_f2c_doublecomplex_type_node,
12212 FFECOM_f2cDOUBLECOMPLEX,
12213 "doublecomplex");
12214 ffecom_f2c_make_type_ (&ffecom_f2c_longint_type_node,
12215 FFECOM_f2cLONGINT,
12216 "longint");
12217 ffecom_f2c_make_type_ (&ffecom_f2c_logical_type_node,
12218 FFECOM_f2cLOGICAL,
12219 "logical");
12220 ffecom_f2c_make_type_ (&ffecom_f2c_flag_type_node,
12221 FFECOM_f2cFLAG,
12222 "flag");
12223 ffecom_f2c_make_type_ (&ffecom_f2c_ftnlen_type_node,
12224 FFECOM_f2cFTNLEN,
12225 "ftnlen");
12226 ffecom_f2c_make_type_ (&ffecom_f2c_ftnint_type_node,
12227 FFECOM_f2cFTNINT,
12228 "ftnint");
5ff904cd 12229
c7e4ee3a
CB
12230 ffecom_f2c_ftnlen_zero_node
12231 = convert (ffecom_f2c_ftnlen_type_node, integer_zero_node);
5ff904cd 12232
c7e4ee3a
CB
12233 ffecom_f2c_ftnlen_one_node
12234 = convert (ffecom_f2c_ftnlen_type_node, integer_one_node);
5ff904cd 12235
c7e4ee3a
CB
12236 ffecom_f2c_ftnlen_two_node = build_int_2 (2, 0);
12237 TREE_TYPE (ffecom_f2c_ftnlen_two_node) = ffecom_integer_type_node;
5ff904cd 12238
c7e4ee3a
CB
12239 ffecom_f2c_ptr_to_ftnlen_type_node
12240 = build_pointer_type (ffecom_f2c_ftnlen_type_node);
5ff904cd 12241
c7e4ee3a
CB
12242 ffecom_f2c_ptr_to_ftnint_type_node
12243 = build_pointer_type (ffecom_f2c_ftnint_type_node);
5ff904cd 12244
c7e4ee3a
CB
12245 ffecom_f2c_ptr_to_integer_type_node
12246 = build_pointer_type (ffecom_f2c_integer_type_node);
5ff904cd 12247
c7e4ee3a
CB
12248 ffecom_f2c_ptr_to_real_type_node
12249 = build_pointer_type (ffecom_f2c_real_type_node);
5ff904cd 12250
c7e4ee3a
CB
12251 ffecom_float_zero_ = build_real (float_type_node, dconst0);
12252 ffecom_double_zero_ = build_real (double_type_node, dconst0);
12253 {
12254 REAL_VALUE_TYPE point_5;
5ff904cd 12255
c7e4ee3a
CB
12256#ifdef REAL_ARITHMETIC
12257 REAL_ARITHMETIC (point_5, RDIV_EXPR, dconst1, dconst2);
12258#else
12259 point_5 = .5;
12260#endif
12261 ffecom_float_half_ = build_real (float_type_node, point_5);
12262 ffecom_double_half_ = build_real (double_type_node, point_5);
12263 }
5ff904cd 12264
c7e4ee3a 12265 /* Do "extern int xargc;". */
5ff904cd 12266
c7e4ee3a
CB
12267 ffecom_tree_xargc_ = build_decl (VAR_DECL,
12268 get_identifier ("f__xargc"),
12269 integer_type_node);
12270 DECL_EXTERNAL (ffecom_tree_xargc_) = 1;
12271 TREE_STATIC (ffecom_tree_xargc_) = 1;
12272 TREE_PUBLIC (ffecom_tree_xargc_) = 1;
12273 ffecom_tree_xargc_ = start_decl (ffecom_tree_xargc_, FALSE);
12274 finish_decl (ffecom_tree_xargc_, NULL_TREE, FALSE);
5ff904cd 12275
c7e4ee3a
CB
12276#if 0 /* This is being fixed, and seems to be working now. */
12277 if ((FLOAT_TYPE_SIZE != 32)
12278 || (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))) != 32))
5ff904cd 12279 {
c7e4ee3a
CB
12280 warning ("configuration: REAL, INTEGER, and LOGICAL are %d bits wide,",
12281 (int) FLOAT_TYPE_SIZE);
12282 warning ("and pointers are %d bits wide, but g77 doesn't yet work",
12283 (int) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))));
12284 warning ("properly unless they all are 32 bits wide.");
12285 warning ("Please keep this in mind before you report bugs. g77 should");
12286 warning ("support non-32-bit machines better as of version 0.6.");
12287 }
12288#endif
5ff904cd 12289
c7e4ee3a
CB
12290#if 0 /* Code in ste.c that would crash has been commented out. */
12291 if (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
12292 < TYPE_PRECISION (string_type_node))
12293 /* I/O will probably crash. */
12294 warning ("configuration: char * holds %d bits, but ftnlen only %d",
12295 TYPE_PRECISION (string_type_node),
12296 TYPE_PRECISION (ffecom_f2c_ftnlen_type_node));
12297#endif
5ff904cd 12298
c7e4ee3a
CB
12299#if 0 /* ASSIGN-related stuff has been changed to accommodate this. */
12300 if (TYPE_PRECISION (ffecom_integer_type_node)
12301 < TYPE_PRECISION (string_type_node))
12302 /* ASSIGN 10 TO I will crash. */
12303 warning ("configuration: char * holds %d bits, but INTEGER only %d --\n\
12304 ASSIGN statement might fail",
12305 TYPE_PRECISION (string_type_node),
12306 TYPE_PRECISION (ffecom_integer_type_node));
12307#endif
12308}
5ff904cd 12309
c7e4ee3a
CB
12310#endif
12311/* ffecom_init_2 -- Initialize
5ff904cd 12312
c7e4ee3a 12313 ffecom_init_2(); */
5ff904cd 12314
c7e4ee3a
CB
12315#if FFECOM_targetCURRENT == FFECOM_targetGCC
12316void
12317ffecom_init_2 ()
12318{
12319 assert (ffecom_outer_function_decl_ == NULL_TREE);
12320 assert (current_function_decl == NULL_TREE);
12321 assert (ffecom_which_entrypoint_decl_ == NULL_TREE);
5ff904cd 12322
c7e4ee3a
CB
12323 ffecom_master_arglist_ = NULL;
12324 ++ffecom_num_fns_;
12325 ffecom_primary_entry_ = NULL;
12326 ffecom_is_altreturning_ = FALSE;
12327 ffecom_func_result_ = NULL_TREE;
12328 ffecom_multi_retval_ = NULL_TREE;
12329}
5ff904cd 12330
c7e4ee3a
CB
12331#endif
12332/* ffecom_list_expr -- Transform list of exprs into gcc tree
5ff904cd 12333
c7e4ee3a
CB
12334 tree t;
12335 ffebld expr; // FFE opITEM list.
12336 tree = ffecom_list_expr(expr);
5ff904cd 12337
c7e4ee3a 12338 List of actual args is transformed into corresponding gcc backend list. */
5ff904cd 12339
c7e4ee3a
CB
12340#if FFECOM_targetCURRENT == FFECOM_targetGCC
12341tree
12342ffecom_list_expr (ffebld expr)
5ff904cd 12343{
c7e4ee3a
CB
12344 tree list;
12345 tree *plist = &list;
12346 tree trail = NULL_TREE; /* Append char length args here. */
12347 tree *ptrail = &trail;
12348 tree length;
5ff904cd 12349
c7e4ee3a 12350 while (expr != NULL)
5ff904cd 12351 {
c7e4ee3a 12352 tree texpr = ffecom_arg_expr (ffebld_head (expr), &length);
5ff904cd 12353
c7e4ee3a
CB
12354 if (texpr == error_mark_node)
12355 return error_mark_node;
5ff904cd 12356
c7e4ee3a
CB
12357 *plist = build_tree_list (NULL_TREE, texpr);
12358 plist = &TREE_CHAIN (*plist);
12359 expr = ffebld_trail (expr);
12360 if (length != NULL_TREE)
5ff904cd 12361 {
c7e4ee3a
CB
12362 *ptrail = build_tree_list (NULL_TREE, length);
12363 ptrail = &TREE_CHAIN (*ptrail);
5ff904cd
JL
12364 }
12365 }
12366
c7e4ee3a 12367 *plist = trail;
5ff904cd 12368
c7e4ee3a
CB
12369 return list;
12370}
5ff904cd 12371
c7e4ee3a
CB
12372#endif
12373/* ffecom_list_ptr_to_expr -- Transform list of exprs into gcc tree
5ff904cd 12374
c7e4ee3a
CB
12375 tree t;
12376 ffebld expr; // FFE opITEM list.
12377 tree = ffecom_list_ptr_to_expr(expr);
5ff904cd 12378
c7e4ee3a
CB
12379 List of actual args is transformed into corresponding gcc backend list for
12380 use in calling an external procedure (vs. a statement function). */
5ff904cd 12381
c7e4ee3a
CB
12382#if FFECOM_targetCURRENT == FFECOM_targetGCC
12383tree
12384ffecom_list_ptr_to_expr (ffebld expr)
12385{
12386 tree list;
12387 tree *plist = &list;
12388 tree trail = NULL_TREE; /* Append char length args here. */
12389 tree *ptrail = &trail;
12390 tree length;
5ff904cd 12391
c7e4ee3a
CB
12392 while (expr != NULL)
12393 {
12394 tree texpr = ffecom_arg_ptr_to_expr (ffebld_head (expr), &length);
5ff904cd 12395
c7e4ee3a
CB
12396 if (texpr == error_mark_node)
12397 return error_mark_node;
5ff904cd 12398
c7e4ee3a
CB
12399 *plist = build_tree_list (NULL_TREE, texpr);
12400 plist = &TREE_CHAIN (*plist);
12401 expr = ffebld_trail (expr);
12402 if (length != NULL_TREE)
12403 {
12404 *ptrail = build_tree_list (NULL_TREE, length);
12405 ptrail = &TREE_CHAIN (*ptrail);
12406 }
12407 }
5ff904cd 12408
c7e4ee3a 12409 *plist = trail;
5ff904cd 12410
c7e4ee3a
CB
12411 return list;
12412}
5ff904cd 12413
c7e4ee3a
CB
12414#endif
12415/* Obtain gcc's LABEL_DECL tree for label. */
5ff904cd 12416
c7e4ee3a
CB
12417#if FFECOM_targetCURRENT == FFECOM_targetGCC
12418tree
12419ffecom_lookup_label (ffelab label)
12420{
12421 tree glabel;
5ff904cd 12422
c7e4ee3a
CB
12423 if (ffelab_hook (label) == NULL_TREE)
12424 {
12425 char labelname[16];
5ff904cd 12426
c7e4ee3a
CB
12427 switch (ffelab_type (label))
12428 {
12429 case FFELAB_typeLOOPEND:
12430 case FFELAB_typeNOTLOOP:
12431 case FFELAB_typeENDIF:
12432 sprintf (labelname, "%" ffelabValue_f "u", ffelab_value (label));
12433 glabel = build_decl (LABEL_DECL, get_identifier (labelname),
12434 void_type_node);
12435 DECL_CONTEXT (glabel) = current_function_decl;
12436 DECL_MODE (glabel) = VOIDmode;
12437 break;
5ff904cd 12438
c7e4ee3a
CB
12439 case FFELAB_typeFORMAT:
12440 push_obstacks_nochange ();
12441 end_temporary_allocation ();
5ff904cd 12442
c7e4ee3a
CB
12443 glabel = build_decl (VAR_DECL,
12444 ffecom_get_invented_identifier
12445 ("__g77_format_%d", NULL,
12446 (int) ffelab_value (label)),
12447 build_type_variant (build_array_type
12448 (char_type_node,
12449 NULL_TREE),
12450 1, 0));
12451 TREE_CONSTANT (glabel) = 1;
12452 TREE_STATIC (glabel) = 1;
12453 DECL_CONTEXT (glabel) = 0;
12454 DECL_INITIAL (glabel) = NULL;
12455 make_decl_rtl (glabel, NULL, 0);
12456 expand_decl (glabel);
5ff904cd 12457
c7e4ee3a
CB
12458 resume_temporary_allocation ();
12459 pop_obstacks ();
5ff904cd 12460
c7e4ee3a 12461 break;
5ff904cd 12462
c7e4ee3a
CB
12463 case FFELAB_typeANY:
12464 glabel = error_mark_node;
12465 break;
5ff904cd 12466
c7e4ee3a
CB
12467 default:
12468 assert ("bad label type" == NULL);
12469 glabel = NULL;
12470 break;
12471 }
12472 ffelab_set_hook (label, glabel);
12473 }
12474 else
12475 {
12476 glabel = ffelab_hook (label);
12477 }
5ff904cd 12478
c7e4ee3a
CB
12479 return glabel;
12480}
5ff904cd 12481
c7e4ee3a
CB
12482#endif
12483/* Stabilizes the arguments. Don't use this if the lhs and rhs come from
12484 a single source specification (as in the fourth argument of MVBITS).
12485 If the type is NULL_TREE, the type of lhs is used to make the type of
12486 the MODIFY_EXPR. */
5ff904cd 12487
c7e4ee3a
CB
12488#if FFECOM_targetCURRENT == FFECOM_targetGCC
12489tree
12490ffecom_modify (tree newtype, tree lhs,
12491 tree rhs)
12492{
12493 if (lhs == error_mark_node || rhs == error_mark_node)
12494 return error_mark_node;
5ff904cd 12495
c7e4ee3a
CB
12496 if (newtype == NULL_TREE)
12497 newtype = TREE_TYPE (lhs);
5ff904cd 12498
c7e4ee3a
CB
12499 if (TREE_SIDE_EFFECTS (lhs))
12500 lhs = stabilize_reference (lhs);
5ff904cd 12501
c7e4ee3a
CB
12502 return ffecom_2s (MODIFY_EXPR, newtype, lhs, rhs);
12503}
5ff904cd 12504
c7e4ee3a 12505#endif
5ff904cd 12506
c7e4ee3a 12507/* Register source file name. */
5ff904cd 12508
c7e4ee3a
CB
12509void
12510ffecom_file (char *name)
12511{
12512#if FFECOM_GCC_INCLUDE
12513 ffecom_file_ (name);
12514#endif
12515}
5ff904cd 12516
c7e4ee3a 12517/* ffecom_notify_init_storage -- An aggregate storage is now fully init'ed
5ff904cd 12518
c7e4ee3a
CB
12519 ffestorag st;
12520 ffecom_notify_init_storage(st);
5ff904cd 12521
c7e4ee3a
CB
12522 Gets called when all possible units in an aggregate storage area (a LOCAL
12523 with equivalences or a COMMON) have been initialized. The initialization
12524 info either is in ffestorag_init or, if that is NULL,
12525 ffestorag_accretion:
5ff904cd 12526
c7e4ee3a
CB
12527 ffestorag_init may contain an opCONTER or opARRTER. opCONTER may occur
12528 even for an array if the array is one element in length!
5ff904cd 12529
c7e4ee3a
CB
12530 ffestorag_accretion will contain an opACCTER. It is much like an
12531 opARRTER except it has an ffebit object in it instead of just a size.
12532 The back end can use the info in the ffebit object, if it wants, to
12533 reduce the amount of actual initialization, but in any case it should
12534 kill the ffebit object when done. Also, set accretion to NULL but
12535 init to a non-NULL value.
5ff904cd 12536
c7e4ee3a
CB
12537 After performing initialization, DO NOT set init to NULL, because that'll
12538 tell the front end it is ok for more initialization to happen. Instead,
12539 set init to an opANY expression or some such thing that you can use to
12540 tell that you've already initialized the object.
5ff904cd 12541
c7e4ee3a
CB
12542 27-Oct-91 JCB 1.1
12543 Support two-pass FFE. */
5ff904cd 12544
c7e4ee3a
CB
12545void
12546ffecom_notify_init_storage (ffestorag st)
12547{
12548 ffebld init; /* The initialization expression. */
12549#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12550 ffetargetOffset size; /* The size of the entity. */
12551 ffetargetAlign pad; /* Its initial padding. */
12552#endif
12553
12554 if (ffestorag_init (st) == NULL)
5ff904cd 12555 {
c7e4ee3a
CB
12556 init = ffestorag_accretion (st);
12557 assert (init != NULL);
12558 ffestorag_set_accretion (st, NULL);
12559 ffestorag_set_accretes (st, 0);
12560
12561#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12562 /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12563 size = ffebld_accter_size (init);
12564 pad = ffebld_accter_pad (init);
12565 ffebit_kill (ffebld_accter_bits (init));
12566 ffebld_set_op (init, FFEBLD_opARRTER);
12567 ffebld_set_arrter (init, ffebld_accter (init));
12568 ffebld_arrter_set_size (init, size);
12569 ffebld_arrter_set_pad (init, size);
12570#endif
12571
12572#if FFECOM_TWOPASS
12573 ffestorag_set_init (st, init);
12574#endif
5ff904cd 12575 }
c7e4ee3a
CB
12576#if FFECOM_ONEPASS
12577 else
12578 init = ffestorag_init (st);
5ff904cd
JL
12579#endif
12580
c7e4ee3a
CB
12581#if FFECOM_ONEPASS /* Process the inits, wipe 'em out. */
12582 ffestorag_set_init (st, ffebld_new_any ());
5ff904cd 12583
c7e4ee3a
CB
12584 if (ffebld_op (init) == FFEBLD_opANY)
12585 return; /* Oh, we already did this! */
5ff904cd 12586
c7e4ee3a
CB
12587#if FFECOM_targetCURRENT == FFECOM_targetFFE
12588 {
12589 ffesymbol s;
5ff904cd 12590
c7e4ee3a
CB
12591 if (ffestorag_symbol (st) != NULL)
12592 s = ffestorag_symbol (st);
12593 else
12594 s = ffestorag_typesymbol (st);
5ff904cd 12595
c7e4ee3a
CB
12596 fprintf (dmpout, "= initialize_storage \"%s\" ",
12597 (s != NULL) ? ffesymbol_text (s) : "(unnamed)");
12598 ffebld_dump (init);
12599 fputc ('\n', dmpout);
12600 }
12601#endif
5ff904cd 12602
c7e4ee3a
CB
12603#endif /* if FFECOM_ONEPASS */
12604}
5ff904cd 12605
c7e4ee3a 12606/* ffecom_notify_init_symbol -- A symbol is now fully init'ed
5ff904cd 12607
c7e4ee3a
CB
12608 ffesymbol s;
12609 ffecom_notify_init_symbol(s);
5ff904cd 12610
c7e4ee3a
CB
12611 Gets called when all possible units in a symbol (not placed in COMMON
12612 or involved in EQUIVALENCE, unless it as yet has no ffestorag object)
12613 have been initialized. The initialization info either is in
12614 ffesymbol_init or, if that is NULL, ffesymbol_accretion:
5ff904cd 12615
c7e4ee3a
CB
12616 ffesymbol_init may contain an opCONTER or opARRTER. opCONTER may occur
12617 even for an array if the array is one element in length!
5ff904cd 12618
c7e4ee3a
CB
12619 ffesymbol_accretion will contain an opACCTER. It is much like an
12620 opARRTER except it has an ffebit object in it instead of just a size.
12621 The back end can use the info in the ffebit object, if it wants, to
12622 reduce the amount of actual initialization, but in any case it should
12623 kill the ffebit object when done. Also, set accretion to NULL but
12624 init to a non-NULL value.
5ff904cd 12625
c7e4ee3a
CB
12626 After performing initialization, DO NOT set init to NULL, because that'll
12627 tell the front end it is ok for more initialization to happen. Instead,
12628 set init to an opANY expression or some such thing that you can use to
12629 tell that you've already initialized the object.
5ff904cd 12630
c7e4ee3a
CB
12631 27-Oct-91 JCB 1.1
12632 Support two-pass FFE. */
5ff904cd 12633
c7e4ee3a
CB
12634void
12635ffecom_notify_init_symbol (ffesymbol s)
12636{
12637 ffebld init; /* The initialization expression. */
12638#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12639 ffetargetOffset size; /* The size of the entity. */
12640 ffetargetAlign pad; /* Its initial padding. */
12641#endif
5ff904cd 12642
c7e4ee3a
CB
12643 if (ffesymbol_storage (s) == NULL)
12644 return; /* Do nothing until COMMON/EQUIVALENCE
12645 possibilities checked. */
5ff904cd 12646
c7e4ee3a
CB
12647 if ((ffesymbol_init (s) == NULL)
12648 && ((init = ffesymbol_accretion (s)) != NULL))
12649 {
12650 ffesymbol_set_accretion (s, NULL);
12651 ffesymbol_set_accretes (s, 0);
5ff904cd 12652
c7e4ee3a
CB
12653#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12654 /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12655 size = ffebld_accter_size (init);
12656 pad = ffebld_accter_pad (init);
12657 ffebit_kill (ffebld_accter_bits (init));
12658 ffebld_set_op (init, FFEBLD_opARRTER);
12659 ffebld_set_arrter (init, ffebld_accter (init));
12660 ffebld_arrter_set_size (init, size);
12661 ffebld_arrter_set_pad (init, size);
12662#endif
5ff904cd 12663
c7e4ee3a
CB
12664#if FFECOM_TWOPASS
12665 ffesymbol_set_init (s, init);
12666#endif
12667 }
12668#if FFECOM_ONEPASS
12669 else
12670 init = ffesymbol_init (s);
12671#endif
5ff904cd 12672
c7e4ee3a
CB
12673#if FFECOM_ONEPASS
12674 ffesymbol_set_init (s, ffebld_new_any ());
5ff904cd 12675
c7e4ee3a
CB
12676 if (ffebld_op (init) == FFEBLD_opANY)
12677 return; /* Oh, we already did this! */
5ff904cd 12678
c7e4ee3a
CB
12679#if FFECOM_targetCURRENT == FFECOM_targetFFE
12680 fprintf (dmpout, "= initialize_symbol \"%s\" ", ffesymbol_text (s));
12681 ffebld_dump (init);
12682 fputc ('\n', dmpout);
12683#endif
5ff904cd 12684
c7e4ee3a
CB
12685#endif /* if FFECOM_ONEPASS */
12686}
5ff904cd 12687
c7e4ee3a 12688/* ffecom_notify_primary_entry -- Learn which is the primary entry point
5ff904cd 12689
c7e4ee3a
CB
12690 ffesymbol s;
12691 ffecom_notify_primary_entry(s);
5ff904cd 12692
c7e4ee3a
CB
12693 Gets called when implicit or explicit PROGRAM statement seen or when
12694 FUNCTION, SUBROUTINE, or BLOCK DATA statement seen, with the primary
12695 global symbol that serves as the entry point. */
5ff904cd 12696
c7e4ee3a
CB
12697void
12698ffecom_notify_primary_entry (ffesymbol s)
12699{
12700 ffecom_primary_entry_ = s;
12701 ffecom_primary_entry_kind_ = ffesymbol_kind (s);
5ff904cd 12702
c7e4ee3a
CB
12703 if ((ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
12704 || (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE))
12705 ffecom_primary_entry_is_proc_ = TRUE;
12706 else
12707 ffecom_primary_entry_is_proc_ = FALSE;
5ff904cd 12708
c7e4ee3a
CB
12709 if (!ffe_is_silent ())
12710 {
12711 if (ffecom_primary_entry_kind_ == FFEINFO_kindPROGRAM)
12712 fprintf (stderr, "%s:\n", ffesymbol_text (s));
12713 else
12714 fprintf (stderr, " %s:\n", ffesymbol_text (s));
12715 }
5ff904cd 12716
c7e4ee3a
CB
12717#if FFECOM_targetCURRENT == FFECOM_targetGCC
12718 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
12719 {
12720 ffebld list;
12721 ffebld arg;
5ff904cd 12722
c7e4ee3a
CB
12723 for (list = ffesymbol_dummyargs (s);
12724 list != NULL;
12725 list = ffebld_trail (list))
12726 {
12727 arg = ffebld_head (list);
12728 if (ffebld_op (arg) == FFEBLD_opSTAR)
12729 {
12730 ffecom_is_altreturning_ = TRUE;
12731 break;
12732 }
12733 }
12734 }
12735#endif
12736}
5ff904cd 12737
c7e4ee3a
CB
12738FILE *
12739ffecom_open_include (char *name, ffewhereLine l, ffewhereColumn c)
12740{
12741#if FFECOM_GCC_INCLUDE
12742 return ffecom_open_include_ (name, l, c);
12743#else
12744 return fopen (name, "r");
5ff904cd 12745#endif
c7e4ee3a 12746}
5ff904cd 12747
c7e4ee3a 12748/* ffecom_ptr_to_expr -- Transform expr into gcc tree with & in front
5ff904cd 12749
c7e4ee3a
CB
12750 tree t;
12751 ffebld expr; // FFE expression.
12752 tree = ffecom_ptr_to_expr(expr);
5ff904cd 12753
c7e4ee3a 12754 Like ffecom_expr, but sticks address-of in front of most things. */
5ff904cd 12755
c7e4ee3a
CB
12756#if FFECOM_targetCURRENT == FFECOM_targetGCC
12757tree
12758ffecom_ptr_to_expr (ffebld expr)
12759{
12760 tree item;
12761 ffeinfoBasictype bt;
12762 ffeinfoKindtype kt;
12763 ffesymbol s;
5ff904cd 12764
c7e4ee3a 12765 assert (expr != NULL);
5ff904cd 12766
c7e4ee3a
CB
12767 switch (ffebld_op (expr))
12768 {
12769 case FFEBLD_opSYMTER:
12770 s = ffebld_symter (expr);
12771 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
12772 {
12773 ffecomGfrt ix;
5ff904cd 12774
c7e4ee3a
CB
12775 ix = ffeintrin_gfrt_indirect (ffebld_symter_implementation (expr));
12776 assert (ix != FFECOM_gfrt);
12777 if ((item = ffecom_gfrt_[ix]) == NULL_TREE)
12778 {
12779 ffecom_make_gfrt_ (ix);
12780 item = ffecom_gfrt_[ix];
12781 }
12782 }
12783 else
12784 {
12785 item = ffesymbol_hook (s).decl_tree;
12786 if (item == NULL_TREE)
12787 {
12788 s = ffecom_sym_transform_ (s);
12789 item = ffesymbol_hook (s).decl_tree;
12790 }
12791 }
12792 assert (item != NULL);
12793 if (item == error_mark_node)
12794 return item;
12795 if (!ffesymbol_hook (s).addr)
12796 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12797 item);
12798 return item;
5ff904cd 12799
c7e4ee3a
CB
12800 case FFEBLD_opARRAYREF:
12801 {
c7e4ee3a 12802 item = ffecom_ptr_to_expr (ffebld_left (expr));
5ff904cd 12803
c7e4ee3a
CB
12804 if (item == error_mark_node)
12805 return item;
5ff904cd 12806
c7e4ee3a
CB
12807 if ((ffebld_where (expr) == FFEINFO_whereFLEETING)
12808 && !mark_addressable (item))
12809 return error_mark_node; /* Make sure non-const ref is to
12810 non-reg. */
5ff904cd 12811
6b55276e 12812 item = ffecom_arrayref_ (item, expr, 1);
c7e4ee3a
CB
12813 }
12814 return item;
5ff904cd 12815
c7e4ee3a 12816 case FFEBLD_opCONTER:
5ff904cd 12817
c7e4ee3a
CB
12818 bt = ffeinfo_basictype (ffebld_info (expr));
12819 kt = ffeinfo_kindtype (ffebld_info (expr));
5ff904cd 12820
c7e4ee3a
CB
12821 item = ffecom_constantunion (&ffebld_constant_union
12822 (ffebld_conter (expr)), bt, kt,
12823 ffecom_tree_type[bt][kt]);
12824 if (item == error_mark_node)
12825 return error_mark_node;
12826 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12827 item);
12828 return item;
5ff904cd 12829
c7e4ee3a
CB
12830 case FFEBLD_opANY:
12831 return error_mark_node;
5ff904cd 12832
c7e4ee3a
CB
12833 default:
12834 bt = ffeinfo_basictype (ffebld_info (expr));
12835 kt = ffeinfo_kindtype (ffebld_info (expr));
12836
12837 item = ffecom_expr (expr);
12838 if (item == error_mark_node)
12839 return error_mark_node;
12840
12841 /* The back end currently optimizes a bit too zealously for us, in that
12842 we fail JCB001 if the following block of code is omitted. It checks
12843 to see if the transformed expression is a symbol or array reference,
12844 and encloses it in a SAVE_EXPR if that is the case. */
12845
12846 STRIP_NOPS (item);
12847 if ((TREE_CODE (item) == VAR_DECL)
12848 || (TREE_CODE (item) == PARM_DECL)
12849 || (TREE_CODE (item) == RESULT_DECL)
12850 || (TREE_CODE (item) == INDIRECT_REF)
12851 || (TREE_CODE (item) == ARRAY_REF)
12852 || (TREE_CODE (item) == COMPONENT_REF)
12853#ifdef OFFSET_REF
12854 || (TREE_CODE (item) == OFFSET_REF)
12855#endif
12856 || (TREE_CODE (item) == BUFFER_REF)
12857 || (TREE_CODE (item) == REALPART_EXPR)
12858 || (TREE_CODE (item) == IMAGPART_EXPR))
12859 {
12860 item = ffecom_save_tree (item);
12861 }
12862
12863 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12864 item);
12865 return item;
12866 }
12867
12868 assert ("fall-through error" == NULL);
12869 return error_mark_node;
5ff904cd
JL
12870}
12871
12872#endif
c7e4ee3a 12873/* Obtain a temp var with given data type.
5ff904cd 12874
c7e4ee3a
CB
12875 size is FFETARGET_charactersizeNONE for a non-CHARACTER type
12876 or >= 0 for a CHARACTER type.
5ff904cd 12877
c7e4ee3a 12878 elements is -1 for a scalar or > 0 for an array of type. */
5ff904cd
JL
12879
12880#if FFECOM_targetCURRENT == FFECOM_targetGCC
12881tree
c7e4ee3a
CB
12882ffecom_make_tempvar (const char *commentary, tree type,
12883 ffetargetCharacterSize size, int elements)
5ff904cd 12884{
c7e4ee3a
CB
12885 int yes;
12886 tree t;
12887 static int mynumber;
5ff904cd 12888
c7e4ee3a 12889 assert (current_binding_level->prep_state < 2);
702edf1d 12890
c7e4ee3a
CB
12891 if (type == error_mark_node)
12892 return error_mark_node;
702edf1d 12893
c7e4ee3a 12894 yes = suspend_momentary ();
5ff904cd 12895
c7e4ee3a
CB
12896 if (size != FFETARGET_charactersizeNONE)
12897 type = build_array_type (type,
12898 build_range_type (ffecom_f2c_ftnlen_type_node,
12899 ffecom_f2c_ftnlen_one_node,
12900 build_int_2 (size, 0)));
12901 if (elements != -1)
12902 type = build_array_type (type,
12903 build_range_type (integer_type_node,
12904 integer_zero_node,
12905 build_int_2 (elements - 1,
12906 0)));
12907 t = build_decl (VAR_DECL,
12908 ffecom_get_invented_identifier ("__g77_%s_%d",
12909 commentary,
12910 mynumber++),
12911 type);
5ff904cd 12912
c7e4ee3a
CB
12913 t = start_decl (t, FALSE);
12914 finish_decl (t, NULL_TREE, FALSE);
12915
12916 resume_momentary (yes);
5ff904cd 12917
c7e4ee3a
CB
12918 return t;
12919}
5ff904cd 12920#endif
5ff904cd 12921
c7e4ee3a 12922/* Prepare argument pointer to expression.
5ff904cd 12923
c7e4ee3a
CB
12924 Like ffecom_prepare_expr, except for expressions to be evaluated
12925 via ffecom_arg_ptr_to_expr. */
5ff904cd 12926
c7e4ee3a
CB
12927void
12928ffecom_prepare_arg_ptr_to_expr (ffebld expr)
5ff904cd 12929{
c7e4ee3a
CB
12930 /* ~~For now, it seems to be the same thing. */
12931 ffecom_prepare_expr (expr);
12932 return;
12933}
702edf1d 12934
c7e4ee3a 12935/* End of preparations. */
702edf1d 12936
c7e4ee3a
CB
12937bool
12938ffecom_prepare_end (void)
12939{
12940 int prep_state = current_binding_level->prep_state;
5ff904cd 12941
c7e4ee3a
CB
12942 assert (prep_state < 2);
12943 current_binding_level->prep_state = 2;
5ff904cd 12944
c7e4ee3a 12945 return (prep_state == 1) ? TRUE : FALSE;
5ff904cd
JL
12946}
12947
c7e4ee3a 12948/* Prepare expression.
5ff904cd 12949
c7e4ee3a
CB
12950 This is called before any code is generated for the current block.
12951 It scans the expression, declares any temporaries that might be needed
12952 during evaluation of the expression, and stores those temporaries in
12953 the appropriate "hook" fields of the expression. `dest', if not NULL,
12954 specifies the destination that ffecom_expr_ will see, in case that
12955 helps avoid generating unused temporaries.
12956
12957 ~~Improve to avoid allocating unused temporaries by taking `dest'
12958 into account vis-a-vis aliasing requirements of complex/character
12959 functions. */
12960
12961void
12962ffecom_prepare_expr_ (ffebld expr, ffebld dest UNUSED)
5ff904cd 12963{
c7e4ee3a
CB
12964 ffeinfoBasictype bt;
12965 ffeinfoKindtype kt;
12966 ffetargetCharacterSize sz;
12967 tree tempvar = NULL_TREE;
5ff904cd 12968
c7e4ee3a
CB
12969 assert (current_binding_level->prep_state < 2);
12970
12971 if (! expr)
12972 return;
12973
12974 bt = ffeinfo_basictype (ffebld_info (expr));
12975 kt = ffeinfo_kindtype (ffebld_info (expr));
12976 sz = ffeinfo_size (ffebld_info (expr));
12977
12978 /* Generate whatever temporaries are needed to represent the result
12979 of the expression. */
12980
12981 switch (ffebld_op (expr))
5ff904cd 12982 {
c7e4ee3a
CB
12983 default:
12984 /* Don't make temps for SYMTER, CONTER, etc. */
12985 if (ffebld_arity (expr) == 0)
12986 break;
5ff904cd 12987
c7e4ee3a 12988 switch (bt)
5ff904cd 12989 {
c7e4ee3a
CB
12990 case FFEINFO_basictypeCOMPLEX:
12991 if (ffebld_op (expr) == FFEBLD_opFUNCREF)
12992 {
12993 ffesymbol s;
5ff904cd 12994
c7e4ee3a
CB
12995 if (ffebld_op (ffebld_left (expr)) != FFEBLD_opSYMTER)
12996 break;
5ff904cd 12997
c7e4ee3a
CB
12998 s = ffebld_symter (ffebld_left (expr));
12999 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT
13000 || ! ffesymbol_is_f2c (s))
13001 break;
13002 }
13003 else if (ffebld_op (expr) == FFEBLD_opPOWER)
13004 {
13005 /* Requires special treatment. There's no POW_CC function
13006 in libg2c, so POW_ZZ is used, which means we always
13007 need a double-complex temp, not a single-complex. */
13008 kt = FFEINFO_kindtypeREAL2;
13009 }
13010 else if (ffebld_op (expr) != FFEBLD_opDIVIDE)
13011 /* The other ops don't need temps for complex operands. */
13012 break;
5ff904cd 13013
c7e4ee3a
CB
13014 /* ~~~Avoid making temps for some intrinsics, such as AIMAG(C),
13015 REAL(C). See 19990325-0.f, routine `check', for cases. */
13016 tempvar = ffecom_make_tempvar ("complex",
13017 ffecom_tree_type
13018 [FFEINFO_basictypeCOMPLEX][kt],
13019 FFETARGET_charactersizeNONE,
13020 -1);
5ff904cd
JL
13021 break;
13022
c7e4ee3a
CB
13023 case FFEINFO_basictypeCHARACTER:
13024 if (ffebld_op (expr) != FFEBLD_opFUNCREF)
13025 break;
13026
13027 if (sz == FFETARGET_charactersizeNONE)
13028 /* ~~Kludge alert! This should someday be fixed. */
13029 sz = 24;
13030
13031 tempvar = ffecom_make_tempvar ("char", char_type_node, sz, -1);
5ff904cd
JL
13032 break;
13033
13034 default:
5ff904cd
JL
13035 break;
13036 }
c7e4ee3a 13037 break;
5ff904cd 13038
c7e4ee3a
CB
13039#ifdef HAHA
13040 case FFEBLD_opPOWER:
13041 {
13042 tree rtype, ltype;
13043 tree rtmp, ltmp, result;
5ff904cd 13044
c7e4ee3a
CB
13045 ltype = ffecom_type_expr (ffebld_left (expr));
13046 rtype = ffecom_type_expr (ffebld_right (expr));
5ff904cd 13047
c7e4ee3a
CB
13048 rtmp = ffecom_make_tempvar (rtype, FFETARGET_charactersizeNONE, -1);
13049 ltmp = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
13050 result = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
5ff904cd 13051
c7e4ee3a
CB
13052 tempvar = make_tree_vec (3);
13053 TREE_VEC_ELT (tempvar, 0) = rtmp;
13054 TREE_VEC_ELT (tempvar, 1) = ltmp;
13055 TREE_VEC_ELT (tempvar, 2) = result;
13056 }
13057 break;
13058#endif /* HAHA */
5ff904cd 13059
c7e4ee3a
CB
13060 case FFEBLD_opCONCATENATE:
13061 {
13062 /* This gets special handling, because only one set of temps
13063 is needed for a tree of these -- the tree is treated as
13064 a flattened list of concatenations when generating code. */
5ff904cd 13065
c7e4ee3a
CB
13066 ffecomConcatList_ catlist;
13067 tree ltmp, itmp, result;
13068 int count;
13069 int i;
5ff904cd 13070
c7e4ee3a
CB
13071 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
13072 count = ffecom_concat_list_count_ (catlist);
5ff904cd 13073
c7e4ee3a
CB
13074 if (count >= 2)
13075 {
13076 ltmp
13077 = ffecom_make_tempvar ("concat_len",
13078 ffecom_f2c_ftnlen_type_node,
13079 FFETARGET_charactersizeNONE, count);
13080 itmp
13081 = ffecom_make_tempvar ("concat_item",
13082 ffecom_f2c_address_type_node,
13083 FFETARGET_charactersizeNONE, count);
13084 result
13085 = ffecom_make_tempvar ("concat_res",
13086 char_type_node,
13087 ffecom_concat_list_maxlen_ (catlist),
13088 -1);
13089
13090 tempvar = make_tree_vec (3);
13091 TREE_VEC_ELT (tempvar, 0) = ltmp;
13092 TREE_VEC_ELT (tempvar, 1) = itmp;
13093 TREE_VEC_ELT (tempvar, 2) = result;
13094 }
5ff904cd 13095
c7e4ee3a
CB
13096 for (i = 0; i < count; ++i)
13097 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist,
13098 i));
5ff904cd 13099
c7e4ee3a 13100 ffecom_concat_list_kill_ (catlist);
5ff904cd 13101
c7e4ee3a
CB
13102 if (tempvar)
13103 {
13104 ffebld_nonter_set_hook (expr, tempvar);
13105 current_binding_level->prep_state = 1;
13106 }
13107 }
13108 return;
5ff904cd 13109
c7e4ee3a
CB
13110 case FFEBLD_opCONVERT:
13111 if (bt == FFEINFO_basictypeCHARACTER
13112 && ((ffebld_size_known (ffebld_left (expr))
13113 == FFETARGET_charactersizeNONE)
13114 || (ffebld_size_known (ffebld_left (expr)) >= sz)))
13115 tempvar = ffecom_make_tempvar ("convert", char_type_node, sz, -1);
13116 break;
13117 }
5ff904cd 13118
c7e4ee3a
CB
13119 if (tempvar)
13120 {
13121 ffebld_nonter_set_hook (expr, tempvar);
13122 current_binding_level->prep_state = 1;
13123 }
5ff904cd 13124
c7e4ee3a 13125 /* Prepare subexpressions for this expr. */
5ff904cd 13126
c7e4ee3a 13127 switch (ffebld_op (expr))
5ff904cd 13128 {
c7e4ee3a
CB
13129 case FFEBLD_opPERCENT_LOC:
13130 ffecom_prepare_ptr_to_expr (ffebld_left (expr));
13131 break;
5ff904cd 13132
c7e4ee3a
CB
13133 case FFEBLD_opPERCENT_VAL:
13134 case FFEBLD_opPERCENT_REF:
13135 ffecom_prepare_expr (ffebld_left (expr));
13136 break;
5ff904cd 13137
c7e4ee3a
CB
13138 case FFEBLD_opPERCENT_DESCR:
13139 ffecom_prepare_arg_ptr_to_expr (ffebld_left (expr));
13140 break;
5ff904cd 13141
c7e4ee3a
CB
13142 case FFEBLD_opITEM:
13143 {
13144 ffebld item;
5ff904cd 13145
c7e4ee3a
CB
13146 for (item = expr;
13147 item != NULL;
13148 item = ffebld_trail (item))
13149 if (ffebld_head (item) != NULL)
13150 ffecom_prepare_expr (ffebld_head (item));
13151 }
13152 break;
5ff904cd 13153
c7e4ee3a
CB
13154 default:
13155 /* Need to handle character conversion specially. */
13156 switch (ffebld_arity (expr))
13157 {
13158 case 2:
13159 ffecom_prepare_expr (ffebld_left (expr));
13160 ffecom_prepare_expr (ffebld_right (expr));
13161 break;
5ff904cd 13162
c7e4ee3a
CB
13163 case 1:
13164 ffecom_prepare_expr (ffebld_left (expr));
13165 break;
5ff904cd 13166
c7e4ee3a
CB
13167 default:
13168 break;
13169 }
13170 }
5ff904cd 13171
c7e4ee3a 13172 return;
5ff904cd
JL
13173}
13174
c7e4ee3a 13175/* Prepare expression for reading and writing.
5ff904cd 13176
c7e4ee3a
CB
13177 Like ffecom_prepare_expr, except for expressions to be evaluated
13178 via ffecom_expr_rw. */
5ff904cd 13179
c7e4ee3a
CB
13180void
13181ffecom_prepare_expr_rw (tree type, ffebld expr)
13182{
13183 /* This is all we support for now. */
13184 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
5ff904cd 13185
c7e4ee3a
CB
13186 /* ~~For now, it seems to be the same thing. */
13187 ffecom_prepare_expr (expr);
13188 return;
13189}
5ff904cd 13190
c7e4ee3a 13191/* Prepare expression for writing.
5ff904cd 13192
c7e4ee3a
CB
13193 Like ffecom_prepare_expr, except for expressions to be evaluated
13194 via ffecom_expr_w. */
5ff904cd
JL
13195
13196void
c7e4ee3a 13197ffecom_prepare_expr_w (tree type, ffebld expr)
5ff904cd 13198{
c7e4ee3a
CB
13199 /* This is all we support for now. */
13200 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
5ff904cd 13201
c7e4ee3a
CB
13202 /* ~~For now, it seems to be the same thing. */
13203 ffecom_prepare_expr (expr);
13204 return;
13205}
5ff904cd 13206
c7e4ee3a 13207/* Prepare expression for returning.
5ff904cd 13208
c7e4ee3a
CB
13209 Like ffecom_prepare_expr, except for expressions to be evaluated
13210 via ffecom_return_expr. */
5ff904cd 13211
c7e4ee3a
CB
13212void
13213ffecom_prepare_return_expr (ffebld expr)
13214{
13215 assert (current_binding_level->prep_state < 2);
5ff904cd 13216
c7e4ee3a
CB
13217 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE
13218 && ffecom_is_altreturning_
13219 && expr != NULL)
13220 ffecom_prepare_expr (expr);
13221}
5ff904cd 13222
c7e4ee3a 13223/* Prepare pointer to expression.
5ff904cd 13224
c7e4ee3a
CB
13225 Like ffecom_prepare_expr, except for expressions to be evaluated
13226 via ffecom_ptr_to_expr. */
5ff904cd 13227
c7e4ee3a
CB
13228void
13229ffecom_prepare_ptr_to_expr (ffebld expr)
13230{
13231 /* ~~For now, it seems to be the same thing. */
13232 ffecom_prepare_expr (expr);
13233 return;
5ff904cd
JL
13234}
13235
c7e4ee3a 13236/* Transform expression into constant pointer-to-expression tree.
5ff904cd 13237
c7e4ee3a
CB
13238 If the expression can be transformed into a pointer-to-expression tree
13239 that is constant, that is done, and the tree returned. Else NULL_TREE
13240 is returned.
5ff904cd 13241
c7e4ee3a
CB
13242 That way, a caller can attempt to provide compile-time initialization
13243 of a variable and, if that fails, *then* choose to start a new block
13244 and resort to using temporaries, as appropriate. */
5ff904cd 13245
c7e4ee3a
CB
13246tree
13247ffecom_ptr_to_const_expr (ffebld expr)
5ff904cd 13248{
c7e4ee3a
CB
13249 if (! expr)
13250 return integer_zero_node;
5ff904cd 13251
c7e4ee3a
CB
13252 if (ffebld_op (expr) == FFEBLD_opANY)
13253 return error_mark_node;
5ff904cd 13254
c7e4ee3a
CB
13255 if (ffebld_arity (expr) == 0
13256 && (ffebld_op (expr) != FFEBLD_opSYMTER
13257 || ffebld_where (expr) == FFEINFO_whereCOMMON
13258 || ffebld_where (expr) == FFEINFO_whereGLOBAL
13259 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
5ff904cd 13260 {
c7e4ee3a
CB
13261 tree t;
13262
13263 t = ffecom_ptr_to_expr (expr);
13264 assert (TREE_CONSTANT (t));
13265 return t;
5ff904cd
JL
13266 }
13267
c7e4ee3a
CB
13268 return NULL_TREE;
13269}
13270
13271/* ffecom_return_expr -- Returns return-value expr given alt return expr
13272
13273 tree rtn; // NULL_TREE means use expand_null_return()
13274 ffebld expr; // NULL if no alt return expr to RETURN stmt
13275 rtn = ffecom_return_expr(expr);
13276
13277 Based on the program unit type and other info (like return function
13278 type, return master function type when alternate ENTRY points,
13279 whether subroutine has any alternate RETURN points, etc), returns the
13280 appropriate expression to be returned to the caller, or NULL_TREE
13281 meaning no return value or the caller expects it to be returned somewhere
13282 else (which is handled by other parts of this module). */
13283
5ff904cd 13284#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
13285tree
13286ffecom_return_expr (ffebld expr)
13287{
13288 tree rtn;
13289
13290 switch (ffecom_primary_entry_kind_)
5ff904cd 13291 {
c7e4ee3a
CB
13292 case FFEINFO_kindPROGRAM:
13293 case FFEINFO_kindBLOCKDATA:
13294 rtn = NULL_TREE;
13295 break;
5ff904cd 13296
c7e4ee3a
CB
13297 case FFEINFO_kindSUBROUTINE:
13298 if (!ffecom_is_altreturning_)
13299 rtn = NULL_TREE; /* No alt returns, never an expr. */
13300 else if (expr == NULL)
13301 rtn = integer_zero_node;
13302 else
13303 rtn = ffecom_expr (expr);
13304 break;
13305
13306 case FFEINFO_kindFUNCTION:
13307 if ((ffecom_multi_retval_ != NULL_TREE)
13308 || (ffesymbol_basictype (ffecom_primary_entry_)
13309 == FFEINFO_basictypeCHARACTER)
13310 || ((ffesymbol_basictype (ffecom_primary_entry_)
13311 == FFEINFO_basictypeCOMPLEX)
13312 && (ffecom_num_entrypoints_ == 0)
13313 && ffesymbol_is_f2c (ffecom_primary_entry_)))
13314 { /* Value is returned by direct assignment
13315 into (implicit) dummy. */
13316 rtn = NULL_TREE;
13317 break;
5ff904cd 13318 }
c7e4ee3a
CB
13319 rtn = ffecom_func_result_;
13320#if 0
13321 /* Spurious error if RETURN happens before first reference! So elide
13322 this code. In particular, for debugging registry, rtn should always
13323 be non-null after all, but TREE_USED won't be set until we encounter
13324 a reference in the code. Perfectly okay (but weird) code that,
13325 e.g., has "GOTO 20;10 RETURN;20 RTN=0;GOTO 10", would result in
13326 this diagnostic for no reason. Have people use -O -Wuninitialized
13327 and leave it to the back end to find obviously weird cases. */
5ff904cd 13328
c7e4ee3a
CB
13329 /* Used to "assert(rtn != NULL_TREE);" here, but it's kind of a valid
13330 situation; if the return value has never been referenced, it won't
13331 have a tree under 2pass mode. */
13332 if ((rtn == NULL_TREE)
13333 || !TREE_USED (rtn))
13334 {
13335 ffebad_start (FFEBAD_RETURN_VALUE_UNSET);
13336 ffebad_here (0, ffesymbol_where_line (ffecom_primary_entry_),
13337 ffesymbol_where_column (ffecom_primary_entry_));
13338 ffebad_string (ffesymbol_text (ffesymbol_funcresult
13339 (ffecom_primary_entry_)));
13340 ffebad_finish ();
13341 }
5ff904cd 13342#endif
c7e4ee3a 13343 break;
5ff904cd 13344
c7e4ee3a
CB
13345 default:
13346 assert ("bad unit kind" == NULL);
13347 case FFEINFO_kindANY:
13348 rtn = error_mark_node;
13349 break;
13350 }
5ff904cd 13351
c7e4ee3a
CB
13352 return rtn;
13353}
5ff904cd 13354
c7e4ee3a
CB
13355#endif
13356/* Do save_expr only if tree is not error_mark_node. */
5ff904cd
JL
13357
13358#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
13359tree
13360ffecom_save_tree (tree t)
5ff904cd 13361{
c7e4ee3a 13362 return save_expr (t);
5ff904cd 13363}
5ff904cd 13364#endif
c7e4ee3a
CB
13365
13366/* Start a compound statement (block). */
5ff904cd
JL
13367
13368#if FFECOM_targetCURRENT == FFECOM_targetGCC
13369void
c7e4ee3a 13370ffecom_start_compstmt (void)
5ff904cd 13371{
c7e4ee3a 13372 bison_rule_pushlevel_ ();
5ff904cd 13373}
c7e4ee3a 13374#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
5ff904cd 13375
c7e4ee3a 13376/* Public entry point for front end to access start_decl. */
5ff904cd
JL
13377
13378#if FFECOM_targetCURRENT == FFECOM_targetGCC
13379tree
c7e4ee3a 13380ffecom_start_decl (tree decl, bool is_initialized)
5ff904cd 13381{
c7e4ee3a
CB
13382 DECL_INITIAL (decl) = is_initialized ? error_mark_node : NULL_TREE;
13383 return start_decl (decl, FALSE);
13384}
5ff904cd 13385
c7e4ee3a
CB
13386#endif
13387/* ffecom_sym_commit -- Symbol's state being committed to reality
5ff904cd 13388
c7e4ee3a
CB
13389 ffesymbol s;
13390 ffecom_sym_commit(s);
5ff904cd 13391
c7e4ee3a
CB
13392 Does whatever the backend needs when a symbol is committed after having
13393 been backtrackable for a period of time. */
5ff904cd 13394
c7e4ee3a
CB
13395#if FFECOM_targetCURRENT == FFECOM_targetGCC
13396void
13397ffecom_sym_commit (ffesymbol s UNUSED)
13398{
13399 assert (!ffesymbol_retractable ());
13400}
5ff904cd 13401
c7e4ee3a
CB
13402#endif
13403/* ffecom_sym_end_transition -- Perform end transition on all symbols
5ff904cd 13404
c7e4ee3a 13405 ffecom_sym_end_transition();
5ff904cd 13406
c7e4ee3a
CB
13407 Does backend-specific stuff and also calls ffest_sym_end_transition
13408 to do the necessary FFE stuff.
5ff904cd 13409
c7e4ee3a
CB
13410 Backtracking is never enabled when this fn is called, so don't worry
13411 about it. */
5ff904cd 13412
c7e4ee3a
CB
13413ffesymbol
13414ffecom_sym_end_transition (ffesymbol s)
13415{
13416 ffestorag st;
5ff904cd 13417
c7e4ee3a 13418 assert (!ffesymbol_retractable ());
5ff904cd 13419
c7e4ee3a 13420 s = ffest_sym_end_transition (s);
5ff904cd 13421
c7e4ee3a
CB
13422#if FFECOM_targetCURRENT == FFECOM_targetGCC
13423 if ((ffesymbol_kind (s) == FFEINFO_kindBLOCKDATA)
13424 && (ffesymbol_where (s) == FFEINFO_whereGLOBAL))
13425 {
13426 ffecom_list_blockdata_
13427 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13428 FFEINTRIN_specNONE,
13429 FFEINTRIN_impNONE),
13430 ffecom_list_blockdata_);
5ff904cd 13431 }
5ff904cd 13432#endif
5ff904cd 13433
c7e4ee3a
CB
13434 /* This is where we finally notice that a symbol has partial initialization
13435 and finalize it. */
5ff904cd 13436
c7e4ee3a
CB
13437 if (ffesymbol_accretion (s) != NULL)
13438 {
13439 assert (ffesymbol_init (s) == NULL);
13440 ffecom_notify_init_symbol (s);
13441 }
13442 else if (((st = ffesymbol_storage (s)) != NULL)
13443 && ((st = ffestorag_parent (st)) != NULL)
13444 && (ffestorag_accretion (st) != NULL))
13445 {
13446 assert (ffestorag_init (st) == NULL);
13447 ffecom_notify_init_storage (st);
13448 }
5ff904cd
JL
13449
13450#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
13451 if ((ffesymbol_kind (s) == FFEINFO_kindCOMMON)
13452 && (ffesymbol_where (s) == FFEINFO_whereLOCAL)
13453 && (ffesymbol_storage (s) != NULL))
13454 {
13455 ffecom_list_common_
13456 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13457 FFEINTRIN_specNONE,
13458 FFEINTRIN_impNONE),
13459 ffecom_list_common_);
13460 }
13461#endif
5ff904cd 13462
c7e4ee3a
CB
13463 return s;
13464}
5ff904cd 13465
c7e4ee3a 13466/* ffecom_sym_exec_transition -- Perform exec transition on all symbols
5ff904cd 13467
c7e4ee3a 13468 ffecom_sym_exec_transition();
5ff904cd 13469
c7e4ee3a
CB
13470 Does backend-specific stuff and also calls ffest_sym_exec_transition
13471 to do the necessary FFE stuff.
5ff904cd 13472
c7e4ee3a
CB
13473 See the long-winded description in ffecom_sym_learned for info
13474 on handling the situation where backtracking is inhibited. */
5ff904cd 13475
c7e4ee3a
CB
13476ffesymbol
13477ffecom_sym_exec_transition (ffesymbol s)
13478{
13479 s = ffest_sym_exec_transition (s);
5ff904cd 13480
c7e4ee3a
CB
13481 return s;
13482}
5ff904cd 13483
c7e4ee3a 13484/* ffecom_sym_learned -- Initial or more info gained on symbol after exec
5ff904cd 13485
c7e4ee3a
CB
13486 ffesymbol s;
13487 s = ffecom_sym_learned(s);
5ff904cd 13488
c7e4ee3a
CB
13489 Called when a new symbol is seen after the exec transition or when more
13490 info (perhaps) is gained for an UNCERTAIN symbol. The symbol state when
13491 it arrives here is that all its latest info is updated already, so its
13492 state may be UNCERTAIN or UNDERSTOOD, it might already have the hook
13493 field filled in if its gone through here or exec_transition first, and
13494 so on.
5ff904cd 13495
c7e4ee3a
CB
13496 The backend probably wants to check ffesymbol_retractable() to see if
13497 backtracking is in effect. If so, the FFE's changes to the symbol may
13498 be retracted (undone) or committed (ratified), at which time the
13499 appropriate ffecom_sym_retract or _commit function will be called
13500 for that function.
5ff904cd 13501
c7e4ee3a
CB
13502 If the backend has its own backtracking mechanism, great, use it so that
13503 committal is a simple operation. Though it doesn't make much difference,
13504 I suppose: the reason for tentative symbol evolution in the FFE is to
13505 enable error detection in weird incorrect statements early and to disable
13506 incorrect error detection on a correct statement. The backend is not
13507 likely to introduce any information that'll get involved in these
13508 considerations, so it is probably just fine that the implementation
13509 model for this fn and for _exec_transition is to not do anything
13510 (besides the required FFE stuff) if ffesymbol_retractable() returns TRUE
13511 and instead wait until ffecom_sym_commit is called (which it never
13512 will be as long as we're using ambiguity-detecting statement analysis in
13513 the FFE, which we are initially to shake out the code, but don't depend
13514 on this), otherwise go ahead and do whatever is needed.
5ff904cd 13515
c7e4ee3a
CB
13516 In essence, then, when this fn and _exec_transition get called while
13517 backtracking is enabled, a general mechanism would be to flag which (or
13518 both) of these were called (and in what order? neat question as to what
13519 might happen that I'm too lame to think through right now) and then when
13520 _commit is called reproduce the original calling sequence, if any, for
13521 the two fns (at which point backtracking will, of course, be disabled). */
5ff904cd 13522
c7e4ee3a
CB
13523ffesymbol
13524ffecom_sym_learned (ffesymbol s)
13525{
13526 ffestorag_exec_layout (s);
5ff904cd 13527
c7e4ee3a 13528 return s;
5ff904cd
JL
13529}
13530
c7e4ee3a 13531/* ffecom_sym_retract -- Symbol's state being retracted from reality
5ff904cd 13532
c7e4ee3a
CB
13533 ffesymbol s;
13534 ffecom_sym_retract(s);
5ff904cd 13535
c7e4ee3a
CB
13536 Does whatever the backend needs when a symbol is retracted after having
13537 been backtrackable for a period of time. */
5ff904cd
JL
13538
13539#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
13540void
13541ffecom_sym_retract (ffesymbol s UNUSED)
5ff904cd 13542{
c7e4ee3a 13543 assert (!ffesymbol_retractable ());
5ff904cd 13544
c7e4ee3a
CB
13545#if 0 /* GCC doesn't commit any backtrackable sins,
13546 so nothing needed here. */
13547 switch (ffesymbol_hook (s).state)
5ff904cd 13548 {
c7e4ee3a 13549 case 0: /* nothing happened yet. */
5ff904cd
JL
13550 break;
13551
c7e4ee3a 13552 case 1: /* exec transition happened. */
5ff904cd
JL
13553 break;
13554
c7e4ee3a
CB
13555 case 2: /* learned happened. */
13556 break;
5ff904cd 13557
c7e4ee3a
CB
13558 case 3: /* learned then exec. */
13559 break;
13560
13561 case 4: /* exec then learned. */
5ff904cd
JL
13562 break;
13563
13564 default:
c7e4ee3a 13565 assert ("bad hook state" == NULL);
5ff904cd
JL
13566 break;
13567 }
c7e4ee3a
CB
13568#endif
13569}
5ff904cd 13570
c7e4ee3a
CB
13571#endif
13572/* Create temporary gcc label. */
13573
13574#if FFECOM_targetCURRENT == FFECOM_targetGCC
13575tree
13576ffecom_temp_label ()
13577{
13578 tree glabel;
13579 static int mynumber = 0;
13580
13581 glabel = build_decl (LABEL_DECL,
13582 ffecom_get_invented_identifier ("__g77_label_%d",
13583 NULL,
13584 mynumber++),
13585 void_type_node);
13586 DECL_CONTEXT (glabel) = current_function_decl;
13587 DECL_MODE (glabel) = VOIDmode;
13588
13589 return glabel;
5ff904cd
JL
13590}
13591
13592#endif
c7e4ee3a
CB
13593/* Return an expression that is usable as an arg in a conditional context
13594 (IF, DO WHILE, .NOT., and so on).
13595
13596 Use the one provided for the back end as of >2.6.0. */
5ff904cd
JL
13597
13598#if FFECOM_targetCURRENT == FFECOM_targetGCC
a2977d2d 13599tree
c7e4ee3a 13600ffecom_truth_value (tree expr)
5ff904cd 13601{
c7e4ee3a 13602 return truthvalue_conversion (expr);
5ff904cd 13603}
c7e4ee3a 13604
5ff904cd 13605#endif
c7e4ee3a
CB
13606/* Return the inversion of a truth value (the inversion of what
13607 ffecom_truth_value builds).
5ff904cd 13608
c7e4ee3a
CB
13609 Apparently invert_truthvalue, which is properly in the back end, is
13610 enough for now, so just use it. */
5ff904cd
JL
13611
13612#if FFECOM_targetCURRENT == FFECOM_targetGCC
13613tree
c7e4ee3a 13614ffecom_truth_value_invert (tree expr)
5ff904cd 13615{
c7e4ee3a 13616 return invert_truthvalue (ffecom_truth_value (expr));
5ff904cd
JL
13617}
13618
13619#endif
5ff904cd 13620
c7e4ee3a
CB
13621/* Return the tree that is the type of the expression, as would be
13622 returned in TREE_TYPE(ffecom_expr(expr)), without otherwise
13623 transforming the expression, generating temporaries, etc. */
5ff904cd 13624
c7e4ee3a
CB
13625tree
13626ffecom_type_expr (ffebld expr)
13627{
13628 ffeinfoBasictype bt;
13629 ffeinfoKindtype kt;
13630 tree tree_type;
13631
13632 assert (expr != NULL);
13633
13634 bt = ffeinfo_basictype (ffebld_info (expr));
13635 kt = ffeinfo_kindtype (ffebld_info (expr));
13636 tree_type = ffecom_tree_type[bt][kt];
13637
13638 switch (ffebld_op (expr))
13639 {
13640 case FFEBLD_opCONTER:
13641 case FFEBLD_opSYMTER:
13642 case FFEBLD_opARRAYREF:
13643 case FFEBLD_opUPLUS:
13644 case FFEBLD_opPAREN:
13645 case FFEBLD_opUMINUS:
13646 case FFEBLD_opADD:
13647 case FFEBLD_opSUBTRACT:
13648 case FFEBLD_opMULTIPLY:
13649 case FFEBLD_opDIVIDE:
13650 case FFEBLD_opPOWER:
13651 case FFEBLD_opNOT:
13652 case FFEBLD_opFUNCREF:
13653 case FFEBLD_opSUBRREF:
13654 case FFEBLD_opAND:
13655 case FFEBLD_opOR:
13656 case FFEBLD_opXOR:
13657 case FFEBLD_opNEQV:
13658 case FFEBLD_opEQV:
13659 case FFEBLD_opCONVERT:
13660 case FFEBLD_opLT:
13661 case FFEBLD_opLE:
13662 case FFEBLD_opEQ:
13663 case FFEBLD_opNE:
13664 case FFEBLD_opGT:
13665 case FFEBLD_opGE:
13666 case FFEBLD_opPERCENT_LOC:
13667 return tree_type;
13668
13669 case FFEBLD_opACCTER:
13670 case FFEBLD_opARRTER:
13671 case FFEBLD_opITEM:
13672 case FFEBLD_opSTAR:
13673 case FFEBLD_opBOUNDS:
13674 case FFEBLD_opREPEAT:
13675 case FFEBLD_opLABTER:
13676 case FFEBLD_opLABTOK:
13677 case FFEBLD_opIMPDO:
13678 case FFEBLD_opCONCATENATE:
13679 case FFEBLD_opSUBSTR:
13680 default:
13681 assert ("bad op for ffecom_type_expr" == NULL);
13682 /* Fall through. */
13683 case FFEBLD_opANY:
13684 return error_mark_node;
13685 }
13686}
13687
13688/* Return PARM_DECL for arg#1 of master fn containing alternate ENTRY points
13689
13690 If the PARM_DECL already exists, return it, else create it. It's an
13691 integer_type_node argument for the master function that implements a
13692 subroutine or function with more than one entrypoint and is bound at
13693 run time with the entrypoint number (0 for SUBROUTINE/FUNCTION, 1 for
13694 first ENTRY statement, and so on). */
5ff904cd
JL
13695
13696#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
13697tree
13698ffecom_which_entrypoint_decl ()
5ff904cd 13699{
c7e4ee3a
CB
13700 assert (ffecom_which_entrypoint_decl_ != NULL_TREE);
13701
13702 return ffecom_which_entrypoint_decl_;
5ff904cd
JL
13703}
13704
13705#endif
c7e4ee3a
CB
13706\f
13707/* The following sections consists of private and public functions
13708 that have the same names and perform roughly the same functions
13709 as counterparts in the C front end. Changes in the C front end
13710 might affect how things should be done here. Only functions
13711 needed by the back end should be public here; the rest should
13712 be private (static in the C sense). Functions needed by other
13713 g77 front-end modules should be accessed by them via public
13714 ffecom_* names, which should themselves call private versions
13715 in this section so the private versions are easy to recognize
13716 when upgrading to a new gcc and finding interesting changes
13717 in the front end.
5ff904cd 13718
c7e4ee3a
CB
13719 Functions named after rule "foo:" in c-parse.y are named
13720 "bison_rule_foo_" so they are easy to find. */
5ff904cd 13721
c7e4ee3a 13722#if FFECOM_targetCURRENT == FFECOM_targetGCC
5ff904cd 13723
c7e4ee3a
CB
13724static void
13725bison_rule_pushlevel_ ()
13726{
13727 emit_line_note (input_filename, lineno);
13728 pushlevel (0);
13729 clear_last_expr ();
13730 push_momentary ();
13731 expand_start_bindings (0);
13732}
5ff904cd 13733
c7e4ee3a
CB
13734static tree
13735bison_rule_compstmt_ ()
5ff904cd 13736{
c7e4ee3a
CB
13737 tree t;
13738 int keep = kept_level_p ();
5ff904cd 13739
c7e4ee3a
CB
13740 /* Make the temps go away. */
13741 if (! keep)
13742 current_binding_level->names = NULL_TREE;
5ff904cd 13743
c7e4ee3a
CB
13744 emit_line_note (input_filename, lineno);
13745 expand_end_bindings (getdecls (), keep, 0);
13746 t = poplevel (keep, 1, 0);
13747 pop_momentary ();
5ff904cd 13748
c7e4ee3a
CB
13749 return t;
13750}
5ff904cd 13751
c7e4ee3a
CB
13752/* Return a definition for a builtin function named NAME and whose data type
13753 is TYPE. TYPE should be a function type with argument types.
13754 FUNCTION_CODE tells later passes how to compile calls to this function.
13755 See tree.h for its possible values.
5ff904cd 13756
c7e4ee3a
CB
13757 If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
13758 the name to be called if we can't opencode the function. */
5ff904cd 13759
c7e4ee3a
CB
13760static tree
13761builtin_function (const char *name, tree type,
13762 enum built_in_function function_code,
13763 const char *library_name)
13764{
13765 tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
13766 DECL_EXTERNAL (decl) = 1;
13767 TREE_PUBLIC (decl) = 1;
13768 if (library_name)
13769 DECL_ASSEMBLER_NAME (decl) = get_identifier (library_name);
13770 make_decl_rtl (decl, NULL_PTR, 1);
13771 pushdecl (decl);
13772 if (function_code != NOT_BUILT_IN)
5ff904cd 13773 {
c7e4ee3a
CB
13774 DECL_BUILT_IN (decl) = 1;
13775 DECL_FUNCTION_CODE (decl) = function_code;
5ff904cd 13776 }
5ff904cd 13777
c7e4ee3a 13778 return decl;
5ff904cd
JL
13779}
13780
c7e4ee3a
CB
13781/* Handle when a new declaration NEWDECL
13782 has the same name as an old one OLDDECL
13783 in the same binding contour.
13784 Prints an error message if appropriate.
5ff904cd 13785
c7e4ee3a
CB
13786 If safely possible, alter OLDDECL to look like NEWDECL, and return 1.
13787 Otherwise, return 0. */
5ff904cd 13788
c7e4ee3a
CB
13789static int
13790duplicate_decls (tree newdecl, tree olddecl)
5ff904cd 13791{
c7e4ee3a
CB
13792 int types_match = 1;
13793 int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
13794 && DECL_INITIAL (newdecl) != 0);
13795 tree oldtype = TREE_TYPE (olddecl);
13796 tree newtype = TREE_TYPE (newdecl);
5ff904cd 13797
c7e4ee3a
CB
13798 if (olddecl == newdecl)
13799 return 1;
5ff904cd 13800
c7e4ee3a
CB
13801 if (TREE_CODE (newtype) == ERROR_MARK
13802 || TREE_CODE (oldtype) == ERROR_MARK)
13803 types_match = 0;
5ff904cd 13804
c7e4ee3a
CB
13805 /* New decl is completely inconsistent with the old one =>
13806 tell caller to replace the old one.
13807 This is always an error except in the case of shadowing a builtin. */
13808 if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
13809 return 0;
5ff904cd 13810
c7e4ee3a
CB
13811 /* For real parm decl following a forward decl,
13812 return 1 so old decl will be reused. */
13813 if (types_match && TREE_CODE (newdecl) == PARM_DECL
13814 && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
13815 return 1;
5ff904cd 13816
c7e4ee3a
CB
13817 /* The new declaration is the same kind of object as the old one.
13818 The declarations may partially match. Print warnings if they don't
13819 match enough. Ultimately, copy most of the information from the new
13820 decl to the old one, and keep using the old one. */
5ff904cd 13821
c7e4ee3a
CB
13822 if (TREE_CODE (olddecl) == FUNCTION_DECL
13823 && DECL_BUILT_IN (olddecl))
13824 {
13825 /* A function declaration for a built-in function. */
13826 if (!TREE_PUBLIC (newdecl))
13827 return 0;
13828 else if (!types_match)
13829 {
13830 /* Accept the return type of the new declaration if same modes. */
13831 tree oldreturntype = TREE_TYPE (TREE_TYPE (olddecl));
13832 tree newreturntype = TREE_TYPE (TREE_TYPE (newdecl));
5ff904cd 13833
c7e4ee3a
CB
13834 /* Make sure we put the new type in the same obstack as the old ones.
13835 If the old types are not both in the same obstack, use the
13836 permanent one. */
13837 if (TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (newtype))
13838 push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
13839 else
13840 {
13841 push_obstacks_nochange ();
13842 end_temporary_allocation ();
13843 }
5ff904cd 13844
c7e4ee3a
CB
13845 if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
13846 {
13847 /* Function types may be shared, so we can't just modify
13848 the return type of olddecl's function type. */
13849 tree newtype
13850 = build_function_type (newreturntype,
13851 TYPE_ARG_TYPES (TREE_TYPE (olddecl)));
5ff904cd 13852
c7e4ee3a
CB
13853 types_match = 1;
13854 if (types_match)
13855 TREE_TYPE (olddecl) = newtype;
13856 }
5ff904cd 13857
c7e4ee3a
CB
13858 pop_obstacks ();
13859 }
13860 if (!types_match)
13861 return 0;
13862 }
13863 else if (TREE_CODE (olddecl) == FUNCTION_DECL
13864 && DECL_SOURCE_LINE (olddecl) == 0)
5ff904cd 13865 {
c7e4ee3a
CB
13866 /* A function declaration for a predeclared function
13867 that isn't actually built in. */
13868 if (!TREE_PUBLIC (newdecl))
13869 return 0;
13870 else if (!types_match)
13871 {
13872 /* If the types don't match, preserve volatility indication.
13873 Later on, we will discard everything else about the
13874 default declaration. */
13875 TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
13876 }
13877 }
5ff904cd 13878
c7e4ee3a
CB
13879 /* Copy all the DECL_... slots specified in the new decl
13880 except for any that we copy here from the old type.
5ff904cd 13881
c7e4ee3a
CB
13882 Past this point, we don't change OLDTYPE and NEWTYPE
13883 even if we change the types of NEWDECL and OLDDECL. */
5ff904cd 13884
c7e4ee3a
CB
13885 if (types_match)
13886 {
13887 /* Make sure we put the new type in the same obstack as the old ones.
13888 If the old types are not both in the same obstack, use the permanent
13889 one. */
13890 if (TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (newtype))
13891 push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
13892 else
13893 {
13894 push_obstacks_nochange ();
13895 end_temporary_allocation ();
13896 }
5ff904cd 13897
c7e4ee3a
CB
13898 /* Merge the data types specified in the two decls. */
13899 if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
13900 TREE_TYPE (newdecl)
13901 = TREE_TYPE (olddecl)
13902 = TREE_TYPE (newdecl);
5ff904cd 13903
c7e4ee3a
CB
13904 /* Lay the type out, unless already done. */
13905 if (oldtype != TREE_TYPE (newdecl))
13906 {
13907 if (TREE_TYPE (newdecl) != error_mark_node)
13908 layout_type (TREE_TYPE (newdecl));
13909 if (TREE_CODE (newdecl) != FUNCTION_DECL
13910 && TREE_CODE (newdecl) != TYPE_DECL
13911 && TREE_CODE (newdecl) != CONST_DECL)
13912 layout_decl (newdecl, 0);
13913 }
13914 else
13915 {
13916 /* Since the type is OLDDECL's, make OLDDECL's size go with. */
13917 DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
13918 if (TREE_CODE (olddecl) != FUNCTION_DECL)
13919 if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
13920 DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
13921 }
5ff904cd 13922
c7e4ee3a
CB
13923 /* Keep the old rtl since we can safely use it. */
13924 DECL_RTL (newdecl) = DECL_RTL (olddecl);
5ff904cd 13925
c7e4ee3a
CB
13926 /* Merge the type qualifiers. */
13927 if (DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl)
13928 && !TREE_THIS_VOLATILE (newdecl))
13929 TREE_THIS_VOLATILE (olddecl) = 0;
13930 if (TREE_READONLY (newdecl))
13931 TREE_READONLY (olddecl) = 1;
13932 if (TREE_THIS_VOLATILE (newdecl))
13933 {
13934 TREE_THIS_VOLATILE (olddecl) = 1;
13935 if (TREE_CODE (newdecl) == VAR_DECL)
13936 make_var_volatile (newdecl);
13937 }
5ff904cd 13938
c7e4ee3a
CB
13939 /* Keep source location of definition rather than declaration.
13940 Likewise, keep decl at outer scope. */
13941 if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
13942 || (DECL_CONTEXT (newdecl) != 0 && DECL_CONTEXT (olddecl) == 0))
13943 {
13944 DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
13945 DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl);
5ff904cd 13946
c7e4ee3a
CB
13947 if (DECL_CONTEXT (olddecl) == 0
13948 && TREE_CODE (newdecl) != FUNCTION_DECL)
13949 DECL_CONTEXT (newdecl) = 0;
13950 }
5ff904cd 13951
c7e4ee3a
CB
13952 /* Merge the unused-warning information. */
13953 if (DECL_IN_SYSTEM_HEADER (olddecl))
13954 DECL_IN_SYSTEM_HEADER (newdecl) = 1;
13955 else if (DECL_IN_SYSTEM_HEADER (newdecl))
13956 DECL_IN_SYSTEM_HEADER (olddecl) = 1;
5ff904cd 13957
c7e4ee3a
CB
13958 /* Merge the initialization information. */
13959 if (DECL_INITIAL (newdecl) == 0)
13960 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
5ff904cd 13961
c7e4ee3a
CB
13962 /* Merge the section attribute.
13963 We want to issue an error if the sections conflict but that must be
13964 done later in decl_attributes since we are called before attributes
13965 are assigned. */
13966 if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
13967 DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
5ff904cd 13968
c7e4ee3a
CB
13969#if BUILT_FOR_270
13970 if (TREE_CODE (newdecl) == FUNCTION_DECL)
13971 {
13972 DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
13973 DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
13974 }
5ff904cd 13975#endif
5ff904cd 13976
c7e4ee3a
CB
13977 pop_obstacks ();
13978 }
13979 /* If cannot merge, then use the new type and qualifiers,
13980 and don't preserve the old rtl. */
13981 else
13982 {
13983 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
13984 TREE_READONLY (olddecl) = TREE_READONLY (newdecl);
13985 TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl);
13986 TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl);
13987 }
5ff904cd 13988
c7e4ee3a
CB
13989 /* Merge the storage class information. */
13990 /* For functions, static overrides non-static. */
13991 if (TREE_CODE (newdecl) == FUNCTION_DECL)
13992 {
13993 TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
13994 /* This is since we don't automatically
13995 copy the attributes of NEWDECL into OLDDECL. */
13996 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
13997 /* If this clears `static', clear it in the identifier too. */
13998 if (! TREE_PUBLIC (olddecl))
13999 TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
14000 }
14001 if (DECL_EXTERNAL (newdecl))
14002 {
14003 TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
14004 DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
14005 /* An extern decl does not override previous storage class. */
14006 TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
14007 }
14008 else
14009 {
14010 TREE_STATIC (olddecl) = TREE_STATIC (newdecl);
14011 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
14012 }
5ff904cd 14013
c7e4ee3a
CB
14014 /* If either decl says `inline', this fn is inline,
14015 unless its definition was passed already. */
14016 if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
14017 DECL_INLINE (olddecl) = 1;
14018 DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
5ff904cd 14019
c7e4ee3a
CB
14020 /* Get rid of any built-in function if new arg types don't match it
14021 or if we have a function definition. */
14022 if (TREE_CODE (newdecl) == FUNCTION_DECL
14023 && DECL_BUILT_IN (olddecl)
14024 && (!types_match || new_is_definition))
14025 {
14026 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
14027 DECL_BUILT_IN (olddecl) = 0;
14028 }
5ff904cd 14029
c7e4ee3a
CB
14030 /* If redeclaring a builtin function, and not a definition,
14031 it stays built in.
14032 Also preserve various other info from the definition. */
14033 if (TREE_CODE (newdecl) == FUNCTION_DECL && !new_is_definition)
14034 {
14035 if (DECL_BUILT_IN (olddecl))
14036 {
14037 DECL_BUILT_IN (newdecl) = 1;
14038 DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
14039 }
14040 else
14041 DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl);
5ff904cd 14042
c7e4ee3a
CB
14043 DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
14044 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
14045 DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
14046 DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
14047 }
5ff904cd 14048
c7e4ee3a
CB
14049 /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
14050 But preserve olddecl's DECL_UID. */
14051 {
14052 register unsigned olddecl_uid = DECL_UID (olddecl);
5ff904cd 14053
c7e4ee3a
CB
14054 memcpy ((char *) olddecl + sizeof (struct tree_common),
14055 (char *) newdecl + sizeof (struct tree_common),
14056 sizeof (struct tree_decl) - sizeof (struct tree_common));
14057 DECL_UID (olddecl) = olddecl_uid;
14058 }
5ff904cd 14059
c7e4ee3a 14060 return 1;
5ff904cd
JL
14061}
14062
c7e4ee3a
CB
14063/* Finish processing of a declaration;
14064 install its initial value.
14065 If the length of an array type is not known before,
14066 it must be determined now, from the initial value, or it is an error. */
14067
5ff904cd 14068static void
c7e4ee3a 14069finish_decl (tree decl, tree init, bool is_top_level)
5ff904cd 14070{
c7e4ee3a
CB
14071 register tree type = TREE_TYPE (decl);
14072 int was_incomplete = (DECL_SIZE (decl) == 0);
14073 int temporary = allocation_temporary_p ();
14074 bool at_top_level = (current_binding_level == global_binding_level);
14075 bool top_level = is_top_level || at_top_level;
5ff904cd 14076
c7e4ee3a
CB
14077 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
14078 level anyway. */
14079 assert (!is_top_level || !at_top_level);
5ff904cd 14080
c7e4ee3a
CB
14081 if (TREE_CODE (decl) == PARM_DECL)
14082 assert (init == NULL_TREE);
14083 /* Remember that PARM_DECL doesn't have a DECL_INITIAL field per se -- it
14084 overlaps DECL_ARG_TYPE. */
14085 else if (init == NULL_TREE)
14086 assert (DECL_INITIAL (decl) == NULL_TREE);
14087 else
14088 assert (DECL_INITIAL (decl) == error_mark_node);
5ff904cd 14089
c7e4ee3a 14090 if (init != NULL_TREE)
5ff904cd 14091 {
c7e4ee3a
CB
14092 if (TREE_CODE (decl) != TYPE_DECL)
14093 DECL_INITIAL (decl) = init;
14094 else
14095 {
14096 /* typedef foo = bar; store the type of bar as the type of foo. */
14097 TREE_TYPE (decl) = TREE_TYPE (init);
14098 DECL_INITIAL (decl) = init = 0;
14099 }
5ff904cd
JL
14100 }
14101
c7e4ee3a
CB
14102 /* Pop back to the obstack that is current for this binding level. This is
14103 because MAXINDEX, rtl, etc. to be made below must go in the permanent
14104 obstack. But don't discard the temporary data yet. */
14105 pop_obstacks ();
5ff904cd 14106
c7e4ee3a 14107 /* Deduce size of array from initialization, if not already known */
5ff904cd 14108
c7e4ee3a
CB
14109 if (TREE_CODE (type) == ARRAY_TYPE
14110 && TYPE_DOMAIN (type) == 0
14111 && TREE_CODE (decl) != TYPE_DECL)
14112 {
14113 assert (top_level);
14114 assert (was_incomplete);
5ff904cd 14115
c7e4ee3a
CB
14116 layout_decl (decl, 0);
14117 }
5ff904cd 14118
c7e4ee3a
CB
14119 if (TREE_CODE (decl) == VAR_DECL)
14120 {
14121 if (DECL_SIZE (decl) == NULL_TREE
14122 && TYPE_SIZE (TREE_TYPE (decl)) != NULL_TREE)
14123 layout_decl (decl, 0);
5ff904cd 14124
c7e4ee3a
CB
14125 if (DECL_SIZE (decl) == NULL_TREE
14126 && (TREE_STATIC (decl)
14127 ?
14128 /* A static variable with an incomplete type is an error if it is
14129 initialized. Also if it is not file scope. Otherwise, let it
14130 through, but if it is not `extern' then it may cause an error
14131 message later. */
14132 (DECL_INITIAL (decl) != 0 || DECL_CONTEXT (decl) != 0)
14133 :
14134 /* An automatic variable with an incomplete type is an error. */
14135 !DECL_EXTERNAL (decl)))
14136 {
14137 assert ("storage size not known" == NULL);
14138 abort ();
14139 }
5ff904cd 14140
c7e4ee3a
CB
14141 if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
14142 && (DECL_SIZE (decl) != 0)
14143 && (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST))
14144 {
14145 assert ("storage size not constant" == NULL);
14146 abort ();
14147 }
14148 }
5ff904cd 14149
c7e4ee3a
CB
14150 /* Output the assembler code and/or RTL code for variables and functions,
14151 unless the type is an undefined structure or union. If not, it will get
14152 done when the type is completed. */
5ff904cd 14153
c7e4ee3a 14154 if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
5ff904cd 14155 {
c7e4ee3a
CB
14156 rest_of_decl_compilation (decl, NULL,
14157 DECL_CONTEXT (decl) == 0,
14158 0);
5ff904cd 14159
c7e4ee3a
CB
14160 if (DECL_CONTEXT (decl) != 0)
14161 {
14162 /* Recompute the RTL of a local array now if it used to be an
14163 incomplete type. */
14164 if (was_incomplete
14165 && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
5ff904cd 14166 {
c7e4ee3a
CB
14167 /* If we used it already as memory, it must stay in memory. */
14168 TREE_ADDRESSABLE (decl) = TREE_USED (decl);
14169 /* If it's still incomplete now, no init will save it. */
14170 if (DECL_SIZE (decl) == 0)
14171 DECL_INITIAL (decl) = 0;
14172 expand_decl (decl);
5ff904cd 14173 }
c7e4ee3a
CB
14174 /* Compute and store the initial value. */
14175 if (TREE_CODE (decl) != FUNCTION_DECL)
14176 expand_decl_init (decl);
14177 }
14178 }
14179 else if (TREE_CODE (decl) == TYPE_DECL)
14180 {
14181 rest_of_decl_compilation (decl, NULL_PTR,
14182 DECL_CONTEXT (decl) == 0,
14183 0);
14184 }
5ff904cd 14185
c7e4ee3a
CB
14186 /* This test used to include TREE_PERMANENT, however, we have the same
14187 problem with initializers at the function level. Such initializers get
14188 saved until the end of the function on the momentary_obstack. */
14189 if (!(TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))
14190 && temporary
14191 /* DECL_INITIAL is not defined in PARM_DECLs, since it shares space with
14192 DECL_ARG_TYPE. */
14193 && TREE_CODE (decl) != PARM_DECL)
14194 {
14195 /* We need to remember that this array HAD an initialization, but
14196 discard the actual temporary nodes, since we can't have a permanent
14197 node keep pointing to them. */
14198 /* We make an exception for inline functions, since it's normal for a
14199 local extern redeclaration of an inline function to have a copy of
14200 the top-level decl's DECL_INLINE. */
14201 if ((DECL_INITIAL (decl) != 0)
14202 && (DECL_INITIAL (decl) != error_mark_node))
14203 {
14204 /* If this is a const variable, then preserve the
14205 initializer instead of discarding it so that we can optimize
14206 references to it. */
14207 /* This test used to include TREE_STATIC, but this won't be set
14208 for function level initializers. */
14209 if (TREE_READONLY (decl))
5ff904cd 14210 {
c7e4ee3a
CB
14211 preserve_initializer ();
14212 /* Hack? Set the permanent bit for something that is
14213 permanent, but not on the permenent obstack, so as to
14214 convince output_constant_def to make its rtl on the
14215 permanent obstack. */
14216 TREE_PERMANENT (DECL_INITIAL (decl)) = 1;
5ff904cd 14217
c7e4ee3a
CB
14218 /* The initializer and DECL must have the same (or equivalent
14219 types), but if the initializer is a STRING_CST, its type
14220 might not be on the right obstack, so copy the type
14221 of DECL. */
14222 TREE_TYPE (DECL_INITIAL (decl)) = type;
5ff904cd 14223 }
c7e4ee3a
CB
14224 else
14225 DECL_INITIAL (decl) = error_mark_node;
5ff904cd 14226 }
5ff904cd 14227 }
c7e4ee3a
CB
14228
14229 /* If requested, warn about definitions of large data objects. */
14230
14231 if (warn_larger_than
14232 && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
14233 && !DECL_EXTERNAL (decl))
5ff904cd 14234 {
c7e4ee3a
CB
14235 register tree decl_size = DECL_SIZE (decl);
14236
14237 if (decl_size && TREE_CODE (decl_size) == INTEGER_CST)
5ff904cd 14238 {
c7e4ee3a
CB
14239 unsigned units = TREE_INT_CST_LOW (decl_size) / BITS_PER_UNIT;
14240
14241 if (units > larger_than_size)
14242 warning_with_decl (decl, "size of `%s' is %u bytes", units);
5ff904cd
JL
14243 }
14244 }
14245
c7e4ee3a
CB
14246 /* If we have gone back from temporary to permanent allocation, actually
14247 free the temporary space that we no longer need. */
14248 if (temporary && !allocation_temporary_p ())
14249 permanent_allocation (0);
5ff904cd 14250
c7e4ee3a
CB
14251 /* At the end of a declaration, throw away any variable type sizes of types
14252 defined inside that declaration. There is no use computing them in the
14253 following function definition. */
14254 if (current_binding_level == global_binding_level)
14255 get_pending_sizes ();
14256}
5ff904cd 14257
c7e4ee3a
CB
14258/* Finish up a function declaration and compile that function
14259 all the way to assembler language output. The free the storage
14260 for the function definition.
5ff904cd 14261
c7e4ee3a 14262 This is called after parsing the body of the function definition.
5ff904cd 14263
c7e4ee3a
CB
14264 NESTED is nonzero if the function being finished is nested in another. */
14265
14266static void
14267finish_function (int nested)
14268{
14269 register tree fndecl = current_function_decl;
14270
14271 assert (fndecl != NULL_TREE);
14272 if (TREE_CODE (fndecl) != ERROR_MARK)
14273 {
14274 if (nested)
14275 assert (DECL_CONTEXT (fndecl) != NULL_TREE);
5ff904cd 14276 else
c7e4ee3a
CB
14277 assert (DECL_CONTEXT (fndecl) == NULL_TREE);
14278 }
5ff904cd 14279
c7e4ee3a
CB
14280/* TREE_READONLY (fndecl) = 1;
14281 This caused &foo to be of type ptr-to-const-function
14282 which then got a warning when stored in a ptr-to-function variable. */
5ff904cd 14283
c7e4ee3a 14284 poplevel (1, 0, 1);
5ff904cd 14285
c7e4ee3a
CB
14286 if (TREE_CODE (fndecl) != ERROR_MARK)
14287 {
14288 BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
5ff904cd 14289
c7e4ee3a 14290 /* Must mark the RESULT_DECL as being in this function. */
5ff904cd 14291
c7e4ee3a 14292 DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
5ff904cd 14293
c7e4ee3a
CB
14294 /* Obey `register' declarations if `setjmp' is called in this fn. */
14295 /* Generate rtl for function exit. */
14296 expand_function_end (input_filename, lineno, 0);
5ff904cd 14297
c7e4ee3a
CB
14298 /* So we can tell if jump_optimize sets it to 1. */
14299 can_reach_end = 0;
5ff904cd 14300
c7e4ee3a
CB
14301 /* Run the optimizers and output the assembler code for this function. */
14302 rest_of_compilation (fndecl);
14303 }
5ff904cd 14304
c7e4ee3a
CB
14305 /* Free all the tree nodes making up this function. */
14306 /* Switch back to allocating nodes permanently until we start another
14307 function. */
14308 if (!nested)
14309 permanent_allocation (1);
14310
14311 if (TREE_CODE (fndecl) != ERROR_MARK
14312 && !nested
14313 && DECL_SAVED_INSNS (fndecl) == 0)
14314 {
14315 /* Stop pointing to the local nodes about to be freed. */
14316 /* But DECL_INITIAL must remain nonzero so we know this was an actual
14317 function definition. */
14318 /* For a nested function, this is done in pop_f_function_context. */
14319 /* If rest_of_compilation set this to 0, leave it 0. */
14320 if (DECL_INITIAL (fndecl) != 0)
14321 DECL_INITIAL (fndecl) = error_mark_node;
14322 DECL_ARGUMENTS (fndecl) = 0;
5ff904cd 14323 }
c7e4ee3a
CB
14324
14325 if (!nested)
5ff904cd 14326 {
c7e4ee3a
CB
14327 /* Let the error reporting routines know that we're outside a function.
14328 For a nested function, this value is used in pop_c_function_context
14329 and then reset via pop_function_context. */
14330 ffecom_outer_function_decl_ = current_function_decl = NULL;
5ff904cd 14331 }
c7e4ee3a 14332}
5ff904cd 14333
c7e4ee3a
CB
14334/* Plug-in replacement for identifying the name of a decl and, for a
14335 function, what we call it in diagnostics. For now, "program unit"
14336 should suffice, since it's a bit of a hassle to figure out which
14337 of several kinds of things it is. Note that it could conceivably
14338 be a statement function, which probably isn't really a program unit
14339 per se, but if that comes up, it should be easy to check (being a
14340 nested function and all). */
14341
14342static char *
14343lang_printable_name (tree decl, int v)
14344{
14345 /* Just to keep GCC quiet about the unused variable.
14346 In theory, differing values of V should produce different
14347 output. */
14348 switch (v)
5ff904cd 14349 {
c7e4ee3a
CB
14350 default:
14351 if (TREE_CODE (decl) == ERROR_MARK)
14352 return "erroneous code";
14353 return IDENTIFIER_POINTER (DECL_NAME (decl));
5ff904cd 14354 }
c7e4ee3a
CB
14355}
14356
14357/* g77's function to print out name of current function that caused
14358 an error. */
14359
14360#if BUILT_FOR_270
14361void
14362lang_print_error_function (file)
14363 char *file;
14364{
14365 static ffeglobal last_g = NULL;
14366 static ffesymbol last_s = NULL;
14367 ffeglobal g;
14368 ffesymbol s;
14369 const char *kind;
14370
14371 if ((ffecom_primary_entry_ == NULL)
14372 || (ffesymbol_global (ffecom_primary_entry_) == NULL))
5ff904cd 14373 {
c7e4ee3a
CB
14374 g = NULL;
14375 s = NULL;
14376 kind = NULL;
5ff904cd
JL
14377 }
14378 else
14379 {
c7e4ee3a
CB
14380 g = ffesymbol_global (ffecom_primary_entry_);
14381 if (ffecom_nested_entry_ == NULL)
14382 {
14383 s = ffecom_primary_entry_;
14384 switch (ffesymbol_kind (s))
14385 {
14386 case FFEINFO_kindFUNCTION:
14387 kind = "function";
14388 break;
5ff904cd 14389
c7e4ee3a
CB
14390 case FFEINFO_kindSUBROUTINE:
14391 kind = "subroutine";
14392 break;
5ff904cd 14393
c7e4ee3a
CB
14394 case FFEINFO_kindPROGRAM:
14395 kind = "program";
14396 break;
14397
14398 case FFEINFO_kindBLOCKDATA:
14399 kind = "block-data";
14400 break;
14401
14402 default:
14403 kind = ffeinfo_kind_message (ffesymbol_kind (s));
14404 break;
14405 }
14406 }
14407 else
14408 {
14409 s = ffecom_nested_entry_;
14410 kind = "statement function";
14411 }
5ff904cd
JL
14412 }
14413
c7e4ee3a 14414 if ((last_g != g) || (last_s != s))
5ff904cd 14415 {
c7e4ee3a
CB
14416 if (file)
14417 fprintf (stderr, "%s: ", file);
14418
14419 if (s == NULL)
14420 fprintf (stderr, "Outside of any program unit:\n");
14421 else
5ff904cd 14422 {
c7e4ee3a
CB
14423 const char *name = ffesymbol_text (s);
14424
14425 fprintf (stderr, "In %s `%s':\n", kind, name);
5ff904cd 14426 }
5ff904cd 14427
c7e4ee3a
CB
14428 last_g = g;
14429 last_s = s;
5ff904cd 14430 }
c7e4ee3a
CB
14431}
14432#endif
5ff904cd 14433
c7e4ee3a 14434/* Similar to `lookup_name' but look only at current binding level. */
5ff904cd 14435
c7e4ee3a
CB
14436static tree
14437lookup_name_current_level (tree name)
14438{
14439 register tree t;
5ff904cd 14440
c7e4ee3a
CB
14441 if (current_binding_level == global_binding_level)
14442 return IDENTIFIER_GLOBAL_VALUE (name);
14443
14444 if (IDENTIFIER_LOCAL_VALUE (name) == 0)
14445 return 0;
14446
14447 for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
14448 if (DECL_NAME (t) == name)
14449 break;
14450
14451 return t;
5ff904cd
JL
14452}
14453
c7e4ee3a 14454/* Create a new `struct binding_level'. */
5ff904cd 14455
c7e4ee3a
CB
14456static struct binding_level *
14457make_binding_level ()
5ff904cd 14458{
c7e4ee3a
CB
14459 /* NOSTRICT */
14460 return (struct binding_level *) xmalloc (sizeof (struct binding_level));
14461}
5ff904cd 14462
c7e4ee3a
CB
14463/* Save and restore the variables in this file and elsewhere
14464 that keep track of the progress of compilation of the current function.
14465 Used for nested functions. */
5ff904cd 14466
c7e4ee3a
CB
14467struct f_function
14468{
14469 struct f_function *next;
14470 tree named_labels;
14471 tree shadowed_labels;
14472 struct binding_level *binding_level;
14473};
5ff904cd 14474
c7e4ee3a 14475struct f_function *f_function_chain;
5ff904cd 14476
c7e4ee3a 14477/* Restore the variables used during compilation of a C function. */
5ff904cd 14478
c7e4ee3a
CB
14479static void
14480pop_f_function_context ()
14481{
14482 struct f_function *p = f_function_chain;
14483 tree link;
5ff904cd 14484
c7e4ee3a
CB
14485 /* Bring back all the labels that were shadowed. */
14486 for (link = shadowed_labels; link; link = TREE_CHAIN (link))
14487 if (DECL_NAME (TREE_VALUE (link)) != 0)
14488 IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)))
14489 = TREE_VALUE (link);
5ff904cd 14490
c7e4ee3a
CB
14491 if (current_function_decl != error_mark_node
14492 && DECL_SAVED_INSNS (current_function_decl) == 0)
14493 {
14494 /* Stop pointing to the local nodes about to be freed. */
14495 /* But DECL_INITIAL must remain nonzero so we know this was an actual
14496 function definition. */
14497 DECL_INITIAL (current_function_decl) = error_mark_node;
14498 DECL_ARGUMENTS (current_function_decl) = 0;
5ff904cd
JL
14499 }
14500
c7e4ee3a 14501 pop_function_context ();
5ff904cd 14502
c7e4ee3a 14503 f_function_chain = p->next;
5ff904cd 14504
c7e4ee3a
CB
14505 named_labels = p->named_labels;
14506 shadowed_labels = p->shadowed_labels;
14507 current_binding_level = p->binding_level;
5ff904cd 14508
c7e4ee3a
CB
14509 free (p);
14510}
5ff904cd 14511
c7e4ee3a
CB
14512/* Save and reinitialize the variables
14513 used during compilation of a C function. */
5ff904cd 14514
c7e4ee3a
CB
14515static void
14516push_f_function_context ()
14517{
14518 struct f_function *p
14519 = (struct f_function *) xmalloc (sizeof (struct f_function));
5ff904cd 14520
c7e4ee3a
CB
14521 push_function_context ();
14522
14523 p->next = f_function_chain;
14524 f_function_chain = p;
14525
14526 p->named_labels = named_labels;
14527 p->shadowed_labels = shadowed_labels;
14528 p->binding_level = current_binding_level;
14529}
5ff904cd 14530
c7e4ee3a
CB
14531static void
14532push_parm_decl (tree parm)
14533{
14534 int old_immediate_size_expand = immediate_size_expand;
5ff904cd 14535
c7e4ee3a 14536 /* Don't try computing parm sizes now -- wait till fn is called. */
5ff904cd 14537
c7e4ee3a 14538 immediate_size_expand = 0;
5ff904cd 14539
c7e4ee3a 14540 push_obstacks_nochange ();
5ff904cd 14541
c7e4ee3a 14542 /* Fill in arg stuff. */
5ff904cd 14543
c7e4ee3a
CB
14544 DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
14545 DECL_ARG_TYPE_AS_WRITTEN (parm) = TREE_TYPE (parm);
14546 TREE_READONLY (parm) = 1; /* All implementation args are read-only. */
5ff904cd 14547
c7e4ee3a
CB
14548 parm = pushdecl (parm);
14549
14550 immediate_size_expand = old_immediate_size_expand;
14551
14552 finish_decl (parm, NULL_TREE, FALSE);
5ff904cd
JL
14553}
14554
c7e4ee3a 14555/* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, if appropriate. */
5ff904cd 14556
c7e4ee3a
CB
14557static tree
14558pushdecl_top_level (x)
14559 tree x;
14560{
14561 register tree t;
14562 register struct binding_level *b = current_binding_level;
14563 register tree f = current_function_decl;
5ff904cd 14564
c7e4ee3a
CB
14565 current_binding_level = global_binding_level;
14566 current_function_decl = NULL_TREE;
14567 t = pushdecl (x);
14568 current_binding_level = b;
14569 current_function_decl = f;
14570 return t;
14571}
14572
14573/* Store the list of declarations of the current level.
14574 This is done for the parameter declarations of a function being defined,
14575 after they are modified in the light of any missing parameters. */
14576
14577static tree
14578storedecls (decls)
14579 tree decls;
14580{
14581 return current_binding_level->names = decls;
14582}
14583
14584/* Store the parameter declarations into the current function declaration.
14585 This is called after parsing the parameter declarations, before
14586 digesting the body of the function.
14587
14588 For an old-style definition, modify the function's type
14589 to specify at least the number of arguments. */
5ff904cd
JL
14590
14591static void
c7e4ee3a 14592store_parm_decls (int is_main_program UNUSED)
5ff904cd
JL
14593{
14594 register tree fndecl = current_function_decl;
14595
c7e4ee3a
CB
14596 if (fndecl == error_mark_node)
14597 return;
5ff904cd 14598
c7e4ee3a
CB
14599 /* This is a chain of PARM_DECLs from old-style parm declarations. */
14600 DECL_ARGUMENTS (fndecl) = storedecls (nreverse (getdecls ()));
5ff904cd 14601
c7e4ee3a 14602 /* Initialize the RTL code for the function. */
5ff904cd 14603
c7e4ee3a 14604 init_function_start (fndecl, input_filename, lineno);
56a0044b 14605
c7e4ee3a 14606 /* Set up parameters and prepare for return, for the function. */
5ff904cd 14607
c7e4ee3a
CB
14608 expand_function_start (fndecl, 0);
14609}
5ff904cd 14610
c7e4ee3a
CB
14611static tree
14612start_decl (tree decl, bool is_top_level)
14613{
14614 register tree tem;
14615 bool at_top_level = (current_binding_level == global_binding_level);
14616 bool top_level = is_top_level || at_top_level;
5ff904cd 14617
c7e4ee3a
CB
14618 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
14619 level anyway. */
14620 assert (!is_top_level || !at_top_level);
5ff904cd 14621
c7e4ee3a
CB
14622 /* The corresponding pop_obstacks is in finish_decl. */
14623 push_obstacks_nochange ();
14624
14625 if (DECL_INITIAL (decl) != NULL_TREE)
14626 {
14627 assert (DECL_INITIAL (decl) == error_mark_node);
14628 assert (!DECL_EXTERNAL (decl));
56a0044b 14629 }
c7e4ee3a
CB
14630 else if (top_level)
14631 assert ((TREE_STATIC (decl) == 1) || DECL_EXTERNAL (decl) == 1);
5ff904cd 14632
c7e4ee3a
CB
14633 /* For Fortran, we by default put things in .common when possible. */
14634 DECL_COMMON (decl) = 1;
5ff904cd 14635
c7e4ee3a
CB
14636 /* Add this decl to the current binding level. TEM may equal DECL or it may
14637 be a previous decl of the same name. */
14638 if (is_top_level)
14639 tem = pushdecl_top_level (decl);
14640 else
14641 tem = pushdecl (decl);
14642
14643 /* For a local variable, define the RTL now. */
14644 if (!top_level
14645 /* But not if this is a duplicate decl and we preserved the rtl from the
14646 previous one (which may or may not happen). */
14647 && DECL_RTL (tem) == 0)
5ff904cd 14648 {
c7e4ee3a
CB
14649 if (TYPE_SIZE (TREE_TYPE (tem)) != 0)
14650 expand_decl (tem);
14651 else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
14652 && DECL_INITIAL (tem) != 0)
14653 expand_decl (tem);
5ff904cd
JL
14654 }
14655
c7e4ee3a 14656 if (DECL_INITIAL (tem) != NULL_TREE)
5ff904cd 14657 {
c7e4ee3a
CB
14658 /* When parsing and digesting the initializer, use temporary storage.
14659 Do this even if we will ignore the value. */
14660 if (at_top_level)
14661 temporary_allocation ();
5ff904cd 14662 }
c7e4ee3a
CB
14663
14664 return tem;
5ff904cd
JL
14665}
14666
c7e4ee3a
CB
14667/* Create the FUNCTION_DECL for a function definition.
14668 DECLSPECS and DECLARATOR are the parts of the declaration;
14669 they describe the function's name and the type it returns,
14670 but twisted together in a fashion that parallels the syntax of C.
5ff904cd 14671
c7e4ee3a
CB
14672 This function creates a binding context for the function body
14673 as well as setting up the FUNCTION_DECL in current_function_decl.
5ff904cd 14674
c7e4ee3a
CB
14675 Returns 1 on success. If the DECLARATOR is not suitable for a function
14676 (it defines a datum instead), we return 0, which tells
14677 yyparse to report a parse error.
5ff904cd 14678
c7e4ee3a
CB
14679 NESTED is nonzero for a function nested within another function. */
14680
14681static void
14682start_function (tree name, tree type, int nested, int public)
5ff904cd 14683{
c7e4ee3a
CB
14684 tree decl1;
14685 tree restype;
14686 int old_immediate_size_expand = immediate_size_expand;
5ff904cd 14687
c7e4ee3a
CB
14688 named_labels = 0;
14689 shadowed_labels = 0;
14690
14691 /* Don't expand any sizes in the return type of the function. */
14692 immediate_size_expand = 0;
14693
14694 if (nested)
5ff904cd 14695 {
c7e4ee3a
CB
14696 assert (!public);
14697 assert (current_function_decl != NULL_TREE);
14698 assert (DECL_CONTEXT (current_function_decl) == NULL_TREE);
14699 }
14700 else
14701 {
14702 assert (current_function_decl == NULL_TREE);
5ff904cd 14703 }
c7e4ee3a
CB
14704
14705 if (TREE_CODE (type) == ERROR_MARK)
14706 decl1 = current_function_decl = error_mark_node;
56a0044b 14707 else
5ff904cd 14708 {
c7e4ee3a
CB
14709 decl1 = build_decl (FUNCTION_DECL,
14710 name,
14711 type);
14712 TREE_PUBLIC (decl1) = public ? 1 : 0;
14713 if (nested)
14714 DECL_INLINE (decl1) = 1;
14715 TREE_STATIC (decl1) = 1;
14716 DECL_EXTERNAL (decl1) = 0;
5ff904cd 14717
c7e4ee3a 14718 announce_function (decl1);
5ff904cd 14719
c7e4ee3a
CB
14720 /* Make the init_value nonzero so pushdecl knows this is not tentative.
14721 error_mark_node is replaced below (in poplevel) with the BLOCK. */
14722 DECL_INITIAL (decl1) = error_mark_node;
5ff904cd 14723
c7e4ee3a
CB
14724 /* Record the decl so that the function name is defined. If we already have
14725 a decl for this name, and it is a FUNCTION_DECL, use the old decl. */
5ff904cd 14726
c7e4ee3a 14727 current_function_decl = pushdecl (decl1);
5ff904cd
JL
14728 }
14729
c7e4ee3a
CB
14730 if (!nested)
14731 ffecom_outer_function_decl_ = current_function_decl;
5ff904cd 14732
c7e4ee3a
CB
14733 pushlevel (0);
14734 current_binding_level->prep_state = 2;
5ff904cd 14735
c7e4ee3a
CB
14736 if (TREE_CODE (current_function_decl) != ERROR_MARK)
14737 {
14738 make_function_rtl (current_function_decl);
5ff904cd 14739
c7e4ee3a
CB
14740 restype = TREE_TYPE (TREE_TYPE (current_function_decl));
14741 DECL_RESULT (current_function_decl)
14742 = build_decl (RESULT_DECL, NULL_TREE, restype);
5ff904cd 14743 }
5ff904cd 14744
c7e4ee3a
CB
14745 if (!nested)
14746 /* Allocate further tree nodes temporarily during compilation of this
14747 function only. */
14748 temporary_allocation ();
5ff904cd 14749
c7e4ee3a
CB
14750 if (!nested && (TREE_CODE (current_function_decl) != ERROR_MARK))
14751 TREE_ADDRESSABLE (current_function_decl) = 1;
14752
14753 immediate_size_expand = old_immediate_size_expand;
14754}
14755\f
14756/* Here are the public functions the GNU back end needs. */
14757
14758tree
14759convert (type, expr)
14760 tree type, expr;
5ff904cd 14761{
c7e4ee3a
CB
14762 register tree e = expr;
14763 register enum tree_code code = TREE_CODE (type);
5ff904cd 14764
c7e4ee3a
CB
14765 if (type == TREE_TYPE (e)
14766 || TREE_CODE (e) == ERROR_MARK)
14767 return e;
14768 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
14769 return fold (build1 (NOP_EXPR, type, e));
14770 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
14771 || code == ERROR_MARK)
14772 return error_mark_node;
14773 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
14774 {
14775 assert ("void value not ignored as it ought to be" == NULL);
14776 return error_mark_node;
14777 }
14778 if (code == VOID_TYPE)
14779 return build1 (CONVERT_EXPR, type, e);
14780 if ((code != RECORD_TYPE)
14781 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
14782 e = ffecom_1 (REALPART_EXPR, TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e))),
14783 e);
14784 if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
14785 return fold (convert_to_integer (type, e));
14786 if (code == POINTER_TYPE)
14787 return fold (convert_to_pointer (type, e));
14788 if (code == REAL_TYPE)
14789 return fold (convert_to_real (type, e));
14790 if (code == COMPLEX_TYPE)
14791 return fold (convert_to_complex (type, e));
14792 if (code == RECORD_TYPE)
14793 return fold (ffecom_convert_to_complex_ (type, e));
5ff904cd 14794
c7e4ee3a
CB
14795 assert ("conversion to non-scalar type requested" == NULL);
14796 return error_mark_node;
14797}
5ff904cd 14798
c7e4ee3a
CB
14799/* integrate_decl_tree calls this function, but since we don't use the
14800 DECL_LANG_SPECIFIC field, this is a no-op. */
5ff904cd 14801
c7e4ee3a
CB
14802void
14803copy_lang_decl (node)
14804 tree node UNUSED;
14805{
5ff904cd
JL
14806}
14807
c7e4ee3a
CB
14808/* Return the list of declarations of the current level.
14809 Note that this list is in reverse order unless/until
14810 you nreverse it; and when you do nreverse it, you must
14811 store the result back using `storedecls' or you will lose. */
5ff904cd 14812
c7e4ee3a
CB
14813tree
14814getdecls ()
5ff904cd 14815{
c7e4ee3a 14816 return current_binding_level->names;
5ff904cd
JL
14817}
14818
c7e4ee3a 14819/* Nonzero if we are currently in the global binding level. */
5ff904cd 14820
c7e4ee3a
CB
14821int
14822global_bindings_p ()
5ff904cd 14823{
c7e4ee3a
CB
14824 return current_binding_level == global_binding_level;
14825}
5ff904cd 14826
c7e4ee3a
CB
14827/* Print an error message for invalid use of an incomplete type.
14828 VALUE is the expression that was used (or 0 if that isn't known)
14829 and TYPE is the type that was invalid. */
5ff904cd 14830
c7e4ee3a
CB
14831void
14832incomplete_type_error (value, type)
14833 tree value UNUSED;
14834 tree type;
14835{
14836 if (TREE_CODE (type) == ERROR_MARK)
14837 return;
5ff904cd 14838
c7e4ee3a
CB
14839 assert ("incomplete type?!?" == NULL);
14840}
14841
14842void
14843init_decl_processing ()
5ff904cd 14844{
c7e4ee3a
CB
14845 malloc_init ();
14846 ffe_init_0 ();
14847}
5ff904cd 14848
c7e4ee3a
CB
14849char *
14850init_parse (filename)
14851 char *filename;
14852{
14853#if BUILT_FOR_270
14854 extern void (*print_error_function) (char *);
14855#endif
5ff904cd 14856
c7e4ee3a
CB
14857 /* Open input file. */
14858 if (filename == 0 || !strcmp (filename, "-"))
5ff904cd 14859 {
c7e4ee3a
CB
14860 finput = stdin;
14861 filename = "stdin";
5ff904cd 14862 }
c7e4ee3a
CB
14863 else
14864 finput = fopen (filename, "r");
14865 if (finput == 0)
14866 pfatal_with_name (filename);
5ff904cd 14867
c7e4ee3a
CB
14868#ifdef IO_BUFFER_SIZE
14869 setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);
14870#endif
5ff904cd 14871
c7e4ee3a
CB
14872 /* Make identifier nodes long enough for the language-specific slots. */
14873 set_identifier_size (sizeof (struct lang_identifier));
14874 decl_printable_name = lang_printable_name;
14875#if BUILT_FOR_270
14876 print_error_function = lang_print_error_function;
14877#endif
5ff904cd 14878
c7e4ee3a
CB
14879 return filename;
14880}
5ff904cd 14881
c7e4ee3a
CB
14882void
14883finish_parse ()
14884{
14885 fclose (finput);
14886}
14887
14888/* Delete the node BLOCK from the current binding level.
14889 This is used for the block inside a stmt expr ({...})
14890 so that the block can be reinserted where appropriate. */
14891
14892static void
14893delete_block (block)
14894 tree block;
14895{
14896 tree t;
14897 if (current_binding_level->blocks == block)
14898 current_binding_level->blocks = TREE_CHAIN (block);
14899 for (t = current_binding_level->blocks; t;)
14900 {
14901 if (TREE_CHAIN (t) == block)
14902 TREE_CHAIN (t) = TREE_CHAIN (block);
14903 else
14904 t = TREE_CHAIN (t);
14905 }
14906 TREE_CHAIN (block) = NULL;
14907 /* Clear TREE_USED which is always set by poplevel.
14908 The flag is set again if insert_block is called. */
14909 TREE_USED (block) = 0;
14910}
14911
14912void
14913insert_block (block)
14914 tree block;
14915{
14916 TREE_USED (block) = 1;
14917 current_binding_level->blocks
14918 = chainon (current_binding_level->blocks, block);
14919}
14920
14921int
14922lang_decode_option (argc, argv)
14923 int argc;
14924 char **argv;
14925{
14926 return ffe_decode_option (argc, argv);
5ff904cd
JL
14927}
14928
c7e4ee3a 14929/* used by print-tree.c */
5ff904cd 14930
c7e4ee3a
CB
14931void
14932lang_print_xnode (file, node, indent)
14933 FILE *file UNUSED;
14934 tree node UNUSED;
14935 int indent UNUSED;
5ff904cd 14936{
c7e4ee3a 14937}
5ff904cd 14938
c7e4ee3a
CB
14939void
14940lang_finish ()
14941{
14942 ffe_terminate_0 ();
5ff904cd 14943
c7e4ee3a
CB
14944 if (ffe_is_ffedebug ())
14945 malloc_pool_display (malloc_pool_image ());
5ff904cd
JL
14946}
14947
c7e4ee3a
CB
14948char *
14949lang_identify ()
5ff904cd 14950{
c7e4ee3a
CB
14951 return "f77";
14952}
5ff904cd 14953
c7e4ee3a
CB
14954void
14955lang_init_options ()
14956{
14957 /* Set default options for Fortran. */
14958 flag_move_all_movables = 1;
14959 flag_reduce_all_givs = 1;
14960 flag_argument_noalias = 2;
41af162c 14961 flag_errno_math = 0;
c7e4ee3a 14962}
5ff904cd 14963
c7e4ee3a
CB
14964void
14965lang_init ()
14966{
14967 /* If the file is output from cpp, it should contain a first line
14968 `# 1 "real-filename"', and the current design of gcc (toplev.c
14969 in particular and the way it sets up information relied on by
14970 INCLUDE) requires that we read this now, and store the
14971 "real-filename" info in master_input_filename. Ask the lexer
14972 to try doing this. */
14973 ffelex_hash_kludge (finput);
14974}
5ff904cd 14975
c7e4ee3a
CB
14976int
14977mark_addressable (exp)
14978 tree exp;
14979{
14980 register tree x = exp;
14981 while (1)
14982 switch (TREE_CODE (x))
14983 {
14984 case ADDR_EXPR:
14985 case COMPONENT_REF:
14986 case ARRAY_REF:
14987 x = TREE_OPERAND (x, 0);
14988 break;
5ff904cd 14989
c7e4ee3a
CB
14990 case CONSTRUCTOR:
14991 TREE_ADDRESSABLE (x) = 1;
14992 return 1;
5ff904cd 14993
c7e4ee3a
CB
14994 case VAR_DECL:
14995 case CONST_DECL:
14996 case PARM_DECL:
14997 case RESULT_DECL:
14998 if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)
14999 && DECL_NONLOCAL (x))
15000 {
15001 if (TREE_PUBLIC (x))
15002 {
15003 assert ("address of global register var requested" == NULL);
15004 return 0;
15005 }
15006 assert ("address of register variable requested" == NULL);
15007 }
15008 else if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x))
15009 {
15010 if (TREE_PUBLIC (x))
15011 {
15012 assert ("address of global register var requested" == NULL);
15013 return 0;
15014 }
15015 assert ("address of register var requested" == NULL);
15016 }
15017 put_var_into_stack (x);
5ff904cd 15018
c7e4ee3a
CB
15019 /* drops in */
15020 case FUNCTION_DECL:
15021 TREE_ADDRESSABLE (x) = 1;
15022#if 0 /* poplevel deals with this now. */
15023 if (DECL_CONTEXT (x) == 0)
15024 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
15025#endif
5ff904cd 15026
c7e4ee3a
CB
15027 default:
15028 return 1;
15029 }
5ff904cd
JL
15030}
15031
c7e4ee3a
CB
15032/* If DECL has a cleanup, build and return that cleanup here.
15033 This is a callback called by expand_expr. */
5ff904cd 15034
c7e4ee3a
CB
15035tree
15036maybe_build_cleanup (decl)
15037 tree decl UNUSED;
5ff904cd 15038{
c7e4ee3a
CB
15039 /* There are no cleanups in Fortran. */
15040 return NULL_TREE;
5ff904cd
JL
15041}
15042
c7e4ee3a
CB
15043/* Exit a binding level.
15044 Pop the level off, and restore the state of the identifier-decl mappings
15045 that were in effect when this level was entered.
5ff904cd 15046
c7e4ee3a
CB
15047 If KEEP is nonzero, this level had explicit declarations, so
15048 and create a "block" (a BLOCK node) for the level
15049 to record its declarations and subblocks for symbol table output.
5ff904cd 15050
c7e4ee3a
CB
15051 If FUNCTIONBODY is nonzero, this level is the body of a function,
15052 so create a block as if KEEP were set and also clear out all
15053 label names.
5ff904cd 15054
c7e4ee3a
CB
15055 If REVERSE is nonzero, reverse the order of decls before putting
15056 them into the BLOCK. */
5ff904cd 15057
c7e4ee3a
CB
15058tree
15059poplevel (keep, reverse, functionbody)
15060 int keep;
15061 int reverse;
15062 int functionbody;
5ff904cd 15063{
c7e4ee3a
CB
15064 register tree link;
15065 /* The chain of decls was accumulated in reverse order.
15066 Put it into forward order, just for cleanliness. */
15067 tree decls;
15068 tree subblocks = current_binding_level->blocks;
15069 tree block = 0;
15070 tree decl;
15071 int block_previously_created;
5ff904cd 15072
c7e4ee3a
CB
15073 /* Get the decls in the order they were written.
15074 Usually current_binding_level->names is in reverse order.
15075 But parameter decls were previously put in forward order. */
702edf1d 15076
c7e4ee3a
CB
15077 if (reverse)
15078 current_binding_level->names
15079 = decls = nreverse (current_binding_level->names);
15080 else
15081 decls = current_binding_level->names;
5ff904cd 15082
c7e4ee3a
CB
15083 /* Output any nested inline functions within this block
15084 if they weren't already output. */
5ff904cd 15085
c7e4ee3a
CB
15086 for (decl = decls; decl; decl = TREE_CHAIN (decl))
15087 if (TREE_CODE (decl) == FUNCTION_DECL
15088 && ! TREE_ASM_WRITTEN (decl)
15089 && DECL_INITIAL (decl) != 0
15090 && TREE_ADDRESSABLE (decl))
15091 {
15092 /* If this decl was copied from a file-scope decl
15093 on account of a block-scope extern decl,
15094 propagate TREE_ADDRESSABLE to the file-scope decl.
15095
15096 DECL_ABSTRACT_ORIGIN can be set to itself if warn_return_type is
15097 true, since then the decl goes through save_for_inline_copying. */
15098 if (DECL_ABSTRACT_ORIGIN (decl) != 0
15099 && DECL_ABSTRACT_ORIGIN (decl) != decl)
15100 TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
15101 else if (DECL_SAVED_INSNS (decl) != 0)
15102 {
15103 push_function_context ();
15104 output_inline_function (decl);
15105 pop_function_context ();
15106 }
15107 }
5ff904cd 15108
c7e4ee3a
CB
15109 /* If there were any declarations or structure tags in that level,
15110 or if this level is a function body,
15111 create a BLOCK to record them for the life of this function. */
5ff904cd 15112
c7e4ee3a
CB
15113 block = 0;
15114 block_previously_created = (current_binding_level->this_block != 0);
15115 if (block_previously_created)
15116 block = current_binding_level->this_block;
15117 else if (keep || functionbody)
15118 block = make_node (BLOCK);
15119 if (block != 0)
15120 {
15121 BLOCK_VARS (block) = decls;
15122 BLOCK_SUBBLOCKS (block) = subblocks;
15123 remember_end_note (block);
15124 }
5ff904cd 15125
c7e4ee3a 15126 /* In each subblock, record that this is its superior. */
5ff904cd 15127
c7e4ee3a
CB
15128 for (link = subblocks; link; link = TREE_CHAIN (link))
15129 BLOCK_SUPERCONTEXT (link) = block;
5ff904cd 15130
c7e4ee3a 15131 /* Clear out the meanings of the local variables of this level. */
5ff904cd 15132
c7e4ee3a 15133 for (link = decls; link; link = TREE_CHAIN (link))
5ff904cd 15134 {
c7e4ee3a
CB
15135 if (DECL_NAME (link) != 0)
15136 {
15137 /* If the ident. was used or addressed via a local extern decl,
15138 don't forget that fact. */
15139 if (DECL_EXTERNAL (link))
15140 {
15141 if (TREE_USED (link))
15142 TREE_USED (DECL_NAME (link)) = 1;
15143 if (TREE_ADDRESSABLE (link))
15144 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
15145 }
15146 IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0;
15147 }
5ff904cd 15148 }
5ff904cd 15149
c7e4ee3a
CB
15150 /* If the level being exited is the top level of a function,
15151 check over all the labels, and clear out the current
15152 (function local) meanings of their names. */
5ff904cd 15153
c7e4ee3a 15154 if (functionbody)
5ff904cd 15155 {
c7e4ee3a
CB
15156 /* If this is the top level block of a function,
15157 the vars are the function's parameters.
15158 Don't leave them in the BLOCK because they are
15159 found in the FUNCTION_DECL instead. */
15160
15161 BLOCK_VARS (block) = 0;
5ff904cd
JL
15162 }
15163
c7e4ee3a
CB
15164 /* Pop the current level, and free the structure for reuse. */
15165
15166 {
15167 register struct binding_level *level = current_binding_level;
15168 current_binding_level = current_binding_level->level_chain;
15169
15170 level->level_chain = free_binding_level;
15171 free_binding_level = level;
15172 }
15173
15174 /* Dispose of the block that we just made inside some higher level. */
15175 if (functionbody
15176 && current_function_decl != error_mark_node)
15177 DECL_INITIAL (current_function_decl) = block;
15178 else if (block)
5ff904cd 15179 {
c7e4ee3a
CB
15180 if (!block_previously_created)
15181 current_binding_level->blocks
15182 = chainon (current_binding_level->blocks, block);
5ff904cd 15183 }
c7e4ee3a
CB
15184 /* If we did not make a block for the level just exited,
15185 any blocks made for inner levels
15186 (since they cannot be recorded as subblocks in that level)
15187 must be carried forward so they will later become subblocks
15188 of something else. */
15189 else if (subblocks)
15190 current_binding_level->blocks
15191 = chainon (current_binding_level->blocks, subblocks);
5ff904cd 15192
c7e4ee3a
CB
15193 if (block)
15194 TREE_USED (block) = 1;
15195 return block;
5ff904cd
JL
15196}
15197
c7e4ee3a
CB
15198void
15199print_lang_decl (file, node, indent)
15200 FILE *file UNUSED;
15201 tree node UNUSED;
15202 int indent UNUSED;
15203{
15204}
5ff904cd 15205
c7e4ee3a
CB
15206void
15207print_lang_identifier (file, node, indent)
15208 FILE *file;
15209 tree node;
15210 int indent;
15211{
15212 print_node (file, "global", IDENTIFIER_GLOBAL_VALUE (node), indent + 4);
15213 print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4);
15214}
5ff904cd 15215
c7e4ee3a
CB
15216void
15217print_lang_statistics ()
15218{
15219}
5ff904cd 15220
c7e4ee3a
CB
15221void
15222print_lang_type (file, node, indent)
15223 FILE *file UNUSED;
15224 tree node UNUSED;
15225 int indent UNUSED;
5ff904cd 15226{
c7e4ee3a 15227}
5ff904cd 15228
c7e4ee3a
CB
15229/* Record a decl-node X as belonging to the current lexical scope.
15230 Check for errors (such as an incompatible declaration for the same
15231 name already seen in the same scope).
5ff904cd 15232
c7e4ee3a
CB
15233 Returns either X or an old decl for the same name.
15234 If an old decl is returned, it may have been smashed
15235 to agree with what X says. */
5ff904cd 15236
c7e4ee3a
CB
15237tree
15238pushdecl (x)
15239 tree x;
15240{
15241 register tree t;
15242 register tree name = DECL_NAME (x);
15243 register struct binding_level *b = current_binding_level;
5ff904cd 15244
c7e4ee3a
CB
15245 if ((TREE_CODE (x) == FUNCTION_DECL)
15246 && (DECL_INITIAL (x) == 0)
15247 && DECL_EXTERNAL (x))
15248 DECL_CONTEXT (x) = NULL_TREE;
56a0044b 15249 else
c7e4ee3a
CB
15250 DECL_CONTEXT (x) = current_function_decl;
15251
15252 if (name)
56a0044b 15253 {
c7e4ee3a
CB
15254 if (IDENTIFIER_INVENTED (name))
15255 {
15256#if BUILT_FOR_270
15257 DECL_ARTIFICIAL (x) = 1;
15258#endif
15259 DECL_IN_SYSTEM_HEADER (x) = 1;
15260 }
5ff904cd 15261
c7e4ee3a 15262 t = lookup_name_current_level (name);
5ff904cd 15263
c7e4ee3a 15264 assert ((t == NULL_TREE) || (DECL_CONTEXT (x) == NULL_TREE));
5ff904cd 15265
c7e4ee3a
CB
15266 /* Don't push non-parms onto list for parms until we understand
15267 why we're doing this and whether it works. */
56a0044b 15268
c7e4ee3a
CB
15269 assert ((b == global_binding_level)
15270 || !ffecom_transform_only_dummies_
15271 || TREE_CODE (x) == PARM_DECL);
5ff904cd 15272
c7e4ee3a
CB
15273 if ((t != NULL_TREE) && duplicate_decls (x, t))
15274 return t;
5ff904cd 15275
c7e4ee3a
CB
15276 /* If we are processing a typedef statement, generate a whole new
15277 ..._TYPE node (which will be just an variant of the existing
15278 ..._TYPE node with identical properties) and then install the
15279 TYPE_DECL node generated to represent the typedef name as the
15280 TYPE_NAME of this brand new (duplicate) ..._TYPE node.
5ff904cd 15281
c7e4ee3a
CB
15282 The whole point here is to end up with a situation where each and every
15283 ..._TYPE node the compiler creates will be uniquely associated with
15284 AT MOST one node representing a typedef name. This way, even though
15285 the compiler substitutes corresponding ..._TYPE nodes for TYPE_DECL
15286 (i.e. "typedef name") nodes very early on, later parts of the
15287 compiler can always do the reverse translation and get back the
15288 corresponding typedef name. For example, given:
5ff904cd 15289
c7e4ee3a 15290 typedef struct S MY_TYPE; MY_TYPE object;
5ff904cd 15291
c7e4ee3a
CB
15292 Later parts of the compiler might only know that `object' was of type
15293 `struct S' if it were not for code just below. With this code
15294 however, later parts of the compiler see something like:
5ff904cd 15295
c7e4ee3a 15296 struct S' == struct S typedef struct S' MY_TYPE; struct S' object;
5ff904cd 15297
c7e4ee3a
CB
15298 And they can then deduce (from the node for type struct S') that the
15299 original object declaration was:
5ff904cd 15300
c7e4ee3a 15301 MY_TYPE object;
5ff904cd 15302
c7e4ee3a
CB
15303 Being able to do this is important for proper support of protoize, and
15304 also for generating precise symbolic debugging information which
15305 takes full account of the programmer's (typedef) vocabulary.
5ff904cd 15306
c7e4ee3a
CB
15307 Obviously, we don't want to generate a duplicate ..._TYPE node if the
15308 TYPE_DECL node that we are now processing really represents a
15309 standard built-in type.
5ff904cd 15310
c7e4ee3a
CB
15311 Since all standard types are effectively declared at line zero in the
15312 source file, we can easily check to see if we are working on a
15313 standard type by checking the current value of lineno. */
15314
15315 if (TREE_CODE (x) == TYPE_DECL)
15316 {
15317 if (DECL_SOURCE_LINE (x) == 0)
15318 {
15319 if (TYPE_NAME (TREE_TYPE (x)) == 0)
15320 TYPE_NAME (TREE_TYPE (x)) = x;
15321 }
15322 else if (TREE_TYPE (x) != error_mark_node)
15323 {
15324 tree tt = TREE_TYPE (x);
15325
15326 tt = build_type_copy (tt);
15327 TYPE_NAME (tt) = x;
15328 TREE_TYPE (x) = tt;
15329 }
15330 }
5ff904cd 15331
c7e4ee3a
CB
15332 /* This name is new in its binding level. Install the new declaration
15333 and return it. */
15334 if (b == global_binding_level)
15335 IDENTIFIER_GLOBAL_VALUE (name) = x;
15336 else
15337 IDENTIFIER_LOCAL_VALUE (name) = x;
15338 }
5ff904cd 15339
c7e4ee3a
CB
15340 /* Put decls on list in reverse order. We will reverse them later if
15341 necessary. */
15342 TREE_CHAIN (x) = b->names;
15343 b->names = x;
5ff904cd 15344
c7e4ee3a 15345 return x;
5ff904cd
JL
15346}
15347
c7e4ee3a 15348/* Nonzero if the current level needs to have a BLOCK made. */
5ff904cd 15349
c7e4ee3a
CB
15350static int
15351kept_level_p ()
5ff904cd 15352{
c7e4ee3a
CB
15353 tree decl;
15354
15355 for (decl = current_binding_level->names;
15356 decl;
15357 decl = TREE_CHAIN (decl))
15358 {
15359 if (TREE_USED (decl) || TREE_CODE (decl) != VAR_DECL
15360 || (DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl)))
15361 /* Currently, there aren't supposed to be non-artificial names
15362 at other than the top block for a function -- they're
15363 believed to always be temps. But it's wise to check anyway. */
15364 return 1;
15365 }
15366 return 0;
5ff904cd
JL
15367}
15368
c7e4ee3a
CB
15369/* Enter a new binding level.
15370 If TAG_TRANSPARENT is nonzero, do so only for the name space of variables,
15371 not for that of tags. */
5ff904cd
JL
15372
15373void
c7e4ee3a
CB
15374pushlevel (tag_transparent)
15375 int tag_transparent;
5ff904cd 15376{
c7e4ee3a 15377 register struct binding_level *newlevel = NULL_BINDING_LEVEL;
5ff904cd 15378
c7e4ee3a 15379 assert (! tag_transparent);
5ff904cd 15380
c7e4ee3a
CB
15381 if (current_binding_level == global_binding_level)
15382 {
15383 named_labels = 0;
15384 }
5ff904cd 15385
c7e4ee3a 15386 /* Reuse or create a struct for this binding level. */
5ff904cd 15387
c7e4ee3a 15388 if (free_binding_level)
77f77701 15389 {
c7e4ee3a
CB
15390 newlevel = free_binding_level;
15391 free_binding_level = free_binding_level->level_chain;
77f77701
DB
15392 }
15393 else
c7e4ee3a
CB
15394 {
15395 newlevel = make_binding_level ();
15396 }
77f77701 15397
c7e4ee3a
CB
15398 /* Add this level to the front of the chain (stack) of levels that
15399 are active. */
71b5e532 15400
c7e4ee3a
CB
15401 *newlevel = clear_binding_level;
15402 newlevel->level_chain = current_binding_level;
15403 current_binding_level = newlevel;
5ff904cd
JL
15404}
15405
c7e4ee3a
CB
15406/* Set the BLOCK node for the innermost scope
15407 (the one we are currently in). */
77f77701 15408
5ff904cd 15409void
c7e4ee3a
CB
15410set_block (block)
15411 register tree block;
5ff904cd 15412{
c7e4ee3a 15413 current_binding_level->this_block = block;
5ff904cd
JL
15414}
15415
c7e4ee3a 15416/* ~~gcc/tree.h *should* declare this, because toplev.c references it. */
5ff904cd 15417
c7e4ee3a 15418/* Can't 'yydebug' a front end not generated by yacc/bison! */
bc289659
ML
15419
15420void
c7e4ee3a
CB
15421set_yydebug (value)
15422 int value;
bc289659 15423{
c7e4ee3a
CB
15424 if (value)
15425 fprintf (stderr, "warning: no yacc/bison-generated output to debug!\n");
bc289659
ML
15426}
15427
c7e4ee3a
CB
15428tree
15429signed_or_unsigned_type (unsignedp, type)
15430 int unsignedp;
15431 tree type;
5ff904cd 15432{
c7e4ee3a 15433 tree type2;
5ff904cd 15434
c7e4ee3a
CB
15435 if (! INTEGRAL_TYPE_P (type))
15436 return type;
15437 if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
15438 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15439 if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
15440 return unsignedp ? unsigned_type_node : integer_type_node;
15441 if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node))
15442 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15443 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node))
15444 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15445 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node))
15446 return (unsignedp ? long_long_unsigned_type_node
15447 : long_long_integer_type_node);
5ff904cd 15448
c7e4ee3a
CB
15449 type2 = type_for_size (TYPE_PRECISION (type), unsignedp);
15450 if (type2 == NULL_TREE)
15451 return type;
f84639ba 15452
c7e4ee3a 15453 return type2;
5ff904cd
JL
15454}
15455
c7e4ee3a
CB
15456tree
15457signed_type (type)
15458 tree type;
5ff904cd 15459{
c7e4ee3a
CB
15460 tree type1 = TYPE_MAIN_VARIANT (type);
15461 ffeinfoKindtype kt;
15462 tree type2;
5ff904cd 15463
c7e4ee3a
CB
15464 if (type1 == unsigned_char_type_node || type1 == char_type_node)
15465 return signed_char_type_node;
15466 if (type1 == unsigned_type_node)
15467 return integer_type_node;
15468 if (type1 == short_unsigned_type_node)
15469 return short_integer_type_node;
15470 if (type1 == long_unsigned_type_node)
15471 return long_integer_type_node;
15472 if (type1 == long_long_unsigned_type_node)
15473 return long_long_integer_type_node;
15474#if 0 /* gcc/c-* files only */
15475 if (type1 == unsigned_intDI_type_node)
15476 return intDI_type_node;
15477 if (type1 == unsigned_intSI_type_node)
15478 return intSI_type_node;
15479 if (type1 == unsigned_intHI_type_node)
15480 return intHI_type_node;
15481 if (type1 == unsigned_intQI_type_node)
15482 return intQI_type_node;
15483#endif
5ff904cd 15484
c7e4ee3a
CB
15485 type2 = type_for_size (TYPE_PRECISION (type1), 0);
15486 if (type2 != NULL_TREE)
15487 return type2;
5ff904cd 15488
c7e4ee3a
CB
15489 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15490 {
15491 type2 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
5ff904cd 15492
c7e4ee3a
CB
15493 if (type1 == type2)
15494 return ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15495 }
15496
15497 return type;
5ff904cd
JL
15498}
15499
c7e4ee3a
CB
15500/* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
15501 or validate its data type for an `if' or `while' statement or ?..: exp.
15502
15503 This preparation consists of taking the ordinary
15504 representation of an expression expr and producing a valid tree
15505 boolean expression describing whether expr is nonzero. We could
15506 simply always do build_binary_op (NE_EXPR, expr, integer_zero_node, 1),
15507 but we optimize comparisons, &&, ||, and !.
15508
15509 The resulting type should always be `integer_type_node'. */
5ff904cd
JL
15510
15511tree
c7e4ee3a
CB
15512truthvalue_conversion (expr)
15513 tree expr;
5ff904cd 15514{
c7e4ee3a
CB
15515 if (TREE_CODE (expr) == ERROR_MARK)
15516 return expr;
5ff904cd 15517
c7e4ee3a
CB
15518#if 0 /* This appears to be wrong for C++. */
15519 /* These really should return error_mark_node after 2.4 is stable.
15520 But not all callers handle ERROR_MARK properly. */
15521 switch (TREE_CODE (TREE_TYPE (expr)))
15522 {
15523 case RECORD_TYPE:
15524 error ("struct type value used where scalar is required");
15525 return integer_zero_node;
5ff904cd 15526
c7e4ee3a
CB
15527 case UNION_TYPE:
15528 error ("union type value used where scalar is required");
15529 return integer_zero_node;
5ff904cd 15530
c7e4ee3a
CB
15531 case ARRAY_TYPE:
15532 error ("array type value used where scalar is required");
15533 return integer_zero_node;
5ff904cd 15534
c7e4ee3a
CB
15535 default:
15536 break;
15537 }
15538#endif /* 0 */
5ff904cd 15539
c7e4ee3a
CB
15540 switch (TREE_CODE (expr))
15541 {
15542 /* It is simpler and generates better code to have only TRUTH_*_EXPR
15543 or comparison expressions as truth values at this level. */
15544#if 0
15545 case COMPONENT_REF:
15546 /* A one-bit unsigned bit-field is already acceptable. */
15547 if (1 == TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (expr, 1)))
15548 && TREE_UNSIGNED (TREE_OPERAND (expr, 1)))
15549 return expr;
15550 break;
15551#endif
15552
15553 case EQ_EXPR:
15554 /* It is simpler and generates better code to have only TRUTH_*_EXPR
15555 or comparison expressions as truth values at this level. */
15556#if 0
15557 if (integer_zerop (TREE_OPERAND (expr, 1)))
15558 return build_unary_op (TRUTH_NOT_EXPR, TREE_OPERAND (expr, 0), 0);
15559#endif
15560 case NE_EXPR: case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
15561 case TRUTH_ANDIF_EXPR:
15562 case TRUTH_ORIF_EXPR:
15563 case TRUTH_AND_EXPR:
15564 case TRUTH_OR_EXPR:
15565 case TRUTH_XOR_EXPR:
15566 TREE_TYPE (expr) = integer_type_node;
15567 return expr;
5ff904cd 15568
c7e4ee3a
CB
15569 case ERROR_MARK:
15570 return expr;
5ff904cd 15571
c7e4ee3a
CB
15572 case INTEGER_CST:
15573 return integer_zerop (expr) ? integer_zero_node : integer_one_node;
5ff904cd 15574
c7e4ee3a
CB
15575 case REAL_CST:
15576 return real_zerop (expr) ? integer_zero_node : integer_one_node;
5ff904cd 15577
c7e4ee3a
CB
15578 case ADDR_EXPR:
15579 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0)))
15580 return build (COMPOUND_EXPR, integer_type_node,
15581 TREE_OPERAND (expr, 0), integer_one_node);
15582 else
15583 return integer_one_node;
5ff904cd 15584
c7e4ee3a
CB
15585 case COMPLEX_EXPR:
15586 return ffecom_2 ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
15587 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15588 integer_type_node,
15589 truthvalue_conversion (TREE_OPERAND (expr, 0)),
15590 truthvalue_conversion (TREE_OPERAND (expr, 1)));
5ff904cd 15591
c7e4ee3a
CB
15592 case NEGATE_EXPR:
15593 case ABS_EXPR:
15594 case FLOAT_EXPR:
15595 case FFS_EXPR:
15596 /* These don't change whether an object is non-zero or zero. */
15597 return truthvalue_conversion (TREE_OPERAND (expr, 0));
5ff904cd 15598
c7e4ee3a
CB
15599 case LROTATE_EXPR:
15600 case RROTATE_EXPR:
15601 /* These don't change whether an object is zero or non-zero, but
15602 we can't ignore them if their second arg has side-effects. */
15603 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
15604 return build (COMPOUND_EXPR, integer_type_node, TREE_OPERAND (expr, 1),
15605 truthvalue_conversion (TREE_OPERAND (expr, 0)));
15606 else
15607 return truthvalue_conversion (TREE_OPERAND (expr, 0));
5ff904cd 15608
c7e4ee3a
CB
15609 case COND_EXPR:
15610 /* Distribute the conversion into the arms of a COND_EXPR. */
15611 return fold (build (COND_EXPR, integer_type_node, TREE_OPERAND (expr, 0),
15612 truthvalue_conversion (TREE_OPERAND (expr, 1)),
15613 truthvalue_conversion (TREE_OPERAND (expr, 2))));
5ff904cd 15614
c7e4ee3a
CB
15615 case CONVERT_EXPR:
15616 /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
15617 since that affects how `default_conversion' will behave. */
15618 if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE
15619 || TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
15620 break;
15621 /* fall through... */
15622 case NOP_EXPR:
15623 /* If this is widening the argument, we can ignore it. */
15624 if (TYPE_PRECISION (TREE_TYPE (expr))
15625 >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
15626 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15627 break;
5ff904cd 15628
c7e4ee3a
CB
15629 case MINUS_EXPR:
15630 /* With IEEE arithmetic, x - x may not equal 0, so we can't optimize
15631 this case. */
15632 if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
15633 && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE)
15634 break;
15635 /* fall through... */
15636 case BIT_XOR_EXPR:
15637 /* This and MINUS_EXPR can be changed into a comparison of the
15638 two objects. */
15639 if (TREE_TYPE (TREE_OPERAND (expr, 0))
15640 == TREE_TYPE (TREE_OPERAND (expr, 1)))
15641 return ffecom_2 (NE_EXPR, integer_type_node,
15642 TREE_OPERAND (expr, 0),
15643 TREE_OPERAND (expr, 1));
15644 return ffecom_2 (NE_EXPR, integer_type_node,
15645 TREE_OPERAND (expr, 0),
15646 fold (build1 (NOP_EXPR,
15647 TREE_TYPE (TREE_OPERAND (expr, 0)),
15648 TREE_OPERAND (expr, 1))));
15649
15650 case BIT_AND_EXPR:
15651 if (integer_onep (TREE_OPERAND (expr, 1)))
15652 return expr;
15653 break;
15654
15655 case MODIFY_EXPR:
15656#if 0 /* No such thing in Fortran. */
15657 if (warn_parentheses && C_EXP_ORIGINAL_CODE (expr) == MODIFY_EXPR)
15658 warning ("suggest parentheses around assignment used as truth value");
15659#endif
15660 break;
15661
15662 default:
15663 break;
5ff904cd
JL
15664 }
15665
c7e4ee3a
CB
15666 if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
15667 return (ffecom_2
15668 ((TREE_SIDE_EFFECTS (expr)
15669 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15670 integer_type_node,
15671 truthvalue_conversion (ffecom_1 (REALPART_EXPR,
15672 TREE_TYPE (TREE_TYPE (expr)),
15673 expr)),
15674 truthvalue_conversion (ffecom_1 (IMAGPART_EXPR,
15675 TREE_TYPE (TREE_TYPE (expr)),
15676 expr))));
15677
15678 return ffecom_2 (NE_EXPR, integer_type_node,
15679 expr,
15680 convert (TREE_TYPE (expr), integer_zero_node));
15681}
15682
15683tree
15684type_for_mode (mode, unsignedp)
15685 enum machine_mode mode;
15686 int unsignedp;
15687{
15688 int i;
15689 int j;
15690 tree t;
5ff904cd 15691
c7e4ee3a
CB
15692 if (mode == TYPE_MODE (integer_type_node))
15693 return unsignedp ? unsigned_type_node : integer_type_node;
5ff904cd 15694
c7e4ee3a
CB
15695 if (mode == TYPE_MODE (signed_char_type_node))
15696 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
5ff904cd 15697
c7e4ee3a
CB
15698 if (mode == TYPE_MODE (short_integer_type_node))
15699 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
5ff904cd 15700
c7e4ee3a
CB
15701 if (mode == TYPE_MODE (long_integer_type_node))
15702 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
5ff904cd 15703
c7e4ee3a
CB
15704 if (mode == TYPE_MODE (long_long_integer_type_node))
15705 return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
5ff904cd 15706
c7e4ee3a
CB
15707 if (mode == TYPE_MODE (float_type_node))
15708 return float_type_node;
5ff904cd 15709
c7e4ee3a
CB
15710 if (mode == TYPE_MODE (double_type_node))
15711 return double_type_node;
5ff904cd 15712
c7e4ee3a
CB
15713 if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
15714 return build_pointer_type (char_type_node);
5ff904cd 15715
c7e4ee3a
CB
15716 if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
15717 return build_pointer_type (integer_type_node);
5ff904cd 15718
c7e4ee3a
CB
15719 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
15720 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
15721 {
15722 if (((t = ffecom_tree_type[i][j]) != NULL_TREE)
15723 && (mode == TYPE_MODE (t)))
15724 {
15725 if ((i == FFEINFO_basictypeINTEGER) && unsignedp)
15726 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][j];
15727 else
15728 return t;
15729 }
15730 }
5ff904cd 15731
c7e4ee3a 15732 return 0;
5ff904cd
JL
15733}
15734
c7e4ee3a
CB
15735tree
15736type_for_size (bits, unsignedp)
15737 unsigned bits;
15738 int unsignedp;
5ff904cd 15739{
c7e4ee3a
CB
15740 ffeinfoKindtype kt;
15741 tree type_node;
5ff904cd 15742
c7e4ee3a
CB
15743 if (bits == TYPE_PRECISION (integer_type_node))
15744 return unsignedp ? unsigned_type_node : integer_type_node;
5ff904cd 15745
c7e4ee3a
CB
15746 if (bits == TYPE_PRECISION (signed_char_type_node))
15747 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
5ff904cd 15748
c7e4ee3a
CB
15749 if (bits == TYPE_PRECISION (short_integer_type_node))
15750 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
5ff904cd 15751
c7e4ee3a
CB
15752 if (bits == TYPE_PRECISION (long_integer_type_node))
15753 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
5ff904cd 15754
c7e4ee3a
CB
15755 if (bits == TYPE_PRECISION (long_long_integer_type_node))
15756 return (unsignedp ? long_long_unsigned_type_node
15757 : long_long_integer_type_node);
5ff904cd 15758
c7e4ee3a 15759 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
5ff904cd 15760 {
c7e4ee3a 15761 type_node = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
5ff904cd 15762
c7e4ee3a
CB
15763 if ((type_node != NULL_TREE) && (bits == TYPE_PRECISION (type_node)))
15764 return unsignedp ? ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt]
15765 : type_node;
15766 }
5ff904cd 15767
c7e4ee3a
CB
15768 return 0;
15769}
5ff904cd 15770
c7e4ee3a
CB
15771tree
15772unsigned_type (type)
15773 tree type;
15774{
15775 tree type1 = TYPE_MAIN_VARIANT (type);
15776 ffeinfoKindtype kt;
15777 tree type2;
5ff904cd 15778
c7e4ee3a
CB
15779 if (type1 == signed_char_type_node || type1 == char_type_node)
15780 return unsigned_char_type_node;
15781 if (type1 == integer_type_node)
15782 return unsigned_type_node;
15783 if (type1 == short_integer_type_node)
15784 return short_unsigned_type_node;
15785 if (type1 == long_integer_type_node)
15786 return long_unsigned_type_node;
15787 if (type1 == long_long_integer_type_node)
15788 return long_long_unsigned_type_node;
15789#if 0 /* gcc/c-* files only */
15790 if (type1 == intDI_type_node)
15791 return unsigned_intDI_type_node;
15792 if (type1 == intSI_type_node)
15793 return unsigned_intSI_type_node;
15794 if (type1 == intHI_type_node)
15795 return unsigned_intHI_type_node;
15796 if (type1 == intQI_type_node)
15797 return unsigned_intQI_type_node;
15798#endif
5ff904cd 15799
c7e4ee3a
CB
15800 type2 = type_for_size (TYPE_PRECISION (type1), 1);
15801 if (type2 != NULL_TREE)
15802 return type2;
5ff904cd 15803
c7e4ee3a
CB
15804 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15805 {
15806 type2 = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
5ff904cd 15807
c7e4ee3a
CB
15808 if (type1 == type2)
15809 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
15810 }
5ff904cd 15811
c7e4ee3a
CB
15812 return type;
15813}
5ff904cd 15814
c7e4ee3a
CB
15815#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
15816\f
15817#if FFECOM_GCC_INCLUDE
5ff904cd 15818
c7e4ee3a 15819/* From gcc/cccp.c, the code to handle -I. */
5ff904cd 15820
c7e4ee3a
CB
15821/* Skip leading "./" from a directory name.
15822 This may yield the empty string, which represents the current directory. */
5ff904cd 15823
c7e4ee3a
CB
15824static const char *
15825skip_redundant_dir_prefix (const char *dir)
15826{
15827 while (dir[0] == '.' && dir[1] == '/')
15828 for (dir += 2; *dir == '/'; dir++)
15829 continue;
15830 if (dir[0] == '.' && !dir[1])
15831 dir++;
15832 return dir;
15833}
5ff904cd 15834
c7e4ee3a
CB
15835/* The file_name_map structure holds a mapping of file names for a
15836 particular directory. This mapping is read from the file named
15837 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
15838 map filenames on a file system with severe filename restrictions,
15839 such as DOS. The format of the file name map file is just a series
15840 of lines with two tokens on each line. The first token is the name
15841 to map, and the second token is the actual name to use. */
5ff904cd 15842
c7e4ee3a
CB
15843struct file_name_map
15844{
15845 struct file_name_map *map_next;
15846 char *map_from;
15847 char *map_to;
15848};
5ff904cd 15849
c7e4ee3a 15850#define FILE_NAME_MAP_FILE "header.gcc"
5ff904cd 15851
c7e4ee3a
CB
15852/* Current maximum length of directory names in the search path
15853 for include files. (Altered as we get more of them.) */
5ff904cd 15854
c7e4ee3a 15855static int max_include_len = 0;
5ff904cd 15856
c7e4ee3a
CB
15857struct file_name_list
15858 {
15859 struct file_name_list *next;
15860 char *fname;
15861 /* Mapping of file names for this directory. */
15862 struct file_name_map *name_map;
15863 /* Non-zero if name_map is valid. */
15864 int got_name_map;
15865 };
5ff904cd 15866
c7e4ee3a
CB
15867static struct file_name_list *include = NULL; /* First dir to search */
15868static struct file_name_list *last_include = NULL; /* Last in chain */
5ff904cd 15869
c7e4ee3a
CB
15870/* I/O buffer structure.
15871 The `fname' field is nonzero for source files and #include files
15872 and for the dummy text used for -D and -U.
15873 It is zero for rescanning results of macro expansion
15874 and for expanding macro arguments. */
15875#define INPUT_STACK_MAX 400
15876static struct file_buf {
15877 char *fname;
15878 /* Filename specified with #line command. */
15879 char *nominal_fname;
15880 /* Record where in the search path this file was found.
15881 For #include_next. */
15882 struct file_name_list *dir;
15883 ffewhereLine line;
15884 ffewhereColumn column;
15885} instack[INPUT_STACK_MAX];
5ff904cd 15886
c7e4ee3a
CB
15887static int last_error_tick = 0; /* Incremented each time we print it. */
15888static int input_file_stack_tick = 0; /* Incremented when status changes. */
5ff904cd 15889
c7e4ee3a
CB
15890/* Current nesting level of input sources.
15891 `instack[indepth]' is the level currently being read. */
15892static int indepth = -1;
5ff904cd 15893
c7e4ee3a 15894typedef struct file_buf FILE_BUF;
5ff904cd 15895
c7e4ee3a 15896typedef unsigned char U_CHAR;
5ff904cd 15897
c7e4ee3a
CB
15898/* table to tell if char can be part of a C identifier. */
15899U_CHAR is_idchar[256];
15900/* table to tell if char can be first char of a c identifier. */
15901U_CHAR is_idstart[256];
15902/* table to tell if c is horizontal space. */
15903U_CHAR is_hor_space[256];
15904/* table to tell if c is horizontal or vertical space. */
15905static U_CHAR is_space[256];
5ff904cd 15906
c7e4ee3a
CB
15907#define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
15908#define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*p]) p++; } while (0)
5ff904cd 15909
c7e4ee3a
CB
15910/* Nonzero means -I- has been seen,
15911 so don't look for #include "foo" the source-file directory. */
15912static int ignore_srcdir;
5ff904cd 15913
c7e4ee3a
CB
15914#ifndef INCLUDE_LEN_FUDGE
15915#define INCLUDE_LEN_FUDGE 0
15916#endif
5ff904cd 15917
c7e4ee3a
CB
15918static void append_include_chain (struct file_name_list *first,
15919 struct file_name_list *last);
15920static FILE *open_include_file (char *filename,
15921 struct file_name_list *searchptr);
15922static void print_containing_files (ffebadSeverity sev);
15923static const char *skip_redundant_dir_prefix (const char *);
15924static char *read_filename_string (int ch, FILE *f);
15925static struct file_name_map *read_name_map (const char *dirname);
5ff904cd 15926
c7e4ee3a
CB
15927/* Append a chain of `struct file_name_list's
15928 to the end of the main include chain.
15929 FIRST is the beginning of the chain to append, and LAST is the end. */
5ff904cd 15930
c7e4ee3a
CB
15931static void
15932append_include_chain (first, last)
15933 struct file_name_list *first, *last;
5ff904cd 15934{
c7e4ee3a 15935 struct file_name_list *dir;
5ff904cd 15936
c7e4ee3a
CB
15937 if (!first || !last)
15938 return;
5ff904cd 15939
c7e4ee3a
CB
15940 if (include == 0)
15941 include = first;
15942 else
15943 last_include->next = first;
5ff904cd 15944
c7e4ee3a
CB
15945 for (dir = first; ; dir = dir->next) {
15946 int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE;
15947 if (len > max_include_len)
15948 max_include_len = len;
15949 if (dir == last)
15950 break;
15951 }
15952
15953 last->next = NULL;
15954 last_include = last;
5ff904cd
JL
15955}
15956
c7e4ee3a
CB
15957/* Try to open include file FILENAME. SEARCHPTR is the directory
15958 being tried from the include file search path. This function maps
15959 filenames on file systems based on information read by
15960 read_name_map. */
15961
15962static FILE *
15963open_include_file (filename, searchptr)
15964 char *filename;
15965 struct file_name_list *searchptr;
5ff904cd 15966{
c7e4ee3a
CB
15967 register struct file_name_map *map;
15968 register char *from;
15969 char *p, *dir;
5ff904cd 15970
c7e4ee3a
CB
15971 if (searchptr && ! searchptr->got_name_map)
15972 {
15973 searchptr->name_map = read_name_map (searchptr->fname
15974 ? searchptr->fname : ".");
15975 searchptr->got_name_map = 1;
15976 }
5ff904cd 15977
c7e4ee3a
CB
15978 /* First check the mapping for the directory we are using. */
15979 if (searchptr && searchptr->name_map)
15980 {
15981 from = filename;
15982 if (searchptr->fname)
15983 from += strlen (searchptr->fname) + 1;
15984 for (map = searchptr->name_map; map; map = map->map_next)
15985 {
15986 if (! strcmp (map->map_from, from))
15987 {
15988 /* Found a match. */
15989 return fopen (map->map_to, "r");
15990 }
15991 }
15992 }
5ff904cd 15993
c7e4ee3a
CB
15994 /* Try to find a mapping file for the particular directory we are
15995 looking in. Thus #include <sys/types.h> will look up sys/types.h
15996 in /usr/include/header.gcc and look up types.h in
15997 /usr/include/sys/header.gcc. */
15998 p = rindex (filename, '/');
15999#ifdef DIR_SEPARATOR
16000 if (! p) p = rindex (filename, DIR_SEPARATOR);
16001 else {
16002 char *tmp = rindex (filename, DIR_SEPARATOR);
16003 if (tmp != NULL && tmp > p) p = tmp;
16004 }
16005#endif
16006 if (! p)
16007 p = filename;
16008 if (searchptr
16009 && searchptr->fname
16010 && strlen (searchptr->fname) == (size_t) (p - filename)
16011 && ! strncmp (searchptr->fname, filename, (int) (p - filename)))
16012 {
16013 /* FILENAME is in SEARCHPTR, which we've already checked. */
16014 return fopen (filename, "r");
16015 }
16016
16017 if (p == filename)
16018 {
16019 from = filename;
16020 map = read_name_map (".");
16021 }
16022 else
5ff904cd 16023 {
c7e4ee3a
CB
16024 dir = (char *) xmalloc (p - filename + 1);
16025 memcpy (dir, filename, p - filename);
16026 dir[p - filename] = '\0';
16027 from = p + 1;
16028 map = read_name_map (dir);
16029 free (dir);
5ff904cd 16030 }
c7e4ee3a
CB
16031 for (; map; map = map->map_next)
16032 if (! strcmp (map->map_from, from))
16033 return fopen (map->map_to, "r");
5ff904cd 16034
c7e4ee3a 16035 return fopen (filename, "r");
5ff904cd
JL
16036}
16037
c7e4ee3a
CB
16038/* Print the file names and line numbers of the #include
16039 commands which led to the current file. */
5ff904cd 16040
c7e4ee3a
CB
16041static void
16042print_containing_files (ffebadSeverity sev)
16043{
16044 FILE_BUF *ip = NULL;
16045 int i;
16046 int first = 1;
16047 const char *str1;
16048 const char *str2;
5ff904cd 16049
c7e4ee3a
CB
16050 /* If stack of files hasn't changed since we last printed
16051 this info, don't repeat it. */
16052 if (last_error_tick == input_file_stack_tick)
16053 return;
5ff904cd 16054
c7e4ee3a
CB
16055 for (i = indepth; i >= 0; i--)
16056 if (instack[i].fname != NULL) {
16057 ip = &instack[i];
16058 break;
16059 }
5ff904cd 16060
c7e4ee3a
CB
16061 /* Give up if we don't find a source file. */
16062 if (ip == NULL)
16063 return;
5ff904cd 16064
c7e4ee3a
CB
16065 /* Find the other, outer source files. */
16066 for (i--; i >= 0; i--)
16067 if (instack[i].fname != NULL)
16068 {
16069 ip = &instack[i];
16070 if (first)
16071 {
16072 first = 0;
16073 str1 = "In file included";
16074 }
16075 else
16076 {
16077 str1 = "... ...";
16078 }
5ff904cd 16079
c7e4ee3a
CB
16080 if (i == 1)
16081 str2 = ":";
16082 else
16083 str2 = "";
5ff904cd 16084
c7e4ee3a
CB
16085 ffebad_start_msg ("%A from %B at %0%C", sev);
16086 ffebad_here (0, ip->line, ip->column);
16087 ffebad_string (str1);
16088 ffebad_string (ip->nominal_fname);
16089 ffebad_string (str2);
16090 ffebad_finish ();
16091 }
5ff904cd 16092
c7e4ee3a
CB
16093 /* Record we have printed the status as of this time. */
16094 last_error_tick = input_file_stack_tick;
16095}
5ff904cd 16096
c7e4ee3a
CB
16097/* Read a space delimited string of unlimited length from a stdio
16098 file. */
5ff904cd 16099
c7e4ee3a
CB
16100static char *
16101read_filename_string (ch, f)
16102 int ch;
16103 FILE *f;
16104{
16105 char *alloc, *set;
16106 int len;
5ff904cd 16107
c7e4ee3a
CB
16108 len = 20;
16109 set = alloc = xmalloc (len + 1);
16110 if (! is_space[ch])
16111 {
16112 *set++ = ch;
16113 while ((ch = getc (f)) != EOF && ! is_space[ch])
16114 {
16115 if (set - alloc == len)
16116 {
16117 len *= 2;
16118 alloc = xrealloc (alloc, len + 1);
16119 set = alloc + len / 2;
16120 }
16121 *set++ = ch;
16122 }
16123 }
16124 *set = '\0';
16125 ungetc (ch, f);
16126 return alloc;
16127}
5ff904cd 16128
c7e4ee3a 16129/* Read the file name map file for DIRNAME. */
5ff904cd 16130
c7e4ee3a
CB
16131static struct file_name_map *
16132read_name_map (dirname)
16133 const char *dirname;
16134{
16135 /* This structure holds a linked list of file name maps, one per
16136 directory. */
16137 struct file_name_map_list
16138 {
16139 struct file_name_map_list *map_list_next;
16140 char *map_list_name;
16141 struct file_name_map *map_list_map;
16142 };
16143 static struct file_name_map_list *map_list;
16144 register struct file_name_map_list *map_list_ptr;
16145 char *name;
16146 FILE *f;
16147 size_t dirlen;
16148 int separator_needed;
5ff904cd 16149
c7e4ee3a 16150 dirname = skip_redundant_dir_prefix (dirname);
5ff904cd 16151
c7e4ee3a
CB
16152 for (map_list_ptr = map_list; map_list_ptr;
16153 map_list_ptr = map_list_ptr->map_list_next)
16154 if (! strcmp (map_list_ptr->map_list_name, dirname))
16155 return map_list_ptr->map_list_map;
5ff904cd 16156
c7e4ee3a
CB
16157 map_list_ptr = ((struct file_name_map_list *)
16158 xmalloc (sizeof (struct file_name_map_list)));
16159 map_list_ptr->map_list_name = xstrdup (dirname);
16160 map_list_ptr->map_list_map = NULL;
5ff904cd 16161
c7e4ee3a
CB
16162 dirlen = strlen (dirname);
16163 separator_needed = dirlen != 0 && dirname[dirlen - 1] != '/';
16164 name = (char *) xmalloc (dirlen + strlen (FILE_NAME_MAP_FILE) + 2);
16165 strcpy (name, dirname);
16166 name[dirlen] = '/';
16167 strcpy (name + dirlen + separator_needed, FILE_NAME_MAP_FILE);
16168 f = fopen (name, "r");
16169 free (name);
16170 if (!f)
16171 map_list_ptr->map_list_map = NULL;
16172 else
16173 {
16174 int ch;
5ff904cd 16175
c7e4ee3a
CB
16176 while ((ch = getc (f)) != EOF)
16177 {
16178 char *from, *to;
16179 struct file_name_map *ptr;
16180
16181 if (is_space[ch])
16182 continue;
16183 from = read_filename_string (ch, f);
16184 while ((ch = getc (f)) != EOF && is_hor_space[ch])
16185 ;
16186 to = read_filename_string (ch, f);
5ff904cd 16187
c7e4ee3a
CB
16188 ptr = ((struct file_name_map *)
16189 xmalloc (sizeof (struct file_name_map)));
16190 ptr->map_from = from;
5ff904cd 16191
c7e4ee3a
CB
16192 /* Make the real filename absolute. */
16193 if (*to == '/')
16194 ptr->map_to = to;
16195 else
16196 {
16197 ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
16198 strcpy (ptr->map_to, dirname);
16199 ptr->map_to[dirlen] = '/';
16200 strcpy (ptr->map_to + dirlen + separator_needed, to);
16201 free (to);
16202 }
5ff904cd 16203
c7e4ee3a
CB
16204 ptr->map_next = map_list_ptr->map_list_map;
16205 map_list_ptr->map_list_map = ptr;
5ff904cd 16206
c7e4ee3a
CB
16207 while ((ch = getc (f)) != '\n')
16208 if (ch == EOF)
16209 break;
16210 }
16211 fclose (f);
5ff904cd
JL
16212 }
16213
c7e4ee3a
CB
16214 map_list_ptr->map_list_next = map_list;
16215 map_list = map_list_ptr;
5ff904cd 16216
c7e4ee3a 16217 return map_list_ptr->map_list_map;
5ff904cd
JL
16218}
16219
c7e4ee3a
CB
16220static void
16221ffecom_file_ (char *name)
5ff904cd 16222{
c7e4ee3a 16223 FILE_BUF *fp;
5ff904cd 16224
c7e4ee3a
CB
16225 /* Do partial setup of input buffer for the sake of generating
16226 early #line directives (when -g is in effect). */
5ff904cd 16227
c7e4ee3a
CB
16228 fp = &instack[++indepth];
16229 memset ((char *) fp, 0, sizeof (FILE_BUF));
16230 if (name == NULL)
16231 name = "";
16232 fp->nominal_fname = fp->fname = name;
16233}
5ff904cd 16234
c7e4ee3a 16235/* Initialize syntactic classifications of characters. */
5ff904cd 16236
c7e4ee3a
CB
16237static void
16238ffecom_initialize_char_syntax_ ()
16239{
16240 register int i;
5ff904cd 16241
c7e4ee3a
CB
16242 /*
16243 * Set up is_idchar and is_idstart tables. These should be
16244 * faster than saying (is_alpha (c) || c == '_'), etc.
16245 * Set up these things before calling any routines tthat
16246 * refer to them.
16247 */
16248 for (i = 'a'; i <= 'z'; i++) {
16249 is_idchar[i - 'a' + 'A'] = 1;
16250 is_idchar[i] = 1;
16251 is_idstart[i - 'a' + 'A'] = 1;
16252 is_idstart[i] = 1;
16253 }
16254 for (i = '0'; i <= '9'; i++)
16255 is_idchar[i] = 1;
16256 is_idchar['_'] = 1;
16257 is_idstart['_'] = 1;
5ff904cd 16258
c7e4ee3a
CB
16259 /* horizontal space table */
16260 is_hor_space[' '] = 1;
16261 is_hor_space['\t'] = 1;
16262 is_hor_space['\v'] = 1;
16263 is_hor_space['\f'] = 1;
16264 is_hor_space['\r'] = 1;
5ff904cd 16265
c7e4ee3a
CB
16266 is_space[' '] = 1;
16267 is_space['\t'] = 1;
16268 is_space['\v'] = 1;
16269 is_space['\f'] = 1;
16270 is_space['\n'] = 1;
16271 is_space['\r'] = 1;
16272}
5ff904cd 16273
c7e4ee3a
CB
16274static void
16275ffecom_close_include_ (FILE *f)
16276{
16277 fclose (f);
5ff904cd 16278
c7e4ee3a
CB
16279 indepth--;
16280 input_file_stack_tick++;
5ff904cd 16281
c7e4ee3a
CB
16282 ffewhere_line_kill (instack[indepth].line);
16283 ffewhere_column_kill (instack[indepth].column);
16284}
5ff904cd 16285
c7e4ee3a
CB
16286static int
16287ffecom_decode_include_option_ (char *spec)
16288{
16289 struct file_name_list *dirtmp;
16290
16291 if (! ignore_srcdir && !strcmp (spec, "-"))
16292 ignore_srcdir = 1;
16293 else
16294 {
16295 dirtmp = (struct file_name_list *)
16296 xmalloc (sizeof (struct file_name_list));
16297 dirtmp->next = 0; /* New one goes on the end */
16298 if (spec[0] != 0)
16299 dirtmp->fname = spec;
16300 else
16301 fatal ("Directory name must immediately follow -I option with no intervening spaces, as in `-Idir', not `-I dir'");
16302 dirtmp->got_name_map = 0;
16303 append_include_chain (dirtmp, dirtmp);
16304 }
16305 return 1;
5ff904cd
JL
16306}
16307
c7e4ee3a
CB
16308/* Open INCLUDEd file. */
16309
16310static FILE *
16311ffecom_open_include_ (char *name, ffewhereLine l, ffewhereColumn c)
5ff904cd 16312{
c7e4ee3a
CB
16313 char *fbeg = name;
16314 size_t flen = strlen (fbeg);
16315 struct file_name_list *search_start = include; /* Chain of dirs to search */
16316 struct file_name_list dsp[1]; /* First in chain, if #include "..." */
16317 struct file_name_list *searchptr = 0;
16318 char *fname; /* Dynamically allocated fname buffer */
16319 FILE *f;
16320 FILE_BUF *fp;
5ff904cd 16321
c7e4ee3a
CB
16322 if (flen == 0)
16323 return NULL;
5ff904cd 16324
c7e4ee3a 16325 dsp[0].fname = NULL;
5ff904cd 16326
c7e4ee3a
CB
16327 /* If -I- was specified, don't search current dir, only spec'd ones. */
16328 if (!ignore_srcdir)
16329 {
16330 for (fp = &instack[indepth]; fp >= instack; fp--)
16331 {
16332 int n;
16333 char *ep;
16334 char *nam;
5ff904cd 16335
c7e4ee3a
CB
16336 if ((nam = fp->nominal_fname) != NULL)
16337 {
16338 /* Found a named file. Figure out dir of the file,
16339 and put it in front of the search list. */
16340 dsp[0].next = search_start;
16341 search_start = dsp;
16342#ifndef VMS
16343 ep = rindex (nam, '/');
16344#ifdef DIR_SEPARATOR
16345 if (ep == NULL) ep = rindex (nam, DIR_SEPARATOR);
16346 else {
16347 char *tmp = rindex (nam, DIR_SEPARATOR);
16348 if (tmp != NULL && tmp > ep) ep = tmp;
16349 }
16350#endif
16351#else /* VMS */
16352 ep = rindex (nam, ']');
16353 if (ep == NULL) ep = rindex (nam, '>');
16354 if (ep == NULL) ep = rindex (nam, ':');
16355 if (ep != NULL) ep++;
16356#endif /* VMS */
16357 if (ep != NULL)
16358 {
16359 n = ep - nam;
16360 dsp[0].fname = (char *) xmalloc (n + 1);
16361 strncpy (dsp[0].fname, nam, n);
16362 dsp[0].fname[n] = '\0';
16363 if (n + INCLUDE_LEN_FUDGE > max_include_len)
16364 max_include_len = n + INCLUDE_LEN_FUDGE;
16365 }
16366 else
16367 dsp[0].fname = NULL; /* Current directory */
16368 dsp[0].got_name_map = 0;
16369 break;
16370 }
16371 }
16372 }
5ff904cd 16373
c7e4ee3a
CB
16374 /* Allocate this permanently, because it gets stored in the definitions
16375 of macros. */
16376 fname = xmalloc (max_include_len + flen + 4);
16377 /* + 2 above for slash and terminating null. */
16378 /* + 2 added for '.h' on VMS (to support '#include filename') (NOT USED
16379 for g77 yet). */
5ff904cd 16380
c7e4ee3a 16381 /* If specified file name is absolute, just open it. */
5ff904cd 16382
c7e4ee3a
CB
16383 if (*fbeg == '/'
16384#ifdef DIR_SEPARATOR
16385 || *fbeg == DIR_SEPARATOR
16386#endif
16387 )
16388 {
16389 strncpy (fname, (char *) fbeg, flen);
16390 fname[flen] = 0;
16391 f = open_include_file (fname, NULL_PTR);
5ff904cd 16392 }
c7e4ee3a
CB
16393 else
16394 {
16395 f = NULL;
5ff904cd 16396
c7e4ee3a
CB
16397 /* Search directory path, trying to open the file.
16398 Copy each filename tried into FNAME. */
5ff904cd 16399
c7e4ee3a
CB
16400 for (searchptr = search_start; searchptr; searchptr = searchptr->next)
16401 {
16402 if (searchptr->fname)
16403 {
16404 /* The empty string in a search path is ignored.
16405 This makes it possible to turn off entirely
16406 a standard piece of the list. */
16407 if (searchptr->fname[0] == 0)
16408 continue;
16409 strcpy (fname, skip_redundant_dir_prefix (searchptr->fname));
16410 if (fname[0] && fname[strlen (fname) - 1] != '/')
16411 strcat (fname, "/");
16412 fname[strlen (fname) + flen] = 0;
16413 }
16414 else
16415 fname[0] = 0;
5ff904cd 16416
c7e4ee3a
CB
16417 strncat (fname, fbeg, flen);
16418#ifdef VMS
16419 /* Change this 1/2 Unix 1/2 VMS file specification into a
16420 full VMS file specification */
16421 if (searchptr->fname && (searchptr->fname[0] != 0))
16422 {
16423 /* Fix up the filename */
16424 hack_vms_include_specification (fname);
16425 }
16426 else
16427 {
16428 /* This is a normal VMS filespec, so use it unchanged. */
16429 strncpy (fname, (char *) fbeg, flen);
16430 fname[flen] = 0;
16431#if 0 /* Not for g77. */
16432 /* if it's '#include filename', add the missing .h */
16433 if (index (fname, '.') == NULL)
16434 strcat (fname, ".h");
5ff904cd 16435#endif
c7e4ee3a
CB
16436 }
16437#endif /* VMS */
16438 f = open_include_file (fname, searchptr);
16439#ifdef EACCES
16440 if (f == NULL && errno == EACCES)
16441 {
16442 print_containing_files (FFEBAD_severityWARNING);
16443 ffebad_start_msg ("At %0, INCLUDE file %A exists, but is not readable",
16444 FFEBAD_severityWARNING);
16445 ffebad_string (fname);
16446 ffebad_here (0, l, c);
16447 ffebad_finish ();
16448 }
16449#endif
16450 if (f != NULL)
16451 break;
16452 }
16453 }
5ff904cd 16454
c7e4ee3a 16455 if (f == NULL)
5ff904cd 16456 {
c7e4ee3a 16457 /* A file that was not found. */
5ff904cd 16458
c7e4ee3a
CB
16459 strncpy (fname, (char *) fbeg, flen);
16460 fname[flen] = 0;
16461 print_containing_files (ffebad_severity (FFEBAD_OPEN_INCLUDE));
16462 ffebad_start (FFEBAD_OPEN_INCLUDE);
16463 ffebad_here (0, l, c);
16464 ffebad_string (fname);
16465 ffebad_finish ();
5ff904cd
JL
16466 }
16467
c7e4ee3a
CB
16468 if (dsp[0].fname != NULL)
16469 free (dsp[0].fname);
5ff904cd 16470
c7e4ee3a
CB
16471 if (f == NULL)
16472 return NULL;
5ff904cd 16473
c7e4ee3a
CB
16474 if (indepth >= (INPUT_STACK_MAX - 1))
16475 {
16476 print_containing_files (FFEBAD_severityFATAL);
16477 ffebad_start_msg ("At %0, INCLUDE nesting too deep",
16478 FFEBAD_severityFATAL);
16479 ffebad_string (fname);
16480 ffebad_here (0, l, c);
16481 ffebad_finish ();
16482 return NULL;
16483 }
5ff904cd 16484
c7e4ee3a
CB
16485 instack[indepth].line = ffewhere_line_use (l);
16486 instack[indepth].column = ffewhere_column_use (c);
5ff904cd 16487
c7e4ee3a
CB
16488 fp = &instack[indepth + 1];
16489 memset ((char *) fp, 0, sizeof (FILE_BUF));
16490 fp->nominal_fname = fp->fname = fname;
16491 fp->dir = searchptr;
5ff904cd 16492
c7e4ee3a
CB
16493 indepth++;
16494 input_file_stack_tick++;
5ff904cd 16495
c7e4ee3a
CB
16496 return f;
16497}
16498#endif /* FFECOM_GCC_INCLUDE */
5ff904cd 16499
c7e4ee3a
CB
16500/**INDENT* (Do not reformat this comment even with -fca option.)
16501 Data-gathering files: Given the source file listed below, compiled with
16502 f2c I obtained the output file listed after that, and from the output
16503 file I derived the above code.
5ff904cd 16504
c7e4ee3a
CB
16505-------- (begin input file to f2c)
16506 implicit none
16507 character*10 A1,A2
16508 complex C1,C2
16509 integer I1,I2
16510 real R1,R2
16511 double precision D1,D2
16512C
16513 call getem(A1,A2,C1,C2,I1,I2,R1,R2,D1,D2)
16514c /
16515 call fooI(I1/I2)
16516 call fooR(R1/I1)
16517 call fooD(D1/I1)
16518 call fooC(C1/I1)
16519 call fooR(R1/R2)
16520 call fooD(R1/D1)
16521 call fooD(D1/D2)
16522 call fooD(D1/R1)
16523 call fooC(C1/C2)
16524 call fooC(C1/R1)
16525 call fooZ(C1/D1)
16526c **
16527 call fooI(I1**I2)
16528 call fooR(R1**I1)
16529 call fooD(D1**I1)
16530 call fooC(C1**I1)
16531 call fooR(R1**R2)
16532 call fooD(R1**D1)
16533 call fooD(D1**D2)
16534 call fooD(D1**R1)
16535 call fooC(C1**C2)
16536 call fooC(C1**R1)
16537 call fooZ(C1**D1)
16538c FFEINTRIN_impABS
16539 call fooR(ABS(R1))
16540c FFEINTRIN_impACOS
16541 call fooR(ACOS(R1))
16542c FFEINTRIN_impAIMAG
16543 call fooR(AIMAG(C1))
16544c FFEINTRIN_impAINT
16545 call fooR(AINT(R1))
16546c FFEINTRIN_impALOG
16547 call fooR(ALOG(R1))
16548c FFEINTRIN_impALOG10
16549 call fooR(ALOG10(R1))
16550c FFEINTRIN_impAMAX0
16551 call fooR(AMAX0(I1,I2))
16552c FFEINTRIN_impAMAX1
16553 call fooR(AMAX1(R1,R2))
16554c FFEINTRIN_impAMIN0
16555 call fooR(AMIN0(I1,I2))
16556c FFEINTRIN_impAMIN1
16557 call fooR(AMIN1(R1,R2))
16558c FFEINTRIN_impAMOD
16559 call fooR(AMOD(R1,R2))
16560c FFEINTRIN_impANINT
16561 call fooR(ANINT(R1))
16562c FFEINTRIN_impASIN
16563 call fooR(ASIN(R1))
16564c FFEINTRIN_impATAN
16565 call fooR(ATAN(R1))
16566c FFEINTRIN_impATAN2
16567 call fooR(ATAN2(R1,R2))
16568c FFEINTRIN_impCABS
16569 call fooR(CABS(C1))
16570c FFEINTRIN_impCCOS
16571 call fooC(CCOS(C1))
16572c FFEINTRIN_impCEXP
16573 call fooC(CEXP(C1))
16574c FFEINTRIN_impCHAR
16575 call fooA(CHAR(I1))
16576c FFEINTRIN_impCLOG
16577 call fooC(CLOG(C1))
16578c FFEINTRIN_impCONJG
16579 call fooC(CONJG(C1))
16580c FFEINTRIN_impCOS
16581 call fooR(COS(R1))
16582c FFEINTRIN_impCOSH
16583 call fooR(COSH(R1))
16584c FFEINTRIN_impCSIN
16585 call fooC(CSIN(C1))
16586c FFEINTRIN_impCSQRT
16587 call fooC(CSQRT(C1))
16588c FFEINTRIN_impDABS
16589 call fooD(DABS(D1))
16590c FFEINTRIN_impDACOS
16591 call fooD(DACOS(D1))
16592c FFEINTRIN_impDASIN
16593 call fooD(DASIN(D1))
16594c FFEINTRIN_impDATAN
16595 call fooD(DATAN(D1))
16596c FFEINTRIN_impDATAN2
16597 call fooD(DATAN2(D1,D2))
16598c FFEINTRIN_impDCOS
16599 call fooD(DCOS(D1))
16600c FFEINTRIN_impDCOSH
16601 call fooD(DCOSH(D1))
16602c FFEINTRIN_impDDIM
16603 call fooD(DDIM(D1,D2))
16604c FFEINTRIN_impDEXP
16605 call fooD(DEXP(D1))
16606c FFEINTRIN_impDIM
16607 call fooR(DIM(R1,R2))
16608c FFEINTRIN_impDINT
16609 call fooD(DINT(D1))
16610c FFEINTRIN_impDLOG
16611 call fooD(DLOG(D1))
16612c FFEINTRIN_impDLOG10
16613 call fooD(DLOG10(D1))
16614c FFEINTRIN_impDMAX1
16615 call fooD(DMAX1(D1,D2))
16616c FFEINTRIN_impDMIN1
16617 call fooD(DMIN1(D1,D2))
16618c FFEINTRIN_impDMOD
16619 call fooD(DMOD(D1,D2))
16620c FFEINTRIN_impDNINT
16621 call fooD(DNINT(D1))
16622c FFEINTRIN_impDPROD
16623 call fooD(DPROD(R1,R2))
16624c FFEINTRIN_impDSIGN
16625 call fooD(DSIGN(D1,D2))
16626c FFEINTRIN_impDSIN
16627 call fooD(DSIN(D1))
16628c FFEINTRIN_impDSINH
16629 call fooD(DSINH(D1))
16630c FFEINTRIN_impDSQRT
16631 call fooD(DSQRT(D1))
16632c FFEINTRIN_impDTAN
16633 call fooD(DTAN(D1))
16634c FFEINTRIN_impDTANH
16635 call fooD(DTANH(D1))
16636c FFEINTRIN_impEXP
16637 call fooR(EXP(R1))
16638c FFEINTRIN_impIABS
16639 call fooI(IABS(I1))
16640c FFEINTRIN_impICHAR
16641 call fooI(ICHAR(A1))
16642c FFEINTRIN_impIDIM
16643 call fooI(IDIM(I1,I2))
16644c FFEINTRIN_impIDNINT
16645 call fooI(IDNINT(D1))
16646c FFEINTRIN_impINDEX
16647 call fooI(INDEX(A1,A2))
16648c FFEINTRIN_impISIGN
16649 call fooI(ISIGN(I1,I2))
16650c FFEINTRIN_impLEN
16651 call fooI(LEN(A1))
16652c FFEINTRIN_impLGE
16653 call fooL(LGE(A1,A2))
16654c FFEINTRIN_impLGT
16655 call fooL(LGT(A1,A2))
16656c FFEINTRIN_impLLE
16657 call fooL(LLE(A1,A2))
16658c FFEINTRIN_impLLT
16659 call fooL(LLT(A1,A2))
16660c FFEINTRIN_impMAX0
16661 call fooI(MAX0(I1,I2))
16662c FFEINTRIN_impMAX1
16663 call fooI(MAX1(R1,R2))
16664c FFEINTRIN_impMIN0
16665 call fooI(MIN0(I1,I2))
16666c FFEINTRIN_impMIN1
16667 call fooI(MIN1(R1,R2))
16668c FFEINTRIN_impMOD
16669 call fooI(MOD(I1,I2))
16670c FFEINTRIN_impNINT
16671 call fooI(NINT(R1))
16672c FFEINTRIN_impSIGN
16673 call fooR(SIGN(R1,R2))
16674c FFEINTRIN_impSIN
16675 call fooR(SIN(R1))
16676c FFEINTRIN_impSINH
16677 call fooR(SINH(R1))
16678c FFEINTRIN_impSQRT
16679 call fooR(SQRT(R1))
16680c FFEINTRIN_impTAN
16681 call fooR(TAN(R1))
16682c FFEINTRIN_impTANH
16683 call fooR(TANH(R1))
16684c FFEINTRIN_imp_CMPLX_C
16685 call fooC(cmplx(C1,C2))
16686c FFEINTRIN_imp_CMPLX_D
16687 call fooZ(cmplx(D1,D2))
16688c FFEINTRIN_imp_CMPLX_I
16689 call fooC(cmplx(I1,I2))
16690c FFEINTRIN_imp_CMPLX_R
16691 call fooC(cmplx(R1,R2))
16692c FFEINTRIN_imp_DBLE_C
16693 call fooD(dble(C1))
16694c FFEINTRIN_imp_DBLE_D
16695 call fooD(dble(D1))
16696c FFEINTRIN_imp_DBLE_I
16697 call fooD(dble(I1))
16698c FFEINTRIN_imp_DBLE_R
16699 call fooD(dble(R1))
16700c FFEINTRIN_imp_INT_C
16701 call fooI(int(C1))
16702c FFEINTRIN_imp_INT_D
16703 call fooI(int(D1))
16704c FFEINTRIN_imp_INT_I
16705 call fooI(int(I1))
16706c FFEINTRIN_imp_INT_R
16707 call fooI(int(R1))
16708c FFEINTRIN_imp_REAL_C
16709 call fooR(real(C1))
16710c FFEINTRIN_imp_REAL_D
16711 call fooR(real(D1))
16712c FFEINTRIN_imp_REAL_I
16713 call fooR(real(I1))
16714c FFEINTRIN_imp_REAL_R
16715 call fooR(real(R1))
16716c
16717c FFEINTRIN_imp_INT_D:
16718c
16719c FFEINTRIN_specIDINT
16720 call fooI(IDINT(D1))
16721c
16722c FFEINTRIN_imp_INT_R:
16723c
16724c FFEINTRIN_specIFIX
16725 call fooI(IFIX(R1))
16726c FFEINTRIN_specINT
16727 call fooI(INT(R1))
16728c
16729c FFEINTRIN_imp_REAL_D:
16730c
16731c FFEINTRIN_specSNGL
16732 call fooR(SNGL(D1))
16733c
16734c FFEINTRIN_imp_REAL_I:
16735c
16736c FFEINTRIN_specFLOAT
16737 call fooR(FLOAT(I1))
16738c FFEINTRIN_specREAL
16739 call fooR(REAL(I1))
16740c
16741 end
16742-------- (end input file to f2c)
5ff904cd 16743
c7e4ee3a
CB
16744-------- (begin output from providing above input file as input to:
16745-------- `f2c | gcc -E -C - | sed -e "s:/[*]*://:g" -e "s:[*]*[/]://:g" \
16746-------- -e "s:^#.*$::g"')
5ff904cd 16747
c7e4ee3a
CB
16748// -- translated by f2c (version 19950223).
16749 You must link the resulting object file with the libraries:
16750 -lf2c -lm (in that order)
16751//
5ff904cd 16752
5ff904cd 16753
c7e4ee3a 16754// f2c.h -- Standard Fortran to C header file //
5ff904cd 16755
c7e4ee3a 16756/// barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed."
5ff904cd 16757
c7e4ee3a 16758 - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) //
5ff904cd 16759
5ff904cd 16760
5ff904cd 16761
5ff904cd 16762
c7e4ee3a
CB
16763// F2C_INTEGER will normally be `int' but would be `long' on 16-bit systems //
16764// we assume short, float are OK //
16765typedef long int // long int // integer;
16766typedef char *address;
16767typedef short int shortint;
16768typedef float real;
16769typedef double doublereal;
16770typedef struct { real r, i; } complex;
16771typedef struct { doublereal r, i; } doublecomplex;
16772typedef long int // long int // logical;
16773typedef short int shortlogical;
16774typedef char logical1;
16775typedef char integer1;
16776// typedef long long longint; // // system-dependent //
5ff904cd 16777
5ff904cd 16778
5ff904cd 16779
5ff904cd 16780
c7e4ee3a 16781// Extern is for use with -E //
5ff904cd 16782
5ff904cd 16783
5ff904cd 16784
5ff904cd 16785
c7e4ee3a 16786// I/O stuff //
5ff904cd 16787
5ff904cd 16788
5ff904cd 16789
5ff904cd 16790
5ff904cd 16791
5ff904cd 16792
5ff904cd 16793
5ff904cd 16794
c7e4ee3a
CB
16795typedef long int // int or long int // flag;
16796typedef long int // int or long int // ftnlen;
16797typedef long int // int or long int // ftnint;
5ff904cd 16798
5ff904cd 16799
c7e4ee3a
CB
16800//external read, write//
16801typedef struct
16802{ flag cierr;
16803 ftnint ciunit;
16804 flag ciend;
16805 char *cifmt;
16806 ftnint cirec;
16807} cilist;
5ff904cd 16808
c7e4ee3a
CB
16809//internal read, write//
16810typedef struct
16811{ flag icierr;
16812 char *iciunit;
16813 flag iciend;
16814 char *icifmt;
16815 ftnint icirlen;
16816 ftnint icirnum;
16817} icilist;
5ff904cd 16818
c7e4ee3a
CB
16819//open//
16820typedef struct
16821{ flag oerr;
16822 ftnint ounit;
16823 char *ofnm;
16824 ftnlen ofnmlen;
16825 char *osta;
16826 char *oacc;
16827 char *ofm;
16828 ftnint orl;
16829 char *oblnk;
16830} olist;
5ff904cd 16831
c7e4ee3a
CB
16832//close//
16833typedef struct
16834{ flag cerr;
16835 ftnint cunit;
16836 char *csta;
16837} cllist;
5ff904cd 16838
c7e4ee3a
CB
16839//rewind, backspace, endfile//
16840typedef struct
16841{ flag aerr;
16842 ftnint aunit;
16843} alist;
5ff904cd 16844
c7e4ee3a
CB
16845// inquire //
16846typedef struct
16847{ flag inerr;
16848 ftnint inunit;
16849 char *infile;
16850 ftnlen infilen;
16851 ftnint *inex; //parameters in standard's order//
16852 ftnint *inopen;
16853 ftnint *innum;
16854 ftnint *innamed;
16855 char *inname;
16856 ftnlen innamlen;
16857 char *inacc;
16858 ftnlen inacclen;
16859 char *inseq;
16860 ftnlen inseqlen;
16861 char *indir;
16862 ftnlen indirlen;
16863 char *infmt;
16864 ftnlen infmtlen;
16865 char *inform;
16866 ftnint informlen;
16867 char *inunf;
16868 ftnlen inunflen;
16869 ftnint *inrecl;
16870 ftnint *innrec;
16871 char *inblank;
16872 ftnlen inblanklen;
16873} inlist;
5ff904cd 16874
5ff904cd 16875
5ff904cd 16876
c7e4ee3a
CB
16877union Multitype { // for multiple entry points //
16878 integer1 g;
16879 shortint h;
16880 integer i;
16881 // longint j; //
16882 real r;
16883 doublereal d;
16884 complex c;
16885 doublecomplex z;
16886 };
16887
16888typedef union Multitype Multitype;
5ff904cd 16889
c7e4ee3a 16890typedef long Long; // No longer used; formerly in Namelist //
5ff904cd 16891
c7e4ee3a
CB
16892struct Vardesc { // for Namelist //
16893 char *name;
16894 char *addr;
16895 ftnlen *dims;
16896 int type;
16897 };
16898typedef struct Vardesc Vardesc;
5ff904cd 16899
c7e4ee3a
CB
16900struct Namelist {
16901 char *name;
16902 Vardesc **vars;
16903 int nvars;
16904 };
16905typedef struct Namelist Namelist;
5ff904cd 16906
5ff904cd 16907
5ff904cd 16908
5ff904cd 16909
5ff904cd 16910
5ff904cd 16911
5ff904cd 16912
5ff904cd 16913
c7e4ee3a 16914// procedure parameter types for -A and -C++ //
5ff904cd 16915
5ff904cd 16916
5ff904cd 16917
5ff904cd 16918
c7e4ee3a
CB
16919typedef int // Unknown procedure type // (*U_fp)();
16920typedef shortint (*J_fp)();
16921typedef integer (*I_fp)();
16922typedef real (*R_fp)();
16923typedef doublereal (*D_fp)(), (*E_fp)();
16924typedef // Complex // void (*C_fp)();
16925typedef // Double Complex // void (*Z_fp)();
16926typedef logical (*L_fp)();
16927typedef shortlogical (*K_fp)();
16928typedef // Character // void (*H_fp)();
16929typedef // Subroutine // int (*S_fp)();
5ff904cd 16930
c7e4ee3a
CB
16931// E_fp is for real functions when -R is not specified //
16932typedef void C_f; // complex function //
16933typedef void H_f; // character function //
16934typedef void Z_f; // double complex function //
16935typedef doublereal E_f; // real function with -R not specified //
5ff904cd 16936
c7e4ee3a 16937// undef any lower-case symbols that your C compiler predefines, e.g.: //
5ff904cd 16938
5ff904cd 16939
c7e4ee3a
CB
16940// (No such symbols should be defined in a strict ANSI C compiler.
16941 We can avoid trouble with f2c-translated code by using
16942 gcc -ansi [-traditional].) //
16943
5ff904cd 16944
5ff904cd 16945
5ff904cd 16946
5ff904cd 16947
5ff904cd 16948
5ff904cd 16949
5ff904cd 16950
5ff904cd 16951
5ff904cd 16952
5ff904cd 16953
5ff904cd 16954
5ff904cd 16955
5ff904cd 16956
5ff904cd 16957
5ff904cd 16958
5ff904cd 16959
5ff904cd 16960
5ff904cd 16961
5ff904cd 16962
5ff904cd 16963
5ff904cd 16964
5ff904cd 16965
c7e4ee3a
CB
16966// Main program // MAIN__()
16967{
16968 // System generated locals //
16969 integer i__1;
16970 real r__1, r__2;
16971 doublereal d__1, d__2;
16972 complex q__1;
16973 doublecomplex z__1, z__2, z__3;
16974 logical L__1;
16975 char ch__1[1];
16976
16977 // Builtin functions //
16978 void c_div();
16979 integer pow_ii();
16980 double pow_ri(), pow_di();
16981 void pow_ci();
16982 double pow_dd();
16983 void pow_zz();
16984 double acos(), r_imag(), r_int(), log(), r_lg10(), r_mod(), r_nint(),
16985 asin(), atan(), atan2(), c_abs();
16986 void c_cos(), c_exp(), c_log(), r_cnjg();
16987 double cos(), cosh();
16988 void c_sin(), c_sqrt();
16989 double d_dim(), exp(), r_dim(), d_int(), d_lg10(), d_mod(), d_nint(),
16990 d_sign(), sin(), sinh(), sqrt(), tan(), tanh();
16991 integer i_dim(), i_dnnt(), i_indx(), i_sign(), i_len();
16992 logical l_ge(), l_gt(), l_le(), l_lt();
16993 integer i_nint();
16994 double r_sign();
16995
16996 // Local variables //
16997 extern // Subroutine // int fooa_(), fooc_(), food_(), fooi_(), foor_(),
16998 fool_(), fooz_(), getem_();
16999 static char a1[10], a2[10];
17000 static complex c1, c2;
17001 static doublereal d1, d2;
17002 static integer i1, i2;
17003 static real r1, r2;
17004
17005
17006 getem_(a1, a2, &c1, &c2, &i1, &i2, &r1, &r2, &d1, &d2, 10L, 10L);
17007// / //
17008 i__1 = i1 / i2;
17009 fooi_(&i__1);
17010 r__1 = r1 / i1;
17011 foor_(&r__1);
17012 d__1 = d1 / i1;
17013 food_(&d__1);
17014 d__1 = (doublereal) i1;
17015 q__1.r = c1.r / d__1, q__1.i = c1.i / d__1;
17016 fooc_(&q__1);
17017 r__1 = r1 / r2;
17018 foor_(&r__1);
17019 d__1 = r1 / d1;
17020 food_(&d__1);
17021 d__1 = d1 / d2;
17022 food_(&d__1);
17023 d__1 = d1 / r1;
17024 food_(&d__1);
17025 c_div(&q__1, &c1, &c2);
17026 fooc_(&q__1);
17027 q__1.r = c1.r / r1, q__1.i = c1.i / r1;
17028 fooc_(&q__1);
17029 z__1.r = c1.r / d1, z__1.i = c1.i / d1;
17030 fooz_(&z__1);
17031// ** //
17032 i__1 = pow_ii(&i1, &i2);
17033 fooi_(&i__1);
17034 r__1 = pow_ri(&r1, &i1);
17035 foor_(&r__1);
17036 d__1 = pow_di(&d1, &i1);
17037 food_(&d__1);
17038 pow_ci(&q__1, &c1, &i1);
17039 fooc_(&q__1);
17040 d__1 = (doublereal) r1;
17041 d__2 = (doublereal) r2;
17042 r__1 = pow_dd(&d__1, &d__2);
17043 foor_(&r__1);
17044 d__2 = (doublereal) r1;
17045 d__1 = pow_dd(&d__2, &d1);
17046 food_(&d__1);
17047 d__1 = pow_dd(&d1, &d2);
17048 food_(&d__1);
17049 d__2 = (doublereal) r1;
17050 d__1 = pow_dd(&d1, &d__2);
17051 food_(&d__1);
17052 z__2.r = c1.r, z__2.i = c1.i;
17053 z__3.r = c2.r, z__3.i = c2.i;
17054 pow_zz(&z__1, &z__2, &z__3);
17055 q__1.r = z__1.r, q__1.i = z__1.i;
17056 fooc_(&q__1);
17057 z__2.r = c1.r, z__2.i = c1.i;
17058 z__3.r = r1, z__3.i = 0.;
17059 pow_zz(&z__1, &z__2, &z__3);
17060 q__1.r = z__1.r, q__1.i = z__1.i;
17061 fooc_(&q__1);
17062 z__2.r = c1.r, z__2.i = c1.i;
17063 z__3.r = d1, z__3.i = 0.;
17064 pow_zz(&z__1, &z__2, &z__3);
17065 fooz_(&z__1);
17066// FFEINTRIN_impABS //
17067 r__1 = (doublereal)(( r1 ) >= 0 ? ( r1 ) : -( r1 )) ;
17068 foor_(&r__1);
17069// FFEINTRIN_impACOS //
17070 r__1 = acos(r1);
17071 foor_(&r__1);
17072// FFEINTRIN_impAIMAG //
17073 r__1 = r_imag(&c1);
17074 foor_(&r__1);
17075// FFEINTRIN_impAINT //
17076 r__1 = r_int(&r1);
17077 foor_(&r__1);
17078// FFEINTRIN_impALOG //
17079 r__1 = log(r1);
17080 foor_(&r__1);
17081// FFEINTRIN_impALOG10 //
17082 r__1 = r_lg10(&r1);
17083 foor_(&r__1);
17084// FFEINTRIN_impAMAX0 //
17085 r__1 = (real) (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
17086 foor_(&r__1);
17087// FFEINTRIN_impAMAX1 //
17088 r__1 = (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
17089 foor_(&r__1);
17090// FFEINTRIN_impAMIN0 //
17091 r__1 = (real) (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
17092 foor_(&r__1);
17093// FFEINTRIN_impAMIN1 //
17094 r__1 = (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
17095 foor_(&r__1);
17096// FFEINTRIN_impAMOD //
17097 r__1 = r_mod(&r1, &r2);
17098 foor_(&r__1);
17099// FFEINTRIN_impANINT //
17100 r__1 = r_nint(&r1);
17101 foor_(&r__1);
17102// FFEINTRIN_impASIN //
17103 r__1 = asin(r1);
17104 foor_(&r__1);
17105// FFEINTRIN_impATAN //
17106 r__1 = atan(r1);
17107 foor_(&r__1);
17108// FFEINTRIN_impATAN2 //
17109 r__1 = atan2(r1, r2);
17110 foor_(&r__1);
17111// FFEINTRIN_impCABS //
17112 r__1 = c_abs(&c1);
17113 foor_(&r__1);
17114// FFEINTRIN_impCCOS //
17115 c_cos(&q__1, &c1);
17116 fooc_(&q__1);
17117// FFEINTRIN_impCEXP //
17118 c_exp(&q__1, &c1);
17119 fooc_(&q__1);
17120// FFEINTRIN_impCHAR //
17121 *(unsigned char *)&ch__1[0] = i1;
17122 fooa_(ch__1, 1L);
17123// FFEINTRIN_impCLOG //
17124 c_log(&q__1, &c1);
17125 fooc_(&q__1);
17126// FFEINTRIN_impCONJG //
17127 r_cnjg(&q__1, &c1);
17128 fooc_(&q__1);
17129// FFEINTRIN_impCOS //
17130 r__1 = cos(r1);
17131 foor_(&r__1);
17132// FFEINTRIN_impCOSH //
17133 r__1 = cosh(r1);
17134 foor_(&r__1);
17135// FFEINTRIN_impCSIN //
17136 c_sin(&q__1, &c1);
17137 fooc_(&q__1);
17138// FFEINTRIN_impCSQRT //
17139 c_sqrt(&q__1, &c1);
17140 fooc_(&q__1);
17141// FFEINTRIN_impDABS //
17142 d__1 = (( d1 ) >= 0 ? ( d1 ) : -( d1 )) ;
17143 food_(&d__1);
17144// FFEINTRIN_impDACOS //
17145 d__1 = acos(d1);
17146 food_(&d__1);
17147// FFEINTRIN_impDASIN //
17148 d__1 = asin(d1);
17149 food_(&d__1);
17150// FFEINTRIN_impDATAN //
17151 d__1 = atan(d1);
17152 food_(&d__1);
17153// FFEINTRIN_impDATAN2 //
17154 d__1 = atan2(d1, d2);
17155 food_(&d__1);
17156// FFEINTRIN_impDCOS //
17157 d__1 = cos(d1);
17158 food_(&d__1);
17159// FFEINTRIN_impDCOSH //
17160 d__1 = cosh(d1);
17161 food_(&d__1);
17162// FFEINTRIN_impDDIM //
17163 d__1 = d_dim(&d1, &d2);
17164 food_(&d__1);
17165// FFEINTRIN_impDEXP //
17166 d__1 = exp(d1);
17167 food_(&d__1);
17168// FFEINTRIN_impDIM //
17169 r__1 = r_dim(&r1, &r2);
17170 foor_(&r__1);
17171// FFEINTRIN_impDINT //
17172 d__1 = d_int(&d1);
17173 food_(&d__1);
17174// FFEINTRIN_impDLOG //
17175 d__1 = log(d1);
17176 food_(&d__1);
17177// FFEINTRIN_impDLOG10 //
17178 d__1 = d_lg10(&d1);
17179 food_(&d__1);
17180// FFEINTRIN_impDMAX1 //
17181 d__1 = (( d1 ) >= ( d2 ) ? ( d1 ) : ( d2 )) ;
17182 food_(&d__1);
17183// FFEINTRIN_impDMIN1 //
17184 d__1 = (( d1 ) <= ( d2 ) ? ( d1 ) : ( d2 )) ;
17185 food_(&d__1);
17186// FFEINTRIN_impDMOD //
17187 d__1 = d_mod(&d1, &d2);
17188 food_(&d__1);
17189// FFEINTRIN_impDNINT //
17190 d__1 = d_nint(&d1);
17191 food_(&d__1);
17192// FFEINTRIN_impDPROD //
17193 d__1 = (doublereal) r1 * r2;
17194 food_(&d__1);
17195// FFEINTRIN_impDSIGN //
17196 d__1 = d_sign(&d1, &d2);
17197 food_(&d__1);
17198// FFEINTRIN_impDSIN //
17199 d__1 = sin(d1);
17200 food_(&d__1);
17201// FFEINTRIN_impDSINH //
17202 d__1 = sinh(d1);
17203 food_(&d__1);
17204// FFEINTRIN_impDSQRT //
17205 d__1 = sqrt(d1);
17206 food_(&d__1);
17207// FFEINTRIN_impDTAN //
17208 d__1 = tan(d1);
17209 food_(&d__1);
17210// FFEINTRIN_impDTANH //
17211 d__1 = tanh(d1);
17212 food_(&d__1);
17213// FFEINTRIN_impEXP //
17214 r__1 = exp(r1);
17215 foor_(&r__1);
17216// FFEINTRIN_impIABS //
17217 i__1 = (( i1 ) >= 0 ? ( i1 ) : -( i1 )) ;
17218 fooi_(&i__1);
17219// FFEINTRIN_impICHAR //
17220 i__1 = *(unsigned char *)a1;
17221 fooi_(&i__1);
17222// FFEINTRIN_impIDIM //
17223 i__1 = i_dim(&i1, &i2);
17224 fooi_(&i__1);
17225// FFEINTRIN_impIDNINT //
17226 i__1 = i_dnnt(&d1);
17227 fooi_(&i__1);
17228// FFEINTRIN_impINDEX //
17229 i__1 = i_indx(a1, a2, 10L, 10L);
17230 fooi_(&i__1);
17231// FFEINTRIN_impISIGN //
17232 i__1 = i_sign(&i1, &i2);
17233 fooi_(&i__1);
17234// FFEINTRIN_impLEN //
17235 i__1 = i_len(a1, 10L);
17236 fooi_(&i__1);
17237// FFEINTRIN_impLGE //
17238 L__1 = l_ge(a1, a2, 10L, 10L);
17239 fool_(&L__1);
17240// FFEINTRIN_impLGT //
17241 L__1 = l_gt(a1, a2, 10L, 10L);
17242 fool_(&L__1);
17243// FFEINTRIN_impLLE //
17244 L__1 = l_le(a1, a2, 10L, 10L);
17245 fool_(&L__1);
17246// FFEINTRIN_impLLT //
17247 L__1 = l_lt(a1, a2, 10L, 10L);
17248 fool_(&L__1);
17249// FFEINTRIN_impMAX0 //
17250 i__1 = (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
17251 fooi_(&i__1);
17252// FFEINTRIN_impMAX1 //
17253 i__1 = (integer) (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
17254 fooi_(&i__1);
17255// FFEINTRIN_impMIN0 //
17256 i__1 = (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
17257 fooi_(&i__1);
17258// FFEINTRIN_impMIN1 //
17259 i__1 = (integer) (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
17260 fooi_(&i__1);
17261// FFEINTRIN_impMOD //
17262 i__1 = i1 % i2;
17263 fooi_(&i__1);
17264// FFEINTRIN_impNINT //
17265 i__1 = i_nint(&r1);
17266 fooi_(&i__1);
17267// FFEINTRIN_impSIGN //
17268 r__1 = r_sign(&r1, &r2);
17269 foor_(&r__1);
17270// FFEINTRIN_impSIN //
17271 r__1 = sin(r1);
17272 foor_(&r__1);
17273// FFEINTRIN_impSINH //
17274 r__1 = sinh(r1);
17275 foor_(&r__1);
17276// FFEINTRIN_impSQRT //
17277 r__1 = sqrt(r1);
17278 foor_(&r__1);
17279// FFEINTRIN_impTAN //
17280 r__1 = tan(r1);
17281 foor_(&r__1);
17282// FFEINTRIN_impTANH //
17283 r__1 = tanh(r1);
17284 foor_(&r__1);
17285// FFEINTRIN_imp_CMPLX_C //
17286 r__1 = c1.r;
17287 r__2 = c2.r;
17288 q__1.r = r__1, q__1.i = r__2;
17289 fooc_(&q__1);
17290// FFEINTRIN_imp_CMPLX_D //
17291 z__1.r = d1, z__1.i = d2;
17292 fooz_(&z__1);
17293// FFEINTRIN_imp_CMPLX_I //
17294 r__1 = (real) i1;
17295 r__2 = (real) i2;
17296 q__1.r = r__1, q__1.i = r__2;
17297 fooc_(&q__1);
17298// FFEINTRIN_imp_CMPLX_R //
17299 q__1.r = r1, q__1.i = r2;
17300 fooc_(&q__1);
17301// FFEINTRIN_imp_DBLE_C //
17302 d__1 = (doublereal) c1.r;
17303 food_(&d__1);
17304// FFEINTRIN_imp_DBLE_D //
17305 d__1 = d1;
17306 food_(&d__1);
17307// FFEINTRIN_imp_DBLE_I //
17308 d__1 = (doublereal) i1;
17309 food_(&d__1);
17310// FFEINTRIN_imp_DBLE_R //
17311 d__1 = (doublereal) r1;
17312 food_(&d__1);
17313// FFEINTRIN_imp_INT_C //
17314 i__1 = (integer) c1.r;
17315 fooi_(&i__1);
17316// FFEINTRIN_imp_INT_D //
17317 i__1 = (integer) d1;
17318 fooi_(&i__1);
17319// FFEINTRIN_imp_INT_I //
17320 i__1 = i1;
17321 fooi_(&i__1);
17322// FFEINTRIN_imp_INT_R //
17323 i__1 = (integer) r1;
17324 fooi_(&i__1);
17325// FFEINTRIN_imp_REAL_C //
17326 r__1 = c1.r;
17327 foor_(&r__1);
17328// FFEINTRIN_imp_REAL_D //
17329 r__1 = (real) d1;
17330 foor_(&r__1);
17331// FFEINTRIN_imp_REAL_I //
17332 r__1 = (real) i1;
17333 foor_(&r__1);
17334// FFEINTRIN_imp_REAL_R //
17335 r__1 = r1;
17336 foor_(&r__1);
17337
17338// FFEINTRIN_imp_INT_D: //
17339
17340// FFEINTRIN_specIDINT //
17341 i__1 = (integer) d1;
17342 fooi_(&i__1);
17343
17344// FFEINTRIN_imp_INT_R: //
17345
17346// FFEINTRIN_specIFIX //
17347 i__1 = (integer) r1;
17348 fooi_(&i__1);
17349// FFEINTRIN_specINT //
17350 i__1 = (integer) r1;
17351 fooi_(&i__1);
17352
17353// FFEINTRIN_imp_REAL_D: //
5ff904cd 17354
c7e4ee3a
CB
17355// FFEINTRIN_specSNGL //
17356 r__1 = (real) d1;
17357 foor_(&r__1);
5ff904cd 17358
c7e4ee3a 17359// FFEINTRIN_imp_REAL_I: //
5ff904cd 17360
c7e4ee3a
CB
17361// FFEINTRIN_specFLOAT //
17362 r__1 = (real) i1;
17363 foor_(&r__1);
17364// FFEINTRIN_specREAL //
17365 r__1 = (real) i1;
17366 foor_(&r__1);
5ff904cd 17367
c7e4ee3a 17368} // MAIN__ //
5ff904cd 17369
c7e4ee3a 17370-------- (end output file from f2c)
5ff904cd 17371
c7e4ee3a 17372*/
This page took 2.156801 seconds and 5 git commands to generate.