]> gcc.gnu.org Git - gcc.git/blame - gcc/f/com.c
class.c (finish_vtbls): Copy BINFO_VIRTUALs before using it to intialize a vtable.
[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;
ff852b44
CB
559static int ffecom_typesize_pointer_;
560static int ffecom_typesize_integer1_;
5ff904cd
JL
561
562/* Holds pointer-to-function expressions. */
563
564static tree ffecom_gfrt_[FFECOM_gfrt]
565=
566{
567#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) NULL_TREE,
568#include "com-rt.def"
569#undef DEFGFRT
570};
571
572/* Holds the external names of the functions. */
573
26f096f9 574static const char *ffecom_gfrt_name_[FFECOM_gfrt]
5ff904cd
JL
575=
576{
577#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) NAME,
578#include "com-rt.def"
579#undef DEFGFRT
580};
581
582/* Whether the function returns. */
583
584static bool ffecom_gfrt_volatile_[FFECOM_gfrt]
585=
586{
587#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) VOLATILE,
588#include "com-rt.def"
589#undef DEFGFRT
590};
591
592/* Whether the function returns type complex. */
593
594static bool ffecom_gfrt_complex_[FFECOM_gfrt]
595=
596{
597#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) COMPLEX,
598#include "com-rt.def"
599#undef DEFGFRT
600};
601
602/* Type code for the function return value. */
603
604static ffecomRttype_ ffecom_gfrt_type_[FFECOM_gfrt]
605=
606{
607#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) TYPE,
608#include "com-rt.def"
609#undef DEFGFRT
610};
611
612/* String of codes for the function's arguments. */
613
26f096f9 614static const char *ffecom_gfrt_argstring_[FFECOM_gfrt]
5ff904cd
JL
615=
616{
617#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) ARGS,
618#include "com-rt.def"
619#undef DEFGFRT
620};
621#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
622
623/* Internal macros. */
624
625#if FFECOM_targetCURRENT == FFECOM_targetGCC
626
627/* We let tm.h override the types used here, to handle trivial differences
628 such as the choice of unsigned int or long unsigned int for size_t.
629 When machines start needing nontrivial differences in the size type,
630 it would be best to do something here to figure out automatically
631 from other information what type to use. */
632
ff852b44
CB
633#ifndef SIZE_TYPE
634#define SIZE_TYPE "long unsigned int"
635#endif
5ff904cd 636
5ff904cd
JL
637#define ffecom_concat_list_count_(catlist) ((catlist).count)
638#define ffecom_concat_list_expr_(catlist,i) ((catlist).exprs[(i)])
639#define ffecom_concat_list_maxlen_(catlist) ((catlist).maxlen)
640#define ffecom_concat_list_minlen_(catlist) ((catlist).minlen)
641
86fc7a6c
CB
642#define ffecom_char_args_(i,l,e) ffecom_char_args_x_((i),(l),(e),FALSE)
643#define ffecom_char_args_with_null_(i,l,e) ffecom_char_args_x_((i),(l),(e),TRUE)
644
5ff904cd
JL
645/* For each binding contour we allocate a binding_level structure
646 * which records the names defined in that contour.
647 * Contours include:
648 * 0) the global one
649 * 1) one for each function definition,
650 * where internal declarations of the parameters appear.
651 *
652 * The current meaning of a name can be found by searching the levels from
653 * the current one out to the global one.
654 */
655
656/* Note that the information in the `names' component of the global contour
657 is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
658
659struct binding_level
660 {
c7e4ee3a
CB
661 /* A chain of _DECL nodes for all variables, constants, functions,
662 and typedef types. These are in the reverse of the order supplied.
663 */
5ff904cd
JL
664 tree names;
665
c7e4ee3a
CB
666 /* For each level (except not the global one),
667 a chain of BLOCK nodes for all the levels
668 that were entered and exited one level down. */
5ff904cd
JL
669 tree blocks;
670
c7e4ee3a
CB
671 /* The BLOCK node for this level, if one has been preallocated.
672 If 0, the BLOCK is allocated (if needed) when the level is popped. */
5ff904cd
JL
673 tree this_block;
674
675 /* The binding level which this one is contained in (inherits from). */
676 struct binding_level *level_chain;
c7e4ee3a
CB
677
678 /* 0: no ffecom_prepare_* functions called at this level yet;
679 1: ffecom_prepare* functions called, except not ffecom_prepare_end;
680 2: ffecom_prepare_end called. */
681 int prep_state;
5ff904cd
JL
682 };
683
684#define NULL_BINDING_LEVEL (struct binding_level *) NULL
685
686/* The binding level currently in effect. */
687
688static struct binding_level *current_binding_level;
689
690/* A chain of binding_level structures awaiting reuse. */
691
692static struct binding_level *free_binding_level;
693
694/* The outermost binding level, for names of file scope.
695 This is created when the compiler is started and exists
696 through the entire run. */
697
698static struct binding_level *global_binding_level;
699
700/* Binding level structures are initialized by copying this one. */
701
702static struct binding_level clear_binding_level
703=
c7e4ee3a 704{NULL, NULL, NULL, NULL_BINDING_LEVEL, 0};
5ff904cd
JL
705
706/* Language-dependent contents of an identifier. */
707
708struct lang_identifier
709 {
710 struct tree_identifier ignore;
711 tree global_value, local_value, label_value;
712 bool invented;
713 };
714
715/* Macros for access to language-specific slots in an identifier. */
716/* Each of these slots contains a DECL node or null. */
717
718/* This represents the value which the identifier has in the
719 file-scope namespace. */
720#define IDENTIFIER_GLOBAL_VALUE(NODE) \
721 (((struct lang_identifier *)(NODE))->global_value)
722/* This represents the value which the identifier has in the current
723 scope. */
724#define IDENTIFIER_LOCAL_VALUE(NODE) \
725 (((struct lang_identifier *)(NODE))->local_value)
726/* This represents the value which the identifier has as a label in
727 the current label scope. */
728#define IDENTIFIER_LABEL_VALUE(NODE) \
729 (((struct lang_identifier *)(NODE))->label_value)
730/* This is nonzero if the identifier was "made up" by g77 code. */
731#define IDENTIFIER_INVENTED(NODE) \
732 (((struct lang_identifier *)(NODE))->invented)
733
734/* In identifiers, C uses the following fields in a special way:
735 TREE_PUBLIC to record that there was a previous local extern decl.
736 TREE_USED to record that such a decl was used.
737 TREE_ADDRESSABLE to record that the address of such a decl was used. */
738
739/* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
740 that have names. Here so we can clear out their names' definitions
741 at the end of the function. */
742
743static tree named_labels;
744
745/* A list of LABEL_DECLs from outer contexts that are currently shadowed. */
746
747static tree shadowed_labels;
748
749#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
750\f
6b55276e
CB
751/* Return the subscript expression, modified to do range-checking.
752
753 `array' is the array to be checked against.
754 `element' is the subscript expression to check.
755 `dim' is the dimension number (starting at 0).
756 `total_dims' is the total number of dimensions (0 for CHARACTER substring).
757*/
758
759static tree
760ffecom_subscript_check_ (tree array, tree element, int dim, int total_dims,
761 char *array_name)
762{
763 tree low = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
764 tree high = TYPE_MAX_VALUE (TYPE_DOMAIN (array));
765 tree cond;
766 tree die;
767 tree args;
768
769 if (element == error_mark_node)
770 return element;
771
ff852b44
CB
772 if (TREE_TYPE (low) != TREE_TYPE (element))
773 {
774 if (TYPE_PRECISION (TREE_TYPE (low))
775 > TYPE_PRECISION (TREE_TYPE (element)))
776 element = convert (TREE_TYPE (low), element);
777 else
778 {
779 low = convert (TREE_TYPE (element), low);
780 if (high)
781 high = convert (TREE_TYPE (element), high);
782 }
783 }
784
6b55276e
CB
785 element = ffecom_save_tree (element);
786 cond = ffecom_2 (LE_EXPR, integer_type_node,
787 low,
788 element);
789 if (high)
790 {
791 cond = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
792 cond,
793 ffecom_2 (LE_EXPR, integer_type_node,
794 element,
795 high));
796 }
797
798 {
799 int len;
800 char *proc;
801 char *var;
802 tree arg3;
803 tree arg2;
804 tree arg1;
805 tree arg4;
806
807 switch (total_dims)
808 {
809 case 0:
810 var = xmalloc (strlen (array_name) + 20);
811 sprintf (&var[0], "%s[%s-substring]",
812 array_name,
813 dim ? "end" : "start");
814 len = strlen (var) + 1;
815 break;
816
817 case 1:
818 len = strlen (array_name) + 1;
819 var = array_name;
820 break;
821
822 default:
823 var = xmalloc (strlen (array_name) + 40);
824 sprintf (&var[0], "%s[subscript-%d-of-%d]",
825 array_name,
826 dim + 1, total_dims);
827 len = strlen (var) + 1;
828 break;
829 }
830
831 arg1 = build_string (len, var);
832
833 if (total_dims != 1)
834 free (var);
835
836 TREE_TYPE (arg1)
837 = build_type_variant (build_array_type (char_type_node,
838 build_range_type
839 (integer_type_node,
840 integer_one_node,
841 build_int_2 (len, 0))),
842 1, 0);
843 TREE_CONSTANT (arg1) = 1;
844 TREE_STATIC (arg1) = 1;
845 arg1 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg1)),
846 arg1);
847
848 /* s_rnge adds one to the element to print it, so bias against
849 that -- want to print a faithful *subscript* value. */
850 arg2 = convert (ffecom_f2c_ftnint_type_node,
851 ffecom_2 (MINUS_EXPR,
852 TREE_TYPE (element),
853 element,
854 convert (TREE_TYPE (element),
855 integer_one_node)));
856
857 proc = xmalloc ((len = strlen (input_filename)
858 + IDENTIFIER_LENGTH (DECL_NAME (current_function_decl))
859 + 2));
860
861 sprintf (&proc[0], "%s/%s",
862 input_filename,
863 IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
864 arg3 = build_string (len, proc);
865
866 free (proc);
867
868 TREE_TYPE (arg3)
869 = build_type_variant (build_array_type (char_type_node,
870 build_range_type
871 (integer_type_node,
872 integer_one_node,
873 build_int_2 (len, 0))),
874 1, 0);
875 TREE_CONSTANT (arg3) = 1;
876 TREE_STATIC (arg3) = 1;
877 arg3 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg3)),
878 arg3);
879
880 arg4 = convert (ffecom_f2c_ftnint_type_node,
881 build_int_2 (lineno, 0));
882
883 arg1 = build_tree_list (NULL_TREE, arg1);
884 arg2 = build_tree_list (NULL_TREE, arg2);
885 arg3 = build_tree_list (NULL_TREE, arg3);
886 arg4 = build_tree_list (NULL_TREE, arg4);
887 TREE_CHAIN (arg3) = arg4;
888 TREE_CHAIN (arg2) = arg3;
889 TREE_CHAIN (arg1) = arg2;
890
891 args = arg1;
892 }
893 die = ffecom_call_gfrt (FFECOM_gfrtRANGE,
894 args, NULL_TREE);
895 TREE_SIDE_EFFECTS (die) = 1;
896
897 element = ffecom_3 (COND_EXPR,
898 TREE_TYPE (element),
899 cond,
900 element,
901 die);
902
903 return element;
904}
905
906/* Return the computed element of an array reference.
907
ff852b44
CB
908 `item' is NULL_TREE, or the transformed pointer to the array.
909 `expr' is the original opARRAYREF expression, which is transformed
910 if `item' is NULL_TREE.
911 `want_ptr' is non-zero if a pointer to the element, instead of
6b55276e
CB
912 the element itself, is to be returned. */
913
914static tree
915ffecom_arrayref_ (tree item, ffebld expr, int want_ptr)
916{
917 ffebld dims[FFECOM_dimensionsMAX];
918 int i;
919 int total_dims;
ff852b44
CB
920 int flatten = ffe_is_flatten_arrays ();
921 int need_ptr;
6b55276e
CB
922 tree array;
923 tree element;
ff852b44
CB
924 tree tree_type;
925 tree tree_type_x;
6b55276e 926 char *array_name;
ff852b44
CB
927 ffetype type;
928 ffebld list;
6b55276e
CB
929
930 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER)
931 array_name = ffesymbol_text (ffebld_symter (ffebld_left (expr)));
932 else
933 array_name = "[expr?]";
934
935 /* Build up ARRAY_REFs in reverse order (since we're column major
936 here in Fortran land). */
937
ff852b44
CB
938 for (i = 0, list = ffebld_right (expr);
939 list != NULL;
940 ++i, list = ffebld_trail (list))
941 {
942 dims[i] = ffebld_head (list);
943 type = ffeinfo_type (ffebld_basictype (dims[i]),
944 ffebld_kindtype (dims[i]));
945 if (! flatten
946 && ffecom_typesize_pointer_ > ffecom_typesize_integer1_
947 && ffetype_size (type) > ffecom_typesize_integer1_)
948 /* E.g. ARRAY(INDEX), given INTEGER*8 INDEX, on a system with 64-bit
949 pointers and 32-bit integers. Do the full 64-bit pointer
950 arithmetic, for codes using arrays for nonstandard heap-like
951 work. */
952 flatten = 1;
953 }
6b55276e
CB
954
955 total_dims = i;
956
ff852b44
CB
957 need_ptr = want_ptr || flatten;
958
959 if (! item)
960 {
961 if (need_ptr)
962 item = ffecom_ptr_to_expr (ffebld_left (expr));
963 else
964 item = ffecom_expr (ffebld_left (expr));
965
966 if (item == error_mark_node)
967 return item;
968
969 if (ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereFLEETING
970 && ! mark_addressable (item))
971 return error_mark_node;
972 }
973
974 if (item == error_mark_node)
975 return item;
976
6b55276e
CB
977 if (need_ptr)
978 {
ff852b44
CB
979 tree min;
980
6b55276e
CB
981 for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
982 i >= 0;
983 --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
984 {
ff852b44
CB
985 min = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
986 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
6b55276e
CB
987 if (ffe_is_subscript_check ())
988 element = ffecom_subscript_check_ (array, element, i, total_dims,
989 array_name);
ff852b44
CB
990 if (element == error_mark_node)
991 return element;
992
993 /* Widen integral arithmetic as desired while preserving
994 signedness. */
995 tree_type = TREE_TYPE (element);
996 tree_type_x = tree_type;
997 if (tree_type
998 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
999 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
1000 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
1001
1002 if (TREE_TYPE (min) != tree_type_x)
1003 min = convert (tree_type_x, min);
1004 if (TREE_TYPE (element) != tree_type_x)
1005 element = convert (tree_type_x, element);
1006
6b55276e
CB
1007 item = ffecom_2 (PLUS_EXPR,
1008 build_pointer_type (TREE_TYPE (array)),
1009 item,
1010 size_binop (MULT_EXPR,
1011 size_in_bytes (TREE_TYPE (array)),
ff852b44
CB
1012 fold (build (MINUS_EXPR,
1013 tree_type_x,
1014 element,
1015 min))));
6b55276e
CB
1016 }
1017 if (! want_ptr)
1018 {
1019 item = ffecom_1 (INDIRECT_REF,
1020 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
1021 item);
1022 }
1023 }
1024 else
1025 {
1026 for (--i;
1027 i >= 0;
1028 --i)
1029 {
1030 array = TYPE_MAIN_VARIANT (TREE_TYPE (item));
1031
1032 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
1033 if (ffe_is_subscript_check ())
1034 element = ffecom_subscript_check_ (array, element, i, total_dims,
1035 array_name);
ff852b44
CB
1036 if (element == error_mark_node)
1037 return element;
1038
1039 /* Widen integral arithmetic as desired while preserving
1040 signedness. */
1041 tree_type = TREE_TYPE (element);
1042 tree_type_x = tree_type;
1043 if (tree_type
1044 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
1045 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
1046 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
1047
1048 element = convert (tree_type_x, element);
1049
6b55276e
CB
1050 item = ffecom_2 (ARRAY_REF,
1051 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
1052 item,
1053 element);
1054 }
1055 }
1056
1057 return item;
1058}
1059
5ff904cd
JL
1060/* This is like gcc's stabilize_reference -- in fact, most of the code
1061 comes from that -- but it handles the situation where the reference
1062 is going to have its subparts picked at, and it shouldn't change
1063 (or trigger extra invocations of functions in the subtrees) due to
1064 this. save_expr is a bit overzealous, because we don't need the
1065 entire thing calculated and saved like a temp. So, for DECLs, no
1066 change is needed, because these are stable aggregates, and ARRAY_REF
1067 and such might well be stable too, but for things like calculations,
1068 we do need to calculate a snapshot of a value before picking at it. */
1069
1070#if FFECOM_targetCURRENT == FFECOM_targetGCC
1071static tree
1072ffecom_stabilize_aggregate_ (tree ref)
1073{
1074 tree result;
1075 enum tree_code code = TREE_CODE (ref);
1076
1077 switch (code)
1078 {
1079 case VAR_DECL:
1080 case PARM_DECL:
1081 case RESULT_DECL:
1082 /* No action is needed in this case. */
1083 return ref;
1084
1085 case NOP_EXPR:
1086 case CONVERT_EXPR:
1087 case FLOAT_EXPR:
1088 case FIX_TRUNC_EXPR:
1089 case FIX_FLOOR_EXPR:
1090 case FIX_ROUND_EXPR:
1091 case FIX_CEIL_EXPR:
1092 result = build_nt (code, stabilize_reference (TREE_OPERAND (ref, 0)));
1093 break;
1094
1095 case INDIRECT_REF:
1096 result = build_nt (INDIRECT_REF,
1097 stabilize_reference_1 (TREE_OPERAND (ref, 0)));
1098 break;
1099
1100 case COMPONENT_REF:
1101 result = build_nt (COMPONENT_REF,
1102 stabilize_reference (TREE_OPERAND (ref, 0)),
1103 TREE_OPERAND (ref, 1));
1104 break;
1105
1106 case BIT_FIELD_REF:
1107 result = build_nt (BIT_FIELD_REF,
1108 stabilize_reference (TREE_OPERAND (ref, 0)),
1109 stabilize_reference_1 (TREE_OPERAND (ref, 1)),
1110 stabilize_reference_1 (TREE_OPERAND (ref, 2)));
1111 break;
1112
1113 case ARRAY_REF:
1114 result = build_nt (ARRAY_REF,
1115 stabilize_reference (TREE_OPERAND (ref, 0)),
1116 stabilize_reference_1 (TREE_OPERAND (ref, 1)));
1117 break;
1118
1119 case COMPOUND_EXPR:
1120 result = build_nt (COMPOUND_EXPR,
1121 stabilize_reference_1 (TREE_OPERAND (ref, 0)),
1122 stabilize_reference (TREE_OPERAND (ref, 1)));
1123 break;
1124
1125 case RTL_EXPR:
1126 result = build1 (INDIRECT_REF, TREE_TYPE (ref),
1127 save_expr (build1 (ADDR_EXPR,
1128 build_pointer_type (TREE_TYPE (ref)),
1129 ref)));
1130 break;
1131
1132
1133 default:
1134 return save_expr (ref);
1135
1136 case ERROR_MARK:
1137 return error_mark_node;
1138 }
1139
1140 TREE_TYPE (result) = TREE_TYPE (ref);
1141 TREE_READONLY (result) = TREE_READONLY (ref);
1142 TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (ref);
1143 TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (ref);
1144 TREE_RAISES (result) = TREE_RAISES (ref);
1145
1146 return result;
1147}
1148#endif
1149
1150/* A rip-off of gcc's convert.c convert_to_complex function,
1151 reworked to handle complex implemented as C structures
1152 (RECORD_TYPE with two fields, real and imaginary `r' and `i'). */
1153
1154#if FFECOM_targetCURRENT == FFECOM_targetGCC
1155static tree
1156ffecom_convert_to_complex_ (tree type, tree expr)
1157{
1158 register enum tree_code form = TREE_CODE (TREE_TYPE (expr));
1159 tree subtype;
1160
1161 assert (TREE_CODE (type) == RECORD_TYPE);
1162
1163 subtype = TREE_TYPE (TYPE_FIELDS (type));
1164
1165 if (form == REAL_TYPE || form == INTEGER_TYPE || form == ENUMERAL_TYPE)
1166 {
1167 expr = convert (subtype, expr);
1168 return ffecom_2 (COMPLEX_EXPR, type, expr,
1169 convert (subtype, integer_zero_node));
1170 }
1171
1172 if (form == RECORD_TYPE)
1173 {
1174 tree elt_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr)));
1175 if (TYPE_MAIN_VARIANT (elt_type) == TYPE_MAIN_VARIANT (subtype))
1176 return expr;
1177 else
1178 {
1179 expr = save_expr (expr);
1180 return ffecom_2 (COMPLEX_EXPR,
1181 type,
1182 convert (subtype,
1183 ffecom_1 (REALPART_EXPR,
1184 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1185 expr)),
1186 convert (subtype,
1187 ffecom_1 (IMAGPART_EXPR,
1188 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1189 expr)));
1190 }
1191 }
1192
1193 if (form == POINTER_TYPE || form == REFERENCE_TYPE)
1194 error ("pointer value used where a complex was expected");
1195 else
1196 error ("aggregate value used where a complex was expected");
1197
1198 return ffecom_2 (COMPLEX_EXPR, type,
1199 convert (subtype, integer_zero_node),
1200 convert (subtype, integer_zero_node));
1201}
1202#endif
1203
1204/* Like gcc's convert(), but crashes if widening might happen. */
1205
1206#if FFECOM_targetCURRENT == FFECOM_targetGCC
1207static tree
1208ffecom_convert_narrow_ (type, expr)
1209 tree type, expr;
1210{
1211 register tree e = expr;
1212 register enum tree_code code = TREE_CODE (type);
1213
1214 if (type == TREE_TYPE (e)
1215 || TREE_CODE (e) == ERROR_MARK)
1216 return e;
1217 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1218 return fold (build1 (NOP_EXPR, type, e));
1219 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1220 || code == ERROR_MARK)
1221 return error_mark_node;
1222 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1223 {
1224 assert ("void value not ignored as it ought to be" == NULL);
1225 return error_mark_node;
1226 }
1227 assert (code != VOID_TYPE);
1228 if ((code != RECORD_TYPE)
1229 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1230 assert ("converting COMPLEX to REAL" == NULL);
1231 assert (code != ENUMERAL_TYPE);
1232 if (code == INTEGER_TYPE)
1233 {
a74de6ea
CB
1234 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1235 && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)))
1236 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1237 && (TYPE_PRECISION (type)
1238 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
5ff904cd
JL
1239 return fold (convert_to_integer (type, e));
1240 }
1241 if (code == POINTER_TYPE)
1242 {
1243 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1244 return fold (convert_to_pointer (type, e));
1245 }
1246 if (code == REAL_TYPE)
1247 {
1248 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1249 assert (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)));
1250 return fold (convert_to_real (type, e));
1251 }
1252 if (code == COMPLEX_TYPE)
1253 {
1254 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1255 assert (TYPE_PRECISION (TREE_TYPE (type)) <= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1256 return fold (convert_to_complex (type, e));
1257 }
1258 if (code == RECORD_TYPE)
1259 {
1260 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
270fc4e8
CB
1261 /* Check that at least the first field name agrees. */
1262 assert (DECL_NAME (TYPE_FIELDS (type))
1263 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
5ff904cd
JL
1264 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1265 <= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
270fc4e8
CB
1266 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1267 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1268 return e;
5ff904cd
JL
1269 return fold (ffecom_convert_to_complex_ (type, e));
1270 }
1271
1272 assert ("conversion to non-scalar type requested" == NULL);
1273 return error_mark_node;
1274}
1275#endif
1276
1277/* Like gcc's convert(), but crashes if narrowing might happen. */
1278
1279#if FFECOM_targetCURRENT == FFECOM_targetGCC
1280static tree
1281ffecom_convert_widen_ (type, expr)
1282 tree type, expr;
1283{
1284 register tree e = expr;
1285 register enum tree_code code = TREE_CODE (type);
1286
1287 if (type == TREE_TYPE (e)
1288 || TREE_CODE (e) == ERROR_MARK)
1289 return e;
1290 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1291 return fold (build1 (NOP_EXPR, type, e));
1292 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1293 || code == ERROR_MARK)
1294 return error_mark_node;
1295 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1296 {
1297 assert ("void value not ignored as it ought to be" == NULL);
1298 return error_mark_node;
1299 }
1300 assert (code != VOID_TYPE);
1301 if ((code != RECORD_TYPE)
1302 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1303 assert ("narrowing COMPLEX to REAL" == NULL);
1304 assert (code != ENUMERAL_TYPE);
1305 if (code == INTEGER_TYPE)
1306 {
a74de6ea
CB
1307 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1308 && TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)))
1309 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1310 && (TYPE_PRECISION (type)
1311 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
5ff904cd
JL
1312 return fold (convert_to_integer (type, e));
1313 }
1314 if (code == POINTER_TYPE)
1315 {
1316 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1317 return fold (convert_to_pointer (type, e));
1318 }
1319 if (code == REAL_TYPE)
1320 {
1321 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1322 assert (TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)));
1323 return fold (convert_to_real (type, e));
1324 }
1325 if (code == COMPLEX_TYPE)
1326 {
1327 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1328 assert (TYPE_PRECISION (TREE_TYPE (type)) >= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1329 return fold (convert_to_complex (type, e));
1330 }
1331 if (code == RECORD_TYPE)
1332 {
1333 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
270fc4e8
CB
1334 /* Check that at least the first field name agrees. */
1335 assert (DECL_NAME (TYPE_FIELDS (type))
1336 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
5ff904cd
JL
1337 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1338 >= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
270fc4e8
CB
1339 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1340 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1341 return e;
5ff904cd
JL
1342 return fold (ffecom_convert_to_complex_ (type, e));
1343 }
1344
1345 assert ("conversion to non-scalar type requested" == NULL);
1346 return error_mark_node;
1347}
1348#endif
1349
1350/* Handles making a COMPLEX type, either the standard
1351 (but buggy?) gbe way, or the safer (but less elegant?)
1352 f2c way. */
1353
1354#if FFECOM_targetCURRENT == FFECOM_targetGCC
1355static tree
1356ffecom_make_complex_type_ (tree subtype)
1357{
1358 tree type;
1359 tree realfield;
1360 tree imagfield;
1361
1362 if (ffe_is_emulate_complex ())
1363 {
1364 type = make_node (RECORD_TYPE);
1365 realfield = ffecom_decl_field (type, NULL_TREE, "r", subtype);
1366 imagfield = ffecom_decl_field (type, realfield, "i", subtype);
1367 TYPE_FIELDS (type) = realfield;
1368 layout_type (type);
1369 }
1370 else
1371 {
1372 type = make_node (COMPLEX_TYPE);
1373 TREE_TYPE (type) = subtype;
1374 layout_type (type);
1375 }
1376
1377 return type;
1378}
1379#endif
1380
1381/* Chooses either the gbe or the f2c way to build a
1382 complex constant. */
1383
1384#if FFECOM_targetCURRENT == FFECOM_targetGCC
1385static tree
1386ffecom_build_complex_constant_ (tree type, tree realpart, tree imagpart)
1387{
1388 tree bothparts;
1389
1390 if (ffe_is_emulate_complex ())
1391 {
1392 bothparts = build_tree_list (TYPE_FIELDS (type), realpart);
1393 TREE_CHAIN (bothparts) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), imagpart);
1394 bothparts = build (CONSTRUCTOR, type, NULL_TREE, bothparts);
1395 }
1396 else
1397 {
1398 bothparts = build_complex (type, realpart, imagpart);
1399 }
1400
1401 return bothparts;
1402}
1403#endif
1404
1405#if FFECOM_targetCURRENT == FFECOM_targetGCC
1406static tree
26f096f9 1407ffecom_arglist_expr_ (const char *c, ffebld expr)
5ff904cd
JL
1408{
1409 tree list;
1410 tree *plist = &list;
1411 tree trail = NULL_TREE; /* Append char length args here. */
1412 tree *ptrail = &trail;
1413 tree length;
1414 ffebld exprh;
1415 tree item;
1416 bool ptr = FALSE;
1417 tree wanted = NULL_TREE;
e2fa159e
JL
1418 static char zed[] = "0";
1419
1420 if (c == NULL)
1421 c = &zed[0];
5ff904cd
JL
1422
1423 while (expr != NULL)
1424 {
1425 if (*c != '\0')
1426 {
1427 ptr = FALSE;
1428 if (*c == '&')
1429 {
1430 ptr = TRUE;
1431 ++c;
1432 }
1433 switch (*(c++))
1434 {
1435 case '\0':
1436 ptr = TRUE;
1437 wanted = NULL_TREE;
1438 break;
1439
1440 case 'a':
1441 assert (ptr);
1442 wanted = NULL_TREE;
1443 break;
1444
1445 case 'c':
1446 wanted = ffecom_f2c_complex_type_node;
1447 break;
1448
1449 case 'd':
1450 wanted = ffecom_f2c_doublereal_type_node;
1451 break;
1452
1453 case 'e':
1454 wanted = ffecom_f2c_doublecomplex_type_node;
1455 break;
1456
1457 case 'f':
1458 wanted = ffecom_f2c_real_type_node;
1459 break;
1460
1461 case 'i':
1462 wanted = ffecom_f2c_integer_type_node;
1463 break;
1464
1465 case 'j':
1466 wanted = ffecom_f2c_longint_type_node;
1467 break;
1468
1469 default:
1470 assert ("bad argstring code" == NULL);
1471 wanted = NULL_TREE;
1472 break;
1473 }
1474 }
1475
1476 exprh = ffebld_head (expr);
1477 if (exprh == NULL)
1478 wanted = NULL_TREE;
1479
1480 if ((wanted == NULL_TREE)
1481 || (ptr
1482 && (TYPE_MODE
1483 (ffecom_tree_type[ffeinfo_basictype (ffebld_info (exprh))]
1484 [ffeinfo_kindtype (ffebld_info (exprh))])
1485 == TYPE_MODE (wanted))))
1486 *plist
1487 = build_tree_list (NULL_TREE,
1488 ffecom_arg_ptr_to_expr (exprh,
1489 &length));
1490 else
1491 {
1492 item = ffecom_arg_expr (exprh, &length);
1493 item = ffecom_convert_widen_ (wanted, item);
1494 if (ptr)
1495 {
1496 item = ffecom_1 (ADDR_EXPR,
1497 build_pointer_type (TREE_TYPE (item)),
1498 item);
1499 }
1500 *plist
1501 = build_tree_list (NULL_TREE,
1502 item);
1503 }
1504
1505 plist = &TREE_CHAIN (*plist);
1506 expr = ffebld_trail (expr);
1507 if (length != NULL_TREE)
1508 {
1509 *ptrail = build_tree_list (NULL_TREE, length);
1510 ptrail = &TREE_CHAIN (*ptrail);
1511 }
1512 }
1513
e2fa159e
JL
1514 /* We've run out of args in the call; if the implementation expects
1515 more, supply null pointers for them, which the implementation can
1516 check to see if an arg was omitted. */
1517
1518 while (*c != '\0' && *c != '0')
1519 {
1520 if (*c == '&')
1521 ++c;
1522 else
1523 assert ("missing arg to run-time routine!" == NULL);
1524
1525 switch (*(c++))
1526 {
1527 case '\0':
1528 case 'a':
1529 case 'c':
1530 case 'd':
1531 case 'e':
1532 case 'f':
1533 case 'i':
1534 case 'j':
1535 break;
1536
1537 default:
1538 assert ("bad arg string code" == NULL);
1539 break;
1540 }
1541 *plist
1542 = build_tree_list (NULL_TREE,
1543 null_pointer_node);
1544 plist = &TREE_CHAIN (*plist);
1545 }
1546
5ff904cd
JL
1547 *plist = trail;
1548
1549 return list;
1550}
1551#endif
1552
1553#if FFECOM_targetCURRENT == FFECOM_targetGCC
1554static tree
1555ffecom_widest_expr_type_ (ffebld list)
1556{
1557 ffebld item;
1558 ffebld widest = NULL;
1559 ffetype type;
1560 ffetype widest_type = NULL;
1561 tree t;
1562
1563 for (; list != NULL; list = ffebld_trail (list))
1564 {
1565 item = ffebld_head (list);
1566 if (item == NULL)
1567 continue;
1568 if ((widest != NULL)
1569 && (ffeinfo_basictype (ffebld_info (item))
1570 != ffeinfo_basictype (ffebld_info (widest))))
1571 continue;
1572 type = ffeinfo_type (ffeinfo_basictype (ffebld_info (item)),
1573 ffeinfo_kindtype (ffebld_info (item)));
1574 if ((widest == FFEINFO_kindtypeNONE)
1575 || (ffetype_size (type)
1576 > ffetype_size (widest_type)))
1577 {
1578 widest = item;
1579 widest_type = type;
1580 }
1581 }
1582
1583 assert (widest != NULL);
1584 t = ffecom_tree_type[ffeinfo_basictype (ffebld_info (widest))]
1585 [ffeinfo_kindtype (ffebld_info (widest))];
1586 assert (t != NULL_TREE);
1587 return t;
1588}
1589#endif
1590
d6cd84e0
CB
1591/* Check whether a partial overlap between two expressions is possible.
1592
1593 Can *starting* to write a portion of expr1 change the value
1594 computed (perhaps already, *partially*) by expr2?
1595
1596 Currently, this is a concern only for a COMPLEX expr1. But if it
1597 isn't in COMMON or local EQUIVALENCE, since we don't support
1598 aliasing of arguments, it isn't a concern. */
1599
1600static bool
1601ffecom_possible_partial_overlap_ (ffebld expr1, ffebld expr2)
1602{
1603 ffesymbol sym;
1604 ffestorag st;
1605
1606 switch (ffebld_op (expr1))
1607 {
1608 case FFEBLD_opSYMTER:
1609 sym = ffebld_symter (expr1);
1610 break;
1611
1612 case FFEBLD_opARRAYREF:
1613 if (ffebld_op (ffebld_left (expr1)) != FFEBLD_opSYMTER)
1614 return FALSE;
1615 sym = ffebld_symter (ffebld_left (expr1));
1616 break;
1617
1618 default:
1619 return FALSE;
1620 }
1621
1622 if (ffesymbol_where (sym) != FFEINFO_whereCOMMON
1623 && (ffesymbol_where (sym) != FFEINFO_whereLOCAL
1624 || ! (st = ffesymbol_storage (sym))
1625 || ! ffestorag_parent (st)))
1626 return FALSE;
1627
1628 /* It's in COMMON or local EQUIVALENCE. */
1629
1630 return TRUE;
1631}
1632
5ff904cd
JL
1633/* Check whether dest and source might overlap. ffebld versions of these
1634 might or might not be passed, will be NULL if not.
1635
1636 The test is really whether source_tree is modifiable and, if modified,
1637 might overlap destination such that the value(s) in the destination might
1638 change before it is finally modified. dest_* are the canonized
1639 destination itself. */
1640
1641#if FFECOM_targetCURRENT == FFECOM_targetGCC
1642static bool
1643ffecom_overlap_ (tree dest_decl, tree dest_offset, tree dest_size,
1644 tree source_tree, ffebld source UNUSED,
1645 bool scalar_arg)
1646{
1647 tree source_decl;
1648 tree source_offset;
1649 tree source_size;
1650 tree t;
1651
1652 if (source_tree == NULL_TREE)
1653 return FALSE;
1654
1655 switch (TREE_CODE (source_tree))
1656 {
1657 case ERROR_MARK:
1658 case IDENTIFIER_NODE:
1659 case INTEGER_CST:
1660 case REAL_CST:
1661 case COMPLEX_CST:
1662 case STRING_CST:
1663 case CONST_DECL:
1664 case VAR_DECL:
1665 case RESULT_DECL:
1666 case FIELD_DECL:
1667 case MINUS_EXPR:
1668 case MULT_EXPR:
1669 case TRUNC_DIV_EXPR:
1670 case CEIL_DIV_EXPR:
1671 case FLOOR_DIV_EXPR:
1672 case ROUND_DIV_EXPR:
1673 case TRUNC_MOD_EXPR:
1674 case CEIL_MOD_EXPR:
1675 case FLOOR_MOD_EXPR:
1676 case ROUND_MOD_EXPR:
1677 case RDIV_EXPR:
1678 case EXACT_DIV_EXPR:
1679 case FIX_TRUNC_EXPR:
1680 case FIX_CEIL_EXPR:
1681 case FIX_FLOOR_EXPR:
1682 case FIX_ROUND_EXPR:
1683 case FLOAT_EXPR:
1684 case EXPON_EXPR:
1685 case NEGATE_EXPR:
1686 case MIN_EXPR:
1687 case MAX_EXPR:
1688 case ABS_EXPR:
1689 case FFS_EXPR:
1690 case LSHIFT_EXPR:
1691 case RSHIFT_EXPR:
1692 case LROTATE_EXPR:
1693 case RROTATE_EXPR:
1694 case BIT_IOR_EXPR:
1695 case BIT_XOR_EXPR:
1696 case BIT_AND_EXPR:
1697 case BIT_ANDTC_EXPR:
1698 case BIT_NOT_EXPR:
1699 case TRUTH_ANDIF_EXPR:
1700 case TRUTH_ORIF_EXPR:
1701 case TRUTH_AND_EXPR:
1702 case TRUTH_OR_EXPR:
1703 case TRUTH_XOR_EXPR:
1704 case TRUTH_NOT_EXPR:
1705 case LT_EXPR:
1706 case LE_EXPR:
1707 case GT_EXPR:
1708 case GE_EXPR:
1709 case EQ_EXPR:
1710 case NE_EXPR:
1711 case COMPLEX_EXPR:
1712 case CONJ_EXPR:
1713 case REALPART_EXPR:
1714 case IMAGPART_EXPR:
1715 case LABEL_EXPR:
1716 case COMPONENT_REF:
1717 return FALSE;
1718
1719 case COMPOUND_EXPR:
1720 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1721 TREE_OPERAND (source_tree, 1), NULL,
1722 scalar_arg);
1723
1724 case MODIFY_EXPR:
1725 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1726 TREE_OPERAND (source_tree, 0), NULL,
1727 scalar_arg);
1728
1729 case CONVERT_EXPR:
1730 case NOP_EXPR:
1731 case NON_LVALUE_EXPR:
1732 case PLUS_EXPR:
1733 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1734 return TRUE;
1735
1736 ffecom_tree_canonize_ptr_ (&source_decl, &source_offset,
1737 source_tree);
1738 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1739 break;
1740
1741 case COND_EXPR:
1742 return
1743 ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1744 TREE_OPERAND (source_tree, 1), NULL,
1745 scalar_arg)
1746 || ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1747 TREE_OPERAND (source_tree, 2), NULL,
1748 scalar_arg);
1749
1750
1751 case ADDR_EXPR:
1752 ffecom_tree_canonize_ref_ (&source_decl, &source_offset,
1753 &source_size,
1754 TREE_OPERAND (source_tree, 0));
1755 break;
1756
1757 case PARM_DECL:
1758 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1759 return TRUE;
1760
1761 source_decl = source_tree;
1762 source_offset = size_zero_node;
1763 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1764 break;
1765
1766 case SAVE_EXPR:
1767 case REFERENCE_EXPR:
1768 case PREDECREMENT_EXPR:
1769 case PREINCREMENT_EXPR:
1770 case POSTDECREMENT_EXPR:
1771 case POSTINCREMENT_EXPR:
1772 case INDIRECT_REF:
1773 case ARRAY_REF:
1774 case CALL_EXPR:
1775 default:
1776 return TRUE;
1777 }
1778
1779 /* Come here when source_decl, source_offset, and source_size filled
1780 in appropriately. */
1781
1782 if (source_decl == NULL_TREE)
1783 return FALSE; /* No decl involved, so no overlap. */
1784
1785 if (source_decl != dest_decl)
1786 return FALSE; /* Different decl, no overlap. */
1787
1788 if (TREE_CODE (dest_size) == ERROR_MARK)
1789 return TRUE; /* Assignment into entire assumed-size
1790 array? Shouldn't happen.... */
1791
1792 t = ffecom_2 (LE_EXPR, integer_type_node,
1793 ffecom_2 (PLUS_EXPR, TREE_TYPE (dest_offset),
1794 dest_offset,
1795 convert (TREE_TYPE (dest_offset),
1796 dest_size)),
1797 convert (TREE_TYPE (dest_offset),
1798 source_offset));
1799
1800 if (integer_onep (t))
1801 return FALSE; /* Destination precedes source. */
1802
1803 if (!scalar_arg
1804 || (source_size == NULL_TREE)
1805 || (TREE_CODE (source_size) == ERROR_MARK)
1806 || integer_zerop (source_size))
1807 return TRUE; /* No way to tell if dest follows source. */
1808
1809 t = ffecom_2 (LE_EXPR, integer_type_node,
1810 ffecom_2 (PLUS_EXPR, TREE_TYPE (source_offset),
1811 source_offset,
1812 convert (TREE_TYPE (source_offset),
1813 source_size)),
1814 convert (TREE_TYPE (source_offset),
1815 dest_offset));
1816
1817 if (integer_onep (t))
1818 return FALSE; /* Destination follows source. */
1819
1820 return TRUE; /* Destination and source overlap. */
1821}
1822#endif
1823
1824/* Check whether dest might overlap any of a list of arguments or is
1825 in a COMMON area the callee might know about (and thus modify). */
1826
1827#if FFECOM_targetCURRENT == FFECOM_targetGCC
1828static bool
1829ffecom_args_overlapping_ (tree dest_tree, ffebld dest UNUSED,
1830 tree args, tree callee_commons,
1831 bool scalar_args)
1832{
1833 tree arg;
1834 tree dest_decl;
1835 tree dest_offset;
1836 tree dest_size;
1837
1838 ffecom_tree_canonize_ref_ (&dest_decl, &dest_offset, &dest_size,
1839 dest_tree);
1840
1841 if (dest_decl == NULL_TREE)
1842 return FALSE; /* Seems unlikely! */
1843
1844 /* If the decl cannot be determined reliably, or if its in COMMON
1845 and the callee isn't known to not futz with COMMON via other
1846 means, overlap might happen. */
1847
1848 if ((TREE_CODE (dest_decl) == ERROR_MARK)
1849 || ((callee_commons != NULL_TREE)
1850 && TREE_PUBLIC (dest_decl)))
1851 return TRUE;
1852
1853 for (; args != NULL_TREE; args = TREE_CHAIN (args))
1854 {
1855 if (((arg = TREE_VALUE (args)) != NULL_TREE)
1856 && ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1857 arg, NULL, scalar_args))
1858 return TRUE;
1859 }
1860
1861 return FALSE;
1862}
1863#endif
1864
1865/* Build a string for a variable name as used by NAMELIST. This means that
1866 if we're using the f2c library, we build an uppercase string, since
1867 f2c does this. */
1868
1869#if FFECOM_targetCURRENT == FFECOM_targetGCC
1870static tree
26f096f9 1871ffecom_build_f2c_string_ (int i, const char *s)
5ff904cd
JL
1872{
1873 if (!ffe_is_f2c_library ())
1874 return build_string (i, s);
1875
1876 {
1877 char *tmp;
26f096f9 1878 const char *p;
5ff904cd
JL
1879 char *q;
1880 char space[34];
1881 tree t;
1882
1883 if (((size_t) i) > ARRAY_SIZE (space))
1884 tmp = malloc_new_ks (malloc_pool_image (), "f2c_string", i);
1885 else
1886 tmp = &space[0];
1887
1888 for (p = s, q = tmp; *p != '\0'; ++p, ++q)
1889 *q = ffesrc_toupper (*p);
1890 *q = '\0';
1891
1892 t = build_string (i, tmp);
1893
1894 if (((size_t) i) > ARRAY_SIZE (space))
1895 malloc_kill_ks (malloc_pool_image (), tmp, i);
1896
1897 return t;
1898 }
1899}
1900
1901#endif
1902/* Returns CALL_EXPR or equivalent with given type (pass NULL_TREE for
1903 type to just get whatever the function returns), handling the
1904 f2c value-returning convention, if required, by prepending
1905 to the arglist a pointer to a temporary to receive the return value. */
1906
1907#if FFECOM_targetCURRENT == FFECOM_targetGCC
1908static tree
1909ffecom_call_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1910 tree type, tree args, tree dest_tree,
1911 ffebld dest, bool *dest_used, tree callee_commons,
c7e4ee3a 1912 bool scalar_args, tree hook)
5ff904cd
JL
1913{
1914 tree item;
1915 tree tempvar;
1916
1917 if (dest_used != NULL)
1918 *dest_used = FALSE;
1919
1920 if (is_f2c_complex)
1921 {
1922 if ((dest_used == NULL)
1923 || (dest == NULL)
1924 || (ffeinfo_basictype (ffebld_info (dest))
1925 != FFEINFO_basictypeCOMPLEX)
1926 || (ffeinfo_kindtype (ffebld_info (dest)) != kt)
1927 || ((type != NULL_TREE) && (TREE_TYPE (dest_tree) != type))
1928 || ffecom_args_overlapping_ (dest_tree, dest, args,
1929 callee_commons,
1930 scalar_args))
1931 {
c7e4ee3a
CB
1932#ifdef HOHO
1933 tempvar = ffecom_make_tempvar (ffecom_tree_type
5ff904cd
JL
1934 [FFEINFO_basictypeCOMPLEX][kt],
1935 FFETARGET_charactersizeNONE,
c7e4ee3a
CB
1936 -1);
1937#else
1938 tempvar = hook;
1939 assert (tempvar);
1940#endif
5ff904cd
JL
1941 }
1942 else
1943 {
1944 *dest_used = TRUE;
1945 tempvar = dest_tree;
1946 type = NULL_TREE;
1947 }
1948
1949 item
1950 = build_tree_list (NULL_TREE,
1951 ffecom_1 (ADDR_EXPR,
c7e4ee3a 1952 build_pointer_type (TREE_TYPE (tempvar)),
5ff904cd
JL
1953 tempvar));
1954 TREE_CHAIN (item) = args;
1955
1956 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1957 item, NULL_TREE);
1958
1959 if (tempvar != dest_tree)
1960 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item, tempvar);
1961 }
1962 else
1963 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1964 args, NULL_TREE);
1965
1966 if ((type != NULL_TREE) && (TREE_TYPE (item) != type))
1967 item = ffecom_convert_narrow_ (type, item);
1968
1969 return item;
1970}
1971#endif
1972
1973/* Given two arguments, transform them and make a call to the given
1974 function via ffecom_call_. */
1975
1976#if FFECOM_targetCURRENT == FFECOM_targetGCC
1977static tree
1978ffecom_call_binop_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1979 tree type, ffebld left, ffebld right,
1980 tree dest_tree, ffebld dest, bool *dest_used,
c7e4ee3a 1981 tree callee_commons, bool scalar_args, tree hook)
5ff904cd
JL
1982{
1983 tree left_tree;
1984 tree right_tree;
1985 tree left_length;
1986 tree right_length;
1987
5ff904cd
JL
1988 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
1989 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
5ff904cd
JL
1990
1991 left_tree = build_tree_list (NULL_TREE, left_tree);
1992 right_tree = build_tree_list (NULL_TREE, right_tree);
1993 TREE_CHAIN (left_tree) = right_tree;
1994
1995 if (left_length != NULL_TREE)
1996 {
1997 left_length = build_tree_list (NULL_TREE, left_length);
1998 TREE_CHAIN (right_tree) = left_length;
1999 }
2000
2001 if (right_length != NULL_TREE)
2002 {
2003 right_length = build_tree_list (NULL_TREE, right_length);
2004 if (left_length != NULL_TREE)
2005 TREE_CHAIN (left_length) = right_length;
2006 else
2007 TREE_CHAIN (right_tree) = right_length;
2008 }
2009
2010 return ffecom_call_ (fn, kt, is_f2c_complex, type, left_tree,
2011 dest_tree, dest, dest_used, callee_commons,
c7e4ee3a 2012 scalar_args, hook);
5ff904cd
JL
2013}
2014#endif
2015
c7e4ee3a 2016/* Return ptr/length args for char subexpression
5ff904cd
JL
2017
2018 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
2019 subexpressions by constructing the appropriate trees for the ptr-to-
2020 character-text and length-of-character-text arguments in a calling
86fc7a6c
CB
2021 sequence.
2022
2023 Note that if with_null is TRUE, and the expression is an opCONTER,
2024 a null byte is appended to the string. */
5ff904cd
JL
2025
2026#if FFECOM_targetCURRENT == FFECOM_targetGCC
2027static void
86fc7a6c 2028ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
5ff904cd
JL
2029{
2030 tree item;
2031 tree high;
2032 ffetargetCharacter1 val;
86fc7a6c 2033 ffetargetCharacterSize newlen;
5ff904cd
JL
2034
2035 switch (ffebld_op (expr))
2036 {
2037 case FFEBLD_opCONTER:
2038 val = ffebld_constant_character1 (ffebld_conter (expr));
86fc7a6c
CB
2039 newlen = ffetarget_length_character1 (val);
2040 if (with_null)
2041 {
c7e4ee3a 2042 /* Begin FFETARGET-NULL-KLUDGE. */
86fc7a6c 2043 if (newlen != 0)
c7e4ee3a 2044 ++newlen;
86fc7a6c
CB
2045 }
2046 *length = build_int_2 (newlen, 0);
5ff904cd 2047 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
86fc7a6c 2048 high = build_int_2 (newlen, 0);
5ff904cd 2049 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
c7e4ee3a 2050 item = build_string (newlen,
5ff904cd 2051 ffetarget_text_character1 (val));
c7e4ee3a 2052 /* End FFETARGET-NULL-KLUDGE. */
5ff904cd
JL
2053 TREE_TYPE (item)
2054 = build_type_variant
2055 (build_array_type
2056 (char_type_node,
2057 build_range_type
2058 (ffecom_f2c_ftnlen_type_node,
2059 ffecom_f2c_ftnlen_one_node,
2060 high)),
2061 1, 0);
2062 TREE_CONSTANT (item) = 1;
2063 TREE_STATIC (item) = 1;
2064 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
2065 item);
2066 break;
2067
2068 case FFEBLD_opSYMTER:
2069 {
2070 ffesymbol s = ffebld_symter (expr);
2071
2072 item = ffesymbol_hook (s).decl_tree;
2073 if (item == NULL_TREE)
2074 {
2075 s = ffecom_sym_transform_ (s);
2076 item = ffesymbol_hook (s).decl_tree;
2077 }
2078 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
2079 {
2080 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
2081 *length = ffesymbol_hook (s).length_tree;
2082 else
2083 {
2084 *length = build_int_2 (ffesymbol_size (s), 0);
2085 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2086 }
2087 }
2088 else if (item == error_mark_node)
2089 *length = error_mark_node;
c7e4ee3a
CB
2090 else
2091 /* FFEINFO_kindFUNCTION. */
5ff904cd
JL
2092 *length = NULL_TREE;
2093 if (!ffesymbol_hook (s).addr
2094 && (item != error_mark_node))
2095 item = ffecom_1 (ADDR_EXPR,
2096 build_pointer_type (TREE_TYPE (item)),
2097 item);
2098 }
2099 break;
2100
2101 case FFEBLD_opARRAYREF:
2102 {
5ff904cd 2103 ffecom_char_args_ (&item, length, ffebld_left (expr));
5ff904cd
JL
2104
2105 if (item == error_mark_node || *length == error_mark_node)
2106 {
2107 item = *length = error_mark_node;
2108 break;
2109 }
2110
6b55276e 2111 item = ffecom_arrayref_ (item, expr, 1);
5ff904cd
JL
2112 }
2113 break;
2114
2115 case FFEBLD_opSUBSTR:
2116 {
2117 ffebld start;
2118 ffebld end;
2119 ffebld thing = ffebld_right (expr);
2120 tree start_tree;
2121 tree end_tree;
6b55276e
CB
2122 char *char_name;
2123 ffebld left_symter;
2124 tree array;
5ff904cd
JL
2125
2126 assert (ffebld_op (thing) == FFEBLD_opITEM);
2127 start = ffebld_head (thing);
2128 thing = ffebld_trail (thing);
2129 assert (ffebld_trail (thing) == NULL);
2130 end = ffebld_head (thing);
2131
6b55276e
CB
2132 /* Determine name for pretty-printing range-check errors. */
2133 for (left_symter = ffebld_left (expr);
2134 left_symter && ffebld_op (left_symter) == FFEBLD_opARRAYREF;
2135 left_symter = ffebld_left (left_symter))
2136 ;
2137 if (ffebld_op (left_symter) == FFEBLD_opSYMTER)
2138 char_name = ffesymbol_text (ffebld_symter (left_symter));
2139 else
2140 char_name = "[expr?]";
2141
5ff904cd 2142 ffecom_char_args_ (&item, length, ffebld_left (expr));
5ff904cd
JL
2143
2144 if (item == error_mark_node || *length == error_mark_node)
2145 {
2146 item = *length = error_mark_node;
2147 break;
2148 }
2149
6b55276e
CB
2150 array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
2151
ff852b44
CB
2152 /* ~~~~Handle INTEGER*8 start/end, a la FFEBLD_opARRAYREF. */
2153
5ff904cd
JL
2154 if (start == NULL)
2155 {
2156 if (end == NULL)
2157 ;
2158 else
2159 {
6b55276e
CB
2160 end_tree = ffecom_expr (end);
2161 if (ffe_is_subscript_check ())
2162 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2163 char_name);
5ff904cd 2164 end_tree = convert (ffecom_f2c_ftnlen_type_node,
6b55276e 2165 end_tree);
5ff904cd
JL
2166
2167 if (end_tree == error_mark_node)
2168 {
2169 item = *length = error_mark_node;
2170 break;
2171 }
2172
2173 *length = end_tree;
2174 }
2175 }
2176 else
2177 {
6b55276e
CB
2178 start_tree = ffecom_expr (start);
2179 if (ffe_is_subscript_check ())
2180 start_tree = ffecom_subscript_check_ (array, start_tree, 0, 0,
2181 char_name);
5ff904cd 2182 start_tree = convert (ffecom_f2c_ftnlen_type_node,
6b55276e 2183 start_tree);
5ff904cd
JL
2184
2185 if (start_tree == error_mark_node)
2186 {
2187 item = *length = error_mark_node;
2188 break;
2189 }
2190
2191 start_tree = ffecom_save_tree (start_tree);
2192
2193 item = ffecom_2 (PLUS_EXPR, TREE_TYPE (item),
2194 item,
2195 ffecom_2 (MINUS_EXPR,
2196 TREE_TYPE (start_tree),
2197 start_tree,
2198 ffecom_f2c_ftnlen_one_node));
2199
2200 if (end == NULL)
2201 {
2202 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2203 ffecom_f2c_ftnlen_one_node,
2204 ffecom_2 (MINUS_EXPR,
2205 ffecom_f2c_ftnlen_type_node,
2206 *length,
2207 start_tree));
2208 }
2209 else
2210 {
6b55276e
CB
2211 end_tree = ffecom_expr (end);
2212 if (ffe_is_subscript_check ())
2213 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2214 char_name);
5ff904cd 2215 end_tree = convert (ffecom_f2c_ftnlen_type_node,
6b55276e 2216 end_tree);
5ff904cd
JL
2217
2218 if (end_tree == error_mark_node)
2219 {
2220 item = *length = error_mark_node;
2221 break;
2222 }
2223
2224 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2225 ffecom_f2c_ftnlen_one_node,
2226 ffecom_2 (MINUS_EXPR,
2227 ffecom_f2c_ftnlen_type_node,
2228 end_tree, start_tree));
2229 }
2230 }
2231 }
2232 break;
2233
2234 case FFEBLD_opFUNCREF:
2235 {
2236 ffesymbol s = ffebld_symter (ffebld_left (expr));
2237 tree tempvar;
2238 tree args;
2239 ffetargetCharacterSize size = ffeinfo_size (ffebld_info (expr));
2240 ffecomGfrt ix;
2241
2242 if (size == FFETARGET_charactersizeNONE)
c7e4ee3a
CB
2243 /* ~~Kludge alert! This should someday be fixed. */
2244 size = 24;
5ff904cd
JL
2245
2246 *length = build_int_2 (size, 0);
2247 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2248
2249 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
2250 == FFEINFO_whereINTRINSIC)
2251 {
2252 if (size == 1)
c7e4ee3a
CB
2253 {
2254 /* Invocation of an intrinsic returning CHARACTER*1. */
5ff904cd
JL
2255 item = ffecom_expr_intrinsic_ (expr, NULL_TREE,
2256 NULL, NULL);
2257 break;
2258 }
2259 ix = ffeintrin_gfrt_direct (ffebld_symter_implementation (ffebld_left (expr)));
2260 assert (ix != FFECOM_gfrt);
2261 item = ffecom_gfrt_tree_ (ix);
2262 }
2263 else
2264 {
2265 ix = FFECOM_gfrt;
2266 item = ffesymbol_hook (s).decl_tree;
2267 if (item == NULL_TREE)
2268 {
2269 s = ffecom_sym_transform_ (s);
2270 item = ffesymbol_hook (s).decl_tree;
2271 }
2272 if (item == error_mark_node)
2273 {
2274 item = *length = error_mark_node;
2275 break;
2276 }
2277
2278 if (!ffesymbol_hook (s).addr)
2279 item = ffecom_1_fn (item);
2280 }
2281
c7e4ee3a 2282#ifdef HOHO
5ff904cd 2283 tempvar = ffecom_push_tempvar (char_type_node, size, -1, TRUE);
c7e4ee3a
CB
2284#else
2285 tempvar = ffebld_nonter_hook (expr);
2286 assert (tempvar);
2287#endif
5ff904cd
JL
2288 tempvar = ffecom_1 (ADDR_EXPR,
2289 build_pointer_type (TREE_TYPE (tempvar)),
2290 tempvar);
2291
5ff904cd
JL
2292 args = build_tree_list (NULL_TREE, tempvar);
2293
2294 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT) /* Sfunc args by value. */
2295 TREE_CHAIN (args) = ffecom_list_expr (ffebld_right (expr));
2296 else
2297 {
2298 TREE_CHAIN (args) = build_tree_list (NULL_TREE, *length);
2299 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
2300 {
2301 TREE_CHAIN (TREE_CHAIN (args))
2302 = ffecom_arglist_expr_ (ffecom_gfrt_args_ (ix),
2303 ffebld_right (expr));
2304 }
2305 else
2306 {
2307 TREE_CHAIN (TREE_CHAIN (args))
2308 = ffecom_list_ptr_to_expr (ffebld_right (expr));
2309 }
2310 }
2311
2312 item = ffecom_3s (CALL_EXPR,
2313 TREE_TYPE (TREE_TYPE (TREE_TYPE (item))),
2314 item, args, NULL_TREE);
2315 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item,
2316 tempvar);
5ff904cd
JL
2317 }
2318 break;
2319
2320 case FFEBLD_opCONVERT:
2321
5ff904cd 2322 ffecom_char_args_ (&item, length, ffebld_left (expr));
5ff904cd
JL
2323
2324 if (item == error_mark_node || *length == error_mark_node)
2325 {
2326 item = *length = error_mark_node;
2327 break;
2328 }
2329
2330 if ((ffebld_size_known (ffebld_left (expr))
2331 == FFETARGET_charactersizeNONE)
2332 || (ffebld_size_known (ffebld_left (expr)) < (ffebld_size (expr))))
2333 { /* Possible blank-padding needed, copy into
2334 temporary. */
2335 tree tempvar;
2336 tree args;
2337 tree newlen;
2338
c7e4ee3a
CB
2339#ifdef HOHO
2340 tempvar = ffecom_make_tempvar (char_type_node,
2341 ffebld_size (expr), -1);
2342#else
2343 tempvar = ffebld_nonter_hook (expr);
2344 assert (tempvar);
2345#endif
5ff904cd
JL
2346 tempvar = ffecom_1 (ADDR_EXPR,
2347 build_pointer_type (TREE_TYPE (tempvar)),
2348 tempvar);
2349
2350 newlen = build_int_2 (ffebld_size (expr), 0);
2351 TREE_TYPE (newlen) = ffecom_f2c_ftnlen_type_node;
2352
2353 args = build_tree_list (NULL_TREE, tempvar);
2354 TREE_CHAIN (args) = build_tree_list (NULL_TREE, item);
2355 TREE_CHAIN (TREE_CHAIN (args)) = build_tree_list (NULL_TREE, newlen);
2356 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (args)))
2357 = build_tree_list (NULL_TREE, *length);
2358
c7e4ee3a 2359 item = ffecom_call_gfrt (FFECOM_gfrtCOPY, args, NULL_TREE);
5ff904cd
JL
2360 TREE_SIDE_EFFECTS (item) = 1;
2361 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), fold (item),
2362 tempvar);
2363 *length = newlen;
2364 }
2365 else
2366 { /* Just truncate the length. */
2367 *length = build_int_2 (ffebld_size (expr), 0);
2368 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2369 }
2370 break;
2371
2372 default:
2373 assert ("bad op for single char arg expr" == NULL);
2374 item = NULL_TREE;
2375 break;
2376 }
2377
2378 *xitem = item;
2379}
2380#endif
2381
2382/* Check the size of the type to be sure it doesn't overflow the
2383 "portable" capacities of the compiler back end. `dummy' types
2384 can generally overflow the normal sizes as long as the computations
2385 themselves don't overflow. A particular target of the back end
2386 must still enforce its size requirements, though, and the back
2387 end takes care of this in stor-layout.c. */
2388
2389#if FFECOM_targetCURRENT == FFECOM_targetGCC
2390static tree
2391ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy)
2392{
2393 if (TREE_CODE (type) == ERROR_MARK)
2394 return type;
2395
2396 if (TYPE_SIZE (type) == NULL_TREE)
2397 return type;
2398
2399 if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
2400 return type;
2401
2402 if ((tree_int_cst_sgn (TYPE_SIZE (type)) < 0)
2b0c2df0
CB
2403 || (!dummy && (((TREE_INT_CST_HIGH (TYPE_SIZE (type)) != 0))
2404 || TREE_OVERFLOW (TYPE_SIZE (type)))))
5ff904cd
JL
2405 {
2406 ffebad_start (FFEBAD_ARRAY_LARGE);
2407 ffebad_string (ffesymbol_text (s));
2408 ffebad_here (0, ffesymbol_where_line (s), ffesymbol_where_column (s));
2409 ffebad_finish ();
2410
2411 return error_mark_node;
2412 }
2413
2414 return type;
2415}
2416#endif
2417
2418/* Builds a length argument (PARM_DECL). Also wraps type in an array type
2419 where the dimension info is (1:size) where <size> is ffesymbol_size(s) if
2420 known, length_arg if not known (FFETARGET_charactersizeNONE). */
2421
2422#if FFECOM_targetCURRENT == FFECOM_targetGCC
2423static tree
2424ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s)
2425{
2426 ffetargetCharacterSize sz = ffesymbol_size (s);
2427 tree highval;
2428 tree tlen;
2429 tree type = *xtype;
2430
2431 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
2432 tlen = NULL_TREE; /* A statement function, no length passed. */
2433 else
2434 {
2435 if (ffesymbol_where (s) == FFEINFO_whereDUMMY)
2436 tlen = ffecom_get_invented_identifier ("__g77_length_%s",
c7e4ee3a 2437 ffesymbol_text (s), -1);
5ff904cd
JL
2438 else
2439 tlen = ffecom_get_invented_identifier ("__g77_%s",
c7e4ee3a 2440 "length", -1);
5ff904cd
JL
2441 tlen = build_decl (PARM_DECL, tlen, ffecom_f2c_ftnlen_type_node);
2442#if BUILT_FOR_270
2443 DECL_ARTIFICIAL (tlen) = 1;
2444#endif
2445 }
2446
2447 if (sz == FFETARGET_charactersizeNONE)
2448 {
2449 assert (tlen != NULL_TREE);
2b0c2df0 2450 highval = variable_size (tlen);
5ff904cd
JL
2451 }
2452 else
2453 {
2454 highval = build_int_2 (sz, 0);
2455 TREE_TYPE (highval) = ffecom_f2c_ftnlen_type_node;
2456 }
2457
2458 type = build_array_type (type,
2459 build_range_type (ffecom_f2c_ftnlen_type_node,
2460 ffecom_f2c_ftnlen_one_node,
2461 highval));
2462
2463 *xtype = type;
2464 return tlen;
2465}
2466
2467#endif
2468/* ffecom_concat_list_gather_ -- Gather list of concatenated string exprs
2469
2470 ffecomConcatList_ catlist;
2471 ffebld expr; // expr of CHARACTER basictype.
2472 ffetargetCharacterSize max; // max chars to gather or _...NONE if no max
2473 catlist = ffecom_concat_list_gather_(catlist,expr,max);
2474
2475 Scans expr for character subexpressions, updates and returns catlist
2476 accordingly. */
2477
2478#if FFECOM_targetCURRENT == FFECOM_targetGCC
2479static ffecomConcatList_
2480ffecom_concat_list_gather_ (ffecomConcatList_ catlist, ffebld expr,
2481 ffetargetCharacterSize max)
2482{
2483 ffetargetCharacterSize sz;
2484
2485recurse: /* :::::::::::::::::::: */
2486
2487 if (expr == NULL)
2488 return catlist;
2489
2490 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen >= max))
2491 return catlist; /* Don't append any more items. */
2492
2493 switch (ffebld_op (expr))
2494 {
2495 case FFEBLD_opCONTER:
2496 case FFEBLD_opSYMTER:
2497 case FFEBLD_opARRAYREF:
2498 case FFEBLD_opFUNCREF:
2499 case FFEBLD_opSUBSTR:
2500 case FFEBLD_opCONVERT: /* Callers should strip this off beforehand
2501 if they don't need to preserve it. */
2502 if (catlist.count == catlist.max)
2503 { /* Make a (larger) list. */
2504 ffebld *newx;
2505 int newmax;
2506
2507 newmax = (catlist.max == 0) ? 8 : catlist.max * 2;
2508 newx = malloc_new_ks (malloc_pool_image (), "catlist",
2509 newmax * sizeof (newx[0]));
2510 if (catlist.max != 0)
2511 {
2512 memcpy (newx, catlist.exprs, catlist.max * sizeof (newx[0]));
2513 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2514 catlist.max * sizeof (newx[0]));
2515 }
2516 catlist.max = newmax;
2517 catlist.exprs = newx;
2518 }
2519 if ((sz = ffebld_size_known (expr)) != FFETARGET_charactersizeNONE)
2520 catlist.minlen += sz;
2521 else
2522 ++catlist.minlen; /* Not true for F90; can be 0 length. */
2523 if ((sz = ffebld_size_max (expr)) == FFETARGET_charactersizeNONE)
2524 catlist.maxlen = sz;
2525 else
2526 catlist.maxlen += sz;
2527 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen > max))
2528 { /* This item overlaps (or is beyond) the end
2529 of the destination. */
2530 switch (ffebld_op (expr))
2531 {
2532 case FFEBLD_opCONTER:
2533 case FFEBLD_opSYMTER:
2534 case FFEBLD_opARRAYREF:
2535 case FFEBLD_opFUNCREF:
2536 case FFEBLD_opSUBSTR:
c7e4ee3a
CB
2537 /* ~~Do useful truncations here. */
2538 break;
5ff904cd
JL
2539
2540 default:
2541 assert ("op changed or inconsistent switches!" == NULL);
2542 break;
2543 }
2544 }
2545 catlist.exprs[catlist.count++] = expr;
2546 return catlist;
2547
2548 case FFEBLD_opPAREN:
2549 expr = ffebld_left (expr);
2550 goto recurse; /* :::::::::::::::::::: */
2551
2552 case FFEBLD_opCONCATENATE:
2553 catlist = ffecom_concat_list_gather_ (catlist, ffebld_left (expr), max);
2554 expr = ffebld_right (expr);
2555 goto recurse; /* :::::::::::::::::::: */
2556
2557#if 0 /* Breaks passing small actual arg to larger
2558 dummy arg of sfunc */
2559 case FFEBLD_opCONVERT:
2560 expr = ffebld_left (expr);
2561 {
2562 ffetargetCharacterSize cmax;
2563
2564 cmax = catlist.len + ffebld_size_known (expr);
2565
2566 if ((max == FFETARGET_charactersizeNONE) || (max > cmax))
2567 max = cmax;
2568 }
2569 goto recurse; /* :::::::::::::::::::: */
2570#endif
2571
2572 case FFEBLD_opANY:
2573 return catlist;
2574
2575 default:
2576 assert ("bad op in _gather_" == NULL);
2577 return catlist;
2578 }
2579}
2580
2581#endif
2582/* ffecom_concat_list_kill_ -- Kill list of concatenated string exprs
2583
2584 ffecomConcatList_ catlist;
2585 ffecom_concat_list_kill_(catlist);
2586
2587 Anything allocated within the list info is deallocated. */
2588
2589#if FFECOM_targetCURRENT == FFECOM_targetGCC
2590static void
2591ffecom_concat_list_kill_ (ffecomConcatList_ catlist)
2592{
2593 if (catlist.max != 0)
2594 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2595 catlist.max * sizeof (catlist.exprs[0]));
2596}
2597
2598#endif
c7e4ee3a 2599/* Make list of concatenated string exprs.
5ff904cd
JL
2600
2601 Returns a flattened list of concatenated subexpressions given a
2602 tree of such expressions. */
2603
2604#if FFECOM_targetCURRENT == FFECOM_targetGCC
2605static ffecomConcatList_
2606ffecom_concat_list_new_ (ffebld expr, ffetargetCharacterSize max)
2607{
2608 ffecomConcatList_ catlist;
2609
2610 catlist.maxlen = catlist.minlen = catlist.max = catlist.count = 0;
2611 return ffecom_concat_list_gather_ (catlist, expr, max);
2612}
2613
2614#endif
2615
2616/* Provide some kind of useful info on member of aggregate area,
2617 since current g77/gcc technology does not provide debug info
2618 on these members. */
2619
2620#if FFECOM_targetCURRENT == FFECOM_targetGCC
2621static void
26f096f9 2622ffecom_debug_kludge_ (tree aggr, const char *aggr_type, ffesymbol member,
5ff904cd
JL
2623 tree member_type UNUSED, ffetargetOffset offset)
2624{
2625 tree value;
2626 tree decl;
2627 int len;
2628 char *buff;
2629 char space[120];
2630#if 0
2631 tree type_id;
2632
2633 for (type_id = member_type;
2634 TREE_CODE (type_id) != IDENTIFIER_NODE;
2635 )
2636 {
2637 switch (TREE_CODE (type_id))
2638 {
2639 case INTEGER_TYPE:
2640 case REAL_TYPE:
2641 type_id = TYPE_NAME (type_id);
2642 break;
2643
2644 case ARRAY_TYPE:
2645 case COMPLEX_TYPE:
2646 type_id = TREE_TYPE (type_id);
2647 break;
2648
2649 default:
2650 assert ("no IDENTIFIER_NODE for type!" == NULL);
2651 type_id = error_mark_node;
2652 break;
2653 }
2654 }
2655#endif
2656
2657 if (ffecom_transform_only_dummies_
2658 || !ffe_is_debug_kludge ())
2659 return; /* Can't do this yet, maybe later. */
2660
2661 len = 60
2662 + strlen (aggr_type)
2663 + IDENTIFIER_LENGTH (DECL_NAME (aggr));
2664#if 0
2665 + IDENTIFIER_LENGTH (type_id);
2666#endif
2667
2668 if (((size_t) len) >= ARRAY_SIZE (space))
2669 buff = malloc_new_ks (malloc_pool_image (), "debug_kludge", len + 1);
2670 else
2671 buff = &space[0];
2672
2673 sprintf (&buff[0], "At (%s) `%s' plus %ld bytes",
2674 aggr_type,
2675 IDENTIFIER_POINTER (DECL_NAME (aggr)),
2676 (long int) offset);
2677
2678 value = build_string (len, buff);
2679 TREE_TYPE (value)
2680 = build_type_variant (build_array_type (char_type_node,
2681 build_range_type
2682 (integer_type_node,
2683 integer_one_node,
2684 build_int_2 (strlen (buff), 0))),
2685 1, 0);
2686 decl = build_decl (VAR_DECL,
2687 ffecom_get_identifier_ (ffesymbol_text (member)),
2688 TREE_TYPE (value));
2689 TREE_CONSTANT (decl) = 1;
2690 TREE_STATIC (decl) = 1;
2691 DECL_INITIAL (decl) = error_mark_node;
2692 DECL_IN_SYSTEM_HEADER (decl) = 1; /* Don't let -Wunused complain. */
2693 decl = start_decl (decl, FALSE);
2694 finish_decl (decl, value, FALSE);
2695
2696 if (buff != &space[0])
2697 malloc_kill_ks (malloc_pool_image (), buff, len + 1);
2698}
2699#endif
2700
2701/* ffecom_do_entry_ -- Do compilation of a particular entrypoint
2702
2703 ffesymbol fn; // the SUBROUTINE, FUNCTION, or ENTRY symbol itself
2704 int i; // entry# for this entrypoint (used by master fn)
2705 ffecom_do_entrypoint_(s,i);
2706
2707 Makes a public entry point that calls our private master fn (already
2708 compiled). */
2709
2710#if FFECOM_targetCURRENT == FFECOM_targetGCC
2711static void
2712ffecom_do_entry_ (ffesymbol fn, int entrynum)
2713{
2714 ffebld item;
2715 tree type; /* Type of function. */
2716 tree multi_retval; /* Var holding return value (union). */
2717 tree result; /* Var holding result. */
2718 ffeinfoBasictype bt;
2719 ffeinfoKindtype kt;
2720 ffeglobal g;
2721 ffeglobalType gt;
2722 bool charfunc; /* All entry points return same type
2723 CHARACTER. */
2724 bool cmplxfunc; /* Use f2c way of returning COMPLEX. */
2725 bool multi; /* Master fn has multiple return types. */
2726 bool altreturning = FALSE; /* This entry point has alternate returns. */
2727 int yes;
44d2eabc
JL
2728 int old_lineno = lineno;
2729 char *old_input_filename = input_filename;
2730
2731 input_filename = ffesymbol_where_filename (fn);
2732 lineno = ffesymbol_where_filelinenum (fn);
5ff904cd
JL
2733
2734 /* c-parse.y indeed does call suspend_momentary and not only ignores the
2735 return value, but also never calls resume_momentary, when starting an
2736 outer function (see "fndef:", "setspecs:", and so on). So g77 does the
2737 same thing. It shouldn't be a problem since start_function calls
2738 temporary_allocation, but it might be necessary. If it causes a problem
2739 here, then maybe there's a bug lurking in gcc. NOTE: This identical
2740 comment appears twice in thist file. */
2741
2742 suspend_momentary ();
2743
2744 ffecom_doing_entry_ = TRUE; /* Don't bother with array dimensions. */
2745
2746 switch (ffecom_primary_entry_kind_)
2747 {
2748 case FFEINFO_kindFUNCTION:
2749
2750 /* Determine actual return type for function. */
2751
2752 gt = FFEGLOBAL_typeFUNC;
2753 bt = ffesymbol_basictype (fn);
2754 kt = ffesymbol_kindtype (fn);
2755 if (bt == FFEINFO_basictypeNONE)
2756 {
2757 ffeimplic_establish_symbol (fn);
2758 if (ffesymbol_funcresult (fn) != NULL)
2759 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
2760 bt = ffesymbol_basictype (fn);
2761 kt = ffesymbol_kindtype (fn);
2762 }
2763
2764 if (bt == FFEINFO_basictypeCHARACTER)
2765 charfunc = TRUE, cmplxfunc = FALSE;
2766 else if ((bt == FFEINFO_basictypeCOMPLEX)
2767 && ffesymbol_is_f2c (fn))
2768 charfunc = FALSE, cmplxfunc = TRUE;
2769 else
2770 charfunc = cmplxfunc = FALSE;
2771
2772 if (charfunc)
2773 type = ffecom_tree_fun_type_void;
2774 else if (ffesymbol_is_f2c (fn))
2775 type = ffecom_tree_fun_type[bt][kt];
2776 else
2777 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
2778
2779 if ((type == NULL_TREE)
2780 || (TREE_TYPE (type) == NULL_TREE))
2781 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
2782
2783 multi = (ffecom_master_bt_ == FFEINFO_basictypeNONE);
2784 break;
2785
2786 case FFEINFO_kindSUBROUTINE:
2787 gt = FFEGLOBAL_typeSUBR;
2788 bt = FFEINFO_basictypeNONE;
2789 kt = FFEINFO_kindtypeNONE;
2790 if (ffecom_is_altreturning_)
2791 { /* Am _I_ altreturning? */
2792 for (item = ffesymbol_dummyargs (fn);
2793 item != NULL;
2794 item = ffebld_trail (item))
2795 {
2796 if (ffebld_op (ffebld_head (item)) == FFEBLD_opSTAR)
2797 {
2798 altreturning = TRUE;
2799 break;
2800 }
2801 }
2802 if (altreturning)
2803 type = ffecom_tree_subr_type;
2804 else
2805 type = ffecom_tree_fun_type_void;
2806 }
2807 else
2808 type = ffecom_tree_fun_type_void;
2809 charfunc = FALSE;
2810 cmplxfunc = FALSE;
2811 multi = FALSE;
2812 break;
2813
2814 default:
2815 assert ("say what??" == NULL);
2816 /* Fall through. */
2817 case FFEINFO_kindANY:
2818 gt = FFEGLOBAL_typeANY;
2819 bt = FFEINFO_basictypeNONE;
2820 kt = FFEINFO_kindtypeNONE;
2821 type = error_mark_node;
2822 charfunc = FALSE;
2823 cmplxfunc = FALSE;
2824 multi = FALSE;
2825 break;
2826 }
2827
2828 /* build_decl uses the current lineno and input_filename to set the decl
2829 source info. So, I've putzed with ffestd and ffeste code to update that
2830 source info to point to the appropriate statement just before calling
2831 ffecom_do_entrypoint (which calls this fn). */
2832
2833 start_function (ffecom_get_external_identifier_ (fn),
2834 type,
2835 0, /* nested/inline */
2836 1); /* TREE_PUBLIC */
2837
2838 if (((g = ffesymbol_global (fn)) != NULL)
2839 && ((ffeglobal_type (g) == gt)
2840 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
2841 {
2842 ffeglobal_set_hook (g, current_function_decl);
2843 }
2844
2845 /* Reset args in master arg list so they get retransitioned. */
2846
2847 for (item = ffecom_master_arglist_;
2848 item != NULL;
2849 item = ffebld_trail (item))
2850 {
2851 ffebld arg;
2852 ffesymbol s;
2853
2854 arg = ffebld_head (item);
2855 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2856 continue; /* Alternate return or some such thing. */
2857 s = ffebld_symter (arg);
2858 ffesymbol_hook (s).decl_tree = NULL_TREE;
2859 ffesymbol_hook (s).length_tree = NULL_TREE;
2860 }
2861
2862 /* Build dummy arg list for this entry point. */
2863
2864 yes = suspend_momentary ();
2865
2866 if (charfunc || cmplxfunc)
2867 { /* Prepend arg for where result goes. */
2868 tree type;
2869 tree length;
2870
2871 if (charfunc)
2872 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
2873 else
2874 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
2875
2876 result = ffecom_get_invented_identifier ("__g77_%s",
c7e4ee3a 2877 "result", -1);
5ff904cd
JL
2878
2879 /* Make length arg _and_ enhance type info for CHAR arg itself. */
2880
2881 if (charfunc)
2882 length = ffecom_char_enhance_arg_ (&type, fn);
2883 else
2884 length = NULL_TREE; /* Not ref'd if !charfunc. */
2885
2886 type = build_pointer_type (type);
2887 result = build_decl (PARM_DECL, result, type);
2888
2889 push_parm_decl (result);
2890 ffecom_func_result_ = result;
2891
2892 if (charfunc)
2893 {
2894 push_parm_decl (length);
2895 ffecom_func_length_ = length;
2896 }
2897 }
2898 else
2899 result = DECL_RESULT (current_function_decl);
2900
2901 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (fn), FALSE);
2902
2903 resume_momentary (yes);
2904
2905 store_parm_decls (0);
2906
c7e4ee3a
CB
2907 ffecom_start_compstmt ();
2908 /* Disallow temp vars at this level. */
2909 current_binding_level->prep_state = 2;
5ff904cd
JL
2910
2911 /* Make local var to hold return type for multi-type master fn. */
2912
2913 if (multi)
2914 {
2915 yes = suspend_momentary ();
2916
2917 multi_retval = ffecom_get_invented_identifier ("__g77_%s",
c7e4ee3a 2918 "multi_retval", -1);
5ff904cd
JL
2919 multi_retval = build_decl (VAR_DECL, multi_retval,
2920 ffecom_multi_type_node_);
2921 multi_retval = start_decl (multi_retval, FALSE);
2922 finish_decl (multi_retval, NULL_TREE, FALSE);
2923
2924 resume_momentary (yes);
2925 }
2926 else
2927 multi_retval = NULL_TREE; /* Not actually ref'd if !multi. */
2928
2929 /* Here we emit the actual code for the entry point. */
2930
2931 {
2932 ffebld list;
2933 ffebld arg;
2934 ffesymbol s;
2935 tree arglist = NULL_TREE;
2936 tree *plist = &arglist;
2937 tree prepend;
2938 tree call;
2939 tree actarg;
2940 tree master_fn;
2941
2942 /* Prepare actual arg list based on master arg list. */
2943
2944 for (list = ffecom_master_arglist_;
2945 list != NULL;
2946 list = ffebld_trail (list))
2947 {
2948 arg = ffebld_head (list);
2949 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2950 continue;
2951 s = ffebld_symter (arg);
702edf1d
CB
2952 if (ffesymbol_hook (s).decl_tree == NULL_TREE
2953 || ffesymbol_hook (s).decl_tree == error_mark_node)
5ff904cd
JL
2954 actarg = null_pointer_node; /* We don't have this arg. */
2955 else
2956 actarg = ffesymbol_hook (s).decl_tree;
2957 *plist = build_tree_list (NULL_TREE, actarg);
2958 plist = &TREE_CHAIN (*plist);
2959 }
2960
2961 /* This code appends the length arguments for character
2962 variables/arrays. */
2963
2964 for (list = ffecom_master_arglist_;
2965 list != NULL;
2966 list = ffebld_trail (list))
2967 {
2968 arg = ffebld_head (list);
2969 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2970 continue;
2971 s = ffebld_symter (arg);
2972 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
2973 continue; /* Only looking for CHARACTER arguments. */
2974 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
2975 continue; /* Only looking for variables and arrays. */
702edf1d
CB
2976 if (ffesymbol_hook (s).length_tree == NULL_TREE
2977 || ffesymbol_hook (s).length_tree == error_mark_node)
5ff904cd
JL
2978 actarg = ffecom_f2c_ftnlen_zero_node; /* We don't have this arg. */
2979 else
2980 actarg = ffesymbol_hook (s).length_tree;
2981 *plist = build_tree_list (NULL_TREE, actarg);
2982 plist = &TREE_CHAIN (*plist);
2983 }
2984
2985 /* Prepend character-value return info to actual arg list. */
2986
2987 if (charfunc)
2988 {
2989 prepend = build_tree_list (NULL_TREE, ffecom_func_result_);
2990 TREE_CHAIN (prepend)
2991 = build_tree_list (NULL_TREE, ffecom_func_length_);
2992 TREE_CHAIN (TREE_CHAIN (prepend)) = arglist;
2993 arglist = prepend;
2994 }
2995
2996 /* Prepend multi-type return value to actual arg list. */
2997
2998 if (multi)
2999 {
3000 prepend
3001 = build_tree_list (NULL_TREE,
3002 ffecom_1 (ADDR_EXPR,
3003 build_pointer_type (TREE_TYPE (multi_retval)),
3004 multi_retval));
3005 TREE_CHAIN (prepend) = arglist;
3006 arglist = prepend;
3007 }
3008
3009 /* Prepend my entry-point number to the actual arg list. */
3010
3011 prepend = build_tree_list (NULL_TREE, build_int_2 (entrynum, 0));
3012 TREE_CHAIN (prepend) = arglist;
3013 arglist = prepend;
3014
3015 /* Build the call to the master function. */
3016
3017 master_fn = ffecom_1_fn (ffecom_previous_function_decl_);
3018 call = ffecom_3s (CALL_EXPR,
3019 TREE_TYPE (TREE_TYPE (TREE_TYPE (master_fn))),
3020 master_fn, arglist, NULL_TREE);
3021
3022 /* Decide whether the master function is a function or subroutine, and
3023 handle the return value for my entry point. */
3024
3025 if (charfunc || ((ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
3026 && !altreturning))
3027 {
3028 expand_expr_stmt (call);
3029 expand_null_return ();
3030 }
3031 else if (multi && cmplxfunc)
3032 {
3033 expand_expr_stmt (call);
3034 result
3035 = ffecom_1 (INDIRECT_REF,
3036 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
3037 result);
3038 result = ffecom_modify (NULL_TREE, result,
3039 ffecom_2 (COMPONENT_REF, TREE_TYPE (result),
3040 multi_retval,
3041 ffecom_multi_fields_[bt][kt]));
3042 expand_expr_stmt (result);
3043 expand_null_return ();
3044 }
3045 else if (multi)
3046 {
3047 expand_expr_stmt (call);
3048 result
3049 = ffecom_modify (NULL_TREE, result,
3050 convert (TREE_TYPE (result),
3051 ffecom_2 (COMPONENT_REF,
3052 ffecom_tree_type[bt][kt],
3053 multi_retval,
3054 ffecom_multi_fields_[bt][kt])));
3055 expand_return (result);
3056 }
3057 else if (cmplxfunc)
3058 {
3059 result
3060 = ffecom_1 (INDIRECT_REF,
3061 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
3062 result);
3063 result = ffecom_modify (NULL_TREE, result, call);
3064 expand_expr_stmt (result);
3065 expand_null_return ();
3066 }
3067 else
3068 {
3069 result = ffecom_modify (NULL_TREE,
3070 result,
3071 convert (TREE_TYPE (result),
3072 call));
3073 expand_return (result);
3074 }
3075
3076 clear_momentary ();
3077 }
3078
c7e4ee3a 3079 ffecom_end_compstmt ();
5ff904cd
JL
3080
3081 finish_function (0);
3082
44d2eabc
JL
3083 lineno = old_lineno;
3084 input_filename = old_input_filename;
3085
5ff904cd
JL
3086 ffecom_doing_entry_ = FALSE;
3087}
3088
3089#endif
3090/* Transform expr into gcc tree with possible destination
3091
3092 Recursive descent on expr while making corresponding tree nodes and
3093 attaching type info and such. If destination supplied and compatible
3094 with temporary that would be made in certain cases, temporary isn't
092a4ef8 3095 made, destination used instead, and dest_used flag set TRUE. */
5ff904cd
JL
3096
3097#if FFECOM_targetCURRENT == FFECOM_targetGCC
3098static tree
092a4ef8
RH
3099ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
3100 bool *dest_used, bool assignp, bool widenp)
5ff904cd
JL
3101{
3102 tree item;
3103 tree list;
3104 tree args;
3105 ffeinfoBasictype bt;
3106 ffeinfoKindtype kt;
3107 tree t;
5ff904cd 3108 tree dt; /* decl_tree for an ffesymbol. */
092a4ef8 3109 tree tree_type, tree_type_x;
af752698 3110 tree left, right;
5ff904cd
JL
3111 ffesymbol s;
3112 enum tree_code code;
3113
3114 assert (expr != NULL);
3115
3116 if (dest_used != NULL)
3117 *dest_used = FALSE;
3118
3119 bt = ffeinfo_basictype (ffebld_info (expr));
3120 kt = ffeinfo_kindtype (ffebld_info (expr));
af752698 3121 tree_type = ffecom_tree_type[bt][kt];
5ff904cd 3122
092a4ef8
RH
3123 /* Widen integral arithmetic as desired while preserving signedness. */
3124 tree_type_x = NULL_TREE;
3125 if (widenp && tree_type
3126 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
3127 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
3128 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
3129
5ff904cd
JL
3130 switch (ffebld_op (expr))
3131 {
3132 case FFEBLD_opACCTER:
5ff904cd
JL
3133 {
3134 ffebitCount i;
3135 ffebit bits = ffebld_accter_bits (expr);
3136 ffetargetOffset source_offset = 0;
a6fa6420 3137 ffetargetOffset dest_offset = ffebld_accter_pad (expr);
5ff904cd
JL
3138 tree purpose;
3139
a6fa6420
CB
3140 assert (dest_offset == 0
3141 || (bt == FFEINFO_basictypeCHARACTER
3142 && kt == FFEINFO_kindtypeCHARACTER1));
5ff904cd
JL
3143
3144 list = item = NULL;
3145 for (;;)
3146 {
3147 ffebldConstantUnion cu;
3148 ffebitCount length;
3149 bool value;
3150 ffebldConstantArray ca = ffebld_accter (expr);
3151
3152 ffebit_test (bits, source_offset, &value, &length);
3153 if (length == 0)
3154 break;
3155
3156 if (value)
3157 {
3158 for (i = 0; i < length; ++i)
3159 {
3160 cu = ffebld_constantarray_get (ca, bt, kt,
3161 source_offset + i);
3162
3163 t = ffecom_constantunion (&cu, bt, kt, tree_type);
3164
a6fa6420
CB
3165 if (i == 0
3166 && dest_offset != 0)
3167 purpose = build_int_2 (dest_offset, 0);
5ff904cd
JL
3168 else
3169 purpose = NULL_TREE;
3170
3171 if (list == NULL_TREE)
3172 list = item = build_tree_list (purpose, t);
3173 else
3174 {
3175 TREE_CHAIN (item) = build_tree_list (purpose, t);
3176 item = TREE_CHAIN (item);
3177 }
3178 }
3179 }
3180 source_offset += length;
a6fa6420 3181 dest_offset += length;
5ff904cd
JL
3182 }
3183 }
3184
a6fa6420
CB
3185 item = build_int_2 ((ffebld_accter_size (expr)
3186 + ffebld_accter_pad (expr)) - 1, 0);
5ff904cd
JL
3187 ffebit_kill (ffebld_accter_bits (expr));
3188 TREE_TYPE (item) = ffecom_integer_type_node;
3189 item
3190 = build_array_type
3191 (tree_type,
3192 build_range_type (ffecom_integer_type_node,
3193 ffecom_integer_zero_node,
3194 item));
3195 list = build (CONSTRUCTOR, item, NULL_TREE, list);
3196 TREE_CONSTANT (list) = 1;
3197 TREE_STATIC (list) = 1;
3198 return list;
3199
3200 case FFEBLD_opARRTER:
5ff904cd
JL
3201 {
3202 ffetargetOffset i;
3203
a6fa6420
CB
3204 list = NULL_TREE;
3205 if (ffebld_arrter_pad (expr) == 0)
3206 item = NULL_TREE;
3207 else
3208 {
3209 assert (bt == FFEINFO_basictypeCHARACTER
3210 && kt == FFEINFO_kindtypeCHARACTER1);
3211
3212 /* Becomes PURPOSE first time through loop. */
3213 item = build_int_2 (ffebld_arrter_pad (expr), 0);
3214 }
3215
5ff904cd
JL
3216 for (i = 0; i < ffebld_arrter_size (expr); ++i)
3217 {
3218 ffebldConstantUnion cu
3219 = ffebld_constantarray_get (ffebld_arrter (expr), bt, kt, i);
3220
3221 t = ffecom_constantunion (&cu, bt, kt, tree_type);
3222
3223 if (list == NULL_TREE)
a6fa6420
CB
3224 /* Assume item is PURPOSE first time through loop. */
3225 list = item = build_tree_list (item, t);
5ff904cd
JL
3226 else
3227 {
3228 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
3229 item = TREE_CHAIN (item);
3230 }
3231 }
3232 }
3233
a6fa6420
CB
3234 item = build_int_2 ((ffebld_arrter_size (expr)
3235 + ffebld_arrter_pad (expr)) - 1, 0);
5ff904cd
JL
3236 TREE_TYPE (item) = ffecom_integer_type_node;
3237 item
3238 = build_array_type
3239 (tree_type,
3240 build_range_type (ffecom_integer_type_node,
a6fa6420 3241 ffecom_integer_zero_node,
5ff904cd
JL
3242 item));
3243 list = build (CONSTRUCTOR, item, NULL_TREE, list);
3244 TREE_CONSTANT (list) = 1;
3245 TREE_STATIC (list) = 1;
3246 return list;
3247
3248 case FFEBLD_opCONTER:
c264f113 3249 assert (ffebld_conter_pad (expr) == 0);
5ff904cd
JL
3250 item
3251 = ffecom_constantunion (&ffebld_constant_union (ffebld_conter (expr)),
3252 bt, kt, tree_type);
3253 return item;
3254
3255 case FFEBLD_opSYMTER:
3256 if ((ffebld_symter_generic (expr) != FFEINTRIN_genNONE)
3257 || (ffebld_symter_specific (expr) != FFEINTRIN_specNONE))
3258 return ffecom_ptr_to_expr (expr); /* Same as %REF(intrinsic). */
3259 s = ffebld_symter (expr);
3260 t = ffesymbol_hook (s).decl_tree;
3261
3262 if (assignp)
3263 { /* ASSIGN'ed-label expr. */
3264 if (ffe_is_ugly_assign ())
3265 {
3266 /* User explicitly wants ASSIGN'ed variables to be at the same
3267 memory address as the variables when used in non-ASSIGN
3268 contexts. That can make old, arcane, non-standard code
3269 work, but don't try to do it when a pointer wouldn't fit
3270 in the normal variable (take other approach, and warn,
3271 instead). */
3272
3273 if (t == NULL_TREE)
3274 {
3275 s = ffecom_sym_transform_ (s);
3276 t = ffesymbol_hook (s).decl_tree;
3277 assert (t != NULL_TREE);
3278 }
3279
3280 if (t == error_mark_node)
3281 return t;
3282
3283 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (t)))
3284 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
3285 {
3286 if (ffesymbol_hook (s).addr)
3287 t = ffecom_1 (INDIRECT_REF,
3288 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3289 return t;
3290 }
3291
3292 if (ffesymbol_hook (s).assign_tree == NULL_TREE)
3293 {
3294 ffebad_start_msg ("ASSIGN'ed label cannot fit into `%A' at %0 -- using wider sibling",
3295 FFEBAD_severityWARNING);
3296 ffebad_string (ffesymbol_text (s));
3297 ffebad_here (0, ffesymbol_where_line (s),
3298 ffesymbol_where_column (s));
3299 ffebad_finish ();
3300 }
3301 }
3302
3303 /* Don't use the normal variable's tree for ASSIGN, though mark
3304 it as in the system header (housekeeping). Use an explicit,
3305 specially created sibling that is known to be wide enough
3306 to hold pointers to labels. */
3307
3308 if (t != NULL_TREE
3309 && TREE_CODE (t) == VAR_DECL)
3310 DECL_IN_SYSTEM_HEADER (t) = 1; /* Don't let -Wunused complain. */
3311
3312 t = ffesymbol_hook (s).assign_tree;
3313 if (t == NULL_TREE)
3314 {
3315 s = ffecom_sym_transform_assign_ (s);
3316 t = ffesymbol_hook (s).assign_tree;
3317 assert (t != NULL_TREE);
3318 }
3319 }
3320 else
3321 {
3322 if (t == NULL_TREE)
3323 {
3324 s = ffecom_sym_transform_ (s);
3325 t = ffesymbol_hook (s).decl_tree;
3326 assert (t != NULL_TREE);
3327 }
3328 if (ffesymbol_hook (s).addr)
3329 t = ffecom_1 (INDIRECT_REF,
3330 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3331 }
3332 return t;
3333
3334 case FFEBLD_opARRAYREF:
ff852b44 3335 return ffecom_arrayref_ (NULL_TREE, expr, 0);
5ff904cd
JL
3336
3337 case FFEBLD_opUPLUS:
092a4ef8 3338 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
af752698 3339 return ffecom_1 (NOP_EXPR, tree_type, left);
5ff904cd 3340
c7e4ee3a
CB
3341 case FFEBLD_opPAREN:
3342 /* ~~~Make sure Fortran rules respected here */
092a4ef8 3343 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
af752698 3344 return ffecom_1 (NOP_EXPR, tree_type, left);
5ff904cd
JL
3345
3346 case FFEBLD_opUMINUS:
092a4ef8 3347 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3348 if (tree_type_x)
3349 {
3350 tree_type = tree_type_x;
3351 left = convert (tree_type, left);
3352 }
3353 return ffecom_1 (NEGATE_EXPR, tree_type, left);
5ff904cd
JL
3354
3355 case FFEBLD_opADD:
092a4ef8
RH
3356 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3357 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3358 if (tree_type_x)
3359 {
3360 tree_type = tree_type_x;
3361 left = convert (tree_type, left);
3362 right = convert (tree_type, right);
3363 }
3364 return ffecom_2 (PLUS_EXPR, tree_type, left, right);
5ff904cd
JL
3365
3366 case FFEBLD_opSUBTRACT:
092a4ef8
RH
3367 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3368 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3369 if (tree_type_x)
3370 {
3371 tree_type = tree_type_x;
3372 left = convert (tree_type, left);
3373 right = convert (tree_type, right);
3374 }
3375 return ffecom_2 (MINUS_EXPR, tree_type, left, right);
5ff904cd
JL
3376
3377 case FFEBLD_opMULTIPLY:
092a4ef8
RH
3378 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3379 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3380 if (tree_type_x)
3381 {
3382 tree_type = tree_type_x;
3383 left = convert (tree_type, left);
3384 right = convert (tree_type, right);
3385 }
3386 return ffecom_2 (MULT_EXPR, tree_type, left, right);
5ff904cd
JL
3387
3388 case FFEBLD_opDIVIDE:
092a4ef8
RH
3389 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3390 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3391 if (tree_type_x)
3392 {
3393 tree_type = tree_type_x;
3394 left = convert (tree_type, left);
3395 right = convert (tree_type, right);
3396 }
3397 return ffecom_tree_divide_ (tree_type, left, right,
c7e4ee3a
CB
3398 dest_tree, dest, dest_used,
3399 ffebld_nonter_hook (expr));
5ff904cd
JL
3400
3401 case FFEBLD_opPOWER:
5ff904cd
JL
3402 {
3403 ffebld left = ffebld_left (expr);
3404 ffebld right = ffebld_right (expr);
3405 ffecomGfrt code;
3406 ffeinfoKindtype rtkt;
270fc4e8 3407 ffeinfoKindtype ltkt;
5ff904cd
JL
3408
3409 switch (ffeinfo_basictype (ffebld_info (right)))
3410 {
3411 case FFEINFO_basictypeINTEGER:
3412 if (1 || optimize)
3413 {
c7e4ee3a 3414 item = ffecom_expr_power_integer_ (expr);
5ff904cd
JL
3415 if (item != NULL_TREE)
3416 return item;
3417 }
3418
3419 rtkt = FFEINFO_kindtypeINTEGER1;
3420 switch (ffeinfo_basictype (ffebld_info (left)))
3421 {
3422 case FFEINFO_basictypeINTEGER:
3423 if ((ffeinfo_kindtype (ffebld_info (left))
3424 == FFEINFO_kindtypeINTEGER4)
3425 || (ffeinfo_kindtype (ffebld_info (right))
3426 == FFEINFO_kindtypeINTEGER4))
3427 {
3428 code = FFECOM_gfrtPOW_QQ;
270fc4e8 3429 ltkt = FFEINFO_kindtypeINTEGER4;
5ff904cd
JL
3430 rtkt = FFEINFO_kindtypeINTEGER4;
3431 }
3432 else
6a047254
CB
3433 {
3434 code = FFECOM_gfrtPOW_II;
3435 ltkt = FFEINFO_kindtypeINTEGER1;
3436 }
5ff904cd
JL
3437 break;
3438
3439 case FFEINFO_basictypeREAL:
3440 if (ffeinfo_kindtype (ffebld_info (left))
3441 == FFEINFO_kindtypeREAL1)
6a047254
CB
3442 {
3443 code = FFECOM_gfrtPOW_RI;
3444 ltkt = FFEINFO_kindtypeREAL1;
3445 }
5ff904cd 3446 else
6a047254
CB
3447 {
3448 code = FFECOM_gfrtPOW_DI;
3449 ltkt = FFEINFO_kindtypeREAL2;
3450 }
5ff904cd
JL
3451 break;
3452
3453 case FFEINFO_basictypeCOMPLEX:
3454 if (ffeinfo_kindtype (ffebld_info (left))
3455 == FFEINFO_kindtypeREAL1)
6a047254
CB
3456 {
3457 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
3458 ltkt = FFEINFO_kindtypeREAL1;
3459 }
5ff904cd 3460 else
6a047254
CB
3461 {
3462 code = FFECOM_gfrtPOW_ZI; /* Overlapping result okay. */
3463 ltkt = FFEINFO_kindtypeREAL2;
3464 }
5ff904cd
JL
3465 break;
3466
3467 default:
3468 assert ("bad pow_*i" == NULL);
3469 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
6a047254 3470 ltkt = FFEINFO_kindtypeREAL1;
5ff904cd
JL
3471 break;
3472 }
270fc4e8 3473 if (ffeinfo_kindtype (ffebld_info (left)) != ltkt)
5ff904cd 3474 left = ffeexpr_convert (left, NULL, NULL,
6a047254 3475 ffeinfo_basictype (ffebld_info (left)),
270fc4e8 3476 ltkt, 0,
5ff904cd
JL
3477 FFETARGET_charactersizeNONE,
3478 FFEEXPR_contextLET);
3479 if (ffeinfo_kindtype (ffebld_info (right)) != rtkt)
3480 right = ffeexpr_convert (right, NULL, NULL,
3481 FFEINFO_basictypeINTEGER,
3482 rtkt, 0,
3483 FFETARGET_charactersizeNONE,
3484 FFEEXPR_contextLET);
3485 break;
3486
3487 case FFEINFO_basictypeREAL:
3488 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3489 left = ffeexpr_convert (left, NULL, NULL, FFEINFO_basictypeREAL,
3490 FFEINFO_kindtypeREALDOUBLE, 0,
3491 FFETARGET_charactersizeNONE,
3492 FFEEXPR_contextLET);
3493 if (ffeinfo_kindtype (ffebld_info (right))
3494 == FFEINFO_kindtypeREAL1)
3495 right = ffeexpr_convert (right, NULL, NULL,
3496 FFEINFO_basictypeREAL,
3497 FFEINFO_kindtypeREALDOUBLE, 0,
3498 FFETARGET_charactersizeNONE,
3499 FFEEXPR_contextLET);
3500 code = FFECOM_gfrtPOW_DD;
3501 break;
3502
3503 case FFEINFO_basictypeCOMPLEX:
3504 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3505 left = ffeexpr_convert (left, NULL, NULL,
3506 FFEINFO_basictypeCOMPLEX,
3507 FFEINFO_kindtypeREALDOUBLE, 0,
3508 FFETARGET_charactersizeNONE,
3509 FFEEXPR_contextLET);
3510 if (ffeinfo_kindtype (ffebld_info (right))
3511 == FFEINFO_kindtypeREAL1)
3512 right = ffeexpr_convert (right, NULL, NULL,
3513 FFEINFO_basictypeCOMPLEX,
3514 FFEINFO_kindtypeREALDOUBLE, 0,
3515 FFETARGET_charactersizeNONE,
3516 FFEEXPR_contextLET);
3517 code = FFECOM_gfrtPOW_ZZ; /* Overlapping result okay. */
3518 break;
3519
3520 default:
3521 assert ("bad pow_x*" == NULL);
3522 code = FFECOM_gfrtPOW_II;
3523 break;
3524 }
3525 return ffecom_call_binop_ (ffecom_gfrt_tree_ (code),
3526 ffecom_gfrt_kindtype (code),
3527 (ffe_is_f2c_library ()
3528 && ffecom_gfrt_complex_[code]),
3529 tree_type, left, right,
3530 dest_tree, dest, dest_used,
c7e4ee3a
CB
3531 NULL_TREE, FALSE,
3532 ffebld_nonter_hook (expr));
5ff904cd
JL
3533 }
3534
3535 case FFEBLD_opNOT:
5ff904cd
JL
3536 switch (bt)
3537 {
3538 case FFEINFO_basictypeLOGICAL:
83ffecd2 3539 item = ffecom_truth_value_invert (ffecom_expr (ffebld_left (expr)));
5ff904cd
JL
3540 return convert (tree_type, item);
3541
3542 case FFEINFO_basictypeINTEGER:
3543 return ffecom_1 (BIT_NOT_EXPR, tree_type,
3544 ffecom_expr (ffebld_left (expr)));
3545
3546 default:
3547 assert ("NOT bad basictype" == NULL);
3548 /* Fall through. */
3549 case FFEINFO_basictypeANY:
3550 return error_mark_node;
3551 }
3552 break;
3553
3554 case FFEBLD_opFUNCREF:
3555 assert (ffeinfo_basictype (ffebld_info (expr))
3556 != FFEINFO_basictypeCHARACTER);
3557 /* Fall through. */
3558 case FFEBLD_opSUBRREF:
5ff904cd
JL
3559 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
3560 == FFEINFO_whereINTRINSIC)
3561 { /* Invocation of an intrinsic. */
3562 item = ffecom_expr_intrinsic_ (expr, dest_tree, dest,
3563 dest_used);
3564 return item;
3565 }
3566 s = ffebld_symter (ffebld_left (expr));
3567 dt = ffesymbol_hook (s).decl_tree;
3568 if (dt == NULL_TREE)
3569 {
3570 s = ffecom_sym_transform_ (s);
3571 dt = ffesymbol_hook (s).decl_tree;
3572 }
3573 if (dt == error_mark_node)
3574 return dt;
3575
3576 if (ffesymbol_hook (s).addr)
3577 item = dt;
3578 else
3579 item = ffecom_1_fn (dt);
3580
5ff904cd
JL
3581 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
3582 args = ffecom_list_expr (ffebld_right (expr));
3583 else
3584 args = ffecom_list_ptr_to_expr (ffebld_right (expr));
5ff904cd 3585
702edf1d
CB
3586 if (args == error_mark_node)
3587 return error_mark_node;
3588
5ff904cd
JL
3589 item = ffecom_call_ (item, kt,
3590 ffesymbol_is_f2c (s)
3591 && (bt == FFEINFO_basictypeCOMPLEX)
3592 && (ffesymbol_where (s)
3593 != FFEINFO_whereCONSTANT),
3594 tree_type,
3595 args,
3596 dest_tree, dest, dest_used,
c7e4ee3a
CB
3597 error_mark_node, FALSE,
3598 ffebld_nonter_hook (expr));
5ff904cd
JL
3599 TREE_SIDE_EFFECTS (item) = 1;
3600 return item;
3601
3602 case FFEBLD_opAND:
5ff904cd
JL
3603 switch (bt)
3604 {
3605 case FFEINFO_basictypeLOGICAL:
3606 item
3607 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3608 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3609 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3610 return convert (tree_type, item);
3611
3612 case FFEINFO_basictypeINTEGER:
3613 return ffecom_2 (BIT_AND_EXPR, tree_type,
3614 ffecom_expr (ffebld_left (expr)),
3615 ffecom_expr (ffebld_right (expr)));
3616
3617 default:
3618 assert ("AND bad basictype" == NULL);
3619 /* Fall through. */
3620 case FFEINFO_basictypeANY:
3621 return error_mark_node;
3622 }
3623 break;
3624
3625 case FFEBLD_opOR:
5ff904cd
JL
3626 switch (bt)
3627 {
3628 case FFEINFO_basictypeLOGICAL:
3629 item
3630 = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
3631 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3632 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3633 return convert (tree_type, item);
3634
3635 case FFEINFO_basictypeINTEGER:
3636 return ffecom_2 (BIT_IOR_EXPR, tree_type,
3637 ffecom_expr (ffebld_left (expr)),
3638 ffecom_expr (ffebld_right (expr)));
3639
3640 default:
3641 assert ("OR bad basictype" == NULL);
3642 /* Fall through. */
3643 case FFEINFO_basictypeANY:
3644 return error_mark_node;
3645 }
3646 break;
3647
3648 case FFEBLD_opXOR:
3649 case FFEBLD_opNEQV:
5ff904cd
JL
3650 switch (bt)
3651 {
3652 case FFEINFO_basictypeLOGICAL:
3653 item
3654 = ffecom_2 (NE_EXPR, integer_type_node,
3655 ffecom_expr (ffebld_left (expr)),
3656 ffecom_expr (ffebld_right (expr)));
3657 return convert (tree_type, ffecom_truth_value (item));
3658
3659 case FFEINFO_basictypeINTEGER:
3660 return ffecom_2 (BIT_XOR_EXPR, tree_type,
3661 ffecom_expr (ffebld_left (expr)),
3662 ffecom_expr (ffebld_right (expr)));
3663
3664 default:
3665 assert ("XOR/NEQV bad basictype" == NULL);
3666 /* Fall through. */
3667 case FFEINFO_basictypeANY:
3668 return error_mark_node;
3669 }
3670 break;
3671
3672 case FFEBLD_opEQV:
5ff904cd
JL
3673 switch (bt)
3674 {
3675 case FFEINFO_basictypeLOGICAL:
3676 item
3677 = ffecom_2 (EQ_EXPR, integer_type_node,
3678 ffecom_expr (ffebld_left (expr)),
3679 ffecom_expr (ffebld_right (expr)));
3680 return convert (tree_type, ffecom_truth_value (item));
3681
3682 case FFEINFO_basictypeINTEGER:
3683 return
3684 ffecom_1 (BIT_NOT_EXPR, tree_type,
3685 ffecom_2 (BIT_XOR_EXPR, tree_type,
3686 ffecom_expr (ffebld_left (expr)),
3687 ffecom_expr (ffebld_right (expr))));
3688
3689 default:
3690 assert ("EQV bad basictype" == NULL);
3691 /* Fall through. */
3692 case FFEINFO_basictypeANY:
3693 return error_mark_node;
3694 }
3695 break;
3696
3697 case FFEBLD_opCONVERT:
3698 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opANY)
3699 return error_mark_node;
3700
5ff904cd
JL
3701 switch (bt)
3702 {
3703 case FFEINFO_basictypeLOGICAL:
3704 case FFEINFO_basictypeINTEGER:
3705 case FFEINFO_basictypeREAL:
3706 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3707
3708 case FFEINFO_basictypeCOMPLEX:
3709 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3710 {
3711 case FFEINFO_basictypeINTEGER:
3712 case FFEINFO_basictypeLOGICAL:
3713 case FFEINFO_basictypeREAL:
3714 item = ffecom_expr (ffebld_left (expr));
3715 if (item == error_mark_node)
3716 return error_mark_node;
3717 /* convert() takes care of converting to the subtype first,
3718 at least in gcc-2.7.2. */
3719 item = convert (tree_type, item);
3720 return item;
3721
3722 case FFEINFO_basictypeCOMPLEX:
3723 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3724
3725 default:
3726 assert ("CONVERT COMPLEX bad basictype" == NULL);
3727 /* Fall through. */
3728 case FFEINFO_basictypeANY:
3729 return error_mark_node;
3730 }
3731 break;
3732
3733 default:
3734 assert ("CONVERT bad basictype" == NULL);
3735 /* Fall through. */
3736 case FFEINFO_basictypeANY:
3737 return error_mark_node;
3738 }
3739 break;
3740
3741 case FFEBLD_opLT:
3742 code = LT_EXPR;
3743 goto relational; /* :::::::::::::::::::: */
3744
3745 case FFEBLD_opLE:
3746 code = LE_EXPR;
3747 goto relational; /* :::::::::::::::::::: */
3748
3749 case FFEBLD_opEQ:
3750 code = EQ_EXPR;
3751 goto relational; /* :::::::::::::::::::: */
3752
3753 case FFEBLD_opNE:
3754 code = NE_EXPR;
3755 goto relational; /* :::::::::::::::::::: */
3756
3757 case FFEBLD_opGT:
3758 code = GT_EXPR;
3759 goto relational; /* :::::::::::::::::::: */
3760
3761 case FFEBLD_opGE:
3762 code = GE_EXPR;
3763
3764 relational: /* :::::::::::::::::::: */
5ff904cd
JL
3765 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3766 {
3767 case FFEINFO_basictypeLOGICAL:
3768 case FFEINFO_basictypeINTEGER:
3769 case FFEINFO_basictypeREAL:
3770 item = ffecom_2 (code, integer_type_node,
3771 ffecom_expr (ffebld_left (expr)),
3772 ffecom_expr (ffebld_right (expr)));
3773 return convert (tree_type, item);
3774
3775 case FFEINFO_basictypeCOMPLEX:
3776 assert (code == EQ_EXPR || code == NE_EXPR);
3777 {
3778 tree real_type;
3779 tree arg1 = ffecom_expr (ffebld_left (expr));
3780 tree arg2 = ffecom_expr (ffebld_right (expr));
3781
3782 if (arg1 == error_mark_node || arg2 == error_mark_node)
3783 return error_mark_node;
3784
3785 arg1 = ffecom_save_tree (arg1);
3786 arg2 = ffecom_save_tree (arg2);
3787
3788 if (TREE_CODE (TREE_TYPE (arg1)) == COMPLEX_TYPE)
3789 {
3790 real_type = TREE_TYPE (TREE_TYPE (arg1));
3791 assert (real_type == TREE_TYPE (TREE_TYPE (arg2)));
3792 }
3793 else
3794 {
3795 real_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg1)));
3796 assert (real_type == TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg2))));
3797 }
3798
3799 item
3800 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3801 ffecom_2 (EQ_EXPR, integer_type_node,
3802 ffecom_1 (REALPART_EXPR, real_type, arg1),
3803 ffecom_1 (REALPART_EXPR, real_type, arg2)),
3804 ffecom_2 (EQ_EXPR, integer_type_node,
3805 ffecom_1 (IMAGPART_EXPR, real_type, arg1),
3806 ffecom_1 (IMAGPART_EXPR, real_type,
3807 arg2)));
3808 if (code == EQ_EXPR)
3809 item = ffecom_truth_value (item);
3810 else
3811 item = ffecom_truth_value_invert (item);
3812 return convert (tree_type, item);
3813 }
3814
3815 case FFEINFO_basictypeCHARACTER:
5ff904cd
JL
3816 {
3817 ffebld left = ffebld_left (expr);
3818 ffebld right = ffebld_right (expr);
3819 tree left_tree;
3820 tree right_tree;
3821 tree left_length;
3822 tree right_length;
3823
3824 /* f2c run-time functions do the implicit blank-padding for us,
3825 so we don't usually have to implement blank-padding ourselves.
3826 (The exception is when we pass an argument to a separately
3827 compiled statement function -- if we know the arg is not the
3828 same length as the dummy, we must truncate or extend it. If
3829 we "inline" statement functions, that necessity goes away as
3830 well.)
3831
3832 Strip off the CONVERT operators that blank-pad. (Truncation by
3833 CONVERT shouldn't happen here, but it can happen in
3834 assignments.) */
3835
3836 while (ffebld_op (left) == FFEBLD_opCONVERT)
3837 left = ffebld_left (left);
3838 while (ffebld_op (right) == FFEBLD_opCONVERT)
3839 right = ffebld_left (right);
3840
3841 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
3842 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
3843
3844 if (left_tree == error_mark_node || left_length == error_mark_node
3845 || right_tree == error_mark_node
3846 || right_length == error_mark_node)
c7e4ee3a 3847 return error_mark_node;
5ff904cd
JL
3848
3849 if ((ffebld_size_known (left) == 1)
3850 && (ffebld_size_known (right) == 1))
3851 {
3852 left_tree
3853 = ffecom_1 (INDIRECT_REF,
3854 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3855 left_tree);
3856 right_tree
3857 = ffecom_1 (INDIRECT_REF,
3858 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3859 right_tree);
3860
3861 item
3862 = ffecom_2 (code, integer_type_node,
3863 ffecom_2 (ARRAY_REF,
3864 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3865 left_tree,
3866 integer_one_node),
3867 ffecom_2 (ARRAY_REF,
3868 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3869 right_tree,
3870 integer_one_node));
3871 }
3872 else
3873 {
3874 item = build_tree_list (NULL_TREE, left_tree);
3875 TREE_CHAIN (item) = build_tree_list (NULL_TREE, right_tree);
3876 TREE_CHAIN (TREE_CHAIN (item)) = build_tree_list (NULL_TREE,
3877 left_length);
3878 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
3879 = build_tree_list (NULL_TREE, right_length);
c7e4ee3a 3880 item = ffecom_call_gfrt (FFECOM_gfrtCMP, item, NULL_TREE);
5ff904cd
JL
3881 item = ffecom_2 (code, integer_type_node,
3882 item,
3883 convert (TREE_TYPE (item),
3884 integer_zero_node));
3885 }
3886 item = convert (tree_type, item);
3887 }
3888
5ff904cd
JL
3889 return item;
3890
3891 default:
3892 assert ("relational bad basictype" == NULL);
3893 /* Fall through. */
3894 case FFEINFO_basictypeANY:
3895 return error_mark_node;
3896 }
3897 break;
3898
3899 case FFEBLD_opPERCENT_LOC:
5ff904cd
JL
3900 item = ffecom_arg_ptr_to_expr (ffebld_left (expr), &list);
3901 return convert (tree_type, item);
3902
3903 case FFEBLD_opITEM:
3904 case FFEBLD_opSTAR:
3905 case FFEBLD_opBOUNDS:
3906 case FFEBLD_opREPEAT:
3907 case FFEBLD_opLABTER:
3908 case FFEBLD_opLABTOK:
3909 case FFEBLD_opIMPDO:
3910 case FFEBLD_opCONCATENATE:
3911 case FFEBLD_opSUBSTR:
3912 default:
3913 assert ("bad op" == NULL);
3914 /* Fall through. */
3915 case FFEBLD_opANY:
3916 return error_mark_node;
3917 }
3918
3919#if 1
3920 assert ("didn't think anything got here anymore!!" == NULL);
3921#else
3922 switch (ffebld_arity (expr))
3923 {
3924 case 2:
3925 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3926 TREE_OPERAND (item, 1) = ffecom_expr (ffebld_right (expr));
3927 if (TREE_OPERAND (item, 0) == error_mark_node
3928 || TREE_OPERAND (item, 1) == error_mark_node)
3929 return error_mark_node;
3930 break;
3931
3932 case 1:
3933 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3934 if (TREE_OPERAND (item, 0) == error_mark_node)
3935 return error_mark_node;
3936 break;
3937
3938 default:
3939 break;
3940 }
3941
3942 return fold (item);
3943#endif
3944}
3945
3946#endif
3947/* Returns the tree that does the intrinsic invocation.
3948
3949 Note: this function applies only to intrinsics returning
3950 CHARACTER*1 or non-CHARACTER results, and to intrinsic
3951 subroutines. */
3952
3953#if FFECOM_targetCURRENT == FFECOM_targetGCC
3954static tree
3955ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
3956 ffebld dest, bool *dest_used)
3957{
3958 tree expr_tree;
3959 tree saved_expr1; /* For those who need it. */
3960 tree saved_expr2; /* For those who need it. */
3961 ffeinfoBasictype bt;
3962 ffeinfoKindtype kt;
3963 tree tree_type;
3964 tree arg1_type;
3965 tree real_type; /* REAL type corresponding to COMPLEX. */
3966 tree tempvar;
3967 ffebld list = ffebld_right (expr); /* List of (some) args. */
3968 ffebld arg1; /* For handy reference. */
3969 ffebld arg2;
3970 ffebld arg3;
3971 ffeintrinImp codegen_imp;
3972 ffecomGfrt gfrt;
3973
3974 assert (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER);
3975
3976 if (dest_used != NULL)
3977 *dest_used = FALSE;
3978
3979 bt = ffeinfo_basictype (ffebld_info (expr));
3980 kt = ffeinfo_kindtype (ffebld_info (expr));
3981 tree_type = ffecom_tree_type[bt][kt];
3982
3983 if (list != NULL)
3984 {
3985 arg1 = ffebld_head (list);
3986 if (arg1 != NULL && ffebld_op (arg1) == FFEBLD_opANY)
3987 return error_mark_node;
3988 if ((list = ffebld_trail (list)) != NULL)
3989 {
3990 arg2 = ffebld_head (list);
3991 if (arg2 != NULL && ffebld_op (arg2) == FFEBLD_opANY)
3992 return error_mark_node;
3993 if ((list = ffebld_trail (list)) != NULL)
3994 {
3995 arg3 = ffebld_head (list);
3996 if (arg3 != NULL && ffebld_op (arg3) == FFEBLD_opANY)
3997 return error_mark_node;
3998 }
3999 else
4000 arg3 = NULL;
4001 }
4002 else
4003 arg2 = arg3 = NULL;
4004 }
4005 else
4006 arg1 = arg2 = arg3 = NULL;
4007
4008 /* <list> ends up at the opITEM of the 3rd arg, or NULL if there are < 3
4009 args. This is used by the MAX/MIN expansions. */
4010
4011 if (arg1 != NULL)
4012 arg1_type = ffecom_tree_type
4013 [ffeinfo_basictype (ffebld_info (arg1))]
4014 [ffeinfo_kindtype (ffebld_info (arg1))];
4015 else
4016 arg1_type = NULL_TREE; /* Really not needed, but might catch bugs
4017 here. */
4018
4019 /* There are several ways for each of the cases in the following switch
4020 statements to exit (from simplest to use to most complicated):
4021
4022 break; (when expr_tree == NULL)
4023
4024 A standard call is made to the specific intrinsic just as if it had been
4025 passed in as a dummy procedure and called as any old procedure. This
4026 method can produce slower code but in some cases it's the easiest way for
4027 now. However, if a (presumably faster) direct call is available,
4028 that is used, so this is the easiest way in many more cases now.
4029
4030 gfrt = FFECOM_gfrtWHATEVER;
4031 break;
4032
4033 gfrt contains the gfrt index of a library function to call, passing the
4034 argument(s) by value rather than by reference. Used when a more
4035 careful choice of library function is needed than that provided
4036 by the vanilla `break;'.
4037
4038 return expr_tree;
4039
4040 The expr_tree has been completely set up and is ready to be returned
4041 as is. No further actions are taken. Use this when the tree is not
4042 in the simple form for one of the arity_n labels. */
4043
4044 /* For info on how the switch statement cases were written, see the files
4045 enclosed in comments below the switch statement. */
4046
4047 codegen_imp = ffebld_symter_implementation (ffebld_left (expr));
4048 gfrt = ffeintrin_gfrt_direct (codegen_imp);
4049 if (gfrt == FFECOM_gfrt)
4050 gfrt = ffeintrin_gfrt_indirect (codegen_imp);
4051
4052 switch (codegen_imp)
4053 {
4054 case FFEINTRIN_impABS:
4055 case FFEINTRIN_impCABS:
4056 case FFEINTRIN_impCDABS:
4057 case FFEINTRIN_impDABS:
4058 case FFEINTRIN_impIABS:
4059 if (ffeinfo_basictype (ffebld_info (arg1))
4060 == FFEINFO_basictypeCOMPLEX)
4061 {
4062 if (kt == FFEINFO_kindtypeREAL1)
4063 gfrt = FFECOM_gfrtCABS;
4064 else if (kt == FFEINFO_kindtypeREAL2)
4065 gfrt = FFECOM_gfrtCDABS;
4066 break;
4067 }
4068 return ffecom_1 (ABS_EXPR, tree_type,
4069 convert (tree_type, ffecom_expr (arg1)));
4070
4071 case FFEINTRIN_impACOS:
4072 case FFEINTRIN_impDACOS:
4073 break;
4074
4075 case FFEINTRIN_impAIMAG:
4076 case FFEINTRIN_impDIMAG:
4077 case FFEINTRIN_impIMAGPART:
4078 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4079 arg1_type = TREE_TYPE (arg1_type);
4080 else
4081 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4082
4083 return
4084 convert (tree_type,
4085 ffecom_1 (IMAGPART_EXPR, arg1_type,
4086 ffecom_expr (arg1)));
4087
4088 case FFEINTRIN_impAINT:
4089 case FFEINTRIN_impDINT:
c7e4ee3a
CB
4090#if 0
4091 /* ~~Someday implement FIX_TRUNC_EXPR yielding same type as arg. */
5ff904cd
JL
4092 return ffecom_1 (FIX_TRUNC_EXPR, tree_type, ffecom_expr (arg1));
4093#else /* in the meantime, must use floor to avoid range problems with ints */
4094 /* r__1 = r1 >= 0 ? floor(r1) : -floor(-r1); */
4095 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4096 return
4097 convert (tree_type,
4098 ffecom_3 (COND_EXPR, double_type_node,
4099 ffecom_truth_value
4100 (ffecom_2 (GE_EXPR, integer_type_node,
4101 saved_expr1,
4102 convert (arg1_type,
4103 ffecom_float_zero_))),
4104 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4105 build_tree_list (NULL_TREE,
4106 convert (double_type_node,
c7e4ee3a
CB
4107 saved_expr1)),
4108 NULL_TREE),
5ff904cd
JL
4109 ffecom_1 (NEGATE_EXPR, double_type_node,
4110 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4111 build_tree_list (NULL_TREE,
4112 convert (double_type_node,
4113 ffecom_1 (NEGATE_EXPR,
4114 arg1_type,
c7e4ee3a
CB
4115 saved_expr1))),
4116 NULL_TREE)
5ff904cd
JL
4117 ))
4118 );
4119#endif
4120
4121 case FFEINTRIN_impANINT:
4122 case FFEINTRIN_impDNINT:
4123#if 0 /* This way of doing it won't handle real
4124 numbers of large magnitudes. */
4125 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4126 expr_tree = convert (tree_type,
4127 convert (integer_type_node,
4128 ffecom_3 (COND_EXPR, tree_type,
4129 ffecom_truth_value
4130 (ffecom_2 (GE_EXPR,
4131 integer_type_node,
4132 saved_expr1,
4133 ffecom_float_zero_)),
4134 ffecom_2 (PLUS_EXPR,
4135 tree_type,
4136 saved_expr1,
4137 ffecom_float_half_),
4138 ffecom_2 (MINUS_EXPR,
4139 tree_type,
4140 saved_expr1,
4141 ffecom_float_half_))));
4142 return expr_tree;
4143#else /* So we instead call floor. */
4144 /* r__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1) */
4145 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4146 return
4147 convert (tree_type,
4148 ffecom_3 (COND_EXPR, double_type_node,
4149 ffecom_truth_value
4150 (ffecom_2 (GE_EXPR, integer_type_node,
4151 saved_expr1,
4152 convert (arg1_type,
4153 ffecom_float_zero_))),
4154 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4155 build_tree_list (NULL_TREE,
4156 convert (double_type_node,
4157 ffecom_2 (PLUS_EXPR,
4158 arg1_type,
4159 saved_expr1,
4160 convert (arg1_type,
c7e4ee3a
CB
4161 ffecom_float_half_)))),
4162 NULL_TREE),
5ff904cd
JL
4163 ffecom_1 (NEGATE_EXPR, double_type_node,
4164 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4165 build_tree_list (NULL_TREE,
4166 convert (double_type_node,
4167 ffecom_2 (MINUS_EXPR,
4168 arg1_type,
4169 convert (arg1_type,
4170 ffecom_float_half_),
c7e4ee3a
CB
4171 saved_expr1))),
4172 NULL_TREE))
5ff904cd
JL
4173 )
4174 );
4175#endif
4176
4177 case FFEINTRIN_impASIN:
4178 case FFEINTRIN_impDASIN:
4179 case FFEINTRIN_impATAN:
4180 case FFEINTRIN_impDATAN:
4181 case FFEINTRIN_impATAN2:
4182 case FFEINTRIN_impDATAN2:
4183 break;
4184
4185 case FFEINTRIN_impCHAR:
4186 case FFEINTRIN_impACHAR:
c7e4ee3a
CB
4187#ifdef HOHO
4188 tempvar = ffecom_make_tempvar (char_type_node, 1, -1);
4189#else
4190 tempvar = ffebld_nonter_hook (expr);
4191 assert (tempvar);
4192#endif
5ff904cd
JL
4193 {
4194 tree tmv = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (tempvar)));
4195
4196 expr_tree = ffecom_modify (tmv,
4197 ffecom_2 (ARRAY_REF, tmv, tempvar,
4198 integer_one_node),
4199 convert (tmv, ffecom_expr (arg1)));
4200 }
4201 expr_tree = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar),
4202 expr_tree,
4203 tempvar);
4204 expr_tree = ffecom_1 (ADDR_EXPR,
4205 build_pointer_type (TREE_TYPE (expr_tree)),
4206 expr_tree);
4207 return expr_tree;
4208
4209 case FFEINTRIN_impCMPLX:
4210 case FFEINTRIN_impDCMPLX:
4211 if (arg2 == NULL)
4212 return
4213 convert (tree_type, ffecom_expr (arg1));
4214
4215 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4216 return
4217 ffecom_2 (COMPLEX_EXPR, tree_type,
4218 convert (real_type, ffecom_expr (arg1)),
4219 convert (real_type,
4220 ffecom_expr (arg2)));
4221
4222 case FFEINTRIN_impCOMPLEX:
4223 return
4224 ffecom_2 (COMPLEX_EXPR, tree_type,
4225 ffecom_expr (arg1),
4226 ffecom_expr (arg2));
4227
4228 case FFEINTRIN_impCONJG:
4229 case FFEINTRIN_impDCONJG:
4230 {
4231 tree arg1_tree;
4232
4233 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4234 arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4235 return
4236 ffecom_2 (COMPLEX_EXPR, tree_type,
4237 ffecom_1 (REALPART_EXPR, real_type, arg1_tree),
4238 ffecom_1 (NEGATE_EXPR, real_type,
4239 ffecom_1 (IMAGPART_EXPR, real_type, arg1_tree)));
4240 }
4241
4242 case FFEINTRIN_impCOS:
4243 case FFEINTRIN_impCCOS:
4244 case FFEINTRIN_impCDCOS:
4245 case FFEINTRIN_impDCOS:
4246 if (bt == FFEINFO_basictypeCOMPLEX)
4247 {
4248 if (kt == FFEINFO_kindtypeREAL1)
4249 gfrt = FFECOM_gfrtCCOS; /* Overlapping result okay. */
4250 else if (kt == FFEINFO_kindtypeREAL2)
4251 gfrt = FFECOM_gfrtCDCOS; /* Overlapping result okay. */
4252 }
4253 break;
4254
4255 case FFEINTRIN_impCOSH:
4256 case FFEINTRIN_impDCOSH:
4257 break;
4258
4259 case FFEINTRIN_impDBLE:
4260 case FFEINTRIN_impDFLOAT:
4261 case FFEINTRIN_impDREAL:
4262 case FFEINTRIN_impFLOAT:
4263 case FFEINTRIN_impIDINT:
4264 case FFEINTRIN_impIFIX:
4265 case FFEINTRIN_impINT2:
4266 case FFEINTRIN_impINT8:
4267 case FFEINTRIN_impINT:
4268 case FFEINTRIN_impLONG:
4269 case FFEINTRIN_impREAL:
4270 case FFEINTRIN_impSHORT:
4271 case FFEINTRIN_impSNGL:
4272 return convert (tree_type, ffecom_expr (arg1));
4273
4274 case FFEINTRIN_impDIM:
4275 case FFEINTRIN_impDDIM:
4276 case FFEINTRIN_impIDIM:
4277 saved_expr1 = ffecom_save_tree (convert (tree_type,
4278 ffecom_expr (arg1)));
4279 saved_expr2 = ffecom_save_tree (convert (tree_type,
4280 ffecom_expr (arg2)));
4281 return
4282 ffecom_3 (COND_EXPR, tree_type,
4283 ffecom_truth_value
4284 (ffecom_2 (GT_EXPR, integer_type_node,
4285 saved_expr1,
4286 saved_expr2)),
4287 ffecom_2 (MINUS_EXPR, tree_type,
4288 saved_expr1,
4289 saved_expr2),
4290 convert (tree_type, ffecom_float_zero_));
4291
4292 case FFEINTRIN_impDPROD:
4293 return
4294 ffecom_2 (MULT_EXPR, tree_type,
4295 convert (tree_type, ffecom_expr (arg1)),
4296 convert (tree_type, ffecom_expr (arg2)));
4297
4298 case FFEINTRIN_impEXP:
4299 case FFEINTRIN_impCDEXP:
4300 case FFEINTRIN_impCEXP:
4301 case FFEINTRIN_impDEXP:
4302 if (bt == FFEINFO_basictypeCOMPLEX)
4303 {
4304 if (kt == FFEINFO_kindtypeREAL1)
4305 gfrt = FFECOM_gfrtCEXP; /* Overlapping result okay. */
4306 else if (kt == FFEINFO_kindtypeREAL2)
4307 gfrt = FFECOM_gfrtCDEXP; /* Overlapping result okay. */
4308 }
4309 break;
4310
4311 case FFEINTRIN_impICHAR:
4312 case FFEINTRIN_impIACHAR:
4313#if 0 /* The simple approach. */
4314 ffecom_char_args_ (&expr_tree, &saved_expr1 /* Ignored */ , arg1);
4315 expr_tree
4316 = ffecom_1 (INDIRECT_REF,
4317 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4318 expr_tree);
4319 expr_tree
4320 = ffecom_2 (ARRAY_REF,
4321 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4322 expr_tree,
4323 integer_one_node);
4324 return convert (tree_type, expr_tree);
4325#else /* The more interesting (and more optimal) approach. */
4326 expr_tree = ffecom_intrinsic_ichar_ (tree_type, arg1, &saved_expr1);
4327 expr_tree = ffecom_3 (COND_EXPR, tree_type,
4328 saved_expr1,
4329 expr_tree,
4330 convert (tree_type, integer_zero_node));
4331 return expr_tree;
4332#endif
4333
4334 case FFEINTRIN_impINDEX:
4335 break;
4336
4337 case FFEINTRIN_impLEN:
4338#if 0
4339 break; /* The simple approach. */
4340#else
4341 return ffecom_intrinsic_len_ (arg1); /* The more optimal approach. */
4342#endif
4343
4344 case FFEINTRIN_impLGE:
4345 case FFEINTRIN_impLGT:
4346 case FFEINTRIN_impLLE:
4347 case FFEINTRIN_impLLT:
4348 break;
4349
4350 case FFEINTRIN_impLOG:
4351 case FFEINTRIN_impALOG:
4352 case FFEINTRIN_impCDLOG:
4353 case FFEINTRIN_impCLOG:
4354 case FFEINTRIN_impDLOG:
4355 if (bt == FFEINFO_basictypeCOMPLEX)
4356 {
4357 if (kt == FFEINFO_kindtypeREAL1)
4358 gfrt = FFECOM_gfrtCLOG; /* Overlapping result okay. */
4359 else if (kt == FFEINFO_kindtypeREAL2)
4360 gfrt = FFECOM_gfrtCDLOG; /* Overlapping result okay. */
4361 }
4362 break;
4363
4364 case FFEINTRIN_impLOG10:
4365 case FFEINTRIN_impALOG10:
4366 case FFEINTRIN_impDLOG10:
4367 if (gfrt != FFECOM_gfrt)
4368 break; /* Already picked one, stick with it. */
4369
4370 if (kt == FFEINFO_kindtypeREAL1)
4371 gfrt = FFECOM_gfrtALOG10;
4372 else if (kt == FFEINFO_kindtypeREAL2)
4373 gfrt = FFECOM_gfrtDLOG10;
4374 break;
4375
4376 case FFEINTRIN_impMAX:
4377 case FFEINTRIN_impAMAX0:
4378 case FFEINTRIN_impAMAX1:
4379 case FFEINTRIN_impDMAX1:
4380 case FFEINTRIN_impMAX0:
4381 case FFEINTRIN_impMAX1:
4382 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4383 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4384 else
4385 arg1_type = tree_type;
4386 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4387 convert (arg1_type, ffecom_expr (arg1)),
4388 convert (arg1_type, ffecom_expr (arg2)));
4389 for (; list != NULL; list = ffebld_trail (list))
4390 {
4391 if ((ffebld_head (list) == NULL)
4392 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4393 continue;
4394 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4395 expr_tree,
4396 convert (arg1_type,
4397 ffecom_expr (ffebld_head (list))));
4398 }
4399 return convert (tree_type, expr_tree);
4400
4401 case FFEINTRIN_impMIN:
4402 case FFEINTRIN_impAMIN0:
4403 case FFEINTRIN_impAMIN1:
4404 case FFEINTRIN_impDMIN1:
4405 case FFEINTRIN_impMIN0:
4406 case FFEINTRIN_impMIN1:
4407 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4408 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4409 else
4410 arg1_type = tree_type;
4411 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4412 convert (arg1_type, ffecom_expr (arg1)),
4413 convert (arg1_type, ffecom_expr (arg2)));
4414 for (; list != NULL; list = ffebld_trail (list))
4415 {
4416 if ((ffebld_head (list) == NULL)
4417 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4418 continue;
4419 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4420 expr_tree,
4421 convert (arg1_type,
4422 ffecom_expr (ffebld_head (list))));
4423 }
4424 return convert (tree_type, expr_tree);
4425
4426 case FFEINTRIN_impMOD:
4427 case FFEINTRIN_impAMOD:
4428 case FFEINTRIN_impDMOD:
4429 if (bt != FFEINFO_basictypeREAL)
4430 return ffecom_2 (TRUNC_MOD_EXPR, tree_type,
4431 convert (tree_type, ffecom_expr (arg1)),
4432 convert (tree_type, ffecom_expr (arg2)));
4433
4434 if (kt == FFEINFO_kindtypeREAL1)
4435 gfrt = FFECOM_gfrtAMOD;
4436 else if (kt == FFEINFO_kindtypeREAL2)
4437 gfrt = FFECOM_gfrtDMOD;
4438 break;
4439
4440 case FFEINTRIN_impNINT:
4441 case FFEINTRIN_impIDNINT:
c7e4ee3a
CB
4442#if 0
4443 /* ~~Ideally FIX_ROUND_EXPR would be implemented, but it ain't yet. */
5ff904cd
JL
4444 return ffecom_1 (FIX_ROUND_EXPR, tree_type, ffecom_expr (arg1));
4445#else
4446 /* i__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1); */
4447 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4448 return
4449 convert (ffecom_integer_type_node,
4450 ffecom_3 (COND_EXPR, arg1_type,
4451 ffecom_truth_value
4452 (ffecom_2 (GE_EXPR, integer_type_node,
4453 saved_expr1,
4454 convert (arg1_type,
4455 ffecom_float_zero_))),
4456 ffecom_2 (PLUS_EXPR, arg1_type,
4457 saved_expr1,
4458 convert (arg1_type,
4459 ffecom_float_half_)),
4460 ffecom_2 (MINUS_EXPR, arg1_type,
4461 saved_expr1,
4462 convert (arg1_type,
4463 ffecom_float_half_))));
4464#endif
4465
4466 case FFEINTRIN_impSIGN:
4467 case FFEINTRIN_impDSIGN:
4468 case FFEINTRIN_impISIGN:
4469 {
4470 tree arg2_tree = ffecom_expr (arg2);
4471
4472 saved_expr1
4473 = ffecom_save_tree
4474 (ffecom_1 (ABS_EXPR, tree_type,
4475 convert (tree_type,
4476 ffecom_expr (arg1))));
4477 expr_tree
4478 = ffecom_3 (COND_EXPR, tree_type,
4479 ffecom_truth_value
4480 (ffecom_2 (GE_EXPR, integer_type_node,
4481 arg2_tree,
4482 convert (TREE_TYPE (arg2_tree),
4483 integer_zero_node))),
4484 saved_expr1,
4485 ffecom_1 (NEGATE_EXPR, tree_type, saved_expr1));
4486 /* Make sure SAVE_EXPRs get referenced early enough. */
4487 expr_tree
4488 = ffecom_2 (COMPOUND_EXPR, tree_type,
4489 convert (void_type_node, saved_expr1),
4490 expr_tree);
4491 }
4492 return expr_tree;
4493
4494 case FFEINTRIN_impSIN:
4495 case FFEINTRIN_impCDSIN:
4496 case FFEINTRIN_impCSIN:
4497 case FFEINTRIN_impDSIN:
4498 if (bt == FFEINFO_basictypeCOMPLEX)
4499 {
4500 if (kt == FFEINFO_kindtypeREAL1)
4501 gfrt = FFECOM_gfrtCSIN; /* Overlapping result okay. */
4502 else if (kt == FFEINFO_kindtypeREAL2)
4503 gfrt = FFECOM_gfrtCDSIN; /* Overlapping result okay. */
4504 }
4505 break;
4506
4507 case FFEINTRIN_impSINH:
4508 case FFEINTRIN_impDSINH:
4509 break;
4510
4511 case FFEINTRIN_impSQRT:
4512 case FFEINTRIN_impCDSQRT:
4513 case FFEINTRIN_impCSQRT:
4514 case FFEINTRIN_impDSQRT:
4515 if (bt == FFEINFO_basictypeCOMPLEX)
4516 {
4517 if (kt == FFEINFO_kindtypeREAL1)
4518 gfrt = FFECOM_gfrtCSQRT; /* Overlapping result okay. */
4519 else if (kt == FFEINFO_kindtypeREAL2)
4520 gfrt = FFECOM_gfrtCDSQRT; /* Overlapping result okay. */
4521 }
4522 break;
4523
4524 case FFEINTRIN_impTAN:
4525 case FFEINTRIN_impDTAN:
4526 case FFEINTRIN_impTANH:
4527 case FFEINTRIN_impDTANH:
4528 break;
4529
4530 case FFEINTRIN_impREALPART:
4531 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4532 arg1_type = TREE_TYPE (arg1_type);
4533 else
4534 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4535
4536 return
4537 convert (tree_type,
4538 ffecom_1 (REALPART_EXPR, arg1_type,
4539 ffecom_expr (arg1)));
4540
4541 case FFEINTRIN_impIAND:
4542 case FFEINTRIN_impAND:
4543 return ffecom_2 (BIT_AND_EXPR, tree_type,
4544 convert (tree_type,
4545 ffecom_expr (arg1)),
4546 convert (tree_type,
4547 ffecom_expr (arg2)));
4548
4549 case FFEINTRIN_impIOR:
4550 case FFEINTRIN_impOR:
4551 return ffecom_2 (BIT_IOR_EXPR, tree_type,
4552 convert (tree_type,
4553 ffecom_expr (arg1)),
4554 convert (tree_type,
4555 ffecom_expr (arg2)));
4556
4557 case FFEINTRIN_impIEOR:
4558 case FFEINTRIN_impXOR:
4559 return ffecom_2 (BIT_XOR_EXPR, tree_type,
4560 convert (tree_type,
4561 ffecom_expr (arg1)),
4562 convert (tree_type,
4563 ffecom_expr (arg2)));
4564
4565 case FFEINTRIN_impLSHIFT:
4566 return ffecom_2 (LSHIFT_EXPR, tree_type,
4567 ffecom_expr (arg1),
4568 convert (integer_type_node,
4569 ffecom_expr (arg2)));
4570
4571 case FFEINTRIN_impRSHIFT:
4572 return ffecom_2 (RSHIFT_EXPR, tree_type,
4573 ffecom_expr (arg1),
4574 convert (integer_type_node,
4575 ffecom_expr (arg2)));
4576
4577 case FFEINTRIN_impNOT:
4578 return ffecom_1 (BIT_NOT_EXPR, tree_type, ffecom_expr (arg1));
4579
4580 case FFEINTRIN_impBIT_SIZE:
4581 return convert (tree_type, TYPE_SIZE (arg1_type));
4582
4583 case FFEINTRIN_impBTEST:
4584 {
4585 ffetargetLogical1 true;
4586 ffetargetLogical1 false;
4587 tree true_tree;
4588 tree false_tree;
4589
4590 ffetarget_logical1 (&true, TRUE);
4591 ffetarget_logical1 (&false, FALSE);
4592 if (true == 1)
4593 true_tree = convert (tree_type, integer_one_node);
4594 else
4595 true_tree = convert (tree_type, build_int_2 (true, 0));
4596 if (false == 0)
4597 false_tree = convert (tree_type, integer_zero_node);
4598 else
4599 false_tree = convert (tree_type, build_int_2 (false, 0));
4600
4601 return
4602 ffecom_3 (COND_EXPR, tree_type,
4603 ffecom_truth_value
4604 (ffecom_2 (EQ_EXPR, integer_type_node,
4605 ffecom_2 (BIT_AND_EXPR, arg1_type,
4606 ffecom_expr (arg1),
4607 ffecom_2 (LSHIFT_EXPR, arg1_type,
4608 convert (arg1_type,
4609 integer_one_node),
4610 convert (integer_type_node,
4611 ffecom_expr (arg2)))),
4612 convert (arg1_type,
4613 integer_zero_node))),
4614 false_tree,
4615 true_tree);
4616 }
4617
4618 case FFEINTRIN_impIBCLR:
4619 return
4620 ffecom_2 (BIT_AND_EXPR, tree_type,
4621 ffecom_expr (arg1),
4622 ffecom_1 (BIT_NOT_EXPR, tree_type,
4623 ffecom_2 (LSHIFT_EXPR, tree_type,
4624 convert (tree_type,
4625 integer_one_node),
4626 convert (integer_type_node,
4627 ffecom_expr (arg2)))));
4628
4629 case FFEINTRIN_impIBITS:
4630 {
4631 tree arg3_tree = ffecom_save_tree (convert (integer_type_node,
4632 ffecom_expr (arg3)));
4633 tree uns_type
4634 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4635
4636 expr_tree
4637 = ffecom_2 (BIT_AND_EXPR, tree_type,
4638 ffecom_2 (RSHIFT_EXPR, tree_type,
4639 ffecom_expr (arg1),
4640 convert (integer_type_node,
4641 ffecom_expr (arg2))),
4642 convert (tree_type,
4643 ffecom_2 (RSHIFT_EXPR, uns_type,
4644 ffecom_1 (BIT_NOT_EXPR,
4645 uns_type,
4646 convert (uns_type,
4647 integer_zero_node)),
4648 ffecom_2 (MINUS_EXPR,
4649 integer_type_node,
4650 TYPE_SIZE (uns_type),
4651 arg3_tree))));
4652#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4653 expr_tree
4654 = ffecom_3 (COND_EXPR, tree_type,
4655 ffecom_truth_value
4656 (ffecom_2 (NE_EXPR, integer_type_node,
4657 arg3_tree,
4658 integer_zero_node)),
4659 expr_tree,
4660 convert (tree_type, integer_zero_node));
4661#endif
4662 }
4663 return expr_tree;
4664
4665 case FFEINTRIN_impIBSET:
4666 return
4667 ffecom_2 (BIT_IOR_EXPR, tree_type,
4668 ffecom_expr (arg1),
4669 ffecom_2 (LSHIFT_EXPR, tree_type,
4670 convert (tree_type, integer_one_node),
4671 convert (integer_type_node,
4672 ffecom_expr (arg2))));
4673
4674 case FFEINTRIN_impISHFT:
4675 {
4676 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4677 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4678 ffecom_expr (arg2)));
4679 tree uns_type
4680 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4681
4682 expr_tree
4683 = ffecom_3 (COND_EXPR, tree_type,
4684 ffecom_truth_value
4685 (ffecom_2 (GE_EXPR, integer_type_node,
4686 arg2_tree,
4687 integer_zero_node)),
4688 ffecom_2 (LSHIFT_EXPR, tree_type,
4689 arg1_tree,
4690 arg2_tree),
4691 convert (tree_type,
4692 ffecom_2 (RSHIFT_EXPR, uns_type,
4693 convert (uns_type, arg1_tree),
4694 ffecom_1 (NEGATE_EXPR,
4695 integer_type_node,
4696 arg2_tree))));
4697#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4698 expr_tree
4699 = ffecom_3 (COND_EXPR, tree_type,
4700 ffecom_truth_value
4701 (ffecom_2 (NE_EXPR, integer_type_node,
4702 arg2_tree,
4703 TYPE_SIZE (uns_type))),
4704 expr_tree,
4705 convert (tree_type, integer_zero_node));
4706#endif
4707 /* Make sure SAVE_EXPRs get referenced early enough. */
4708 expr_tree
4709 = ffecom_2 (COMPOUND_EXPR, tree_type,
4710 convert (void_type_node, arg1_tree),
4711 ffecom_2 (COMPOUND_EXPR, tree_type,
4712 convert (void_type_node, arg2_tree),
4713 expr_tree));
4714 }
4715 return expr_tree;
4716
4717 case FFEINTRIN_impISHFTC:
4718 {
4719 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4720 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4721 ffecom_expr (arg2)));
4722 tree arg3_tree = (arg3 == NULL) ? TYPE_SIZE (tree_type)
4723 : ffecom_save_tree (convert (integer_type_node, ffecom_expr (arg3)));
4724 tree shift_neg;
4725 tree shift_pos;
4726 tree mask_arg1;
4727 tree masked_arg1;
4728 tree uns_type
4729 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4730
4731 mask_arg1
4732 = ffecom_2 (LSHIFT_EXPR, tree_type,
4733 ffecom_1 (BIT_NOT_EXPR, tree_type,
4734 convert (tree_type, integer_zero_node)),
4735 arg3_tree);
4736#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4737 mask_arg1
4738 = ffecom_3 (COND_EXPR, tree_type,
4739 ffecom_truth_value
4740 (ffecom_2 (NE_EXPR, integer_type_node,
4741 arg3_tree,
4742 TYPE_SIZE (uns_type))),
4743 mask_arg1,
4744 convert (tree_type, integer_zero_node));
4745#endif
4746 mask_arg1 = ffecom_save_tree (mask_arg1);
4747 masked_arg1
4748 = ffecom_2 (BIT_AND_EXPR, tree_type,
4749 arg1_tree,
4750 ffecom_1 (BIT_NOT_EXPR, tree_type,
4751 mask_arg1));
4752 masked_arg1 = ffecom_save_tree (masked_arg1);
4753 shift_neg
4754 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4755 convert (tree_type,
4756 ffecom_2 (RSHIFT_EXPR, uns_type,
4757 convert (uns_type, masked_arg1),
4758 ffecom_1 (NEGATE_EXPR,
4759 integer_type_node,
4760 arg2_tree))),
4761 ffecom_2 (LSHIFT_EXPR, tree_type,
4762 arg1_tree,
4763 ffecom_2 (PLUS_EXPR, integer_type_node,
4764 arg2_tree,
4765 arg3_tree)));
4766 shift_pos
4767 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4768 ffecom_2 (LSHIFT_EXPR, tree_type,
4769 arg1_tree,
4770 arg2_tree),
4771 convert (tree_type,
4772 ffecom_2 (RSHIFT_EXPR, uns_type,
4773 convert (uns_type, masked_arg1),
4774 ffecom_2 (MINUS_EXPR,
4775 integer_type_node,
4776 arg3_tree,
4777 arg2_tree))));
4778 expr_tree
4779 = ffecom_3 (COND_EXPR, tree_type,
4780 ffecom_truth_value
4781 (ffecom_2 (LT_EXPR, integer_type_node,
4782 arg2_tree,
4783 integer_zero_node)),
4784 shift_neg,
4785 shift_pos);
4786 expr_tree
4787 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4788 ffecom_2 (BIT_AND_EXPR, tree_type,
4789 mask_arg1,
4790 arg1_tree),
4791 ffecom_2 (BIT_AND_EXPR, tree_type,
4792 ffecom_1 (BIT_NOT_EXPR, tree_type,
4793 mask_arg1),
4794 expr_tree));
4795 expr_tree
4796 = ffecom_3 (COND_EXPR, tree_type,
4797 ffecom_truth_value
4798 (ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
4799 ffecom_2 (EQ_EXPR, integer_type_node,
4800 ffecom_1 (ABS_EXPR,
4801 integer_type_node,
4802 arg2_tree),
4803 arg3_tree),
4804 ffecom_2 (EQ_EXPR, integer_type_node,
4805 arg2_tree,
4806 integer_zero_node))),
4807 arg1_tree,
4808 expr_tree);
4809 /* Make sure SAVE_EXPRs get referenced early enough. */
4810 expr_tree
4811 = ffecom_2 (COMPOUND_EXPR, tree_type,
4812 convert (void_type_node, arg1_tree),
4813 ffecom_2 (COMPOUND_EXPR, tree_type,
4814 convert (void_type_node, arg2_tree),
4815 ffecom_2 (COMPOUND_EXPR, tree_type,
4816 convert (void_type_node,
4817 mask_arg1),
4818 ffecom_2 (COMPOUND_EXPR, tree_type,
4819 convert (void_type_node,
4820 masked_arg1),
4821 expr_tree))));
4822 expr_tree
4823 = ffecom_2 (COMPOUND_EXPR, tree_type,
4824 convert (void_type_node,
4825 arg3_tree),
4826 expr_tree);
4827 }
4828 return expr_tree;
4829
4830 case FFEINTRIN_impLOC:
4831 {
4832 tree arg1_tree = ffecom_expr (arg1);
4833
4834 expr_tree
4835 = convert (tree_type,
4836 ffecom_1 (ADDR_EXPR,
4837 build_pointer_type (TREE_TYPE (arg1_tree)),
4838 arg1_tree));
4839 }
4840 return expr_tree;
4841
4842 case FFEINTRIN_impMVBITS:
4843 {
4844 tree arg1_tree;
4845 tree arg2_tree;
4846 tree arg3_tree;
4847 ffebld arg4 = ffebld_head (ffebld_trail (list));
4848 tree arg4_tree;
4849 tree arg4_type;
4850 ffebld arg5 = ffebld_head (ffebld_trail (ffebld_trail (list)));
4851 tree arg5_tree;
4852 tree prep_arg1;
4853 tree prep_arg4;
4854 tree arg5_plus_arg3;
4855
5ff904cd
JL
4856 arg2_tree = convert (integer_type_node,
4857 ffecom_expr (arg2));
4858 arg3_tree = ffecom_save_tree (convert (integer_type_node,
4859 ffecom_expr (arg3)));
c7e4ee3a 4860 arg4_tree = ffecom_expr_rw (NULL_TREE, arg4);
5ff904cd
JL
4861 arg4_type = TREE_TYPE (arg4_tree);
4862
4863 arg1_tree = ffecom_save_tree (convert (arg4_type,
4864 ffecom_expr (arg1)));
4865
4866 arg5_tree = ffecom_save_tree (convert (integer_type_node,
4867 ffecom_expr (arg5)));
4868
5ff904cd
JL
4869 prep_arg1
4870 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4871 ffecom_2 (BIT_AND_EXPR, arg4_type,
4872 ffecom_2 (RSHIFT_EXPR, arg4_type,
4873 arg1_tree,
4874 arg2_tree),
4875 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4876 ffecom_2 (LSHIFT_EXPR, arg4_type,
4877 ffecom_1 (BIT_NOT_EXPR,
4878 arg4_type,
4879 convert
4880 (arg4_type,
4881 integer_zero_node)),
4882 arg3_tree))),
4883 arg5_tree);
4884 arg5_plus_arg3
4885 = ffecom_save_tree (ffecom_2 (PLUS_EXPR, arg4_type,
4886 arg5_tree,
4887 arg3_tree));
4888 prep_arg4
4889 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4890 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4891 convert (arg4_type,
4892 integer_zero_node)),
4893 arg5_plus_arg3);
4894#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4895 prep_arg4
4896 = ffecom_3 (COND_EXPR, arg4_type,
4897 ffecom_truth_value
4898 (ffecom_2 (NE_EXPR, integer_type_node,
4899 arg5_plus_arg3,
4900 convert (TREE_TYPE (arg5_plus_arg3),
4901 TYPE_SIZE (arg4_type)))),
4902 prep_arg4,
4903 convert (arg4_type, integer_zero_node));
4904#endif
4905 prep_arg4
4906 = ffecom_2 (BIT_AND_EXPR, arg4_type,
4907 arg4_tree,
4908 ffecom_2 (BIT_IOR_EXPR, arg4_type,
4909 prep_arg4,
4910 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4911 ffecom_2 (LSHIFT_EXPR, arg4_type,
4912 ffecom_1 (BIT_NOT_EXPR,
4913 arg4_type,
4914 convert
4915 (arg4_type,
4916 integer_zero_node)),
4917 arg5_tree))));
4918 prep_arg1
4919 = ffecom_2 (BIT_IOR_EXPR, arg4_type,
4920 prep_arg1,
4921 prep_arg4);
4922#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4923 prep_arg1
4924 = ffecom_3 (COND_EXPR, arg4_type,
4925 ffecom_truth_value
4926 (ffecom_2 (NE_EXPR, integer_type_node,
4927 arg3_tree,
4928 convert (TREE_TYPE (arg3_tree),
4929 integer_zero_node))),
4930 prep_arg1,
4931 arg4_tree);
4932 prep_arg1
4933 = ffecom_3 (COND_EXPR, arg4_type,
4934 ffecom_truth_value
4935 (ffecom_2 (NE_EXPR, integer_type_node,
4936 arg3_tree,
4937 convert (TREE_TYPE (arg3_tree),
4938 TYPE_SIZE (arg4_type)))),
4939 prep_arg1,
4940 arg1_tree);
4941#endif
4942 expr_tree
4943 = ffecom_2s (MODIFY_EXPR, void_type_node,
4944 arg4_tree,
4945 prep_arg1);
4946 /* Make sure SAVE_EXPRs get referenced early enough. */
4947 expr_tree
4948 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4949 arg1_tree,
4950 ffecom_2 (COMPOUND_EXPR, void_type_node,
4951 arg3_tree,
4952 ffecom_2 (COMPOUND_EXPR, void_type_node,
4953 arg5_tree,
4954 ffecom_2 (COMPOUND_EXPR, void_type_node,
4955 arg5_plus_arg3,
4956 expr_tree))));
4957 expr_tree
4958 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4959 arg4_tree,
4960 expr_tree);
4961
4962 }
4963 return expr_tree;
4964
4965 case FFEINTRIN_impDERF:
4966 case FFEINTRIN_impERF:
4967 case FFEINTRIN_impDERFC:
4968 case FFEINTRIN_impERFC:
4969 break;
4970
4971 case FFEINTRIN_impIARGC:
4972 /* extern int xargc; i__1 = xargc - 1; */
4973 expr_tree = ffecom_2 (MINUS_EXPR, TREE_TYPE (ffecom_tree_xargc_),
4974 ffecom_tree_xargc_,
4975 convert (TREE_TYPE (ffecom_tree_xargc_),
4976 integer_one_node));
4977 return expr_tree;
4978
4979 case FFEINTRIN_impSIGNAL_func:
4980 case FFEINTRIN_impSIGNAL_subr:
4981 {
4982 tree arg1_tree;
4983 tree arg2_tree;
4984 tree arg3_tree;
4985
5ff904cd
JL
4986 arg1_tree = convert (ffecom_f2c_integer_type_node,
4987 ffecom_expr (arg1));
4988 arg1_tree = ffecom_1 (ADDR_EXPR,
4989 build_pointer_type (TREE_TYPE (arg1_tree)),
4990 arg1_tree);
4991
4992 /* Pass procedure as a pointer to it, anything else by value. */
4993 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4994 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4995 else
4996 arg2_tree = ffecom_ptr_to_expr (arg2);
4997 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4998 arg2_tree);
4999
5000 if (arg3 != NULL)
c7e4ee3a 5001 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5002 else
5003 arg3_tree = NULL_TREE;
5004
5ff904cd
JL
5005 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5006 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5007 TREE_CHAIN (arg1_tree) = arg2_tree;
5008
5009 expr_tree
5010 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5011 ffecom_gfrt_kindtype (gfrt),
5012 FALSE,
5013 ((codegen_imp == FFEINTRIN_impSIGNAL_subr) ?
5014 NULL_TREE :
5015 tree_type),
5016 arg1_tree,
c7e4ee3a
CB
5017 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5018 ffebld_nonter_hook (expr));
5ff904cd
JL
5019
5020 if (arg3_tree != NULL_TREE)
5021 expr_tree
5022 = ffecom_modify (NULL_TREE, arg3_tree,
5023 convert (TREE_TYPE (arg3_tree),
5024 expr_tree));
5025 }
5026 return expr_tree;
5027
5028 case FFEINTRIN_impALARM:
5029 {
5030 tree arg1_tree;
5031 tree arg2_tree;
5032 tree arg3_tree;
5033
5ff904cd
JL
5034 arg1_tree = convert (ffecom_f2c_integer_type_node,
5035 ffecom_expr (arg1));
5036 arg1_tree = ffecom_1 (ADDR_EXPR,
5037 build_pointer_type (TREE_TYPE (arg1_tree)),
5038 arg1_tree);
5039
5040 /* Pass procedure as a pointer to it, anything else by value. */
5041 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
5042 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
5043 else
5044 arg2_tree = ffecom_ptr_to_expr (arg2);
5045 arg2_tree = convert (TREE_TYPE (null_pointer_node),
5046 arg2_tree);
5047
5048 if (arg3 != NULL)
c7e4ee3a 5049 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5050 else
5051 arg3_tree = NULL_TREE;
5052
5ff904cd
JL
5053 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5054 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5055 TREE_CHAIN (arg1_tree) = arg2_tree;
5056
5057 expr_tree
5058 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5059 ffecom_gfrt_kindtype (gfrt),
5060 FALSE,
5061 NULL_TREE,
5062 arg1_tree,
c7e4ee3a
CB
5063 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5064 ffebld_nonter_hook (expr));
5ff904cd
JL
5065
5066 if (arg3_tree != NULL_TREE)
5067 expr_tree
5068 = ffecom_modify (NULL_TREE, arg3_tree,
5069 convert (TREE_TYPE (arg3_tree),
5070 expr_tree));
5071 }
5072 return expr_tree;
5073
5074 case FFEINTRIN_impCHDIR_subr:
5075 case FFEINTRIN_impFDATE_subr:
5076 case FFEINTRIN_impFGET_subr:
5077 case FFEINTRIN_impFPUT_subr:
5078 case FFEINTRIN_impGETCWD_subr:
5079 case FFEINTRIN_impHOSTNM_subr:
5080 case FFEINTRIN_impSYSTEM_subr:
5081 case FFEINTRIN_impUNLINK_subr:
5082 {
5083 tree arg1_len = integer_zero_node;
5084 tree arg1_tree;
5085 tree arg2_tree;
5086
5ff904cd
JL
5087 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5088
5089 if (arg2 != NULL)
c7e4ee3a 5090 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
5ff904cd
JL
5091 else
5092 arg2_tree = NULL_TREE;
5093
5ff904cd
JL
5094 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5095 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5096 TREE_CHAIN (arg1_tree) = arg1_len;
5097
5098 expr_tree
5099 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5100 ffecom_gfrt_kindtype (gfrt),
5101 FALSE,
5102 NULL_TREE,
5103 arg1_tree,
c7e4ee3a
CB
5104 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5105 ffebld_nonter_hook (expr));
5ff904cd
JL
5106
5107 if (arg2_tree != NULL_TREE)
5108 expr_tree
5109 = ffecom_modify (NULL_TREE, arg2_tree,
5110 convert (TREE_TYPE (arg2_tree),
5111 expr_tree));
5112 }
5113 return expr_tree;
5114
5115 case FFEINTRIN_impEXIT:
5116 if (arg1 != NULL)
5117 break;
5118
5119 expr_tree = build_tree_list (NULL_TREE,
5120 ffecom_1 (ADDR_EXPR,
5121 build_pointer_type
5122 (ffecom_integer_type_node),
5123 integer_zero_node));
5124
5125 return
5126 ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5127 ffecom_gfrt_kindtype (gfrt),
5128 FALSE,
5129 void_type_node,
5130 expr_tree,
c7e4ee3a
CB
5131 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5132 ffebld_nonter_hook (expr));
5ff904cd
JL
5133
5134 case FFEINTRIN_impFLUSH:
5135 if (arg1 == NULL)
5136 gfrt = FFECOM_gfrtFLUSH;
5137 else
5138 gfrt = FFECOM_gfrtFLUSH1;
5139 break;
5140
5141 case FFEINTRIN_impCHMOD_subr:
5142 case FFEINTRIN_impLINK_subr:
5143 case FFEINTRIN_impRENAME_subr:
5144 case FFEINTRIN_impSYMLNK_subr:
5145 {
5146 tree arg1_len = integer_zero_node;
5147 tree arg1_tree;
5148 tree arg2_len = integer_zero_node;
5149 tree arg2_tree;
5150 tree arg3_tree;
5151
5ff904cd
JL
5152 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5153 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
5154 if (arg3 != NULL)
c7e4ee3a 5155 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5156 else
5157 arg3_tree = NULL_TREE;
5158
5ff904cd
JL
5159 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5160 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5161 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5162 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5163 TREE_CHAIN (arg1_tree) = arg2_tree;
5164 TREE_CHAIN (arg2_tree) = arg1_len;
5165 TREE_CHAIN (arg1_len) = arg2_len;
5166 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5167 ffecom_gfrt_kindtype (gfrt),
5168 FALSE,
5169 NULL_TREE,
5170 arg1_tree,
c7e4ee3a
CB
5171 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5172 ffebld_nonter_hook (expr));
5ff904cd
JL
5173 if (arg3_tree != NULL_TREE)
5174 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5175 convert (TREE_TYPE (arg3_tree),
5176 expr_tree));
5177 }
5178 return expr_tree;
5179
5180 case FFEINTRIN_impLSTAT_subr:
5181 case FFEINTRIN_impSTAT_subr:
5182 {
5183 tree arg1_len = integer_zero_node;
5184 tree arg1_tree;
5185 tree arg2_tree;
5186 tree arg3_tree;
5187
5ff904cd
JL
5188 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5189
5190 arg2_tree = ffecom_ptr_to_expr (arg2);
5191
5192 if (arg3 != NULL)
c7e4ee3a 5193 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5194 else
5195 arg3_tree = NULL_TREE;
5196
5ff904cd
JL
5197 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5198 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5199 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5200 TREE_CHAIN (arg1_tree) = arg2_tree;
5201 TREE_CHAIN (arg2_tree) = arg1_len;
5202 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5203 ffecom_gfrt_kindtype (gfrt),
5204 FALSE,
5205 NULL_TREE,
5206 arg1_tree,
c7e4ee3a
CB
5207 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5208 ffebld_nonter_hook (expr));
5ff904cd
JL
5209 if (arg3_tree != NULL_TREE)
5210 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5211 convert (TREE_TYPE (arg3_tree),
5212 expr_tree));
5213 }
5214 return expr_tree;
5215
5216 case FFEINTRIN_impFGETC_subr:
5217 case FFEINTRIN_impFPUTC_subr:
5218 {
5219 tree arg1_tree;
5220 tree arg2_tree;
5221 tree arg2_len = integer_zero_node;
5222 tree arg3_tree;
5223
5ff904cd
JL
5224 arg1_tree = convert (ffecom_f2c_integer_type_node,
5225 ffecom_expr (arg1));
5226 arg1_tree = ffecom_1 (ADDR_EXPR,
5227 build_pointer_type (TREE_TYPE (arg1_tree)),
5228 arg1_tree);
5229
5230 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
c7e4ee3a 5231 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5232
5233 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5234 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5235 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5236 TREE_CHAIN (arg1_tree) = arg2_tree;
5237 TREE_CHAIN (arg2_tree) = arg2_len;
5238
5239 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5240 ffecom_gfrt_kindtype (gfrt),
5241 FALSE,
5242 NULL_TREE,
5243 arg1_tree,
c7e4ee3a
CB
5244 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5245 ffebld_nonter_hook (expr));
5ff904cd
JL
5246 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5247 convert (TREE_TYPE (arg3_tree),
5248 expr_tree));
5249 }
5250 return expr_tree;
5251
5252 case FFEINTRIN_impFSTAT_subr:
5253 {
5254 tree arg1_tree;
5255 tree arg2_tree;
5256 tree arg3_tree;
5257
5ff904cd
JL
5258 arg1_tree = convert (ffecom_f2c_integer_type_node,
5259 ffecom_expr (arg1));
5260 arg1_tree = ffecom_1 (ADDR_EXPR,
5261 build_pointer_type (TREE_TYPE (arg1_tree)),
5262 arg1_tree);
5263
5264 arg2_tree = convert (ffecom_f2c_ptr_to_integer_type_node,
5265 ffecom_ptr_to_expr (arg2));
5266
5267 if (arg3 == NULL)
5268 arg3_tree = NULL_TREE;
5269 else
c7e4ee3a 5270 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5271
5272 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5273 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5274 TREE_CHAIN (arg1_tree) = arg2_tree;
5275 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5276 ffecom_gfrt_kindtype (gfrt),
5277 FALSE,
5278 NULL_TREE,
5279 arg1_tree,
c7e4ee3a
CB
5280 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5281 ffebld_nonter_hook (expr));
5ff904cd
JL
5282 if (arg3_tree != NULL_TREE) {
5283 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5284 convert (TREE_TYPE (arg3_tree),
5285 expr_tree));
5286 }
5287 }
5288 return expr_tree;
5289
5290 case FFEINTRIN_impKILL_subr:
5291 {
5292 tree arg1_tree;
5293 tree arg2_tree;
5294 tree arg3_tree;
5295
5ff904cd
JL
5296 arg1_tree = convert (ffecom_f2c_integer_type_node,
5297 ffecom_expr (arg1));
5298 arg1_tree = ffecom_1 (ADDR_EXPR,
5299 build_pointer_type (TREE_TYPE (arg1_tree)),
5300 arg1_tree);
5301
5302 arg2_tree = convert (ffecom_f2c_integer_type_node,
5303 ffecom_expr (arg2));
5304 arg2_tree = ffecom_1 (ADDR_EXPR,
5305 build_pointer_type (TREE_TYPE (arg2_tree)),
5306 arg2_tree);
5307
5308 if (arg3 == NULL)
5309 arg3_tree = NULL_TREE;
5310 else
c7e4ee3a 5311 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5ff904cd
JL
5312
5313 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5314 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5315 TREE_CHAIN (arg1_tree) = arg2_tree;
5316 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5317 ffecom_gfrt_kindtype (gfrt),
5318 FALSE,
5319 NULL_TREE,
5320 arg1_tree,
c7e4ee3a
CB
5321 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5322 ffebld_nonter_hook (expr));
5ff904cd
JL
5323 if (arg3_tree != NULL_TREE) {
5324 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5325 convert (TREE_TYPE (arg3_tree),
5326 expr_tree));
5327 }
5328 }
5329 return expr_tree;
5330
5331 case FFEINTRIN_impCTIME_subr:
5332 case FFEINTRIN_impTTYNAM_subr:
5333 {
5334 tree arg1_len = integer_zero_node;
5335 tree arg1_tree;
5336 tree arg2_tree;
5337
2b0bdd9a 5338 arg1_tree = ffecom_arg_ptr_to_expr (arg2, &arg1_len);
5ff904cd 5339
c56f65d6 5340 arg2_tree = convert (((codegen_imp == FFEINTRIN_impCTIME_subr) ?
5ff904cd
JL
5341 ffecom_f2c_longint_type_node :
5342 ffecom_f2c_integer_type_node),
2b0bdd9a 5343 ffecom_expr (arg1));
5ff904cd
JL
5344 arg2_tree = ffecom_1 (ADDR_EXPR,
5345 build_pointer_type (TREE_TYPE (arg2_tree)),
5346 arg2_tree);
5347
5ff904cd
JL
5348 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5349 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5350 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5351 TREE_CHAIN (arg1_len) = arg2_tree;
5352 TREE_CHAIN (arg1_tree) = arg1_len;
5353
5354 expr_tree
5355 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5356 ffecom_gfrt_kindtype (gfrt),
5357 FALSE,
5358 NULL_TREE,
5359 arg1_tree,
c7e4ee3a
CB
5360 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5361 ffebld_nonter_hook (expr));
2b0bdd9a 5362 TREE_SIDE_EFFECTS (expr_tree) = 1;
5ff904cd
JL
5363 }
5364 return expr_tree;
5365
5366 case FFEINTRIN_impIRAND:
5367 case FFEINTRIN_impRAND:
5368 /* Arg defaults to 0 (normal random case) */
5369 {
5370 tree arg1_tree;
5371
5372 if (arg1 == NULL)
5373 arg1_tree = ffecom_integer_zero_node;
5374 else
5375 arg1_tree = ffecom_expr (arg1);
5376 arg1_tree = convert (ffecom_f2c_integer_type_node,
5377 arg1_tree);
5378 arg1_tree = ffecom_1 (ADDR_EXPR,
5379 build_pointer_type (TREE_TYPE (arg1_tree)),
5380 arg1_tree);
5381 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5382
5383 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5384 ffecom_gfrt_kindtype (gfrt),
5385 FALSE,
5386 ((codegen_imp == FFEINTRIN_impIRAND) ?
5387 ffecom_f2c_integer_type_node :
de7f278a 5388 ffecom_f2c_real_type_node),
5ff904cd
JL
5389 arg1_tree,
5390 dest_tree, dest, dest_used,
c7e4ee3a
CB
5391 NULL_TREE, TRUE,
5392 ffebld_nonter_hook (expr));
5ff904cd
JL
5393 }
5394 return expr_tree;
5395
5396 case FFEINTRIN_impFTELL_subr:
5397 case FFEINTRIN_impUMASK_subr:
5398 {
5399 tree arg1_tree;
5400 tree arg2_tree;
5401
5ff904cd
JL
5402 arg1_tree = convert (ffecom_f2c_integer_type_node,
5403 ffecom_expr (arg1));
5404 arg1_tree = ffecom_1 (ADDR_EXPR,
5405 build_pointer_type (TREE_TYPE (arg1_tree)),
5406 arg1_tree);
5407
5408 if (arg2 == NULL)
5409 arg2_tree = NULL_TREE;
5410 else
c7e4ee3a 5411 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
5ff904cd
JL
5412
5413 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5414 ffecom_gfrt_kindtype (gfrt),
5415 FALSE,
5416 NULL_TREE,
5417 build_tree_list (NULL_TREE, arg1_tree),
5418 NULL_TREE, NULL, NULL, NULL_TREE,
c7e4ee3a
CB
5419 TRUE,
5420 ffebld_nonter_hook (expr));
5ff904cd
JL
5421 if (arg2_tree != NULL_TREE) {
5422 expr_tree = ffecom_modify (NULL_TREE, arg2_tree,
5423 convert (TREE_TYPE (arg2_tree),
5424 expr_tree));
5425 }
5426 }
5427 return expr_tree;
5428
5429 case FFEINTRIN_impCPU_TIME:
5430 case FFEINTRIN_impSECOND_subr:
5431 {
5432 tree arg1_tree;
5433
c7e4ee3a 5434 arg1_tree = ffecom_expr_w (NULL_TREE, arg1);
5ff904cd
JL
5435
5436 expr_tree
5437 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5438 ffecom_gfrt_kindtype (gfrt),
5439 FALSE,
5440 NULL_TREE,
5441 NULL_TREE,
c7e4ee3a
CB
5442 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5443 ffebld_nonter_hook (expr));
5ff904cd
JL
5444
5445 expr_tree
5446 = ffecom_modify (NULL_TREE, arg1_tree,
5447 convert (TREE_TYPE (arg1_tree),
5448 expr_tree));
5449 }
5450 return expr_tree;
5451
5452 case FFEINTRIN_impDTIME_subr:
5453 case FFEINTRIN_impETIME_subr:
5454 {
5455 tree arg1_tree;
2b0bdd9a 5456 tree result_tree;
5ff904cd 5457
2b0bdd9a 5458 result_tree = ffecom_expr_w (NULL_TREE, arg2);
5ff904cd 5459
2b0bdd9a 5460 arg1_tree = ffecom_ptr_to_expr (arg1);
5ff904cd 5461
5ff904cd
JL
5462 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5463 ffecom_gfrt_kindtype (gfrt),
5464 FALSE,
5465 NULL_TREE,
2b0bdd9a 5466 build_tree_list (NULL_TREE, arg1_tree),
5ff904cd 5467 NULL_TREE, NULL, NULL, NULL_TREE,
c7e4ee3a
CB
5468 TRUE,
5469 ffebld_nonter_hook (expr));
2b0bdd9a
CB
5470 expr_tree = ffecom_modify (NULL_TREE, result_tree,
5471 convert (TREE_TYPE (result_tree),
5ff904cd
JL
5472 expr_tree));
5473 }
5474 return expr_tree;
5475
c7e4ee3a 5476 /* Straightforward calls of libf2c routines: */
5ff904cd
JL
5477 case FFEINTRIN_impABORT:
5478 case FFEINTRIN_impACCESS:
5479 case FFEINTRIN_impBESJ0:
5480 case FFEINTRIN_impBESJ1:
5481 case FFEINTRIN_impBESJN:
5482 case FFEINTRIN_impBESY0:
5483 case FFEINTRIN_impBESY1:
5484 case FFEINTRIN_impBESYN:
5485 case FFEINTRIN_impCHDIR_func:
5486 case FFEINTRIN_impCHMOD_func:
5487 case FFEINTRIN_impDATE:
9e8e701d 5488 case FFEINTRIN_impDATE_AND_TIME:
5ff904cd
JL
5489 case FFEINTRIN_impDBESJ0:
5490 case FFEINTRIN_impDBESJ1:
5491 case FFEINTRIN_impDBESJN:
5492 case FFEINTRIN_impDBESY0:
5493 case FFEINTRIN_impDBESY1:
5494 case FFEINTRIN_impDBESYN:
5495 case FFEINTRIN_impDTIME_func:
5496 case FFEINTRIN_impETIME_func:
5497 case FFEINTRIN_impFGETC_func:
5498 case FFEINTRIN_impFGET_func:
5499 case FFEINTRIN_impFNUM:
5500 case FFEINTRIN_impFPUTC_func:
5501 case FFEINTRIN_impFPUT_func:
5502 case FFEINTRIN_impFSEEK:
5503 case FFEINTRIN_impFSTAT_func:
5504 case FFEINTRIN_impFTELL_func:
5505 case FFEINTRIN_impGERROR:
5506 case FFEINTRIN_impGETARG:
5507 case FFEINTRIN_impGETCWD_func:
5508 case FFEINTRIN_impGETENV:
5509 case FFEINTRIN_impGETGID:
5510 case FFEINTRIN_impGETLOG:
5511 case FFEINTRIN_impGETPID:
5512 case FFEINTRIN_impGETUID:
5513 case FFEINTRIN_impGMTIME:
5514 case FFEINTRIN_impHOSTNM_func:
5515 case FFEINTRIN_impIDATE_unix:
5516 case FFEINTRIN_impIDATE_vxt:
5517 case FFEINTRIN_impIERRNO:
5518 case FFEINTRIN_impISATTY:
5519 case FFEINTRIN_impITIME:
5520 case FFEINTRIN_impKILL_func:
5521 case FFEINTRIN_impLINK_func:
5522 case FFEINTRIN_impLNBLNK:
5523 case FFEINTRIN_impLSTAT_func:
5524 case FFEINTRIN_impLTIME:
5525 case FFEINTRIN_impMCLOCK8:
5526 case FFEINTRIN_impMCLOCK:
5527 case FFEINTRIN_impPERROR:
5528 case FFEINTRIN_impRENAME_func:
5529 case FFEINTRIN_impSECNDS:
5530 case FFEINTRIN_impSECOND_func:
5531 case FFEINTRIN_impSLEEP:
5532 case FFEINTRIN_impSRAND:
5533 case FFEINTRIN_impSTAT_func:
5534 case FFEINTRIN_impSYMLNK_func:
5535 case FFEINTRIN_impSYSTEM_CLOCK:
5536 case FFEINTRIN_impSYSTEM_func:
5537 case FFEINTRIN_impTIME8:
5538 case FFEINTRIN_impTIME_unix:
5539 case FFEINTRIN_impTIME_vxt:
5540 case FFEINTRIN_impUMASK_func:
5541 case FFEINTRIN_impUNLINK_func:
5542 break;
5543
5544 case FFEINTRIN_impCTIME_func: /* CHARACTER functions not handled here. */
5545 case FFEINTRIN_impFDATE_func: /* CHARACTER functions not handled here. */
5546 case FFEINTRIN_impTTYNAM_func: /* CHARACTER functions not handled here. */
5547 case FFEINTRIN_impNONE:
5548 case FFEINTRIN_imp: /* Hush up gcc warning. */
5549 fprintf (stderr, "No %s implementation.\n",
5550 ffeintrin_name_implementation (ffebld_symter_implementation (ffebld_left (expr))));
5551 assert ("unimplemented intrinsic" == NULL);
5552 return error_mark_node;
5553 }
5554
5555 assert (gfrt != FFECOM_gfrt); /* Must have an implementation! */
5556
5ff904cd
JL
5557 expr_tree = ffecom_arglist_expr_ (ffecom_gfrt_args_ (gfrt),
5558 ffebld_right (expr));
5ff904cd
JL
5559
5560 return ffecom_call_ (ffecom_gfrt_tree_ (gfrt), ffecom_gfrt_kindtype (gfrt),
5561 (ffe_is_f2c_library () && ffecom_gfrt_complex_[gfrt]),
5562 tree_type,
5563 expr_tree, dest_tree, dest, dest_used,
c7e4ee3a
CB
5564 NULL_TREE, TRUE,
5565 ffebld_nonter_hook (expr));
5ff904cd 5566
c7e4ee3a
CB
5567 /* See bottom of this file for f2c transforms used to determine
5568 many of the above implementations. The info seems to confuse
5569 Emacs's C mode indentation, which is why it's been moved to
5570 the bottom of this source file. */
5571}
5ff904cd 5572
c7e4ee3a
CB
5573#endif
5574/* For power (exponentiation) where right-hand operand is type INTEGER,
5575 generate in-line code to do it the fast way (which, if the operand
5576 is a constant, might just mean a series of multiplies). */
5ff904cd 5577
c7e4ee3a
CB
5578#if FFECOM_targetCURRENT == FFECOM_targetGCC
5579static tree
5580ffecom_expr_power_integer_ (ffebld expr)
5581{
5582 tree l = ffecom_expr (ffebld_left (expr));
5583 tree r = ffecom_expr (ffebld_right (expr));
5584 tree ltype = TREE_TYPE (l);
5585 tree rtype = TREE_TYPE (r);
5586 tree result = NULL_TREE;
5ff904cd 5587
c7e4ee3a
CB
5588 if (l == error_mark_node
5589 || r == error_mark_node)
5590 return error_mark_node;
5ff904cd 5591
c7e4ee3a
CB
5592 if (TREE_CODE (r) == INTEGER_CST)
5593 {
5594 int sgn = tree_int_cst_sgn (r);
5ff904cd 5595
c7e4ee3a
CB
5596 if (sgn == 0)
5597 return convert (ltype, integer_one_node);
5ff904cd 5598
c7e4ee3a
CB
5599 if ((TREE_CODE (ltype) == INTEGER_TYPE)
5600 && (sgn < 0))
5601 {
5602 /* Reciprocal of integer is either 0, -1, or 1, so after
5603 calculating that (which we leave to the back end to do
5604 or not do optimally), don't bother with any multiplying. */
5ff904cd 5605
c7e4ee3a
CB
5606 result = ffecom_tree_divide_ (ltype,
5607 convert (ltype, integer_one_node),
5608 l,
5609 NULL_TREE, NULL, NULL, NULL_TREE);
5610 r = ffecom_1 (NEGATE_EXPR,
5611 rtype,
5612 r);
5613 if ((TREE_INT_CST_LOW (r) & 1) == 0)
5614 result = ffecom_1 (ABS_EXPR, rtype,
5615 result);
5616 }
5ff904cd 5617
c7e4ee3a
CB
5618 /* Generate appropriate series of multiplies, preceded
5619 by divide if the exponent is negative. */
5ff904cd 5620
c7e4ee3a 5621 l = save_expr (l);
5ff904cd 5622
c7e4ee3a
CB
5623 if (sgn < 0)
5624 {
5625 l = ffecom_tree_divide_ (ltype,
5626 convert (ltype, integer_one_node),
5627 l,
5628 NULL_TREE, NULL, NULL,
5629 ffebld_nonter_hook (expr));
5630 r = ffecom_1 (NEGATE_EXPR, rtype, r);
5631 assert (TREE_CODE (r) == INTEGER_CST);
5ff904cd 5632
c7e4ee3a
CB
5633 if (tree_int_cst_sgn (r) < 0)
5634 { /* The "most negative" number. */
5635 r = ffecom_1 (NEGATE_EXPR, rtype,
5636 ffecom_2 (RSHIFT_EXPR, rtype,
5637 r,
5638 integer_one_node));
5639 l = save_expr (l);
5640 l = ffecom_2 (MULT_EXPR, ltype,
5641 l,
5642 l);
5643 }
5644 }
5ff904cd 5645
c7e4ee3a
CB
5646 for (;;)
5647 {
5648 if (TREE_INT_CST_LOW (r) & 1)
5649 {
5650 if (result == NULL_TREE)
5651 result = l;
5652 else
5653 result = ffecom_2 (MULT_EXPR, ltype,
5654 result,
5655 l);
5656 }
5ff904cd 5657
c7e4ee3a
CB
5658 r = ffecom_2 (RSHIFT_EXPR, rtype,
5659 r,
5660 integer_one_node);
5661 if (integer_zerop (r))
5662 break;
5663 assert (TREE_CODE (r) == INTEGER_CST);
5ff904cd 5664
c7e4ee3a
CB
5665 l = save_expr (l);
5666 l = ffecom_2 (MULT_EXPR, ltype,
5667 l,
5668 l);
5669 }
5670 return result;
5671 }
5ff904cd 5672
c7e4ee3a
CB
5673 /* Though rhs isn't a constant, in-line code cannot be expanded
5674 while transforming dummies
5675 because the back end cannot be easily convinced to generate
5676 stores (MODIFY_EXPR), handle temporaries, and so on before
5677 all the appropriate rtx's have been generated for things like
5678 dummy args referenced in rhs -- which doesn't happen until
5679 store_parm_decls() is called (expand_function_start, I believe,
5680 does the actual rtx-stuffing of PARM_DECLs).
5ff904cd 5681
c7e4ee3a
CB
5682 So, in this case, let the caller generate the call to the
5683 run-time-library function to evaluate the power for us. */
5ff904cd 5684
c7e4ee3a
CB
5685 if (ffecom_transform_only_dummies_)
5686 return NULL_TREE;
5ff904cd 5687
c7e4ee3a
CB
5688 /* Right-hand operand not a constant, expand in-line code to figure
5689 out how to do the multiplies, &c.
5ff904cd 5690
c7e4ee3a
CB
5691 The returned expression is expressed this way in GNU C, where l and
5692 r are the "inputs":
5ff904cd 5693
c7e4ee3a
CB
5694 ({ typeof (r) rtmp = r;
5695 typeof (l) ltmp = l;
5696 typeof (l) result;
5ff904cd 5697
c7e4ee3a
CB
5698 if (rtmp == 0)
5699 result = 1;
5700 else
5701 {
5702 if ((basetypeof (l) == basetypeof (int))
5703 && (rtmp < 0))
5704 {
5705 result = ((typeof (l)) 1) / ltmp;
5706 if ((ltmp < 0) && (((-rtmp) & 1) == 0))
5707 result = -result;
5708 }
5709 else
5710 {
5711 result = 1;
5712 if ((basetypeof (l) != basetypeof (int))
5713 && (rtmp < 0))
5714 {
5715 ltmp = ((typeof (l)) 1) / ltmp;
5716 rtmp = -rtmp;
5717 if (rtmp < 0)
5718 {
5719 rtmp = -(rtmp >> 1);
5720 ltmp *= ltmp;
5721 }
5722 }
5723 for (;;)
5724 {
5725 if (rtmp & 1)
5726 result *= ltmp;
5727 if ((rtmp >>= 1) == 0)
5728 break;
5729 ltmp *= ltmp;
5730 }
5731 }
5732 }
5733 result;
5734 })
5ff904cd 5735
c7e4ee3a
CB
5736 Note that some of the above is compile-time collapsable, such as
5737 the first part of the if statements that checks the base type of
5738 l against int. The if statements are phrased that way to suggest
5739 an easy way to generate the if/else constructs here, knowing that
5740 the back end should (and probably does) eliminate the resulting
5741 dead code (either the int case or the non-int case), something
5742 it couldn't do without the redundant phrasing, requiring explicit
5743 dead-code elimination here, which would be kind of difficult to
5744 read. */
5ff904cd 5745
c7e4ee3a
CB
5746 {
5747 tree rtmp;
5748 tree ltmp;
5749 tree divide;
5750 tree basetypeof_l_is_int;
5751 tree se;
5752 tree t;
5ff904cd 5753
c7e4ee3a
CB
5754 basetypeof_l_is_int
5755 = build_int_2 ((TREE_CODE (ltype) == INTEGER_TYPE), 0);
5ff904cd 5756
c7e4ee3a 5757 se = expand_start_stmt_expr ();
5ff904cd 5758
c7e4ee3a
CB
5759 ffecom_start_compstmt ();
5760
5761#ifndef HAHA
5762 rtmp = ffecom_make_tempvar ("power_r", rtype,
5763 FFETARGET_charactersizeNONE, -1);
5764 ltmp = ffecom_make_tempvar ("power_l", ltype,
5765 FFETARGET_charactersizeNONE, -1);
5766 result = ffecom_make_tempvar ("power_res", ltype,
5767 FFETARGET_charactersizeNONE, -1);
5768 if (TREE_CODE (ltype) == COMPLEX_TYPE
5769 || TREE_CODE (ltype) == RECORD_TYPE)
5770 divide = ffecom_make_tempvar ("power_div", ltype,
5771 FFETARGET_charactersizeNONE, -1);
5772 else
5773 divide = NULL_TREE;
5774#else /* HAHA */
5775 {
5776 tree hook;
5777
5778 hook = ffebld_nonter_hook (expr);
5779 assert (hook);
5780 assert (TREE_CODE (hook) == TREE_VEC);
5781 assert (TREE_VEC_LENGTH (hook) == 4);
5782 rtmp = TREE_VEC_ELT (hook, 0);
5783 ltmp = TREE_VEC_ELT (hook, 1);
5784 result = TREE_VEC_ELT (hook, 2);
5785 divide = TREE_VEC_ELT (hook, 3);
5786 if (TREE_CODE (ltype) == COMPLEX_TYPE
5787 || TREE_CODE (ltype) == RECORD_TYPE)
5788 assert (divide);
5789 else
5790 assert (! divide);
5791 }
5792#endif /* HAHA */
5ff904cd 5793
c7e4ee3a
CB
5794 expand_expr_stmt (ffecom_modify (void_type_node,
5795 rtmp,
5796 r));
5797 expand_expr_stmt (ffecom_modify (void_type_node,
5798 ltmp,
5799 l));
5800 expand_start_cond (ffecom_truth_value
5801 (ffecom_2 (EQ_EXPR, integer_type_node,
5802 rtmp,
5803 convert (rtype, integer_zero_node))),
5804 0);
5805 expand_expr_stmt (ffecom_modify (void_type_node,
5806 result,
5807 convert (ltype, integer_one_node)));
5808 expand_start_else ();
5809 if (! integer_zerop (basetypeof_l_is_int))
5810 {
5811 expand_start_cond (ffecom_2 (LT_EXPR, integer_type_node,
5812 rtmp,
5813 convert (rtype,
5814 integer_zero_node)),
5815 0);
5816 expand_expr_stmt (ffecom_modify (void_type_node,
5817 result,
5818 ffecom_tree_divide_
5819 (ltype,
5820 convert (ltype, integer_one_node),
5821 ltmp,
5822 NULL_TREE, NULL, NULL,
5823 divide)));
5824 expand_start_cond (ffecom_truth_value
5825 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5826 ffecom_2 (LT_EXPR, integer_type_node,
5827 ltmp,
5828 convert (ltype,
5829 integer_zero_node)),
5830 ffecom_2 (EQ_EXPR, integer_type_node,
5831 ffecom_2 (BIT_AND_EXPR,
5832 rtype,
5833 ffecom_1 (NEGATE_EXPR,
5834 rtype,
5835 rtmp),
5836 convert (rtype,
5837 integer_one_node)),
5838 convert (rtype,
5839 integer_zero_node)))),
5840 0);
5841 expand_expr_stmt (ffecom_modify (void_type_node,
5842 result,
5843 ffecom_1 (NEGATE_EXPR,
5844 ltype,
5845 result)));
5846 expand_end_cond ();
5847 expand_start_else ();
5848 }
5849 expand_expr_stmt (ffecom_modify (void_type_node,
5850 result,
5851 convert (ltype, integer_one_node)));
5852 expand_start_cond (ffecom_truth_value
5853 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5854 ffecom_truth_value_invert
5855 (basetypeof_l_is_int),
5856 ffecom_2 (LT_EXPR, integer_type_node,
5857 rtmp,
5858 convert (rtype,
5859 integer_zero_node)))),
5860 0);
5861 expand_expr_stmt (ffecom_modify (void_type_node,
5862 ltmp,
5863 ffecom_tree_divide_
5864 (ltype,
5865 convert (ltype, integer_one_node),
5866 ltmp,
5867 NULL_TREE, NULL, NULL,
5868 divide)));
5869 expand_expr_stmt (ffecom_modify (void_type_node,
5870 rtmp,
5871 ffecom_1 (NEGATE_EXPR, rtype,
5872 rtmp)));
5873 expand_start_cond (ffecom_truth_value
5874 (ffecom_2 (LT_EXPR, integer_type_node,
5875 rtmp,
5876 convert (rtype, integer_zero_node))),
5877 0);
5878 expand_expr_stmt (ffecom_modify (void_type_node,
5879 rtmp,
5880 ffecom_1 (NEGATE_EXPR, rtype,
5881 ffecom_2 (RSHIFT_EXPR,
5882 rtype,
5883 rtmp,
5884 integer_one_node))));
5885 expand_expr_stmt (ffecom_modify (void_type_node,
5886 ltmp,
5887 ffecom_2 (MULT_EXPR, ltype,
5888 ltmp,
5889 ltmp)));
5890 expand_end_cond ();
5891 expand_end_cond ();
5892 expand_start_loop (1);
5893 expand_start_cond (ffecom_truth_value
5894 (ffecom_2 (BIT_AND_EXPR, rtype,
5895 rtmp,
5896 convert (rtype, integer_one_node))),
5897 0);
5898 expand_expr_stmt (ffecom_modify (void_type_node,
5899 result,
5900 ffecom_2 (MULT_EXPR, ltype,
5901 result,
5902 ltmp)));
5903 expand_end_cond ();
5904 expand_exit_loop_if_false (NULL,
5905 ffecom_truth_value
5906 (ffecom_modify (rtype,
5907 rtmp,
5908 ffecom_2 (RSHIFT_EXPR,
5909 rtype,
5910 rtmp,
5911 integer_one_node))));
5912 expand_expr_stmt (ffecom_modify (void_type_node,
5913 ltmp,
5914 ffecom_2 (MULT_EXPR, ltype,
5915 ltmp,
5916 ltmp)));
5917 expand_end_loop ();
5918 expand_end_cond ();
5919 if (!integer_zerop (basetypeof_l_is_int))
5920 expand_end_cond ();
5921 expand_expr_stmt (result);
5ff904cd 5922
c7e4ee3a 5923 t = ffecom_end_compstmt ();
5ff904cd 5924
c7e4ee3a 5925 result = expand_end_stmt_expr (se);
5ff904cd 5926
c7e4ee3a 5927 /* This code comes from c-parse.in, after its expand_end_stmt_expr. */
5ff904cd 5928
c7e4ee3a
CB
5929 if (TREE_CODE (t) == BLOCK)
5930 {
5931 /* Make a BIND_EXPR for the BLOCK already made. */
5932 result = build (BIND_EXPR, TREE_TYPE (result),
5933 NULL_TREE, result, t);
5934 /* Remove the block from the tree at this point.
5935 It gets put back at the proper place
5936 when the BIND_EXPR is expanded. */
5937 delete_block (t);
5938 }
5939 else
5940 result = t;
5941 }
5ff904cd 5942
c7e4ee3a
CB
5943 return result;
5944}
5ff904cd 5945
c7e4ee3a
CB
5946#endif
5947/* ffecom_expr_transform_ -- Transform symbols in expr
5ff904cd 5948
c7e4ee3a
CB
5949 ffebld expr; // FFE expression.
5950 ffecom_expr_transform_ (expr);
5ff904cd 5951
c7e4ee3a 5952 Recursive descent on expr while transforming any untransformed SYMTERs. */
5ff904cd 5953
c7e4ee3a
CB
5954#if FFECOM_targetCURRENT == FFECOM_targetGCC
5955static void
5956ffecom_expr_transform_ (ffebld expr)
5957{
5958 tree t;
5959 ffesymbol s;
5ff904cd 5960
c7e4ee3a 5961tail_recurse: /* :::::::::::::::::::: */
5ff904cd 5962
c7e4ee3a
CB
5963 if (expr == NULL)
5964 return;
5ff904cd 5965
c7e4ee3a
CB
5966 switch (ffebld_op (expr))
5967 {
5968 case FFEBLD_opSYMTER:
5969 s = ffebld_symter (expr);
5970 t = ffesymbol_hook (s).decl_tree;
5971 if ((t == NULL_TREE)
5972 && ((ffesymbol_kind (s) != FFEINFO_kindNONE)
5973 || ((ffesymbol_where (s) != FFEINFO_whereNONE)
5974 && (ffesymbol_where (s) != FFEINFO_whereINTRINSIC))))
5975 {
5976 s = ffecom_sym_transform_ (s);
5977 t = ffesymbol_hook (s).decl_tree; /* Sfunc expr non-dummy,
5978 DIMENSION expr? */
5979 }
5980 break; /* Ok if (t == NULL) here. */
5ff904cd 5981
c7e4ee3a
CB
5982 case FFEBLD_opITEM:
5983 ffecom_expr_transform_ (ffebld_head (expr));
5984 expr = ffebld_trail (expr);
5985 goto tail_recurse; /* :::::::::::::::::::: */
5ff904cd 5986
c7e4ee3a
CB
5987 default:
5988 break;
5989 }
5ff904cd 5990
c7e4ee3a
CB
5991 switch (ffebld_arity (expr))
5992 {
5993 case 2:
5994 ffecom_expr_transform_ (ffebld_left (expr));
5995 expr = ffebld_right (expr);
5996 goto tail_recurse; /* :::::::::::::::::::: */
5ff904cd 5997
c7e4ee3a
CB
5998 case 1:
5999 expr = ffebld_left (expr);
6000 goto tail_recurse; /* :::::::::::::::::::: */
5ff904cd 6001
c7e4ee3a
CB
6002 default:
6003 break;
6004 }
5ff904cd 6005
c7e4ee3a
CB
6006 return;
6007}
5ff904cd 6008
c7e4ee3a
CB
6009#endif
6010/* Make a type based on info in live f2c.h file. */
5ff904cd 6011
c7e4ee3a
CB
6012#if FFECOM_targetCURRENT == FFECOM_targetGCC
6013static void
6014ffecom_f2c_make_type_ (tree *type, int tcode, const char *name)
6015{
6016 switch (tcode)
6017 {
6018 case FFECOM_f2ccodeCHAR:
6019 *type = make_signed_type (CHAR_TYPE_SIZE);
6020 break;
5ff904cd 6021
c7e4ee3a
CB
6022 case FFECOM_f2ccodeSHORT:
6023 *type = make_signed_type (SHORT_TYPE_SIZE);
6024 break;
5ff904cd 6025
c7e4ee3a
CB
6026 case FFECOM_f2ccodeINT:
6027 *type = make_signed_type (INT_TYPE_SIZE);
6028 break;
5ff904cd 6029
c7e4ee3a
CB
6030 case FFECOM_f2ccodeLONG:
6031 *type = make_signed_type (LONG_TYPE_SIZE);
6032 break;
5ff904cd 6033
c7e4ee3a
CB
6034 case FFECOM_f2ccodeLONGLONG:
6035 *type = make_signed_type (LONG_LONG_TYPE_SIZE);
6036 break;
5ff904cd 6037
c7e4ee3a
CB
6038 case FFECOM_f2ccodeCHARPTR:
6039 *type = build_pointer_type (DEFAULT_SIGNED_CHAR
6040 ? signed_char_type_node
6041 : unsigned_char_type_node);
6042 break;
5ff904cd 6043
c7e4ee3a
CB
6044 case FFECOM_f2ccodeFLOAT:
6045 *type = make_node (REAL_TYPE);
6046 TYPE_PRECISION (*type) = FLOAT_TYPE_SIZE;
6047 layout_type (*type);
6048 break;
6049
6050 case FFECOM_f2ccodeDOUBLE:
6051 *type = make_node (REAL_TYPE);
6052 TYPE_PRECISION (*type) = DOUBLE_TYPE_SIZE;
6053 layout_type (*type);
6054 break;
6055
6056 case FFECOM_f2ccodeLONGDOUBLE:
6057 *type = make_node (REAL_TYPE);
6058 TYPE_PRECISION (*type) = LONG_DOUBLE_TYPE_SIZE;
6059 layout_type (*type);
6060 break;
5ff904cd 6061
c7e4ee3a
CB
6062 case FFECOM_f2ccodeTWOREALS:
6063 *type = ffecom_make_complex_type_ (ffecom_f2c_real_type_node);
6064 break;
5ff904cd 6065
c7e4ee3a
CB
6066 case FFECOM_f2ccodeTWODOUBLEREALS:
6067 *type = ffecom_make_complex_type_ (ffecom_f2c_doublereal_type_node);
6068 break;
5ff904cd 6069
c7e4ee3a
CB
6070 default:
6071 assert ("unexpected FFECOM_f2ccodeXYZZY!" == NULL);
6072 *type = error_mark_node;
6073 return;
6074 }
5ff904cd 6075
c7e4ee3a
CB
6076 pushdecl (build_decl (TYPE_DECL,
6077 ffecom_get_invented_identifier ("__g77_f2c_%s",
6078 name, -1),
6079 *type));
6080}
5ff904cd 6081
c7e4ee3a
CB
6082#endif
6083#if FFECOM_targetCURRENT == FFECOM_targetGCC
6084/* Set the f2c list-directed-I/O code for whatever (integral) type has the
6085 given size. */
5ff904cd 6086
c7e4ee3a
CB
6087static void
6088ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
6089 int code)
6090{
6091 int j;
6092 tree t;
5ff904cd 6093
c7e4ee3a
CB
6094 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
6095 if (((t = ffecom_tree_type[bt][j]) != NULL_TREE)
6096 && (TREE_INT_CST_LOW (TYPE_SIZE (t)) == size))
6097 {
6098 assert (code != -1);
6099 ffecom_f2c_typecode_[bt][j] = code;
6100 code = -1;
6101 }
6102}
5ff904cd 6103
c7e4ee3a
CB
6104#endif
6105/* Finish up globals after doing all program units in file
5ff904cd 6106
c7e4ee3a 6107 Need to handle only uninitialized COMMON areas. */
5ff904cd 6108
c7e4ee3a
CB
6109#if FFECOM_targetCURRENT == FFECOM_targetGCC
6110static ffeglobal
6111ffecom_finish_global_ (ffeglobal global)
6112{
6113 tree cbtype;
6114 tree cbt;
6115 tree size;
5ff904cd 6116
c7e4ee3a
CB
6117 if (ffeglobal_type (global) != FFEGLOBAL_typeCOMMON)
6118 return global;
5ff904cd 6119
c7e4ee3a
CB
6120 if (ffeglobal_common_init (global))
6121 return global;
5ff904cd 6122
c7e4ee3a
CB
6123 cbt = ffeglobal_hook (global);
6124 if ((cbt == NULL_TREE)
6125 || !ffeglobal_common_have_size (global))
6126 return global; /* No need to make common, never ref'd. */
5ff904cd 6127
c7e4ee3a 6128 suspend_momentary ();
5ff904cd 6129
c7e4ee3a 6130 DECL_EXTERNAL (cbt) = 0;
5ff904cd 6131
c7e4ee3a 6132 /* Give the array a size now. */
5ff904cd 6133
c7e4ee3a
CB
6134 size = build_int_2 ((ffeglobal_common_size (global)
6135 + ffeglobal_common_pad (global)) - 1,
6136 0);
5ff904cd 6137
c7e4ee3a
CB
6138 cbtype = TREE_TYPE (cbt);
6139 TYPE_DOMAIN (cbtype) = build_range_type (integer_type_node,
6140 integer_zero_node,
6141 size);
6142 if (!TREE_TYPE (size))
6143 TREE_TYPE (size) = TYPE_DOMAIN (cbtype);
6144 layout_type (cbtype);
5ff904cd 6145
c7e4ee3a
CB
6146 cbt = start_decl (cbt, FALSE);
6147 assert (cbt == ffeglobal_hook (global));
5ff904cd 6148
c7e4ee3a 6149 finish_decl (cbt, NULL_TREE, FALSE);
5ff904cd 6150
c7e4ee3a
CB
6151 return global;
6152}
5ff904cd 6153
c7e4ee3a
CB
6154#endif
6155/* Finish up any untransformed symbols. */
5ff904cd 6156
c7e4ee3a
CB
6157#if FFECOM_targetCURRENT == FFECOM_targetGCC
6158static ffesymbol
6159ffecom_finish_symbol_transform_ (ffesymbol s)
5ff904cd 6160{
c7e4ee3a
CB
6161 if ((s == NULL) || (TREE_CODE (current_function_decl) == ERROR_MARK))
6162 return s;
5ff904cd 6163
c7e4ee3a
CB
6164 /* It's easy to know to transform an untransformed symbol, to make sure
6165 we put out debugging info for it. But COMMON variables, unlike
6166 EQUIVALENCE ones, aren't given declarations in addition to the
6167 tree expressions that specify offsets, because COMMON variables
6168 can be referenced in the outer scope where only dummy arguments
6169 (PARM_DECLs) should really be seen. To be safe, just don't do any
6170 VAR_DECLs for COMMON variables when we transform them for real
6171 use, and therefore we do all the VAR_DECL creating here. */
5ff904cd 6172
c7e4ee3a
CB
6173 if (ffesymbol_hook (s).decl_tree == NULL_TREE)
6174 {
6175 if (ffesymbol_kind (s) != FFEINFO_kindNONE
6176 || (ffesymbol_where (s) != FFEINFO_whereNONE
6177 && ffesymbol_where (s) != FFEINFO_whereINTRINSIC
6178 && ffesymbol_where (s) != FFEINFO_whereDUMMY))
6179 /* Not transformed, and not CHARACTER*(*), and not a dummy
6180 argument, which can happen only if the entry point names
6181 it "rides in on" are all invalidated for other reasons. */
6182 s = ffecom_sym_transform_ (s);
6183 }
5ff904cd 6184
c7e4ee3a
CB
6185 if ((ffesymbol_where (s) == FFEINFO_whereCOMMON)
6186 && (ffesymbol_hook (s).decl_tree != error_mark_node))
6187 {
6188#ifdef SOMEONE_GETS_DEBUG_SUPPORT_WORKING
6189 int yes = suspend_momentary ();
5ff904cd 6190
c7e4ee3a
CB
6191 /* This isn't working, at least for dbxout. The .s file looks
6192 okay to me (burley), but in gdb 4.9 at least, the variables
6193 appear to reside somewhere outside of the common area, so
6194 it doesn't make sense to mislead anyone by generating the info
6195 on those variables until this is fixed. NOTE: Same problem
6196 with EQUIVALENCE, sadly...see similar #if later. */
6197 ffecom_member_phase2_ (ffesymbol_storage (ffesymbol_common (s)),
6198 ffesymbol_storage (s));
5ff904cd 6199
c7e4ee3a
CB
6200 resume_momentary (yes);
6201#endif
5ff904cd
JL
6202 }
6203
c7e4ee3a
CB
6204 return s;
6205}
5ff904cd 6206
c7e4ee3a
CB
6207#endif
6208/* Append underscore(s) to name before calling get_identifier. "us"
6209 is nonzero if the name already contains an underscore and thus
6210 needs two underscores appended. */
5ff904cd 6211
c7e4ee3a
CB
6212#if FFECOM_targetCURRENT == FFECOM_targetGCC
6213static tree
6214ffecom_get_appended_identifier_ (char us, const char *name)
6215{
6216 int i;
6217 char *newname;
6218 tree id;
5ff904cd 6219
c7e4ee3a
CB
6220 newname = xmalloc ((i = strlen (name)) + 1
6221 + ffe_is_underscoring ()
6222 + us);
6223 memcpy (newname, name, i);
6224 newname[i] = '_';
6225 newname[i + us] = '_';
6226 newname[i + 1 + us] = '\0';
6227 id = get_identifier (newname);
5ff904cd 6228
c7e4ee3a 6229 free (newname);
5ff904cd 6230
c7e4ee3a
CB
6231 return id;
6232}
5ff904cd 6233
c7e4ee3a
CB
6234#endif
6235/* Decide whether to append underscore to name before calling
6236 get_identifier. */
5ff904cd 6237
c7e4ee3a
CB
6238#if FFECOM_targetCURRENT == FFECOM_targetGCC
6239static tree
6240ffecom_get_external_identifier_ (ffesymbol s)
6241{
6242 char us;
6243 const char *name = ffesymbol_text (s);
5ff904cd 6244
c7e4ee3a 6245 /* If name is a built-in name, just return it as is. */
5ff904cd 6246
c7e4ee3a
CB
6247 if (!ffe_is_underscoring ()
6248 || (strcmp (name, FFETARGET_nameBLANK_COMMON) == 0)
6249#if FFETARGET_isENFORCED_MAIN_NAME
6250 || (strcmp (name, FFETARGET_nameENFORCED_NAME) == 0)
6251#else
6252 || (strcmp (name, FFETARGET_nameUNNAMED_MAIN) == 0)
6253#endif
6254 || (strcmp (name, FFETARGET_nameUNNAMED_BLOCK_DATA) == 0))
6255 return get_identifier (name);
5ff904cd 6256
c7e4ee3a
CB
6257 us = ffe_is_second_underscore ()
6258 ? (strchr (name, '_') != NULL)
6259 : 0;
5ff904cd 6260
c7e4ee3a
CB
6261 return ffecom_get_appended_identifier_ (us, name);
6262}
5ff904cd 6263
c7e4ee3a
CB
6264#endif
6265/* Decide whether to append underscore to internal name before calling
6266 get_identifier.
6267
6268 This is for non-external, top-function-context names only. Transform
6269 identifier so it doesn't conflict with the transformed result
6270 of using a _different_ external name. E.g. if "CALL FOO" is
6271 transformed into "FOO_();", then the variable in "FOO_ = 3"
6272 must be transformed into something that does not conflict, since
6273 these two things should be independent.
5ff904cd 6274
c7e4ee3a
CB
6275 The transformation is as follows. If the name does not contain
6276 an underscore, there is no possible conflict, so just return.
6277 If the name does contain an underscore, then transform it just
6278 like we transform an external identifier. */
5ff904cd 6279
c7e4ee3a
CB
6280#if FFECOM_targetCURRENT == FFECOM_targetGCC
6281static tree
6282ffecom_get_identifier_ (const char *name)
6283{
6284 /* If name does not contain an underscore, just return it as is. */
6285
6286 if (!ffe_is_underscoring ()
6287 || (strchr (name, '_') == NULL))
6288 return get_identifier (name);
6289
6290 return ffecom_get_appended_identifier_ (ffe_is_second_underscore (),
6291 name);
5ff904cd
JL
6292}
6293
6294#endif
c7e4ee3a 6295/* ffecom_gen_sfuncdef_ -- Generate definition of statement function
5ff904cd 6296
c7e4ee3a
CB
6297 tree t;
6298 ffesymbol s; // kindFUNCTION, whereIMMEDIATE.
6299 t = ffecom_gen_sfuncdef_(s,ffesymbol_basictype(s),
6300 ffesymbol_kindtype(s));
5ff904cd 6301
c7e4ee3a
CB
6302 Call after setting up containing function and getting trees for all
6303 other symbols. */
5ff904cd
JL
6304
6305#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
6306static tree
6307ffecom_gen_sfuncdef_ (ffesymbol s, ffeinfoBasictype bt, ffeinfoKindtype kt)
5ff904cd 6308{
c7e4ee3a
CB
6309 ffebld expr = ffesymbol_sfexpr (s);
6310 tree type;
6311 tree func;
6312 tree result;
6313 bool charfunc = (bt == FFEINFO_basictypeCHARACTER);
6314 static bool recurse = FALSE;
6315 int yes;
6316 int old_lineno = lineno;
6317 char *old_input_filename = input_filename;
5ff904cd 6318
c7e4ee3a 6319 ffecom_nested_entry_ = s;
5ff904cd 6320
c7e4ee3a
CB
6321 /* For now, we don't have a handy pointer to where the sfunc is actually
6322 defined, though that should be easy to add to an ffesymbol. (The
6323 token/where info available might well point to the place where the type
6324 of the sfunc is declared, especially if that precedes the place where
6325 the sfunc itself is defined, which is typically the case.) We should
6326 put out a null pointer rather than point somewhere wrong, but I want to
6327 see how it works at this point. */
5ff904cd 6328
c7e4ee3a
CB
6329 input_filename = ffesymbol_where_filename (s);
6330 lineno = ffesymbol_where_filelinenum (s);
5ff904cd 6331
c7e4ee3a
CB
6332 /* Pretransform the expression so any newly discovered things belong to the
6333 outer program unit, not to the statement function. */
5ff904cd 6334
c7e4ee3a 6335 ffecom_expr_transform_ (expr);
5ff904cd 6336
c7e4ee3a
CB
6337 /* Make sure no recursive invocation of this fn (a specific case of failing
6338 to pretransform an sfunc's expression, i.e. where its expression
6339 references another untransformed sfunc) happens. */
6340
6341 assert (!recurse);
6342 recurse = TRUE;
6343
6344 yes = suspend_momentary ();
6345
6346 push_f_function_context ();
6347
6348 if (charfunc)
6349 type = void_type_node;
6350 else
5ff904cd 6351 {
c7e4ee3a
CB
6352 type = ffecom_tree_type[bt][kt];
6353 if (type == NULL_TREE)
6354 type = integer_type_node; /* _sym_exec_transition reports
6355 error. */
6356 }
5ff904cd 6357
c7e4ee3a
CB
6358 start_function (ffecom_get_identifier_ (ffesymbol_text (s)),
6359 build_function_type (type, NULL_TREE),
6360 1, /* nested/inline */
6361 0); /* TREE_PUBLIC */
5ff904cd 6362
c7e4ee3a
CB
6363 /* We don't worry about COMPLEX return values here, because this is
6364 entirely internal to our code, and gcc has the ability to return COMPLEX
6365 directly as a value. */
6366
6367 yes = suspend_momentary ();
6368
6369 if (charfunc)
6370 { /* Prepend arg for where result goes. */
6371 tree type;
6372
6373 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
6374
6375 result = ffecom_get_invented_identifier ("__g77_%s",
6376 "result", -1);
6377
6378 ffecom_char_enhance_arg_ (&type, s); /* Ignore returned length. */
6379
6380 type = build_pointer_type (type);
6381 result = build_decl (PARM_DECL, result, type);
6382
6383 push_parm_decl (result);
5ff904cd 6384 }
c7e4ee3a
CB
6385 else
6386 result = NULL_TREE; /* Not ref'd if !charfunc. */
5ff904cd 6387
c7e4ee3a 6388 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (s), TRUE);
5ff904cd 6389
c7e4ee3a 6390 resume_momentary (yes);
5ff904cd 6391
c7e4ee3a
CB
6392 store_parm_decls (0);
6393
6394 ffecom_start_compstmt ();
6395
6396 if (expr != NULL)
5ff904cd 6397 {
c7e4ee3a
CB
6398 if (charfunc)
6399 {
6400 ffetargetCharacterSize sz = ffesymbol_size (s);
6401 tree result_length;
5ff904cd 6402
c7e4ee3a
CB
6403 result_length = build_int_2 (sz, 0);
6404 TREE_TYPE (result_length) = ffecom_f2c_ftnlen_type_node;
5ff904cd 6405
c7e4ee3a 6406 ffecom_prepare_let_char_ (sz, expr);
5ff904cd 6407
c7e4ee3a 6408 ffecom_prepare_end ();
5ff904cd 6409
c7e4ee3a
CB
6410 ffecom_let_char_ (result, result_length, sz, expr);
6411 expand_null_return ();
6412 }
6413 else
6414 {
6415 ffecom_prepare_expr (expr);
5ff904cd 6416
c7e4ee3a 6417 ffecom_prepare_end ();
5ff904cd 6418
c7e4ee3a
CB
6419 expand_return (ffecom_modify (NULL_TREE,
6420 DECL_RESULT (current_function_decl),
6421 ffecom_expr (expr)));
6422 }
5ff904cd 6423
c7e4ee3a
CB
6424 clear_momentary ();
6425 }
5ff904cd 6426
c7e4ee3a 6427 ffecom_end_compstmt ();
5ff904cd 6428
c7e4ee3a
CB
6429 func = current_function_decl;
6430 finish_function (1);
5ff904cd 6431
c7e4ee3a 6432 pop_f_function_context ();
5ff904cd 6433
c7e4ee3a 6434 resume_momentary (yes);
5ff904cd 6435
c7e4ee3a
CB
6436 recurse = FALSE;
6437
6438 lineno = old_lineno;
6439 input_filename = old_input_filename;
6440
6441 ffecom_nested_entry_ = NULL;
6442
6443 return func;
5ff904cd
JL
6444}
6445
6446#endif
5ff904cd 6447
c7e4ee3a
CB
6448#if FFECOM_targetCURRENT == FFECOM_targetGCC
6449static const char *
6450ffecom_gfrt_args_ (ffecomGfrt ix)
5ff904cd 6451{
c7e4ee3a
CB
6452 return ffecom_gfrt_argstring_[ix];
6453}
5ff904cd 6454
c7e4ee3a
CB
6455#endif
6456#if FFECOM_targetCURRENT == FFECOM_targetGCC
6457static tree
6458ffecom_gfrt_tree_ (ffecomGfrt ix)
6459{
6460 if (ffecom_gfrt_[ix] == NULL_TREE)
6461 ffecom_make_gfrt_ (ix);
6462
6463 return ffecom_1 (ADDR_EXPR,
6464 build_pointer_type (TREE_TYPE (ffecom_gfrt_[ix])),
6465 ffecom_gfrt_[ix]);
5ff904cd
JL
6466}
6467
6468#endif
c7e4ee3a 6469/* Return initialize-to-zero expression for this VAR_DECL. */
5ff904cd
JL
6470
6471#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
6472static tree
6473ffecom_init_zero_ (tree decl)
5ff904cd 6474{
c7e4ee3a
CB
6475 tree init;
6476 int incremental = TREE_STATIC (decl);
6477 tree type = TREE_TYPE (decl);
5ff904cd 6478
c7e4ee3a
CB
6479 if (incremental)
6480 {
6481 int momentary = suspend_momentary ();
6482 push_obstacks_nochange ();
6483 if (TREE_PERMANENT (decl))
6484 end_temporary_allocation ();
6485 make_decl_rtl (decl, NULL, TREE_PUBLIC (decl) ? 1 : 0);
6486 assemble_variable (decl, TREE_PUBLIC (decl) ? 1 : 0, 0, 1);
6487 pop_obstacks ();
6488 resume_momentary (momentary);
6489 }
5ff904cd 6490
c7e4ee3a 6491 push_momentary ();
5ff904cd 6492
c7e4ee3a
CB
6493 if ((TREE_CODE (type) != ARRAY_TYPE)
6494 && (TREE_CODE (type) != RECORD_TYPE)
6495 && (TREE_CODE (type) != UNION_TYPE)
6496 && !incremental)
6497 init = convert (type, integer_zero_node);
6498 else if (!incremental)
6499 {
6500 int momentary = suspend_momentary ();
5ff904cd 6501
c7e4ee3a
CB
6502 init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
6503 TREE_CONSTANT (init) = 1;
6504 TREE_STATIC (init) = 1;
5ff904cd 6505
c7e4ee3a
CB
6506 resume_momentary (momentary);
6507 }
6508 else
6509 {
6510 int momentary = suspend_momentary ();
5ff904cd 6511
c7e4ee3a
CB
6512 assemble_zeros (int_size_in_bytes (type));
6513 init = error_mark_node;
5ff904cd 6514
c7e4ee3a
CB
6515 resume_momentary (momentary);
6516 }
5ff904cd 6517
c7e4ee3a 6518 pop_momentary_nofree ();
5ff904cd 6519
c7e4ee3a 6520 return init;
5ff904cd
JL
6521}
6522
6523#endif
5ff904cd 6524#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
6525static tree
6526ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
6527 tree *maybe_tree)
5ff904cd 6528{
c7e4ee3a
CB
6529 tree expr_tree;
6530 tree length_tree;
5ff904cd 6531
c7e4ee3a 6532 switch (ffebld_op (arg))
6829256f 6533 {
c7e4ee3a
CB
6534 case FFEBLD_opCONTER: /* For F90, check 0-length. */
6535 if (ffetarget_length_character1
6536 (ffebld_constant_character1
6537 (ffebld_conter (arg))) == 0)
6538 {
6539 *maybe_tree = integer_zero_node;
6540 return convert (tree_type, integer_zero_node);
6541 }
5ff904cd 6542
c7e4ee3a
CB
6543 *maybe_tree = integer_one_node;
6544 expr_tree = build_int_2 (*ffetarget_text_character1
6545 (ffebld_constant_character1
6546 (ffebld_conter (arg))),
6547 0);
6548 TREE_TYPE (expr_tree) = tree_type;
6549 return expr_tree;
5ff904cd 6550
c7e4ee3a
CB
6551 case FFEBLD_opSYMTER:
6552 case FFEBLD_opARRAYREF:
6553 case FFEBLD_opFUNCREF:
6554 case FFEBLD_opSUBSTR:
6555 ffecom_char_args_ (&expr_tree, &length_tree, arg);
5ff904cd 6556
c7e4ee3a
CB
6557 if ((expr_tree == error_mark_node)
6558 || (length_tree == error_mark_node))
6559 {
6560 *maybe_tree = error_mark_node;
6561 return error_mark_node;
6562 }
5ff904cd 6563
c7e4ee3a
CB
6564 if (integer_zerop (length_tree))
6565 {
6566 *maybe_tree = integer_zero_node;
6567 return convert (tree_type, integer_zero_node);
6568 }
6569
6570 expr_tree
6571 = ffecom_1 (INDIRECT_REF,
6572 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6573 expr_tree);
6574 expr_tree
6575 = ffecom_2 (ARRAY_REF,
6576 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6577 expr_tree,
6578 integer_one_node);
6579 expr_tree = convert (tree_type, expr_tree);
6580
6581 if (TREE_CODE (length_tree) == INTEGER_CST)
6582 *maybe_tree = integer_one_node;
6583 else /* Must check length at run time. */
6584 *maybe_tree
6585 = ffecom_truth_value
6586 (ffecom_2 (GT_EXPR, integer_type_node,
6587 length_tree,
6588 ffecom_f2c_ftnlen_zero_node));
6589 return expr_tree;
6590
6591 case FFEBLD_opPAREN:
6592 case FFEBLD_opCONVERT:
6593 if (ffeinfo_size (ffebld_info (arg)) == 0)
6594 {
6595 *maybe_tree = integer_zero_node;
6596 return convert (tree_type, integer_zero_node);
6597 }
6598 return ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6599 maybe_tree);
6600
6601 case FFEBLD_opCONCATENATE:
6602 {
6603 tree maybe_left;
6604 tree maybe_right;
6605 tree expr_left;
6606 tree expr_right;
6607
6608 expr_left = ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6609 &maybe_left);
6610 expr_right = ffecom_intrinsic_ichar_ (tree_type, ffebld_right (arg),
6611 &maybe_right);
6612 *maybe_tree = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
6613 maybe_left,
6614 maybe_right);
6615 expr_tree = ffecom_3 (COND_EXPR, tree_type,
6616 maybe_left,
6617 expr_left,
6618 expr_right);
6619 return expr_tree;
6620 }
6621
6622 default:
6623 assert ("bad op in ICHAR" == NULL);
6624 return error_mark_node;
6625 }
5ff904cd
JL
6626}
6627
6628#endif
c7e4ee3a
CB
6629/* ffecom_intrinsic_len_ -- Return length info for char arg (LEN())
6630
6631 tree length_arg;
6632 ffebld expr;
6633 length_arg = ffecom_intrinsic_len_ (expr);
6634
6635 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
6636 subexpressions by constructing the appropriate tree for the
6637 length-of-character-text argument in a calling sequence. */
5ff904cd
JL
6638
6639#if FFECOM_targetCURRENT == FFECOM_targetGCC
6640static tree
c7e4ee3a 6641ffecom_intrinsic_len_ (ffebld expr)
5ff904cd 6642{
c7e4ee3a
CB
6643 ffetargetCharacter1 val;
6644 tree length;
6645
6646 switch (ffebld_op (expr))
6647 {
6648 case FFEBLD_opCONTER:
6649 val = ffebld_constant_character1 (ffebld_conter (expr));
6650 length = build_int_2 (ffetarget_length_character1 (val), 0);
6651 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6652 break;
6653
6654 case FFEBLD_opSYMTER:
6655 {
6656 ffesymbol s = ffebld_symter (expr);
6657 tree item;
6658
6659 item = ffesymbol_hook (s).decl_tree;
6660 if (item == NULL_TREE)
6661 {
6662 s = ffecom_sym_transform_ (s);
6663 item = ffesymbol_hook (s).decl_tree;
6664 }
6665 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
6666 {
6667 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
6668 length = ffesymbol_hook (s).length_tree;
6669 else
6670 {
6671 length = build_int_2 (ffesymbol_size (s), 0);
6672 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6673 }
6674 }
6675 else if (item == error_mark_node)
6676 length = error_mark_node;
6677 else /* FFEINFO_kindFUNCTION: */
6678 length = NULL_TREE;
6679 }
6680 break;
5ff904cd 6681
c7e4ee3a
CB
6682 case FFEBLD_opARRAYREF:
6683 length = ffecom_intrinsic_len_ (ffebld_left (expr));
6684 break;
5ff904cd 6685
c7e4ee3a
CB
6686 case FFEBLD_opSUBSTR:
6687 {
6688 ffebld start;
6689 ffebld end;
6690 ffebld thing = ffebld_right (expr);
6691 tree start_tree;
6692 tree end_tree;
5ff904cd 6693
c7e4ee3a
CB
6694 assert (ffebld_op (thing) == FFEBLD_opITEM);
6695 start = ffebld_head (thing);
6696 thing = ffebld_trail (thing);
6697 assert (ffebld_trail (thing) == NULL);
6698 end = ffebld_head (thing);
5ff904cd 6699
c7e4ee3a 6700 length = ffecom_intrinsic_len_ (ffebld_left (expr));
5ff904cd 6701
c7e4ee3a
CB
6702 if (length == error_mark_node)
6703 break;
5ff904cd 6704
c7e4ee3a
CB
6705 if (start == NULL)
6706 {
6707 if (end == NULL)
6708 ;
6709 else
6710 {
6711 length = convert (ffecom_f2c_ftnlen_type_node,
6712 ffecom_expr (end));
6713 }
6714 }
6715 else
6716 {
6717 start_tree = convert (ffecom_f2c_ftnlen_type_node,
6718 ffecom_expr (start));
5ff904cd 6719
c7e4ee3a
CB
6720 if (start_tree == error_mark_node)
6721 {
6722 length = error_mark_node;
6723 break;
6724 }
5ff904cd 6725
c7e4ee3a
CB
6726 if (end == NULL)
6727 {
6728 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6729 ffecom_f2c_ftnlen_one_node,
6730 ffecom_2 (MINUS_EXPR,
6731 ffecom_f2c_ftnlen_type_node,
6732 length,
6733 start_tree));
6734 }
6735 else
6736 {
6737 end_tree = convert (ffecom_f2c_ftnlen_type_node,
6738 ffecom_expr (end));
5ff904cd 6739
c7e4ee3a
CB
6740 if (end_tree == error_mark_node)
6741 {
6742 length = error_mark_node;
6743 break;
6744 }
5ff904cd 6745
c7e4ee3a
CB
6746 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6747 ffecom_f2c_ftnlen_one_node,
6748 ffecom_2 (MINUS_EXPR,
6749 ffecom_f2c_ftnlen_type_node,
6750 end_tree, start_tree));
6751 }
6752 }
6753 }
6754 break;
5ff904cd 6755
c7e4ee3a
CB
6756 case FFEBLD_opCONCATENATE:
6757 length
6758 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6759 ffecom_intrinsic_len_ (ffebld_left (expr)),
6760 ffecom_intrinsic_len_ (ffebld_right (expr)));
6761 break;
5ff904cd 6762
c7e4ee3a
CB
6763 case FFEBLD_opFUNCREF:
6764 case FFEBLD_opCONVERT:
6765 length = build_int_2 (ffebld_size (expr), 0);
6766 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6767 break;
5ff904cd 6768
c7e4ee3a
CB
6769 default:
6770 assert ("bad op for single char arg expr" == NULL);
6771 length = ffecom_f2c_ftnlen_zero_node;
6772 break;
6773 }
5ff904cd 6774
c7e4ee3a 6775 assert (length != NULL_TREE);
5ff904cd 6776
c7e4ee3a 6777 return length;
5ff904cd
JL
6778}
6779
6780#endif
c7e4ee3a 6781/* Handle CHARACTER assignments.
5ff904cd 6782
c7e4ee3a
CB
6783 Generates code to do the assignment. Used by ordinary assignment
6784 statement handler ffecom_let_stmt and by statement-function
6785 handler to generate code for a statement function. */
5ff904cd
JL
6786
6787#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
6788static void
6789ffecom_let_char_ (tree dest_tree, tree dest_length,
6790 ffetargetCharacterSize dest_size, ffebld source)
5ff904cd 6791{
c7e4ee3a
CB
6792 ffecomConcatList_ catlist;
6793 tree source_length;
6794 tree source_tree;
6795 tree expr_tree;
5ff904cd 6796
c7e4ee3a
CB
6797 if ((dest_tree == error_mark_node)
6798 || (dest_length == error_mark_node))
6799 return;
5ff904cd 6800
c7e4ee3a
CB
6801 assert (dest_tree != NULL_TREE);
6802 assert (dest_length != NULL_TREE);
5ff904cd 6803
c7e4ee3a
CB
6804 /* Source might be an opCONVERT, which just means it is a different size
6805 than the destination. Since the underlying implementation here handles
6806 that (directly or via the s_copy or s_cat run-time-library functions),
6807 we don't need the "convenience" of an opCONVERT that tells us to
6808 truncate or blank-pad, particularly since the resulting implementation
6809 would probably be slower than otherwise. */
5ff904cd 6810
c7e4ee3a
CB
6811 while (ffebld_op (source) == FFEBLD_opCONVERT)
6812 source = ffebld_left (source);
5ff904cd 6813
c7e4ee3a
CB
6814 catlist = ffecom_concat_list_new_ (source, dest_size);
6815 switch (ffecom_concat_list_count_ (catlist))
6816 {
6817 case 0: /* Shouldn't happen, but in case it does... */
6818 ffecom_concat_list_kill_ (catlist);
6819 source_tree = null_pointer_node;
6820 source_length = ffecom_f2c_ftnlen_zero_node;
6821 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6822 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6823 TREE_CHAIN (TREE_CHAIN (expr_tree))
6824 = build_tree_list (NULL_TREE, dest_length);
6825 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6826 = build_tree_list (NULL_TREE, source_length);
5ff904cd 6827
c7e4ee3a
CB
6828 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6829 TREE_SIDE_EFFECTS (expr_tree) = 1;
5ff904cd 6830
c7e4ee3a 6831 expand_expr_stmt (expr_tree);
5ff904cd 6832
c7e4ee3a 6833 return;
5ff904cd 6834
c7e4ee3a
CB
6835 case 1: /* The (fairly) easy case. */
6836 ffecom_char_args_ (&source_tree, &source_length,
6837 ffecom_concat_list_expr_ (catlist, 0));
6838 ffecom_concat_list_kill_ (catlist);
6839 assert (source_tree != NULL_TREE);
6840 assert (source_length != NULL_TREE);
6841
6842 if ((source_tree == error_mark_node)
6843 || (source_length == error_mark_node))
6844 return;
6845
6846 if (dest_size == 1)
6847 {
6848 dest_tree
6849 = ffecom_1 (INDIRECT_REF,
6850 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6851 (dest_tree))),
6852 dest_tree);
6853 dest_tree
6854 = ffecom_2 (ARRAY_REF,
6855 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6856 (dest_tree))),
6857 dest_tree,
6858 integer_one_node);
6859 source_tree
6860 = ffecom_1 (INDIRECT_REF,
6861 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6862 (source_tree))),
6863 source_tree);
6864 source_tree
6865 = ffecom_2 (ARRAY_REF,
6866 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6867 (source_tree))),
6868 source_tree,
6869 integer_one_node);
5ff904cd 6870
c7e4ee3a 6871 expr_tree = ffecom_modify (void_type_node, dest_tree, source_tree);
5ff904cd 6872
c7e4ee3a 6873 expand_expr_stmt (expr_tree);
5ff904cd 6874
c7e4ee3a
CB
6875 return;
6876 }
5ff904cd 6877
c7e4ee3a
CB
6878 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6879 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6880 TREE_CHAIN (TREE_CHAIN (expr_tree))
6881 = build_tree_list (NULL_TREE, dest_length);
6882 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6883 = build_tree_list (NULL_TREE, source_length);
5ff904cd 6884
c7e4ee3a
CB
6885 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6886 TREE_SIDE_EFFECTS (expr_tree) = 1;
5ff904cd 6887
c7e4ee3a 6888 expand_expr_stmt (expr_tree);
5ff904cd 6889
c7e4ee3a 6890 return;
5ff904cd 6891
c7e4ee3a
CB
6892 default: /* Must actually concatenate things. */
6893 break;
6894 }
5ff904cd 6895
c7e4ee3a 6896 /* Heavy-duty concatenation. */
5ff904cd 6897
c7e4ee3a
CB
6898 {
6899 int count = ffecom_concat_list_count_ (catlist);
6900 int i;
6901 tree lengths;
6902 tree items;
6903 tree length_array;
6904 tree item_array;
6905 tree citem;
6906 tree clength;
5ff904cd 6907
c7e4ee3a
CB
6908#ifdef HOHO
6909 length_array
6910 = lengths
6911 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
6912 FFETARGET_charactersizeNONE, count, TRUE);
6913 item_array = items = ffecom_push_tempvar (ffecom_f2c_address_type_node,
6914 FFETARGET_charactersizeNONE,
6915 count, TRUE);
6916#else
6917 {
6918 tree hook;
6919
6920 hook = ffebld_nonter_hook (source);
6921 assert (hook);
6922 assert (TREE_CODE (hook) == TREE_VEC);
6923 assert (TREE_VEC_LENGTH (hook) == 2);
6924 length_array = lengths = TREE_VEC_ELT (hook, 0);
6925 item_array = items = TREE_VEC_ELT (hook, 1);
5ff904cd 6926 }
c7e4ee3a 6927#endif
5ff904cd 6928
c7e4ee3a
CB
6929 for (i = 0; i < count; ++i)
6930 {
6931 ffecom_char_args_ (&citem, &clength,
6932 ffecom_concat_list_expr_ (catlist, i));
6933 if ((citem == error_mark_node)
6934 || (clength == error_mark_node))
6935 {
6936 ffecom_concat_list_kill_ (catlist);
6937 return;
6938 }
5ff904cd 6939
c7e4ee3a
CB
6940 items
6941 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
6942 ffecom_modify (void_type_node,
6943 ffecom_2 (ARRAY_REF,
6944 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
6945 item_array,
6946 build_int_2 (i, 0)),
6947 citem),
6948 items);
6949 lengths
6950 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
6951 ffecom_modify (void_type_node,
6952 ffecom_2 (ARRAY_REF,
6953 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
6954 length_array,
6955 build_int_2 (i, 0)),
6956 clength),
6957 lengths);
6958 }
5ff904cd 6959
c7e4ee3a
CB
6960 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6961 TREE_CHAIN (expr_tree)
6962 = build_tree_list (NULL_TREE,
6963 ffecom_1 (ADDR_EXPR,
6964 build_pointer_type (TREE_TYPE (items)),
6965 items));
6966 TREE_CHAIN (TREE_CHAIN (expr_tree))
6967 = build_tree_list (NULL_TREE,
6968 ffecom_1 (ADDR_EXPR,
6969 build_pointer_type (TREE_TYPE (lengths)),
6970 lengths));
6971 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6972 = build_tree_list
6973 (NULL_TREE,
6974 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
6975 convert (ffecom_f2c_ftnlen_type_node,
6976 build_int_2 (count, 0))));
6977 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree))))
6978 = build_tree_list (NULL_TREE, dest_length);
5ff904cd 6979
c7e4ee3a
CB
6980 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCAT, expr_tree, NULL_TREE);
6981 TREE_SIDE_EFFECTS (expr_tree) = 1;
5ff904cd 6982
c7e4ee3a
CB
6983 expand_expr_stmt (expr_tree);
6984 }
5ff904cd 6985
c7e4ee3a
CB
6986 ffecom_concat_list_kill_ (catlist);
6987}
5ff904cd 6988
c7e4ee3a
CB
6989#endif
6990/* ffecom_make_gfrt_ -- Make initial info for run-time routine
5ff904cd 6991
c7e4ee3a
CB
6992 ffecomGfrt ix;
6993 ffecom_make_gfrt_(ix);
5ff904cd 6994
c7e4ee3a
CB
6995 Assumes gfrt_[ix] is NULL_TREE, and replaces it with the FUNCTION_DECL
6996 for the indicated run-time routine (ix). */
5ff904cd 6997
c7e4ee3a
CB
6998#if FFECOM_targetCURRENT == FFECOM_targetGCC
6999static void
7000ffecom_make_gfrt_ (ffecomGfrt ix)
7001{
7002 tree t;
7003 tree ttype;
5ff904cd 7004
c7e4ee3a
CB
7005 push_obstacks_nochange ();
7006 end_temporary_allocation ();
5ff904cd 7007
c7e4ee3a
CB
7008 switch (ffecom_gfrt_type_[ix])
7009 {
7010 case FFECOM_rttypeVOID_:
7011 ttype = void_type_node;
7012 break;
5ff904cd 7013
c7e4ee3a
CB
7014 case FFECOM_rttypeVOIDSTAR_:
7015 ttype = TREE_TYPE (null_pointer_node); /* `void *'. */
7016 break;
5ff904cd 7017
c7e4ee3a
CB
7018 case FFECOM_rttypeFTNINT_:
7019 ttype = ffecom_f2c_ftnint_type_node;
7020 break;
5ff904cd 7021
c7e4ee3a
CB
7022 case FFECOM_rttypeINTEGER_:
7023 ttype = ffecom_f2c_integer_type_node;
7024 break;
5ff904cd 7025
c7e4ee3a
CB
7026 case FFECOM_rttypeLONGINT_:
7027 ttype = ffecom_f2c_longint_type_node;
7028 break;
5ff904cd 7029
c7e4ee3a
CB
7030 case FFECOM_rttypeLOGICAL_:
7031 ttype = ffecom_f2c_logical_type_node;
7032 break;
5ff904cd 7033
c7e4ee3a
CB
7034 case FFECOM_rttypeREAL_F2C_:
7035 ttype = double_type_node;
7036 break;
5ff904cd 7037
c7e4ee3a
CB
7038 case FFECOM_rttypeREAL_GNU_:
7039 ttype = float_type_node;
7040 break;
5ff904cd 7041
c7e4ee3a
CB
7042 case FFECOM_rttypeCOMPLEX_F2C_:
7043 ttype = void_type_node;
7044 break;
5ff904cd 7045
c7e4ee3a
CB
7046 case FFECOM_rttypeCOMPLEX_GNU_:
7047 ttype = ffecom_f2c_complex_type_node;
7048 break;
5ff904cd 7049
c7e4ee3a
CB
7050 case FFECOM_rttypeDOUBLE_:
7051 ttype = double_type_node;
7052 break;
5ff904cd 7053
c7e4ee3a
CB
7054 case FFECOM_rttypeDOUBLEREAL_:
7055 ttype = ffecom_f2c_doublereal_type_node;
7056 break;
5ff904cd 7057
c7e4ee3a
CB
7058 case FFECOM_rttypeDBLCMPLX_F2C_:
7059 ttype = void_type_node;
7060 break;
5ff904cd 7061
c7e4ee3a
CB
7062 case FFECOM_rttypeDBLCMPLX_GNU_:
7063 ttype = ffecom_f2c_doublecomplex_type_node;
7064 break;
5ff904cd 7065
c7e4ee3a
CB
7066 case FFECOM_rttypeCHARACTER_:
7067 ttype = void_type_node;
7068 break;
7069
7070 default:
7071 ttype = NULL;
7072 assert ("bad rttype" == NULL);
7073 break;
5ff904cd 7074 }
5ff904cd 7075
c7e4ee3a
CB
7076 ttype = build_function_type (ttype, NULL_TREE);
7077 t = build_decl (FUNCTION_DECL,
7078 get_identifier (ffecom_gfrt_name_[ix]),
7079 ttype);
7080 DECL_EXTERNAL (t) = 1;
7081 TREE_PUBLIC (t) = 1;
7082 TREE_THIS_VOLATILE (t) = ffecom_gfrt_volatile_[ix] ? 1 : 0;
5ff904cd 7083
c7e4ee3a 7084 t = start_decl (t, TRUE);
5ff904cd 7085
c7e4ee3a 7086 finish_decl (t, NULL_TREE, TRUE);
5ff904cd 7087
c7e4ee3a
CB
7088 resume_temporary_allocation ();
7089 pop_obstacks ();
7090
7091 ffecom_gfrt_[ix] = t;
5ff904cd
JL
7092}
7093
7094#endif
c7e4ee3a
CB
7095/* Phase 1 pass over each member of a COMMON/EQUIVALENCE group. */
7096
5ff904cd 7097#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
7098static void
7099ffecom_member_phase1_ (ffestorag mst UNUSED, ffestorag st)
5ff904cd 7100{
c7e4ee3a 7101 ffesymbol s = ffestorag_symbol (st);
5ff904cd 7102
c7e4ee3a
CB
7103 if (ffesymbol_namelisted (s))
7104 ffecom_member_namelisted_ = TRUE;
7105}
5ff904cd 7106
c7e4ee3a
CB
7107#endif
7108/* Phase 2 pass over each member of a COMMON/EQUIVALENCE group. Declare
7109 the member so debugger will see it. Otherwise nobody should be
7110 referencing the member. */
5ff904cd 7111
c7e4ee3a
CB
7112#if FFECOM_targetCURRENT == FFECOM_targetGCC
7113#ifdef SOMEONE_GETS_DEBUG_SUPPORT_WORKING
7114static void
7115ffecom_member_phase2_ (ffestorag mst, ffestorag st)
7116{
7117 ffesymbol s;
7118 tree t;
7119 tree mt;
7120 tree type;
5ff904cd 7121
c7e4ee3a
CB
7122 if ((mst == NULL)
7123 || ((mt = ffestorag_hook (mst)) == NULL)
7124 || (mt == error_mark_node))
7125 return;
5ff904cd 7126
c7e4ee3a
CB
7127 if ((st == NULL)
7128 || ((s = ffestorag_symbol (st)) == NULL))
7129 return;
5ff904cd 7130
c7e4ee3a
CB
7131 type = ffecom_type_localvar_ (s,
7132 ffesymbol_basictype (s),
7133 ffesymbol_kindtype (s));
7134 if (type == error_mark_node)
7135 return;
5ff904cd 7136
c7e4ee3a
CB
7137 t = build_decl (VAR_DECL,
7138 ffecom_get_identifier_ (ffesymbol_text (s)),
7139 type);
5ff904cd 7140
c7e4ee3a
CB
7141 TREE_STATIC (t) = TREE_STATIC (mt);
7142 DECL_INITIAL (t) = NULL_TREE;
7143 TREE_ASM_WRITTEN (t) = 1;
5ff904cd 7144
c7e4ee3a
CB
7145 DECL_RTL (t)
7146 = gen_rtx (MEM, TYPE_MODE (type),
7147 plus_constant (XEXP (DECL_RTL (mt), 0),
7148 ffestorag_modulo (mst)
7149 + ffestorag_offset (st)
7150 - ffestorag_offset (mst)));
5ff904cd 7151
c7e4ee3a 7152 t = start_decl (t, FALSE);
5ff904cd 7153
c7e4ee3a 7154 finish_decl (t, NULL_TREE, FALSE);
5ff904cd
JL
7155}
7156
7157#endif
c7e4ee3a
CB
7158#endif
7159/* Prepare source expression for assignment into a destination perhaps known
7160 to be of a specific size. */
5ff904cd 7161
c7e4ee3a
CB
7162static void
7163ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size, ffebld source)
5ff904cd 7164{
c7e4ee3a
CB
7165 ffecomConcatList_ catlist;
7166 int count;
7167 int i;
7168 tree ltmp;
7169 tree itmp;
7170 tree tempvar = NULL_TREE;
5ff904cd 7171
c7e4ee3a
CB
7172 while (ffebld_op (source) == FFEBLD_opCONVERT)
7173 source = ffebld_left (source);
5ff904cd 7174
c7e4ee3a
CB
7175 catlist = ffecom_concat_list_new_ (source, dest_size);
7176 count = ffecom_concat_list_count_ (catlist);
5ff904cd 7177
c7e4ee3a
CB
7178 if (count >= 2)
7179 {
7180 ltmp
7181 = ffecom_make_tempvar ("let_char_len", ffecom_f2c_ftnlen_type_node,
7182 FFETARGET_charactersizeNONE, count);
7183 itmp
7184 = ffecom_make_tempvar ("let_char_item", ffecom_f2c_address_type_node,
7185 FFETARGET_charactersizeNONE, count);
7186
7187 tempvar = make_tree_vec (2);
7188 TREE_VEC_ELT (tempvar, 0) = ltmp;
7189 TREE_VEC_ELT (tempvar, 1) = itmp;
7190 }
5ff904cd 7191
c7e4ee3a
CB
7192 for (i = 0; i < count; ++i)
7193 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist, i));
5ff904cd 7194
c7e4ee3a 7195 ffecom_concat_list_kill_ (catlist);
5ff904cd 7196
c7e4ee3a
CB
7197 if (tempvar)
7198 {
7199 ffebld_nonter_set_hook (source, tempvar);
7200 current_binding_level->prep_state = 1;
7201 }
7202}
5ff904cd 7203
c7e4ee3a 7204/* ffecom_push_dummy_decls_ -- Transform dummy args, push parm decls in order
5ff904cd 7205
c7e4ee3a
CB
7206 Ignores STAR (alternate-return) dummies. All other get exec-transitioned
7207 (which generates their trees) and then their trees get push_parm_decl'd.
5ff904cd 7208
c7e4ee3a
CB
7209 The second arg is TRUE if the dummies are for a statement function, in
7210 which case lengths are not pushed for character arguments (since they are
7211 always known by both the caller and the callee, though the code allows
7212 for someday permitting CHAR*(*) stmtfunc dummies). */
5ff904cd 7213
c7e4ee3a
CB
7214#if FFECOM_targetCURRENT == FFECOM_targetGCC
7215static void
7216ffecom_push_dummy_decls_ (ffebld dummy_list, bool stmtfunc)
7217{
7218 ffebld dummy;
7219 ffebld dumlist;
7220 ffesymbol s;
7221 tree parm;
5ff904cd 7222
c7e4ee3a 7223 ffecom_transform_only_dummies_ = TRUE;
5ff904cd 7224
c7e4ee3a 7225 /* First push the parms corresponding to actual dummy "contents". */
5ff904cd 7226
c7e4ee3a
CB
7227 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7228 {
7229 dummy = ffebld_head (dumlist);
7230 switch (ffebld_op (dummy))
7231 {
7232 case FFEBLD_opSTAR:
7233 case FFEBLD_opANY:
7234 continue; /* Forget alternate returns. */
5ff904cd 7235
c7e4ee3a
CB
7236 default:
7237 break;
7238 }
7239 assert (ffebld_op (dummy) == FFEBLD_opSYMTER);
7240 s = ffebld_symter (dummy);
7241 parm = ffesymbol_hook (s).decl_tree;
7242 if (parm == NULL_TREE)
7243 {
7244 s = ffecom_sym_transform_ (s);
7245 parm = ffesymbol_hook (s).decl_tree;
7246 assert (parm != NULL_TREE);
7247 }
7248 if (parm != error_mark_node)
7249 push_parm_decl (parm);
5ff904cd
JL
7250 }
7251
c7e4ee3a 7252 /* Then, for CHARACTER dummies, push the parms giving their lengths. */
5ff904cd 7253
c7e4ee3a
CB
7254 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7255 {
7256 dummy = ffebld_head (dumlist);
7257 switch (ffebld_op (dummy))
7258 {
7259 case FFEBLD_opSTAR:
7260 case FFEBLD_opANY:
7261 continue; /* Forget alternate returns, they mean
7262 NOTHING! */
7263
7264 default:
7265 break;
7266 }
7267 s = ffebld_symter (dummy);
7268 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
7269 continue; /* Only looking for CHARACTER arguments. */
7270 if (stmtfunc && (ffesymbol_size (s) != FFETARGET_charactersizeNONE))
7271 continue; /* Stmtfunc arg with known size needs no
7272 length param. */
7273 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
7274 continue; /* Only looking for variables and arrays. */
7275 parm = ffesymbol_hook (s).length_tree;
7276 assert (parm != NULL_TREE);
7277 if (parm != error_mark_node)
7278 push_parm_decl (parm);
7279 }
7280
7281 ffecom_transform_only_dummies_ = FALSE;
5ff904cd
JL
7282}
7283
7284#endif
c7e4ee3a 7285/* ffecom_start_progunit_ -- Beginning of program unit
5ff904cd 7286
c7e4ee3a
CB
7287 Does GNU back end stuff necessary to teach it about the start of its
7288 equivalent of a Fortran program unit. */
5ff904cd
JL
7289
7290#if FFECOM_targetCURRENT == FFECOM_targetGCC
7291static void
c7e4ee3a 7292ffecom_start_progunit_ ()
5ff904cd 7293{
c7e4ee3a
CB
7294 ffesymbol fn = ffecom_primary_entry_;
7295 ffebld arglist;
7296 tree id; /* Identifier (name) of function. */
7297 tree type; /* Type of function. */
7298 tree result; /* Result of function. */
7299 ffeinfoBasictype bt;
7300 ffeinfoKindtype kt;
7301 ffeglobal g;
7302 ffeglobalType gt;
7303 ffeglobalType egt = FFEGLOBAL_type;
7304 bool charfunc;
7305 bool cmplxfunc;
7306 bool altentries = (ffecom_num_entrypoints_ != 0);
7307 bool multi
7308 = altentries
7309 && (ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
7310 && (ffecom_master_bt_ == FFEINFO_basictypeNONE);
7311 bool main_program = FALSE;
7312 int old_lineno = lineno;
7313 char *old_input_filename = input_filename;
7314 int yes;
5ff904cd 7315
c7e4ee3a
CB
7316 assert (fn != NULL);
7317 assert (ffesymbol_hook (fn).decl_tree == NULL_TREE);
5ff904cd 7318
c7e4ee3a
CB
7319 input_filename = ffesymbol_where_filename (fn);
7320 lineno = ffesymbol_where_filelinenum (fn);
5ff904cd 7321
c7e4ee3a
CB
7322 /* c-parse.y indeed does call suspend_momentary and not only ignores the
7323 return value, but also never calls resume_momentary, when starting an
7324 outer function (see "fndef:", "setspecs:", and so on). So g77 does the
7325 same thing. It shouldn't be a problem since start_function calls
7326 temporary_allocation, but it might be necessary. If it causes a problem
7327 here, then maybe there's a bug lurking in gcc. NOTE: This identical
7328 comment appears twice in thist file. */
7329
7330 suspend_momentary ();
7331
7332 switch (ffecom_primary_entry_kind_)
7333 {
7334 case FFEINFO_kindPROGRAM:
7335 main_program = TRUE;
7336 gt = FFEGLOBAL_typeMAIN;
7337 bt = FFEINFO_basictypeNONE;
7338 kt = FFEINFO_kindtypeNONE;
7339 type = ffecom_tree_fun_type_void;
7340 charfunc = FALSE;
7341 cmplxfunc = FALSE;
7342 break;
7343
7344 case FFEINFO_kindBLOCKDATA:
7345 gt = FFEGLOBAL_typeBDATA;
7346 bt = FFEINFO_basictypeNONE;
7347 kt = FFEINFO_kindtypeNONE;
7348 type = ffecom_tree_fun_type_void;
7349 charfunc = FALSE;
7350 cmplxfunc = FALSE;
7351 break;
7352
7353 case FFEINFO_kindFUNCTION:
7354 gt = FFEGLOBAL_typeFUNC;
7355 egt = FFEGLOBAL_typeEXT;
7356 bt = ffesymbol_basictype (fn);
7357 kt = ffesymbol_kindtype (fn);
7358 if (bt == FFEINFO_basictypeNONE)
7359 {
7360 ffeimplic_establish_symbol (fn);
7361 if (ffesymbol_funcresult (fn) != NULL)
7362 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
7363 bt = ffesymbol_basictype (fn);
7364 kt = ffesymbol_kindtype (fn);
7365 }
7366
7367 if (multi)
7368 charfunc = cmplxfunc = FALSE;
7369 else if (bt == FFEINFO_basictypeCHARACTER)
7370 charfunc = TRUE, cmplxfunc = FALSE;
7371 else if ((bt == FFEINFO_basictypeCOMPLEX)
7372 && ffesymbol_is_f2c (fn)
7373 && !altentries)
7374 charfunc = FALSE, cmplxfunc = TRUE;
7375 else
7376 charfunc = cmplxfunc = FALSE;
7377
7378 if (multi || charfunc)
7379 type = ffecom_tree_fun_type_void;
7380 else if (ffesymbol_is_f2c (fn) && !altentries)
7381 type = ffecom_tree_fun_type[bt][kt];
7382 else
7383 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
7384
7385 if ((type == NULL_TREE)
7386 || (TREE_TYPE (type) == NULL_TREE))
7387 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
7388 break;
7389
7390 case FFEINFO_kindSUBROUTINE:
7391 gt = FFEGLOBAL_typeSUBR;
7392 egt = FFEGLOBAL_typeEXT;
7393 bt = FFEINFO_basictypeNONE;
7394 kt = FFEINFO_kindtypeNONE;
7395 if (ffecom_is_altreturning_)
7396 type = ffecom_tree_subr_type;
7397 else
7398 type = ffecom_tree_fun_type_void;
7399 charfunc = FALSE;
7400 cmplxfunc = FALSE;
7401 break;
5ff904cd 7402
c7e4ee3a
CB
7403 default:
7404 assert ("say what??" == NULL);
7405 /* Fall through. */
7406 case FFEINFO_kindANY:
7407 gt = FFEGLOBAL_typeANY;
7408 bt = FFEINFO_basictypeNONE;
7409 kt = FFEINFO_kindtypeNONE;
7410 type = error_mark_node;
7411 charfunc = FALSE;
7412 cmplxfunc = FALSE;
7413 break;
7414 }
5ff904cd 7415
c7e4ee3a 7416 if (altentries)
5ff904cd 7417 {
c7e4ee3a
CB
7418 id = ffecom_get_invented_identifier ("__g77_masterfun_%s",
7419 ffesymbol_text (fn),
7420 -1);
7421 }
7422#if FFETARGET_isENFORCED_MAIN
7423 else if (main_program)
7424 id = get_identifier (FFETARGET_nameENFORCED_MAIN_NAME);
7425#endif
7426 else
7427 id = ffecom_get_external_identifier_ (fn);
5ff904cd 7428
c7e4ee3a
CB
7429 start_function (id,
7430 type,
7431 0, /* nested/inline */
7432 !altentries); /* TREE_PUBLIC */
5ff904cd 7433
c7e4ee3a 7434 TREE_USED (current_function_decl) = 1; /* Avoid spurious warning if altentries. */
5ff904cd 7435
c7e4ee3a
CB
7436 if (!altentries
7437 && ((g = ffesymbol_global (fn)) != NULL)
7438 && ((ffeglobal_type (g) == gt)
7439 || (ffeglobal_type (g) == egt)))
7440 {
7441 ffeglobal_set_hook (g, current_function_decl);
7442 }
5ff904cd 7443
c7e4ee3a 7444 yes = suspend_momentary ();
5ff904cd 7445
c7e4ee3a
CB
7446 /* Arg handling needs exec-transitioned ffesymbols to work with. But
7447 exec-transitioning needs current_function_decl to be filled in. So we
7448 do these things in two phases. */
5ff904cd 7449
c7e4ee3a
CB
7450 if (altentries)
7451 { /* 1st arg identifies which entrypoint. */
7452 ffecom_which_entrypoint_decl_
7453 = build_decl (PARM_DECL,
7454 ffecom_get_invented_identifier ("__g77_%s",
7455 "which_entrypoint",
7456 -1),
7457 integer_type_node);
7458 push_parm_decl (ffecom_which_entrypoint_decl_);
7459 }
5ff904cd 7460
c7e4ee3a
CB
7461 if (charfunc
7462 || cmplxfunc
7463 || multi)
7464 { /* Arg for result (return value). */
7465 tree type;
7466 tree length;
5ff904cd 7467
c7e4ee3a
CB
7468 if (charfunc)
7469 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
7470 else if (cmplxfunc)
7471 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
7472 else
7473 type = ffecom_multi_type_node_;
5ff904cd 7474
c7e4ee3a
CB
7475 result = ffecom_get_invented_identifier ("__g77_%s",
7476 "result", -1);
5ff904cd 7477
c7e4ee3a 7478 /* Make length arg _and_ enhance type info for CHAR arg itself. */
5ff904cd 7479
c7e4ee3a
CB
7480 if (charfunc)
7481 length = ffecom_char_enhance_arg_ (&type, fn);
7482 else
7483 length = NULL_TREE; /* Not ref'd if !charfunc. */
5ff904cd 7484
c7e4ee3a
CB
7485 type = build_pointer_type (type);
7486 result = build_decl (PARM_DECL, result, type);
5ff904cd 7487
c7e4ee3a
CB
7488 push_parm_decl (result);
7489 if (multi)
7490 ffecom_multi_retval_ = result;
7491 else
7492 ffecom_func_result_ = result;
5ff904cd 7493
c7e4ee3a
CB
7494 if (charfunc)
7495 {
7496 push_parm_decl (length);
7497 ffecom_func_length_ = length;
7498 }
5ff904cd
JL
7499 }
7500
c7e4ee3a
CB
7501 if (ffecom_primary_entry_is_proc_)
7502 {
7503 if (altentries)
7504 arglist = ffecom_master_arglist_;
7505 else
7506 arglist = ffesymbol_dummyargs (fn);
7507 ffecom_push_dummy_decls_ (arglist, FALSE);
7508 }
5ff904cd 7509
c7e4ee3a 7510 resume_momentary (yes);
5ff904cd 7511
c7e4ee3a
CB
7512 if (TREE_CODE (current_function_decl) != ERROR_MARK)
7513 store_parm_decls (main_program ? 1 : 0);
5ff904cd 7514
c7e4ee3a
CB
7515 ffecom_start_compstmt ();
7516 /* Disallow temp vars at this level. */
7517 current_binding_level->prep_state = 2;
5ff904cd 7518
c7e4ee3a
CB
7519 lineno = old_lineno;
7520 input_filename = old_input_filename;
5ff904cd 7521
c7e4ee3a
CB
7522 /* This handles any symbols still untransformed, in case -g specified.
7523 This used to be done in ffecom_finish_progunit, but it turns out to
7524 be necessary to do it here so that statement functions are
7525 expanded before code. But don't bother for BLOCK DATA. */
5ff904cd 7526
c7e4ee3a
CB
7527 if (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
7528 ffesymbol_drive (ffecom_finish_symbol_transform_);
5ff904cd
JL
7529}
7530
7531#endif
c7e4ee3a 7532/* ffecom_sym_transform_ -- Transform FFE sym into backend sym
5ff904cd 7533
c7e4ee3a
CB
7534 ffesymbol s;
7535 ffecom_sym_transform_(s);
7536
7537 The ffesymbol_hook info for s is updated with appropriate backend info
7538 on the symbol. */
7539
7540#if FFECOM_targetCURRENT == FFECOM_targetGCC
7541static ffesymbol
7542ffecom_sym_transform_ (ffesymbol s)
7543{
7544 tree t; /* Transformed thingy. */
7545 tree tlen; /* Length if CHAR*(*). */
7546 bool addr; /* Is t the address of the thingy? */
7547 ffeinfoBasictype bt;
7548 ffeinfoKindtype kt;
7549 ffeglobal g;
7550 int yes;
7551 int old_lineno = lineno;
7552 char *old_input_filename = input_filename;
5ff904cd 7553
c7e4ee3a
CB
7554 /* Must ensure special ASSIGN variables are declared at top of outermost
7555 block, else they'll end up in the innermost block when their first
7556 ASSIGN is seen, which leaves them out of scope when they're the
7557 subject of a GOTO or I/O statement.
5ff904cd 7558
c7e4ee3a
CB
7559 We make this variable even if -fugly-assign. Just let it go unused,
7560 in case it turns out there are cases where we really want to use this
7561 variable anyway (e.g. ASSIGN to INTEGER*2 variable). */
5ff904cd 7562
c7e4ee3a
CB
7563 if (! ffecom_transform_only_dummies_
7564 && ffesymbol_assigned (s)
7565 && ! ffesymbol_hook (s).assign_tree)
7566 s = ffecom_sym_transform_assign_ (s);
5ff904cd 7567
c7e4ee3a 7568 if (ffesymbol_sfdummyparent (s) == NULL)
5ff904cd 7569 {
c7e4ee3a
CB
7570 input_filename = ffesymbol_where_filename (s);
7571 lineno = ffesymbol_where_filelinenum (s);
7572 }
7573 else
7574 {
7575 ffesymbol sf = ffesymbol_sfdummyparent (s);
5ff904cd 7576
c7e4ee3a
CB
7577 input_filename = ffesymbol_where_filename (sf);
7578 lineno = ffesymbol_where_filelinenum (sf);
7579 }
6d433196 7580
c7e4ee3a
CB
7581 bt = ffeinfo_basictype (ffebld_info (s));
7582 kt = ffeinfo_kindtype (ffebld_info (s));
5ff904cd 7583
c7e4ee3a
CB
7584 t = NULL_TREE;
7585 tlen = NULL_TREE;
7586 addr = FALSE;
5ff904cd 7587
c7e4ee3a
CB
7588 switch (ffesymbol_kind (s))
7589 {
7590 case FFEINFO_kindNONE:
7591 switch (ffesymbol_where (s))
7592 {
7593 case FFEINFO_whereDUMMY: /* Subroutine or function. */
7594 assert (ffecom_transform_only_dummies_);
5ff904cd 7595
c7e4ee3a
CB
7596 /* Before 0.4, this could be ENTITY/DUMMY, but see
7597 ffestu_sym_end_transition -- no longer true (in particular, if
7598 it could be an ENTITY, it _will_ be made one, so that
7599 possibility won't come through here). So we never make length
7600 arg for CHARACTER type. */
5ff904cd 7601
c7e4ee3a
CB
7602 t = build_decl (PARM_DECL,
7603 ffecom_get_identifier_ (ffesymbol_text (s)),
7604 ffecom_tree_ptr_to_subr_type);
7605#if BUILT_FOR_270
7606 DECL_ARTIFICIAL (t) = 1;
7607#endif
7608 addr = TRUE;
7609 break;
5ff904cd 7610
c7e4ee3a
CB
7611 case FFEINFO_whereGLOBAL: /* Subroutine or function. */
7612 assert (!ffecom_transform_only_dummies_);
5ff904cd 7613
c7e4ee3a
CB
7614 if (((g = ffesymbol_global (s)) != NULL)
7615 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7616 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7617 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
7618 && (ffeglobal_hook (g) != NULL_TREE)
7619 && ffe_is_globals ())
7620 {
7621 t = ffeglobal_hook (g);
7622 break;
7623 }
5ff904cd 7624
c7e4ee3a
CB
7625 push_obstacks_nochange ();
7626 end_temporary_allocation ();
5ff904cd 7627
c7e4ee3a
CB
7628 t = build_decl (FUNCTION_DECL,
7629 ffecom_get_external_identifier_ (s),
7630 ffecom_tree_subr_type); /* Assume subr. */
7631 DECL_EXTERNAL (t) = 1;
7632 TREE_PUBLIC (t) = 1;
5ff904cd 7633
c7e4ee3a
CB
7634 t = start_decl (t, FALSE);
7635 finish_decl (t, NULL_TREE, FALSE);
795232f7 7636
c7e4ee3a
CB
7637 if ((g != NULL)
7638 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7639 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7640 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
7641 ffeglobal_set_hook (g, t);
5ff904cd 7642
c7e4ee3a
CB
7643 resume_temporary_allocation ();
7644 pop_obstacks ();
5ff904cd 7645
c7e4ee3a 7646 break;
5ff904cd 7647
c7e4ee3a
CB
7648 default:
7649 assert ("NONE where unexpected" == NULL);
7650 /* Fall through. */
7651 case FFEINFO_whereANY:
7652 break;
7653 }
5ff904cd 7654 break;
5ff904cd 7655
c7e4ee3a
CB
7656 case FFEINFO_kindENTITY:
7657 switch (ffeinfo_where (ffesymbol_info (s)))
7658 {
5ff904cd 7659
c7e4ee3a
CB
7660 case FFEINFO_whereCONSTANT:
7661 /* ~~Debugging info needed? */
7662 assert (!ffecom_transform_only_dummies_);
7663 t = error_mark_node; /* Shouldn't ever see this in expr. */
7664 break;
5ff904cd 7665
c7e4ee3a
CB
7666 case FFEINFO_whereLOCAL:
7667 assert (!ffecom_transform_only_dummies_);
5ff904cd 7668
c7e4ee3a
CB
7669 {
7670 ffestorag st = ffesymbol_storage (s);
7671 tree type;
5ff904cd 7672
c7e4ee3a
CB
7673 if ((st != NULL)
7674 && (ffestorag_size (st) == 0))
7675 {
7676 t = error_mark_node;
7677 break;
7678 }
5ff904cd 7679
c7e4ee3a
CB
7680 yes = suspend_momentary ();
7681 type = ffecom_type_localvar_ (s, bt, kt);
7682 resume_momentary (yes);
5ff904cd 7683
c7e4ee3a
CB
7684 if (type == error_mark_node)
7685 {
7686 t = error_mark_node;
7687 break;
7688 }
5ff904cd 7689
c7e4ee3a
CB
7690 if ((st != NULL)
7691 && (ffestorag_parent (st) != NULL))
7692 { /* Child of EQUIVALENCE parent. */
7693 ffestorag est;
7694 tree et;
7695 int yes;
7696 ffetargetOffset offset;
5ff904cd 7697
c7e4ee3a
CB
7698 est = ffestorag_parent (st);
7699 ffecom_transform_equiv_ (est);
5ff904cd 7700
c7e4ee3a
CB
7701 et = ffestorag_hook (est);
7702 assert (et != NULL_TREE);
5ff904cd 7703
c7e4ee3a
CB
7704 if (! TREE_STATIC (et))
7705 put_var_into_stack (et);
5ff904cd 7706
c7e4ee3a 7707 yes = suspend_momentary ();
5ff904cd 7708
c7e4ee3a
CB
7709 offset = ffestorag_modulo (est)
7710 + ffestorag_offset (ffesymbol_storage (s))
7711 - ffestorag_offset (est);
5ff904cd 7712
c7e4ee3a 7713 ffecom_debug_kludge_ (et, "EQUIVALENCE", s, type, offset);
5ff904cd 7714
c7e4ee3a 7715 /* (t_type *) (((char *) &et) + offset) */
5ff904cd 7716
c7e4ee3a
CB
7717 t = convert (string_type_node, /* (char *) */
7718 ffecom_1 (ADDR_EXPR,
7719 build_pointer_type (TREE_TYPE (et)),
7720 et));
7721 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
7722 t,
7723 build_int_2 (offset, 0));
7724 t = convert (build_pointer_type (type),
7725 t);
d50108c7 7726 TREE_CONSTANT (t) = staticp (et);
5ff904cd 7727
c7e4ee3a 7728 addr = TRUE;
5ff904cd 7729
c7e4ee3a
CB
7730 resume_momentary (yes);
7731 }
7732 else
7733 {
7734 tree initexpr;
7735 bool init = ffesymbol_is_init (s);
5ff904cd 7736
c7e4ee3a 7737 yes = suspend_momentary ();
5ff904cd 7738
c7e4ee3a
CB
7739 t = build_decl (VAR_DECL,
7740 ffecom_get_identifier_ (ffesymbol_text (s)),
7741 type);
5ff904cd 7742
c7e4ee3a
CB
7743 if (init
7744 || ffesymbol_namelisted (s)
7745#ifdef FFECOM_sizeMAXSTACKITEM
7746 || ((st != NULL)
7747 && (ffestorag_size (st) > FFECOM_sizeMAXSTACKITEM))
7748#endif
7749 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
7750 && (ffecom_primary_entry_kind_
7751 != FFEINFO_kindBLOCKDATA)
7752 && (ffesymbol_is_save (s) || ffe_is_saveall ())))
7753 TREE_STATIC (t) = !ffesymbol_attr (s, FFESYMBOL_attrADJUSTABLE);
7754 else
7755 TREE_STATIC (t) = 0; /* No need to make static. */
5ff904cd 7756
c7e4ee3a
CB
7757 if (init || ffe_is_init_local_zero ())
7758 DECL_INITIAL (t) = error_mark_node;
5ff904cd 7759
c7e4ee3a
CB
7760 /* Keep -Wunused from complaining about var if it
7761 is used as sfunc arg or DATA implied-DO. */
7762 if (ffesymbol_attrs (s) & FFESYMBOL_attrsSFARG)
7763 DECL_IN_SYSTEM_HEADER (t) = 1;
5ff904cd 7764
c7e4ee3a 7765 t = start_decl (t, FALSE);
5ff904cd 7766
c7e4ee3a
CB
7767 if (init)
7768 {
7769 if (ffesymbol_init (s) != NULL)
7770 initexpr = ffecom_expr (ffesymbol_init (s));
7771 else
7772 initexpr = ffecom_init_zero_ (t);
7773 }
7774 else if (ffe_is_init_local_zero ())
7775 initexpr = ffecom_init_zero_ (t);
7776 else
7777 initexpr = NULL_TREE; /* Not ref'd if !init. */
5ff904cd 7778
c7e4ee3a 7779 finish_decl (t, initexpr, FALSE);
5ff904cd 7780
c7e4ee3a
CB
7781 if ((st != NULL) && (DECL_SIZE (t) != error_mark_node))
7782 {
7783 tree size_tree;
5ff904cd 7784
c7e4ee3a
CB
7785 size_tree = size_binop (CEIL_DIV_EXPR,
7786 DECL_SIZE (t),
7787 size_int (BITS_PER_UNIT));
7788 assert (TREE_INT_CST_HIGH (size_tree) == 0);
7789 assert (TREE_INT_CST_LOW (size_tree) == ffestorag_size (st));
7790 }
5ff904cd 7791
c7e4ee3a
CB
7792 resume_momentary (yes);
7793 }
7794 }
5ff904cd 7795 break;
5ff904cd 7796
c7e4ee3a
CB
7797 case FFEINFO_whereRESULT:
7798 assert (!ffecom_transform_only_dummies_);
5ff904cd 7799
c7e4ee3a
CB
7800 if (bt == FFEINFO_basictypeCHARACTER)
7801 { /* Result is already in list of dummies, use
7802 it (& length). */
7803 t = ffecom_func_result_;
7804 tlen = ffecom_func_length_;
7805 addr = TRUE;
7806 break;
7807 }
7808 if ((ffecom_num_entrypoints_ == 0)
7809 && (bt == FFEINFO_basictypeCOMPLEX)
7810 && (ffesymbol_is_f2c (ffecom_primary_entry_)))
7811 { /* Result is already in list of dummies, use
7812 it. */
7813 t = ffecom_func_result_;
7814 addr = TRUE;
7815 break;
7816 }
7817 if (ffecom_func_result_ != NULL_TREE)
7818 {
7819 t = ffecom_func_result_;
7820 break;
7821 }
7822 if ((ffecom_num_entrypoints_ != 0)
7823 && (ffecom_master_bt_ == FFEINFO_basictypeNONE))
7824 {
7825 yes = suspend_momentary ();
5ff904cd 7826
c7e4ee3a
CB
7827 assert (ffecom_multi_retval_ != NULL_TREE);
7828 t = ffecom_1 (INDIRECT_REF, ffecom_multi_type_node_,
7829 ffecom_multi_retval_);
7830 t = ffecom_2 (COMPONENT_REF, ffecom_tree_type[bt][kt],
7831 t, ffecom_multi_fields_[bt][kt]);
5ff904cd 7832
c7e4ee3a
CB
7833 resume_momentary (yes);
7834 break;
7835 }
5ff904cd 7836
c7e4ee3a 7837 yes = suspend_momentary ();
5ff904cd 7838
c7e4ee3a
CB
7839 t = build_decl (VAR_DECL,
7840 ffecom_get_identifier_ (ffesymbol_text (s)),
7841 ffecom_tree_type[bt][kt]);
7842 TREE_STATIC (t) = 0; /* Put result on stack. */
7843 t = start_decl (t, FALSE);
7844 finish_decl (t, NULL_TREE, FALSE);
5ff904cd 7845
c7e4ee3a 7846 ffecom_func_result_ = t;
5ff904cd 7847
c7e4ee3a
CB
7848 resume_momentary (yes);
7849 break;
5ff904cd 7850
c7e4ee3a
CB
7851 case FFEINFO_whereDUMMY:
7852 {
7853 tree type;
7854 ffebld dl;
7855 ffebld dim;
7856 tree low;
7857 tree high;
7858 tree old_sizes;
7859 bool adjustable = FALSE; /* Conditionally adjustable? */
5ff904cd 7860
c7e4ee3a
CB
7861 type = ffecom_tree_type[bt][kt];
7862 if (ffesymbol_sfdummyparent (s) != NULL)
7863 {
7864 if (current_function_decl == ffecom_outer_function_decl_)
7865 { /* Exec transition before sfunc
7866 context; get it later. */
7867 break;
7868 }
7869 t = ffecom_get_identifier_ (ffesymbol_text
7870 (ffesymbol_sfdummyparent (s)));
7871 }
7872 else
7873 t = ffecom_get_identifier_ (ffesymbol_text (s));
5ff904cd 7874
c7e4ee3a 7875 assert (ffecom_transform_only_dummies_);
5ff904cd 7876
c7e4ee3a
CB
7877 old_sizes = get_pending_sizes ();
7878 put_pending_sizes (old_sizes);
5ff904cd 7879
c7e4ee3a
CB
7880 if (bt == FFEINFO_basictypeCHARACTER)
7881 tlen = ffecom_char_enhance_arg_ (&type, s);
7882 type = ffecom_check_size_overflow_ (s, type, TRUE);
5ff904cd 7883
c7e4ee3a
CB
7884 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
7885 {
7886 if (type == error_mark_node)
7887 break;
5ff904cd 7888
c7e4ee3a
CB
7889 dim = ffebld_head (dl);
7890 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
7891 if ((ffebld_left (dim) == NULL) || ffecom_doing_entry_)
7892 low = ffecom_integer_one_node;
7893 else
7894 low = ffecom_expr (ffebld_left (dim));
7895 assert (ffebld_right (dim) != NULL);
7896 if ((ffebld_op (ffebld_right (dim)) == FFEBLD_opSTAR)
7897 || ffecom_doing_entry_)
7898 {
7899 /* Used to just do high=low. But for ffecom_tree_
7900 canonize_ref_, it probably is important to correctly
7901 assess the size. E.g. given COMPLEX C(*),CFUNC and
7902 C(2)=CFUNC(C), overlap can happen, while it can't
7903 for, say, C(1)=CFUNC(C(2)). */
7904 /* Even more recently used to set to INT_MAX, but that
7905 broke when some overflow checking went into the back
7906 end. Now we just leave the upper bound unspecified. */
7907 high = NULL;
7908 }
7909 else
7910 high = ffecom_expr (ffebld_right (dim));
5ff904cd 7911
c7e4ee3a
CB
7912 /* Determine whether array is conditionally adjustable,
7913 to decide whether back-end magic is needed.
5ff904cd 7914
c7e4ee3a
CB
7915 Normally the front end uses the back-end function
7916 variable_size to wrap SAVE_EXPR's around expressions
7917 affecting the size/shape of an array so that the
7918 size/shape info doesn't change during execution
7919 of the compiled code even though variables and
7920 functions referenced in those expressions might.
5ff904cd 7921
c7e4ee3a
CB
7922 variable_size also makes sure those saved expressions
7923 get evaluated immediately upon entry to the
7924 compiled procedure -- the front end normally doesn't
7925 have to worry about that.
3cf0cea4 7926
c7e4ee3a
CB
7927 However, there is a problem with this that affects
7928 g77's implementation of entry points, and that is
7929 that it is _not_ true that each invocation of the
7930 compiled procedure is permitted to evaluate
7931 array size/shape info -- because it is possible
7932 that, for some invocations, that info is invalid (in
7933 which case it is "promised" -- i.e. a violation of
7934 the Fortran standard -- that the compiled code
7935 won't reference the array or its size/shape
7936 during that particular invocation).
5ff904cd 7937
c7e4ee3a 7938 To phrase this in C terms, consider this gcc function:
5ff904cd 7939
c7e4ee3a
CB
7940 void foo (int *n, float (*a)[*n])
7941 {
7942 // a is "pointer to array ...", fyi.
7943 }
5ff904cd 7944
c7e4ee3a
CB
7945 Suppose that, for some invocations, it is permitted
7946 for a caller of foo to do this:
5ff904cd 7947
c7e4ee3a 7948 foo (NULL, NULL);
5ff904cd 7949
c7e4ee3a
CB
7950 Now the _written_ code for foo can take such a call
7951 into account by either testing explicitly for whether
7952 (a == NULL) || (n == NULL) -- presumably it is
7953 not permitted to reference *a in various fashions
7954 if (n == NULL) I suppose -- or it can avoid it by
7955 looking at other info (other arguments, static/global
7956 data, etc.).
5ff904cd 7957
c7e4ee3a
CB
7958 However, this won't work in gcc 2.5.8 because it'll
7959 automatically emit the code to save the "*n"
7960 expression, which'll yield a NULL dereference for
7961 the "foo (NULL, NULL)" call, something the code
7962 for foo cannot prevent.
5ff904cd 7963
c7e4ee3a
CB
7964 g77 definitely needs to avoid executing such
7965 code anytime the pointer to the adjustable array
7966 is NULL, because even if its bounds expressions
7967 don't have any references to possible "absent"
7968 variables like "*n" -- say all variable references
7969 are to COMMON variables, i.e. global (though in C,
7970 local static could actually make sense) -- the
7971 expressions could yield other run-time problems
7972 for allowably "dead" values in those variables.
5ff904cd 7973
c7e4ee3a
CB
7974 For example, let's consider a more complicated
7975 version of foo:
5ff904cd 7976
c7e4ee3a
CB
7977 extern int i;
7978 extern int j;
5ff904cd 7979
c7e4ee3a
CB
7980 void foo (float (*a)[i/j])
7981 {
7982 ...
7983 }
5ff904cd 7984
c7e4ee3a
CB
7985 The above is (essentially) quite valid for Fortran
7986 but, again, for a call like "foo (NULL);", it is
7987 permitted for i and j to be undefined when the
7988 call is made. If j happened to be zero, for
7989 example, emitting the code to evaluate "i/j"
7990 could result in a run-time error.
5ff904cd 7991
c7e4ee3a
CB
7992 Offhand, though I don't have my F77 or F90
7993 standards handy, it might even be valid for a
7994 bounds expression to contain a function reference,
7995 in which case I doubt it is permitted for an
7996 implementation to invoke that function in the
7997 Fortran case involved here (invocation of an
7998 alternate ENTRY point that doesn't have the adjustable
7999 array as one of its arguments).
5ff904cd 8000
c7e4ee3a
CB
8001 So, the code that the compiler would normally emit
8002 to preevaluate the size/shape info for an
8003 adjustable array _must not_ be executed at run time
8004 in certain cases. Specifically, for Fortran,
8005 the case is when the pointer to the adjustable
8006 array == NULL. (For gnu-ish C, it might be nice
8007 for the source code itself to specify an expression
8008 that, if TRUE, inhibits execution of the code. Or
8009 reverse the sense for elegance.)
5ff904cd 8010
c7e4ee3a
CB
8011 (Note that g77 could use a different test than NULL,
8012 actually, since it happens to always pass an
8013 integer to the called function that specifies which
8014 entry point is being invoked. Hmm, this might
8015 solve the next problem.)
8016
8017 One way a user could, I suppose, write "foo" so
8018 it works is to insert COND_EXPR's for the
8019 size/shape info so the dangerous stuff isn't
8020 actually done, as in:
8021
8022 void foo (int *n, float (*a)[(a == NULL) ? 0 : *n])
8023 {
8024 ...
8025 }
5ff904cd 8026
c7e4ee3a
CB
8027 The next problem is that the front end needs to
8028 be able to tell the back end about the array's
8029 decl _before_ it tells it about the conditional
8030 expression to inhibit evaluation of size/shape info,
8031 as shown above.
5ff904cd 8032
c7e4ee3a
CB
8033 To solve this, the front end needs to be able
8034 to give the back end the expression to inhibit
8035 generation of the preevaluation code _after_
8036 it makes the decl for the adjustable array.
5ff904cd 8037
c7e4ee3a
CB
8038 Until then, the above example using the COND_EXPR
8039 doesn't pass muster with gcc because the "(a == NULL)"
8040 part has a reference to "a", which is still
8041 undefined at that point.
5ff904cd 8042
c7e4ee3a
CB
8043 g77 will therefore use a different mechanism in the
8044 meantime. */
5ff904cd 8045
c7e4ee3a
CB
8046 if (!adjustable
8047 && ((TREE_CODE (low) != INTEGER_CST)
8048 || (high && TREE_CODE (high) != INTEGER_CST)))
8049 adjustable = TRUE;
5ff904cd 8050
c7e4ee3a
CB
8051#if 0 /* Old approach -- see below. */
8052 if (TREE_CODE (low) != INTEGER_CST)
8053 low = ffecom_3 (COND_EXPR, integer_type_node,
8054 ffecom_adjarray_passed_ (s),
8055 low,
8056 ffecom_integer_zero_node);
5ff904cd 8057
c7e4ee3a
CB
8058 if (high && TREE_CODE (high) != INTEGER_CST)
8059 high = ffecom_3 (COND_EXPR, integer_type_node,
8060 ffecom_adjarray_passed_ (s),
8061 high,
8062 ffecom_integer_zero_node);
8063#endif
5ff904cd 8064
c7e4ee3a
CB
8065 /* ~~~gcc/stor-layout.c (layout_type) should do this,
8066 probably. Fixes 950302-1.f. */
5ff904cd 8067
c7e4ee3a
CB
8068 if (TREE_CODE (low) != INTEGER_CST)
8069 low = variable_size (low);
5ff904cd 8070
c7e4ee3a
CB
8071 /* ~~~Similarly, this fixes dumb0.f. The C front end
8072 does this, which is why dumb0.c would work. */
5ff904cd 8073
c7e4ee3a
CB
8074 if (high && TREE_CODE (high) != INTEGER_CST)
8075 high = variable_size (high);
5ff904cd 8076
c7e4ee3a
CB
8077 type
8078 = build_array_type
8079 (type,
8080 build_range_type (ffecom_integer_type_node,
8081 low, high));
8082 type = ffecom_check_size_overflow_ (s, type, TRUE);
8083 }
5ff904cd 8084
c7e4ee3a
CB
8085 if (type == error_mark_node)
8086 {
8087 t = error_mark_node;
8088 break;
8089 }
5ff904cd 8090
c7e4ee3a
CB
8091 if ((ffesymbol_sfdummyparent (s) == NULL)
8092 || (ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER))
8093 {
8094 type = build_pointer_type (type);
8095 addr = TRUE;
8096 }
5ff904cd 8097
c7e4ee3a 8098 t = build_decl (PARM_DECL, t, type);
5ff904cd 8099#if BUILT_FOR_270
c7e4ee3a 8100 DECL_ARTIFICIAL (t) = 1;
5ff904cd 8101#endif
5ff904cd 8102
c7e4ee3a
CB
8103 /* If this arg is present in every entry point's list of
8104 dummy args, then we're done. */
5ff904cd 8105
c7e4ee3a
CB
8106 if (ffesymbol_numentries (s)
8107 == (ffecom_num_entrypoints_ + 1))
5ff904cd 8108 break;
5ff904cd 8109
c7e4ee3a 8110#if 1
5ff904cd 8111
c7e4ee3a
CB
8112 /* If variable_size in stor-layout has been called during
8113 the above, then get_pending_sizes should have the
8114 yet-to-be-evaluated saved expressions pending.
8115 Make the whole lot of them get emitted, conditionally
8116 on whether the array decl ("t" above) is not NULL. */
5ff904cd 8117
c7e4ee3a
CB
8118 {
8119 tree sizes = get_pending_sizes ();
8120 tree tem;
5ff904cd 8121
c7e4ee3a
CB
8122 for (tem = sizes;
8123 tem != old_sizes;
8124 tem = TREE_CHAIN (tem))
8125 {
8126 tree temv = TREE_VALUE (tem);
5ff904cd 8127
c7e4ee3a
CB
8128 if (sizes == tem)
8129 sizes = temv;
8130 else
8131 sizes
8132 = ffecom_2 (COMPOUND_EXPR,
8133 TREE_TYPE (sizes),
8134 temv,
8135 sizes);
8136 }
5ff904cd 8137
c7e4ee3a
CB
8138 if (sizes != tem)
8139 {
8140 sizes
8141 = ffecom_3 (COND_EXPR,
8142 TREE_TYPE (sizes),
8143 ffecom_2 (NE_EXPR,
8144 integer_type_node,
8145 t,
8146 null_pointer_node),
8147 sizes,
8148 convert (TREE_TYPE (sizes),
8149 integer_zero_node));
8150 sizes = ffecom_save_tree (sizes);
5ff904cd 8151
c7e4ee3a
CB
8152 sizes
8153 = tree_cons (NULL_TREE, sizes, tem);
8154 }
5ff904cd 8155
c7e4ee3a
CB
8156 if (sizes)
8157 put_pending_sizes (sizes);
8158 }
5ff904cd 8159
c7e4ee3a
CB
8160#else
8161#if 0
8162 if (adjustable
8163 && (ffesymbol_numentries (s)
8164 != ffecom_num_entrypoints_ + 1))
8165 DECL_SOMETHING (t)
8166 = ffecom_2 (NE_EXPR, integer_type_node,
8167 t,
8168 null_pointer_node);
8169#else
8170#if 0
8171 if (adjustable
8172 && (ffesymbol_numentries (s)
8173 != ffecom_num_entrypoints_ + 1))
8174 {
8175 ffebad_start (FFEBAD_MISSING_ADJARRAY_UNSUPPORTED);
8176 ffebad_here (0, ffesymbol_where_line (s),
8177 ffesymbol_where_column (s));
8178 ffebad_string (ffesymbol_text (s));
8179 ffebad_finish ();
8180 }
8181#endif
8182#endif
8183#endif
8184 }
5ff904cd
JL
8185 break;
8186
c7e4ee3a 8187 case FFEINFO_whereCOMMON:
5ff904cd 8188 {
c7e4ee3a
CB
8189 ffesymbol cs;
8190 ffeglobal cg;
8191 tree ct;
5ff904cd
JL
8192 ffestorag st = ffesymbol_storage (s);
8193 tree type;
c7e4ee3a 8194 int yes;
5ff904cd 8195
c7e4ee3a
CB
8196 cs = ffesymbol_common (s); /* The COMMON area itself. */
8197 if (st != NULL) /* Else not laid out. */
5ff904cd 8198 {
c7e4ee3a
CB
8199 ffecom_transform_common_ (cs);
8200 st = ffesymbol_storage (s);
5ff904cd
JL
8201 }
8202
c7e4ee3a 8203 yes = suspend_momentary ();
5ff904cd 8204
c7e4ee3a 8205 type = ffecom_type_localvar_ (s, bt, kt);
5ff904cd 8206
c7e4ee3a
CB
8207 cg = ffesymbol_global (cs); /* The global COMMON info. */
8208 if ((cg == NULL)
8209 || (ffeglobal_type (cg) != FFEGLOBAL_typeCOMMON))
8210 ct = NULL_TREE;
8211 else
8212 ct = ffeglobal_hook (cg); /* The common area's tree. */
5ff904cd 8213
c7e4ee3a
CB
8214 if ((ct == NULL_TREE)
8215 || (st == NULL)
8216 || (type == error_mark_node))
8217 t = error_mark_node;
8218 else
8219 {
8220 ffetargetOffset offset;
8221 ffestorag cst;
5ff904cd 8222
c7e4ee3a
CB
8223 cst = ffestorag_parent (st);
8224 assert (cst == ffesymbol_storage (cs));
5ff904cd 8225
c7e4ee3a
CB
8226 offset = ffestorag_modulo (cst)
8227 + ffestorag_offset (st)
8228 - ffestorag_offset (cst);
5ff904cd 8229
c7e4ee3a 8230 ffecom_debug_kludge_ (ct, "COMMON", s, type, offset);
5ff904cd 8231
c7e4ee3a 8232 /* (t_type *) (((char *) &ct) + offset) */
5ff904cd
JL
8233
8234 t = convert (string_type_node, /* (char *) */
8235 ffecom_1 (ADDR_EXPR,
c7e4ee3a
CB
8236 build_pointer_type (TREE_TYPE (ct)),
8237 ct));
5ff904cd
JL
8238 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
8239 t,
8240 build_int_2 (offset, 0));
8241 t = convert (build_pointer_type (type),
8242 t);
d50108c7 8243 TREE_CONSTANT (t) = 1;
5ff904cd
JL
8244
8245 addr = TRUE;
5ff904cd 8246 }
5ff904cd 8247
c7e4ee3a
CB
8248 resume_momentary (yes);
8249 }
8250 break;
5ff904cd 8251
c7e4ee3a
CB
8252 case FFEINFO_whereIMMEDIATE:
8253 case FFEINFO_whereGLOBAL:
8254 case FFEINFO_whereFLEETING:
8255 case FFEINFO_whereFLEETING_CADDR:
8256 case FFEINFO_whereFLEETING_IADDR:
8257 case FFEINFO_whereINTRINSIC:
8258 case FFEINFO_whereCONSTANT_SUBOBJECT:
8259 default:
8260 assert ("ENTITY where unheard of" == NULL);
8261 /* Fall through. */
8262 case FFEINFO_whereANY:
8263 t = error_mark_node;
8264 break;
8265 }
8266 break;
5ff904cd 8267
c7e4ee3a
CB
8268 case FFEINFO_kindFUNCTION:
8269 switch (ffeinfo_where (ffesymbol_info (s)))
8270 {
8271 case FFEINFO_whereLOCAL: /* Me. */
8272 assert (!ffecom_transform_only_dummies_);
8273 t = current_function_decl;
5ff904cd
JL
8274 break;
8275
c7e4ee3a 8276 case FFEINFO_whereGLOBAL:
5ff904cd
JL
8277 assert (!ffecom_transform_only_dummies_);
8278
c7e4ee3a
CB
8279 if (((g = ffesymbol_global (s)) != NULL)
8280 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8281 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8282 && (ffeglobal_hook (g) != NULL_TREE)
8283 && ffe_is_globals ())
5ff904cd 8284 {
c7e4ee3a 8285 t = ffeglobal_hook (g);
5ff904cd
JL
8286 break;
8287 }
5ff904cd 8288
c7e4ee3a
CB
8289 push_obstacks_nochange ();
8290 end_temporary_allocation ();
5ff904cd 8291
c7e4ee3a
CB
8292 if (ffesymbol_is_f2c (s)
8293 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8294 t = ffecom_tree_fun_type[bt][kt];
8295 else
8296 t = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
5ff904cd 8297
c7e4ee3a
CB
8298 t = build_decl (FUNCTION_DECL,
8299 ffecom_get_external_identifier_ (s),
8300 t);
8301 DECL_EXTERNAL (t) = 1;
8302 TREE_PUBLIC (t) = 1;
5ff904cd 8303
5ff904cd
JL
8304 t = start_decl (t, FALSE);
8305 finish_decl (t, NULL_TREE, FALSE);
8306
c7e4ee3a
CB
8307 if ((g != NULL)
8308 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8309 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8310 ffeglobal_set_hook (g, t);
8311
8312 resume_temporary_allocation ();
8313 pop_obstacks ();
5ff904cd 8314
5ff904cd
JL
8315 break;
8316
8317 case FFEINFO_whereDUMMY:
c7e4ee3a 8318 assert (ffecom_transform_only_dummies_);
5ff904cd 8319
c7e4ee3a
CB
8320 if (ffesymbol_is_f2c (s)
8321 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8322 t = ffecom_tree_ptr_to_fun_type[bt][kt];
8323 else
8324 t = build_pointer_type
8325 (build_function_type (ffecom_tree_type[bt][kt], NULL_TREE));
8326
8327 t = build_decl (PARM_DECL,
8328 ffecom_get_identifier_ (ffesymbol_text (s)),
8329 t);
8330#if BUILT_FOR_270
8331 DECL_ARTIFICIAL (t) = 1;
8332#endif
8333 addr = TRUE;
8334 break;
8335
8336 case FFEINFO_whereCONSTANT: /* Statement function. */
8337 assert (!ffecom_transform_only_dummies_);
8338 t = ffecom_gen_sfuncdef_ (s, bt, kt);
8339 break;
8340
8341 case FFEINFO_whereINTRINSIC:
8342 assert (!ffecom_transform_only_dummies_);
8343 break; /* Let actual references generate their
8344 decls. */
8345
8346 default:
8347 assert ("FUNCTION where unheard of" == NULL);
8348 /* Fall through. */
8349 case FFEINFO_whereANY:
8350 t = error_mark_node;
8351 break;
8352 }
8353 break;
8354
8355 case FFEINFO_kindSUBROUTINE:
8356 switch (ffeinfo_where (ffesymbol_info (s)))
8357 {
8358 case FFEINFO_whereLOCAL: /* Me. */
8359 assert (!ffecom_transform_only_dummies_);
8360 t = current_function_decl;
8361 break;
5ff904cd 8362
c7e4ee3a
CB
8363 case FFEINFO_whereGLOBAL:
8364 assert (!ffecom_transform_only_dummies_);
5ff904cd 8365
c7e4ee3a
CB
8366 if (((g = ffesymbol_global (s)) != NULL)
8367 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8368 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8369 && (ffeglobal_hook (g) != NULL_TREE)
8370 && ffe_is_globals ())
8371 {
8372 t = ffeglobal_hook (g);
8373 break;
8374 }
5ff904cd 8375
c7e4ee3a
CB
8376 push_obstacks_nochange ();
8377 end_temporary_allocation ();
5ff904cd 8378
c7e4ee3a
CB
8379 t = build_decl (FUNCTION_DECL,
8380 ffecom_get_external_identifier_ (s),
8381 ffecom_tree_subr_type);
8382 DECL_EXTERNAL (t) = 1;
8383 TREE_PUBLIC (t) = 1;
5ff904cd 8384
c7e4ee3a
CB
8385 t = start_decl (t, FALSE);
8386 finish_decl (t, NULL_TREE, FALSE);
5ff904cd 8387
c7e4ee3a
CB
8388 if ((g != NULL)
8389 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8390 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8391 ffeglobal_set_hook (g, t);
5ff904cd 8392
c7e4ee3a
CB
8393 resume_temporary_allocation ();
8394 pop_obstacks ();
5ff904cd 8395
c7e4ee3a 8396 break;
5ff904cd 8397
c7e4ee3a
CB
8398 case FFEINFO_whereDUMMY:
8399 assert (ffecom_transform_only_dummies_);
5ff904cd 8400
c7e4ee3a
CB
8401 t = build_decl (PARM_DECL,
8402 ffecom_get_identifier_ (ffesymbol_text (s)),
8403 ffecom_tree_ptr_to_subr_type);
8404#if BUILT_FOR_270
8405 DECL_ARTIFICIAL (t) = 1;
8406#endif
8407 addr = TRUE;
8408 break;
5ff904cd 8409
c7e4ee3a
CB
8410 case FFEINFO_whereINTRINSIC:
8411 assert (!ffecom_transform_only_dummies_);
8412 break; /* Let actual references generate their
8413 decls. */
5ff904cd 8414
c7e4ee3a
CB
8415 default:
8416 assert ("SUBROUTINE where unheard of" == NULL);
8417 /* Fall through. */
8418 case FFEINFO_whereANY:
8419 t = error_mark_node;
8420 break;
8421 }
8422 break;
5ff904cd 8423
c7e4ee3a
CB
8424 case FFEINFO_kindPROGRAM:
8425 switch (ffeinfo_where (ffesymbol_info (s)))
8426 {
8427 case FFEINFO_whereLOCAL: /* Me. */
8428 assert (!ffecom_transform_only_dummies_);
8429 t = current_function_decl;
8430 break;
5ff904cd 8431
c7e4ee3a
CB
8432 case FFEINFO_whereCOMMON:
8433 case FFEINFO_whereDUMMY:
8434 case FFEINFO_whereGLOBAL:
8435 case FFEINFO_whereRESULT:
8436 case FFEINFO_whereFLEETING:
8437 case FFEINFO_whereFLEETING_CADDR:
8438 case FFEINFO_whereFLEETING_IADDR:
8439 case FFEINFO_whereIMMEDIATE:
8440 case FFEINFO_whereINTRINSIC:
8441 case FFEINFO_whereCONSTANT:
8442 case FFEINFO_whereCONSTANT_SUBOBJECT:
8443 default:
8444 assert ("PROGRAM where unheard of" == NULL);
8445 /* Fall through. */
8446 case FFEINFO_whereANY:
8447 t = error_mark_node;
8448 break;
8449 }
8450 break;
5ff904cd 8451
c7e4ee3a
CB
8452 case FFEINFO_kindBLOCKDATA:
8453 switch (ffeinfo_where (ffesymbol_info (s)))
8454 {
8455 case FFEINFO_whereLOCAL: /* Me. */
8456 assert (!ffecom_transform_only_dummies_);
8457 t = current_function_decl;
8458 break;
5ff904cd 8459
c7e4ee3a
CB
8460 case FFEINFO_whereGLOBAL:
8461 assert (!ffecom_transform_only_dummies_);
5ff904cd 8462
c7e4ee3a
CB
8463 push_obstacks_nochange ();
8464 end_temporary_allocation ();
5ff904cd 8465
c7e4ee3a
CB
8466 t = build_decl (FUNCTION_DECL,
8467 ffecom_get_external_identifier_ (s),
8468 ffecom_tree_blockdata_type);
8469 DECL_EXTERNAL (t) = 1;
8470 TREE_PUBLIC (t) = 1;
5ff904cd 8471
c7e4ee3a
CB
8472 t = start_decl (t, FALSE);
8473 finish_decl (t, NULL_TREE, FALSE);
5ff904cd 8474
c7e4ee3a
CB
8475 resume_temporary_allocation ();
8476 pop_obstacks ();
5ff904cd 8477
c7e4ee3a 8478 break;
5ff904cd 8479
c7e4ee3a
CB
8480 case FFEINFO_whereCOMMON:
8481 case FFEINFO_whereDUMMY:
8482 case FFEINFO_whereRESULT:
8483 case FFEINFO_whereFLEETING:
8484 case FFEINFO_whereFLEETING_CADDR:
8485 case FFEINFO_whereFLEETING_IADDR:
8486 case FFEINFO_whereIMMEDIATE:
8487 case FFEINFO_whereINTRINSIC:
8488 case FFEINFO_whereCONSTANT:
8489 case FFEINFO_whereCONSTANT_SUBOBJECT:
8490 default:
8491 assert ("BLOCKDATA where unheard of" == NULL);
8492 /* Fall through. */
8493 case FFEINFO_whereANY:
8494 t = error_mark_node;
8495 break;
8496 }
8497 break;
5ff904cd 8498
c7e4ee3a
CB
8499 case FFEINFO_kindCOMMON:
8500 switch (ffeinfo_where (ffesymbol_info (s)))
8501 {
8502 case FFEINFO_whereLOCAL:
8503 assert (!ffecom_transform_only_dummies_);
8504 ffecom_transform_common_ (s);
8505 break;
8506
8507 case FFEINFO_whereNONE:
8508 case FFEINFO_whereCOMMON:
8509 case FFEINFO_whereDUMMY:
8510 case FFEINFO_whereGLOBAL:
8511 case FFEINFO_whereRESULT:
8512 case FFEINFO_whereFLEETING:
8513 case FFEINFO_whereFLEETING_CADDR:
8514 case FFEINFO_whereFLEETING_IADDR:
8515 case FFEINFO_whereIMMEDIATE:
8516 case FFEINFO_whereINTRINSIC:
8517 case FFEINFO_whereCONSTANT:
8518 case FFEINFO_whereCONSTANT_SUBOBJECT:
8519 default:
8520 assert ("COMMON where unheard of" == NULL);
8521 /* Fall through. */
8522 case FFEINFO_whereANY:
8523 t = error_mark_node;
8524 break;
8525 }
8526 break;
5ff904cd 8527
c7e4ee3a
CB
8528 case FFEINFO_kindCONSTRUCT:
8529 switch (ffeinfo_where (ffesymbol_info (s)))
8530 {
8531 case FFEINFO_whereLOCAL:
8532 assert (!ffecom_transform_only_dummies_);
8533 break;
5ff904cd 8534
c7e4ee3a
CB
8535 case FFEINFO_whereNONE:
8536 case FFEINFO_whereCOMMON:
8537 case FFEINFO_whereDUMMY:
8538 case FFEINFO_whereGLOBAL:
8539 case FFEINFO_whereRESULT:
8540 case FFEINFO_whereFLEETING:
8541 case FFEINFO_whereFLEETING_CADDR:
8542 case FFEINFO_whereFLEETING_IADDR:
8543 case FFEINFO_whereIMMEDIATE:
8544 case FFEINFO_whereINTRINSIC:
8545 case FFEINFO_whereCONSTANT:
8546 case FFEINFO_whereCONSTANT_SUBOBJECT:
8547 default:
8548 assert ("CONSTRUCT where unheard of" == NULL);
8549 /* Fall through. */
8550 case FFEINFO_whereANY:
8551 t = error_mark_node;
8552 break;
8553 }
8554 break;
5ff904cd 8555
c7e4ee3a
CB
8556 case FFEINFO_kindNAMELIST:
8557 switch (ffeinfo_where (ffesymbol_info (s)))
8558 {
8559 case FFEINFO_whereLOCAL:
8560 assert (!ffecom_transform_only_dummies_);
8561 t = ffecom_transform_namelist_ (s);
8562 break;
5ff904cd 8563
c7e4ee3a
CB
8564 case FFEINFO_whereNONE:
8565 case FFEINFO_whereCOMMON:
8566 case FFEINFO_whereDUMMY:
8567 case FFEINFO_whereGLOBAL:
8568 case FFEINFO_whereRESULT:
8569 case FFEINFO_whereFLEETING:
8570 case FFEINFO_whereFLEETING_CADDR:
8571 case FFEINFO_whereFLEETING_IADDR:
8572 case FFEINFO_whereIMMEDIATE:
8573 case FFEINFO_whereINTRINSIC:
8574 case FFEINFO_whereCONSTANT:
8575 case FFEINFO_whereCONSTANT_SUBOBJECT:
8576 default:
8577 assert ("NAMELIST where unheard of" == NULL);
8578 /* Fall through. */
8579 case FFEINFO_whereANY:
8580 t = error_mark_node;
8581 break;
8582 }
8583 break;
5ff904cd 8584
c7e4ee3a
CB
8585 default:
8586 assert ("kind unheard of" == NULL);
8587 /* Fall through. */
8588 case FFEINFO_kindANY:
8589 t = error_mark_node;
8590 break;
8591 }
5ff904cd 8592
c7e4ee3a
CB
8593 ffesymbol_hook (s).decl_tree = t;
8594 ffesymbol_hook (s).length_tree = tlen;
8595 ffesymbol_hook (s).addr = addr;
5ff904cd 8596
c7e4ee3a
CB
8597 lineno = old_lineno;
8598 input_filename = old_input_filename;
5ff904cd 8599
c7e4ee3a
CB
8600 return s;
8601}
5ff904cd 8602
5ff904cd 8603#endif
c7e4ee3a 8604/* Transform into ASSIGNable symbol.
5ff904cd 8605
c7e4ee3a
CB
8606 Symbol has already been transformed, but for whatever reason, the
8607 resulting decl_tree has been deemed not usable for an ASSIGN target.
8608 (E.g. it isn't wide enough to hold a pointer.) So, here we invent
8609 another local symbol of type void * and stuff that in the assign_tree
8610 argument. The F77/F90 standards allow this implementation. */
5ff904cd 8611
c7e4ee3a
CB
8612#if FFECOM_targetCURRENT == FFECOM_targetGCC
8613static ffesymbol
8614ffecom_sym_transform_assign_ (ffesymbol s)
8615{
8616 tree t; /* Transformed thingy. */
8617 int yes;
8618 int old_lineno = lineno;
8619 char *old_input_filename = input_filename;
5ff904cd 8620
c7e4ee3a
CB
8621 if (ffesymbol_sfdummyparent (s) == NULL)
8622 {
8623 input_filename = ffesymbol_where_filename (s);
8624 lineno = ffesymbol_where_filelinenum (s);
8625 }
8626 else
8627 {
8628 ffesymbol sf = ffesymbol_sfdummyparent (s);
5ff904cd 8629
c7e4ee3a
CB
8630 input_filename = ffesymbol_where_filename (sf);
8631 lineno = ffesymbol_where_filelinenum (sf);
8632 }
5ff904cd 8633
c7e4ee3a 8634 assert (!ffecom_transform_only_dummies_);
5ff904cd 8635
c7e4ee3a 8636 yes = suspend_momentary ();
5ff904cd 8637
c7e4ee3a
CB
8638 t = build_decl (VAR_DECL,
8639 ffecom_get_invented_identifier ("__g77_ASSIGN_%s",
8640 ffesymbol_text (s),
8641 -1),
8642 TREE_TYPE (null_pointer_node));
5ff904cd 8643
c7e4ee3a
CB
8644 switch (ffesymbol_where (s))
8645 {
8646 case FFEINFO_whereLOCAL:
8647 /* Unlike for regular vars, SAVE status is easy to determine for
8648 ASSIGNed vars, since there's no initialization, there's no
8649 effective storage association (so "SAVE J" does not apply to
8650 K even given "EQUIVALENCE (J,K)"), there's no size issue
8651 to worry about, etc. */
8652 if ((ffesymbol_is_save (s) || ffe_is_saveall ())
8653 && (ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8654 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA))
8655 TREE_STATIC (t) = 1; /* SAVEd in proc, make static. */
8656 else
8657 TREE_STATIC (t) = 0; /* No need to make static. */
8658 break;
5ff904cd 8659
c7e4ee3a
CB
8660 case FFEINFO_whereCOMMON:
8661 TREE_STATIC (t) = 1; /* Assume COMMONs always SAVEd. */
8662 break;
5ff904cd 8663
c7e4ee3a
CB
8664 case FFEINFO_whereDUMMY:
8665 /* Note that twinning a DUMMY means the caller won't see
8666 the ASSIGNed value. But both F77 and F90 allow implementations
8667 to do this, i.e. disallow Fortran code that would try and
8668 take advantage of actually putting a label into a variable
8669 via a dummy argument (or any other storage association, for
8670 that matter). */
8671 TREE_STATIC (t) = 0;
8672 break;
5ff904cd 8673
c7e4ee3a
CB
8674 default:
8675 TREE_STATIC (t) = 0;
8676 break;
8677 }
5ff904cd 8678
c7e4ee3a
CB
8679 t = start_decl (t, FALSE);
8680 finish_decl (t, NULL_TREE, FALSE);
5ff904cd 8681
c7e4ee3a 8682 resume_momentary (yes);
5ff904cd 8683
c7e4ee3a 8684 ffesymbol_hook (s).assign_tree = t;
5ff904cd 8685
c7e4ee3a
CB
8686 lineno = old_lineno;
8687 input_filename = old_input_filename;
5ff904cd 8688
c7e4ee3a
CB
8689 return s;
8690}
5ff904cd 8691
c7e4ee3a
CB
8692#endif
8693/* Implement COMMON area in back end.
5ff904cd 8694
c7e4ee3a
CB
8695 Because COMMON-based variables can be referenced in the dimension
8696 expressions of dummy (adjustable) arrays, and because dummies
8697 (in the gcc back end) need to be put in the outer binding level
8698 of a function (which has two binding levels, the outer holding
8699 the dummies and the inner holding the other vars), special care
8700 must be taken to handle COMMON areas.
5ff904cd 8701
c7e4ee3a
CB
8702 The current strategy is basically to always tell the back end about
8703 the COMMON area as a top-level external reference to just a block
8704 of storage of the master type of that area (e.g. integer, real,
8705 character, whatever -- not a structure). As a distinct action,
8706 if initial values are provided, tell the back end about the area
8707 as a top-level non-external (initialized) area and remember not to
8708 allow further initialization or expansion of the area. Meanwhile,
8709 if no initialization happens at all, tell the back end about
8710 the largest size we've seen declared so the space does get reserved.
8711 (This function doesn't handle all that stuff, but it does some
8712 of the important things.)
5ff904cd 8713
c7e4ee3a
CB
8714 Meanwhile, for COMMON variables themselves, just keep creating
8715 references like *((float *) (&common_area + offset)) each time
8716 we reference the variable. In other words, don't make a VAR_DECL
8717 or any kind of component reference (like we used to do before 0.4),
8718 though we might do that as well just for debugging purposes (and
8719 stuff the rtl with the appropriate offset expression). */
5ff904cd 8720
c7e4ee3a
CB
8721#if FFECOM_targetCURRENT == FFECOM_targetGCC
8722static void
8723ffecom_transform_common_ (ffesymbol s)
8724{
8725 ffestorag st = ffesymbol_storage (s);
8726 ffeglobal g = ffesymbol_global (s);
8727 tree cbt;
8728 tree cbtype;
8729 tree init;
8730 tree high;
8731 bool is_init = ffestorag_is_init (st);
5ff904cd 8732
c7e4ee3a 8733 assert (st != NULL);
5ff904cd 8734
c7e4ee3a
CB
8735 if ((g == NULL)
8736 || (ffeglobal_type (g) != FFEGLOBAL_typeCOMMON))
8737 return;
5ff904cd 8738
c7e4ee3a 8739 /* First update the size of the area in global terms. */
5ff904cd 8740
c7e4ee3a 8741 ffeglobal_size_common (s, ffestorag_size (st));
5ff904cd 8742
c7e4ee3a
CB
8743 if (!ffeglobal_common_init (g))
8744 is_init = FALSE; /* No explicit init, don't let erroneous joins init. */
5ff904cd 8745
c7e4ee3a 8746 cbt = ffeglobal_hook (g);
5ff904cd 8747
c7e4ee3a
CB
8748 /* If we already have declared this common block for a previous program
8749 unit, and either we already initialized it or we don't have new
8750 initialization for it, just return what we have without changing it. */
5ff904cd 8751
c7e4ee3a
CB
8752 if ((cbt != NULL_TREE)
8753 && (!is_init
8754 || !DECL_EXTERNAL (cbt)))
8755 return;
5ff904cd 8756
c7e4ee3a 8757 /* Process inits. */
5ff904cd 8758
c7e4ee3a
CB
8759 if (is_init)
8760 {
8761 if (ffestorag_init (st) != NULL)
5ff904cd 8762 {
c7e4ee3a 8763 ffebld sexp;
5ff904cd 8764
c7e4ee3a
CB
8765 /* Set the padding for the expression, so ffecom_expr
8766 knows to insert that many zeros. */
8767 switch (ffebld_op (sexp = ffestorag_init (st)))
5ff904cd 8768 {
c7e4ee3a
CB
8769 case FFEBLD_opCONTER:
8770 ffebld_conter_set_pad (sexp, ffestorag_modulo (st));
5ff904cd 8771 break;
5ff904cd 8772
c7e4ee3a
CB
8773 case FFEBLD_opARRTER:
8774 ffebld_arrter_set_pad (sexp, ffestorag_modulo (st));
8775 break;
5ff904cd 8776
c7e4ee3a
CB
8777 case FFEBLD_opACCTER:
8778 ffebld_accter_set_pad (sexp, ffestorag_modulo (st));
8779 break;
5ff904cd 8780
c7e4ee3a
CB
8781 default:
8782 assert ("bad op for cmn init (pad)" == NULL);
8783 break;
8784 }
5ff904cd 8785
c7e4ee3a
CB
8786 init = ffecom_expr (sexp);
8787 if (init == error_mark_node)
8788 { /* Hopefully the back end complained! */
8789 init = NULL_TREE;
8790 if (cbt != NULL_TREE)
8791 return;
8792 }
8793 }
8794 else
8795 init = error_mark_node;
8796 }
8797 else
8798 init = NULL_TREE;
5ff904cd 8799
c7e4ee3a
CB
8800 push_obstacks_nochange ();
8801 end_temporary_allocation ();
5ff904cd 8802
c7e4ee3a 8803 /* cbtype must be permanently allocated! */
5ff904cd 8804
c7e4ee3a
CB
8805 /* Allocate the MAX of the areas so far, seen filewide. */
8806 high = build_int_2 ((ffeglobal_common_size (g)
8807 + ffeglobal_common_pad (g)) - 1, 0);
8808 TREE_TYPE (high) = ffecom_integer_type_node;
5ff904cd 8809
c7e4ee3a
CB
8810 if (init)
8811 cbtype = build_array_type (char_type_node,
8812 build_range_type (integer_type_node,
8813 integer_zero_node,
8814 high));
8815 else
8816 cbtype = build_array_type (char_type_node, NULL_TREE);
5ff904cd 8817
c7e4ee3a
CB
8818 if (cbt == NULL_TREE)
8819 {
8820 cbt
8821 = build_decl (VAR_DECL,
8822 ffecom_get_external_identifier_ (s),
8823 cbtype);
8824 TREE_STATIC (cbt) = 1;
8825 TREE_PUBLIC (cbt) = 1;
8826 }
8827 else
8828 {
8829 assert (is_init);
8830 TREE_TYPE (cbt) = cbtype;
8831 }
8832 DECL_EXTERNAL (cbt) = init ? 0 : 1;
8833 DECL_INITIAL (cbt) = init ? error_mark_node : NULL_TREE;
5ff904cd 8834
c7e4ee3a
CB
8835 cbt = start_decl (cbt, TRUE);
8836 if (ffeglobal_hook (g) != NULL)
8837 assert (cbt == ffeglobal_hook (g));
5ff904cd 8838
c7e4ee3a 8839 assert (!init || !DECL_EXTERNAL (cbt));
5ff904cd 8840
c7e4ee3a
CB
8841 /* Make sure that any type can live in COMMON and be referenced
8842 without getting a bus error. We could pick the most restrictive
8843 alignment of all entities actually placed in the COMMON, but
8844 this seems easy enough. */
5ff904cd 8845
c7e4ee3a 8846 DECL_ALIGN (cbt) = BIGGEST_ALIGNMENT;
5ff904cd 8847
c7e4ee3a
CB
8848 if (is_init && (ffestorag_init (st) == NULL))
8849 init = ffecom_init_zero_ (cbt);
5ff904cd 8850
c7e4ee3a 8851 finish_decl (cbt, init, TRUE);
5ff904cd 8852
c7e4ee3a
CB
8853 if (is_init)
8854 ffestorag_set_init (st, ffebld_new_any ());
5ff904cd 8855
c7e4ee3a
CB
8856 if (init)
8857 {
8858 tree size_tree;
5ff904cd 8859
c7e4ee3a
CB
8860 assert (DECL_SIZE (cbt) != NULL_TREE);
8861 assert (TREE_CODE (DECL_SIZE (cbt)) == INTEGER_CST);
8862 size_tree = size_binop (CEIL_DIV_EXPR,
8863 DECL_SIZE (cbt),
8864 size_int (BITS_PER_UNIT));
8865 assert (TREE_INT_CST_HIGH (size_tree) == 0);
8866 assert (TREE_INT_CST_LOW (size_tree)
8867 == ffeglobal_common_size (g) + ffeglobal_common_pad (g));
8868 }
5ff904cd 8869
c7e4ee3a 8870 ffeglobal_set_hook (g, cbt);
5ff904cd 8871
c7e4ee3a 8872 ffestorag_set_hook (st, cbt);
5ff904cd 8873
c7e4ee3a
CB
8874 resume_temporary_allocation ();
8875 pop_obstacks ();
8876}
5ff904cd 8877
c7e4ee3a
CB
8878#endif
8879/* Make master area for local EQUIVALENCE. */
5ff904cd 8880
c7e4ee3a
CB
8881#if FFECOM_targetCURRENT == FFECOM_targetGCC
8882static void
8883ffecom_transform_equiv_ (ffestorag eqst)
8884{
8885 tree eqt;
8886 tree eqtype;
8887 tree init;
8888 tree high;
8889 bool is_init = ffestorag_is_init (eqst);
8890 int yes;
5ff904cd 8891
c7e4ee3a 8892 assert (eqst != NULL);
5ff904cd 8893
c7e4ee3a 8894 eqt = ffestorag_hook (eqst);
5ff904cd 8895
c7e4ee3a
CB
8896 if (eqt != NULL_TREE)
8897 return;
5ff904cd 8898
c7e4ee3a
CB
8899 /* Process inits. */
8900
8901 if (is_init)
8902 {
8903 if (ffestorag_init (eqst) != NULL)
5ff904cd 8904 {
c7e4ee3a 8905 ffebld sexp;
5ff904cd 8906
c7e4ee3a
CB
8907 /* Set the padding for the expression, so ffecom_expr
8908 knows to insert that many zeros. */
8909 switch (ffebld_op (sexp = ffestorag_init (eqst)))
8910 {
8911 case FFEBLD_opCONTER:
8912 ffebld_conter_set_pad (sexp, ffestorag_modulo (eqst));
8913 break;
5ff904cd 8914
c7e4ee3a
CB
8915 case FFEBLD_opARRTER:
8916 ffebld_arrter_set_pad (sexp, ffestorag_modulo (eqst));
8917 break;
5ff904cd 8918
c7e4ee3a
CB
8919 case FFEBLD_opACCTER:
8920 ffebld_accter_set_pad (sexp, ffestorag_modulo (eqst));
8921 break;
5ff904cd 8922
c7e4ee3a
CB
8923 default:
8924 assert ("bad op for eqv init (pad)" == NULL);
8925 break;
8926 }
5ff904cd 8927
c7e4ee3a
CB
8928 init = ffecom_expr (sexp);
8929 if (init == error_mark_node)
8930 init = NULL_TREE; /* Hopefully the back end complained! */
8931 }
8932 else
8933 init = error_mark_node;
8934 }
8935 else if (ffe_is_init_local_zero ())
8936 init = error_mark_node;
8937 else
8938 init = NULL_TREE;
5ff904cd 8939
c7e4ee3a
CB
8940 ffecom_member_namelisted_ = FALSE;
8941 ffestorag_drive (ffestorag_list_equivs (eqst),
8942 &ffecom_member_phase1_,
8943 eqst);
5ff904cd 8944
c7e4ee3a 8945 yes = suspend_momentary ();
5ff904cd 8946
c7e4ee3a
CB
8947 high = build_int_2 ((ffestorag_size (eqst)
8948 + ffestorag_modulo (eqst)) - 1, 0);
8949 TREE_TYPE (high) = ffecom_integer_type_node;
5ff904cd 8950
c7e4ee3a
CB
8951 eqtype = build_array_type (char_type_node,
8952 build_range_type (ffecom_integer_type_node,
8953 ffecom_integer_zero_node,
8954 high));
8955
8956 eqt = build_decl (VAR_DECL,
8957 ffecom_get_invented_identifier ("__g77_equiv_%s",
8958 ffesymbol_text
8959 (ffestorag_symbol
8960 (eqst)),
8961 -1),
8962 eqtype);
8963 DECL_EXTERNAL (eqt) = 0;
8964 if (is_init
8965 || ffecom_member_namelisted_
8966#ifdef FFECOM_sizeMAXSTACKITEM
8967 || (ffestorag_size (eqst) > FFECOM_sizeMAXSTACKITEM)
8968#endif
8969 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8970 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
8971 && (ffestorag_is_save (eqst) || ffe_is_saveall ())))
8972 TREE_STATIC (eqt) = 1;
8973 else
8974 TREE_STATIC (eqt) = 0;
8975 TREE_PUBLIC (eqt) = 0;
8976 DECL_CONTEXT (eqt) = current_function_decl;
8977 if (init)
8978 DECL_INITIAL (eqt) = error_mark_node;
8979 else
8980 DECL_INITIAL (eqt) = NULL_TREE;
5ff904cd 8981
c7e4ee3a 8982 eqt = start_decl (eqt, FALSE);
5ff904cd 8983
c7e4ee3a
CB
8984 /* Make sure that any type can live in EQUIVALENCE and be referenced
8985 without getting a bus error. We could pick the most restrictive
8986 alignment of all entities actually placed in the EQUIVALENCE, but
8987 this seems easy enough. */
5ff904cd 8988
c7e4ee3a 8989 DECL_ALIGN (eqt) = BIGGEST_ALIGNMENT;
5ff904cd 8990
c7e4ee3a
CB
8991 if ((!is_init && ffe_is_init_local_zero ())
8992 || (is_init && (ffestorag_init (eqst) == NULL)))
8993 init = ffecom_init_zero_ (eqt);
5ff904cd 8994
c7e4ee3a 8995 finish_decl (eqt, init, FALSE);
5ff904cd 8996
c7e4ee3a
CB
8997 if (is_init)
8998 ffestorag_set_init (eqst, ffebld_new_any ());
5ff904cd 8999
c7e4ee3a
CB
9000 {
9001 tree size_tree;
5ff904cd 9002
c7e4ee3a
CB
9003 size_tree = size_binop (CEIL_DIV_EXPR,
9004 DECL_SIZE (eqt),
9005 size_int (BITS_PER_UNIT));
9006 assert (TREE_INT_CST_HIGH (size_tree) == 0);
9007 assert (TREE_INT_CST_LOW (size_tree)
9008 == ffestorag_size (eqst) + ffestorag_modulo (eqst));
9009 }
5ff904cd 9010
c7e4ee3a 9011 ffestorag_set_hook (eqst, eqt);
5ff904cd 9012
c7e4ee3a
CB
9013#ifdef SOMEONE_GETS_DEBUG_SUPPORT_WORKING
9014 ffestorag_drive (ffestorag_list_equivs (eqst),
9015 &ffecom_member_phase2_,
9016 eqst);
9017#endif
9018
9019 resume_momentary (yes);
5ff904cd
JL
9020}
9021
9022#endif
c7e4ee3a 9023/* Implement NAMELIST in back end. See f2c/format.c for more info. */
5ff904cd
JL
9024
9025#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
9026static tree
9027ffecom_transform_namelist_ (ffesymbol s)
5ff904cd 9028{
c7e4ee3a
CB
9029 tree nmlt;
9030 tree nmltype = ffecom_type_namelist_ ();
9031 tree nmlinits;
9032 tree nameinit;
9033 tree varsinit;
9034 tree nvarsinit;
9035 tree field;
9036 tree high;
5ff904cd 9037 int yes;
c7e4ee3a
CB
9038 int i;
9039 static int mynumber = 0;
5ff904cd 9040
c7e4ee3a 9041 yes = suspend_momentary ();
5ff904cd 9042
c7e4ee3a
CB
9043 nmlt = build_decl (VAR_DECL,
9044 ffecom_get_invented_identifier ("__g77_namelist_%d",
9045 NULL, mynumber++),
9046 nmltype);
9047 TREE_STATIC (nmlt) = 1;
9048 DECL_INITIAL (nmlt) = error_mark_node;
5ff904cd 9049
c7e4ee3a 9050 nmlt = start_decl (nmlt, FALSE);
5ff904cd 9051
c7e4ee3a 9052 /* Process inits. */
5ff904cd 9053
c7e4ee3a 9054 i = strlen (ffesymbol_text (s));
5ff904cd 9055
c7e4ee3a
CB
9056 high = build_int_2 (i, 0);
9057 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
9058
9059 nameinit = ffecom_build_f2c_string_ (i + 1,
9060 ffesymbol_text (s));
9061 TREE_TYPE (nameinit)
9062 = build_type_variant
9063 (build_array_type
9064 (char_type_node,
9065 build_range_type (ffecom_f2c_ftnlen_type_node,
9066 ffecom_f2c_ftnlen_one_node,
9067 high)),
9068 1, 0);
9069 TREE_CONSTANT (nameinit) = 1;
9070 TREE_STATIC (nameinit) = 1;
9071 nameinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (nameinit)),
9072 nameinit);
9073
9074 varsinit = ffecom_vardesc_array_ (s);
9075 varsinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (varsinit)),
9076 varsinit);
9077 TREE_CONSTANT (varsinit) = 1;
9078 TREE_STATIC (varsinit) = 1;
9079
9080 {
9081 ffebld b;
9082
9083 for (i = 0, b = ffesymbol_namelist (s); b != NULL; b = ffebld_trail (b))
9084 ++i;
9085 }
9086 nvarsinit = build_int_2 (i, 0);
9087 TREE_TYPE (nvarsinit) = integer_type_node;
9088 TREE_CONSTANT (nvarsinit) = 1;
9089 TREE_STATIC (nvarsinit) = 1;
9090
9091 nmlinits = build_tree_list ((field = TYPE_FIELDS (nmltype)), nameinit);
9092 TREE_CHAIN (nmlinits) = build_tree_list ((field = TREE_CHAIN (field)),
9093 varsinit);
9094 TREE_CHAIN (TREE_CHAIN (nmlinits))
9095 = build_tree_list ((field = TREE_CHAIN (field)), nvarsinit);
9096
9097 nmlinits = build (CONSTRUCTOR, nmltype, NULL_TREE, nmlinits);
9098 TREE_CONSTANT (nmlinits) = 1;
9099 TREE_STATIC (nmlinits) = 1;
9100
9101 finish_decl (nmlt, nmlinits, FALSE);
9102
9103 nmlt = ffecom_1 (ADDR_EXPR, build_pointer_type (nmltype), nmlt);
9104
9105 resume_momentary (yes);
9106
9107 return nmlt;
9108}
9109
9110#endif
9111
9112/* A subroutine of ffecom_tree_canonize_ref_. The incoming tree is
9113 analyzed on the assumption it is calculating a pointer to be
9114 indirected through. It must return the proper decl and offset,
9115 taking into account different units of measurements for offsets. */
9116
9117#if FFECOM_targetCURRENT == FFECOM_targetGCC
9118static void
9119ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
9120 tree t)
9121{
9122 switch (TREE_CODE (t))
9123 {
9124 case NOP_EXPR:
9125 case CONVERT_EXPR:
9126 case NON_LVALUE_EXPR:
9127 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
5ff904cd
JL
9128 break;
9129
c7e4ee3a
CB
9130 case PLUS_EXPR:
9131 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
9132 if ((*decl == NULL_TREE)
9133 || (*decl == error_mark_node))
9134 break;
9135
9136 if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST)
9137 {
9138 /* An offset into COMMON. */
9139 *offset = size_binop (PLUS_EXPR,
9140 *offset,
9141 TREE_OPERAND (t, 1));
9142 /* Convert offset (presumably in bytes) into canonical units
9143 (presumably bits). */
9144 *offset = size_binop (MULT_EXPR,
9145 TYPE_SIZE (TREE_TYPE (TREE_TYPE (t))),
9146 *offset);
9147 break;
9148 }
9149 /* Not a COMMON reference, so an unrecognized pattern. */
9150 *decl = error_mark_node;
5ff904cd
JL
9151 break;
9152
c7e4ee3a
CB
9153 case PARM_DECL:
9154 *decl = t;
9155 *offset = bitsize_int (0L, 0L);
5ff904cd
JL
9156 break;
9157
c7e4ee3a
CB
9158 case ADDR_EXPR:
9159 if (TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL)
9160 {
9161 /* A reference to COMMON. */
9162 *decl = TREE_OPERAND (t, 0);
9163 *offset = bitsize_int (0L, 0L);
9164 break;
9165 }
9166 /* Fall through. */
5ff904cd 9167 default:
c7e4ee3a
CB
9168 /* Not a COMMON reference, so an unrecognized pattern. */
9169 *decl = error_mark_node;
5ff904cd
JL
9170 break;
9171 }
c7e4ee3a
CB
9172}
9173#endif
5ff904cd 9174
c7e4ee3a
CB
9175/* Given a tree that is possibly intended for use as an lvalue, return
9176 information representing a canonical view of that tree as a decl, an
9177 offset into that decl, and a size for the lvalue.
5ff904cd 9178
c7e4ee3a
CB
9179 If there's no applicable decl, NULL_TREE is returned for the decl,
9180 and the other fields are left undefined.
5ff904cd 9181
c7e4ee3a
CB
9182 If the tree doesn't fit the recognizable forms, an ERROR_MARK node
9183 is returned for the decl, and the other fields are left undefined.
5ff904cd 9184
c7e4ee3a
CB
9185 Otherwise, the decl returned currently is either a VAR_DECL or a
9186 PARM_DECL.
5ff904cd 9187
c7e4ee3a
CB
9188 The offset returned is always valid, but of course not necessarily
9189 a constant, and not necessarily converted into the appropriate
9190 type, leaving that up to the caller (so as to avoid that overhead
9191 if the decls being looked at are different anyway).
5ff904cd 9192
c7e4ee3a
CB
9193 If the size cannot be determined (e.g. an adjustable array),
9194 an ERROR_MARK node is returned for the size. Otherwise, the
9195 size returned is valid, not necessarily a constant, and not
9196 necessarily converted into the appropriate type as with the
9197 offset.
5ff904cd 9198
c7e4ee3a
CB
9199 Note that the offset and size expressions are expressed in the
9200 base storage units (usually bits) rather than in the units of
9201 the type of the decl, because two decls with different types
9202 might overlap but with apparently non-overlapping array offsets,
9203 whereas converting the array offsets to consistant offsets will
9204 reveal the overlap. */
5ff904cd
JL
9205
9206#if FFECOM_targetCURRENT == FFECOM_targetGCC
9207static void
c7e4ee3a
CB
9208ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
9209 tree *size, tree t)
5ff904cd 9210{
c7e4ee3a
CB
9211 /* The default path is to report a nonexistant decl. */
9212 *decl = NULL_TREE;
5ff904cd 9213
c7e4ee3a 9214 if (t == NULL_TREE)
5ff904cd
JL
9215 return;
9216
c7e4ee3a
CB
9217 switch (TREE_CODE (t))
9218 {
9219 case ERROR_MARK:
9220 case IDENTIFIER_NODE:
9221 case INTEGER_CST:
9222 case REAL_CST:
9223 case COMPLEX_CST:
9224 case STRING_CST:
9225 case CONST_DECL:
9226 case PLUS_EXPR:
9227 case MINUS_EXPR:
9228 case MULT_EXPR:
9229 case TRUNC_DIV_EXPR:
9230 case CEIL_DIV_EXPR:
9231 case FLOOR_DIV_EXPR:
9232 case ROUND_DIV_EXPR:
9233 case TRUNC_MOD_EXPR:
9234 case CEIL_MOD_EXPR:
9235 case FLOOR_MOD_EXPR:
9236 case ROUND_MOD_EXPR:
9237 case RDIV_EXPR:
9238 case EXACT_DIV_EXPR:
9239 case FIX_TRUNC_EXPR:
9240 case FIX_CEIL_EXPR:
9241 case FIX_FLOOR_EXPR:
9242 case FIX_ROUND_EXPR:
9243 case FLOAT_EXPR:
9244 case EXPON_EXPR:
9245 case NEGATE_EXPR:
9246 case MIN_EXPR:
9247 case MAX_EXPR:
9248 case ABS_EXPR:
9249 case FFS_EXPR:
9250 case LSHIFT_EXPR:
9251 case RSHIFT_EXPR:
9252 case LROTATE_EXPR:
9253 case RROTATE_EXPR:
9254 case BIT_IOR_EXPR:
9255 case BIT_XOR_EXPR:
9256 case BIT_AND_EXPR:
9257 case BIT_ANDTC_EXPR:
9258 case BIT_NOT_EXPR:
9259 case TRUTH_ANDIF_EXPR:
9260 case TRUTH_ORIF_EXPR:
9261 case TRUTH_AND_EXPR:
9262 case TRUTH_OR_EXPR:
9263 case TRUTH_XOR_EXPR:
9264 case TRUTH_NOT_EXPR:
9265 case LT_EXPR:
9266 case LE_EXPR:
9267 case GT_EXPR:
9268 case GE_EXPR:
9269 case EQ_EXPR:
9270 case NE_EXPR:
9271 case COMPLEX_EXPR:
9272 case CONJ_EXPR:
9273 case REALPART_EXPR:
9274 case IMAGPART_EXPR:
9275 case LABEL_EXPR:
9276 case COMPONENT_REF:
9277 case COMPOUND_EXPR:
9278 case ADDR_EXPR:
9279 return;
5ff904cd 9280
c7e4ee3a
CB
9281 case VAR_DECL:
9282 case PARM_DECL:
9283 *decl = t;
9284 *offset = bitsize_int (0L, 0L);
9285 *size = TYPE_SIZE (TREE_TYPE (t));
9286 return;
5ff904cd 9287
c7e4ee3a
CB
9288 case ARRAY_REF:
9289 {
9290 tree array = TREE_OPERAND (t, 0);
9291 tree element = TREE_OPERAND (t, 1);
9292 tree init_offset;
9293
9294 if ((array == NULL_TREE)
9295 || (element == NULL_TREE))
9296 {
9297 *decl = error_mark_node;
9298 return;
9299 }
9300
9301 ffecom_tree_canonize_ref_ (decl, &init_offset, size,
9302 array);
9303 if ((*decl == NULL_TREE)
9304 || (*decl == error_mark_node))
9305 return;
9306
9307 *offset = size_binop (MULT_EXPR,
9308 TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))),
9309 size_binop (MINUS_EXPR,
9310 element,
9311 TYPE_MIN_VALUE
9312 (TYPE_DOMAIN
9313 (TREE_TYPE (array)))));
9314
9315 *offset = size_binop (PLUS_EXPR,
9316 init_offset,
9317 *offset);
9318
9319 *size = TYPE_SIZE (TREE_TYPE (t));
9320 return;
9321 }
9322
9323 case INDIRECT_REF:
9324
9325 /* Most of this code is to handle references to COMMON. And so
9326 far that is useful only for calling library functions, since
9327 external (user) functions might reference common areas. But
9328 even calling an external function, it's worthwhile to decode
9329 COMMON references because if not storing into COMMON, we don't
9330 want COMMON-based arguments to gratuitously force use of a
9331 temporary. */
9332
9333 *size = TYPE_SIZE (TREE_TYPE (t));
5ff904cd 9334
c7e4ee3a
CB
9335 ffecom_tree_canonize_ptr_ (decl, offset,
9336 TREE_OPERAND (t, 0));
5ff904cd 9337
c7e4ee3a 9338 return;
5ff904cd 9339
c7e4ee3a
CB
9340 case CONVERT_EXPR:
9341 case NOP_EXPR:
9342 case MODIFY_EXPR:
9343 case NON_LVALUE_EXPR:
9344 case RESULT_DECL:
9345 case FIELD_DECL:
9346 case COND_EXPR: /* More cases than we can handle. */
9347 case SAVE_EXPR:
9348 case REFERENCE_EXPR:
9349 case PREDECREMENT_EXPR:
9350 case PREINCREMENT_EXPR:
9351 case POSTDECREMENT_EXPR:
9352 case POSTINCREMENT_EXPR:
9353 case CALL_EXPR:
9354 default:
9355 *decl = error_mark_node;
9356 return;
9357 }
9358}
9359#endif
5ff904cd 9360
c7e4ee3a 9361/* Do divide operation appropriate to type of operands. */
5ff904cd 9362
c7e4ee3a
CB
9363#if FFECOM_targetCURRENT == FFECOM_targetGCC
9364static tree
9365ffecom_tree_divide_ (tree tree_type, tree left, tree right,
9366 tree dest_tree, ffebld dest, bool *dest_used,
9367 tree hook)
9368{
9369 if ((left == error_mark_node)
9370 || (right == error_mark_node))
9371 return error_mark_node;
a6fa6420 9372
c7e4ee3a
CB
9373 switch (TREE_CODE (tree_type))
9374 {
9375 case INTEGER_TYPE:
9376 return ffecom_2 (TRUNC_DIV_EXPR, tree_type,
9377 left,
9378 right);
a6fa6420 9379
c7e4ee3a 9380 case COMPLEX_TYPE:
c64f913e
CB
9381 if (! optimize_size)
9382 return ffecom_2 (RDIV_EXPR, tree_type,
9383 left,
9384 right);
c7e4ee3a
CB
9385 {
9386 ffecomGfrt ix;
a6fa6420 9387
c7e4ee3a
CB
9388 if (TREE_TYPE (tree_type)
9389 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9390 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9391 else
9392 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
a6fa6420 9393
c7e4ee3a
CB
9394 left = ffecom_1 (ADDR_EXPR,
9395 build_pointer_type (TREE_TYPE (left)),
9396 left);
9397 left = build_tree_list (NULL_TREE, left);
9398 right = ffecom_1 (ADDR_EXPR,
9399 build_pointer_type (TREE_TYPE (right)),
9400 right);
9401 right = build_tree_list (NULL_TREE, right);
9402 TREE_CHAIN (left) = right;
a6fa6420 9403
c7e4ee3a
CB
9404 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9405 ffecom_gfrt_kindtype (ix),
9406 ffe_is_f2c_library (),
9407 tree_type,
9408 left,
9409 dest_tree, dest, dest_used,
9410 NULL_TREE, TRUE, hook);
9411 }
9412 break;
5ff904cd 9413
c7e4ee3a
CB
9414 case RECORD_TYPE:
9415 {
9416 ffecomGfrt ix;
5ff904cd 9417
c7e4ee3a
CB
9418 if (TREE_TYPE (TYPE_FIELDS (tree_type))
9419 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9420 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9421 else
9422 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
5ff904cd 9423
c7e4ee3a
CB
9424 left = ffecom_1 (ADDR_EXPR,
9425 build_pointer_type (TREE_TYPE (left)),
9426 left);
9427 left = build_tree_list (NULL_TREE, left);
9428 right = ffecom_1 (ADDR_EXPR,
9429 build_pointer_type (TREE_TYPE (right)),
9430 right);
9431 right = build_tree_list (NULL_TREE, right);
9432 TREE_CHAIN (left) = right;
a6fa6420 9433
c7e4ee3a
CB
9434 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9435 ffecom_gfrt_kindtype (ix),
9436 ffe_is_f2c_library (),
9437 tree_type,
9438 left,
9439 dest_tree, dest, dest_used,
9440 NULL_TREE, TRUE, hook);
9441 }
9442 break;
5ff904cd 9443
c7e4ee3a
CB
9444 default:
9445 return ffecom_2 (RDIV_EXPR, tree_type,
9446 left,
9447 right);
5ff904cd 9448 }
c7e4ee3a 9449}
5ff904cd 9450
c7e4ee3a
CB
9451#endif
9452/* Build type info for non-dummy variable. */
5ff904cd 9453
c7e4ee3a
CB
9454#if FFECOM_targetCURRENT == FFECOM_targetGCC
9455static tree
9456ffecom_type_localvar_ (ffesymbol s, ffeinfoBasictype bt,
9457 ffeinfoKindtype kt)
9458{
9459 tree type;
9460 ffebld dl;
9461 ffebld dim;
9462 tree lowt;
9463 tree hight;
5ff904cd 9464
c7e4ee3a
CB
9465 type = ffecom_tree_type[bt][kt];
9466 if (bt == FFEINFO_basictypeCHARACTER)
9467 {
9468 hight = build_int_2 (ffesymbol_size (s), 0);
9469 TREE_TYPE (hight) = ffecom_f2c_ftnlen_type_node;
5ff904cd 9470
c7e4ee3a
CB
9471 type
9472 = build_array_type
9473 (type,
9474 build_range_type (ffecom_f2c_ftnlen_type_node,
9475 ffecom_f2c_ftnlen_one_node,
9476 hight));
9477 type = ffecom_check_size_overflow_ (s, type, FALSE);
9478 }
5ff904cd 9479
c7e4ee3a
CB
9480 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
9481 {
9482 if (type == error_mark_node)
9483 break;
5ff904cd 9484
c7e4ee3a
CB
9485 dim = ffebld_head (dl);
9486 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
5ff904cd 9487
c7e4ee3a
CB
9488 if (ffebld_left (dim) == NULL)
9489 lowt = integer_one_node;
9490 else
9491 lowt = ffecom_expr (ffebld_left (dim));
5ff904cd 9492
c7e4ee3a
CB
9493 if (TREE_CODE (lowt) != INTEGER_CST)
9494 lowt = variable_size (lowt);
5ff904cd 9495
c7e4ee3a
CB
9496 assert (ffebld_right (dim) != NULL);
9497 hight = ffecom_expr (ffebld_right (dim));
5ff904cd 9498
c7e4ee3a
CB
9499 if (TREE_CODE (hight) != INTEGER_CST)
9500 hight = variable_size (hight);
5ff904cd 9501
c7e4ee3a
CB
9502 type = build_array_type (type,
9503 build_range_type (ffecom_integer_type_node,
9504 lowt, hight));
9505 type = ffecom_check_size_overflow_ (s, type, FALSE);
9506 }
5ff904cd 9507
c7e4ee3a 9508 return type;
5ff904cd
JL
9509}
9510
9511#endif
c7e4ee3a 9512/* Build Namelist type. */
5ff904cd 9513
c7e4ee3a
CB
9514#if FFECOM_targetCURRENT == FFECOM_targetGCC
9515static tree
9516ffecom_type_namelist_ ()
9517{
9518 static tree type = NULL_TREE;
5ff904cd 9519
c7e4ee3a
CB
9520 if (type == NULL_TREE)
9521 {
9522 static tree namefield, varsfield, nvarsfield;
9523 tree vardesctype;
5ff904cd 9524
c7e4ee3a 9525 vardesctype = ffecom_type_vardesc_ ();
5ff904cd 9526
c7e4ee3a
CB
9527 push_obstacks_nochange ();
9528 end_temporary_allocation ();
a6fa6420 9529
c7e4ee3a 9530 type = make_node (RECORD_TYPE);
a6fa6420 9531
c7e4ee3a 9532 vardesctype = build_pointer_type (build_pointer_type (vardesctype));
a6fa6420 9533
c7e4ee3a
CB
9534 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9535 string_type_node);
9536 varsfield = ffecom_decl_field (type, namefield, "vars", vardesctype);
9537 nvarsfield = ffecom_decl_field (type, varsfield, "nvars",
9538 integer_type_node);
a6fa6420 9539
c7e4ee3a
CB
9540 TYPE_FIELDS (type) = namefield;
9541 layout_type (type);
a6fa6420 9542
c7e4ee3a
CB
9543 resume_temporary_allocation ();
9544 pop_obstacks ();
5ff904cd 9545 }
5ff904cd 9546
c7e4ee3a
CB
9547 return type;
9548}
5ff904cd 9549
c7e4ee3a 9550#endif
5ff904cd 9551
c7e4ee3a
CB
9552/* Make a copy of a type, assuming caller has switched to the permanent
9553 obstacks and that the type is for an aggregate (array) initializer. */
5ff904cd 9554
c7e4ee3a
CB
9555#if FFECOM_targetCURRENT == FFECOM_targetGCC && 0 /* Not used now. */
9556static tree
9557ffecom_type_permanent_copy_ (tree t)
9558{
9559 tree domain;
9560 tree max;
5ff904cd 9561
c7e4ee3a 9562 assert (TREE_TYPE (t) != NULL_TREE);
5ff904cd 9563
c7e4ee3a 9564 domain = TYPE_DOMAIN (t);
5ff904cd 9565
c7e4ee3a
CB
9566 assert (TREE_CODE (t) == ARRAY_TYPE);
9567 assert (TREE_PERMANENT (TREE_TYPE (t)));
9568 assert (TREE_PERMANENT (TREE_TYPE (domain)));
9569 assert (TREE_PERMANENT (TYPE_MIN_VALUE (domain)));
5ff904cd 9570
c7e4ee3a
CB
9571 max = TYPE_MAX_VALUE (domain);
9572 if (!TREE_PERMANENT (max))
9573 {
9574 assert (TREE_CODE (max) == INTEGER_CST);
5ff904cd 9575
c7e4ee3a
CB
9576 max = build_int_2 (TREE_INT_CST_LOW (max), TREE_INT_CST_HIGH (max));
9577 TREE_TYPE (max) = TREE_TYPE (TYPE_MIN_VALUE (domain));
9578 }
5ff904cd 9579
c7e4ee3a
CB
9580 return build_array_type (TREE_TYPE (t),
9581 build_range_type (TREE_TYPE (domain),
9582 TYPE_MIN_VALUE (domain),
9583 max));
9584}
9585#endif
5ff904cd 9586
c7e4ee3a 9587/* Build Vardesc type. */
5ff904cd 9588
c7e4ee3a
CB
9589#if FFECOM_targetCURRENT == FFECOM_targetGCC
9590static tree
9591ffecom_type_vardesc_ ()
9592{
9593 static tree type = NULL_TREE;
9594 static tree namefield, addrfield, dimsfield, typefield;
5ff904cd 9595
c7e4ee3a
CB
9596 if (type == NULL_TREE)
9597 {
9598 push_obstacks_nochange ();
9599 end_temporary_allocation ();
5ff904cd 9600
c7e4ee3a 9601 type = make_node (RECORD_TYPE);
5ff904cd 9602
c7e4ee3a
CB
9603 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9604 string_type_node);
9605 addrfield = ffecom_decl_field (type, namefield, "addr",
9606 string_type_node);
9607 dimsfield = ffecom_decl_field (type, addrfield, "dims",
9608 ffecom_f2c_ptr_to_ftnlen_type_node);
9609 typefield = ffecom_decl_field (type, dimsfield, "type",
9610 integer_type_node);
5ff904cd 9611
c7e4ee3a
CB
9612 TYPE_FIELDS (type) = namefield;
9613 layout_type (type);
9614
9615 resume_temporary_allocation ();
9616 pop_obstacks ();
9617 }
9618
9619 return type;
5ff904cd
JL
9620}
9621
9622#endif
5ff904cd
JL
9623
9624#if FFECOM_targetCURRENT == FFECOM_targetGCC
9625static tree
c7e4ee3a 9626ffecom_vardesc_ (ffebld expr)
5ff904cd 9627{
c7e4ee3a 9628 ffesymbol s;
5ff904cd 9629
c7e4ee3a
CB
9630 assert (ffebld_op (expr) == FFEBLD_opSYMTER);
9631 s = ffebld_symter (expr);
5ff904cd 9632
c7e4ee3a
CB
9633 if (ffesymbol_hook (s).vardesc_tree == NULL_TREE)
9634 {
9635 int i;
9636 tree vardesctype = ffecom_type_vardesc_ ();
9637 tree var;
9638 tree nameinit;
9639 tree dimsinit;
9640 tree addrinit;
9641 tree typeinit;
9642 tree field;
9643 tree varinits;
9644 int yes;
9645 static int mynumber = 0;
5ff904cd 9646
c7e4ee3a 9647 yes = suspend_momentary ();
5ff904cd 9648
c7e4ee3a
CB
9649 var = build_decl (VAR_DECL,
9650 ffecom_get_invented_identifier ("__g77_vardesc_%d",
9651 NULL, mynumber++),
9652 vardesctype);
9653 TREE_STATIC (var) = 1;
9654 DECL_INITIAL (var) = error_mark_node;
5ff904cd 9655
c7e4ee3a 9656 var = start_decl (var, FALSE);
5ff904cd 9657
c7e4ee3a 9658 /* Process inits. */
5ff904cd 9659
c7e4ee3a
CB
9660 nameinit = ffecom_build_f2c_string_ ((i = strlen (ffesymbol_text (s)))
9661 + 1,
9662 ffesymbol_text (s));
9663 TREE_TYPE (nameinit)
9664 = build_type_variant
9665 (build_array_type
9666 (char_type_node,
9667 build_range_type (integer_type_node,
9668 integer_one_node,
9669 build_int_2 (i, 0))),
9670 1, 0);
9671 TREE_CONSTANT (nameinit) = 1;
9672 TREE_STATIC (nameinit) = 1;
9673 nameinit = ffecom_1 (ADDR_EXPR,
9674 build_pointer_type (TREE_TYPE (nameinit)),
9675 nameinit);
5ff904cd 9676
c7e4ee3a 9677 addrinit = ffecom_arg_ptr_to_expr (expr, &typeinit);
5ff904cd 9678
c7e4ee3a 9679 dimsinit = ffecom_vardesc_dims_ (s);
5ff904cd 9680
c7e4ee3a
CB
9681 if (typeinit == NULL_TREE)
9682 {
9683 ffeinfoBasictype bt = ffesymbol_basictype (s);
9684 ffeinfoKindtype kt = ffesymbol_kindtype (s);
9685 int tc = ffecom_f2c_typecode (bt, kt);
5ff904cd 9686
c7e4ee3a
CB
9687 assert (tc != -1);
9688 typeinit = build_int_2 (tc, (tc < 0) ? -1 : 0);
9689 }
9690 else
9691 typeinit = ffecom_1 (NEGATE_EXPR, TREE_TYPE (typeinit), typeinit);
5ff904cd 9692
c7e4ee3a
CB
9693 varinits = build_tree_list ((field = TYPE_FIELDS (vardesctype)),
9694 nameinit);
9695 TREE_CHAIN (varinits) = build_tree_list ((field = TREE_CHAIN (field)),
9696 addrinit);
9697 TREE_CHAIN (TREE_CHAIN (varinits))
9698 = build_tree_list ((field = TREE_CHAIN (field)), dimsinit);
9699 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (varinits)))
9700 = build_tree_list ((field = TREE_CHAIN (field)), typeinit);
5ff904cd 9701
c7e4ee3a
CB
9702 varinits = build (CONSTRUCTOR, vardesctype, NULL_TREE, varinits);
9703 TREE_CONSTANT (varinits) = 1;
9704 TREE_STATIC (varinits) = 1;
5ff904cd 9705
c7e4ee3a 9706 finish_decl (var, varinits, FALSE);
5ff904cd 9707
c7e4ee3a 9708 var = ffecom_1 (ADDR_EXPR, build_pointer_type (vardesctype), var);
5ff904cd 9709
c7e4ee3a 9710 resume_momentary (yes);
5ff904cd 9711
c7e4ee3a
CB
9712 ffesymbol_hook (s).vardesc_tree = var;
9713 }
5ff904cd 9714
c7e4ee3a
CB
9715 return ffesymbol_hook (s).vardesc_tree;
9716}
5ff904cd 9717
c7e4ee3a 9718#endif
5ff904cd 9719#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
9720static tree
9721ffecom_vardesc_array_ (ffesymbol s)
5ff904cd 9722{
c7e4ee3a
CB
9723 ffebld b;
9724 tree list;
9725 tree item = NULL_TREE;
9726 tree var;
9727 int i;
9728 int yes;
9729 static int mynumber = 0;
5ff904cd 9730
c7e4ee3a
CB
9731 for (i = 0, list = NULL_TREE, b = ffesymbol_namelist (s);
9732 b != NULL;
9733 b = ffebld_trail (b), ++i)
9734 {
9735 tree t;
5ff904cd 9736
c7e4ee3a 9737 t = ffecom_vardesc_ (ffebld_head (b));
5ff904cd 9738
c7e4ee3a
CB
9739 if (list == NULL_TREE)
9740 list = item = build_tree_list (NULL_TREE, t);
9741 else
5ff904cd 9742 {
c7e4ee3a
CB
9743 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9744 item = TREE_CHAIN (item);
5ff904cd 9745 }
5ff904cd 9746 }
5ff904cd 9747
c7e4ee3a 9748 yes = suspend_momentary ();
5ff904cd 9749
c7e4ee3a
CB
9750 item = build_array_type (build_pointer_type (ffecom_type_vardesc_ ()),
9751 build_range_type (integer_type_node,
9752 integer_one_node,
9753 build_int_2 (i, 0)));
9754 list = build (CONSTRUCTOR, item, NULL_TREE, list);
9755 TREE_CONSTANT (list) = 1;
9756 TREE_STATIC (list) = 1;
5ff904cd 9757
c7e4ee3a
CB
9758 var = ffecom_get_invented_identifier ("__g77_vardesc_array_%d", NULL,
9759 mynumber++);
9760 var = build_decl (VAR_DECL, var, item);
9761 TREE_STATIC (var) = 1;
9762 DECL_INITIAL (var) = error_mark_node;
9763 var = start_decl (var, FALSE);
9764 finish_decl (var, list, FALSE);
5ff904cd 9765
c7e4ee3a 9766 resume_momentary (yes);
5ff904cd 9767
c7e4ee3a
CB
9768 return var;
9769}
5ff904cd 9770
c7e4ee3a
CB
9771#endif
9772#if FFECOM_targetCURRENT == FFECOM_targetGCC
9773static tree
9774ffecom_vardesc_dims_ (ffesymbol s)
9775{
9776 if (ffesymbol_dims (s) == NULL)
9777 return convert (ffecom_f2c_ptr_to_ftnlen_type_node,
9778 integer_zero_node);
5ff904cd 9779
c7e4ee3a
CB
9780 {
9781 ffebld b;
9782 ffebld e;
9783 tree list;
9784 tree backlist;
9785 tree item = NULL_TREE;
9786 tree var;
9787 int yes;
9788 tree numdim;
9789 tree numelem;
9790 tree baseoff = NULL_TREE;
9791 static int mynumber = 0;
9792
9793 numdim = build_int_2 ((int) ffesymbol_rank (s), 0);
9794 TREE_TYPE (numdim) = ffecom_f2c_ftnlen_type_node;
9795
9796 numelem = ffecom_expr (ffesymbol_arraysize (s));
9797 TREE_TYPE (numelem) = ffecom_f2c_ftnlen_type_node;
9798
9799 list = NULL_TREE;
9800 backlist = NULL_TREE;
9801 for (b = ffesymbol_dims (s), e = ffesymbol_extents (s);
9802 b != NULL;
9803 b = ffebld_trail (b), e = ffebld_trail (e))
5ff904cd 9804 {
c7e4ee3a
CB
9805 tree t;
9806 tree low;
9807 tree back;
5ff904cd 9808
c7e4ee3a
CB
9809 if (ffebld_trail (b) == NULL)
9810 t = NULL_TREE;
9811 else
5ff904cd 9812 {
c7e4ee3a
CB
9813 t = convert (ffecom_f2c_ftnlen_type_node,
9814 ffecom_expr (ffebld_head (e)));
5ff904cd 9815
c7e4ee3a
CB
9816 if (list == NULL_TREE)
9817 list = item = build_tree_list (NULL_TREE, t);
9818 else
9819 {
9820 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9821 item = TREE_CHAIN (item);
9822 }
9823 }
5ff904cd 9824
c7e4ee3a
CB
9825 if (ffebld_left (ffebld_head (b)) == NULL)
9826 low = ffecom_integer_one_node;
9827 else
9828 low = ffecom_expr (ffebld_left (ffebld_head (b)));
9829 low = convert (ffecom_f2c_ftnlen_type_node, low);
5ff904cd 9830
c7e4ee3a
CB
9831 back = build_tree_list (low, t);
9832 TREE_CHAIN (back) = backlist;
9833 backlist = back;
9834 }
5ff904cd 9835
c7e4ee3a
CB
9836 for (item = backlist; item != NULL_TREE; item = TREE_CHAIN (item))
9837 {
9838 if (TREE_VALUE (item) == NULL_TREE)
9839 baseoff = TREE_PURPOSE (item);
9840 else
9841 baseoff = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
9842 TREE_PURPOSE (item),
9843 ffecom_2 (MULT_EXPR,
9844 ffecom_f2c_ftnlen_type_node,
9845 TREE_VALUE (item),
9846 baseoff));
5ff904cd
JL
9847 }
9848
c7e4ee3a 9849 /* backlist now dead, along with all TREE_PURPOSEs on it. */
5ff904cd 9850
c7e4ee3a
CB
9851 baseoff = build_tree_list (NULL_TREE, baseoff);
9852 TREE_CHAIN (baseoff) = list;
5ff904cd 9853
c7e4ee3a
CB
9854 numelem = build_tree_list (NULL_TREE, numelem);
9855 TREE_CHAIN (numelem) = baseoff;
5ff904cd 9856
c7e4ee3a
CB
9857 numdim = build_tree_list (NULL_TREE, numdim);
9858 TREE_CHAIN (numdim) = numelem;
5ff904cd 9859
c7e4ee3a 9860 yes = suspend_momentary ();
5ff904cd 9861
c7e4ee3a
CB
9862 item = build_array_type (ffecom_f2c_ftnlen_type_node,
9863 build_range_type (integer_type_node,
9864 integer_zero_node,
9865 build_int_2
9866 ((int) ffesymbol_rank (s)
9867 + 2, 0)));
9868 list = build (CONSTRUCTOR, item, NULL_TREE, numdim);
9869 TREE_CONSTANT (list) = 1;
9870 TREE_STATIC (list) = 1;
9871
9872 var = ffecom_get_invented_identifier ("__g77_dims_%d", NULL,
9873 mynumber++);
9874 var = build_decl (VAR_DECL, var, item);
9875 TREE_STATIC (var) = 1;
9876 DECL_INITIAL (var) = error_mark_node;
9877 var = start_decl (var, FALSE);
9878 finish_decl (var, list, FALSE);
9879
9880 var = ffecom_1 (ADDR_EXPR, build_pointer_type (item), var);
9881
9882 resume_momentary (yes);
9883
9884 return var;
9885 }
5ff904cd 9886}
c7e4ee3a 9887
5ff904cd 9888#endif
c7e4ee3a
CB
9889/* Essentially does a "fold (build1 (code, type, node))" while checking
9890 for certain housekeeping things.
5ff904cd 9891
c7e4ee3a
CB
9892 NOTE: for building an ADDR_EXPR around a FUNCTION_DECL, use
9893 ffecom_1_fn instead. */
5ff904cd
JL
9894
9895#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
9896tree
9897ffecom_1 (enum tree_code code, tree type, tree node)
5ff904cd 9898{
c7e4ee3a
CB
9899 tree item;
9900
9901 if ((node == error_mark_node)
9902 || (type == error_mark_node))
5ff904cd
JL
9903 return error_mark_node;
9904
c7e4ee3a 9905 if (code == ADDR_EXPR)
5ff904cd 9906 {
c7e4ee3a
CB
9907 if (!mark_addressable (node))
9908 assert ("can't mark_addressable this node!" == NULL);
9909 }
5ff904cd 9910
c7e4ee3a
CB
9911 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
9912 {
9913 tree realtype;
5ff904cd 9914
c7e4ee3a
CB
9915 case REALPART_EXPR:
9916 item = build (COMPONENT_REF, type, node, TYPE_FIELDS (TREE_TYPE (node)));
5ff904cd
JL
9917 break;
9918
c7e4ee3a
CB
9919 case IMAGPART_EXPR:
9920 item = build (COMPONENT_REF, type, node, TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (node))));
9921 break;
5ff904cd 9922
5ff904cd 9923
c7e4ee3a
CB
9924 case NEGATE_EXPR:
9925 if (TREE_CODE (type) != RECORD_TYPE)
9926 {
9927 item = build1 (code, type, node);
9928 break;
9929 }
9930 node = ffecom_stabilize_aggregate_ (node);
9931 realtype = TREE_TYPE (TYPE_FIELDS (type));
9932 item =
9933 ffecom_2 (COMPLEX_EXPR, type,
9934 ffecom_1 (NEGATE_EXPR, realtype,
9935 ffecom_1 (REALPART_EXPR, realtype,
9936 node)),
9937 ffecom_1 (NEGATE_EXPR, realtype,
9938 ffecom_1 (IMAGPART_EXPR, realtype,
9939 node)));
5ff904cd
JL
9940 break;
9941
9942 default:
c7e4ee3a
CB
9943 item = build1 (code, type, node);
9944 break;
5ff904cd 9945 }
5ff904cd 9946
c7e4ee3a
CB
9947 if (TREE_SIDE_EFFECTS (node))
9948 TREE_SIDE_EFFECTS (item) = 1;
9949 if ((code == ADDR_EXPR) && staticp (node))
9950 TREE_CONSTANT (item) = 1;
9951 return fold (item);
9952}
5ff904cd 9953#endif
5ff904cd 9954
c7e4ee3a
CB
9955/* Like ffecom_1 (ADDR_EXPR, TREE_TYPE (node), node), except
9956 handles TREE_CODE (node) == FUNCTION_DECL. In particular,
9957 does not set TREE_ADDRESSABLE (because calling an inline
9958 function does not mean the function needs to be separately
9959 compiled). */
5ff904cd
JL
9960
9961#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
9962tree
9963ffecom_1_fn (tree node)
5ff904cd 9964{
c7e4ee3a 9965 tree item;
5ff904cd 9966 tree type;
5ff904cd 9967
c7e4ee3a
CB
9968 if (node == error_mark_node)
9969 return error_mark_node;
5ff904cd 9970
c7e4ee3a
CB
9971 type = build_type_variant (TREE_TYPE (node),
9972 TREE_READONLY (node),
9973 TREE_THIS_VOLATILE (node));
9974 item = build1 (ADDR_EXPR,
9975 build_pointer_type (type), node);
9976 if (TREE_SIDE_EFFECTS (node))
9977 TREE_SIDE_EFFECTS (item) = 1;
9978 if (staticp (node))
9979 TREE_CONSTANT (item) = 1;
9980 return fold (item);
5ff904cd 9981}
5ff904cd 9982#endif
c7e4ee3a
CB
9983
9984/* Essentially does a "fold (build (code, type, node1, node2))" while
9985 checking for certain housekeeping things. */
5ff904cd
JL
9986
9987#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
9988tree
9989ffecom_2 (enum tree_code code, tree type, tree node1,
9990 tree node2)
5ff904cd 9991{
c7e4ee3a 9992 tree item;
5ff904cd 9993
c7e4ee3a
CB
9994 if ((node1 == error_mark_node)
9995 || (node2 == error_mark_node)
9996 || (type == error_mark_node))
9997 return error_mark_node;
9998
9999 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
5ff904cd 10000 {
c7e4ee3a 10001 tree a, b, c, d, realtype;
5ff904cd 10002
c7e4ee3a
CB
10003 case CONJ_EXPR:
10004 assert ("no CONJ_EXPR support yet" == NULL);
10005 return error_mark_node;
5ff904cd 10006
c7e4ee3a
CB
10007 case COMPLEX_EXPR:
10008 item = build_tree_list (TYPE_FIELDS (type), node1);
10009 TREE_CHAIN (item) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), node2);
10010 item = build (CONSTRUCTOR, type, NULL_TREE, item);
10011 break;
5ff904cd 10012
c7e4ee3a
CB
10013 case PLUS_EXPR:
10014 if (TREE_CODE (type) != RECORD_TYPE)
10015 {
10016 item = build (code, type, node1, node2);
10017 break;
10018 }
10019 node1 = ffecom_stabilize_aggregate_ (node1);
10020 node2 = ffecom_stabilize_aggregate_ (node2);
10021 realtype = TREE_TYPE (TYPE_FIELDS (type));
10022 item =
10023 ffecom_2 (COMPLEX_EXPR, type,
10024 ffecom_2 (PLUS_EXPR, realtype,
10025 ffecom_1 (REALPART_EXPR, realtype,
10026 node1),
10027 ffecom_1 (REALPART_EXPR, realtype,
10028 node2)),
10029 ffecom_2 (PLUS_EXPR, realtype,
10030 ffecom_1 (IMAGPART_EXPR, realtype,
10031 node1),
10032 ffecom_1 (IMAGPART_EXPR, realtype,
10033 node2)));
10034 break;
5ff904cd 10035
c7e4ee3a
CB
10036 case MINUS_EXPR:
10037 if (TREE_CODE (type) != RECORD_TYPE)
10038 {
10039 item = build (code, type, node1, node2);
10040 break;
10041 }
10042 node1 = ffecom_stabilize_aggregate_ (node1);
10043 node2 = ffecom_stabilize_aggregate_ (node2);
10044 realtype = TREE_TYPE (TYPE_FIELDS (type));
10045 item =
10046 ffecom_2 (COMPLEX_EXPR, type,
10047 ffecom_2 (MINUS_EXPR, realtype,
10048 ffecom_1 (REALPART_EXPR, realtype,
10049 node1),
10050 ffecom_1 (REALPART_EXPR, realtype,
10051 node2)),
10052 ffecom_2 (MINUS_EXPR, realtype,
10053 ffecom_1 (IMAGPART_EXPR, realtype,
10054 node1),
10055 ffecom_1 (IMAGPART_EXPR, realtype,
10056 node2)));
10057 break;
5ff904cd 10058
c7e4ee3a
CB
10059 case MULT_EXPR:
10060 if (TREE_CODE (type) != RECORD_TYPE)
10061 {
10062 item = build (code, type, node1, node2);
10063 break;
10064 }
10065 node1 = ffecom_stabilize_aggregate_ (node1);
10066 node2 = ffecom_stabilize_aggregate_ (node2);
10067 realtype = TREE_TYPE (TYPE_FIELDS (type));
10068 a = save_expr (ffecom_1 (REALPART_EXPR, realtype,
10069 node1));
10070 b = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
10071 node1));
10072 c = save_expr (ffecom_1 (REALPART_EXPR, realtype,
10073 node2));
10074 d = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
10075 node2));
10076 item =
10077 ffecom_2 (COMPLEX_EXPR, type,
10078 ffecom_2 (MINUS_EXPR, realtype,
10079 ffecom_2 (MULT_EXPR, realtype,
10080 a,
10081 c),
10082 ffecom_2 (MULT_EXPR, realtype,
10083 b,
10084 d)),
10085 ffecom_2 (PLUS_EXPR, realtype,
10086 ffecom_2 (MULT_EXPR, realtype,
10087 a,
10088 d),
10089 ffecom_2 (MULT_EXPR, realtype,
10090 c,
10091 b)));
10092 break;
5ff904cd 10093
c7e4ee3a
CB
10094 case EQ_EXPR:
10095 if ((TREE_CODE (node1) != RECORD_TYPE)
10096 && (TREE_CODE (node2) != RECORD_TYPE))
10097 {
10098 item = build (code, type, node1, node2);
10099 break;
10100 }
10101 assert (TREE_CODE (node1) == RECORD_TYPE);
10102 assert (TREE_CODE (node2) == RECORD_TYPE);
10103 node1 = ffecom_stabilize_aggregate_ (node1);
10104 node2 = ffecom_stabilize_aggregate_ (node2);
10105 realtype = TREE_TYPE (TYPE_FIELDS (type));
10106 item =
10107 ffecom_2 (TRUTH_ANDIF_EXPR, type,
10108 ffecom_2 (code, type,
10109 ffecom_1 (REALPART_EXPR, realtype,
10110 node1),
10111 ffecom_1 (REALPART_EXPR, realtype,
10112 node2)),
10113 ffecom_2 (code, type,
10114 ffecom_1 (IMAGPART_EXPR, realtype,
10115 node1),
10116 ffecom_1 (IMAGPART_EXPR, realtype,
10117 node2)));
10118 break;
10119
10120 case NE_EXPR:
10121 if ((TREE_CODE (node1) != RECORD_TYPE)
10122 && (TREE_CODE (node2) != RECORD_TYPE))
10123 {
10124 item = build (code, type, node1, node2);
10125 break;
10126 }
10127 assert (TREE_CODE (node1) == RECORD_TYPE);
10128 assert (TREE_CODE (node2) == RECORD_TYPE);
10129 node1 = ffecom_stabilize_aggregate_ (node1);
10130 node2 = ffecom_stabilize_aggregate_ (node2);
10131 realtype = TREE_TYPE (TYPE_FIELDS (type));
10132 item =
10133 ffecom_2 (TRUTH_ORIF_EXPR, type,
10134 ffecom_2 (code, type,
10135 ffecom_1 (REALPART_EXPR, realtype,
10136 node1),
10137 ffecom_1 (REALPART_EXPR, realtype,
10138 node2)),
10139 ffecom_2 (code, type,
10140 ffecom_1 (IMAGPART_EXPR, realtype,
10141 node1),
10142 ffecom_1 (IMAGPART_EXPR, realtype,
10143 node2)));
10144 break;
5ff904cd 10145
c7e4ee3a
CB
10146 default:
10147 item = build (code, type, node1, node2);
10148 break;
5ff904cd
JL
10149 }
10150
c7e4ee3a
CB
10151 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2))
10152 TREE_SIDE_EFFECTS (item) = 1;
10153 return fold (item);
5ff904cd
JL
10154}
10155
10156#endif
c7e4ee3a 10157/* ffecom_2pass_advise_entrypoint -- Advise that there's this entrypoint
5ff904cd 10158
c7e4ee3a
CB
10159 ffesymbol s; // the ENTRY point itself
10160 if (ffecom_2pass_advise_entrypoint(s))
10161 // the ENTRY point has been accepted
5ff904cd 10162
c7e4ee3a
CB
10163 Does whatever compiler needs to do when it learns about the entrypoint,
10164 like determine the return type of the master function, count the
10165 number of entrypoints, etc. Returns FALSE if the return type is
10166 not compatible with the return type(s) of other entrypoint(s).
5ff904cd 10167
c7e4ee3a
CB
10168 NOTE: for every call to this fn that returns TRUE, _do_entrypoint must
10169 later (after _finish_progunit) be called with the same entrypoint(s)
10170 as passed to this fn for which TRUE was returned.
5ff904cd 10171
c7e4ee3a
CB
10172 03-Jan-92 JCB 2.0
10173 Return FALSE if the return type conflicts with previous entrypoints. */
5ff904cd
JL
10174
10175#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
10176bool
10177ffecom_2pass_advise_entrypoint (ffesymbol entry)
5ff904cd 10178{
c7e4ee3a
CB
10179 ffebld list; /* opITEM. */
10180 ffebld mlist; /* opITEM. */
10181 ffebld plist; /* opITEM. */
10182 ffebld arg; /* ffebld_head(opITEM). */
10183 ffebld item; /* opITEM. */
10184 ffesymbol s; /* ffebld_symter(arg). */
10185 ffeinfoBasictype bt = ffesymbol_basictype (entry);
10186 ffeinfoKindtype kt = ffesymbol_kindtype (entry);
10187 ffetargetCharacterSize size = ffesymbol_size (entry);
10188 bool ok;
5ff904cd 10189
c7e4ee3a
CB
10190 if (ffecom_num_entrypoints_ == 0)
10191 { /* First entrypoint, make list of main
10192 arglist's dummies. */
10193 assert (ffecom_primary_entry_ != NULL);
5ff904cd 10194
c7e4ee3a
CB
10195 ffecom_master_bt_ = ffesymbol_basictype (ffecom_primary_entry_);
10196 ffecom_master_kt_ = ffesymbol_kindtype (ffecom_primary_entry_);
10197 ffecom_master_size_ = ffesymbol_size (ffecom_primary_entry_);
5ff904cd 10198
c7e4ee3a
CB
10199 for (plist = NULL, list = ffesymbol_dummyargs (ffecom_primary_entry_);
10200 list != NULL;
10201 list = ffebld_trail (list))
10202 {
10203 arg = ffebld_head (list);
10204 if (ffebld_op (arg) != FFEBLD_opSYMTER)
10205 continue; /* Alternate return or some such thing. */
10206 item = ffebld_new_item (arg, NULL);
10207 if (plist == NULL)
10208 ffecom_master_arglist_ = item;
10209 else
10210 ffebld_set_trail (plist, item);
10211 plist = item;
10212 }
5ff904cd
JL
10213 }
10214
c7e4ee3a
CB
10215 /* If necessary, scan entry arglist for alternate returns. Do this scan
10216 apparently redundantly (it's done below to UNIONize the arglists) so
10217 that we don't complain about RETURN 1 if an offending ENTRY is the only
10218 one with an alternate return. */
5ff904cd 10219
c7e4ee3a 10220 if (!ffecom_is_altreturning_)
5ff904cd 10221 {
c7e4ee3a
CB
10222 for (list = ffesymbol_dummyargs (entry);
10223 list != NULL;
10224 list = ffebld_trail (list))
10225 {
10226 arg = ffebld_head (list);
10227 if (ffebld_op (arg) == FFEBLD_opSTAR)
10228 {
10229 ffecom_is_altreturning_ = TRUE;
10230 break;
10231 }
10232 }
10233 }
5ff904cd 10234
c7e4ee3a 10235 /* Now check type compatibility. */
5ff904cd 10236
c7e4ee3a
CB
10237 switch (ffecom_master_bt_)
10238 {
10239 case FFEINFO_basictypeNONE:
10240 ok = (bt != FFEINFO_basictypeCHARACTER);
10241 break;
5ff904cd 10242
c7e4ee3a
CB
10243 case FFEINFO_basictypeCHARACTER:
10244 ok
10245 = (bt == FFEINFO_basictypeCHARACTER)
10246 && (kt == ffecom_master_kt_)
10247 && (size == ffecom_master_size_);
10248 break;
5ff904cd 10249
c7e4ee3a
CB
10250 case FFEINFO_basictypeANY:
10251 return FALSE; /* Just don't bother. */
5ff904cd 10252
c7e4ee3a
CB
10253 default:
10254 if (bt == FFEINFO_basictypeCHARACTER)
5ff904cd 10255 {
c7e4ee3a
CB
10256 ok = FALSE;
10257 break;
5ff904cd 10258 }
c7e4ee3a
CB
10259 ok = TRUE;
10260 if ((bt != ffecom_master_bt_) || (kt != ffecom_master_kt_))
10261 {
10262 ffecom_master_bt_ = FFEINFO_basictypeNONE;
10263 ffecom_master_kt_ = FFEINFO_kindtypeNONE;
10264 }
10265 break;
10266 }
5ff904cd 10267
c7e4ee3a
CB
10268 if (!ok)
10269 {
10270 ffebad_start (FFEBAD_ENTRY_CONFLICTS);
10271 ffest_ffebad_here_current_stmt (0);
10272 ffebad_finish ();
10273 return FALSE; /* Can't handle entrypoint. */
10274 }
5ff904cd 10275
c7e4ee3a 10276 /* Entrypoint type compatible with previous types. */
5ff904cd 10277
c7e4ee3a 10278 ++ffecom_num_entrypoints_;
5ff904cd 10279
c7e4ee3a
CB
10280 /* Master-arg-list = UNION(Master-arg-list,entry-arg-list). */
10281
10282 for (list = ffesymbol_dummyargs (entry);
10283 list != NULL;
10284 list = ffebld_trail (list))
10285 {
10286 arg = ffebld_head (list);
10287 if (ffebld_op (arg) != FFEBLD_opSYMTER)
10288 continue; /* Alternate return or some such thing. */
10289 s = ffebld_symter (arg);
10290 for (plist = NULL, mlist = ffecom_master_arglist_;
10291 mlist != NULL;
10292 plist = mlist, mlist = ffebld_trail (mlist))
10293 { /* plist points to previous item for easy
10294 appending of arg. */
10295 if (ffebld_symter (ffebld_head (mlist)) == s)
10296 break; /* Already have this arg in the master list. */
10297 }
10298 if (mlist != NULL)
10299 continue; /* Already have this arg in the master list. */
5ff904cd 10300
c7e4ee3a 10301 /* Append this arg to the master list. */
5ff904cd 10302
c7e4ee3a
CB
10303 item = ffebld_new_item (arg, NULL);
10304 if (plist == NULL)
10305 ffecom_master_arglist_ = item;
10306 else
10307 ffebld_set_trail (plist, item);
5ff904cd
JL
10308 }
10309
c7e4ee3a 10310 return TRUE;
5ff904cd
JL
10311}
10312
10313#endif
c7e4ee3a
CB
10314/* ffecom_2pass_do_entrypoint -- Do compilation of entrypoint
10315
10316 ffesymbol s; // the ENTRY point itself
10317 ffecom_2pass_do_entrypoint(s);
10318
10319 Does whatever compiler needs to do to make the entrypoint actually
10320 happen. Must be called for each entrypoint after
10321 ffecom_finish_progunit is called. */
10322
5ff904cd 10323#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
10324void
10325ffecom_2pass_do_entrypoint (ffesymbol entry)
5ff904cd 10326{
c7e4ee3a
CB
10327 static int mfn_num = 0;
10328 static int ent_num;
5ff904cd 10329
c7e4ee3a
CB
10330 if (mfn_num != ffecom_num_fns_)
10331 { /* First entrypoint for this program unit. */
10332 ent_num = 1;
10333 mfn_num = ffecom_num_fns_;
10334 ffecom_do_entry_ (ffecom_primary_entry_, 0);
10335 }
10336 else
10337 ++ent_num;
5ff904cd 10338
c7e4ee3a 10339 --ffecom_num_entrypoints_;
5ff904cd 10340
c7e4ee3a
CB
10341 ffecom_do_entry_ (entry, ent_num);
10342}
5ff904cd 10343
c7e4ee3a 10344#endif
5ff904cd 10345
c7e4ee3a
CB
10346/* Essentially does a "fold (build (code, type, node1, node2))" while
10347 checking for certain housekeeping things. Always sets
10348 TREE_SIDE_EFFECTS. */
5ff904cd 10349
c7e4ee3a
CB
10350#if FFECOM_targetCURRENT == FFECOM_targetGCC
10351tree
10352ffecom_2s (enum tree_code code, tree type, tree node1,
10353 tree node2)
10354{
10355 tree item;
5ff904cd 10356
c7e4ee3a
CB
10357 if ((node1 == error_mark_node)
10358 || (node2 == error_mark_node)
10359 || (type == error_mark_node))
10360 return error_mark_node;
5ff904cd 10361
c7e4ee3a
CB
10362 item = build (code, type, node1, node2);
10363 TREE_SIDE_EFFECTS (item) = 1;
10364 return fold (item);
5ff904cd
JL
10365}
10366
10367#endif
c7e4ee3a
CB
10368/* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10369 checking for certain housekeeping things. */
10370
5ff904cd 10371#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
10372tree
10373ffecom_3 (enum tree_code code, tree type, tree node1,
10374 tree node2, tree node3)
5ff904cd 10375{
c7e4ee3a 10376 tree item;
5ff904cd 10377
c7e4ee3a
CB
10378 if ((node1 == error_mark_node)
10379 || (node2 == error_mark_node)
10380 || (node3 == error_mark_node)
10381 || (type == error_mark_node))
10382 return error_mark_node;
5ff904cd 10383
c7e4ee3a
CB
10384 item = build (code, type, node1, node2, node3);
10385 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2)
10386 || (node3 != NULL_TREE && TREE_SIDE_EFFECTS (node3)))
10387 TREE_SIDE_EFFECTS (item) = 1;
10388 return fold (item);
10389}
5ff904cd 10390
c7e4ee3a
CB
10391#endif
10392/* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10393 checking for certain housekeeping things. Always sets
10394 TREE_SIDE_EFFECTS. */
5ff904cd 10395
c7e4ee3a
CB
10396#if FFECOM_targetCURRENT == FFECOM_targetGCC
10397tree
10398ffecom_3s (enum tree_code code, tree type, tree node1,
10399 tree node2, tree node3)
10400{
10401 tree item;
5ff904cd 10402
c7e4ee3a
CB
10403 if ((node1 == error_mark_node)
10404 || (node2 == error_mark_node)
10405 || (node3 == error_mark_node)
10406 || (type == error_mark_node))
10407 return error_mark_node;
5ff904cd 10408
c7e4ee3a
CB
10409 item = build (code, type, node1, node2, node3);
10410 TREE_SIDE_EFFECTS (item) = 1;
10411 return fold (item);
10412}
5ff904cd 10413
c7e4ee3a 10414#endif
5ff904cd 10415
c7e4ee3a 10416/* ffecom_arg_expr -- Transform argument expr into gcc tree
5ff904cd 10417
c7e4ee3a 10418 See use by ffecom_list_expr.
5ff904cd 10419
c7e4ee3a
CB
10420 If expression is NULL, returns an integer zero tree. If it is not
10421 a CHARACTER expression, returns whatever ffecom_expr
10422 returns and sets the length return value to NULL_TREE. Otherwise
10423 generates code to evaluate the character expression, returns the proper
10424 pointer to the result, but does NOT set the length return value to a tree
10425 that specifies the length of the result. (In other words, the length
10426 variable is always set to NULL_TREE, because a length is never passed.)
5ff904cd 10427
c7e4ee3a
CB
10428 21-Dec-91 JCB 1.1
10429 Don't set returned length, since nobody needs it (yet; someday if
10430 we allow CHARACTER*(*) dummies to statement functions, we'll need
10431 it). */
5ff904cd 10432
c7e4ee3a
CB
10433#if FFECOM_targetCURRENT == FFECOM_targetGCC
10434tree
10435ffecom_arg_expr (ffebld expr, tree *length)
10436{
10437 tree ign;
5ff904cd 10438
c7e4ee3a 10439 *length = NULL_TREE;
5ff904cd 10440
c7e4ee3a
CB
10441 if (expr == NULL)
10442 return integer_zero_node;
5ff904cd 10443
c7e4ee3a
CB
10444 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10445 return ffecom_expr (expr);
5ff904cd 10446
c7e4ee3a
CB
10447 return ffecom_arg_ptr_to_expr (expr, &ign);
10448}
10449
10450#endif
10451/* Transform expression into constant argument-pointer-to-expression tree.
10452
10453 If the expression can be transformed into a argument-pointer-to-expression
10454 tree that is constant, that is done, and the tree returned. Else
10455 NULL_TREE is returned.
5ff904cd 10456
c7e4ee3a
CB
10457 That way, a caller can attempt to provide compile-time initialization
10458 of a variable and, if that fails, *then* choose to start a new block
10459 and resort to using temporaries, as appropriate. */
5ff904cd 10460
c7e4ee3a
CB
10461tree
10462ffecom_arg_ptr_to_const_expr (ffebld expr, tree *length)
10463{
10464 if (! expr)
10465 return integer_zero_node;
5ff904cd 10466
c7e4ee3a
CB
10467 if (ffebld_op (expr) == FFEBLD_opANY)
10468 {
10469 if (length)
10470 *length = error_mark_node;
10471 return error_mark_node;
10472 }
10473
10474 if (ffebld_arity (expr) == 0
10475 && (ffebld_op (expr) != FFEBLD_opSYMTER
10476 || ffebld_where (expr) == FFEINFO_whereCOMMON
10477 || ffebld_where (expr) == FFEINFO_whereGLOBAL
10478 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
10479 {
10480 tree t;
10481
10482 t = ffecom_arg_ptr_to_expr (expr, length);
10483 assert (TREE_CONSTANT (t));
10484 assert (! length || TREE_CONSTANT (*length));
10485 return t;
10486 }
10487
10488 if (length
10489 && ffebld_size (expr) != FFETARGET_charactersizeNONE)
10490 *length = build_int_2 (ffebld_size (expr), 0);
10491 else if (length)
10492 *length = NULL_TREE;
10493 return NULL_TREE;
5ff904cd
JL
10494}
10495
c7e4ee3a 10496/* ffecom_arg_ptr_to_expr -- Transform argument expr into gcc tree
5ff904cd 10497
c7e4ee3a
CB
10498 See use by ffecom_list_ptr_to_expr.
10499
10500 If expression is NULL, returns an integer zero tree. If it is not
10501 a CHARACTER expression, returns whatever ffecom_ptr_to_expr
10502 returns and sets the length return value to NULL_TREE. Otherwise
10503 generates code to evaluate the character expression, returns the proper
10504 pointer to the result, AND sets the length return value to a tree that
10505 specifies the length of the result.
10506
10507 If the length argument is NULL, this is a slightly special
10508 case of building a FORMAT expression, that is, an expression that
10509 will be used at run time without regard to length. For the current
10510 implementation, which uses the libf2c library, this means it is nice
10511 to append a null byte to the end of the expression, where feasible,
10512 to make sure any diagnostic about the FORMAT string terminates at
10513 some useful point.
10514
10515 For now, treat %REF(char-expr) as the same as char-expr with a NULL
10516 length argument. This might even be seen as a feature, if a null
10517 byte can always be appended. */
5ff904cd
JL
10518
10519#if FFECOM_targetCURRENT == FFECOM_targetGCC
10520tree
c7e4ee3a 10521ffecom_arg_ptr_to_expr (ffebld expr, tree *length)
5ff904cd
JL
10522{
10523 tree item;
c7e4ee3a
CB
10524 tree ign_length;
10525 ffecomConcatList_ catlist;
5ff904cd 10526
c7e4ee3a
CB
10527 if (length != NULL)
10528 *length = NULL_TREE;
5ff904cd 10529
c7e4ee3a
CB
10530 if (expr == NULL)
10531 return integer_zero_node;
5ff904cd 10532
c7e4ee3a 10533 switch (ffebld_op (expr))
5ff904cd 10534 {
c7e4ee3a
CB
10535 case FFEBLD_opPERCENT_VAL:
10536 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10537 return ffecom_expr (ffebld_left (expr));
10538 {
10539 tree temp_exp;
10540 tree temp_length;
5ff904cd 10541
c7e4ee3a
CB
10542 temp_exp = ffecom_arg_ptr_to_expr (ffebld_left (expr), &temp_length);
10543 if (temp_exp == error_mark_node)
10544 return error_mark_node;
5ff904cd 10545
c7e4ee3a
CB
10546 return ffecom_1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (temp_exp)),
10547 temp_exp);
10548 }
5ff904cd 10549
c7e4ee3a
CB
10550 case FFEBLD_opPERCENT_REF:
10551 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10552 return ffecom_ptr_to_expr (ffebld_left (expr));
10553 if (length != NULL)
10554 {
10555 ign_length = NULL_TREE;
10556 length = &ign_length;
10557 }
10558 expr = ffebld_left (expr);
10559 break;
5ff904cd 10560
c7e4ee3a
CB
10561 case FFEBLD_opPERCENT_DESCR:
10562 switch (ffeinfo_basictype (ffebld_info (expr)))
5ff904cd 10563 {
c7e4ee3a
CB
10564#ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10565 case FFEINFO_basictypeHOLLERITH:
10566#endif
10567 case FFEINFO_basictypeCHARACTER:
10568 break; /* Passed by descriptor anyway. */
10569
10570 default:
10571 item = ffecom_ptr_to_expr (expr);
10572 if (item != error_mark_node)
10573 *length = TYPE_SIZE (TREE_TYPE (TREE_TYPE (item)));
5ff904cd
JL
10574 break;
10575 }
5ff904cd
JL
10576 break;
10577
10578 default:
5ff904cd
JL
10579 break;
10580 }
10581
c7e4ee3a
CB
10582#ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10583 if ((ffeinfo_basictype (ffebld_info (expr)) == FFEINFO_basictypeHOLLERITH)
10584 && (length != NULL))
10585 { /* Pass Hollerith by descriptor. */
10586 ffetargetHollerith h;
10587
10588 assert (ffebld_op (expr) == FFEBLD_opCONTER);
10589 h = ffebld_cu_val_hollerith (ffebld_constant_union
10590 (ffebld_conter (expr)));
10591 *length
10592 = build_int_2 (h.length, 0);
10593 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10594 }
10595#endif
10596
10597 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10598 return ffecom_ptr_to_expr (expr);
10599
10600 assert (ffeinfo_kindtype (ffebld_info (expr))
10601 == FFEINFO_kindtypeCHARACTER1);
10602
10603 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
10604 switch (ffecom_concat_list_count_ (catlist))
10605 {
10606 case 0: /* Shouldn't happen, but in case it does... */
10607 if (length != NULL)
10608 {
10609 *length = ffecom_f2c_ftnlen_zero_node;
10610 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10611 }
10612 ffecom_concat_list_kill_ (catlist);
10613 return null_pointer_node;
10614
10615 case 1: /* The (fairly) easy case. */
10616 if (length == NULL)
10617 ffecom_char_args_with_null_ (&item, &ign_length,
10618 ffecom_concat_list_expr_ (catlist, 0));
10619 else
10620 ffecom_char_args_ (&item, length,
10621 ffecom_concat_list_expr_ (catlist, 0));
10622 ffecom_concat_list_kill_ (catlist);
10623 assert (item != NULL_TREE);
10624 return item;
10625
10626 default: /* Must actually concatenate things. */
10627 break;
10628 }
10629
10630 {
10631 int count = ffecom_concat_list_count_ (catlist);
10632 int i;
10633 tree lengths;
10634 tree items;
10635 tree length_array;
10636 tree item_array;
10637 tree citem;
10638 tree clength;
10639 tree temporary;
10640 tree num;
10641 tree known_length;
10642 ffetargetCharacterSize sz;
10643
10644 sz = ffecom_concat_list_maxlen_ (catlist);
10645 /* ~~Kludge! */
10646 assert (sz != FFETARGET_charactersizeNONE);
10647
10648#ifdef HOHO
10649 length_array
10650 = lengths
10651 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
10652 FFETARGET_charactersizeNONE, count, TRUE);
10653 item_array
10654 = items
10655 = ffecom_push_tempvar (ffecom_f2c_address_type_node,
10656 FFETARGET_charactersizeNONE, count, TRUE);
10657 temporary = ffecom_push_tempvar (char_type_node,
10658 sz, -1, TRUE);
10659#else
10660 {
10661 tree hook;
10662
10663 hook = ffebld_nonter_hook (expr);
10664 assert (hook);
10665 assert (TREE_CODE (hook) == TREE_VEC);
10666 assert (TREE_VEC_LENGTH (hook) == 3);
10667 length_array = lengths = TREE_VEC_ELT (hook, 0);
10668 item_array = items = TREE_VEC_ELT (hook, 1);
10669 temporary = TREE_VEC_ELT (hook, 2);
10670 }
10671#endif
10672
10673 known_length = ffecom_f2c_ftnlen_zero_node;
10674
10675 for (i = 0; i < count; ++i)
10676 {
10677 if ((i == count)
10678 && (length == NULL))
10679 ffecom_char_args_with_null_ (&citem, &clength,
10680 ffecom_concat_list_expr_ (catlist, i));
10681 else
10682 ffecom_char_args_ (&citem, &clength,
10683 ffecom_concat_list_expr_ (catlist, i));
10684 if ((citem == error_mark_node)
10685 || (clength == error_mark_node))
10686 {
10687 ffecom_concat_list_kill_ (catlist);
10688 *length = error_mark_node;
10689 return error_mark_node;
10690 }
10691
10692 items
10693 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
10694 ffecom_modify (void_type_node,
10695 ffecom_2 (ARRAY_REF,
10696 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
10697 item_array,
10698 build_int_2 (i, 0)),
10699 citem),
10700 items);
10701 clength = ffecom_save_tree (clength);
10702 if (length != NULL)
10703 known_length
10704 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
10705 known_length,
10706 clength);
10707 lengths
10708 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
10709 ffecom_modify (void_type_node,
10710 ffecom_2 (ARRAY_REF,
10711 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
10712 length_array,
10713 build_int_2 (i, 0)),
10714 clength),
10715 lengths);
10716 }
10717
10718 temporary = ffecom_1 (ADDR_EXPR,
10719 build_pointer_type (TREE_TYPE (temporary)),
10720 temporary);
10721
10722 item = build_tree_list (NULL_TREE, temporary);
10723 TREE_CHAIN (item)
10724 = build_tree_list (NULL_TREE,
10725 ffecom_1 (ADDR_EXPR,
10726 build_pointer_type (TREE_TYPE (items)),
10727 items));
10728 TREE_CHAIN (TREE_CHAIN (item))
10729 = build_tree_list (NULL_TREE,
10730 ffecom_1 (ADDR_EXPR,
10731 build_pointer_type (TREE_TYPE (lengths)),
10732 lengths));
10733 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
10734 = build_tree_list
10735 (NULL_TREE,
10736 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
10737 convert (ffecom_f2c_ftnlen_type_node,
10738 build_int_2 (count, 0))));
10739 num = build_int_2 (sz, 0);
10740 TREE_TYPE (num) = ffecom_f2c_ftnlen_type_node;
10741 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item))))
10742 = build_tree_list (NULL_TREE, num);
10743
10744 item = ffecom_call_gfrt (FFECOM_gfrtCAT, item, NULL_TREE);
5ff904cd 10745 TREE_SIDE_EFFECTS (item) = 1;
c7e4ee3a
CB
10746 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (temporary),
10747 item,
10748 temporary);
10749
10750 if (length != NULL)
10751 *length = known_length;
10752 }
10753
10754 ffecom_concat_list_kill_ (catlist);
10755 assert (item != NULL_TREE);
10756 return item;
5ff904cd 10757}
c7e4ee3a 10758
5ff904cd 10759#endif
c7e4ee3a 10760/* Generate call to run-time function.
5ff904cd 10761
c7e4ee3a
CB
10762 The first arg is the GNU Fortran Run-Time function index, the second
10763 arg is the list of arguments to pass to it. Returned is the expression
10764 (WITHOUT TREE_SIDE_EFFECTS set!) that makes the call and returns the
10765 result (which may be void). */
5ff904cd
JL
10766
10767#if FFECOM_targetCURRENT == FFECOM_targetGCC
10768tree
c7e4ee3a 10769ffecom_call_gfrt (ffecomGfrt ix, tree args, tree hook)
5ff904cd 10770{
c7e4ee3a
CB
10771 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
10772 ffecom_gfrt_kindtype (ix),
10773 ffe_is_f2c_library () && ffecom_gfrt_complex_[ix],
10774 NULL_TREE, args, NULL_TREE, NULL,
10775 NULL, NULL_TREE, TRUE, hook);
5ff904cd
JL
10776}
10777#endif
10778
c7e4ee3a 10779/* Transform constant-union to tree. */
5ff904cd
JL
10780
10781#if FFECOM_targetCURRENT == FFECOM_targetGCC
10782tree
c7e4ee3a
CB
10783ffecom_constantunion (ffebldConstantUnion *cu, ffeinfoBasictype bt,
10784 ffeinfoKindtype kt, tree tree_type)
5ff904cd
JL
10785{
10786 tree item;
10787
c7e4ee3a 10788 switch (bt)
5ff904cd 10789 {
c7e4ee3a
CB
10790 case FFEINFO_basictypeINTEGER:
10791 {
10792 int val;
5ff904cd 10793
c7e4ee3a
CB
10794 switch (kt)
10795 {
10796#if FFETARGET_okINTEGER1
10797 case FFEINFO_kindtypeINTEGER1:
10798 val = ffebld_cu_val_integer1 (*cu);
10799 break;
10800#endif
5ff904cd 10801
c7e4ee3a
CB
10802#if FFETARGET_okINTEGER2
10803 case FFEINFO_kindtypeINTEGER2:
10804 val = ffebld_cu_val_integer2 (*cu);
10805 break;
10806#endif
5ff904cd 10807
c7e4ee3a
CB
10808#if FFETARGET_okINTEGER3
10809 case FFEINFO_kindtypeINTEGER3:
10810 val = ffebld_cu_val_integer3 (*cu);
10811 break;
10812#endif
5ff904cd 10813
c7e4ee3a
CB
10814#if FFETARGET_okINTEGER4
10815 case FFEINFO_kindtypeINTEGER4:
10816 val = ffebld_cu_val_integer4 (*cu);
10817 break;
10818#endif
5ff904cd 10819
c7e4ee3a
CB
10820 default:
10821 assert ("bad INTEGER constant kind type" == NULL);
10822 /* Fall through. */
10823 case FFEINFO_kindtypeANY:
10824 return error_mark_node;
10825 }
10826 item = build_int_2 (val, (val < 0) ? -1 : 0);
10827 TREE_TYPE (item) = tree_type;
10828 }
5ff904cd 10829 break;
5ff904cd 10830
c7e4ee3a
CB
10831 case FFEINFO_basictypeLOGICAL:
10832 {
10833 int val;
5ff904cd 10834
c7e4ee3a
CB
10835 switch (kt)
10836 {
10837#if FFETARGET_okLOGICAL1
10838 case FFEINFO_kindtypeLOGICAL1:
10839 val = ffebld_cu_val_logical1 (*cu);
10840 break;
5ff904cd 10841#endif
5ff904cd 10842
c7e4ee3a
CB
10843#if FFETARGET_okLOGICAL2
10844 case FFEINFO_kindtypeLOGICAL2:
10845 val = ffebld_cu_val_logical2 (*cu);
10846 break;
10847#endif
5ff904cd 10848
c7e4ee3a
CB
10849#if FFETARGET_okLOGICAL3
10850 case FFEINFO_kindtypeLOGICAL3:
10851 val = ffebld_cu_val_logical3 (*cu);
10852 break;
10853#endif
5ff904cd 10854
c7e4ee3a
CB
10855#if FFETARGET_okLOGICAL4
10856 case FFEINFO_kindtypeLOGICAL4:
10857 val = ffebld_cu_val_logical4 (*cu);
10858 break;
10859#endif
5ff904cd 10860
c7e4ee3a
CB
10861 default:
10862 assert ("bad LOGICAL constant kind type" == NULL);
10863 /* Fall through. */
10864 case FFEINFO_kindtypeANY:
10865 return error_mark_node;
10866 }
10867 item = build_int_2 (val, (val < 0) ? -1 : 0);
10868 TREE_TYPE (item) = tree_type;
10869 }
10870 break;
5ff904cd 10871
c7e4ee3a
CB
10872 case FFEINFO_basictypeREAL:
10873 {
10874 REAL_VALUE_TYPE val;
5ff904cd 10875
c7e4ee3a
CB
10876 switch (kt)
10877 {
10878#if FFETARGET_okREAL1
10879 case FFEINFO_kindtypeREAL1:
10880 val = ffetarget_value_real1 (ffebld_cu_val_real1 (*cu));
10881 break;
10882#endif
5ff904cd 10883
c7e4ee3a
CB
10884#if FFETARGET_okREAL2
10885 case FFEINFO_kindtypeREAL2:
10886 val = ffetarget_value_real2 (ffebld_cu_val_real2 (*cu));
10887 break;
10888#endif
5ff904cd 10889
c7e4ee3a
CB
10890#if FFETARGET_okREAL3
10891 case FFEINFO_kindtypeREAL3:
10892 val = ffetarget_value_real3 (ffebld_cu_val_real3 (*cu));
10893 break;
10894#endif
5ff904cd 10895
c7e4ee3a
CB
10896#if FFETARGET_okREAL4
10897 case FFEINFO_kindtypeREAL4:
10898 val = ffetarget_value_real4 (ffebld_cu_val_real4 (*cu));
10899 break;
10900#endif
5ff904cd 10901
c7e4ee3a
CB
10902 default:
10903 assert ("bad REAL constant kind type" == NULL);
10904 /* Fall through. */
10905 case FFEINFO_kindtypeANY:
10906 return error_mark_node;
10907 }
10908 item = build_real (tree_type, val);
10909 }
5ff904cd
JL
10910 break;
10911
c7e4ee3a
CB
10912 case FFEINFO_basictypeCOMPLEX:
10913 {
10914 REAL_VALUE_TYPE real;
10915 REAL_VALUE_TYPE imag;
10916 tree el_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
5ff904cd 10917
c7e4ee3a
CB
10918 switch (kt)
10919 {
10920#if FFETARGET_okCOMPLEX1
10921 case FFEINFO_kindtypeREAL1:
10922 real = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).real);
10923 imag = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).imaginary);
10924 break;
10925#endif
5ff904cd 10926
c7e4ee3a
CB
10927#if FFETARGET_okCOMPLEX2
10928 case FFEINFO_kindtypeREAL2:
10929 real = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).real);
10930 imag = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).imaginary);
10931 break;
10932#endif
5ff904cd 10933
c7e4ee3a
CB
10934#if FFETARGET_okCOMPLEX3
10935 case FFEINFO_kindtypeREAL3:
10936 real = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).real);
10937 imag = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).imaginary);
10938 break;
10939#endif
5ff904cd 10940
c7e4ee3a
CB
10941#if FFETARGET_okCOMPLEX4
10942 case FFEINFO_kindtypeREAL4:
10943 real = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).real);
10944 imag = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).imaginary);
10945 break;
10946#endif
5ff904cd 10947
c7e4ee3a
CB
10948 default:
10949 assert ("bad REAL constant kind type" == NULL);
10950 /* Fall through. */
10951 case FFEINFO_kindtypeANY:
10952 return error_mark_node;
10953 }
10954 item = ffecom_build_complex_constant_ (tree_type,
10955 build_real (el_type, real),
10956 build_real (el_type, imag));
10957 }
10958 break;
5ff904cd 10959
c7e4ee3a
CB
10960 case FFEINFO_basictypeCHARACTER:
10961 { /* Happens only in DATA and similar contexts. */
10962 ffetargetCharacter1 val;
5ff904cd 10963
c7e4ee3a
CB
10964 switch (kt)
10965 {
10966#if FFETARGET_okCHARACTER1
10967 case FFEINFO_kindtypeLOGICAL1:
10968 val = ffebld_cu_val_character1 (*cu);
10969 break;
10970#endif
10971
10972 default:
10973 assert ("bad CHARACTER constant kind type" == NULL);
10974 /* Fall through. */
10975 case FFEINFO_kindtypeANY:
10976 return error_mark_node;
10977 }
10978 item = build_string (ffetarget_length_character1 (val),
10979 ffetarget_text_character1 (val));
10980 TREE_TYPE (item)
10981 = build_type_variant (build_array_type (char_type_node,
10982 build_range_type
10983 (integer_type_node,
10984 integer_one_node,
10985 build_int_2
10986 (ffetarget_length_character1
10987 (val), 0))),
10988 1, 0);
10989 }
10990 break;
5ff904cd 10991
c7e4ee3a
CB
10992 case FFEINFO_basictypeHOLLERITH:
10993 {
10994 ffetargetHollerith h;
5ff904cd 10995
c7e4ee3a 10996 h = ffebld_cu_val_hollerith (*cu);
5ff904cd 10997
c7e4ee3a
CB
10998 /* If not at least as wide as default INTEGER, widen it. */
10999 if (h.length >= FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE)
11000 item = build_string (h.length, h.text);
11001 else
11002 {
11003 char str[FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE];
5ff904cd 11004
c7e4ee3a
CB
11005 memcpy (str, h.text, h.length);
11006 memset (&str[h.length], ' ',
11007 FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE
11008 - h.length);
11009 item = build_string (FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE,
11010 str);
11011 }
11012 TREE_TYPE (item)
11013 = build_type_variant (build_array_type (char_type_node,
11014 build_range_type
11015 (integer_type_node,
11016 integer_one_node,
11017 build_int_2
11018 (h.length, 0))),
11019 1, 0);
11020 }
11021 break;
5ff904cd 11022
c7e4ee3a
CB
11023 case FFEINFO_basictypeTYPELESS:
11024 {
11025 ffetargetInteger1 ival;
11026 ffetargetTypeless tless;
11027 ffebad error;
5ff904cd 11028
c7e4ee3a
CB
11029 tless = ffebld_cu_val_typeless (*cu);
11030 error = ffetarget_convert_integer1_typeless (&ival, tless);
11031 assert (error == FFEBAD);
5ff904cd 11032
c7e4ee3a
CB
11033 item = build_int_2 ((int) ival, 0);
11034 }
11035 break;
5ff904cd 11036
c7e4ee3a
CB
11037 default:
11038 assert ("not yet on constant type" == NULL);
11039 /* Fall through. */
11040 case FFEINFO_basictypeANY:
11041 return error_mark_node;
5ff904cd 11042 }
5ff904cd 11043
c7e4ee3a 11044 TREE_CONSTANT (item) = 1;
5ff904cd 11045
c7e4ee3a 11046 return item;
5ff904cd
JL
11047}
11048
11049#endif
11050
c7e4ee3a
CB
11051/* Transform expression into constant tree.
11052
11053 If the expression can be transformed into a tree that is constant,
11054 that is done, and the tree returned. Else NULL_TREE is returned.
11055
11056 That way, a caller can attempt to provide compile-time initialization
11057 of a variable and, if that fails, *then* choose to start a new block
11058 and resort to using temporaries, as appropriate. */
5ff904cd 11059
5ff904cd 11060tree
c7e4ee3a 11061ffecom_const_expr (ffebld expr)
5ff904cd 11062{
c7e4ee3a
CB
11063 if (! expr)
11064 return integer_zero_node;
5ff904cd 11065
c7e4ee3a 11066 if (ffebld_op (expr) == FFEBLD_opANY)
5ff904cd
JL
11067 return error_mark_node;
11068
c7e4ee3a
CB
11069 if (ffebld_arity (expr) == 0
11070 && (ffebld_op (expr) != FFEBLD_opSYMTER
11071#if NEWCOMMON
11072 /* ~~Enable once common/equivalence is handled properly? */
11073 || ffebld_where (expr) == FFEINFO_whereCOMMON
5ff904cd 11074#endif
c7e4ee3a
CB
11075 || ffebld_where (expr) == FFEINFO_whereGLOBAL
11076 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
11077 {
11078 tree t;
5ff904cd 11079
c7e4ee3a
CB
11080 t = ffecom_expr (expr);
11081 assert (TREE_CONSTANT (t));
11082 return t;
11083 }
5ff904cd 11084
c7e4ee3a 11085 return NULL_TREE;
5ff904cd
JL
11086}
11087
c7e4ee3a 11088/* Handy way to make a field in a struct/union. */
5ff904cd
JL
11089
11090#if FFECOM_targetCURRENT == FFECOM_targetGCC
11091tree
c7e4ee3a
CB
11092ffecom_decl_field (tree context, tree prevfield,
11093 const char *name, tree type)
5ff904cd 11094{
c7e4ee3a 11095 tree field;
5ff904cd 11096
c7e4ee3a
CB
11097 field = build_decl (FIELD_DECL, get_identifier (name), type);
11098 DECL_CONTEXT (field) = context;
11099 DECL_FRAME_SIZE (field) = 0;
11100 if (prevfield != NULL_TREE)
11101 TREE_CHAIN (prevfield) = field;
5ff904cd 11102
c7e4ee3a 11103 return field;
5ff904cd
JL
11104}
11105
11106#endif
5ff904cd 11107
c7e4ee3a
CB
11108void
11109ffecom_close_include (FILE *f)
11110{
11111#if FFECOM_GCC_INCLUDE
11112 ffecom_close_include_ (f);
11113#endif
11114}
5ff904cd 11115
c7e4ee3a
CB
11116int
11117ffecom_decode_include_option (char *spec)
11118{
11119#if FFECOM_GCC_INCLUDE
11120 return ffecom_decode_include_option_ (spec);
11121#else
11122 return 1;
11123#endif
11124}
5ff904cd 11125
c7e4ee3a 11126/* End a compound statement (block). */
5ff904cd
JL
11127
11128#if FFECOM_targetCURRENT == FFECOM_targetGCC
11129tree
c7e4ee3a 11130ffecom_end_compstmt (void)
5ff904cd 11131{
c7e4ee3a
CB
11132 return bison_rule_compstmt_ ();
11133}
11134#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
5ff904cd 11135
c7e4ee3a 11136/* ffecom_end_transition -- Perform end transition on all symbols
5ff904cd 11137
c7e4ee3a 11138 ffecom_end_transition();
5ff904cd 11139
c7e4ee3a 11140 Calls ffecom_sym_end_transition for each global and local symbol. */
5ff904cd 11141
c7e4ee3a
CB
11142void
11143ffecom_end_transition ()
11144{
11145#if FFECOM_targetCURRENT == FFECOM_targetGCC
11146 ffebld item;
5ff904cd 11147#endif
5ff904cd 11148
c7e4ee3a
CB
11149 if (ffe_is_ffedebug ())
11150 fprintf (dmpout, "; end_stmt_transition\n");
86fc7a6c 11151
c7e4ee3a
CB
11152#if FFECOM_targetCURRENT == FFECOM_targetGCC
11153 ffecom_list_blockdata_ = NULL;
11154 ffecom_list_common_ = NULL;
11155#endif
86fc7a6c 11156
c7e4ee3a
CB
11157 ffesymbol_drive (ffecom_sym_end_transition);
11158 if (ffe_is_ffedebug ())
11159 {
11160 ffestorag_report ();
11161#if FFECOM_targetCURRENT == FFECOM_targetFFE
11162 ffesymbol_report_all ();
11163#endif
11164 }
5ff904cd
JL
11165
11166#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
11167 ffecom_start_progunit_ ();
11168
11169 for (item = ffecom_list_blockdata_;
11170 item != NULL;
11171 item = ffebld_trail (item))
11172 {
11173 ffebld callee;
11174 ffesymbol s;
11175 tree dt;
11176 tree t;
11177 tree var;
11178 int yes;
11179 static int number = 0;
11180
11181 callee = ffebld_head (item);
11182 s = ffebld_symter (callee);
11183 t = ffesymbol_hook (s).decl_tree;
11184 if (t == NULL_TREE)
11185 {
11186 s = ffecom_sym_transform_ (s);
11187 t = ffesymbol_hook (s).decl_tree;
11188 }
5ff904cd 11189
c7e4ee3a 11190 yes = suspend_momentary ();
5ff904cd 11191
c7e4ee3a 11192 dt = build_pointer_type (TREE_TYPE (t));
5ff904cd 11193
c7e4ee3a
CB
11194 var = build_decl (VAR_DECL,
11195 ffecom_get_invented_identifier ("__g77_forceload_%d",
11196 NULL, number++),
11197 dt);
11198 DECL_EXTERNAL (var) = 0;
11199 TREE_STATIC (var) = 1;
11200 TREE_PUBLIC (var) = 0;
11201 DECL_INITIAL (var) = error_mark_node;
11202 TREE_USED (var) = 1;
5ff904cd 11203
c7e4ee3a 11204 var = start_decl (var, FALSE);
702edf1d 11205
c7e4ee3a 11206 t = ffecom_1 (ADDR_EXPR, dt, t);
5ff904cd 11207
c7e4ee3a 11208 finish_decl (var, t, FALSE);
5ff904cd 11209
c7e4ee3a
CB
11210 resume_momentary (yes);
11211 }
11212
11213 /* This handles any COMMON areas that weren't referenced but have, for
11214 example, important initial data. */
11215
11216 for (item = ffecom_list_common_;
11217 item != NULL;
11218 item = ffebld_trail (item))
11219 ffecom_transform_common_ (ffebld_symter (ffebld_head (item)));
11220
11221 ffecom_list_common_ = NULL;
5ff904cd 11222#endif
c7e4ee3a 11223}
5ff904cd 11224
c7e4ee3a 11225/* ffecom_exec_transition -- Perform exec transition on all symbols
5ff904cd 11226
c7e4ee3a 11227 ffecom_exec_transition();
5ff904cd 11228
c7e4ee3a
CB
11229 Calls ffecom_sym_exec_transition for each global and local symbol.
11230 Make sure error updating not inhibited. */
5ff904cd 11231
c7e4ee3a
CB
11232void
11233ffecom_exec_transition ()
11234{
11235 bool inhibited;
5ff904cd 11236
c7e4ee3a
CB
11237 if (ffe_is_ffedebug ())
11238 fprintf (dmpout, "; exec_stmt_transition\n");
5ff904cd 11239
c7e4ee3a
CB
11240 inhibited = ffebad_inhibit ();
11241 ffebad_set_inhibit (FALSE);
5ff904cd 11242
c7e4ee3a
CB
11243 ffesymbol_drive (ffecom_sym_exec_transition); /* Don't retract! */
11244 ffeequiv_exec_transition (); /* Handle all pending EQUIVALENCEs. */
11245 if (ffe_is_ffedebug ())
5ff904cd 11246 {
c7e4ee3a
CB
11247 ffestorag_report ();
11248#if FFECOM_targetCURRENT == FFECOM_targetFFE
11249 ffesymbol_report_all ();
11250#endif
11251 }
5ff904cd 11252
c7e4ee3a
CB
11253 if (inhibited)
11254 ffebad_set_inhibit (TRUE);
11255}
5ff904cd 11256
c7e4ee3a 11257/* Handle assignment statement.
5ff904cd 11258
c7e4ee3a
CB
11259 Convert dest and source using ffecom_expr, then join them
11260 with an ASSIGN op and pass the whole thing to expand_expr_stmt. */
5ff904cd 11261
c7e4ee3a
CB
11262#if FFECOM_targetCURRENT == FFECOM_targetGCC
11263void
11264ffecom_expand_let_stmt (ffebld dest, ffebld source)
11265{
11266 tree dest_tree;
11267 tree dest_length;
11268 tree source_tree;
11269 tree expr_tree;
5ff904cd 11270
c7e4ee3a
CB
11271 if (ffeinfo_basictype (ffebld_info (dest)) != FFEINFO_basictypeCHARACTER)
11272 {
11273 bool dest_used;
d6cd84e0 11274 tree assign_temp;
5ff904cd 11275
c7e4ee3a
CB
11276 /* This attempts to replicate the test below, but must not be
11277 true when the test below is false. (Always err on the side
11278 of creating unused temporaries, to avoid ICEs.) */
11279 if (ffebld_op (dest) != FFEBLD_opSYMTER
11280 || ((dest_tree = ffesymbol_hook (ffebld_symter (dest)).decl_tree)
11281 && (TREE_CODE (dest_tree) != VAR_DECL
11282 || TREE_ADDRESSABLE (dest_tree))))
11283 {
11284 ffecom_prepare_expr_ (source, dest);
11285 dest_used = TRUE;
11286 }
11287 else
11288 {
11289 ffecom_prepare_expr_ (source, NULL);
11290 dest_used = FALSE;
11291 }
5ff904cd 11292
c7e4ee3a 11293 ffecom_prepare_expr_w (NULL_TREE, dest);
5ff904cd 11294
d6cd84e0
CB
11295 /* For COMPLEX assignment like C1=C2, if partial overlap is possible,
11296 create a temporary through which the assignment is to take place,
11297 since MODIFY_EXPR doesn't handle partial overlap properly. */
11298 if (ffebld_basictype (dest) == FFEINFO_basictypeCOMPLEX
11299 && ffecom_possible_partial_overlap_ (dest, source))
11300 {
11301 assign_temp = ffecom_make_tempvar ("complex_let",
11302 ffecom_tree_type
11303 [ffebld_basictype (dest)]
11304 [ffebld_kindtype (dest)],
11305 FFETARGET_charactersizeNONE,
11306 -1);
11307 }
11308 else
11309 assign_temp = NULL_TREE;
11310
c7e4ee3a 11311 ffecom_prepare_end ();
5ff904cd 11312
c7e4ee3a
CB
11313 dest_tree = ffecom_expr_w (NULL_TREE, dest);
11314 if (dest_tree == error_mark_node)
11315 return;
5ff904cd 11316
c7e4ee3a
CB
11317 if ((TREE_CODE (dest_tree) != VAR_DECL)
11318 || TREE_ADDRESSABLE (dest_tree))
11319 source_tree = ffecom_expr_ (source, dest_tree, dest, &dest_used,
11320 FALSE, FALSE);
11321 else
11322 {
11323 assert (! dest_used);
11324 dest_used = FALSE;
11325 source_tree = ffecom_expr (source);
11326 }
11327 if (source_tree == error_mark_node)
11328 return;
5ff904cd 11329
c7e4ee3a
CB
11330 if (dest_used)
11331 expr_tree = source_tree;
d6cd84e0
CB
11332 else if (assign_temp)
11333 {
11334#ifdef MOVE_EXPR
11335 /* The back end understands a conceptual move (evaluate source;
11336 store into dest), so use that, in case it can determine
11337 that it is going to use, say, two registers as temporaries
11338 anyway. So don't use the temp (and someday avoid generating
11339 it, once this code starts triggering regularly). */
11340 expr_tree = ffecom_2s (MOVE_EXPR, void_type_node,
11341 dest_tree,
11342 source_tree);
11343#else
11344 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11345 assign_temp,
11346 source_tree);
11347 expand_expr_stmt (expr_tree);
11348 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11349 dest_tree,
11350 assign_temp);
11351#endif
11352 }
c7e4ee3a
CB
11353 else
11354 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11355 dest_tree,
11356 source_tree);
5ff904cd 11357
c7e4ee3a
CB
11358 expand_expr_stmt (expr_tree);
11359 return;
11360 }
5ff904cd 11361
c7e4ee3a
CB
11362 ffecom_prepare_let_char_ (ffebld_size_known (dest), source);
11363 ffecom_prepare_expr_w (NULL_TREE, dest);
11364
11365 ffecom_prepare_end ();
11366
11367 ffecom_char_args_ (&dest_tree, &dest_length, dest);
11368 ffecom_let_char_ (dest_tree, dest_length, ffebld_size_known (dest),
11369 source);
5ff904cd
JL
11370}
11371
11372#endif
c7e4ee3a 11373/* ffecom_expr -- Transform expr into gcc tree
5ff904cd 11374
c7e4ee3a
CB
11375 tree t;
11376 ffebld expr; // FFE expression.
11377 tree = ffecom_expr(expr);
5ff904cd 11378
c7e4ee3a
CB
11379 Recursive descent on expr while making corresponding tree nodes and
11380 attaching type info and such. */
5ff904cd
JL
11381
11382#if FFECOM_targetCURRENT == FFECOM_targetGCC
11383tree
c7e4ee3a 11384ffecom_expr (ffebld expr)
5ff904cd 11385{
c7e4ee3a 11386 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, FALSE, FALSE);
5ff904cd 11387}
c7e4ee3a 11388
5ff904cd 11389#endif
c7e4ee3a 11390/* Like ffecom_expr, but return tree usable for assigned GOTO or FORMAT. */
5ff904cd 11391
c7e4ee3a
CB
11392#if FFECOM_targetCURRENT == FFECOM_targetGCC
11393tree
11394ffecom_expr_assign (ffebld expr)
11395{
11396 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
11397}
5ff904cd 11398
c7e4ee3a
CB
11399#endif
11400/* Like ffecom_expr_rw, but return tree usable for ASSIGN. */
5ff904cd
JL
11401
11402#if FFECOM_targetCURRENT == FFECOM_targetGCC
11403tree
c7e4ee3a 11404ffecom_expr_assign_w (ffebld expr)
5ff904cd 11405{
c7e4ee3a
CB
11406 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
11407}
5ff904cd 11408
5ff904cd 11409#endif
c7e4ee3a
CB
11410/* Transform expr for use as into read/write tree and stabilize the
11411 reference. Not for use on CHARACTER expressions.
5ff904cd 11412
c7e4ee3a
CB
11413 Recursive descent on expr while making corresponding tree nodes and
11414 attaching type info and such. */
5ff904cd 11415
c7e4ee3a
CB
11416#if FFECOM_targetCURRENT == FFECOM_targetGCC
11417tree
11418ffecom_expr_rw (tree type, ffebld expr)
11419{
11420 assert (expr != NULL);
11421 /* Different target types not yet supported. */
11422 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
11423
11424 return stabilize_reference (ffecom_expr (expr));
11425}
5ff904cd 11426
5ff904cd 11427#endif
c7e4ee3a
CB
11428/* Transform expr for use as into write tree and stabilize the
11429 reference. Not for use on CHARACTER expressions.
5ff904cd 11430
c7e4ee3a
CB
11431 Recursive descent on expr while making corresponding tree nodes and
11432 attaching type info and such. */
5ff904cd 11433
c7e4ee3a
CB
11434#if FFECOM_targetCURRENT == FFECOM_targetGCC
11435tree
11436ffecom_expr_w (tree type, ffebld expr)
11437{
11438 assert (expr != NULL);
11439 /* Different target types not yet supported. */
11440 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
11441
11442 return stabilize_reference (ffecom_expr (expr));
11443}
5ff904cd 11444
5ff904cd 11445#endif
c7e4ee3a
CB
11446/* Do global stuff. */
11447
11448#if FFECOM_targetCURRENT == FFECOM_targetGCC
11449void
11450ffecom_finish_compile ()
11451{
11452 assert (ffecom_outer_function_decl_ == NULL_TREE);
11453 assert (current_function_decl == NULL_TREE);
11454
11455 ffeglobal_drive (ffecom_finish_global_);
11456}
5ff904cd 11457
5ff904cd 11458#endif
c7e4ee3a
CB
11459/* Public entry point for front end to access finish_decl. */
11460
11461#if FFECOM_targetCURRENT == FFECOM_targetGCC
11462void
11463ffecom_finish_decl (tree decl, tree init, bool is_top_level)
11464{
11465 assert (!is_top_level);
11466 finish_decl (decl, init, FALSE);
11467}
5ff904cd 11468
5ff904cd 11469#endif
c7e4ee3a
CB
11470/* Finish a program unit. */
11471
11472#if FFECOM_targetCURRENT == FFECOM_targetGCC
11473void
11474ffecom_finish_progunit ()
11475{
11476 ffecom_end_compstmt ();
11477
11478 ffecom_previous_function_decl_ = current_function_decl;
11479 ffecom_which_entrypoint_decl_ = NULL_TREE;
11480
11481 finish_function (0);
11482}
5ff904cd 11483
5ff904cd 11484#endif
c7e4ee3a
CB
11485/* Wrapper for get_identifier. pattern is sprintf-like, assumed to contain
11486 one %s if text is not NULL, assumed to contain one %d if number is
11487 not -1. If both are assumed, the %s is assumed to precede the %d. */
11488
11489#if FFECOM_targetCURRENT == FFECOM_targetGCC
11490tree
11491ffecom_get_invented_identifier (const char *pattern, const char *text,
11492 int number)
11493{
11494 tree decl;
11495 char *nam;
11496 mallocSize lenlen;
11497 char space[66];
11498
11499 lenlen = 0;
11500 if (text)
11501 lenlen += strlen (text);
11502 if (number != -1)
11503 lenlen += 20;
11504 if (text || number != -1)
11505 {
11506 lenlen += strlen (pattern);
11507 if (lenlen > ARRAY_SIZE (space))
11508 nam = malloc_new_ks (malloc_pool_image (), pattern, lenlen);
11509 else
11510 nam = &space[0];
11511 }
11512 else
11513 {
11514 lenlen = 0;
11515 nam = (char *) pattern;
11516 }
11517
11518 if (text == NULL)
11519 {
11520 if (number != -1)
11521 sprintf (&nam[0], pattern, number);
11522 }
11523 else
11524 {
11525 if (number == -1)
11526 sprintf (&nam[0], pattern, text);
11527 else
11528 sprintf (&nam[0], pattern, text, number);
11529 }
11530
11531 decl = get_identifier (nam);
11532
11533 if (lenlen > ARRAY_SIZE (space))
11534 malloc_kill_ks (malloc_pool_image (), nam, lenlen);
11535
11536 IDENTIFIER_INVENTED (decl) = 1;
11537
11538 return decl;
11539}
11540
11541ffeinfoBasictype
11542ffecom_gfrt_basictype (ffecomGfrt gfrt)
11543{
11544 assert (gfrt < FFECOM_gfrt);
11545
11546 switch (ffecom_gfrt_type_[gfrt])
11547 {
11548 case FFECOM_rttypeVOID_:
11549 case FFECOM_rttypeVOIDSTAR_:
11550 return FFEINFO_basictypeNONE;
11551
11552 case FFECOM_rttypeFTNINT_:
11553 return FFEINFO_basictypeINTEGER;
11554
11555 case FFECOM_rttypeINTEGER_:
11556 return FFEINFO_basictypeINTEGER;
11557
11558 case FFECOM_rttypeLONGINT_:
11559 return FFEINFO_basictypeINTEGER;
11560
11561 case FFECOM_rttypeLOGICAL_:
11562 return FFEINFO_basictypeLOGICAL;
11563
11564 case FFECOM_rttypeREAL_F2C_:
11565 case FFECOM_rttypeREAL_GNU_:
11566 return FFEINFO_basictypeREAL;
11567
11568 case FFECOM_rttypeCOMPLEX_F2C_:
11569 case FFECOM_rttypeCOMPLEX_GNU_:
11570 return FFEINFO_basictypeCOMPLEX;
11571
11572 case FFECOM_rttypeDOUBLE_:
11573 case FFECOM_rttypeDOUBLEREAL_:
11574 return FFEINFO_basictypeREAL;
11575
11576 case FFECOM_rttypeDBLCMPLX_F2C_:
11577 case FFECOM_rttypeDBLCMPLX_GNU_:
11578 return FFEINFO_basictypeCOMPLEX;
11579
11580 case FFECOM_rttypeCHARACTER_:
11581 return FFEINFO_basictypeCHARACTER;
11582
11583 default:
11584 return FFEINFO_basictypeANY;
11585 }
11586}
11587
11588ffeinfoKindtype
11589ffecom_gfrt_kindtype (ffecomGfrt gfrt)
11590{
11591 assert (gfrt < FFECOM_gfrt);
11592
11593 switch (ffecom_gfrt_type_[gfrt])
11594 {
11595 case FFECOM_rttypeVOID_:
11596 case FFECOM_rttypeVOIDSTAR_:
11597 return FFEINFO_kindtypeNONE;
5ff904cd 11598
c7e4ee3a
CB
11599 case FFECOM_rttypeFTNINT_:
11600 return FFEINFO_kindtypeINTEGER1;
5ff904cd 11601
c7e4ee3a
CB
11602 case FFECOM_rttypeINTEGER_:
11603 return FFEINFO_kindtypeINTEGER1;
5ff904cd 11604
c7e4ee3a
CB
11605 case FFECOM_rttypeLONGINT_:
11606 return FFEINFO_kindtypeINTEGER4;
5ff904cd 11607
c7e4ee3a
CB
11608 case FFECOM_rttypeLOGICAL_:
11609 return FFEINFO_kindtypeLOGICAL1;
5ff904cd 11610
c7e4ee3a
CB
11611 case FFECOM_rttypeREAL_F2C_:
11612 case FFECOM_rttypeREAL_GNU_:
11613 return FFEINFO_kindtypeREAL1;
5ff904cd 11614
c7e4ee3a
CB
11615 case FFECOM_rttypeCOMPLEX_F2C_:
11616 case FFECOM_rttypeCOMPLEX_GNU_:
11617 return FFEINFO_kindtypeREAL1;
5ff904cd 11618
c7e4ee3a
CB
11619 case FFECOM_rttypeDOUBLE_:
11620 case FFECOM_rttypeDOUBLEREAL_:
11621 return FFEINFO_kindtypeREAL2;
5ff904cd 11622
c7e4ee3a
CB
11623 case FFECOM_rttypeDBLCMPLX_F2C_:
11624 case FFECOM_rttypeDBLCMPLX_GNU_:
11625 return FFEINFO_kindtypeREAL2;
5ff904cd 11626
c7e4ee3a
CB
11627 case FFECOM_rttypeCHARACTER_:
11628 return FFEINFO_kindtypeCHARACTER1;
5ff904cd 11629
c7e4ee3a
CB
11630 default:
11631 return FFEINFO_kindtypeANY;
11632 }
11633}
5ff904cd 11634
c7e4ee3a
CB
11635void
11636ffecom_init_0 ()
11637{
11638 tree endlink;
11639 int i;
11640 int j;
11641 tree t;
11642 tree field;
11643 ffetype type;
11644 ffetype base_type;
5ff904cd 11645
c7e4ee3a
CB
11646 /* This block of code comes from the now-obsolete cktyps.c. It checks
11647 whether the compiler environment is buggy in known ways, some of which
11648 would, if not explicitly checked here, result in subtle bugs in g77. */
5ff904cd 11649
c7e4ee3a
CB
11650 if (ffe_is_do_internal_checks ())
11651 {
11652 static char names[][12]
11653 =
11654 {"bar", "bletch", "foo", "foobar"};
11655 char *name;
11656 unsigned long ul;
11657 double fl;
5ff904cd 11658
c7e4ee3a
CB
11659 name = bsearch ("foo", &names[0], ARRAY_SIZE (names), sizeof (names[0]),
11660 (int (*)()) strcmp);
11661 if (name != (char *) &names[2])
11662 {
11663 assert ("bsearch doesn't work, #define FFEPROJ_BSEARCH 0 in proj.h"
11664 == NULL);
11665 abort ();
11666 }
5ff904cd 11667
c7e4ee3a
CB
11668 ul = strtoul ("123456789", NULL, 10);
11669 if (ul != 123456789L)
11670 {
11671 assert ("strtoul doesn't have enough range, #define FFEPROJ_STRTOUL 0\
11672 in proj.h" == NULL);
11673 abort ();
11674 }
5ff904cd 11675
c7e4ee3a
CB
11676 fl = atof ("56.789");
11677 if ((fl < 56.788) || (fl > 56.79))
11678 {
11679 assert ("atof not type double, fix your #include <stdio.h>"
11680 == NULL);
11681 abort ();
11682 }
11683 }
5ff904cd 11684
c7e4ee3a
CB
11685#if FFECOM_GCC_INCLUDE
11686 ffecom_initialize_char_syntax_ ();
11687#endif
5ff904cd 11688
c7e4ee3a
CB
11689 ffecom_outer_function_decl_ = NULL_TREE;
11690 current_function_decl = NULL_TREE;
11691 named_labels = NULL_TREE;
11692 current_binding_level = NULL_BINDING_LEVEL;
11693 free_binding_level = NULL_BINDING_LEVEL;
11694 /* Make the binding_level structure for global names. */
11695 pushlevel (0);
11696 global_binding_level = current_binding_level;
11697 current_binding_level->prep_state = 2;
5ff904cd 11698
c7e4ee3a 11699 /* Define `int' and `char' first so that dbx will output them first. */
5ff904cd 11700
c7e4ee3a
CB
11701 integer_type_node = make_signed_type (INT_TYPE_SIZE);
11702 pushdecl (build_decl (TYPE_DECL, get_identifier ("int"),
11703 integer_type_node));
5ff904cd 11704
c7e4ee3a
CB
11705 char_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
11706 pushdecl (build_decl (TYPE_DECL, get_identifier ("char"),
11707 char_type_node));
5ff904cd 11708
c7e4ee3a
CB
11709 long_integer_type_node = make_signed_type (LONG_TYPE_SIZE);
11710 pushdecl (build_decl (TYPE_DECL, get_identifier ("long int"),
11711 long_integer_type_node));
5ff904cd 11712
c7e4ee3a
CB
11713 unsigned_type_node = make_unsigned_type (INT_TYPE_SIZE);
11714 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned int"),
11715 unsigned_type_node));
5ff904cd 11716
c7e4ee3a
CB
11717 long_unsigned_type_node = make_unsigned_type (LONG_TYPE_SIZE);
11718 pushdecl (build_decl (TYPE_DECL, get_identifier ("long unsigned int"),
11719 long_unsigned_type_node));
5ff904cd 11720
c7e4ee3a
CB
11721 long_long_integer_type_node = make_signed_type (LONG_LONG_TYPE_SIZE);
11722 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long int"),
11723 long_long_integer_type_node));
5ff904cd 11724
c7e4ee3a
CB
11725 long_long_unsigned_type_node = make_unsigned_type (LONG_LONG_TYPE_SIZE);
11726 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"),
11727 long_long_unsigned_type_node));
5ff904cd 11728
c7e4ee3a
CB
11729 short_integer_type_node = make_signed_type (SHORT_TYPE_SIZE);
11730 pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"),
11731 short_integer_type_node));
5ff904cd 11732
c7e4ee3a
CB
11733 short_unsigned_type_node = make_unsigned_type (SHORT_TYPE_SIZE);
11734 pushdecl (build_decl (TYPE_DECL, get_identifier ("short unsigned int"),
11735 short_unsigned_type_node));
5ff904cd 11736
ff852b44
CB
11737 /* Set the sizetype before we make other types. This *should* be the
11738 first type we create. */
11739
11740 set_sizetype
11741 (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))));
11742 ffecom_typesize_pointer_
11743 = TREE_INT_CST_LOW (TYPE_SIZE (sizetype)) / BITS_PER_UNIT;
11744
11745 error_mark_node = make_node (ERROR_MARK);
11746 TREE_TYPE (error_mark_node) = error_mark_node;
11747
c7e4ee3a
CB
11748 /* Define both `signed char' and `unsigned char'. */
11749 signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE);
11750 pushdecl (build_decl (TYPE_DECL, get_identifier ("signed char"),
11751 signed_char_type_node));
5ff904cd 11752
c7e4ee3a
CB
11753 unsigned_char_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
11754 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned char"),
11755 unsigned_char_type_node));
5ff904cd 11756
c7e4ee3a
CB
11757 float_type_node = make_node (REAL_TYPE);
11758 TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE;
11759 layout_type (float_type_node);
11760 pushdecl (build_decl (TYPE_DECL, get_identifier ("float"),
11761 float_type_node));
5ff904cd 11762
c7e4ee3a
CB
11763 double_type_node = make_node (REAL_TYPE);
11764 TYPE_PRECISION (double_type_node) = DOUBLE_TYPE_SIZE;
11765 layout_type (double_type_node);
11766 pushdecl (build_decl (TYPE_DECL, get_identifier ("double"),
11767 double_type_node));
5ff904cd 11768
c7e4ee3a
CB
11769 long_double_type_node = make_node (REAL_TYPE);
11770 TYPE_PRECISION (long_double_type_node) = LONG_DOUBLE_TYPE_SIZE;
11771 layout_type (long_double_type_node);
11772 pushdecl (build_decl (TYPE_DECL, get_identifier ("long double"),
11773 long_double_type_node));
5ff904cd 11774
c7e4ee3a
CB
11775 complex_integer_type_node = ffecom_make_complex_type_ (integer_type_node);
11776 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"),
11777 complex_integer_type_node));
5ff904cd 11778
c7e4ee3a
CB
11779 complex_float_type_node = ffecom_make_complex_type_ (float_type_node);
11780 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"),
11781 complex_float_type_node));
5ff904cd 11782
c7e4ee3a
CB
11783 complex_double_type_node = ffecom_make_complex_type_ (double_type_node);
11784 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"),
11785 complex_double_type_node));
5ff904cd 11786
c7e4ee3a
CB
11787 complex_long_double_type_node = ffecom_make_complex_type_ (long_double_type_node);
11788 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"),
11789 complex_long_double_type_node));
5ff904cd 11790
c7e4ee3a
CB
11791 integer_zero_node = build_int_2 (0, 0);
11792 TREE_TYPE (integer_zero_node) = integer_type_node;
11793 integer_one_node = build_int_2 (1, 0);
11794 TREE_TYPE (integer_one_node) = integer_type_node;
5ff904cd 11795
c7e4ee3a
CB
11796 size_zero_node = build_int_2 (0, 0);
11797 TREE_TYPE (size_zero_node) = sizetype;
11798 size_one_node = build_int_2 (1, 0);
11799 TREE_TYPE (size_one_node) = sizetype;
5ff904cd 11800
c7e4ee3a
CB
11801 void_type_node = make_node (VOID_TYPE);
11802 pushdecl (build_decl (TYPE_DECL, get_identifier ("void"),
11803 void_type_node));
11804 layout_type (void_type_node); /* Uses integer_zero_node */
11805 /* We are not going to have real types in C with less than byte alignment,
11806 so we might as well not have any types that claim to have it. */
11807 TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
5ff904cd 11808
c7e4ee3a
CB
11809 null_pointer_node = build_int_2 (0, 0);
11810 TREE_TYPE (null_pointer_node) = build_pointer_type (void_type_node);
11811 layout_type (TREE_TYPE (null_pointer_node));
5ff904cd 11812
c7e4ee3a 11813 string_type_node = build_pointer_type (char_type_node);
5ff904cd 11814
c7e4ee3a
CB
11815 ffecom_tree_fun_type_void
11816 = build_function_type (void_type_node, NULL_TREE);
5ff904cd 11817
c7e4ee3a
CB
11818 ffecom_tree_ptr_to_fun_type_void
11819 = build_pointer_type (ffecom_tree_fun_type_void);
5ff904cd 11820
c7e4ee3a 11821 endlink = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
5ff904cd 11822
c7e4ee3a
CB
11823 float_ftype_float
11824 = build_function_type (float_type_node,
11825 tree_cons (NULL_TREE, float_type_node, endlink));
5ff904cd 11826
c7e4ee3a
CB
11827 double_ftype_double
11828 = build_function_type (double_type_node,
11829 tree_cons (NULL_TREE, double_type_node, endlink));
5ff904cd 11830
c7e4ee3a
CB
11831 ldouble_ftype_ldouble
11832 = build_function_type (long_double_type_node,
11833 tree_cons (NULL_TREE, long_double_type_node,
11834 endlink));
5ff904cd 11835
c7e4ee3a
CB
11836 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11837 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11838 {
11839 ffecom_tree_type[i][j] = NULL_TREE;
11840 ffecom_tree_fun_type[i][j] = NULL_TREE;
11841 ffecom_tree_ptr_to_fun_type[i][j] = NULL_TREE;
11842 ffecom_f2c_typecode_[i][j] = -1;
11843 }
5ff904cd 11844
c7e4ee3a
CB
11845 /* Set up standard g77 types. Note that INTEGER and LOGICAL are set
11846 to size FLOAT_TYPE_SIZE because they have to be the same size as
11847 REAL, which also is FLOAT_TYPE_SIZE, according to the standard.
11848 Compiler options and other such stuff that change the ways these
11849 types are set should not affect this particular setup. */
5ff904cd 11850
c7e4ee3a
CB
11851 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1]
11852 = t = make_signed_type (FLOAT_TYPE_SIZE);
11853 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer"),
11854 t));
11855 type = ffetype_new ();
11856 base_type = type;
11857 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER1,
11858 type);
11859 ffetype_set_ams (type,
11860 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11861 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11862 ffetype_set_star (base_type,
11863 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11864 type);
11865 ffetype_set_kind (base_type, 1, type);
ff852b44 11866 ffecom_typesize_integer1_ = ffetype_size (type);
c7e4ee3a 11867 assert (ffetype_size (type) == sizeof (ffetargetInteger1));
5ff904cd 11868
c7e4ee3a
CB
11869 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER1]
11870 = t = make_unsigned_type (FLOAT_TYPE_SIZE); /* HOLLERITH means unsigned. */
11871 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned"),
11872 t));
5ff904cd 11873
c7e4ee3a
CB
11874 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER2]
11875 = t = make_signed_type (CHAR_TYPE_SIZE);
11876 pushdecl (build_decl (TYPE_DECL, get_identifier ("byte"),
11877 t));
11878 type = ffetype_new ();
11879 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER2,
11880 type);
11881 ffetype_set_ams (type,
11882 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11883 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11884 ffetype_set_star (base_type,
11885 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11886 type);
11887 ffetype_set_kind (base_type, 3, type);
11888 assert (ffetype_size (type) == sizeof (ffetargetInteger2));
5ff904cd 11889
c7e4ee3a
CB
11890 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER2]
11891 = t = make_unsigned_type (CHAR_TYPE_SIZE);
11892 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned byte"),
11893 t));
11894
11895 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER3]
11896 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11897 pushdecl (build_decl (TYPE_DECL, get_identifier ("word"),
11898 t));
11899 type = ffetype_new ();
11900 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER3,
11901 type);
11902 ffetype_set_ams (type,
11903 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11904 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11905 ffetype_set_star (base_type,
11906 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11907 type);
11908 ffetype_set_kind (base_type, 6, type);
11909 assert (ffetype_size (type) == sizeof (ffetargetInteger3));
5ff904cd 11910
c7e4ee3a
CB
11911 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER3]
11912 = t = make_unsigned_type (CHAR_TYPE_SIZE * 2);
11913 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned word"),
11914 t));
5ff904cd 11915
c7e4ee3a
CB
11916 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER4]
11917 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11918 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer4"),
11919 t));
11920 type = ffetype_new ();
11921 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER4,
11922 type);
11923 ffetype_set_ams (type,
11924 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11925 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11926 ffetype_set_star (base_type,
11927 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11928 type);
11929 ffetype_set_kind (base_type, 2, type);
11930 assert (ffetype_size (type) == sizeof (ffetargetInteger4));
5ff904cd 11931
c7e4ee3a
CB
11932 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER4]
11933 = t = make_unsigned_type (FLOAT_TYPE_SIZE * 2);
11934 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned4"),
11935 t));
5ff904cd 11936
c7e4ee3a
CB
11937#if 0
11938 if (ffe_is_do_internal_checks ()
11939 && LONG_TYPE_SIZE != FLOAT_TYPE_SIZE
11940 && LONG_TYPE_SIZE != CHAR_TYPE_SIZE
11941 && LONG_TYPE_SIZE != SHORT_TYPE_SIZE
11942 && LONG_TYPE_SIZE != LONG_LONG_TYPE_SIZE)
5ff904cd 11943 {
c7e4ee3a
CB
11944 fprintf (stderr, "Sorry, no g77 support for LONG_TYPE_SIZE (%d bits) yet.\n",
11945 LONG_TYPE_SIZE);
5ff904cd 11946 }
c7e4ee3a 11947#endif
5ff904cd 11948
c7e4ee3a
CB
11949 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL1]
11950 = t = make_signed_type (FLOAT_TYPE_SIZE);
11951 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical"),
11952 t));
11953 type = ffetype_new ();
11954 base_type = type;
11955 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL1,
11956 type);
11957 ffetype_set_ams (type,
11958 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11959 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11960 ffetype_set_star (base_type,
11961 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11962 type);
11963 ffetype_set_kind (base_type, 1, type);
11964 assert (ffetype_size (type) == sizeof (ffetargetLogical1));
5ff904cd 11965
c7e4ee3a
CB
11966 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL2]
11967 = t = make_signed_type (CHAR_TYPE_SIZE);
11968 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical2"),
11969 t));
11970 type = ffetype_new ();
11971 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL2,
11972 type);
11973 ffetype_set_ams (type,
11974 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11975 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11976 ffetype_set_star (base_type,
11977 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11978 type);
11979 ffetype_set_kind (base_type, 3, type);
11980 assert (ffetype_size (type) == sizeof (ffetargetLogical2));
5ff904cd 11981
c7e4ee3a
CB
11982 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL3]
11983 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11984 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical3"),
11985 t));
11986 type = ffetype_new ();
11987 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL3,
11988 type);
11989 ffetype_set_ams (type,
11990 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11991 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11992 ffetype_set_star (base_type,
11993 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11994 type);
11995 ffetype_set_kind (base_type, 6, type);
11996 assert (ffetype_size (type) == sizeof (ffetargetLogical3));
5ff904cd 11997
c7e4ee3a
CB
11998 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL4]
11999 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
12000 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical4"),
12001 t));
12002 type = ffetype_new ();
12003 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL4,
12004 type);
12005 ffetype_set_ams (type,
12006 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12007 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12008 ffetype_set_star (base_type,
12009 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12010 type);
12011 ffetype_set_kind (base_type, 2, type);
12012 assert (ffetype_size (type) == sizeof (ffetargetLogical4));
5ff904cd 12013
c7e4ee3a
CB
12014 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
12015 = t = make_node (REAL_TYPE);
12016 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE;
12017 pushdecl (build_decl (TYPE_DECL, get_identifier ("real"),
12018 t));
12019 layout_type (t);
12020 type = ffetype_new ();
12021 base_type = type;
12022 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREAL1,
12023 type);
12024 ffetype_set_ams (type,
12025 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12026 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12027 ffetype_set_star (base_type,
12028 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12029 type);
12030 ffetype_set_kind (base_type, 1, type);
12031 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
12032 = FFETARGET_f2cTYREAL;
12033 assert (ffetype_size (type) == sizeof (ffetargetReal1));
5ff904cd 12034
c7e4ee3a
CB
12035 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREALDOUBLE]
12036 = t = make_node (REAL_TYPE);
12037 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE * 2; /* Always twice REAL. */
12038 pushdecl (build_decl (TYPE_DECL, get_identifier ("double precision"),
12039 t));
12040 layout_type (t);
12041 type = ffetype_new ();
12042 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREALDOUBLE,
12043 type);
12044 ffetype_set_ams (type,
12045 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12046 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12047 ffetype_set_star (base_type,
12048 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12049 type);
12050 ffetype_set_kind (base_type, 2, type);
12051 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]
12052 = FFETARGET_f2cTYDREAL;
12053 assert (ffetype_size (type) == sizeof (ffetargetReal2));
5ff904cd 12054
c7e4ee3a
CB
12055 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
12056 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]);
12057 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex"),
12058 t));
12059 type = ffetype_new ();
12060 base_type = type;
12061 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREAL1,
12062 type);
12063 ffetype_set_ams (type,
12064 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12065 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12066 ffetype_set_star (base_type,
12067 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12068 type);
12069 ffetype_set_kind (base_type, 1, type);
12070 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
12071 = FFETARGET_f2cTYCOMPLEX;
12072 assert (ffetype_size (type) == sizeof (ffetargetComplex1));
5ff904cd 12073
c7e4ee3a
CB
12074 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREALDOUBLE]
12075 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]);
12076 pushdecl (build_decl (TYPE_DECL, get_identifier ("double complex"),
12077 t));
12078 type = ffetype_new ();
12079 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREALDOUBLE,
12080 type);
12081 ffetype_set_ams (type,
12082 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12083 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12084 ffetype_set_star (base_type,
12085 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12086 type);
12087 ffetype_set_kind (base_type, 2,
12088 type);
12089 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL2]
12090 = FFETARGET_f2cTYDCOMPLEX;
12091 assert (ffetype_size (type) == sizeof (ffetargetComplex2));
5ff904cd 12092
c7e4ee3a 12093 /* Make function and ptr-to-function types for non-CHARACTER types. */
5ff904cd 12094
c7e4ee3a
CB
12095 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
12096 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
12097 {
12098 if ((t = ffecom_tree_type[i][j]) != NULL_TREE)
12099 {
12100 if (i == FFEINFO_basictypeINTEGER)
12101 {
12102 /* Figure out the smallest INTEGER type that can hold
12103 a pointer on this machine. */
12104 if (GET_MODE_SIZE (TYPE_MODE (t))
12105 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
12106 {
12107 if ((ffecom_pointer_kind_ == FFEINFO_kindtypeNONE)
12108 || (GET_MODE_SIZE (TYPE_MODE (ffecom_tree_type[i][ffecom_pointer_kind_]))
12109 > GET_MODE_SIZE (TYPE_MODE (t))))
12110 ffecom_pointer_kind_ = j;
12111 }
12112 }
12113 else if (i == FFEINFO_basictypeCOMPLEX)
12114 t = void_type_node;
12115 /* For f2c compatibility, REAL functions are really
12116 implemented as DOUBLE PRECISION. */
12117 else if ((i == FFEINFO_basictypeREAL)
12118 && (j == FFEINFO_kindtypeREAL1))
12119 t = ffecom_tree_type
12120 [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2];
5ff904cd 12121
c7e4ee3a
CB
12122 t = ffecom_tree_fun_type[i][j] = build_function_type (t,
12123 NULL_TREE);
12124 ffecom_tree_ptr_to_fun_type[i][j] = build_pointer_type (t);
12125 }
12126 }
5ff904cd 12127
c7e4ee3a 12128 /* Set up pointer types. */
5ff904cd 12129
c7e4ee3a
CB
12130 if (ffecom_pointer_kind_ == FFEINFO_basictypeNONE)
12131 fatal ("no INTEGER type can hold a pointer on this configuration");
12132 else if (0 && ffe_is_do_internal_checks ())
12133 fprintf (stderr, "Pointer type kt=%d\n", ffecom_pointer_kind_);
12134 ffetype_set_kind (ffeinfo_type (FFEINFO_basictypeINTEGER,
12135 FFEINFO_kindtypeINTEGERDEFAULT),
12136 7,
12137 ffeinfo_type (FFEINFO_basictypeINTEGER,
12138 ffecom_pointer_kind_));
5ff904cd 12139
c7e4ee3a
CB
12140 if (ffe_is_ugly_assign ())
12141 ffecom_label_kind_ = ffecom_pointer_kind_; /* Require ASSIGN etc to this. */
12142 else
12143 ffecom_label_kind_ = FFEINFO_kindtypeINTEGERDEFAULT;
12144 if (0 && ffe_is_do_internal_checks ())
12145 fprintf (stderr, "Label type kt=%d\n", ffecom_label_kind_);
5ff904cd 12146
c7e4ee3a
CB
12147 ffecom_integer_type_node
12148 = ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1];
12149 ffecom_integer_zero_node = convert (ffecom_integer_type_node,
12150 integer_zero_node);
12151 ffecom_integer_one_node = convert (ffecom_integer_type_node,
12152 integer_one_node);
5ff904cd 12153
c7e4ee3a
CB
12154 /* Yes, the "FLOAT_TYPE_SIZE" references below are intentional.
12155 Turns out that by TYLONG, runtime/libI77/lio.h really means
12156 "whatever size an ftnint is". For consistency and sanity,
12157 com.h and runtime/f2c.h.in agree that flag, ftnint, and ftlen
12158 all are INTEGER, which we also make out of whatever back-end
12159 integer type is FLOAT_TYPE_SIZE bits wide. This change, from
12160 LONG_TYPE_SIZE, for TYLONG and TYLOGICAL, was necessary to
12161 accommodate machines like the Alpha. Note that this suggests
12162 f2c and libf2c are missing a distinction perhaps needed on
12163 some machines between "int" and "long int". -- burley 0.5.5 950215 */
5ff904cd 12164
c7e4ee3a
CB
12165 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, FLOAT_TYPE_SIZE,
12166 FFETARGET_f2cTYLONG);
12167 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, SHORT_TYPE_SIZE,
12168 FFETARGET_f2cTYSHORT);
12169 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, CHAR_TYPE_SIZE,
12170 FFETARGET_f2cTYINT1);
12171 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, LONG_LONG_TYPE_SIZE,
12172 FFETARGET_f2cTYQUAD);
12173 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, FLOAT_TYPE_SIZE,
12174 FFETARGET_f2cTYLOGICAL);
12175 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, SHORT_TYPE_SIZE,
12176 FFETARGET_f2cTYLOGICAL2);
12177 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, CHAR_TYPE_SIZE,
12178 FFETARGET_f2cTYLOGICAL1);
12179 /* ~~~Not really such a type in libf2c, e.g. I/O support? */
12180 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, LONG_LONG_TYPE_SIZE,
12181 FFETARGET_f2cTYQUAD);
5ff904cd 12182
c7e4ee3a
CB
12183 /* CHARACTER stuff is all special-cased, so it is not handled in the above
12184 loop. CHARACTER items are built as arrays of unsigned char. */
5ff904cd 12185
c7e4ee3a
CB
12186 ffecom_tree_type[FFEINFO_basictypeCHARACTER]
12187 [FFEINFO_kindtypeCHARACTER1] = t = char_type_node;
12188 type = ffetype_new ();
12189 base_type = type;
12190 ffeinfo_set_type (FFEINFO_basictypeCHARACTER,
12191 FFEINFO_kindtypeCHARACTER1,
12192 type);
12193 ffetype_set_ams (type,
12194 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12195 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12196 ffetype_set_kind (base_type, 1, type);
12197 assert (ffetype_size (type)
12198 == sizeof (((ffetargetCharacter1) { 0, NULL }).text[0]));
5ff904cd 12199
c7e4ee3a
CB
12200 ffecom_tree_fun_type[FFEINFO_basictypeCHARACTER]
12201 [FFEINFO_kindtypeCHARACTER1] = ffecom_tree_fun_type_void;
12202 ffecom_tree_ptr_to_fun_type[FFEINFO_basictypeCHARACTER]
12203 [FFEINFO_kindtypeCHARACTER1]
12204 = ffecom_tree_ptr_to_fun_type_void;
12205 ffecom_f2c_typecode_[FFEINFO_basictypeCHARACTER][FFEINFO_kindtypeCHARACTER1]
12206 = FFETARGET_f2cTYCHAR;
5ff904cd 12207
c7e4ee3a
CB
12208 ffecom_f2c_typecode_[FFEINFO_basictypeANY][FFEINFO_kindtypeANY]
12209 = 0;
5ff904cd 12210
c7e4ee3a 12211 /* Make multi-return-value type and fields. */
5ff904cd 12212
c7e4ee3a 12213 ffecom_multi_type_node_ = make_node (UNION_TYPE);
5ff904cd 12214
c7e4ee3a 12215 field = NULL_TREE;
5ff904cd 12216
c7e4ee3a
CB
12217 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
12218 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
12219 {
12220 char name[30];
5ff904cd 12221
c7e4ee3a
CB
12222 if (ffecom_tree_type[i][j] == NULL_TREE)
12223 continue; /* Not supported. */
12224 sprintf (&name[0], "bt_%s_kt_%s",
12225 ffeinfo_basictype_string ((ffeinfoBasictype) i),
12226 ffeinfo_kindtype_string ((ffeinfoKindtype) j));
12227 ffecom_multi_fields_[i][j] = build_decl (FIELD_DECL,
12228 get_identifier (name),
12229 ffecom_tree_type[i][j]);
12230 DECL_CONTEXT (ffecom_multi_fields_[i][j])
12231 = ffecom_multi_type_node_;
12232 DECL_FRAME_SIZE (ffecom_multi_fields_[i][j]) = 0;
12233 TREE_CHAIN (ffecom_multi_fields_[i][j]) = field;
12234 field = ffecom_multi_fields_[i][j];
12235 }
5ff904cd 12236
c7e4ee3a
CB
12237 TYPE_FIELDS (ffecom_multi_type_node_) = field;
12238 layout_type (ffecom_multi_type_node_);
5ff904cd 12239
c7e4ee3a
CB
12240 /* Subroutines usually return integer because they might have alternate
12241 returns. */
5ff904cd 12242
c7e4ee3a
CB
12243 ffecom_tree_subr_type
12244 = build_function_type (integer_type_node, NULL_TREE);
12245 ffecom_tree_ptr_to_subr_type
12246 = build_pointer_type (ffecom_tree_subr_type);
12247 ffecom_tree_blockdata_type
12248 = build_function_type (void_type_node, NULL_TREE);
5ff904cd 12249
c7e4ee3a
CB
12250 builtin_function ("__builtin_sqrtf", float_ftype_float,
12251 BUILT_IN_FSQRT, "sqrtf");
12252 builtin_function ("__builtin_fsqrt", double_ftype_double,
12253 BUILT_IN_FSQRT, "sqrt");
12254 builtin_function ("__builtin_sqrtl", ldouble_ftype_ldouble,
12255 BUILT_IN_FSQRT, "sqrtl");
12256 builtin_function ("__builtin_sinf", float_ftype_float,
12257 BUILT_IN_SIN, "sinf");
12258 builtin_function ("__builtin_sin", double_ftype_double,
12259 BUILT_IN_SIN, "sin");
12260 builtin_function ("__builtin_sinl", ldouble_ftype_ldouble,
12261 BUILT_IN_SIN, "sinl");
12262 builtin_function ("__builtin_cosf", float_ftype_float,
12263 BUILT_IN_COS, "cosf");
12264 builtin_function ("__builtin_cos", double_ftype_double,
12265 BUILT_IN_COS, "cos");
12266 builtin_function ("__builtin_cosl", ldouble_ftype_ldouble,
12267 BUILT_IN_COS, "cosl");
5ff904cd 12268
c7e4ee3a
CB
12269#if BUILT_FOR_270
12270 pedantic_lvalues = FALSE;
5ff904cd 12271#endif
5ff904cd 12272
c7e4ee3a
CB
12273 ffecom_f2c_make_type_ (&ffecom_f2c_integer_type_node,
12274 FFECOM_f2cINTEGER,
12275 "integer");
12276 ffecom_f2c_make_type_ (&ffecom_f2c_address_type_node,
12277 FFECOM_f2cADDRESS,
12278 "address");
12279 ffecom_f2c_make_type_ (&ffecom_f2c_real_type_node,
12280 FFECOM_f2cREAL,
12281 "real");
12282 ffecom_f2c_make_type_ (&ffecom_f2c_doublereal_type_node,
12283 FFECOM_f2cDOUBLEREAL,
12284 "doublereal");
12285 ffecom_f2c_make_type_ (&ffecom_f2c_complex_type_node,
12286 FFECOM_f2cCOMPLEX,
12287 "complex");
12288 ffecom_f2c_make_type_ (&ffecom_f2c_doublecomplex_type_node,
12289 FFECOM_f2cDOUBLECOMPLEX,
12290 "doublecomplex");
12291 ffecom_f2c_make_type_ (&ffecom_f2c_longint_type_node,
12292 FFECOM_f2cLONGINT,
12293 "longint");
12294 ffecom_f2c_make_type_ (&ffecom_f2c_logical_type_node,
12295 FFECOM_f2cLOGICAL,
12296 "logical");
12297 ffecom_f2c_make_type_ (&ffecom_f2c_flag_type_node,
12298 FFECOM_f2cFLAG,
12299 "flag");
12300 ffecom_f2c_make_type_ (&ffecom_f2c_ftnlen_type_node,
12301 FFECOM_f2cFTNLEN,
12302 "ftnlen");
12303 ffecom_f2c_make_type_ (&ffecom_f2c_ftnint_type_node,
12304 FFECOM_f2cFTNINT,
12305 "ftnint");
5ff904cd 12306
c7e4ee3a
CB
12307 ffecom_f2c_ftnlen_zero_node
12308 = convert (ffecom_f2c_ftnlen_type_node, integer_zero_node);
5ff904cd 12309
c7e4ee3a
CB
12310 ffecom_f2c_ftnlen_one_node
12311 = convert (ffecom_f2c_ftnlen_type_node, integer_one_node);
5ff904cd 12312
c7e4ee3a
CB
12313 ffecom_f2c_ftnlen_two_node = build_int_2 (2, 0);
12314 TREE_TYPE (ffecom_f2c_ftnlen_two_node) = ffecom_integer_type_node;
5ff904cd 12315
c7e4ee3a
CB
12316 ffecom_f2c_ptr_to_ftnlen_type_node
12317 = build_pointer_type (ffecom_f2c_ftnlen_type_node);
5ff904cd 12318
c7e4ee3a
CB
12319 ffecom_f2c_ptr_to_ftnint_type_node
12320 = build_pointer_type (ffecom_f2c_ftnint_type_node);
5ff904cd 12321
c7e4ee3a
CB
12322 ffecom_f2c_ptr_to_integer_type_node
12323 = build_pointer_type (ffecom_f2c_integer_type_node);
5ff904cd 12324
c7e4ee3a
CB
12325 ffecom_f2c_ptr_to_real_type_node
12326 = build_pointer_type (ffecom_f2c_real_type_node);
5ff904cd 12327
c7e4ee3a
CB
12328 ffecom_float_zero_ = build_real (float_type_node, dconst0);
12329 ffecom_double_zero_ = build_real (double_type_node, dconst0);
12330 {
12331 REAL_VALUE_TYPE point_5;
5ff904cd 12332
c7e4ee3a
CB
12333#ifdef REAL_ARITHMETIC
12334 REAL_ARITHMETIC (point_5, RDIV_EXPR, dconst1, dconst2);
12335#else
12336 point_5 = .5;
12337#endif
12338 ffecom_float_half_ = build_real (float_type_node, point_5);
12339 ffecom_double_half_ = build_real (double_type_node, point_5);
12340 }
5ff904cd 12341
c7e4ee3a 12342 /* Do "extern int xargc;". */
5ff904cd 12343
c7e4ee3a
CB
12344 ffecom_tree_xargc_ = build_decl (VAR_DECL,
12345 get_identifier ("f__xargc"),
12346 integer_type_node);
12347 DECL_EXTERNAL (ffecom_tree_xargc_) = 1;
12348 TREE_STATIC (ffecom_tree_xargc_) = 1;
12349 TREE_PUBLIC (ffecom_tree_xargc_) = 1;
12350 ffecom_tree_xargc_ = start_decl (ffecom_tree_xargc_, FALSE);
12351 finish_decl (ffecom_tree_xargc_, NULL_TREE, FALSE);
5ff904cd 12352
c7e4ee3a
CB
12353#if 0 /* This is being fixed, and seems to be working now. */
12354 if ((FLOAT_TYPE_SIZE != 32)
12355 || (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))) != 32))
5ff904cd 12356 {
c7e4ee3a
CB
12357 warning ("configuration: REAL, INTEGER, and LOGICAL are %d bits wide,",
12358 (int) FLOAT_TYPE_SIZE);
12359 warning ("and pointers are %d bits wide, but g77 doesn't yet work",
12360 (int) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))));
12361 warning ("properly unless they all are 32 bits wide.");
12362 warning ("Please keep this in mind before you report bugs. g77 should");
12363 warning ("support non-32-bit machines better as of version 0.6.");
12364 }
12365#endif
5ff904cd 12366
c7e4ee3a
CB
12367#if 0 /* Code in ste.c that would crash has been commented out. */
12368 if (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
12369 < TYPE_PRECISION (string_type_node))
12370 /* I/O will probably crash. */
12371 warning ("configuration: char * holds %d bits, but ftnlen only %d",
12372 TYPE_PRECISION (string_type_node),
12373 TYPE_PRECISION (ffecom_f2c_ftnlen_type_node));
12374#endif
5ff904cd 12375
c7e4ee3a
CB
12376#if 0 /* ASSIGN-related stuff has been changed to accommodate this. */
12377 if (TYPE_PRECISION (ffecom_integer_type_node)
12378 < TYPE_PRECISION (string_type_node))
12379 /* ASSIGN 10 TO I will crash. */
12380 warning ("configuration: char * holds %d bits, but INTEGER only %d --\n\
12381 ASSIGN statement might fail",
12382 TYPE_PRECISION (string_type_node),
12383 TYPE_PRECISION (ffecom_integer_type_node));
12384#endif
12385}
5ff904cd 12386
c7e4ee3a
CB
12387#endif
12388/* ffecom_init_2 -- Initialize
5ff904cd 12389
c7e4ee3a 12390 ffecom_init_2(); */
5ff904cd 12391
c7e4ee3a
CB
12392#if FFECOM_targetCURRENT == FFECOM_targetGCC
12393void
12394ffecom_init_2 ()
12395{
12396 assert (ffecom_outer_function_decl_ == NULL_TREE);
12397 assert (current_function_decl == NULL_TREE);
12398 assert (ffecom_which_entrypoint_decl_ == NULL_TREE);
5ff904cd 12399
c7e4ee3a
CB
12400 ffecom_master_arglist_ = NULL;
12401 ++ffecom_num_fns_;
12402 ffecom_primary_entry_ = NULL;
12403 ffecom_is_altreturning_ = FALSE;
12404 ffecom_func_result_ = NULL_TREE;
12405 ffecom_multi_retval_ = NULL_TREE;
12406}
5ff904cd 12407
c7e4ee3a
CB
12408#endif
12409/* ffecom_list_expr -- Transform list of exprs into gcc tree
5ff904cd 12410
c7e4ee3a
CB
12411 tree t;
12412 ffebld expr; // FFE opITEM list.
12413 tree = ffecom_list_expr(expr);
5ff904cd 12414
c7e4ee3a 12415 List of actual args is transformed into corresponding gcc backend list. */
5ff904cd 12416
c7e4ee3a
CB
12417#if FFECOM_targetCURRENT == FFECOM_targetGCC
12418tree
12419ffecom_list_expr (ffebld expr)
5ff904cd 12420{
c7e4ee3a
CB
12421 tree list;
12422 tree *plist = &list;
12423 tree trail = NULL_TREE; /* Append char length args here. */
12424 tree *ptrail = &trail;
12425 tree length;
5ff904cd 12426
c7e4ee3a 12427 while (expr != NULL)
5ff904cd 12428 {
c7e4ee3a 12429 tree texpr = ffecom_arg_expr (ffebld_head (expr), &length);
5ff904cd 12430
c7e4ee3a
CB
12431 if (texpr == error_mark_node)
12432 return error_mark_node;
5ff904cd 12433
c7e4ee3a
CB
12434 *plist = build_tree_list (NULL_TREE, texpr);
12435 plist = &TREE_CHAIN (*plist);
12436 expr = ffebld_trail (expr);
12437 if (length != NULL_TREE)
5ff904cd 12438 {
c7e4ee3a
CB
12439 *ptrail = build_tree_list (NULL_TREE, length);
12440 ptrail = &TREE_CHAIN (*ptrail);
5ff904cd
JL
12441 }
12442 }
12443
c7e4ee3a 12444 *plist = trail;
5ff904cd 12445
c7e4ee3a
CB
12446 return list;
12447}
5ff904cd 12448
c7e4ee3a
CB
12449#endif
12450/* ffecom_list_ptr_to_expr -- Transform list of exprs into gcc tree
5ff904cd 12451
c7e4ee3a
CB
12452 tree t;
12453 ffebld expr; // FFE opITEM list.
12454 tree = ffecom_list_ptr_to_expr(expr);
5ff904cd 12455
c7e4ee3a
CB
12456 List of actual args is transformed into corresponding gcc backend list for
12457 use in calling an external procedure (vs. a statement function). */
5ff904cd 12458
c7e4ee3a
CB
12459#if FFECOM_targetCURRENT == FFECOM_targetGCC
12460tree
12461ffecom_list_ptr_to_expr (ffebld expr)
12462{
12463 tree list;
12464 tree *plist = &list;
12465 tree trail = NULL_TREE; /* Append char length args here. */
12466 tree *ptrail = &trail;
12467 tree length;
5ff904cd 12468
c7e4ee3a
CB
12469 while (expr != NULL)
12470 {
12471 tree texpr = ffecom_arg_ptr_to_expr (ffebld_head (expr), &length);
5ff904cd 12472
c7e4ee3a
CB
12473 if (texpr == error_mark_node)
12474 return error_mark_node;
5ff904cd 12475
c7e4ee3a
CB
12476 *plist = build_tree_list (NULL_TREE, texpr);
12477 plist = &TREE_CHAIN (*plist);
12478 expr = ffebld_trail (expr);
12479 if (length != NULL_TREE)
12480 {
12481 *ptrail = build_tree_list (NULL_TREE, length);
12482 ptrail = &TREE_CHAIN (*ptrail);
12483 }
12484 }
5ff904cd 12485
c7e4ee3a 12486 *plist = trail;
5ff904cd 12487
c7e4ee3a
CB
12488 return list;
12489}
5ff904cd 12490
c7e4ee3a
CB
12491#endif
12492/* Obtain gcc's LABEL_DECL tree for label. */
5ff904cd 12493
c7e4ee3a
CB
12494#if FFECOM_targetCURRENT == FFECOM_targetGCC
12495tree
12496ffecom_lookup_label (ffelab label)
12497{
12498 tree glabel;
5ff904cd 12499
c7e4ee3a
CB
12500 if (ffelab_hook (label) == NULL_TREE)
12501 {
12502 char labelname[16];
5ff904cd 12503
c7e4ee3a
CB
12504 switch (ffelab_type (label))
12505 {
12506 case FFELAB_typeLOOPEND:
12507 case FFELAB_typeNOTLOOP:
12508 case FFELAB_typeENDIF:
12509 sprintf (labelname, "%" ffelabValue_f "u", ffelab_value (label));
12510 glabel = build_decl (LABEL_DECL, get_identifier (labelname),
12511 void_type_node);
12512 DECL_CONTEXT (glabel) = current_function_decl;
12513 DECL_MODE (glabel) = VOIDmode;
12514 break;
5ff904cd 12515
c7e4ee3a
CB
12516 case FFELAB_typeFORMAT:
12517 push_obstacks_nochange ();
12518 end_temporary_allocation ();
5ff904cd 12519
c7e4ee3a
CB
12520 glabel = build_decl (VAR_DECL,
12521 ffecom_get_invented_identifier
12522 ("__g77_format_%d", NULL,
12523 (int) ffelab_value (label)),
12524 build_type_variant (build_array_type
12525 (char_type_node,
12526 NULL_TREE),
12527 1, 0));
12528 TREE_CONSTANT (glabel) = 1;
12529 TREE_STATIC (glabel) = 1;
12530 DECL_CONTEXT (glabel) = 0;
12531 DECL_INITIAL (glabel) = NULL;
12532 make_decl_rtl (glabel, NULL, 0);
12533 expand_decl (glabel);
5ff904cd 12534
c7e4ee3a
CB
12535 resume_temporary_allocation ();
12536 pop_obstacks ();
5ff904cd 12537
c7e4ee3a 12538 break;
5ff904cd 12539
c7e4ee3a
CB
12540 case FFELAB_typeANY:
12541 glabel = error_mark_node;
12542 break;
5ff904cd 12543
c7e4ee3a
CB
12544 default:
12545 assert ("bad label type" == NULL);
12546 glabel = NULL;
12547 break;
12548 }
12549 ffelab_set_hook (label, glabel);
12550 }
12551 else
12552 {
12553 glabel = ffelab_hook (label);
12554 }
5ff904cd 12555
c7e4ee3a
CB
12556 return glabel;
12557}
5ff904cd 12558
c7e4ee3a
CB
12559#endif
12560/* Stabilizes the arguments. Don't use this if the lhs and rhs come from
12561 a single source specification (as in the fourth argument of MVBITS).
12562 If the type is NULL_TREE, the type of lhs is used to make the type of
12563 the MODIFY_EXPR. */
5ff904cd 12564
c7e4ee3a
CB
12565#if FFECOM_targetCURRENT == FFECOM_targetGCC
12566tree
12567ffecom_modify (tree newtype, tree lhs,
12568 tree rhs)
12569{
12570 if (lhs == error_mark_node || rhs == error_mark_node)
12571 return error_mark_node;
5ff904cd 12572
c7e4ee3a
CB
12573 if (newtype == NULL_TREE)
12574 newtype = TREE_TYPE (lhs);
5ff904cd 12575
c7e4ee3a
CB
12576 if (TREE_SIDE_EFFECTS (lhs))
12577 lhs = stabilize_reference (lhs);
5ff904cd 12578
c7e4ee3a
CB
12579 return ffecom_2s (MODIFY_EXPR, newtype, lhs, rhs);
12580}
5ff904cd 12581
c7e4ee3a 12582#endif
5ff904cd 12583
c7e4ee3a 12584/* Register source file name. */
5ff904cd 12585
c7e4ee3a
CB
12586void
12587ffecom_file (char *name)
12588{
12589#if FFECOM_GCC_INCLUDE
12590 ffecom_file_ (name);
12591#endif
12592}
5ff904cd 12593
c7e4ee3a 12594/* ffecom_notify_init_storage -- An aggregate storage is now fully init'ed
5ff904cd 12595
c7e4ee3a
CB
12596 ffestorag st;
12597 ffecom_notify_init_storage(st);
5ff904cd 12598
c7e4ee3a
CB
12599 Gets called when all possible units in an aggregate storage area (a LOCAL
12600 with equivalences or a COMMON) have been initialized. The initialization
12601 info either is in ffestorag_init or, if that is NULL,
12602 ffestorag_accretion:
5ff904cd 12603
c7e4ee3a
CB
12604 ffestorag_init may contain an opCONTER or opARRTER. opCONTER may occur
12605 even for an array if the array is one element in length!
5ff904cd 12606
c7e4ee3a
CB
12607 ffestorag_accretion will contain an opACCTER. It is much like an
12608 opARRTER except it has an ffebit object in it instead of just a size.
12609 The back end can use the info in the ffebit object, if it wants, to
12610 reduce the amount of actual initialization, but in any case it should
12611 kill the ffebit object when done. Also, set accretion to NULL but
12612 init to a non-NULL value.
5ff904cd 12613
c7e4ee3a
CB
12614 After performing initialization, DO NOT set init to NULL, because that'll
12615 tell the front end it is ok for more initialization to happen. Instead,
12616 set init to an opANY expression or some such thing that you can use to
12617 tell that you've already initialized the object.
5ff904cd 12618
c7e4ee3a
CB
12619 27-Oct-91 JCB 1.1
12620 Support two-pass FFE. */
5ff904cd 12621
c7e4ee3a
CB
12622void
12623ffecom_notify_init_storage (ffestorag st)
12624{
12625 ffebld init; /* The initialization expression. */
12626#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12627 ffetargetOffset size; /* The size of the entity. */
12628 ffetargetAlign pad; /* Its initial padding. */
12629#endif
12630
12631 if (ffestorag_init (st) == NULL)
5ff904cd 12632 {
c7e4ee3a
CB
12633 init = ffestorag_accretion (st);
12634 assert (init != NULL);
12635 ffestorag_set_accretion (st, NULL);
12636 ffestorag_set_accretes (st, 0);
12637
12638#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12639 /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12640 size = ffebld_accter_size (init);
12641 pad = ffebld_accter_pad (init);
12642 ffebit_kill (ffebld_accter_bits (init));
12643 ffebld_set_op (init, FFEBLD_opARRTER);
12644 ffebld_set_arrter (init, ffebld_accter (init));
12645 ffebld_arrter_set_size (init, size);
12646 ffebld_arrter_set_pad (init, size);
12647#endif
12648
12649#if FFECOM_TWOPASS
12650 ffestorag_set_init (st, init);
12651#endif
5ff904cd 12652 }
c7e4ee3a
CB
12653#if FFECOM_ONEPASS
12654 else
12655 init = ffestorag_init (st);
5ff904cd
JL
12656#endif
12657
c7e4ee3a
CB
12658#if FFECOM_ONEPASS /* Process the inits, wipe 'em out. */
12659 ffestorag_set_init (st, ffebld_new_any ());
5ff904cd 12660
c7e4ee3a
CB
12661 if (ffebld_op (init) == FFEBLD_opANY)
12662 return; /* Oh, we already did this! */
5ff904cd 12663
c7e4ee3a
CB
12664#if FFECOM_targetCURRENT == FFECOM_targetFFE
12665 {
12666 ffesymbol s;
5ff904cd 12667
c7e4ee3a
CB
12668 if (ffestorag_symbol (st) != NULL)
12669 s = ffestorag_symbol (st);
12670 else
12671 s = ffestorag_typesymbol (st);
5ff904cd 12672
c7e4ee3a
CB
12673 fprintf (dmpout, "= initialize_storage \"%s\" ",
12674 (s != NULL) ? ffesymbol_text (s) : "(unnamed)");
12675 ffebld_dump (init);
12676 fputc ('\n', dmpout);
12677 }
12678#endif
5ff904cd 12679
c7e4ee3a
CB
12680#endif /* if FFECOM_ONEPASS */
12681}
5ff904cd 12682
c7e4ee3a 12683/* ffecom_notify_init_symbol -- A symbol is now fully init'ed
5ff904cd 12684
c7e4ee3a
CB
12685 ffesymbol s;
12686 ffecom_notify_init_symbol(s);
5ff904cd 12687
c7e4ee3a
CB
12688 Gets called when all possible units in a symbol (not placed in COMMON
12689 or involved in EQUIVALENCE, unless it as yet has no ffestorag object)
12690 have been initialized. The initialization info either is in
12691 ffesymbol_init or, if that is NULL, ffesymbol_accretion:
5ff904cd 12692
c7e4ee3a
CB
12693 ffesymbol_init may contain an opCONTER or opARRTER. opCONTER may occur
12694 even for an array if the array is one element in length!
5ff904cd 12695
c7e4ee3a
CB
12696 ffesymbol_accretion will contain an opACCTER. It is much like an
12697 opARRTER except it has an ffebit object in it instead of just a size.
12698 The back end can use the info in the ffebit object, if it wants, to
12699 reduce the amount of actual initialization, but in any case it should
12700 kill the ffebit object when done. Also, set accretion to NULL but
12701 init to a non-NULL value.
5ff904cd 12702
c7e4ee3a
CB
12703 After performing initialization, DO NOT set init to NULL, because that'll
12704 tell the front end it is ok for more initialization to happen. Instead,
12705 set init to an opANY expression or some such thing that you can use to
12706 tell that you've already initialized the object.
5ff904cd 12707
c7e4ee3a
CB
12708 27-Oct-91 JCB 1.1
12709 Support two-pass FFE. */
5ff904cd 12710
c7e4ee3a
CB
12711void
12712ffecom_notify_init_symbol (ffesymbol s)
12713{
12714 ffebld init; /* The initialization expression. */
12715#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12716 ffetargetOffset size; /* The size of the entity. */
12717 ffetargetAlign pad; /* Its initial padding. */
12718#endif
5ff904cd 12719
c7e4ee3a
CB
12720 if (ffesymbol_storage (s) == NULL)
12721 return; /* Do nothing until COMMON/EQUIVALENCE
12722 possibilities checked. */
5ff904cd 12723
c7e4ee3a
CB
12724 if ((ffesymbol_init (s) == NULL)
12725 && ((init = ffesymbol_accretion (s)) != NULL))
12726 {
12727 ffesymbol_set_accretion (s, NULL);
12728 ffesymbol_set_accretes (s, 0);
5ff904cd 12729
c7e4ee3a
CB
12730#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12731 /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12732 size = ffebld_accter_size (init);
12733 pad = ffebld_accter_pad (init);
12734 ffebit_kill (ffebld_accter_bits (init));
12735 ffebld_set_op (init, FFEBLD_opARRTER);
12736 ffebld_set_arrter (init, ffebld_accter (init));
12737 ffebld_arrter_set_size (init, size);
12738 ffebld_arrter_set_pad (init, size);
12739#endif
5ff904cd 12740
c7e4ee3a
CB
12741#if FFECOM_TWOPASS
12742 ffesymbol_set_init (s, init);
12743#endif
12744 }
12745#if FFECOM_ONEPASS
12746 else
12747 init = ffesymbol_init (s);
12748#endif
5ff904cd 12749
c7e4ee3a
CB
12750#if FFECOM_ONEPASS
12751 ffesymbol_set_init (s, ffebld_new_any ());
5ff904cd 12752
c7e4ee3a
CB
12753 if (ffebld_op (init) == FFEBLD_opANY)
12754 return; /* Oh, we already did this! */
5ff904cd 12755
c7e4ee3a
CB
12756#if FFECOM_targetCURRENT == FFECOM_targetFFE
12757 fprintf (dmpout, "= initialize_symbol \"%s\" ", ffesymbol_text (s));
12758 ffebld_dump (init);
12759 fputc ('\n', dmpout);
12760#endif
5ff904cd 12761
c7e4ee3a
CB
12762#endif /* if FFECOM_ONEPASS */
12763}
5ff904cd 12764
c7e4ee3a 12765/* ffecom_notify_primary_entry -- Learn which is the primary entry point
5ff904cd 12766
c7e4ee3a
CB
12767 ffesymbol s;
12768 ffecom_notify_primary_entry(s);
5ff904cd 12769
c7e4ee3a
CB
12770 Gets called when implicit or explicit PROGRAM statement seen or when
12771 FUNCTION, SUBROUTINE, or BLOCK DATA statement seen, with the primary
12772 global symbol that serves as the entry point. */
5ff904cd 12773
c7e4ee3a
CB
12774void
12775ffecom_notify_primary_entry (ffesymbol s)
12776{
12777 ffecom_primary_entry_ = s;
12778 ffecom_primary_entry_kind_ = ffesymbol_kind (s);
5ff904cd 12779
c7e4ee3a
CB
12780 if ((ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
12781 || (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE))
12782 ffecom_primary_entry_is_proc_ = TRUE;
12783 else
12784 ffecom_primary_entry_is_proc_ = FALSE;
5ff904cd 12785
c7e4ee3a
CB
12786 if (!ffe_is_silent ())
12787 {
12788 if (ffecom_primary_entry_kind_ == FFEINFO_kindPROGRAM)
12789 fprintf (stderr, "%s:\n", ffesymbol_text (s));
12790 else
12791 fprintf (stderr, " %s:\n", ffesymbol_text (s));
12792 }
5ff904cd 12793
c7e4ee3a
CB
12794#if FFECOM_targetCURRENT == FFECOM_targetGCC
12795 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
12796 {
12797 ffebld list;
12798 ffebld arg;
5ff904cd 12799
c7e4ee3a
CB
12800 for (list = ffesymbol_dummyargs (s);
12801 list != NULL;
12802 list = ffebld_trail (list))
12803 {
12804 arg = ffebld_head (list);
12805 if (ffebld_op (arg) == FFEBLD_opSTAR)
12806 {
12807 ffecom_is_altreturning_ = TRUE;
12808 break;
12809 }
12810 }
12811 }
12812#endif
12813}
5ff904cd 12814
c7e4ee3a
CB
12815FILE *
12816ffecom_open_include (char *name, ffewhereLine l, ffewhereColumn c)
12817{
12818#if FFECOM_GCC_INCLUDE
12819 return ffecom_open_include_ (name, l, c);
12820#else
12821 return fopen (name, "r");
5ff904cd 12822#endif
c7e4ee3a 12823}
5ff904cd 12824
c7e4ee3a 12825/* ffecom_ptr_to_expr -- Transform expr into gcc tree with & in front
5ff904cd 12826
c7e4ee3a
CB
12827 tree t;
12828 ffebld expr; // FFE expression.
12829 tree = ffecom_ptr_to_expr(expr);
5ff904cd 12830
c7e4ee3a 12831 Like ffecom_expr, but sticks address-of in front of most things. */
5ff904cd 12832
c7e4ee3a
CB
12833#if FFECOM_targetCURRENT == FFECOM_targetGCC
12834tree
12835ffecom_ptr_to_expr (ffebld expr)
12836{
12837 tree item;
12838 ffeinfoBasictype bt;
12839 ffeinfoKindtype kt;
12840 ffesymbol s;
5ff904cd 12841
c7e4ee3a 12842 assert (expr != NULL);
5ff904cd 12843
c7e4ee3a
CB
12844 switch (ffebld_op (expr))
12845 {
12846 case FFEBLD_opSYMTER:
12847 s = ffebld_symter (expr);
12848 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
12849 {
12850 ffecomGfrt ix;
5ff904cd 12851
c7e4ee3a
CB
12852 ix = ffeintrin_gfrt_indirect (ffebld_symter_implementation (expr));
12853 assert (ix != FFECOM_gfrt);
12854 if ((item = ffecom_gfrt_[ix]) == NULL_TREE)
12855 {
12856 ffecom_make_gfrt_ (ix);
12857 item = ffecom_gfrt_[ix];
12858 }
12859 }
12860 else
12861 {
12862 item = ffesymbol_hook (s).decl_tree;
12863 if (item == NULL_TREE)
12864 {
12865 s = ffecom_sym_transform_ (s);
12866 item = ffesymbol_hook (s).decl_tree;
12867 }
12868 }
12869 assert (item != NULL);
12870 if (item == error_mark_node)
12871 return item;
12872 if (!ffesymbol_hook (s).addr)
12873 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12874 item);
12875 return item;
5ff904cd 12876
c7e4ee3a 12877 case FFEBLD_opARRAYREF:
ff852b44 12878 return ffecom_arrayref_ (NULL_TREE, expr, 1);
5ff904cd 12879
c7e4ee3a 12880 case FFEBLD_opCONTER:
5ff904cd 12881
c7e4ee3a
CB
12882 bt = ffeinfo_basictype (ffebld_info (expr));
12883 kt = ffeinfo_kindtype (ffebld_info (expr));
5ff904cd 12884
c7e4ee3a
CB
12885 item = ffecom_constantunion (&ffebld_constant_union
12886 (ffebld_conter (expr)), bt, kt,
12887 ffecom_tree_type[bt][kt]);
12888 if (item == error_mark_node)
12889 return error_mark_node;
12890 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12891 item);
12892 return item;
5ff904cd 12893
c7e4ee3a
CB
12894 case FFEBLD_opANY:
12895 return error_mark_node;
5ff904cd 12896
c7e4ee3a
CB
12897 default:
12898 bt = ffeinfo_basictype (ffebld_info (expr));
12899 kt = ffeinfo_kindtype (ffebld_info (expr));
12900
12901 item = ffecom_expr (expr);
12902 if (item == error_mark_node)
12903 return error_mark_node;
12904
12905 /* The back end currently optimizes a bit too zealously for us, in that
12906 we fail JCB001 if the following block of code is omitted. It checks
12907 to see if the transformed expression is a symbol or array reference,
12908 and encloses it in a SAVE_EXPR if that is the case. */
12909
12910 STRIP_NOPS (item);
12911 if ((TREE_CODE (item) == VAR_DECL)
12912 || (TREE_CODE (item) == PARM_DECL)
12913 || (TREE_CODE (item) == RESULT_DECL)
12914 || (TREE_CODE (item) == INDIRECT_REF)
12915 || (TREE_CODE (item) == ARRAY_REF)
12916 || (TREE_CODE (item) == COMPONENT_REF)
12917#ifdef OFFSET_REF
12918 || (TREE_CODE (item) == OFFSET_REF)
12919#endif
12920 || (TREE_CODE (item) == BUFFER_REF)
12921 || (TREE_CODE (item) == REALPART_EXPR)
12922 || (TREE_CODE (item) == IMAGPART_EXPR))
12923 {
12924 item = ffecom_save_tree (item);
12925 }
12926
12927 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12928 item);
12929 return item;
12930 }
12931
12932 assert ("fall-through error" == NULL);
12933 return error_mark_node;
5ff904cd
JL
12934}
12935
12936#endif
c7e4ee3a 12937/* Obtain a temp var with given data type.
5ff904cd 12938
c7e4ee3a
CB
12939 size is FFETARGET_charactersizeNONE for a non-CHARACTER type
12940 or >= 0 for a CHARACTER type.
5ff904cd 12941
c7e4ee3a 12942 elements is -1 for a scalar or > 0 for an array of type. */
5ff904cd
JL
12943
12944#if FFECOM_targetCURRENT == FFECOM_targetGCC
12945tree
c7e4ee3a
CB
12946ffecom_make_tempvar (const char *commentary, tree type,
12947 ffetargetCharacterSize size, int elements)
5ff904cd 12948{
c7e4ee3a
CB
12949 int yes;
12950 tree t;
12951 static int mynumber;
5ff904cd 12952
c7e4ee3a 12953 assert (current_binding_level->prep_state < 2);
702edf1d 12954
c7e4ee3a
CB
12955 if (type == error_mark_node)
12956 return error_mark_node;
702edf1d 12957
c7e4ee3a 12958 yes = suspend_momentary ();
5ff904cd 12959
c7e4ee3a
CB
12960 if (size != FFETARGET_charactersizeNONE)
12961 type = build_array_type (type,
12962 build_range_type (ffecom_f2c_ftnlen_type_node,
12963 ffecom_f2c_ftnlen_one_node,
12964 build_int_2 (size, 0)));
12965 if (elements != -1)
12966 type = build_array_type (type,
12967 build_range_type (integer_type_node,
12968 integer_zero_node,
12969 build_int_2 (elements - 1,
12970 0)));
12971 t = build_decl (VAR_DECL,
12972 ffecom_get_invented_identifier ("__g77_%s_%d",
12973 commentary,
12974 mynumber++),
12975 type);
5ff904cd 12976
c7e4ee3a
CB
12977 t = start_decl (t, FALSE);
12978 finish_decl (t, NULL_TREE, FALSE);
12979
12980 resume_momentary (yes);
5ff904cd 12981
c7e4ee3a
CB
12982 return t;
12983}
5ff904cd 12984#endif
5ff904cd 12985
c7e4ee3a 12986/* Prepare argument pointer to expression.
5ff904cd 12987
c7e4ee3a
CB
12988 Like ffecom_prepare_expr, except for expressions to be evaluated
12989 via ffecom_arg_ptr_to_expr. */
5ff904cd 12990
c7e4ee3a
CB
12991void
12992ffecom_prepare_arg_ptr_to_expr (ffebld expr)
5ff904cd 12993{
c7e4ee3a
CB
12994 /* ~~For now, it seems to be the same thing. */
12995 ffecom_prepare_expr (expr);
12996 return;
12997}
702edf1d 12998
c7e4ee3a 12999/* End of preparations. */
702edf1d 13000
c7e4ee3a
CB
13001bool
13002ffecom_prepare_end (void)
13003{
13004 int prep_state = current_binding_level->prep_state;
5ff904cd 13005
c7e4ee3a
CB
13006 assert (prep_state < 2);
13007 current_binding_level->prep_state = 2;
5ff904cd 13008
c7e4ee3a 13009 return (prep_state == 1) ? TRUE : FALSE;
5ff904cd
JL
13010}
13011
c7e4ee3a 13012/* Prepare expression.
5ff904cd 13013
c7e4ee3a
CB
13014 This is called before any code is generated for the current block.
13015 It scans the expression, declares any temporaries that might be needed
13016 during evaluation of the expression, and stores those temporaries in
13017 the appropriate "hook" fields of the expression. `dest', if not NULL,
13018 specifies the destination that ffecom_expr_ will see, in case that
13019 helps avoid generating unused temporaries.
13020
13021 ~~Improve to avoid allocating unused temporaries by taking `dest'
13022 into account vis-a-vis aliasing requirements of complex/character
13023 functions. */
13024
13025void
13026ffecom_prepare_expr_ (ffebld expr, ffebld dest UNUSED)
5ff904cd 13027{
c7e4ee3a
CB
13028 ffeinfoBasictype bt;
13029 ffeinfoKindtype kt;
13030 ffetargetCharacterSize sz;
13031 tree tempvar = NULL_TREE;
5ff904cd 13032
c7e4ee3a
CB
13033 assert (current_binding_level->prep_state < 2);
13034
13035 if (! expr)
13036 return;
13037
13038 bt = ffeinfo_basictype (ffebld_info (expr));
13039 kt = ffeinfo_kindtype (ffebld_info (expr));
13040 sz = ffeinfo_size (ffebld_info (expr));
13041
13042 /* Generate whatever temporaries are needed to represent the result
13043 of the expression. */
13044
13045 switch (ffebld_op (expr))
5ff904cd 13046 {
c7e4ee3a
CB
13047 default:
13048 /* Don't make temps for SYMTER, CONTER, etc. */
13049 if (ffebld_arity (expr) == 0)
13050 break;
5ff904cd 13051
c7e4ee3a 13052 switch (bt)
5ff904cd 13053 {
c7e4ee3a
CB
13054 case FFEINFO_basictypeCOMPLEX:
13055 if (ffebld_op (expr) == FFEBLD_opFUNCREF)
13056 {
13057 ffesymbol s;
5ff904cd 13058
c7e4ee3a
CB
13059 if (ffebld_op (ffebld_left (expr)) != FFEBLD_opSYMTER)
13060 break;
5ff904cd 13061
c7e4ee3a
CB
13062 s = ffebld_symter (ffebld_left (expr));
13063 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT
13064 || ! ffesymbol_is_f2c (s))
13065 break;
13066 }
13067 else if (ffebld_op (expr) == FFEBLD_opPOWER)
13068 {
13069 /* Requires special treatment. There's no POW_CC function
13070 in libg2c, so POW_ZZ is used, which means we always
13071 need a double-complex temp, not a single-complex. */
13072 kt = FFEINFO_kindtypeREAL2;
13073 }
13074 else if (ffebld_op (expr) != FFEBLD_opDIVIDE)
13075 /* The other ops don't need temps for complex operands. */
13076 break;
5ff904cd 13077
c7e4ee3a
CB
13078 /* ~~~Avoid making temps for some intrinsics, such as AIMAG(C),
13079 REAL(C). See 19990325-0.f, routine `check', for cases. */
13080 tempvar = ffecom_make_tempvar ("complex",
13081 ffecom_tree_type
13082 [FFEINFO_basictypeCOMPLEX][kt],
13083 FFETARGET_charactersizeNONE,
13084 -1);
5ff904cd
JL
13085 break;
13086
c7e4ee3a
CB
13087 case FFEINFO_basictypeCHARACTER:
13088 if (ffebld_op (expr) != FFEBLD_opFUNCREF)
13089 break;
13090
13091 if (sz == FFETARGET_charactersizeNONE)
13092 /* ~~Kludge alert! This should someday be fixed. */
13093 sz = 24;
13094
13095 tempvar = ffecom_make_tempvar ("char", char_type_node, sz, -1);
5ff904cd
JL
13096 break;
13097
13098 default:
5ff904cd
JL
13099 break;
13100 }
c7e4ee3a 13101 break;
5ff904cd 13102
c7e4ee3a
CB
13103#ifdef HAHA
13104 case FFEBLD_opPOWER:
13105 {
13106 tree rtype, ltype;
13107 tree rtmp, ltmp, result;
5ff904cd 13108
c7e4ee3a
CB
13109 ltype = ffecom_type_expr (ffebld_left (expr));
13110 rtype = ffecom_type_expr (ffebld_right (expr));
5ff904cd 13111
c7e4ee3a
CB
13112 rtmp = ffecom_make_tempvar (rtype, FFETARGET_charactersizeNONE, -1);
13113 ltmp = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
13114 result = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
5ff904cd 13115
c7e4ee3a
CB
13116 tempvar = make_tree_vec (3);
13117 TREE_VEC_ELT (tempvar, 0) = rtmp;
13118 TREE_VEC_ELT (tempvar, 1) = ltmp;
13119 TREE_VEC_ELT (tempvar, 2) = result;
13120 }
13121 break;
13122#endif /* HAHA */
5ff904cd 13123
c7e4ee3a
CB
13124 case FFEBLD_opCONCATENATE:
13125 {
13126 /* This gets special handling, because only one set of temps
13127 is needed for a tree of these -- the tree is treated as
13128 a flattened list of concatenations when generating code. */
5ff904cd 13129
c7e4ee3a
CB
13130 ffecomConcatList_ catlist;
13131 tree ltmp, itmp, result;
13132 int count;
13133 int i;
5ff904cd 13134
c7e4ee3a
CB
13135 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
13136 count = ffecom_concat_list_count_ (catlist);
5ff904cd 13137
c7e4ee3a
CB
13138 if (count >= 2)
13139 {
13140 ltmp
13141 = ffecom_make_tempvar ("concat_len",
13142 ffecom_f2c_ftnlen_type_node,
13143 FFETARGET_charactersizeNONE, count);
13144 itmp
13145 = ffecom_make_tempvar ("concat_item",
13146 ffecom_f2c_address_type_node,
13147 FFETARGET_charactersizeNONE, count);
13148 result
13149 = ffecom_make_tempvar ("concat_res",
13150 char_type_node,
13151 ffecom_concat_list_maxlen_ (catlist),
13152 -1);
13153
13154 tempvar = make_tree_vec (3);
13155 TREE_VEC_ELT (tempvar, 0) = ltmp;
13156 TREE_VEC_ELT (tempvar, 1) = itmp;
13157 TREE_VEC_ELT (tempvar, 2) = result;
13158 }
5ff904cd 13159
c7e4ee3a
CB
13160 for (i = 0; i < count; ++i)
13161 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist,
13162 i));
5ff904cd 13163
c7e4ee3a 13164 ffecom_concat_list_kill_ (catlist);
5ff904cd 13165
c7e4ee3a
CB
13166 if (tempvar)
13167 {
13168 ffebld_nonter_set_hook (expr, tempvar);
13169 current_binding_level->prep_state = 1;
13170 }
13171 }
13172 return;
5ff904cd 13173
c7e4ee3a
CB
13174 case FFEBLD_opCONVERT:
13175 if (bt == FFEINFO_basictypeCHARACTER
13176 && ((ffebld_size_known (ffebld_left (expr))
13177 == FFETARGET_charactersizeNONE)
13178 || (ffebld_size_known (ffebld_left (expr)) >= sz)))
13179 tempvar = ffecom_make_tempvar ("convert", char_type_node, sz, -1);
13180 break;
13181 }
5ff904cd 13182
c7e4ee3a
CB
13183 if (tempvar)
13184 {
13185 ffebld_nonter_set_hook (expr, tempvar);
13186 current_binding_level->prep_state = 1;
13187 }
5ff904cd 13188
c7e4ee3a 13189 /* Prepare subexpressions for this expr. */
5ff904cd 13190
c7e4ee3a 13191 switch (ffebld_op (expr))
5ff904cd 13192 {
c7e4ee3a
CB
13193 case FFEBLD_opPERCENT_LOC:
13194 ffecom_prepare_ptr_to_expr (ffebld_left (expr));
13195 break;
5ff904cd 13196
c7e4ee3a
CB
13197 case FFEBLD_opPERCENT_VAL:
13198 case FFEBLD_opPERCENT_REF:
13199 ffecom_prepare_expr (ffebld_left (expr));
13200 break;
5ff904cd 13201
c7e4ee3a
CB
13202 case FFEBLD_opPERCENT_DESCR:
13203 ffecom_prepare_arg_ptr_to_expr (ffebld_left (expr));
13204 break;
5ff904cd 13205
c7e4ee3a
CB
13206 case FFEBLD_opITEM:
13207 {
13208 ffebld item;
5ff904cd 13209
c7e4ee3a
CB
13210 for (item = expr;
13211 item != NULL;
13212 item = ffebld_trail (item))
13213 if (ffebld_head (item) != NULL)
13214 ffecom_prepare_expr (ffebld_head (item));
13215 }
13216 break;
5ff904cd 13217
c7e4ee3a
CB
13218 default:
13219 /* Need to handle character conversion specially. */
13220 switch (ffebld_arity (expr))
13221 {
13222 case 2:
13223 ffecom_prepare_expr (ffebld_left (expr));
13224 ffecom_prepare_expr (ffebld_right (expr));
13225 break;
5ff904cd 13226
c7e4ee3a
CB
13227 case 1:
13228 ffecom_prepare_expr (ffebld_left (expr));
13229 break;
5ff904cd 13230
c7e4ee3a
CB
13231 default:
13232 break;
13233 }
13234 }
5ff904cd 13235
c7e4ee3a 13236 return;
5ff904cd
JL
13237}
13238
c7e4ee3a 13239/* Prepare expression for reading and writing.
5ff904cd 13240
c7e4ee3a
CB
13241 Like ffecom_prepare_expr, except for expressions to be evaluated
13242 via ffecom_expr_rw. */
5ff904cd 13243
c7e4ee3a
CB
13244void
13245ffecom_prepare_expr_rw (tree type, ffebld expr)
13246{
13247 /* This is all we support for now. */
13248 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
5ff904cd 13249
c7e4ee3a
CB
13250 /* ~~For now, it seems to be the same thing. */
13251 ffecom_prepare_expr (expr);
13252 return;
13253}
5ff904cd 13254
c7e4ee3a 13255/* Prepare expression for writing.
5ff904cd 13256
c7e4ee3a
CB
13257 Like ffecom_prepare_expr, except for expressions to be evaluated
13258 via ffecom_expr_w. */
5ff904cd
JL
13259
13260void
c7e4ee3a 13261ffecom_prepare_expr_w (tree type, ffebld expr)
5ff904cd 13262{
c7e4ee3a
CB
13263 /* This is all we support for now. */
13264 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
5ff904cd 13265
c7e4ee3a
CB
13266 /* ~~For now, it seems to be the same thing. */
13267 ffecom_prepare_expr (expr);
13268 return;
13269}
5ff904cd 13270
c7e4ee3a 13271/* Prepare expression for returning.
5ff904cd 13272
c7e4ee3a
CB
13273 Like ffecom_prepare_expr, except for expressions to be evaluated
13274 via ffecom_return_expr. */
5ff904cd 13275
c7e4ee3a
CB
13276void
13277ffecom_prepare_return_expr (ffebld expr)
13278{
13279 assert (current_binding_level->prep_state < 2);
5ff904cd 13280
c7e4ee3a
CB
13281 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE
13282 && ffecom_is_altreturning_
13283 && expr != NULL)
13284 ffecom_prepare_expr (expr);
13285}
5ff904cd 13286
c7e4ee3a 13287/* Prepare pointer to expression.
5ff904cd 13288
c7e4ee3a
CB
13289 Like ffecom_prepare_expr, except for expressions to be evaluated
13290 via ffecom_ptr_to_expr. */
5ff904cd 13291
c7e4ee3a
CB
13292void
13293ffecom_prepare_ptr_to_expr (ffebld expr)
13294{
13295 /* ~~For now, it seems to be the same thing. */
13296 ffecom_prepare_expr (expr);
13297 return;
5ff904cd
JL
13298}
13299
c7e4ee3a 13300/* Transform expression into constant pointer-to-expression tree.
5ff904cd 13301
c7e4ee3a
CB
13302 If the expression can be transformed into a pointer-to-expression tree
13303 that is constant, that is done, and the tree returned. Else NULL_TREE
13304 is returned.
5ff904cd 13305
c7e4ee3a
CB
13306 That way, a caller can attempt to provide compile-time initialization
13307 of a variable and, if that fails, *then* choose to start a new block
13308 and resort to using temporaries, as appropriate. */
5ff904cd 13309
c7e4ee3a
CB
13310tree
13311ffecom_ptr_to_const_expr (ffebld expr)
5ff904cd 13312{
c7e4ee3a
CB
13313 if (! expr)
13314 return integer_zero_node;
5ff904cd 13315
c7e4ee3a
CB
13316 if (ffebld_op (expr) == FFEBLD_opANY)
13317 return error_mark_node;
5ff904cd 13318
c7e4ee3a
CB
13319 if (ffebld_arity (expr) == 0
13320 && (ffebld_op (expr) != FFEBLD_opSYMTER
13321 || ffebld_where (expr) == FFEINFO_whereCOMMON
13322 || ffebld_where (expr) == FFEINFO_whereGLOBAL
13323 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
5ff904cd 13324 {
c7e4ee3a
CB
13325 tree t;
13326
13327 t = ffecom_ptr_to_expr (expr);
13328 assert (TREE_CONSTANT (t));
13329 return t;
5ff904cd
JL
13330 }
13331
c7e4ee3a
CB
13332 return NULL_TREE;
13333}
13334
13335/* ffecom_return_expr -- Returns return-value expr given alt return expr
13336
13337 tree rtn; // NULL_TREE means use expand_null_return()
13338 ffebld expr; // NULL if no alt return expr to RETURN stmt
13339 rtn = ffecom_return_expr(expr);
13340
13341 Based on the program unit type and other info (like return function
13342 type, return master function type when alternate ENTRY points,
13343 whether subroutine has any alternate RETURN points, etc), returns the
13344 appropriate expression to be returned to the caller, or NULL_TREE
13345 meaning no return value or the caller expects it to be returned somewhere
13346 else (which is handled by other parts of this module). */
13347
5ff904cd 13348#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
13349tree
13350ffecom_return_expr (ffebld expr)
13351{
13352 tree rtn;
13353
13354 switch (ffecom_primary_entry_kind_)
5ff904cd 13355 {
c7e4ee3a
CB
13356 case FFEINFO_kindPROGRAM:
13357 case FFEINFO_kindBLOCKDATA:
13358 rtn = NULL_TREE;
13359 break;
5ff904cd 13360
c7e4ee3a
CB
13361 case FFEINFO_kindSUBROUTINE:
13362 if (!ffecom_is_altreturning_)
13363 rtn = NULL_TREE; /* No alt returns, never an expr. */
13364 else if (expr == NULL)
13365 rtn = integer_zero_node;
13366 else
13367 rtn = ffecom_expr (expr);
13368 break;
13369
13370 case FFEINFO_kindFUNCTION:
13371 if ((ffecom_multi_retval_ != NULL_TREE)
13372 || (ffesymbol_basictype (ffecom_primary_entry_)
13373 == FFEINFO_basictypeCHARACTER)
13374 || ((ffesymbol_basictype (ffecom_primary_entry_)
13375 == FFEINFO_basictypeCOMPLEX)
13376 && (ffecom_num_entrypoints_ == 0)
13377 && ffesymbol_is_f2c (ffecom_primary_entry_)))
13378 { /* Value is returned by direct assignment
13379 into (implicit) dummy. */
13380 rtn = NULL_TREE;
13381 break;
5ff904cd 13382 }
c7e4ee3a
CB
13383 rtn = ffecom_func_result_;
13384#if 0
13385 /* Spurious error if RETURN happens before first reference! So elide
13386 this code. In particular, for debugging registry, rtn should always
13387 be non-null after all, but TREE_USED won't be set until we encounter
13388 a reference in the code. Perfectly okay (but weird) code that,
13389 e.g., has "GOTO 20;10 RETURN;20 RTN=0;GOTO 10", would result in
13390 this diagnostic for no reason. Have people use -O -Wuninitialized
13391 and leave it to the back end to find obviously weird cases. */
5ff904cd 13392
c7e4ee3a
CB
13393 /* Used to "assert(rtn != NULL_TREE);" here, but it's kind of a valid
13394 situation; if the return value has never been referenced, it won't
13395 have a tree under 2pass mode. */
13396 if ((rtn == NULL_TREE)
13397 || !TREE_USED (rtn))
13398 {
13399 ffebad_start (FFEBAD_RETURN_VALUE_UNSET);
13400 ffebad_here (0, ffesymbol_where_line (ffecom_primary_entry_),
13401 ffesymbol_where_column (ffecom_primary_entry_));
13402 ffebad_string (ffesymbol_text (ffesymbol_funcresult
13403 (ffecom_primary_entry_)));
13404 ffebad_finish ();
13405 }
5ff904cd 13406#endif
c7e4ee3a 13407 break;
5ff904cd 13408
c7e4ee3a
CB
13409 default:
13410 assert ("bad unit kind" == NULL);
13411 case FFEINFO_kindANY:
13412 rtn = error_mark_node;
13413 break;
13414 }
5ff904cd 13415
c7e4ee3a
CB
13416 return rtn;
13417}
5ff904cd 13418
c7e4ee3a
CB
13419#endif
13420/* Do save_expr only if tree is not error_mark_node. */
5ff904cd
JL
13421
13422#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
13423tree
13424ffecom_save_tree (tree t)
5ff904cd 13425{
c7e4ee3a 13426 return save_expr (t);
5ff904cd 13427}
5ff904cd 13428#endif
c7e4ee3a
CB
13429
13430/* Start a compound statement (block). */
5ff904cd
JL
13431
13432#if FFECOM_targetCURRENT == FFECOM_targetGCC
13433void
c7e4ee3a 13434ffecom_start_compstmt (void)
5ff904cd 13435{
c7e4ee3a 13436 bison_rule_pushlevel_ ();
5ff904cd 13437}
c7e4ee3a 13438#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
5ff904cd 13439
c7e4ee3a 13440/* Public entry point for front end to access start_decl. */
5ff904cd
JL
13441
13442#if FFECOM_targetCURRENT == FFECOM_targetGCC
13443tree
c7e4ee3a 13444ffecom_start_decl (tree decl, bool is_initialized)
5ff904cd 13445{
c7e4ee3a
CB
13446 DECL_INITIAL (decl) = is_initialized ? error_mark_node : NULL_TREE;
13447 return start_decl (decl, FALSE);
13448}
5ff904cd 13449
c7e4ee3a
CB
13450#endif
13451/* ffecom_sym_commit -- Symbol's state being committed to reality
5ff904cd 13452
c7e4ee3a
CB
13453 ffesymbol s;
13454 ffecom_sym_commit(s);
5ff904cd 13455
c7e4ee3a
CB
13456 Does whatever the backend needs when a symbol is committed after having
13457 been backtrackable for a period of time. */
5ff904cd 13458
c7e4ee3a
CB
13459#if FFECOM_targetCURRENT == FFECOM_targetGCC
13460void
13461ffecom_sym_commit (ffesymbol s UNUSED)
13462{
13463 assert (!ffesymbol_retractable ());
13464}
5ff904cd 13465
c7e4ee3a
CB
13466#endif
13467/* ffecom_sym_end_transition -- Perform end transition on all symbols
5ff904cd 13468
c7e4ee3a 13469 ffecom_sym_end_transition();
5ff904cd 13470
c7e4ee3a
CB
13471 Does backend-specific stuff and also calls ffest_sym_end_transition
13472 to do the necessary FFE stuff.
5ff904cd 13473
c7e4ee3a
CB
13474 Backtracking is never enabled when this fn is called, so don't worry
13475 about it. */
5ff904cd 13476
c7e4ee3a
CB
13477ffesymbol
13478ffecom_sym_end_transition (ffesymbol s)
13479{
13480 ffestorag st;
5ff904cd 13481
c7e4ee3a 13482 assert (!ffesymbol_retractable ());
5ff904cd 13483
c7e4ee3a 13484 s = ffest_sym_end_transition (s);
5ff904cd 13485
c7e4ee3a
CB
13486#if FFECOM_targetCURRENT == FFECOM_targetGCC
13487 if ((ffesymbol_kind (s) == FFEINFO_kindBLOCKDATA)
13488 && (ffesymbol_where (s) == FFEINFO_whereGLOBAL))
13489 {
13490 ffecom_list_blockdata_
13491 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13492 FFEINTRIN_specNONE,
13493 FFEINTRIN_impNONE),
13494 ffecom_list_blockdata_);
5ff904cd 13495 }
5ff904cd 13496#endif
5ff904cd 13497
c7e4ee3a
CB
13498 /* This is where we finally notice that a symbol has partial initialization
13499 and finalize it. */
5ff904cd 13500
c7e4ee3a
CB
13501 if (ffesymbol_accretion (s) != NULL)
13502 {
13503 assert (ffesymbol_init (s) == NULL);
13504 ffecom_notify_init_symbol (s);
13505 }
13506 else if (((st = ffesymbol_storage (s)) != NULL)
13507 && ((st = ffestorag_parent (st)) != NULL)
13508 && (ffestorag_accretion (st) != NULL))
13509 {
13510 assert (ffestorag_init (st) == NULL);
13511 ffecom_notify_init_storage (st);
13512 }
5ff904cd
JL
13513
13514#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
13515 if ((ffesymbol_kind (s) == FFEINFO_kindCOMMON)
13516 && (ffesymbol_where (s) == FFEINFO_whereLOCAL)
13517 && (ffesymbol_storage (s) != NULL))
13518 {
13519 ffecom_list_common_
13520 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13521 FFEINTRIN_specNONE,
13522 FFEINTRIN_impNONE),
13523 ffecom_list_common_);
13524 }
13525#endif
5ff904cd 13526
c7e4ee3a
CB
13527 return s;
13528}
5ff904cd 13529
c7e4ee3a 13530/* ffecom_sym_exec_transition -- Perform exec transition on all symbols
5ff904cd 13531
c7e4ee3a 13532 ffecom_sym_exec_transition();
5ff904cd 13533
c7e4ee3a
CB
13534 Does backend-specific stuff and also calls ffest_sym_exec_transition
13535 to do the necessary FFE stuff.
5ff904cd 13536
c7e4ee3a
CB
13537 See the long-winded description in ffecom_sym_learned for info
13538 on handling the situation where backtracking is inhibited. */
5ff904cd 13539
c7e4ee3a
CB
13540ffesymbol
13541ffecom_sym_exec_transition (ffesymbol s)
13542{
13543 s = ffest_sym_exec_transition (s);
5ff904cd 13544
c7e4ee3a
CB
13545 return s;
13546}
5ff904cd 13547
c7e4ee3a 13548/* ffecom_sym_learned -- Initial or more info gained on symbol after exec
5ff904cd 13549
c7e4ee3a
CB
13550 ffesymbol s;
13551 s = ffecom_sym_learned(s);
5ff904cd 13552
c7e4ee3a
CB
13553 Called when a new symbol is seen after the exec transition or when more
13554 info (perhaps) is gained for an UNCERTAIN symbol. The symbol state when
13555 it arrives here is that all its latest info is updated already, so its
13556 state may be UNCERTAIN or UNDERSTOOD, it might already have the hook
13557 field filled in if its gone through here or exec_transition first, and
13558 so on.
5ff904cd 13559
c7e4ee3a
CB
13560 The backend probably wants to check ffesymbol_retractable() to see if
13561 backtracking is in effect. If so, the FFE's changes to the symbol may
13562 be retracted (undone) or committed (ratified), at which time the
13563 appropriate ffecom_sym_retract or _commit function will be called
13564 for that function.
5ff904cd 13565
c7e4ee3a
CB
13566 If the backend has its own backtracking mechanism, great, use it so that
13567 committal is a simple operation. Though it doesn't make much difference,
13568 I suppose: the reason for tentative symbol evolution in the FFE is to
13569 enable error detection in weird incorrect statements early and to disable
13570 incorrect error detection on a correct statement. The backend is not
13571 likely to introduce any information that'll get involved in these
13572 considerations, so it is probably just fine that the implementation
13573 model for this fn and for _exec_transition is to not do anything
13574 (besides the required FFE stuff) if ffesymbol_retractable() returns TRUE
13575 and instead wait until ffecom_sym_commit is called (which it never
13576 will be as long as we're using ambiguity-detecting statement analysis in
13577 the FFE, which we are initially to shake out the code, but don't depend
13578 on this), otherwise go ahead and do whatever is needed.
5ff904cd 13579
c7e4ee3a
CB
13580 In essence, then, when this fn and _exec_transition get called while
13581 backtracking is enabled, a general mechanism would be to flag which (or
13582 both) of these were called (and in what order? neat question as to what
13583 might happen that I'm too lame to think through right now) and then when
13584 _commit is called reproduce the original calling sequence, if any, for
13585 the two fns (at which point backtracking will, of course, be disabled). */
5ff904cd 13586
c7e4ee3a
CB
13587ffesymbol
13588ffecom_sym_learned (ffesymbol s)
13589{
13590 ffestorag_exec_layout (s);
5ff904cd 13591
c7e4ee3a 13592 return s;
5ff904cd
JL
13593}
13594
c7e4ee3a 13595/* ffecom_sym_retract -- Symbol's state being retracted from reality
5ff904cd 13596
c7e4ee3a
CB
13597 ffesymbol s;
13598 ffecom_sym_retract(s);
5ff904cd 13599
c7e4ee3a
CB
13600 Does whatever the backend needs when a symbol is retracted after having
13601 been backtrackable for a period of time. */
5ff904cd
JL
13602
13603#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
13604void
13605ffecom_sym_retract (ffesymbol s UNUSED)
5ff904cd 13606{
c7e4ee3a 13607 assert (!ffesymbol_retractable ());
5ff904cd 13608
c7e4ee3a
CB
13609#if 0 /* GCC doesn't commit any backtrackable sins,
13610 so nothing needed here. */
13611 switch (ffesymbol_hook (s).state)
5ff904cd 13612 {
c7e4ee3a 13613 case 0: /* nothing happened yet. */
5ff904cd
JL
13614 break;
13615
c7e4ee3a 13616 case 1: /* exec transition happened. */
5ff904cd
JL
13617 break;
13618
c7e4ee3a
CB
13619 case 2: /* learned happened. */
13620 break;
5ff904cd 13621
c7e4ee3a
CB
13622 case 3: /* learned then exec. */
13623 break;
13624
13625 case 4: /* exec then learned. */
5ff904cd
JL
13626 break;
13627
13628 default:
c7e4ee3a 13629 assert ("bad hook state" == NULL);
5ff904cd
JL
13630 break;
13631 }
c7e4ee3a
CB
13632#endif
13633}
5ff904cd 13634
c7e4ee3a
CB
13635#endif
13636/* Create temporary gcc label. */
13637
13638#if FFECOM_targetCURRENT == FFECOM_targetGCC
13639tree
13640ffecom_temp_label ()
13641{
13642 tree glabel;
13643 static int mynumber = 0;
13644
13645 glabel = build_decl (LABEL_DECL,
13646 ffecom_get_invented_identifier ("__g77_label_%d",
13647 NULL,
13648 mynumber++),
13649 void_type_node);
13650 DECL_CONTEXT (glabel) = current_function_decl;
13651 DECL_MODE (glabel) = VOIDmode;
13652
13653 return glabel;
5ff904cd
JL
13654}
13655
13656#endif
c7e4ee3a
CB
13657/* Return an expression that is usable as an arg in a conditional context
13658 (IF, DO WHILE, .NOT., and so on).
13659
13660 Use the one provided for the back end as of >2.6.0. */
5ff904cd
JL
13661
13662#if FFECOM_targetCURRENT == FFECOM_targetGCC
a2977d2d 13663tree
c7e4ee3a 13664ffecom_truth_value (tree expr)
5ff904cd 13665{
c7e4ee3a 13666 return truthvalue_conversion (expr);
5ff904cd 13667}
c7e4ee3a 13668
5ff904cd 13669#endif
c7e4ee3a
CB
13670/* Return the inversion of a truth value (the inversion of what
13671 ffecom_truth_value builds).
5ff904cd 13672
c7e4ee3a
CB
13673 Apparently invert_truthvalue, which is properly in the back end, is
13674 enough for now, so just use it. */
5ff904cd
JL
13675
13676#if FFECOM_targetCURRENT == FFECOM_targetGCC
13677tree
c7e4ee3a 13678ffecom_truth_value_invert (tree expr)
5ff904cd 13679{
c7e4ee3a 13680 return invert_truthvalue (ffecom_truth_value (expr));
5ff904cd
JL
13681}
13682
13683#endif
5ff904cd 13684
c7e4ee3a
CB
13685/* Return the tree that is the type of the expression, as would be
13686 returned in TREE_TYPE(ffecom_expr(expr)), without otherwise
13687 transforming the expression, generating temporaries, etc. */
5ff904cd 13688
c7e4ee3a
CB
13689tree
13690ffecom_type_expr (ffebld expr)
13691{
13692 ffeinfoBasictype bt;
13693 ffeinfoKindtype kt;
13694 tree tree_type;
13695
13696 assert (expr != NULL);
13697
13698 bt = ffeinfo_basictype (ffebld_info (expr));
13699 kt = ffeinfo_kindtype (ffebld_info (expr));
13700 tree_type = ffecom_tree_type[bt][kt];
13701
13702 switch (ffebld_op (expr))
13703 {
13704 case FFEBLD_opCONTER:
13705 case FFEBLD_opSYMTER:
13706 case FFEBLD_opARRAYREF:
13707 case FFEBLD_opUPLUS:
13708 case FFEBLD_opPAREN:
13709 case FFEBLD_opUMINUS:
13710 case FFEBLD_opADD:
13711 case FFEBLD_opSUBTRACT:
13712 case FFEBLD_opMULTIPLY:
13713 case FFEBLD_opDIVIDE:
13714 case FFEBLD_opPOWER:
13715 case FFEBLD_opNOT:
13716 case FFEBLD_opFUNCREF:
13717 case FFEBLD_opSUBRREF:
13718 case FFEBLD_opAND:
13719 case FFEBLD_opOR:
13720 case FFEBLD_opXOR:
13721 case FFEBLD_opNEQV:
13722 case FFEBLD_opEQV:
13723 case FFEBLD_opCONVERT:
13724 case FFEBLD_opLT:
13725 case FFEBLD_opLE:
13726 case FFEBLD_opEQ:
13727 case FFEBLD_opNE:
13728 case FFEBLD_opGT:
13729 case FFEBLD_opGE:
13730 case FFEBLD_opPERCENT_LOC:
13731 return tree_type;
13732
13733 case FFEBLD_opACCTER:
13734 case FFEBLD_opARRTER:
13735 case FFEBLD_opITEM:
13736 case FFEBLD_opSTAR:
13737 case FFEBLD_opBOUNDS:
13738 case FFEBLD_opREPEAT:
13739 case FFEBLD_opLABTER:
13740 case FFEBLD_opLABTOK:
13741 case FFEBLD_opIMPDO:
13742 case FFEBLD_opCONCATENATE:
13743 case FFEBLD_opSUBSTR:
13744 default:
13745 assert ("bad op for ffecom_type_expr" == NULL);
13746 /* Fall through. */
13747 case FFEBLD_opANY:
13748 return error_mark_node;
13749 }
13750}
13751
13752/* Return PARM_DECL for arg#1 of master fn containing alternate ENTRY points
13753
13754 If the PARM_DECL already exists, return it, else create it. It's an
13755 integer_type_node argument for the master function that implements a
13756 subroutine or function with more than one entrypoint and is bound at
13757 run time with the entrypoint number (0 for SUBROUTINE/FUNCTION, 1 for
13758 first ENTRY statement, and so on). */
5ff904cd
JL
13759
13760#if FFECOM_targetCURRENT == FFECOM_targetGCC
c7e4ee3a
CB
13761tree
13762ffecom_which_entrypoint_decl ()
5ff904cd 13763{
c7e4ee3a
CB
13764 assert (ffecom_which_entrypoint_decl_ != NULL_TREE);
13765
13766 return ffecom_which_entrypoint_decl_;
5ff904cd
JL
13767}
13768
13769#endif
c7e4ee3a
CB
13770\f
13771/* The following sections consists of private and public functions
13772 that have the same names and perform roughly the same functions
13773 as counterparts in the C front end. Changes in the C front end
13774 might affect how things should be done here. Only functions
13775 needed by the back end should be public here; the rest should
13776 be private (static in the C sense). Functions needed by other
13777 g77 front-end modules should be accessed by them via public
13778 ffecom_* names, which should themselves call private versions
13779 in this section so the private versions are easy to recognize
13780 when upgrading to a new gcc and finding interesting changes
13781 in the front end.
5ff904cd 13782
c7e4ee3a
CB
13783 Functions named after rule "foo:" in c-parse.y are named
13784 "bison_rule_foo_" so they are easy to find. */
5ff904cd 13785
c7e4ee3a 13786#if FFECOM_targetCURRENT == FFECOM_targetGCC
5ff904cd 13787
c7e4ee3a
CB
13788static void
13789bison_rule_pushlevel_ ()
13790{
13791 emit_line_note (input_filename, lineno);
13792 pushlevel (0);
13793 clear_last_expr ();
13794 push_momentary ();
13795 expand_start_bindings (0);
13796}
5ff904cd 13797
c7e4ee3a
CB
13798static tree
13799bison_rule_compstmt_ ()
5ff904cd 13800{
c7e4ee3a
CB
13801 tree t;
13802 int keep = kept_level_p ();
5ff904cd 13803
c7e4ee3a
CB
13804 /* Make the temps go away. */
13805 if (! keep)
13806 current_binding_level->names = NULL_TREE;
5ff904cd 13807
c7e4ee3a
CB
13808 emit_line_note (input_filename, lineno);
13809 expand_end_bindings (getdecls (), keep, 0);
13810 t = poplevel (keep, 1, 0);
13811 pop_momentary ();
5ff904cd 13812
c7e4ee3a
CB
13813 return t;
13814}
5ff904cd 13815
c7e4ee3a
CB
13816/* Return a definition for a builtin function named NAME and whose data type
13817 is TYPE. TYPE should be a function type with argument types.
13818 FUNCTION_CODE tells later passes how to compile calls to this function.
13819 See tree.h for its possible values.
5ff904cd 13820
c7e4ee3a
CB
13821 If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
13822 the name to be called if we can't opencode the function. */
5ff904cd 13823
c7e4ee3a
CB
13824static tree
13825builtin_function (const char *name, tree type,
13826 enum built_in_function function_code,
13827 const char *library_name)
13828{
13829 tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
13830 DECL_EXTERNAL (decl) = 1;
13831 TREE_PUBLIC (decl) = 1;
13832 if (library_name)
13833 DECL_ASSEMBLER_NAME (decl) = get_identifier (library_name);
13834 make_decl_rtl (decl, NULL_PTR, 1);
13835 pushdecl (decl);
13836 if (function_code != NOT_BUILT_IN)
5ff904cd 13837 {
c7e4ee3a
CB
13838 DECL_BUILT_IN (decl) = 1;
13839 DECL_FUNCTION_CODE (decl) = function_code;
5ff904cd 13840 }
5ff904cd 13841
c7e4ee3a 13842 return decl;
5ff904cd
JL
13843}
13844
c7e4ee3a
CB
13845/* Handle when a new declaration NEWDECL
13846 has the same name as an old one OLDDECL
13847 in the same binding contour.
13848 Prints an error message if appropriate.
5ff904cd 13849
c7e4ee3a
CB
13850 If safely possible, alter OLDDECL to look like NEWDECL, and return 1.
13851 Otherwise, return 0. */
5ff904cd 13852
c7e4ee3a
CB
13853static int
13854duplicate_decls (tree newdecl, tree olddecl)
5ff904cd 13855{
c7e4ee3a
CB
13856 int types_match = 1;
13857 int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
13858 && DECL_INITIAL (newdecl) != 0);
13859 tree oldtype = TREE_TYPE (olddecl);
13860 tree newtype = TREE_TYPE (newdecl);
5ff904cd 13861
c7e4ee3a
CB
13862 if (olddecl == newdecl)
13863 return 1;
5ff904cd 13864
c7e4ee3a
CB
13865 if (TREE_CODE (newtype) == ERROR_MARK
13866 || TREE_CODE (oldtype) == ERROR_MARK)
13867 types_match = 0;
5ff904cd 13868
c7e4ee3a
CB
13869 /* New decl is completely inconsistent with the old one =>
13870 tell caller to replace the old one.
13871 This is always an error except in the case of shadowing a builtin. */
13872 if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
13873 return 0;
5ff904cd 13874
c7e4ee3a
CB
13875 /* For real parm decl following a forward decl,
13876 return 1 so old decl will be reused. */
13877 if (types_match && TREE_CODE (newdecl) == PARM_DECL
13878 && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
13879 return 1;
5ff904cd 13880
c7e4ee3a
CB
13881 /* The new declaration is the same kind of object as the old one.
13882 The declarations may partially match. Print warnings if they don't
13883 match enough. Ultimately, copy most of the information from the new
13884 decl to the old one, and keep using the old one. */
5ff904cd 13885
c7e4ee3a
CB
13886 if (TREE_CODE (olddecl) == FUNCTION_DECL
13887 && DECL_BUILT_IN (olddecl))
13888 {
13889 /* A function declaration for a built-in function. */
13890 if (!TREE_PUBLIC (newdecl))
13891 return 0;
13892 else if (!types_match)
13893 {
13894 /* Accept the return type of the new declaration if same modes. */
13895 tree oldreturntype = TREE_TYPE (TREE_TYPE (olddecl));
13896 tree newreturntype = TREE_TYPE (TREE_TYPE (newdecl));
5ff904cd 13897
c7e4ee3a
CB
13898 /* Make sure we put the new type in the same obstack as the old ones.
13899 If the old types are not both in the same obstack, use the
13900 permanent one. */
13901 if (TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (newtype))
13902 push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
13903 else
13904 {
13905 push_obstacks_nochange ();
13906 end_temporary_allocation ();
13907 }
5ff904cd 13908
c7e4ee3a
CB
13909 if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
13910 {
13911 /* Function types may be shared, so we can't just modify
13912 the return type of olddecl's function type. */
13913 tree newtype
13914 = build_function_type (newreturntype,
13915 TYPE_ARG_TYPES (TREE_TYPE (olddecl)));
5ff904cd 13916
c7e4ee3a
CB
13917 types_match = 1;
13918 if (types_match)
13919 TREE_TYPE (olddecl) = newtype;
13920 }
5ff904cd 13921
c7e4ee3a
CB
13922 pop_obstacks ();
13923 }
13924 if (!types_match)
13925 return 0;
13926 }
13927 else if (TREE_CODE (olddecl) == FUNCTION_DECL
13928 && DECL_SOURCE_LINE (olddecl) == 0)
5ff904cd 13929 {
c7e4ee3a
CB
13930 /* A function declaration for a predeclared function
13931 that isn't actually built in. */
13932 if (!TREE_PUBLIC (newdecl))
13933 return 0;
13934 else if (!types_match)
13935 {
13936 /* If the types don't match, preserve volatility indication.
13937 Later on, we will discard everything else about the
13938 default declaration. */
13939 TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
13940 }
13941 }
5ff904cd 13942
c7e4ee3a
CB
13943 /* Copy all the DECL_... slots specified in the new decl
13944 except for any that we copy here from the old type.
5ff904cd 13945
c7e4ee3a
CB
13946 Past this point, we don't change OLDTYPE and NEWTYPE
13947 even if we change the types of NEWDECL and OLDDECL. */
5ff904cd 13948
c7e4ee3a
CB
13949 if (types_match)
13950 {
13951 /* Make sure we put the new type in the same obstack as the old ones.
13952 If the old types are not both in the same obstack, use the permanent
13953 one. */
13954 if (TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (newtype))
13955 push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
13956 else
13957 {
13958 push_obstacks_nochange ();
13959 end_temporary_allocation ();
13960 }
5ff904cd 13961
c7e4ee3a
CB
13962 /* Merge the data types specified in the two decls. */
13963 if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
13964 TREE_TYPE (newdecl)
13965 = TREE_TYPE (olddecl)
13966 = TREE_TYPE (newdecl);
5ff904cd 13967
c7e4ee3a
CB
13968 /* Lay the type out, unless already done. */
13969 if (oldtype != TREE_TYPE (newdecl))
13970 {
13971 if (TREE_TYPE (newdecl) != error_mark_node)
13972 layout_type (TREE_TYPE (newdecl));
13973 if (TREE_CODE (newdecl) != FUNCTION_DECL
13974 && TREE_CODE (newdecl) != TYPE_DECL
13975 && TREE_CODE (newdecl) != CONST_DECL)
13976 layout_decl (newdecl, 0);
13977 }
13978 else
13979 {
13980 /* Since the type is OLDDECL's, make OLDDECL's size go with. */
13981 DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
13982 if (TREE_CODE (olddecl) != FUNCTION_DECL)
13983 if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
13984 DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
13985 }
5ff904cd 13986
c7e4ee3a
CB
13987 /* Keep the old rtl since we can safely use it. */
13988 DECL_RTL (newdecl) = DECL_RTL (olddecl);
5ff904cd 13989
c7e4ee3a
CB
13990 /* Merge the type qualifiers. */
13991 if (DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl)
13992 && !TREE_THIS_VOLATILE (newdecl))
13993 TREE_THIS_VOLATILE (olddecl) = 0;
13994 if (TREE_READONLY (newdecl))
13995 TREE_READONLY (olddecl) = 1;
13996 if (TREE_THIS_VOLATILE (newdecl))
13997 {
13998 TREE_THIS_VOLATILE (olddecl) = 1;
13999 if (TREE_CODE (newdecl) == VAR_DECL)
14000 make_var_volatile (newdecl);
14001 }
5ff904cd 14002
c7e4ee3a
CB
14003 /* Keep source location of definition rather than declaration.
14004 Likewise, keep decl at outer scope. */
14005 if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
14006 || (DECL_CONTEXT (newdecl) != 0 && DECL_CONTEXT (olddecl) == 0))
14007 {
14008 DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
14009 DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl);
5ff904cd 14010
c7e4ee3a
CB
14011 if (DECL_CONTEXT (olddecl) == 0
14012 && TREE_CODE (newdecl) != FUNCTION_DECL)
14013 DECL_CONTEXT (newdecl) = 0;
14014 }
5ff904cd 14015
c7e4ee3a
CB
14016 /* Merge the unused-warning information. */
14017 if (DECL_IN_SYSTEM_HEADER (olddecl))
14018 DECL_IN_SYSTEM_HEADER (newdecl) = 1;
14019 else if (DECL_IN_SYSTEM_HEADER (newdecl))
14020 DECL_IN_SYSTEM_HEADER (olddecl) = 1;
5ff904cd 14021
c7e4ee3a
CB
14022 /* Merge the initialization information. */
14023 if (DECL_INITIAL (newdecl) == 0)
14024 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
5ff904cd 14025
c7e4ee3a
CB
14026 /* Merge the section attribute.
14027 We want to issue an error if the sections conflict but that must be
14028 done later in decl_attributes since we are called before attributes
14029 are assigned. */
14030 if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
14031 DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
5ff904cd 14032
c7e4ee3a
CB
14033#if BUILT_FOR_270
14034 if (TREE_CODE (newdecl) == FUNCTION_DECL)
14035 {
14036 DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
14037 DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
14038 }
5ff904cd 14039#endif
5ff904cd 14040
c7e4ee3a
CB
14041 pop_obstacks ();
14042 }
14043 /* If cannot merge, then use the new type and qualifiers,
14044 and don't preserve the old rtl. */
14045 else
14046 {
14047 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
14048 TREE_READONLY (olddecl) = TREE_READONLY (newdecl);
14049 TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl);
14050 TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl);
14051 }
5ff904cd 14052
c7e4ee3a
CB
14053 /* Merge the storage class information. */
14054 /* For functions, static overrides non-static. */
14055 if (TREE_CODE (newdecl) == FUNCTION_DECL)
14056 {
14057 TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
14058 /* This is since we don't automatically
14059 copy the attributes of NEWDECL into OLDDECL. */
14060 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
14061 /* If this clears `static', clear it in the identifier too. */
14062 if (! TREE_PUBLIC (olddecl))
14063 TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
14064 }
14065 if (DECL_EXTERNAL (newdecl))
14066 {
14067 TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
14068 DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
14069 /* An extern decl does not override previous storage class. */
14070 TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
14071 }
14072 else
14073 {
14074 TREE_STATIC (olddecl) = TREE_STATIC (newdecl);
14075 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
14076 }
5ff904cd 14077
c7e4ee3a
CB
14078 /* If either decl says `inline', this fn is inline,
14079 unless its definition was passed already. */
14080 if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
14081 DECL_INLINE (olddecl) = 1;
14082 DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
5ff904cd 14083
c7e4ee3a
CB
14084 /* Get rid of any built-in function if new arg types don't match it
14085 or if we have a function definition. */
14086 if (TREE_CODE (newdecl) == FUNCTION_DECL
14087 && DECL_BUILT_IN (olddecl)
14088 && (!types_match || new_is_definition))
14089 {
14090 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
14091 DECL_BUILT_IN (olddecl) = 0;
14092 }
5ff904cd 14093
c7e4ee3a
CB
14094 /* If redeclaring a builtin function, and not a definition,
14095 it stays built in.
14096 Also preserve various other info from the definition. */
14097 if (TREE_CODE (newdecl) == FUNCTION_DECL && !new_is_definition)
14098 {
14099 if (DECL_BUILT_IN (olddecl))
14100 {
14101 DECL_BUILT_IN (newdecl) = 1;
14102 DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
14103 }
14104 else
14105 DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl);
5ff904cd 14106
c7e4ee3a
CB
14107 DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
14108 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
14109 DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
14110 DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
14111 }
5ff904cd 14112
c7e4ee3a
CB
14113 /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
14114 But preserve olddecl's DECL_UID. */
14115 {
14116 register unsigned olddecl_uid = DECL_UID (olddecl);
5ff904cd 14117
c7e4ee3a
CB
14118 memcpy ((char *) olddecl + sizeof (struct tree_common),
14119 (char *) newdecl + sizeof (struct tree_common),
14120 sizeof (struct tree_decl) - sizeof (struct tree_common));
14121 DECL_UID (olddecl) = olddecl_uid;
14122 }
5ff904cd 14123
c7e4ee3a 14124 return 1;
5ff904cd
JL
14125}
14126
c7e4ee3a
CB
14127/* Finish processing of a declaration;
14128 install its initial value.
14129 If the length of an array type is not known before,
14130 it must be determined now, from the initial value, or it is an error. */
14131
5ff904cd 14132static void
c7e4ee3a 14133finish_decl (tree decl, tree init, bool is_top_level)
5ff904cd 14134{
c7e4ee3a
CB
14135 register tree type = TREE_TYPE (decl);
14136 int was_incomplete = (DECL_SIZE (decl) == 0);
14137 int temporary = allocation_temporary_p ();
14138 bool at_top_level = (current_binding_level == global_binding_level);
14139 bool top_level = is_top_level || at_top_level;
5ff904cd 14140
c7e4ee3a
CB
14141 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
14142 level anyway. */
14143 assert (!is_top_level || !at_top_level);
5ff904cd 14144
c7e4ee3a
CB
14145 if (TREE_CODE (decl) == PARM_DECL)
14146 assert (init == NULL_TREE);
14147 /* Remember that PARM_DECL doesn't have a DECL_INITIAL field per se -- it
14148 overlaps DECL_ARG_TYPE. */
14149 else if (init == NULL_TREE)
14150 assert (DECL_INITIAL (decl) == NULL_TREE);
14151 else
14152 assert (DECL_INITIAL (decl) == error_mark_node);
5ff904cd 14153
c7e4ee3a 14154 if (init != NULL_TREE)
5ff904cd 14155 {
c7e4ee3a
CB
14156 if (TREE_CODE (decl) != TYPE_DECL)
14157 DECL_INITIAL (decl) = init;
14158 else
14159 {
14160 /* typedef foo = bar; store the type of bar as the type of foo. */
14161 TREE_TYPE (decl) = TREE_TYPE (init);
14162 DECL_INITIAL (decl) = init = 0;
14163 }
5ff904cd
JL
14164 }
14165
c7e4ee3a
CB
14166 /* Pop back to the obstack that is current for this binding level. This is
14167 because MAXINDEX, rtl, etc. to be made below must go in the permanent
14168 obstack. But don't discard the temporary data yet. */
14169 pop_obstacks ();
5ff904cd 14170
c7e4ee3a 14171 /* Deduce size of array from initialization, if not already known */
5ff904cd 14172
c7e4ee3a
CB
14173 if (TREE_CODE (type) == ARRAY_TYPE
14174 && TYPE_DOMAIN (type) == 0
14175 && TREE_CODE (decl) != TYPE_DECL)
14176 {
14177 assert (top_level);
14178 assert (was_incomplete);
5ff904cd 14179
c7e4ee3a
CB
14180 layout_decl (decl, 0);
14181 }
5ff904cd 14182
c7e4ee3a
CB
14183 if (TREE_CODE (decl) == VAR_DECL)
14184 {
14185 if (DECL_SIZE (decl) == NULL_TREE
14186 && TYPE_SIZE (TREE_TYPE (decl)) != NULL_TREE)
14187 layout_decl (decl, 0);
5ff904cd 14188
c7e4ee3a
CB
14189 if (DECL_SIZE (decl) == NULL_TREE
14190 && (TREE_STATIC (decl)
14191 ?
14192 /* A static variable with an incomplete type is an error if it is
14193 initialized. Also if it is not file scope. Otherwise, let it
14194 through, but if it is not `extern' then it may cause an error
14195 message later. */
14196 (DECL_INITIAL (decl) != 0 || DECL_CONTEXT (decl) != 0)
14197 :
14198 /* An automatic variable with an incomplete type is an error. */
14199 !DECL_EXTERNAL (decl)))
14200 {
14201 assert ("storage size not known" == NULL);
14202 abort ();
14203 }
5ff904cd 14204
c7e4ee3a
CB
14205 if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
14206 && (DECL_SIZE (decl) != 0)
14207 && (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST))
14208 {
14209 assert ("storage size not constant" == NULL);
14210 abort ();
14211 }
14212 }
5ff904cd 14213
c7e4ee3a
CB
14214 /* Output the assembler code and/or RTL code for variables and functions,
14215 unless the type is an undefined structure or union. If not, it will get
14216 done when the type is completed. */
5ff904cd 14217
c7e4ee3a 14218 if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
5ff904cd 14219 {
c7e4ee3a
CB
14220 rest_of_decl_compilation (decl, NULL,
14221 DECL_CONTEXT (decl) == 0,
14222 0);
5ff904cd 14223
c7e4ee3a
CB
14224 if (DECL_CONTEXT (decl) != 0)
14225 {
14226 /* Recompute the RTL of a local array now if it used to be an
14227 incomplete type. */
14228 if (was_incomplete
14229 && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
5ff904cd 14230 {
c7e4ee3a
CB
14231 /* If we used it already as memory, it must stay in memory. */
14232 TREE_ADDRESSABLE (decl) = TREE_USED (decl);
14233 /* If it's still incomplete now, no init will save it. */
14234 if (DECL_SIZE (decl) == 0)
14235 DECL_INITIAL (decl) = 0;
14236 expand_decl (decl);
5ff904cd 14237 }
c7e4ee3a
CB
14238 /* Compute and store the initial value. */
14239 if (TREE_CODE (decl) != FUNCTION_DECL)
14240 expand_decl_init (decl);
14241 }
14242 }
14243 else if (TREE_CODE (decl) == TYPE_DECL)
14244 {
14245 rest_of_decl_compilation (decl, NULL_PTR,
14246 DECL_CONTEXT (decl) == 0,
14247 0);
14248 }
5ff904cd 14249
c7e4ee3a
CB
14250 /* This test used to include TREE_PERMANENT, however, we have the same
14251 problem with initializers at the function level. Such initializers get
14252 saved until the end of the function on the momentary_obstack. */
14253 if (!(TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))
14254 && temporary
14255 /* DECL_INITIAL is not defined in PARM_DECLs, since it shares space with
14256 DECL_ARG_TYPE. */
14257 && TREE_CODE (decl) != PARM_DECL)
14258 {
14259 /* We need to remember that this array HAD an initialization, but
14260 discard the actual temporary nodes, since we can't have a permanent
14261 node keep pointing to them. */
14262 /* We make an exception for inline functions, since it's normal for a
14263 local extern redeclaration of an inline function to have a copy of
14264 the top-level decl's DECL_INLINE. */
14265 if ((DECL_INITIAL (decl) != 0)
14266 && (DECL_INITIAL (decl) != error_mark_node))
14267 {
14268 /* If this is a const variable, then preserve the
14269 initializer instead of discarding it so that we can optimize
14270 references to it. */
14271 /* This test used to include TREE_STATIC, but this won't be set
14272 for function level initializers. */
14273 if (TREE_READONLY (decl))
5ff904cd 14274 {
c7e4ee3a
CB
14275 preserve_initializer ();
14276 /* Hack? Set the permanent bit for something that is
14277 permanent, but not on the permenent obstack, so as to
14278 convince output_constant_def to make its rtl on the
14279 permanent obstack. */
14280 TREE_PERMANENT (DECL_INITIAL (decl)) = 1;
5ff904cd 14281
c7e4ee3a
CB
14282 /* The initializer and DECL must have the same (or equivalent
14283 types), but if the initializer is a STRING_CST, its type
14284 might not be on the right obstack, so copy the type
14285 of DECL. */
14286 TREE_TYPE (DECL_INITIAL (decl)) = type;
5ff904cd 14287 }
c7e4ee3a
CB
14288 else
14289 DECL_INITIAL (decl) = error_mark_node;
5ff904cd 14290 }
5ff904cd 14291 }
c7e4ee3a
CB
14292
14293 /* If requested, warn about definitions of large data objects. */
14294
14295 if (warn_larger_than
14296 && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
14297 && !DECL_EXTERNAL (decl))
5ff904cd 14298 {
c7e4ee3a
CB
14299 register tree decl_size = DECL_SIZE (decl);
14300
14301 if (decl_size && TREE_CODE (decl_size) == INTEGER_CST)
5ff904cd 14302 {
c7e4ee3a
CB
14303 unsigned units = TREE_INT_CST_LOW (decl_size) / BITS_PER_UNIT;
14304
14305 if (units > larger_than_size)
14306 warning_with_decl (decl, "size of `%s' is %u bytes", units);
5ff904cd
JL
14307 }
14308 }
14309
c7e4ee3a
CB
14310 /* If we have gone back from temporary to permanent allocation, actually
14311 free the temporary space that we no longer need. */
14312 if (temporary && !allocation_temporary_p ())
14313 permanent_allocation (0);
5ff904cd 14314
c7e4ee3a
CB
14315 /* At the end of a declaration, throw away any variable type sizes of types
14316 defined inside that declaration. There is no use computing them in the
14317 following function definition. */
14318 if (current_binding_level == global_binding_level)
14319 get_pending_sizes ();
14320}
5ff904cd 14321
c7e4ee3a
CB
14322/* Finish up a function declaration and compile that function
14323 all the way to assembler language output. The free the storage
14324 for the function definition.
5ff904cd 14325
c7e4ee3a 14326 This is called after parsing the body of the function definition.
5ff904cd 14327
c7e4ee3a
CB
14328 NESTED is nonzero if the function being finished is nested in another. */
14329
14330static void
14331finish_function (int nested)
14332{
14333 register tree fndecl = current_function_decl;
14334
14335 assert (fndecl != NULL_TREE);
14336 if (TREE_CODE (fndecl) != ERROR_MARK)
14337 {
14338 if (nested)
14339 assert (DECL_CONTEXT (fndecl) != NULL_TREE);
5ff904cd 14340 else
c7e4ee3a
CB
14341 assert (DECL_CONTEXT (fndecl) == NULL_TREE);
14342 }
5ff904cd 14343
c7e4ee3a
CB
14344/* TREE_READONLY (fndecl) = 1;
14345 This caused &foo to be of type ptr-to-const-function
14346 which then got a warning when stored in a ptr-to-function variable. */
5ff904cd 14347
c7e4ee3a 14348 poplevel (1, 0, 1);
5ff904cd 14349
c7e4ee3a
CB
14350 if (TREE_CODE (fndecl) != ERROR_MARK)
14351 {
14352 BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
5ff904cd 14353
c7e4ee3a 14354 /* Must mark the RESULT_DECL as being in this function. */
5ff904cd 14355
c7e4ee3a 14356 DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
5ff904cd 14357
c7e4ee3a
CB
14358 /* Obey `register' declarations if `setjmp' is called in this fn. */
14359 /* Generate rtl for function exit. */
14360 expand_function_end (input_filename, lineno, 0);
5ff904cd 14361
c7e4ee3a
CB
14362 /* So we can tell if jump_optimize sets it to 1. */
14363 can_reach_end = 0;
5ff904cd 14364
c7e4ee3a
CB
14365 /* Run the optimizers and output the assembler code for this function. */
14366 rest_of_compilation (fndecl);
14367 }
5ff904cd 14368
c7e4ee3a
CB
14369 /* Free all the tree nodes making up this function. */
14370 /* Switch back to allocating nodes permanently until we start another
14371 function. */
14372 if (!nested)
14373 permanent_allocation (1);
14374
14375 if (TREE_CODE (fndecl) != ERROR_MARK
14376 && !nested
14377 && DECL_SAVED_INSNS (fndecl) == 0)
14378 {
14379 /* Stop pointing to the local nodes about to be freed. */
14380 /* But DECL_INITIAL must remain nonzero so we know this was an actual
14381 function definition. */
14382 /* For a nested function, this is done in pop_f_function_context. */
14383 /* If rest_of_compilation set this to 0, leave it 0. */
14384 if (DECL_INITIAL (fndecl) != 0)
14385 DECL_INITIAL (fndecl) = error_mark_node;
14386 DECL_ARGUMENTS (fndecl) = 0;
5ff904cd 14387 }
c7e4ee3a
CB
14388
14389 if (!nested)
5ff904cd 14390 {
c7e4ee3a
CB
14391 /* Let the error reporting routines know that we're outside a function.
14392 For a nested function, this value is used in pop_c_function_context
14393 and then reset via pop_function_context. */
14394 ffecom_outer_function_decl_ = current_function_decl = NULL;
5ff904cd 14395 }
c7e4ee3a 14396}
5ff904cd 14397
c7e4ee3a
CB
14398/* Plug-in replacement for identifying the name of a decl and, for a
14399 function, what we call it in diagnostics. For now, "program unit"
14400 should suffice, since it's a bit of a hassle to figure out which
14401 of several kinds of things it is. Note that it could conceivably
14402 be a statement function, which probably isn't really a program unit
14403 per se, but if that comes up, it should be easy to check (being a
14404 nested function and all). */
14405
14406static char *
14407lang_printable_name (tree decl, int v)
14408{
14409 /* Just to keep GCC quiet about the unused variable.
14410 In theory, differing values of V should produce different
14411 output. */
14412 switch (v)
5ff904cd 14413 {
c7e4ee3a
CB
14414 default:
14415 if (TREE_CODE (decl) == ERROR_MARK)
14416 return "erroneous code";
14417 return IDENTIFIER_POINTER (DECL_NAME (decl));
5ff904cd 14418 }
c7e4ee3a
CB
14419}
14420
14421/* g77's function to print out name of current function that caused
14422 an error. */
14423
14424#if BUILT_FOR_270
14425void
14426lang_print_error_function (file)
14427 char *file;
14428{
14429 static ffeglobal last_g = NULL;
14430 static ffesymbol last_s = NULL;
14431 ffeglobal g;
14432 ffesymbol s;
14433 const char *kind;
14434
14435 if ((ffecom_primary_entry_ == NULL)
14436 || (ffesymbol_global (ffecom_primary_entry_) == NULL))
5ff904cd 14437 {
c7e4ee3a
CB
14438 g = NULL;
14439 s = NULL;
14440 kind = NULL;
5ff904cd
JL
14441 }
14442 else
14443 {
c7e4ee3a
CB
14444 g = ffesymbol_global (ffecom_primary_entry_);
14445 if (ffecom_nested_entry_ == NULL)
14446 {
14447 s = ffecom_primary_entry_;
14448 switch (ffesymbol_kind (s))
14449 {
14450 case FFEINFO_kindFUNCTION:
14451 kind = "function";
14452 break;
5ff904cd 14453
c7e4ee3a
CB
14454 case FFEINFO_kindSUBROUTINE:
14455 kind = "subroutine";
14456 break;
5ff904cd 14457
c7e4ee3a
CB
14458 case FFEINFO_kindPROGRAM:
14459 kind = "program";
14460 break;
14461
14462 case FFEINFO_kindBLOCKDATA:
14463 kind = "block-data";
14464 break;
14465
14466 default:
14467 kind = ffeinfo_kind_message (ffesymbol_kind (s));
14468 break;
14469 }
14470 }
14471 else
14472 {
14473 s = ffecom_nested_entry_;
14474 kind = "statement function";
14475 }
5ff904cd
JL
14476 }
14477
c7e4ee3a 14478 if ((last_g != g) || (last_s != s))
5ff904cd 14479 {
c7e4ee3a
CB
14480 if (file)
14481 fprintf (stderr, "%s: ", file);
14482
14483 if (s == NULL)
14484 fprintf (stderr, "Outside of any program unit:\n");
14485 else
5ff904cd 14486 {
c7e4ee3a
CB
14487 const char *name = ffesymbol_text (s);
14488
14489 fprintf (stderr, "In %s `%s':\n", kind, name);
5ff904cd 14490 }
5ff904cd 14491
c7e4ee3a
CB
14492 last_g = g;
14493 last_s = s;
5ff904cd 14494 }
c7e4ee3a
CB
14495}
14496#endif
5ff904cd 14497
c7e4ee3a 14498/* Similar to `lookup_name' but look only at current binding level. */
5ff904cd 14499
c7e4ee3a
CB
14500static tree
14501lookup_name_current_level (tree name)
14502{
14503 register tree t;
5ff904cd 14504
c7e4ee3a
CB
14505 if (current_binding_level == global_binding_level)
14506 return IDENTIFIER_GLOBAL_VALUE (name);
14507
14508 if (IDENTIFIER_LOCAL_VALUE (name) == 0)
14509 return 0;
14510
14511 for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
14512 if (DECL_NAME (t) == name)
14513 break;
14514
14515 return t;
5ff904cd
JL
14516}
14517
c7e4ee3a 14518/* Create a new `struct binding_level'. */
5ff904cd 14519
c7e4ee3a
CB
14520static struct binding_level *
14521make_binding_level ()
5ff904cd 14522{
c7e4ee3a
CB
14523 /* NOSTRICT */
14524 return (struct binding_level *) xmalloc (sizeof (struct binding_level));
14525}
5ff904cd 14526
c7e4ee3a
CB
14527/* Save and restore the variables in this file and elsewhere
14528 that keep track of the progress of compilation of the current function.
14529 Used for nested functions. */
5ff904cd 14530
c7e4ee3a
CB
14531struct f_function
14532{
14533 struct f_function *next;
14534 tree named_labels;
14535 tree shadowed_labels;
14536 struct binding_level *binding_level;
14537};
5ff904cd 14538
c7e4ee3a 14539struct f_function *f_function_chain;
5ff904cd 14540
c7e4ee3a 14541/* Restore the variables used during compilation of a C function. */
5ff904cd 14542
c7e4ee3a
CB
14543static void
14544pop_f_function_context ()
14545{
14546 struct f_function *p = f_function_chain;
14547 tree link;
5ff904cd 14548
c7e4ee3a
CB
14549 /* Bring back all the labels that were shadowed. */
14550 for (link = shadowed_labels; link; link = TREE_CHAIN (link))
14551 if (DECL_NAME (TREE_VALUE (link)) != 0)
14552 IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)))
14553 = TREE_VALUE (link);
5ff904cd 14554
c7e4ee3a
CB
14555 if (current_function_decl != error_mark_node
14556 && DECL_SAVED_INSNS (current_function_decl) == 0)
14557 {
14558 /* Stop pointing to the local nodes about to be freed. */
14559 /* But DECL_INITIAL must remain nonzero so we know this was an actual
14560 function definition. */
14561 DECL_INITIAL (current_function_decl) = error_mark_node;
14562 DECL_ARGUMENTS (current_function_decl) = 0;
5ff904cd
JL
14563 }
14564
c7e4ee3a 14565 pop_function_context ();
5ff904cd 14566
c7e4ee3a 14567 f_function_chain = p->next;
5ff904cd 14568
c7e4ee3a
CB
14569 named_labels = p->named_labels;
14570 shadowed_labels = p->shadowed_labels;
14571 current_binding_level = p->binding_level;
5ff904cd 14572
c7e4ee3a
CB
14573 free (p);
14574}
5ff904cd 14575
c7e4ee3a
CB
14576/* Save and reinitialize the variables
14577 used during compilation of a C function. */
5ff904cd 14578
c7e4ee3a
CB
14579static void
14580push_f_function_context ()
14581{
14582 struct f_function *p
14583 = (struct f_function *) xmalloc (sizeof (struct f_function));
5ff904cd 14584
c7e4ee3a
CB
14585 push_function_context ();
14586
14587 p->next = f_function_chain;
14588 f_function_chain = p;
14589
14590 p->named_labels = named_labels;
14591 p->shadowed_labels = shadowed_labels;
14592 p->binding_level = current_binding_level;
14593}
5ff904cd 14594
c7e4ee3a
CB
14595static void
14596push_parm_decl (tree parm)
14597{
14598 int old_immediate_size_expand = immediate_size_expand;
5ff904cd 14599
c7e4ee3a 14600 /* Don't try computing parm sizes now -- wait till fn is called. */
5ff904cd 14601
c7e4ee3a 14602 immediate_size_expand = 0;
5ff904cd 14603
c7e4ee3a 14604 push_obstacks_nochange ();
5ff904cd 14605
c7e4ee3a 14606 /* Fill in arg stuff. */
5ff904cd 14607
c7e4ee3a
CB
14608 DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
14609 DECL_ARG_TYPE_AS_WRITTEN (parm) = TREE_TYPE (parm);
14610 TREE_READONLY (parm) = 1; /* All implementation args are read-only. */
5ff904cd 14611
c7e4ee3a
CB
14612 parm = pushdecl (parm);
14613
14614 immediate_size_expand = old_immediate_size_expand;
14615
14616 finish_decl (parm, NULL_TREE, FALSE);
5ff904cd
JL
14617}
14618
c7e4ee3a 14619/* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, if appropriate. */
5ff904cd 14620
c7e4ee3a
CB
14621static tree
14622pushdecl_top_level (x)
14623 tree x;
14624{
14625 register tree t;
14626 register struct binding_level *b = current_binding_level;
14627 register tree f = current_function_decl;
5ff904cd 14628
c7e4ee3a
CB
14629 current_binding_level = global_binding_level;
14630 current_function_decl = NULL_TREE;
14631 t = pushdecl (x);
14632 current_binding_level = b;
14633 current_function_decl = f;
14634 return t;
14635}
14636
14637/* Store the list of declarations of the current level.
14638 This is done for the parameter declarations of a function being defined,
14639 after they are modified in the light of any missing parameters. */
14640
14641static tree
14642storedecls (decls)
14643 tree decls;
14644{
14645 return current_binding_level->names = decls;
14646}
14647
14648/* Store the parameter declarations into the current function declaration.
14649 This is called after parsing the parameter declarations, before
14650 digesting the body of the function.
14651
14652 For an old-style definition, modify the function's type
14653 to specify at least the number of arguments. */
5ff904cd
JL
14654
14655static void
c7e4ee3a 14656store_parm_decls (int is_main_program UNUSED)
5ff904cd
JL
14657{
14658 register tree fndecl = current_function_decl;
14659
c7e4ee3a
CB
14660 if (fndecl == error_mark_node)
14661 return;
5ff904cd 14662
c7e4ee3a
CB
14663 /* This is a chain of PARM_DECLs from old-style parm declarations. */
14664 DECL_ARGUMENTS (fndecl) = storedecls (nreverse (getdecls ()));
5ff904cd 14665
c7e4ee3a 14666 /* Initialize the RTL code for the function. */
5ff904cd 14667
c7e4ee3a 14668 init_function_start (fndecl, input_filename, lineno);
56a0044b 14669
c7e4ee3a 14670 /* Set up parameters and prepare for return, for the function. */
5ff904cd 14671
c7e4ee3a
CB
14672 expand_function_start (fndecl, 0);
14673}
5ff904cd 14674
c7e4ee3a
CB
14675static tree
14676start_decl (tree decl, bool is_top_level)
14677{
14678 register tree tem;
14679 bool at_top_level = (current_binding_level == global_binding_level);
14680 bool top_level = is_top_level || at_top_level;
5ff904cd 14681
c7e4ee3a
CB
14682 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
14683 level anyway. */
14684 assert (!is_top_level || !at_top_level);
5ff904cd 14685
c7e4ee3a
CB
14686 /* The corresponding pop_obstacks is in finish_decl. */
14687 push_obstacks_nochange ();
14688
14689 if (DECL_INITIAL (decl) != NULL_TREE)
14690 {
14691 assert (DECL_INITIAL (decl) == error_mark_node);
14692 assert (!DECL_EXTERNAL (decl));
56a0044b 14693 }
c7e4ee3a
CB
14694 else if (top_level)
14695 assert ((TREE_STATIC (decl) == 1) || DECL_EXTERNAL (decl) == 1);
5ff904cd 14696
c7e4ee3a
CB
14697 /* For Fortran, we by default put things in .common when possible. */
14698 DECL_COMMON (decl) = 1;
5ff904cd 14699
c7e4ee3a
CB
14700 /* Add this decl to the current binding level. TEM may equal DECL or it may
14701 be a previous decl of the same name. */
14702 if (is_top_level)
14703 tem = pushdecl_top_level (decl);
14704 else
14705 tem = pushdecl (decl);
14706
14707 /* For a local variable, define the RTL now. */
14708 if (!top_level
14709 /* But not if this is a duplicate decl and we preserved the rtl from the
14710 previous one (which may or may not happen). */
14711 && DECL_RTL (tem) == 0)
5ff904cd 14712 {
c7e4ee3a
CB
14713 if (TYPE_SIZE (TREE_TYPE (tem)) != 0)
14714 expand_decl (tem);
14715 else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
14716 && DECL_INITIAL (tem) != 0)
14717 expand_decl (tem);
5ff904cd
JL
14718 }
14719
c7e4ee3a 14720 if (DECL_INITIAL (tem) != NULL_TREE)
5ff904cd 14721 {
c7e4ee3a
CB
14722 /* When parsing and digesting the initializer, use temporary storage.
14723 Do this even if we will ignore the value. */
14724 if (at_top_level)
14725 temporary_allocation ();
5ff904cd 14726 }
c7e4ee3a
CB
14727
14728 return tem;
5ff904cd
JL
14729}
14730
c7e4ee3a
CB
14731/* Create the FUNCTION_DECL for a function definition.
14732 DECLSPECS and DECLARATOR are the parts of the declaration;
14733 they describe the function's name and the type it returns,
14734 but twisted together in a fashion that parallels the syntax of C.
5ff904cd 14735
c7e4ee3a
CB
14736 This function creates a binding context for the function body
14737 as well as setting up the FUNCTION_DECL in current_function_decl.
5ff904cd 14738
c7e4ee3a
CB
14739 Returns 1 on success. If the DECLARATOR is not suitable for a function
14740 (it defines a datum instead), we return 0, which tells
14741 yyparse to report a parse error.
5ff904cd 14742
c7e4ee3a
CB
14743 NESTED is nonzero for a function nested within another function. */
14744
14745static void
14746start_function (tree name, tree type, int nested, int public)
5ff904cd 14747{
c7e4ee3a
CB
14748 tree decl1;
14749 tree restype;
14750 int old_immediate_size_expand = immediate_size_expand;
5ff904cd 14751
c7e4ee3a
CB
14752 named_labels = 0;
14753 shadowed_labels = 0;
14754
14755 /* Don't expand any sizes in the return type of the function. */
14756 immediate_size_expand = 0;
14757
14758 if (nested)
5ff904cd 14759 {
c7e4ee3a
CB
14760 assert (!public);
14761 assert (current_function_decl != NULL_TREE);
14762 assert (DECL_CONTEXT (current_function_decl) == NULL_TREE);
14763 }
14764 else
14765 {
14766 assert (current_function_decl == NULL_TREE);
5ff904cd 14767 }
c7e4ee3a
CB
14768
14769 if (TREE_CODE (type) == ERROR_MARK)
14770 decl1 = current_function_decl = error_mark_node;
56a0044b 14771 else
5ff904cd 14772 {
c7e4ee3a
CB
14773 decl1 = build_decl (FUNCTION_DECL,
14774 name,
14775 type);
14776 TREE_PUBLIC (decl1) = public ? 1 : 0;
14777 if (nested)
14778 DECL_INLINE (decl1) = 1;
14779 TREE_STATIC (decl1) = 1;
14780 DECL_EXTERNAL (decl1) = 0;
5ff904cd 14781
c7e4ee3a 14782 announce_function (decl1);
5ff904cd 14783
c7e4ee3a
CB
14784 /* Make the init_value nonzero so pushdecl knows this is not tentative.
14785 error_mark_node is replaced below (in poplevel) with the BLOCK. */
14786 DECL_INITIAL (decl1) = error_mark_node;
5ff904cd 14787
c7e4ee3a
CB
14788 /* Record the decl so that the function name is defined. If we already have
14789 a decl for this name, and it is a FUNCTION_DECL, use the old decl. */
5ff904cd 14790
c7e4ee3a 14791 current_function_decl = pushdecl (decl1);
5ff904cd
JL
14792 }
14793
c7e4ee3a
CB
14794 if (!nested)
14795 ffecom_outer_function_decl_ = current_function_decl;
5ff904cd 14796
c7e4ee3a
CB
14797 pushlevel (0);
14798 current_binding_level->prep_state = 2;
5ff904cd 14799
c7e4ee3a
CB
14800 if (TREE_CODE (current_function_decl) != ERROR_MARK)
14801 {
14802 make_function_rtl (current_function_decl);
5ff904cd 14803
c7e4ee3a
CB
14804 restype = TREE_TYPE (TREE_TYPE (current_function_decl));
14805 DECL_RESULT (current_function_decl)
14806 = build_decl (RESULT_DECL, NULL_TREE, restype);
5ff904cd 14807 }
5ff904cd 14808
c7e4ee3a
CB
14809 if (!nested)
14810 /* Allocate further tree nodes temporarily during compilation of this
14811 function only. */
14812 temporary_allocation ();
5ff904cd 14813
c7e4ee3a
CB
14814 if (!nested && (TREE_CODE (current_function_decl) != ERROR_MARK))
14815 TREE_ADDRESSABLE (current_function_decl) = 1;
14816
14817 immediate_size_expand = old_immediate_size_expand;
14818}
14819\f
14820/* Here are the public functions the GNU back end needs. */
14821
14822tree
14823convert (type, expr)
14824 tree type, expr;
5ff904cd 14825{
c7e4ee3a
CB
14826 register tree e = expr;
14827 register enum tree_code code = TREE_CODE (type);
5ff904cd 14828
c7e4ee3a
CB
14829 if (type == TREE_TYPE (e)
14830 || TREE_CODE (e) == ERROR_MARK)
14831 return e;
14832 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
14833 return fold (build1 (NOP_EXPR, type, e));
14834 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
14835 || code == ERROR_MARK)
14836 return error_mark_node;
14837 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
14838 {
14839 assert ("void value not ignored as it ought to be" == NULL);
14840 return error_mark_node;
14841 }
14842 if (code == VOID_TYPE)
14843 return build1 (CONVERT_EXPR, type, e);
14844 if ((code != RECORD_TYPE)
14845 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
14846 e = ffecom_1 (REALPART_EXPR, TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e))),
14847 e);
14848 if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
14849 return fold (convert_to_integer (type, e));
14850 if (code == POINTER_TYPE)
14851 return fold (convert_to_pointer (type, e));
14852 if (code == REAL_TYPE)
14853 return fold (convert_to_real (type, e));
14854 if (code == COMPLEX_TYPE)
14855 return fold (convert_to_complex (type, e));
14856 if (code == RECORD_TYPE)
14857 return fold (ffecom_convert_to_complex_ (type, e));
5ff904cd 14858
c7e4ee3a
CB
14859 assert ("conversion to non-scalar type requested" == NULL);
14860 return error_mark_node;
14861}
5ff904cd 14862
c7e4ee3a
CB
14863/* integrate_decl_tree calls this function, but since we don't use the
14864 DECL_LANG_SPECIFIC field, this is a no-op. */
5ff904cd 14865
c7e4ee3a
CB
14866void
14867copy_lang_decl (node)
14868 tree node UNUSED;
14869{
5ff904cd
JL
14870}
14871
c7e4ee3a
CB
14872/* Return the list of declarations of the current level.
14873 Note that this list is in reverse order unless/until
14874 you nreverse it; and when you do nreverse it, you must
14875 store the result back using `storedecls' or you will lose. */
5ff904cd 14876
c7e4ee3a
CB
14877tree
14878getdecls ()
5ff904cd 14879{
c7e4ee3a 14880 return current_binding_level->names;
5ff904cd
JL
14881}
14882
c7e4ee3a 14883/* Nonzero if we are currently in the global binding level. */
5ff904cd 14884
c7e4ee3a
CB
14885int
14886global_bindings_p ()
5ff904cd 14887{
c7e4ee3a
CB
14888 return current_binding_level == global_binding_level;
14889}
5ff904cd 14890
c7e4ee3a
CB
14891/* Print an error message for invalid use of an incomplete type.
14892 VALUE is the expression that was used (or 0 if that isn't known)
14893 and TYPE is the type that was invalid. */
5ff904cd 14894
c7e4ee3a
CB
14895void
14896incomplete_type_error (value, type)
14897 tree value UNUSED;
14898 tree type;
14899{
14900 if (TREE_CODE (type) == ERROR_MARK)
14901 return;
5ff904cd 14902
c7e4ee3a
CB
14903 assert ("incomplete type?!?" == NULL);
14904}
14905
14906void
14907init_decl_processing ()
5ff904cd 14908{
c7e4ee3a
CB
14909 malloc_init ();
14910 ffe_init_0 ();
14911}
5ff904cd 14912
c7e4ee3a
CB
14913char *
14914init_parse (filename)
14915 char *filename;
14916{
14917#if BUILT_FOR_270
14918 extern void (*print_error_function) (char *);
14919#endif
5ff904cd 14920
c7e4ee3a
CB
14921 /* Open input file. */
14922 if (filename == 0 || !strcmp (filename, "-"))
5ff904cd 14923 {
c7e4ee3a
CB
14924 finput = stdin;
14925 filename = "stdin";
5ff904cd 14926 }
c7e4ee3a
CB
14927 else
14928 finput = fopen (filename, "r");
14929 if (finput == 0)
14930 pfatal_with_name (filename);
5ff904cd 14931
c7e4ee3a
CB
14932#ifdef IO_BUFFER_SIZE
14933 setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);
14934#endif
5ff904cd 14935
c7e4ee3a
CB
14936 /* Make identifier nodes long enough for the language-specific slots. */
14937 set_identifier_size (sizeof (struct lang_identifier));
14938 decl_printable_name = lang_printable_name;
14939#if BUILT_FOR_270
14940 print_error_function = lang_print_error_function;
14941#endif
5ff904cd 14942
c7e4ee3a
CB
14943 return filename;
14944}
5ff904cd 14945
c7e4ee3a
CB
14946void
14947finish_parse ()
14948{
14949 fclose (finput);
14950}
14951
14952/* Delete the node BLOCK from the current binding level.
14953 This is used for the block inside a stmt expr ({...})
14954 so that the block can be reinserted where appropriate. */
14955
14956static void
14957delete_block (block)
14958 tree block;
14959{
14960 tree t;
14961 if (current_binding_level->blocks == block)
14962 current_binding_level->blocks = TREE_CHAIN (block);
14963 for (t = current_binding_level->blocks; t;)
14964 {
14965 if (TREE_CHAIN (t) == block)
14966 TREE_CHAIN (t) = TREE_CHAIN (block);
14967 else
14968 t = TREE_CHAIN (t);
14969 }
14970 TREE_CHAIN (block) = NULL;
14971 /* Clear TREE_USED which is always set by poplevel.
14972 The flag is set again if insert_block is called. */
14973 TREE_USED (block) = 0;
14974}
14975
14976void
14977insert_block (block)
14978 tree block;
14979{
14980 TREE_USED (block) = 1;
14981 current_binding_level->blocks
14982 = chainon (current_binding_level->blocks, block);
14983}
14984
14985int
14986lang_decode_option (argc, argv)
14987 int argc;
14988 char **argv;
14989{
14990 return ffe_decode_option (argc, argv);
5ff904cd
JL
14991}
14992
c7e4ee3a 14993/* used by print-tree.c */
5ff904cd 14994
c7e4ee3a
CB
14995void
14996lang_print_xnode (file, node, indent)
14997 FILE *file UNUSED;
14998 tree node UNUSED;
14999 int indent UNUSED;
5ff904cd 15000{
c7e4ee3a 15001}
5ff904cd 15002
c7e4ee3a
CB
15003void
15004lang_finish ()
15005{
15006 ffe_terminate_0 ();
5ff904cd 15007
c7e4ee3a
CB
15008 if (ffe_is_ffedebug ())
15009 malloc_pool_display (malloc_pool_image ());
5ff904cd
JL
15010}
15011
c7e4ee3a
CB
15012char *
15013lang_identify ()
5ff904cd 15014{
c7e4ee3a
CB
15015 return "f77";
15016}
5ff904cd 15017
c7e4ee3a
CB
15018void
15019lang_init_options ()
15020{
15021 /* Set default options for Fortran. */
15022 flag_move_all_movables = 1;
15023 flag_reduce_all_givs = 1;
15024 flag_argument_noalias = 2;
41af162c 15025 flag_errno_math = 0;
c64f913e 15026 flag_complex_divide_method = 1;
c7e4ee3a 15027}
5ff904cd 15028
c7e4ee3a
CB
15029void
15030lang_init ()
15031{
15032 /* If the file is output from cpp, it should contain a first line
15033 `# 1 "real-filename"', and the current design of gcc (toplev.c
15034 in particular and the way it sets up information relied on by
15035 INCLUDE) requires that we read this now, and store the
15036 "real-filename" info in master_input_filename. Ask the lexer
15037 to try doing this. */
15038 ffelex_hash_kludge (finput);
15039}
5ff904cd 15040
c7e4ee3a
CB
15041int
15042mark_addressable (exp)
15043 tree exp;
15044{
15045 register tree x = exp;
15046 while (1)
15047 switch (TREE_CODE (x))
15048 {
15049 case ADDR_EXPR:
15050 case COMPONENT_REF:
15051 case ARRAY_REF:
15052 x = TREE_OPERAND (x, 0);
15053 break;
5ff904cd 15054
c7e4ee3a
CB
15055 case CONSTRUCTOR:
15056 TREE_ADDRESSABLE (x) = 1;
15057 return 1;
5ff904cd 15058
c7e4ee3a
CB
15059 case VAR_DECL:
15060 case CONST_DECL:
15061 case PARM_DECL:
15062 case RESULT_DECL:
15063 if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)
15064 && DECL_NONLOCAL (x))
15065 {
15066 if (TREE_PUBLIC (x))
15067 {
15068 assert ("address of global register var requested" == NULL);
15069 return 0;
15070 }
15071 assert ("address of register variable requested" == NULL);
15072 }
15073 else if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x))
15074 {
15075 if (TREE_PUBLIC (x))
15076 {
15077 assert ("address of global register var requested" == NULL);
15078 return 0;
15079 }
15080 assert ("address of register var requested" == NULL);
15081 }
15082 put_var_into_stack (x);
5ff904cd 15083
c7e4ee3a
CB
15084 /* drops in */
15085 case FUNCTION_DECL:
15086 TREE_ADDRESSABLE (x) = 1;
15087#if 0 /* poplevel deals with this now. */
15088 if (DECL_CONTEXT (x) == 0)
15089 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
15090#endif
5ff904cd 15091
c7e4ee3a
CB
15092 default:
15093 return 1;
15094 }
5ff904cd
JL
15095}
15096
c7e4ee3a
CB
15097/* If DECL has a cleanup, build and return that cleanup here.
15098 This is a callback called by expand_expr. */
5ff904cd 15099
c7e4ee3a
CB
15100tree
15101maybe_build_cleanup (decl)
15102 tree decl UNUSED;
5ff904cd 15103{
c7e4ee3a
CB
15104 /* There are no cleanups in Fortran. */
15105 return NULL_TREE;
5ff904cd
JL
15106}
15107
c7e4ee3a
CB
15108/* Exit a binding level.
15109 Pop the level off, and restore the state of the identifier-decl mappings
15110 that were in effect when this level was entered.
5ff904cd 15111
c7e4ee3a
CB
15112 If KEEP is nonzero, this level had explicit declarations, so
15113 and create a "block" (a BLOCK node) for the level
15114 to record its declarations and subblocks for symbol table output.
5ff904cd 15115
c7e4ee3a
CB
15116 If FUNCTIONBODY is nonzero, this level is the body of a function,
15117 so create a block as if KEEP were set and also clear out all
15118 label names.
5ff904cd 15119
c7e4ee3a
CB
15120 If REVERSE is nonzero, reverse the order of decls before putting
15121 them into the BLOCK. */
5ff904cd 15122
c7e4ee3a
CB
15123tree
15124poplevel (keep, reverse, functionbody)
15125 int keep;
15126 int reverse;
15127 int functionbody;
5ff904cd 15128{
c7e4ee3a
CB
15129 register tree link;
15130 /* The chain of decls was accumulated in reverse order.
15131 Put it into forward order, just for cleanliness. */
15132 tree decls;
15133 tree subblocks = current_binding_level->blocks;
15134 tree block = 0;
15135 tree decl;
15136 int block_previously_created;
5ff904cd 15137
c7e4ee3a
CB
15138 /* Get the decls in the order they were written.
15139 Usually current_binding_level->names is in reverse order.
15140 But parameter decls were previously put in forward order. */
702edf1d 15141
c7e4ee3a
CB
15142 if (reverse)
15143 current_binding_level->names
15144 = decls = nreverse (current_binding_level->names);
15145 else
15146 decls = current_binding_level->names;
5ff904cd 15147
c7e4ee3a
CB
15148 /* Output any nested inline functions within this block
15149 if they weren't already output. */
5ff904cd 15150
c7e4ee3a
CB
15151 for (decl = decls; decl; decl = TREE_CHAIN (decl))
15152 if (TREE_CODE (decl) == FUNCTION_DECL
15153 && ! TREE_ASM_WRITTEN (decl)
15154 && DECL_INITIAL (decl) != 0
15155 && TREE_ADDRESSABLE (decl))
15156 {
15157 /* If this decl was copied from a file-scope decl
15158 on account of a block-scope extern decl,
15159 propagate TREE_ADDRESSABLE to the file-scope decl.
15160
15161 DECL_ABSTRACT_ORIGIN can be set to itself if warn_return_type is
15162 true, since then the decl goes through save_for_inline_copying. */
15163 if (DECL_ABSTRACT_ORIGIN (decl) != 0
15164 && DECL_ABSTRACT_ORIGIN (decl) != decl)
15165 TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
15166 else if (DECL_SAVED_INSNS (decl) != 0)
15167 {
15168 push_function_context ();
15169 output_inline_function (decl);
15170 pop_function_context ();
15171 }
15172 }
5ff904cd 15173
c7e4ee3a
CB
15174 /* If there were any declarations or structure tags in that level,
15175 or if this level is a function body,
15176 create a BLOCK to record them for the life of this function. */
5ff904cd 15177
c7e4ee3a
CB
15178 block = 0;
15179 block_previously_created = (current_binding_level->this_block != 0);
15180 if (block_previously_created)
15181 block = current_binding_level->this_block;
15182 else if (keep || functionbody)
15183 block = make_node (BLOCK);
15184 if (block != 0)
15185 {
15186 BLOCK_VARS (block) = decls;
15187 BLOCK_SUBBLOCKS (block) = subblocks;
15188 remember_end_note (block);
15189 }
5ff904cd 15190
c7e4ee3a 15191 /* In each subblock, record that this is its superior. */
5ff904cd 15192
c7e4ee3a
CB
15193 for (link = subblocks; link; link = TREE_CHAIN (link))
15194 BLOCK_SUPERCONTEXT (link) = block;
5ff904cd 15195
c7e4ee3a 15196 /* Clear out the meanings of the local variables of this level. */
5ff904cd 15197
c7e4ee3a 15198 for (link = decls; link; link = TREE_CHAIN (link))
5ff904cd 15199 {
c7e4ee3a
CB
15200 if (DECL_NAME (link) != 0)
15201 {
15202 /* If the ident. was used or addressed via a local extern decl,
15203 don't forget that fact. */
15204 if (DECL_EXTERNAL (link))
15205 {
15206 if (TREE_USED (link))
15207 TREE_USED (DECL_NAME (link)) = 1;
15208 if (TREE_ADDRESSABLE (link))
15209 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
15210 }
15211 IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0;
15212 }
5ff904cd 15213 }
5ff904cd 15214
c7e4ee3a
CB
15215 /* If the level being exited is the top level of a function,
15216 check over all the labels, and clear out the current
15217 (function local) meanings of their names. */
5ff904cd 15218
c7e4ee3a 15219 if (functionbody)
5ff904cd 15220 {
c7e4ee3a
CB
15221 /* If this is the top level block of a function,
15222 the vars are the function's parameters.
15223 Don't leave them in the BLOCK because they are
15224 found in the FUNCTION_DECL instead. */
15225
15226 BLOCK_VARS (block) = 0;
5ff904cd
JL
15227 }
15228
c7e4ee3a
CB
15229 /* Pop the current level, and free the structure for reuse. */
15230
15231 {
15232 register struct binding_level *level = current_binding_level;
15233 current_binding_level = current_binding_level->level_chain;
15234
15235 level->level_chain = free_binding_level;
15236 free_binding_level = level;
15237 }
15238
15239 /* Dispose of the block that we just made inside some higher level. */
15240 if (functionbody
15241 && current_function_decl != error_mark_node)
15242 DECL_INITIAL (current_function_decl) = block;
15243 else if (block)
5ff904cd 15244 {
c7e4ee3a
CB
15245 if (!block_previously_created)
15246 current_binding_level->blocks
15247 = chainon (current_binding_level->blocks, block);
5ff904cd 15248 }
c7e4ee3a
CB
15249 /* If we did not make a block for the level just exited,
15250 any blocks made for inner levels
15251 (since they cannot be recorded as subblocks in that level)
15252 must be carried forward so they will later become subblocks
15253 of something else. */
15254 else if (subblocks)
15255 current_binding_level->blocks
15256 = chainon (current_binding_level->blocks, subblocks);
5ff904cd 15257
c7e4ee3a
CB
15258 if (block)
15259 TREE_USED (block) = 1;
15260 return block;
5ff904cd
JL
15261}
15262
c7e4ee3a
CB
15263void
15264print_lang_decl (file, node, indent)
15265 FILE *file UNUSED;
15266 tree node UNUSED;
15267 int indent UNUSED;
15268{
15269}
5ff904cd 15270
c7e4ee3a
CB
15271void
15272print_lang_identifier (file, node, indent)
15273 FILE *file;
15274 tree node;
15275 int indent;
15276{
15277 print_node (file, "global", IDENTIFIER_GLOBAL_VALUE (node), indent + 4);
15278 print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4);
15279}
5ff904cd 15280
c7e4ee3a
CB
15281void
15282print_lang_statistics ()
15283{
15284}
5ff904cd 15285
c7e4ee3a
CB
15286void
15287print_lang_type (file, node, indent)
15288 FILE *file UNUSED;
15289 tree node UNUSED;
15290 int indent UNUSED;
5ff904cd 15291{
c7e4ee3a 15292}
5ff904cd 15293
c7e4ee3a
CB
15294/* Record a decl-node X as belonging to the current lexical scope.
15295 Check for errors (such as an incompatible declaration for the same
15296 name already seen in the same scope).
5ff904cd 15297
c7e4ee3a
CB
15298 Returns either X or an old decl for the same name.
15299 If an old decl is returned, it may have been smashed
15300 to agree with what X says. */
5ff904cd 15301
c7e4ee3a
CB
15302tree
15303pushdecl (x)
15304 tree x;
15305{
15306 register tree t;
15307 register tree name = DECL_NAME (x);
15308 register struct binding_level *b = current_binding_level;
5ff904cd 15309
c7e4ee3a
CB
15310 if ((TREE_CODE (x) == FUNCTION_DECL)
15311 && (DECL_INITIAL (x) == 0)
15312 && DECL_EXTERNAL (x))
15313 DECL_CONTEXT (x) = NULL_TREE;
56a0044b 15314 else
c7e4ee3a
CB
15315 DECL_CONTEXT (x) = current_function_decl;
15316
15317 if (name)
56a0044b 15318 {
c7e4ee3a
CB
15319 if (IDENTIFIER_INVENTED (name))
15320 {
15321#if BUILT_FOR_270
15322 DECL_ARTIFICIAL (x) = 1;
15323#endif
15324 DECL_IN_SYSTEM_HEADER (x) = 1;
15325 }
5ff904cd 15326
c7e4ee3a 15327 t = lookup_name_current_level (name);
5ff904cd 15328
c7e4ee3a 15329 assert ((t == NULL_TREE) || (DECL_CONTEXT (x) == NULL_TREE));
5ff904cd 15330
c7e4ee3a
CB
15331 /* Don't push non-parms onto list for parms until we understand
15332 why we're doing this and whether it works. */
56a0044b 15333
c7e4ee3a
CB
15334 assert ((b == global_binding_level)
15335 || !ffecom_transform_only_dummies_
15336 || TREE_CODE (x) == PARM_DECL);
5ff904cd 15337
c7e4ee3a
CB
15338 if ((t != NULL_TREE) && duplicate_decls (x, t))
15339 return t;
5ff904cd 15340
c7e4ee3a
CB
15341 /* If we are processing a typedef statement, generate a whole new
15342 ..._TYPE node (which will be just an variant of the existing
15343 ..._TYPE node with identical properties) and then install the
15344 TYPE_DECL node generated to represent the typedef name as the
15345 TYPE_NAME of this brand new (duplicate) ..._TYPE node.
5ff904cd 15346
c7e4ee3a
CB
15347 The whole point here is to end up with a situation where each and every
15348 ..._TYPE node the compiler creates will be uniquely associated with
15349 AT MOST one node representing a typedef name. This way, even though
15350 the compiler substitutes corresponding ..._TYPE nodes for TYPE_DECL
15351 (i.e. "typedef name") nodes very early on, later parts of the
15352 compiler can always do the reverse translation and get back the
15353 corresponding typedef name. For example, given:
5ff904cd 15354
c7e4ee3a 15355 typedef struct S MY_TYPE; MY_TYPE object;
5ff904cd 15356
c7e4ee3a
CB
15357 Later parts of the compiler might only know that `object' was of type
15358 `struct S' if it were not for code just below. With this code
15359 however, later parts of the compiler see something like:
5ff904cd 15360
c7e4ee3a 15361 struct S' == struct S typedef struct S' MY_TYPE; struct S' object;
5ff904cd 15362
c7e4ee3a
CB
15363 And they can then deduce (from the node for type struct S') that the
15364 original object declaration was:
5ff904cd 15365
c7e4ee3a 15366 MY_TYPE object;
5ff904cd 15367
c7e4ee3a
CB
15368 Being able to do this is important for proper support of protoize, and
15369 also for generating precise symbolic debugging information which
15370 takes full account of the programmer's (typedef) vocabulary.
5ff904cd 15371
c7e4ee3a
CB
15372 Obviously, we don't want to generate a duplicate ..._TYPE node if the
15373 TYPE_DECL node that we are now processing really represents a
15374 standard built-in type.
5ff904cd 15375
c7e4ee3a
CB
15376 Since all standard types are effectively declared at line zero in the
15377 source file, we can easily check to see if we are working on a
15378 standard type by checking the current value of lineno. */
15379
15380 if (TREE_CODE (x) == TYPE_DECL)
15381 {
15382 if (DECL_SOURCE_LINE (x) == 0)
15383 {
15384 if (TYPE_NAME (TREE_TYPE (x)) == 0)
15385 TYPE_NAME (TREE_TYPE (x)) = x;
15386 }
15387 else if (TREE_TYPE (x) != error_mark_node)
15388 {
15389 tree tt = TREE_TYPE (x);
15390
15391 tt = build_type_copy (tt);
15392 TYPE_NAME (tt) = x;
15393 TREE_TYPE (x) = tt;
15394 }
15395 }
5ff904cd 15396
c7e4ee3a
CB
15397 /* This name is new in its binding level. Install the new declaration
15398 and return it. */
15399 if (b == global_binding_level)
15400 IDENTIFIER_GLOBAL_VALUE (name) = x;
15401 else
15402 IDENTIFIER_LOCAL_VALUE (name) = x;
15403 }
5ff904cd 15404
c7e4ee3a
CB
15405 /* Put decls on list in reverse order. We will reverse them later if
15406 necessary. */
15407 TREE_CHAIN (x) = b->names;
15408 b->names = x;
5ff904cd 15409
c7e4ee3a 15410 return x;
5ff904cd
JL
15411}
15412
c7e4ee3a 15413/* Nonzero if the current level needs to have a BLOCK made. */
5ff904cd 15414
c7e4ee3a
CB
15415static int
15416kept_level_p ()
5ff904cd 15417{
c7e4ee3a
CB
15418 tree decl;
15419
15420 for (decl = current_binding_level->names;
15421 decl;
15422 decl = TREE_CHAIN (decl))
15423 {
15424 if (TREE_USED (decl) || TREE_CODE (decl) != VAR_DECL
15425 || (DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl)))
15426 /* Currently, there aren't supposed to be non-artificial names
15427 at other than the top block for a function -- they're
15428 believed to always be temps. But it's wise to check anyway. */
15429 return 1;
15430 }
15431 return 0;
5ff904cd
JL
15432}
15433
c7e4ee3a
CB
15434/* Enter a new binding level.
15435 If TAG_TRANSPARENT is nonzero, do so only for the name space of variables,
15436 not for that of tags. */
5ff904cd
JL
15437
15438void
c7e4ee3a
CB
15439pushlevel (tag_transparent)
15440 int tag_transparent;
5ff904cd 15441{
c7e4ee3a 15442 register struct binding_level *newlevel = NULL_BINDING_LEVEL;
5ff904cd 15443
c7e4ee3a 15444 assert (! tag_transparent);
5ff904cd 15445
c7e4ee3a
CB
15446 if (current_binding_level == global_binding_level)
15447 {
15448 named_labels = 0;
15449 }
5ff904cd 15450
c7e4ee3a 15451 /* Reuse or create a struct for this binding level. */
5ff904cd 15452
c7e4ee3a 15453 if (free_binding_level)
77f77701 15454 {
c7e4ee3a
CB
15455 newlevel = free_binding_level;
15456 free_binding_level = free_binding_level->level_chain;
77f77701
DB
15457 }
15458 else
c7e4ee3a
CB
15459 {
15460 newlevel = make_binding_level ();
15461 }
77f77701 15462
c7e4ee3a
CB
15463 /* Add this level to the front of the chain (stack) of levels that
15464 are active. */
71b5e532 15465
c7e4ee3a
CB
15466 *newlevel = clear_binding_level;
15467 newlevel->level_chain = current_binding_level;
15468 current_binding_level = newlevel;
5ff904cd
JL
15469}
15470
c7e4ee3a
CB
15471/* Set the BLOCK node for the innermost scope
15472 (the one we are currently in). */
77f77701 15473
5ff904cd 15474void
c7e4ee3a
CB
15475set_block (block)
15476 register tree block;
5ff904cd 15477{
c7e4ee3a 15478 current_binding_level->this_block = block;
5ff904cd
JL
15479}
15480
c7e4ee3a 15481/* ~~gcc/tree.h *should* declare this, because toplev.c references it. */
5ff904cd 15482
c7e4ee3a 15483/* Can't 'yydebug' a front end not generated by yacc/bison! */
bc289659
ML
15484
15485void
c7e4ee3a
CB
15486set_yydebug (value)
15487 int value;
bc289659 15488{
c7e4ee3a
CB
15489 if (value)
15490 fprintf (stderr, "warning: no yacc/bison-generated output to debug!\n");
bc289659
ML
15491}
15492
c7e4ee3a
CB
15493tree
15494signed_or_unsigned_type (unsignedp, type)
15495 int unsignedp;
15496 tree type;
5ff904cd 15497{
c7e4ee3a 15498 tree type2;
5ff904cd 15499
c7e4ee3a
CB
15500 if (! INTEGRAL_TYPE_P (type))
15501 return type;
15502 if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
15503 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15504 if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
15505 return unsignedp ? unsigned_type_node : integer_type_node;
15506 if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node))
15507 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15508 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node))
15509 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15510 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node))
15511 return (unsignedp ? long_long_unsigned_type_node
15512 : long_long_integer_type_node);
5ff904cd 15513
c7e4ee3a
CB
15514 type2 = type_for_size (TYPE_PRECISION (type), unsignedp);
15515 if (type2 == NULL_TREE)
15516 return type;
f84639ba 15517
c7e4ee3a 15518 return type2;
5ff904cd
JL
15519}
15520
c7e4ee3a
CB
15521tree
15522signed_type (type)
15523 tree type;
5ff904cd 15524{
c7e4ee3a
CB
15525 tree type1 = TYPE_MAIN_VARIANT (type);
15526 ffeinfoKindtype kt;
15527 tree type2;
5ff904cd 15528
c7e4ee3a
CB
15529 if (type1 == unsigned_char_type_node || type1 == char_type_node)
15530 return signed_char_type_node;
15531 if (type1 == unsigned_type_node)
15532 return integer_type_node;
15533 if (type1 == short_unsigned_type_node)
15534 return short_integer_type_node;
15535 if (type1 == long_unsigned_type_node)
15536 return long_integer_type_node;
15537 if (type1 == long_long_unsigned_type_node)
15538 return long_long_integer_type_node;
15539#if 0 /* gcc/c-* files only */
15540 if (type1 == unsigned_intDI_type_node)
15541 return intDI_type_node;
15542 if (type1 == unsigned_intSI_type_node)
15543 return intSI_type_node;
15544 if (type1 == unsigned_intHI_type_node)
15545 return intHI_type_node;
15546 if (type1 == unsigned_intQI_type_node)
15547 return intQI_type_node;
15548#endif
5ff904cd 15549
c7e4ee3a
CB
15550 type2 = type_for_size (TYPE_PRECISION (type1), 0);
15551 if (type2 != NULL_TREE)
15552 return type2;
5ff904cd 15553
c7e4ee3a
CB
15554 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15555 {
15556 type2 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
5ff904cd 15557
c7e4ee3a
CB
15558 if (type1 == type2)
15559 return ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15560 }
15561
15562 return type;
5ff904cd
JL
15563}
15564
c7e4ee3a
CB
15565/* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
15566 or validate its data type for an `if' or `while' statement or ?..: exp.
15567
15568 This preparation consists of taking the ordinary
15569 representation of an expression expr and producing a valid tree
15570 boolean expression describing whether expr is nonzero. We could
15571 simply always do build_binary_op (NE_EXPR, expr, integer_zero_node, 1),
15572 but we optimize comparisons, &&, ||, and !.
15573
15574 The resulting type should always be `integer_type_node'. */
5ff904cd
JL
15575
15576tree
c7e4ee3a
CB
15577truthvalue_conversion (expr)
15578 tree expr;
5ff904cd 15579{
c7e4ee3a
CB
15580 if (TREE_CODE (expr) == ERROR_MARK)
15581 return expr;
5ff904cd 15582
c7e4ee3a
CB
15583#if 0 /* This appears to be wrong for C++. */
15584 /* These really should return error_mark_node after 2.4 is stable.
15585 But not all callers handle ERROR_MARK properly. */
15586 switch (TREE_CODE (TREE_TYPE (expr)))
15587 {
15588 case RECORD_TYPE:
15589 error ("struct type value used where scalar is required");
15590 return integer_zero_node;
5ff904cd 15591
c7e4ee3a
CB
15592 case UNION_TYPE:
15593 error ("union type value used where scalar is required");
15594 return integer_zero_node;
5ff904cd 15595
c7e4ee3a
CB
15596 case ARRAY_TYPE:
15597 error ("array type value used where scalar is required");
15598 return integer_zero_node;
5ff904cd 15599
c7e4ee3a
CB
15600 default:
15601 break;
15602 }
15603#endif /* 0 */
5ff904cd 15604
c7e4ee3a
CB
15605 switch (TREE_CODE (expr))
15606 {
15607 /* It is simpler and generates better code to have only TRUTH_*_EXPR
15608 or comparison expressions as truth values at this level. */
15609#if 0
15610 case COMPONENT_REF:
15611 /* A one-bit unsigned bit-field is already acceptable. */
15612 if (1 == TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (expr, 1)))
15613 && TREE_UNSIGNED (TREE_OPERAND (expr, 1)))
15614 return expr;
15615 break;
15616#endif
15617
15618 case EQ_EXPR:
15619 /* It is simpler and generates better code to have only TRUTH_*_EXPR
15620 or comparison expressions as truth values at this level. */
15621#if 0
15622 if (integer_zerop (TREE_OPERAND (expr, 1)))
15623 return build_unary_op (TRUTH_NOT_EXPR, TREE_OPERAND (expr, 0), 0);
15624#endif
15625 case NE_EXPR: case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
15626 case TRUTH_ANDIF_EXPR:
15627 case TRUTH_ORIF_EXPR:
15628 case TRUTH_AND_EXPR:
15629 case TRUTH_OR_EXPR:
15630 case TRUTH_XOR_EXPR:
15631 TREE_TYPE (expr) = integer_type_node;
15632 return expr;
5ff904cd 15633
c7e4ee3a
CB
15634 case ERROR_MARK:
15635 return expr;
5ff904cd 15636
c7e4ee3a
CB
15637 case INTEGER_CST:
15638 return integer_zerop (expr) ? integer_zero_node : integer_one_node;
5ff904cd 15639
c7e4ee3a
CB
15640 case REAL_CST:
15641 return real_zerop (expr) ? integer_zero_node : integer_one_node;
5ff904cd 15642
c7e4ee3a
CB
15643 case ADDR_EXPR:
15644 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0)))
15645 return build (COMPOUND_EXPR, integer_type_node,
15646 TREE_OPERAND (expr, 0), integer_one_node);
15647 else
15648 return integer_one_node;
5ff904cd 15649
c7e4ee3a
CB
15650 case COMPLEX_EXPR:
15651 return ffecom_2 ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
15652 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15653 integer_type_node,
15654 truthvalue_conversion (TREE_OPERAND (expr, 0)),
15655 truthvalue_conversion (TREE_OPERAND (expr, 1)));
5ff904cd 15656
c7e4ee3a
CB
15657 case NEGATE_EXPR:
15658 case ABS_EXPR:
15659 case FLOAT_EXPR:
15660 case FFS_EXPR:
15661 /* These don't change whether an object is non-zero or zero. */
15662 return truthvalue_conversion (TREE_OPERAND (expr, 0));
5ff904cd 15663
c7e4ee3a
CB
15664 case LROTATE_EXPR:
15665 case RROTATE_EXPR:
15666 /* These don't change whether an object is zero or non-zero, but
15667 we can't ignore them if their second arg has side-effects. */
15668 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
15669 return build (COMPOUND_EXPR, integer_type_node, TREE_OPERAND (expr, 1),
15670 truthvalue_conversion (TREE_OPERAND (expr, 0)));
15671 else
15672 return truthvalue_conversion (TREE_OPERAND (expr, 0));
5ff904cd 15673
c7e4ee3a
CB
15674 case COND_EXPR:
15675 /* Distribute the conversion into the arms of a COND_EXPR. */
15676 return fold (build (COND_EXPR, integer_type_node, TREE_OPERAND (expr, 0),
15677 truthvalue_conversion (TREE_OPERAND (expr, 1)),
15678 truthvalue_conversion (TREE_OPERAND (expr, 2))));
5ff904cd 15679
c7e4ee3a
CB
15680 case CONVERT_EXPR:
15681 /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
15682 since that affects how `default_conversion' will behave. */
15683 if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE
15684 || TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
15685 break;
15686 /* fall through... */
15687 case NOP_EXPR:
15688 /* If this is widening the argument, we can ignore it. */
15689 if (TYPE_PRECISION (TREE_TYPE (expr))
15690 >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
15691 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15692 break;
5ff904cd 15693
c7e4ee3a
CB
15694 case MINUS_EXPR:
15695 /* With IEEE arithmetic, x - x may not equal 0, so we can't optimize
15696 this case. */
15697 if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
15698 && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE)
15699 break;
15700 /* fall through... */
15701 case BIT_XOR_EXPR:
15702 /* This and MINUS_EXPR can be changed into a comparison of the
15703 two objects. */
15704 if (TREE_TYPE (TREE_OPERAND (expr, 0))
15705 == TREE_TYPE (TREE_OPERAND (expr, 1)))
15706 return ffecom_2 (NE_EXPR, integer_type_node,
15707 TREE_OPERAND (expr, 0),
15708 TREE_OPERAND (expr, 1));
15709 return ffecom_2 (NE_EXPR, integer_type_node,
15710 TREE_OPERAND (expr, 0),
15711 fold (build1 (NOP_EXPR,
15712 TREE_TYPE (TREE_OPERAND (expr, 0)),
15713 TREE_OPERAND (expr, 1))));
15714
15715 case BIT_AND_EXPR:
15716 if (integer_onep (TREE_OPERAND (expr, 1)))
15717 return expr;
15718 break;
15719
15720 case MODIFY_EXPR:
15721#if 0 /* No such thing in Fortran. */
15722 if (warn_parentheses && C_EXP_ORIGINAL_CODE (expr) == MODIFY_EXPR)
15723 warning ("suggest parentheses around assignment used as truth value");
15724#endif
15725 break;
15726
15727 default:
15728 break;
5ff904cd
JL
15729 }
15730
c7e4ee3a
CB
15731 if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
15732 return (ffecom_2
15733 ((TREE_SIDE_EFFECTS (expr)
15734 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15735 integer_type_node,
15736 truthvalue_conversion (ffecom_1 (REALPART_EXPR,
15737 TREE_TYPE (TREE_TYPE (expr)),
15738 expr)),
15739 truthvalue_conversion (ffecom_1 (IMAGPART_EXPR,
15740 TREE_TYPE (TREE_TYPE (expr)),
15741 expr))));
15742
15743 return ffecom_2 (NE_EXPR, integer_type_node,
15744 expr,
15745 convert (TREE_TYPE (expr), integer_zero_node));
15746}
15747
15748tree
15749type_for_mode (mode, unsignedp)
15750 enum machine_mode mode;
15751 int unsignedp;
15752{
15753 int i;
15754 int j;
15755 tree t;
5ff904cd 15756
c7e4ee3a
CB
15757 if (mode == TYPE_MODE (integer_type_node))
15758 return unsignedp ? unsigned_type_node : integer_type_node;
5ff904cd 15759
c7e4ee3a
CB
15760 if (mode == TYPE_MODE (signed_char_type_node))
15761 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
5ff904cd 15762
c7e4ee3a
CB
15763 if (mode == TYPE_MODE (short_integer_type_node))
15764 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
5ff904cd 15765
c7e4ee3a
CB
15766 if (mode == TYPE_MODE (long_integer_type_node))
15767 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
5ff904cd 15768
c7e4ee3a
CB
15769 if (mode == TYPE_MODE (long_long_integer_type_node))
15770 return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
5ff904cd 15771
c7e4ee3a
CB
15772 if (mode == TYPE_MODE (float_type_node))
15773 return float_type_node;
5ff904cd 15774
c7e4ee3a
CB
15775 if (mode == TYPE_MODE (double_type_node))
15776 return double_type_node;
5ff904cd 15777
c7e4ee3a
CB
15778 if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
15779 return build_pointer_type (char_type_node);
5ff904cd 15780
c7e4ee3a
CB
15781 if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
15782 return build_pointer_type (integer_type_node);
5ff904cd 15783
c7e4ee3a
CB
15784 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
15785 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
15786 {
15787 if (((t = ffecom_tree_type[i][j]) != NULL_TREE)
15788 && (mode == TYPE_MODE (t)))
15789 {
15790 if ((i == FFEINFO_basictypeINTEGER) && unsignedp)
15791 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][j];
15792 else
15793 return t;
15794 }
15795 }
5ff904cd 15796
c7e4ee3a 15797 return 0;
5ff904cd
JL
15798}
15799
c7e4ee3a
CB
15800tree
15801type_for_size (bits, unsignedp)
15802 unsigned bits;
15803 int unsignedp;
5ff904cd 15804{
c7e4ee3a
CB
15805 ffeinfoKindtype kt;
15806 tree type_node;
5ff904cd 15807
c7e4ee3a
CB
15808 if (bits == TYPE_PRECISION (integer_type_node))
15809 return unsignedp ? unsigned_type_node : integer_type_node;
5ff904cd 15810
c7e4ee3a
CB
15811 if (bits == TYPE_PRECISION (signed_char_type_node))
15812 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
5ff904cd 15813
c7e4ee3a
CB
15814 if (bits == TYPE_PRECISION (short_integer_type_node))
15815 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
5ff904cd 15816
c7e4ee3a
CB
15817 if (bits == TYPE_PRECISION (long_integer_type_node))
15818 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
5ff904cd 15819
c7e4ee3a
CB
15820 if (bits == TYPE_PRECISION (long_long_integer_type_node))
15821 return (unsignedp ? long_long_unsigned_type_node
15822 : long_long_integer_type_node);
5ff904cd 15823
c7e4ee3a 15824 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
5ff904cd 15825 {
c7e4ee3a 15826 type_node = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
5ff904cd 15827
c7e4ee3a
CB
15828 if ((type_node != NULL_TREE) && (bits == TYPE_PRECISION (type_node)))
15829 return unsignedp ? ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt]
15830 : type_node;
15831 }
5ff904cd 15832
c7e4ee3a
CB
15833 return 0;
15834}
5ff904cd 15835
c7e4ee3a
CB
15836tree
15837unsigned_type (type)
15838 tree type;
15839{
15840 tree type1 = TYPE_MAIN_VARIANT (type);
15841 ffeinfoKindtype kt;
15842 tree type2;
5ff904cd 15843
c7e4ee3a
CB
15844 if (type1 == signed_char_type_node || type1 == char_type_node)
15845 return unsigned_char_type_node;
15846 if (type1 == integer_type_node)
15847 return unsigned_type_node;
15848 if (type1 == short_integer_type_node)
15849 return short_unsigned_type_node;
15850 if (type1 == long_integer_type_node)
15851 return long_unsigned_type_node;
15852 if (type1 == long_long_integer_type_node)
15853 return long_long_unsigned_type_node;
15854#if 0 /* gcc/c-* files only */
15855 if (type1 == intDI_type_node)
15856 return unsigned_intDI_type_node;
15857 if (type1 == intSI_type_node)
15858 return unsigned_intSI_type_node;
15859 if (type1 == intHI_type_node)
15860 return unsigned_intHI_type_node;
15861 if (type1 == intQI_type_node)
15862 return unsigned_intQI_type_node;
15863#endif
5ff904cd 15864
c7e4ee3a
CB
15865 type2 = type_for_size (TYPE_PRECISION (type1), 1);
15866 if (type2 != NULL_TREE)
15867 return type2;
5ff904cd 15868
c7e4ee3a
CB
15869 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15870 {
15871 type2 = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
5ff904cd 15872
c7e4ee3a
CB
15873 if (type1 == type2)
15874 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
15875 }
5ff904cd 15876
c7e4ee3a
CB
15877 return type;
15878}
5ff904cd 15879
c7e4ee3a
CB
15880#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
15881\f
15882#if FFECOM_GCC_INCLUDE
5ff904cd 15883
c7e4ee3a 15884/* From gcc/cccp.c, the code to handle -I. */
5ff904cd 15885
c7e4ee3a
CB
15886/* Skip leading "./" from a directory name.
15887 This may yield the empty string, which represents the current directory. */
5ff904cd 15888
c7e4ee3a
CB
15889static const char *
15890skip_redundant_dir_prefix (const char *dir)
15891{
15892 while (dir[0] == '.' && dir[1] == '/')
15893 for (dir += 2; *dir == '/'; dir++)
15894 continue;
15895 if (dir[0] == '.' && !dir[1])
15896 dir++;
15897 return dir;
15898}
5ff904cd 15899
c7e4ee3a
CB
15900/* The file_name_map structure holds a mapping of file names for a
15901 particular directory. This mapping is read from the file named
15902 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
15903 map filenames on a file system with severe filename restrictions,
15904 such as DOS. The format of the file name map file is just a series
15905 of lines with two tokens on each line. The first token is the name
15906 to map, and the second token is the actual name to use. */
5ff904cd 15907
c7e4ee3a
CB
15908struct file_name_map
15909{
15910 struct file_name_map *map_next;
15911 char *map_from;
15912 char *map_to;
15913};
5ff904cd 15914
c7e4ee3a 15915#define FILE_NAME_MAP_FILE "header.gcc"
5ff904cd 15916
c7e4ee3a
CB
15917/* Current maximum length of directory names in the search path
15918 for include files. (Altered as we get more of them.) */
5ff904cd 15919
c7e4ee3a 15920static int max_include_len = 0;
5ff904cd 15921
c7e4ee3a
CB
15922struct file_name_list
15923 {
15924 struct file_name_list *next;
15925 char *fname;
15926 /* Mapping of file names for this directory. */
15927 struct file_name_map *name_map;
15928 /* Non-zero if name_map is valid. */
15929 int got_name_map;
15930 };
5ff904cd 15931
c7e4ee3a
CB
15932static struct file_name_list *include = NULL; /* First dir to search */
15933static struct file_name_list *last_include = NULL; /* Last in chain */
5ff904cd 15934
c7e4ee3a
CB
15935/* I/O buffer structure.
15936 The `fname' field is nonzero for source files and #include files
15937 and for the dummy text used for -D and -U.
15938 It is zero for rescanning results of macro expansion
15939 and for expanding macro arguments. */
15940#define INPUT_STACK_MAX 400
15941static struct file_buf {
15942 char *fname;
15943 /* Filename specified with #line command. */
15944 char *nominal_fname;
15945 /* Record where in the search path this file was found.
15946 For #include_next. */
15947 struct file_name_list *dir;
15948 ffewhereLine line;
15949 ffewhereColumn column;
15950} instack[INPUT_STACK_MAX];
5ff904cd 15951
c7e4ee3a
CB
15952static int last_error_tick = 0; /* Incremented each time we print it. */
15953static int input_file_stack_tick = 0; /* Incremented when status changes. */
5ff904cd 15954
c7e4ee3a
CB
15955/* Current nesting level of input sources.
15956 `instack[indepth]' is the level currently being read. */
15957static int indepth = -1;
5ff904cd 15958
c7e4ee3a 15959typedef struct file_buf FILE_BUF;
5ff904cd 15960
c7e4ee3a 15961typedef unsigned char U_CHAR;
5ff904cd 15962
c7e4ee3a
CB
15963/* table to tell if char can be part of a C identifier. */
15964U_CHAR is_idchar[256];
15965/* table to tell if char can be first char of a c identifier. */
15966U_CHAR is_idstart[256];
15967/* table to tell if c is horizontal space. */
15968U_CHAR is_hor_space[256];
15969/* table to tell if c is horizontal or vertical space. */
15970static U_CHAR is_space[256];
5ff904cd 15971
c7e4ee3a
CB
15972#define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
15973#define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*p]) p++; } while (0)
5ff904cd 15974
c7e4ee3a
CB
15975/* Nonzero means -I- has been seen,
15976 so don't look for #include "foo" the source-file directory. */
15977static int ignore_srcdir;
5ff904cd 15978
c7e4ee3a
CB
15979#ifndef INCLUDE_LEN_FUDGE
15980#define INCLUDE_LEN_FUDGE 0
15981#endif
5ff904cd 15982
c7e4ee3a
CB
15983static void append_include_chain (struct file_name_list *first,
15984 struct file_name_list *last);
15985static FILE *open_include_file (char *filename,
15986 struct file_name_list *searchptr);
15987static void print_containing_files (ffebadSeverity sev);
15988static const char *skip_redundant_dir_prefix (const char *);
15989static char *read_filename_string (int ch, FILE *f);
15990static struct file_name_map *read_name_map (const char *dirname);
5ff904cd 15991
c7e4ee3a
CB
15992/* Append a chain of `struct file_name_list's
15993 to the end of the main include chain.
15994 FIRST is the beginning of the chain to append, and LAST is the end. */
5ff904cd 15995
c7e4ee3a
CB
15996static void
15997append_include_chain (first, last)
15998 struct file_name_list *first, *last;
5ff904cd 15999{
c7e4ee3a 16000 struct file_name_list *dir;
5ff904cd 16001
c7e4ee3a
CB
16002 if (!first || !last)
16003 return;
5ff904cd 16004
c7e4ee3a
CB
16005 if (include == 0)
16006 include = first;
16007 else
16008 last_include->next = first;
5ff904cd 16009
c7e4ee3a
CB
16010 for (dir = first; ; dir = dir->next) {
16011 int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE;
16012 if (len > max_include_len)
16013 max_include_len = len;
16014 if (dir == last)
16015 break;
16016 }
16017
16018 last->next = NULL;
16019 last_include = last;
5ff904cd
JL
16020}
16021
c7e4ee3a
CB
16022/* Try to open include file FILENAME. SEARCHPTR is the directory
16023 being tried from the include file search path. This function maps
16024 filenames on file systems based on information read by
16025 read_name_map. */
16026
16027static FILE *
16028open_include_file (filename, searchptr)
16029 char *filename;
16030 struct file_name_list *searchptr;
5ff904cd 16031{
c7e4ee3a
CB
16032 register struct file_name_map *map;
16033 register char *from;
16034 char *p, *dir;
5ff904cd 16035
c7e4ee3a
CB
16036 if (searchptr && ! searchptr->got_name_map)
16037 {
16038 searchptr->name_map = read_name_map (searchptr->fname
16039 ? searchptr->fname : ".");
16040 searchptr->got_name_map = 1;
16041 }
5ff904cd 16042
c7e4ee3a
CB
16043 /* First check the mapping for the directory we are using. */
16044 if (searchptr && searchptr->name_map)
16045 {
16046 from = filename;
16047 if (searchptr->fname)
16048 from += strlen (searchptr->fname) + 1;
16049 for (map = searchptr->name_map; map; map = map->map_next)
16050 {
16051 if (! strcmp (map->map_from, from))
16052 {
16053 /* Found a match. */
16054 return fopen (map->map_to, "r");
16055 }
16056 }
16057 }
5ff904cd 16058
c7e4ee3a
CB
16059 /* Try to find a mapping file for the particular directory we are
16060 looking in. Thus #include <sys/types.h> will look up sys/types.h
16061 in /usr/include/header.gcc and look up types.h in
16062 /usr/include/sys/header.gcc. */
16063 p = rindex (filename, '/');
16064#ifdef DIR_SEPARATOR
16065 if (! p) p = rindex (filename, DIR_SEPARATOR);
16066 else {
16067 char *tmp = rindex (filename, DIR_SEPARATOR);
16068 if (tmp != NULL && tmp > p) p = tmp;
16069 }
16070#endif
16071 if (! p)
16072 p = filename;
16073 if (searchptr
16074 && searchptr->fname
16075 && strlen (searchptr->fname) == (size_t) (p - filename)
16076 && ! strncmp (searchptr->fname, filename, (int) (p - filename)))
16077 {
16078 /* FILENAME is in SEARCHPTR, which we've already checked. */
16079 return fopen (filename, "r");
16080 }
16081
16082 if (p == filename)
16083 {
16084 from = filename;
16085 map = read_name_map (".");
16086 }
16087 else
5ff904cd 16088 {
c7e4ee3a
CB
16089 dir = (char *) xmalloc (p - filename + 1);
16090 memcpy (dir, filename, p - filename);
16091 dir[p - filename] = '\0';
16092 from = p + 1;
16093 map = read_name_map (dir);
16094 free (dir);
5ff904cd 16095 }
c7e4ee3a
CB
16096 for (; map; map = map->map_next)
16097 if (! strcmp (map->map_from, from))
16098 return fopen (map->map_to, "r");
5ff904cd 16099
c7e4ee3a 16100 return fopen (filename, "r");
5ff904cd
JL
16101}
16102
c7e4ee3a
CB
16103/* Print the file names and line numbers of the #include
16104 commands which led to the current file. */
5ff904cd 16105
c7e4ee3a
CB
16106static void
16107print_containing_files (ffebadSeverity sev)
16108{
16109 FILE_BUF *ip = NULL;
16110 int i;
16111 int first = 1;
16112 const char *str1;
16113 const char *str2;
5ff904cd 16114
c7e4ee3a
CB
16115 /* If stack of files hasn't changed since we last printed
16116 this info, don't repeat it. */
16117 if (last_error_tick == input_file_stack_tick)
16118 return;
5ff904cd 16119
c7e4ee3a
CB
16120 for (i = indepth; i >= 0; i--)
16121 if (instack[i].fname != NULL) {
16122 ip = &instack[i];
16123 break;
16124 }
5ff904cd 16125
c7e4ee3a
CB
16126 /* Give up if we don't find a source file. */
16127 if (ip == NULL)
16128 return;
5ff904cd 16129
c7e4ee3a
CB
16130 /* Find the other, outer source files. */
16131 for (i--; i >= 0; i--)
16132 if (instack[i].fname != NULL)
16133 {
16134 ip = &instack[i];
16135 if (first)
16136 {
16137 first = 0;
16138 str1 = "In file included";
16139 }
16140 else
16141 {
16142 str1 = "... ...";
16143 }
5ff904cd 16144
c7e4ee3a
CB
16145 if (i == 1)
16146 str2 = ":";
16147 else
16148 str2 = "";
5ff904cd 16149
c7e4ee3a
CB
16150 ffebad_start_msg ("%A from %B at %0%C", sev);
16151 ffebad_here (0, ip->line, ip->column);
16152 ffebad_string (str1);
16153 ffebad_string (ip->nominal_fname);
16154 ffebad_string (str2);
16155 ffebad_finish ();
16156 }
5ff904cd 16157
c7e4ee3a
CB
16158 /* Record we have printed the status as of this time. */
16159 last_error_tick = input_file_stack_tick;
16160}
5ff904cd 16161
c7e4ee3a
CB
16162/* Read a space delimited string of unlimited length from a stdio
16163 file. */
5ff904cd 16164
c7e4ee3a
CB
16165static char *
16166read_filename_string (ch, f)
16167 int ch;
16168 FILE *f;
16169{
16170 char *alloc, *set;
16171 int len;
5ff904cd 16172
c7e4ee3a
CB
16173 len = 20;
16174 set = alloc = xmalloc (len + 1);
16175 if (! is_space[ch])
16176 {
16177 *set++ = ch;
16178 while ((ch = getc (f)) != EOF && ! is_space[ch])
16179 {
16180 if (set - alloc == len)
16181 {
16182 len *= 2;
16183 alloc = xrealloc (alloc, len + 1);
16184 set = alloc + len / 2;
16185 }
16186 *set++ = ch;
16187 }
16188 }
16189 *set = '\0';
16190 ungetc (ch, f);
16191 return alloc;
16192}
5ff904cd 16193
c7e4ee3a 16194/* Read the file name map file for DIRNAME. */
5ff904cd 16195
c7e4ee3a
CB
16196static struct file_name_map *
16197read_name_map (dirname)
16198 const char *dirname;
16199{
16200 /* This structure holds a linked list of file name maps, one per
16201 directory. */
16202 struct file_name_map_list
16203 {
16204 struct file_name_map_list *map_list_next;
16205 char *map_list_name;
16206 struct file_name_map *map_list_map;
16207 };
16208 static struct file_name_map_list *map_list;
16209 register struct file_name_map_list *map_list_ptr;
16210 char *name;
16211 FILE *f;
16212 size_t dirlen;
16213 int separator_needed;
5ff904cd 16214
c7e4ee3a 16215 dirname = skip_redundant_dir_prefix (dirname);
5ff904cd 16216
c7e4ee3a
CB
16217 for (map_list_ptr = map_list; map_list_ptr;
16218 map_list_ptr = map_list_ptr->map_list_next)
16219 if (! strcmp (map_list_ptr->map_list_name, dirname))
16220 return map_list_ptr->map_list_map;
5ff904cd 16221
c7e4ee3a
CB
16222 map_list_ptr = ((struct file_name_map_list *)
16223 xmalloc (sizeof (struct file_name_map_list)));
16224 map_list_ptr->map_list_name = xstrdup (dirname);
16225 map_list_ptr->map_list_map = NULL;
5ff904cd 16226
c7e4ee3a
CB
16227 dirlen = strlen (dirname);
16228 separator_needed = dirlen != 0 && dirname[dirlen - 1] != '/';
16229 name = (char *) xmalloc (dirlen + strlen (FILE_NAME_MAP_FILE) + 2);
16230 strcpy (name, dirname);
16231 name[dirlen] = '/';
16232 strcpy (name + dirlen + separator_needed, FILE_NAME_MAP_FILE);
16233 f = fopen (name, "r");
16234 free (name);
16235 if (!f)
16236 map_list_ptr->map_list_map = NULL;
16237 else
16238 {
16239 int ch;
5ff904cd 16240
c7e4ee3a
CB
16241 while ((ch = getc (f)) != EOF)
16242 {
16243 char *from, *to;
16244 struct file_name_map *ptr;
16245
16246 if (is_space[ch])
16247 continue;
16248 from = read_filename_string (ch, f);
16249 while ((ch = getc (f)) != EOF && is_hor_space[ch])
16250 ;
16251 to = read_filename_string (ch, f);
5ff904cd 16252
c7e4ee3a
CB
16253 ptr = ((struct file_name_map *)
16254 xmalloc (sizeof (struct file_name_map)));
16255 ptr->map_from = from;
5ff904cd 16256
c7e4ee3a
CB
16257 /* Make the real filename absolute. */
16258 if (*to == '/')
16259 ptr->map_to = to;
16260 else
16261 {
16262 ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
16263 strcpy (ptr->map_to, dirname);
16264 ptr->map_to[dirlen] = '/';
16265 strcpy (ptr->map_to + dirlen + separator_needed, to);
16266 free (to);
16267 }
5ff904cd 16268
c7e4ee3a
CB
16269 ptr->map_next = map_list_ptr->map_list_map;
16270 map_list_ptr->map_list_map = ptr;
5ff904cd 16271
c7e4ee3a
CB
16272 while ((ch = getc (f)) != '\n')
16273 if (ch == EOF)
16274 break;
16275 }
16276 fclose (f);
5ff904cd
JL
16277 }
16278
c7e4ee3a
CB
16279 map_list_ptr->map_list_next = map_list;
16280 map_list = map_list_ptr;
5ff904cd 16281
c7e4ee3a 16282 return map_list_ptr->map_list_map;
5ff904cd
JL
16283}
16284
c7e4ee3a
CB
16285static void
16286ffecom_file_ (char *name)
5ff904cd 16287{
c7e4ee3a 16288 FILE_BUF *fp;
5ff904cd 16289
c7e4ee3a
CB
16290 /* Do partial setup of input buffer for the sake of generating
16291 early #line directives (when -g is in effect). */
5ff904cd 16292
c7e4ee3a
CB
16293 fp = &instack[++indepth];
16294 memset ((char *) fp, 0, sizeof (FILE_BUF));
16295 if (name == NULL)
16296 name = "";
16297 fp->nominal_fname = fp->fname = name;
16298}
5ff904cd 16299
c7e4ee3a 16300/* Initialize syntactic classifications of characters. */
5ff904cd 16301
c7e4ee3a
CB
16302static void
16303ffecom_initialize_char_syntax_ ()
16304{
16305 register int i;
5ff904cd 16306
c7e4ee3a
CB
16307 /*
16308 * Set up is_idchar and is_idstart tables. These should be
16309 * faster than saying (is_alpha (c) || c == '_'), etc.
16310 * Set up these things before calling any routines tthat
16311 * refer to them.
16312 */
16313 for (i = 'a'; i <= 'z'; i++) {
16314 is_idchar[i - 'a' + 'A'] = 1;
16315 is_idchar[i] = 1;
16316 is_idstart[i - 'a' + 'A'] = 1;
16317 is_idstart[i] = 1;
16318 }
16319 for (i = '0'; i <= '9'; i++)
16320 is_idchar[i] = 1;
16321 is_idchar['_'] = 1;
16322 is_idstart['_'] = 1;
5ff904cd 16323
c7e4ee3a
CB
16324 /* horizontal space table */
16325 is_hor_space[' '] = 1;
16326 is_hor_space['\t'] = 1;
16327 is_hor_space['\v'] = 1;
16328 is_hor_space['\f'] = 1;
16329 is_hor_space['\r'] = 1;
5ff904cd 16330
c7e4ee3a
CB
16331 is_space[' '] = 1;
16332 is_space['\t'] = 1;
16333 is_space['\v'] = 1;
16334 is_space['\f'] = 1;
16335 is_space['\n'] = 1;
16336 is_space['\r'] = 1;
16337}
5ff904cd 16338
c7e4ee3a
CB
16339static void
16340ffecom_close_include_ (FILE *f)
16341{
16342 fclose (f);
5ff904cd 16343
c7e4ee3a
CB
16344 indepth--;
16345 input_file_stack_tick++;
5ff904cd 16346
c7e4ee3a
CB
16347 ffewhere_line_kill (instack[indepth].line);
16348 ffewhere_column_kill (instack[indepth].column);
16349}
5ff904cd 16350
c7e4ee3a
CB
16351static int
16352ffecom_decode_include_option_ (char *spec)
16353{
16354 struct file_name_list *dirtmp;
16355
16356 if (! ignore_srcdir && !strcmp (spec, "-"))
16357 ignore_srcdir = 1;
16358 else
16359 {
16360 dirtmp = (struct file_name_list *)
16361 xmalloc (sizeof (struct file_name_list));
16362 dirtmp->next = 0; /* New one goes on the end */
16363 if (spec[0] != 0)
16364 dirtmp->fname = spec;
16365 else
16366 fatal ("Directory name must immediately follow -I option with no intervening spaces, as in `-Idir', not `-I dir'");
16367 dirtmp->got_name_map = 0;
16368 append_include_chain (dirtmp, dirtmp);
16369 }
16370 return 1;
5ff904cd
JL
16371}
16372
c7e4ee3a
CB
16373/* Open INCLUDEd file. */
16374
16375static FILE *
16376ffecom_open_include_ (char *name, ffewhereLine l, ffewhereColumn c)
5ff904cd 16377{
c7e4ee3a
CB
16378 char *fbeg = name;
16379 size_t flen = strlen (fbeg);
16380 struct file_name_list *search_start = include; /* Chain of dirs to search */
16381 struct file_name_list dsp[1]; /* First in chain, if #include "..." */
16382 struct file_name_list *searchptr = 0;
16383 char *fname; /* Dynamically allocated fname buffer */
16384 FILE *f;
16385 FILE_BUF *fp;
5ff904cd 16386
c7e4ee3a
CB
16387 if (flen == 0)
16388 return NULL;
5ff904cd 16389
c7e4ee3a 16390 dsp[0].fname = NULL;
5ff904cd 16391
c7e4ee3a
CB
16392 /* If -I- was specified, don't search current dir, only spec'd ones. */
16393 if (!ignore_srcdir)
16394 {
16395 for (fp = &instack[indepth]; fp >= instack; fp--)
16396 {
16397 int n;
16398 char *ep;
16399 char *nam;
5ff904cd 16400
c7e4ee3a
CB
16401 if ((nam = fp->nominal_fname) != NULL)
16402 {
16403 /* Found a named file. Figure out dir of the file,
16404 and put it in front of the search list. */
16405 dsp[0].next = search_start;
16406 search_start = dsp;
16407#ifndef VMS
16408 ep = rindex (nam, '/');
16409#ifdef DIR_SEPARATOR
16410 if (ep == NULL) ep = rindex (nam, DIR_SEPARATOR);
16411 else {
16412 char *tmp = rindex (nam, DIR_SEPARATOR);
16413 if (tmp != NULL && tmp > ep) ep = tmp;
16414 }
16415#endif
16416#else /* VMS */
16417 ep = rindex (nam, ']');
16418 if (ep == NULL) ep = rindex (nam, '>');
16419 if (ep == NULL) ep = rindex (nam, ':');
16420 if (ep != NULL) ep++;
16421#endif /* VMS */
16422 if (ep != NULL)
16423 {
16424 n = ep - nam;
16425 dsp[0].fname = (char *) xmalloc (n + 1);
16426 strncpy (dsp[0].fname, nam, n);
16427 dsp[0].fname[n] = '\0';
16428 if (n + INCLUDE_LEN_FUDGE > max_include_len)
16429 max_include_len = n + INCLUDE_LEN_FUDGE;
16430 }
16431 else
16432 dsp[0].fname = NULL; /* Current directory */
16433 dsp[0].got_name_map = 0;
16434 break;
16435 }
16436 }
16437 }
5ff904cd 16438
c7e4ee3a
CB
16439 /* Allocate this permanently, because it gets stored in the definitions
16440 of macros. */
16441 fname = xmalloc (max_include_len + flen + 4);
16442 /* + 2 above for slash and terminating null. */
16443 /* + 2 added for '.h' on VMS (to support '#include filename') (NOT USED
16444 for g77 yet). */
5ff904cd 16445
c7e4ee3a 16446 /* If specified file name is absolute, just open it. */
5ff904cd 16447
c7e4ee3a
CB
16448 if (*fbeg == '/'
16449#ifdef DIR_SEPARATOR
16450 || *fbeg == DIR_SEPARATOR
16451#endif
16452 )
16453 {
16454 strncpy (fname, (char *) fbeg, flen);
16455 fname[flen] = 0;
16456 f = open_include_file (fname, NULL_PTR);
5ff904cd 16457 }
c7e4ee3a
CB
16458 else
16459 {
16460 f = NULL;
5ff904cd 16461
c7e4ee3a
CB
16462 /* Search directory path, trying to open the file.
16463 Copy each filename tried into FNAME. */
5ff904cd 16464
c7e4ee3a
CB
16465 for (searchptr = search_start; searchptr; searchptr = searchptr->next)
16466 {
16467 if (searchptr->fname)
16468 {
16469 /* The empty string in a search path is ignored.
16470 This makes it possible to turn off entirely
16471 a standard piece of the list. */
16472 if (searchptr->fname[0] == 0)
16473 continue;
16474 strcpy (fname, skip_redundant_dir_prefix (searchptr->fname));
16475 if (fname[0] && fname[strlen (fname) - 1] != '/')
16476 strcat (fname, "/");
16477 fname[strlen (fname) + flen] = 0;
16478 }
16479 else
16480 fname[0] = 0;
5ff904cd 16481
c7e4ee3a
CB
16482 strncat (fname, fbeg, flen);
16483#ifdef VMS
16484 /* Change this 1/2 Unix 1/2 VMS file specification into a
16485 full VMS file specification */
16486 if (searchptr->fname && (searchptr->fname[0] != 0))
16487 {
16488 /* Fix up the filename */
16489 hack_vms_include_specification (fname);
16490 }
16491 else
16492 {
16493 /* This is a normal VMS filespec, so use it unchanged. */
16494 strncpy (fname, (char *) fbeg, flen);
16495 fname[flen] = 0;
16496#if 0 /* Not for g77. */
16497 /* if it's '#include filename', add the missing .h */
16498 if (index (fname, '.') == NULL)
16499 strcat (fname, ".h");
5ff904cd 16500#endif
c7e4ee3a
CB
16501 }
16502#endif /* VMS */
16503 f = open_include_file (fname, searchptr);
16504#ifdef EACCES
16505 if (f == NULL && errno == EACCES)
16506 {
16507 print_containing_files (FFEBAD_severityWARNING);
16508 ffebad_start_msg ("At %0, INCLUDE file %A exists, but is not readable",
16509 FFEBAD_severityWARNING);
16510 ffebad_string (fname);
16511 ffebad_here (0, l, c);
16512 ffebad_finish ();
16513 }
16514#endif
16515 if (f != NULL)
16516 break;
16517 }
16518 }
5ff904cd 16519
c7e4ee3a 16520 if (f == NULL)
5ff904cd 16521 {
c7e4ee3a 16522 /* A file that was not found. */
5ff904cd 16523
c7e4ee3a
CB
16524 strncpy (fname, (char *) fbeg, flen);
16525 fname[flen] = 0;
16526 print_containing_files (ffebad_severity (FFEBAD_OPEN_INCLUDE));
16527 ffebad_start (FFEBAD_OPEN_INCLUDE);
16528 ffebad_here (0, l, c);
16529 ffebad_string (fname);
16530 ffebad_finish ();
5ff904cd
JL
16531 }
16532
c7e4ee3a
CB
16533 if (dsp[0].fname != NULL)
16534 free (dsp[0].fname);
5ff904cd 16535
c7e4ee3a
CB
16536 if (f == NULL)
16537 return NULL;
5ff904cd 16538
c7e4ee3a
CB
16539 if (indepth >= (INPUT_STACK_MAX - 1))
16540 {
16541 print_containing_files (FFEBAD_severityFATAL);
16542 ffebad_start_msg ("At %0, INCLUDE nesting too deep",
16543 FFEBAD_severityFATAL);
16544 ffebad_string (fname);
16545 ffebad_here (0, l, c);
16546 ffebad_finish ();
16547 return NULL;
16548 }
5ff904cd 16549
c7e4ee3a
CB
16550 instack[indepth].line = ffewhere_line_use (l);
16551 instack[indepth].column = ffewhere_column_use (c);
5ff904cd 16552
c7e4ee3a
CB
16553 fp = &instack[indepth + 1];
16554 memset ((char *) fp, 0, sizeof (FILE_BUF));
16555 fp->nominal_fname = fp->fname = fname;
16556 fp->dir = searchptr;
5ff904cd 16557
c7e4ee3a
CB
16558 indepth++;
16559 input_file_stack_tick++;
5ff904cd 16560
c7e4ee3a
CB
16561 return f;
16562}
16563#endif /* FFECOM_GCC_INCLUDE */
5ff904cd 16564
c7e4ee3a
CB
16565/**INDENT* (Do not reformat this comment even with -fca option.)
16566 Data-gathering files: Given the source file listed below, compiled with
16567 f2c I obtained the output file listed after that, and from the output
16568 file I derived the above code.
5ff904cd 16569
c7e4ee3a
CB
16570-------- (begin input file to f2c)
16571 implicit none
16572 character*10 A1,A2
16573 complex C1,C2
16574 integer I1,I2
16575 real R1,R2
16576 double precision D1,D2
16577C
16578 call getem(A1,A2,C1,C2,I1,I2,R1,R2,D1,D2)
16579c /
16580 call fooI(I1/I2)
16581 call fooR(R1/I1)
16582 call fooD(D1/I1)
16583 call fooC(C1/I1)
16584 call fooR(R1/R2)
16585 call fooD(R1/D1)
16586 call fooD(D1/D2)
16587 call fooD(D1/R1)
16588 call fooC(C1/C2)
16589 call fooC(C1/R1)
16590 call fooZ(C1/D1)
16591c **
16592 call fooI(I1**I2)
16593 call fooR(R1**I1)
16594 call fooD(D1**I1)
16595 call fooC(C1**I1)
16596 call fooR(R1**R2)
16597 call fooD(R1**D1)
16598 call fooD(D1**D2)
16599 call fooD(D1**R1)
16600 call fooC(C1**C2)
16601 call fooC(C1**R1)
16602 call fooZ(C1**D1)
16603c FFEINTRIN_impABS
16604 call fooR(ABS(R1))
16605c FFEINTRIN_impACOS
16606 call fooR(ACOS(R1))
16607c FFEINTRIN_impAIMAG
16608 call fooR(AIMAG(C1))
16609c FFEINTRIN_impAINT
16610 call fooR(AINT(R1))
16611c FFEINTRIN_impALOG
16612 call fooR(ALOG(R1))
16613c FFEINTRIN_impALOG10
16614 call fooR(ALOG10(R1))
16615c FFEINTRIN_impAMAX0
16616 call fooR(AMAX0(I1,I2))
16617c FFEINTRIN_impAMAX1
16618 call fooR(AMAX1(R1,R2))
16619c FFEINTRIN_impAMIN0
16620 call fooR(AMIN0(I1,I2))
16621c FFEINTRIN_impAMIN1
16622 call fooR(AMIN1(R1,R2))
16623c FFEINTRIN_impAMOD
16624 call fooR(AMOD(R1,R2))
16625c FFEINTRIN_impANINT
16626 call fooR(ANINT(R1))
16627c FFEINTRIN_impASIN
16628 call fooR(ASIN(R1))
16629c FFEINTRIN_impATAN
16630 call fooR(ATAN(R1))
16631c FFEINTRIN_impATAN2
16632 call fooR(ATAN2(R1,R2))
16633c FFEINTRIN_impCABS
16634 call fooR(CABS(C1))
16635c FFEINTRIN_impCCOS
16636 call fooC(CCOS(C1))
16637c FFEINTRIN_impCEXP
16638 call fooC(CEXP(C1))
16639c FFEINTRIN_impCHAR
16640 call fooA(CHAR(I1))
16641c FFEINTRIN_impCLOG
16642 call fooC(CLOG(C1))
16643c FFEINTRIN_impCONJG
16644 call fooC(CONJG(C1))
16645c FFEINTRIN_impCOS
16646 call fooR(COS(R1))
16647c FFEINTRIN_impCOSH
16648 call fooR(COSH(R1))
16649c FFEINTRIN_impCSIN
16650 call fooC(CSIN(C1))
16651c FFEINTRIN_impCSQRT
16652 call fooC(CSQRT(C1))
16653c FFEINTRIN_impDABS
16654 call fooD(DABS(D1))
16655c FFEINTRIN_impDACOS
16656 call fooD(DACOS(D1))
16657c FFEINTRIN_impDASIN
16658 call fooD(DASIN(D1))
16659c FFEINTRIN_impDATAN
16660 call fooD(DATAN(D1))
16661c FFEINTRIN_impDATAN2
16662 call fooD(DATAN2(D1,D2))
16663c FFEINTRIN_impDCOS
16664 call fooD(DCOS(D1))
16665c FFEINTRIN_impDCOSH
16666 call fooD(DCOSH(D1))
16667c FFEINTRIN_impDDIM
16668 call fooD(DDIM(D1,D2))
16669c FFEINTRIN_impDEXP
16670 call fooD(DEXP(D1))
16671c FFEINTRIN_impDIM
16672 call fooR(DIM(R1,R2))
16673c FFEINTRIN_impDINT
16674 call fooD(DINT(D1))
16675c FFEINTRIN_impDLOG
16676 call fooD(DLOG(D1))
16677c FFEINTRIN_impDLOG10
16678 call fooD(DLOG10(D1))
16679c FFEINTRIN_impDMAX1
16680 call fooD(DMAX1(D1,D2))
16681c FFEINTRIN_impDMIN1
16682 call fooD(DMIN1(D1,D2))
16683c FFEINTRIN_impDMOD
16684 call fooD(DMOD(D1,D2))
16685c FFEINTRIN_impDNINT
16686 call fooD(DNINT(D1))
16687c FFEINTRIN_impDPROD
16688 call fooD(DPROD(R1,R2))
16689c FFEINTRIN_impDSIGN
16690 call fooD(DSIGN(D1,D2))
16691c FFEINTRIN_impDSIN
16692 call fooD(DSIN(D1))
16693c FFEINTRIN_impDSINH
16694 call fooD(DSINH(D1))
16695c FFEINTRIN_impDSQRT
16696 call fooD(DSQRT(D1))
16697c FFEINTRIN_impDTAN
16698 call fooD(DTAN(D1))
16699c FFEINTRIN_impDTANH
16700 call fooD(DTANH(D1))
16701c FFEINTRIN_impEXP
16702 call fooR(EXP(R1))
16703c FFEINTRIN_impIABS
16704 call fooI(IABS(I1))
16705c FFEINTRIN_impICHAR
16706 call fooI(ICHAR(A1))
16707c FFEINTRIN_impIDIM
16708 call fooI(IDIM(I1,I2))
16709c FFEINTRIN_impIDNINT
16710 call fooI(IDNINT(D1))
16711c FFEINTRIN_impINDEX
16712 call fooI(INDEX(A1,A2))
16713c FFEINTRIN_impISIGN
16714 call fooI(ISIGN(I1,I2))
16715c FFEINTRIN_impLEN
16716 call fooI(LEN(A1))
16717c FFEINTRIN_impLGE
16718 call fooL(LGE(A1,A2))
16719c FFEINTRIN_impLGT
16720 call fooL(LGT(A1,A2))
16721c FFEINTRIN_impLLE
16722 call fooL(LLE(A1,A2))
16723c FFEINTRIN_impLLT
16724 call fooL(LLT(A1,A2))
16725c FFEINTRIN_impMAX0
16726 call fooI(MAX0(I1,I2))
16727c FFEINTRIN_impMAX1
16728 call fooI(MAX1(R1,R2))
16729c FFEINTRIN_impMIN0
16730 call fooI(MIN0(I1,I2))
16731c FFEINTRIN_impMIN1
16732 call fooI(MIN1(R1,R2))
16733c FFEINTRIN_impMOD
16734 call fooI(MOD(I1,I2))
16735c FFEINTRIN_impNINT
16736 call fooI(NINT(R1))
16737c FFEINTRIN_impSIGN
16738 call fooR(SIGN(R1,R2))
16739c FFEINTRIN_impSIN
16740 call fooR(SIN(R1))
16741c FFEINTRIN_impSINH
16742 call fooR(SINH(R1))
16743c FFEINTRIN_impSQRT
16744 call fooR(SQRT(R1))
16745c FFEINTRIN_impTAN
16746 call fooR(TAN(R1))
16747c FFEINTRIN_impTANH
16748 call fooR(TANH(R1))
16749c FFEINTRIN_imp_CMPLX_C
16750 call fooC(cmplx(C1,C2))
16751c FFEINTRIN_imp_CMPLX_D
16752 call fooZ(cmplx(D1,D2))
16753c FFEINTRIN_imp_CMPLX_I
16754 call fooC(cmplx(I1,I2))
16755c FFEINTRIN_imp_CMPLX_R
16756 call fooC(cmplx(R1,R2))
16757c FFEINTRIN_imp_DBLE_C
16758 call fooD(dble(C1))
16759c FFEINTRIN_imp_DBLE_D
16760 call fooD(dble(D1))
16761c FFEINTRIN_imp_DBLE_I
16762 call fooD(dble(I1))
16763c FFEINTRIN_imp_DBLE_R
16764 call fooD(dble(R1))
16765c FFEINTRIN_imp_INT_C
16766 call fooI(int(C1))
16767c FFEINTRIN_imp_INT_D
16768 call fooI(int(D1))
16769c FFEINTRIN_imp_INT_I
16770 call fooI(int(I1))
16771c FFEINTRIN_imp_INT_R
16772 call fooI(int(R1))
16773c FFEINTRIN_imp_REAL_C
16774 call fooR(real(C1))
16775c FFEINTRIN_imp_REAL_D
16776 call fooR(real(D1))
16777c FFEINTRIN_imp_REAL_I
16778 call fooR(real(I1))
16779c FFEINTRIN_imp_REAL_R
16780 call fooR(real(R1))
16781c
16782c FFEINTRIN_imp_INT_D:
16783c
16784c FFEINTRIN_specIDINT
16785 call fooI(IDINT(D1))
16786c
16787c FFEINTRIN_imp_INT_R:
16788c
16789c FFEINTRIN_specIFIX
16790 call fooI(IFIX(R1))
16791c FFEINTRIN_specINT
16792 call fooI(INT(R1))
16793c
16794c FFEINTRIN_imp_REAL_D:
16795c
16796c FFEINTRIN_specSNGL
16797 call fooR(SNGL(D1))
16798c
16799c FFEINTRIN_imp_REAL_I:
16800c
16801c FFEINTRIN_specFLOAT
16802 call fooR(FLOAT(I1))
16803c FFEINTRIN_specREAL
16804 call fooR(REAL(I1))
16805c
16806 end
16807-------- (end input file to f2c)
5ff904cd 16808
c7e4ee3a
CB
16809-------- (begin output from providing above input file as input to:
16810-------- `f2c | gcc -E -C - | sed -e "s:/[*]*://:g" -e "s:[*]*[/]://:g" \
16811-------- -e "s:^#.*$::g"')
5ff904cd 16812
c7e4ee3a
CB
16813// -- translated by f2c (version 19950223).
16814 You must link the resulting object file with the libraries:
16815 -lf2c -lm (in that order)
16816//
5ff904cd 16817
5ff904cd 16818
c7e4ee3a 16819// f2c.h -- Standard Fortran to C header file //
5ff904cd 16820
c7e4ee3a 16821/// barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed."
5ff904cd 16822
c7e4ee3a 16823 - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) //
5ff904cd 16824
5ff904cd 16825
5ff904cd 16826
5ff904cd 16827
c7e4ee3a
CB
16828// F2C_INTEGER will normally be `int' but would be `long' on 16-bit systems //
16829// we assume short, float are OK //
16830typedef long int // long int // integer;
16831typedef char *address;
16832typedef short int shortint;
16833typedef float real;
16834typedef double doublereal;
16835typedef struct { real r, i; } complex;
16836typedef struct { doublereal r, i; } doublecomplex;
16837typedef long int // long int // logical;
16838typedef short int shortlogical;
16839typedef char logical1;
16840typedef char integer1;
16841// typedef long long longint; // // system-dependent //
5ff904cd 16842
5ff904cd 16843
5ff904cd 16844
5ff904cd 16845
c7e4ee3a 16846// Extern is for use with -E //
5ff904cd 16847
5ff904cd 16848
5ff904cd 16849
5ff904cd 16850
c7e4ee3a 16851// I/O stuff //
5ff904cd 16852
5ff904cd 16853
5ff904cd 16854
5ff904cd 16855
5ff904cd 16856
5ff904cd 16857
5ff904cd 16858
5ff904cd 16859
c7e4ee3a
CB
16860typedef long int // int or long int // flag;
16861typedef long int // int or long int // ftnlen;
16862typedef long int // int or long int // ftnint;
5ff904cd 16863
5ff904cd 16864
c7e4ee3a
CB
16865//external read, write//
16866typedef struct
16867{ flag cierr;
16868 ftnint ciunit;
16869 flag ciend;
16870 char *cifmt;
16871 ftnint cirec;
16872} cilist;
5ff904cd 16873
c7e4ee3a
CB
16874//internal read, write//
16875typedef struct
16876{ flag icierr;
16877 char *iciunit;
16878 flag iciend;
16879 char *icifmt;
16880 ftnint icirlen;
16881 ftnint icirnum;
16882} icilist;
5ff904cd 16883
c7e4ee3a
CB
16884//open//
16885typedef struct
16886{ flag oerr;
16887 ftnint ounit;
16888 char *ofnm;
16889 ftnlen ofnmlen;
16890 char *osta;
16891 char *oacc;
16892 char *ofm;
16893 ftnint orl;
16894 char *oblnk;
16895} olist;
5ff904cd 16896
c7e4ee3a
CB
16897//close//
16898typedef struct
16899{ flag cerr;
16900 ftnint cunit;
16901 char *csta;
16902} cllist;
5ff904cd 16903
c7e4ee3a
CB
16904//rewind, backspace, endfile//
16905typedef struct
16906{ flag aerr;
16907 ftnint aunit;
16908} alist;
5ff904cd 16909
c7e4ee3a
CB
16910// inquire //
16911typedef struct
16912{ flag inerr;
16913 ftnint inunit;
16914 char *infile;
16915 ftnlen infilen;
16916 ftnint *inex; //parameters in standard's order//
16917 ftnint *inopen;
16918 ftnint *innum;
16919 ftnint *innamed;
16920 char *inname;
16921 ftnlen innamlen;
16922 char *inacc;
16923 ftnlen inacclen;
16924 char *inseq;
16925 ftnlen inseqlen;
16926 char *indir;
16927 ftnlen indirlen;
16928 char *infmt;
16929 ftnlen infmtlen;
16930 char *inform;
16931 ftnint informlen;
16932 char *inunf;
16933 ftnlen inunflen;
16934 ftnint *inrecl;
16935 ftnint *innrec;
16936 char *inblank;
16937 ftnlen inblanklen;
16938} inlist;
5ff904cd 16939
5ff904cd 16940
5ff904cd 16941
c7e4ee3a
CB
16942union Multitype { // for multiple entry points //
16943 integer1 g;
16944 shortint h;
16945 integer i;
16946 // longint j; //
16947 real r;
16948 doublereal d;
16949 complex c;
16950 doublecomplex z;
16951 };
16952
16953typedef union Multitype Multitype;
5ff904cd 16954
c7e4ee3a 16955typedef long Long; // No longer used; formerly in Namelist //
5ff904cd 16956
c7e4ee3a
CB
16957struct Vardesc { // for Namelist //
16958 char *name;
16959 char *addr;
16960 ftnlen *dims;
16961 int type;
16962 };
16963typedef struct Vardesc Vardesc;
5ff904cd 16964
c7e4ee3a
CB
16965struct Namelist {
16966 char *name;
16967 Vardesc **vars;
16968 int nvars;
16969 };
16970typedef struct Namelist Namelist;
5ff904cd 16971
5ff904cd 16972
5ff904cd 16973
5ff904cd 16974
5ff904cd 16975
5ff904cd 16976
5ff904cd 16977
5ff904cd 16978
c7e4ee3a 16979// procedure parameter types for -A and -C++ //
5ff904cd 16980
5ff904cd 16981
5ff904cd 16982
5ff904cd 16983
c7e4ee3a
CB
16984typedef int // Unknown procedure type // (*U_fp)();
16985typedef shortint (*J_fp)();
16986typedef integer (*I_fp)();
16987typedef real (*R_fp)();
16988typedef doublereal (*D_fp)(), (*E_fp)();
16989typedef // Complex // void (*C_fp)();
16990typedef // Double Complex // void (*Z_fp)();
16991typedef logical (*L_fp)();
16992typedef shortlogical (*K_fp)();
16993typedef // Character // void (*H_fp)();
16994typedef // Subroutine // int (*S_fp)();
5ff904cd 16995
c7e4ee3a
CB
16996// E_fp is for real functions when -R is not specified //
16997typedef void C_f; // complex function //
16998typedef void H_f; // character function //
16999typedef void Z_f; // double complex function //
17000typedef doublereal E_f; // real function with -R not specified //
5ff904cd 17001
c7e4ee3a 17002// undef any lower-case symbols that your C compiler predefines, e.g.: //
5ff904cd 17003
5ff904cd 17004
c7e4ee3a
CB
17005// (No such symbols should be defined in a strict ANSI C compiler.
17006 We can avoid trouble with f2c-translated code by using
17007 gcc -ansi [-traditional].) //
17008
5ff904cd 17009
5ff904cd 17010
5ff904cd 17011
5ff904cd 17012
5ff904cd 17013
5ff904cd 17014
5ff904cd 17015
5ff904cd 17016
5ff904cd 17017
5ff904cd 17018
5ff904cd 17019
5ff904cd 17020
5ff904cd 17021
5ff904cd 17022
5ff904cd 17023
5ff904cd 17024
5ff904cd 17025
5ff904cd 17026
5ff904cd 17027
5ff904cd 17028
5ff904cd 17029
5ff904cd 17030
c7e4ee3a
CB
17031// Main program // MAIN__()
17032{
17033 // System generated locals //
17034 integer i__1;
17035 real r__1, r__2;
17036 doublereal d__1, d__2;
17037 complex q__1;
17038 doublecomplex z__1, z__2, z__3;
17039 logical L__1;
17040 char ch__1[1];
17041
17042 // Builtin functions //
17043 void c_div();
17044 integer pow_ii();
17045 double pow_ri(), pow_di();
17046 void pow_ci();
17047 double pow_dd();
17048 void pow_zz();
17049 double acos(), r_imag(), r_int(), log(), r_lg10(), r_mod(), r_nint(),
17050 asin(), atan(), atan2(), c_abs();
17051 void c_cos(), c_exp(), c_log(), r_cnjg();
17052 double cos(), cosh();
17053 void c_sin(), c_sqrt();
17054 double d_dim(), exp(), r_dim(), d_int(), d_lg10(), d_mod(), d_nint(),
17055 d_sign(), sin(), sinh(), sqrt(), tan(), tanh();
17056 integer i_dim(), i_dnnt(), i_indx(), i_sign(), i_len();
17057 logical l_ge(), l_gt(), l_le(), l_lt();
17058 integer i_nint();
17059 double r_sign();
17060
17061 // Local variables //
17062 extern // Subroutine // int fooa_(), fooc_(), food_(), fooi_(), foor_(),
17063 fool_(), fooz_(), getem_();
17064 static char a1[10], a2[10];
17065 static complex c1, c2;
17066 static doublereal d1, d2;
17067 static integer i1, i2;
17068 static real r1, r2;
17069
17070
17071 getem_(a1, a2, &c1, &c2, &i1, &i2, &r1, &r2, &d1, &d2, 10L, 10L);
17072// / //
17073 i__1 = i1 / i2;
17074 fooi_(&i__1);
17075 r__1 = r1 / i1;
17076 foor_(&r__1);
17077 d__1 = d1 / i1;
17078 food_(&d__1);
17079 d__1 = (doublereal) i1;
17080 q__1.r = c1.r / d__1, q__1.i = c1.i / d__1;
17081 fooc_(&q__1);
17082 r__1 = r1 / r2;
17083 foor_(&r__1);
17084 d__1 = r1 / d1;
17085 food_(&d__1);
17086 d__1 = d1 / d2;
17087 food_(&d__1);
17088 d__1 = d1 / r1;
17089 food_(&d__1);
17090 c_div(&q__1, &c1, &c2);
17091 fooc_(&q__1);
17092 q__1.r = c1.r / r1, q__1.i = c1.i / r1;
17093 fooc_(&q__1);
17094 z__1.r = c1.r / d1, z__1.i = c1.i / d1;
17095 fooz_(&z__1);
17096// ** //
17097 i__1 = pow_ii(&i1, &i2);
17098 fooi_(&i__1);
17099 r__1 = pow_ri(&r1, &i1);
17100 foor_(&r__1);
17101 d__1 = pow_di(&d1, &i1);
17102 food_(&d__1);
17103 pow_ci(&q__1, &c1, &i1);
17104 fooc_(&q__1);
17105 d__1 = (doublereal) r1;
17106 d__2 = (doublereal) r2;
17107 r__1 = pow_dd(&d__1, &d__2);
17108 foor_(&r__1);
17109 d__2 = (doublereal) r1;
17110 d__1 = pow_dd(&d__2, &d1);
17111 food_(&d__1);
17112 d__1 = pow_dd(&d1, &d2);
17113 food_(&d__1);
17114 d__2 = (doublereal) r1;
17115 d__1 = pow_dd(&d1, &d__2);
17116 food_(&d__1);
17117 z__2.r = c1.r, z__2.i = c1.i;
17118 z__3.r = c2.r, z__3.i = c2.i;
17119 pow_zz(&z__1, &z__2, &z__3);
17120 q__1.r = z__1.r, q__1.i = z__1.i;
17121 fooc_(&q__1);
17122 z__2.r = c1.r, z__2.i = c1.i;
17123 z__3.r = r1, z__3.i = 0.;
17124 pow_zz(&z__1, &z__2, &z__3);
17125 q__1.r = z__1.r, q__1.i = z__1.i;
17126 fooc_(&q__1);
17127 z__2.r = c1.r, z__2.i = c1.i;
17128 z__3.r = d1, z__3.i = 0.;
17129 pow_zz(&z__1, &z__2, &z__3);
17130 fooz_(&z__1);
17131// FFEINTRIN_impABS //
17132 r__1 = (doublereal)(( r1 ) >= 0 ? ( r1 ) : -( r1 )) ;
17133 foor_(&r__1);
17134// FFEINTRIN_impACOS //
17135 r__1 = acos(r1);
17136 foor_(&r__1);
17137// FFEINTRIN_impAIMAG //
17138 r__1 = r_imag(&c1);
17139 foor_(&r__1);
17140// FFEINTRIN_impAINT //
17141 r__1 = r_int(&r1);
17142 foor_(&r__1);
17143// FFEINTRIN_impALOG //
17144 r__1 = log(r1);
17145 foor_(&r__1);
17146// FFEINTRIN_impALOG10 //
17147 r__1 = r_lg10(&r1);
17148 foor_(&r__1);
17149// FFEINTRIN_impAMAX0 //
17150 r__1 = (real) (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
17151 foor_(&r__1);
17152// FFEINTRIN_impAMAX1 //
17153 r__1 = (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
17154 foor_(&r__1);
17155// FFEINTRIN_impAMIN0 //
17156 r__1 = (real) (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
17157 foor_(&r__1);
17158// FFEINTRIN_impAMIN1 //
17159 r__1 = (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
17160 foor_(&r__1);
17161// FFEINTRIN_impAMOD //
17162 r__1 = r_mod(&r1, &r2);
17163 foor_(&r__1);
17164// FFEINTRIN_impANINT //
17165 r__1 = r_nint(&r1);
17166 foor_(&r__1);
17167// FFEINTRIN_impASIN //
17168 r__1 = asin(r1);
17169 foor_(&r__1);
17170// FFEINTRIN_impATAN //
17171 r__1 = atan(r1);
17172 foor_(&r__1);
17173// FFEINTRIN_impATAN2 //
17174 r__1 = atan2(r1, r2);
17175 foor_(&r__1);
17176// FFEINTRIN_impCABS //
17177 r__1 = c_abs(&c1);
17178 foor_(&r__1);
17179// FFEINTRIN_impCCOS //
17180 c_cos(&q__1, &c1);
17181 fooc_(&q__1);
17182// FFEINTRIN_impCEXP //
17183 c_exp(&q__1, &c1);
17184 fooc_(&q__1);
17185// FFEINTRIN_impCHAR //
17186 *(unsigned char *)&ch__1[0] = i1;
17187 fooa_(ch__1, 1L);
17188// FFEINTRIN_impCLOG //
17189 c_log(&q__1, &c1);
17190 fooc_(&q__1);
17191// FFEINTRIN_impCONJG //
17192 r_cnjg(&q__1, &c1);
17193 fooc_(&q__1);
17194// FFEINTRIN_impCOS //
17195 r__1 = cos(r1);
17196 foor_(&r__1);
17197// FFEINTRIN_impCOSH //
17198 r__1 = cosh(r1);
17199 foor_(&r__1);
17200// FFEINTRIN_impCSIN //
17201 c_sin(&q__1, &c1);
17202 fooc_(&q__1);
17203// FFEINTRIN_impCSQRT //
17204 c_sqrt(&q__1, &c1);
17205 fooc_(&q__1);
17206// FFEINTRIN_impDABS //
17207 d__1 = (( d1 ) >= 0 ? ( d1 ) : -( d1 )) ;
17208 food_(&d__1);
17209// FFEINTRIN_impDACOS //
17210 d__1 = acos(d1);
17211 food_(&d__1);
17212// FFEINTRIN_impDASIN //
17213 d__1 = asin(d1);
17214 food_(&d__1);
17215// FFEINTRIN_impDATAN //
17216 d__1 = atan(d1);
17217 food_(&d__1);
17218// FFEINTRIN_impDATAN2 //
17219 d__1 = atan2(d1, d2);
17220 food_(&d__1);
17221// FFEINTRIN_impDCOS //
17222 d__1 = cos(d1);
17223 food_(&d__1);
17224// FFEINTRIN_impDCOSH //
17225 d__1 = cosh(d1);
17226 food_(&d__1);
17227// FFEINTRIN_impDDIM //
17228 d__1 = d_dim(&d1, &d2);
17229 food_(&d__1);
17230// FFEINTRIN_impDEXP //
17231 d__1 = exp(d1);
17232 food_(&d__1);
17233// FFEINTRIN_impDIM //
17234 r__1 = r_dim(&r1, &r2);
17235 foor_(&r__1);
17236// FFEINTRIN_impDINT //
17237 d__1 = d_int(&d1);
17238 food_(&d__1);
17239// FFEINTRIN_impDLOG //
17240 d__1 = log(d1);
17241 food_(&d__1);
17242// FFEINTRIN_impDLOG10 //
17243 d__1 = d_lg10(&d1);
17244 food_(&d__1);
17245// FFEINTRIN_impDMAX1 //
17246 d__1 = (( d1 ) >= ( d2 ) ? ( d1 ) : ( d2 )) ;
17247 food_(&d__1);
17248// FFEINTRIN_impDMIN1 //
17249 d__1 = (( d1 ) <= ( d2 ) ? ( d1 ) : ( d2 )) ;
17250 food_(&d__1);
17251// FFEINTRIN_impDMOD //
17252 d__1 = d_mod(&d1, &d2);
17253 food_(&d__1);
17254// FFEINTRIN_impDNINT //
17255 d__1 = d_nint(&d1);
17256 food_(&d__1);
17257// FFEINTRIN_impDPROD //
17258 d__1 = (doublereal) r1 * r2;
17259 food_(&d__1);
17260// FFEINTRIN_impDSIGN //
17261 d__1 = d_sign(&d1, &d2);
17262 food_(&d__1);
17263// FFEINTRIN_impDSIN //
17264 d__1 = sin(d1);
17265 food_(&d__1);
17266// FFEINTRIN_impDSINH //
17267 d__1 = sinh(d1);
17268 food_(&d__1);
17269// FFEINTRIN_impDSQRT //
17270 d__1 = sqrt(d1);
17271 food_(&d__1);
17272// FFEINTRIN_impDTAN //
17273 d__1 = tan(d1);
17274 food_(&d__1);
17275// FFEINTRIN_impDTANH //
17276 d__1 = tanh(d1);
17277 food_(&d__1);
17278// FFEINTRIN_impEXP //
17279 r__1 = exp(r1);
17280 foor_(&r__1);
17281// FFEINTRIN_impIABS //
17282 i__1 = (( i1 ) >= 0 ? ( i1 ) : -( i1 )) ;
17283 fooi_(&i__1);
17284// FFEINTRIN_impICHAR //
17285 i__1 = *(unsigned char *)a1;
17286 fooi_(&i__1);
17287// FFEINTRIN_impIDIM //
17288 i__1 = i_dim(&i1, &i2);
17289 fooi_(&i__1);
17290// FFEINTRIN_impIDNINT //
17291 i__1 = i_dnnt(&d1);
17292 fooi_(&i__1);
17293// FFEINTRIN_impINDEX //
17294 i__1 = i_indx(a1, a2, 10L, 10L);
17295 fooi_(&i__1);
17296// FFEINTRIN_impISIGN //
17297 i__1 = i_sign(&i1, &i2);
17298 fooi_(&i__1);
17299// FFEINTRIN_impLEN //
17300 i__1 = i_len(a1, 10L);
17301 fooi_(&i__1);
17302// FFEINTRIN_impLGE //
17303 L__1 = l_ge(a1, a2, 10L, 10L);
17304 fool_(&L__1);
17305// FFEINTRIN_impLGT //
17306 L__1 = l_gt(a1, a2, 10L, 10L);
17307 fool_(&L__1);
17308// FFEINTRIN_impLLE //
17309 L__1 = l_le(a1, a2, 10L, 10L);
17310 fool_(&L__1);
17311// FFEINTRIN_impLLT //
17312 L__1 = l_lt(a1, a2, 10L, 10L);
17313 fool_(&L__1);
17314// FFEINTRIN_impMAX0 //
17315 i__1 = (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
17316 fooi_(&i__1);
17317// FFEINTRIN_impMAX1 //
17318 i__1 = (integer) (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
17319 fooi_(&i__1);
17320// FFEINTRIN_impMIN0 //
17321 i__1 = (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
17322 fooi_(&i__1);
17323// FFEINTRIN_impMIN1 //
17324 i__1 = (integer) (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
17325 fooi_(&i__1);
17326// FFEINTRIN_impMOD //
17327 i__1 = i1 % i2;
17328 fooi_(&i__1);
17329// FFEINTRIN_impNINT //
17330 i__1 = i_nint(&r1);
17331 fooi_(&i__1);
17332// FFEINTRIN_impSIGN //
17333 r__1 = r_sign(&r1, &r2);
17334 foor_(&r__1);
17335// FFEINTRIN_impSIN //
17336 r__1 = sin(r1);
17337 foor_(&r__1);
17338// FFEINTRIN_impSINH //
17339 r__1 = sinh(r1);
17340 foor_(&r__1);
17341// FFEINTRIN_impSQRT //
17342 r__1 = sqrt(r1);
17343 foor_(&r__1);
17344// FFEINTRIN_impTAN //
17345 r__1 = tan(r1);
17346 foor_(&r__1);
17347// FFEINTRIN_impTANH //
17348 r__1 = tanh(r1);
17349 foor_(&r__1);
17350// FFEINTRIN_imp_CMPLX_C //
17351 r__1 = c1.r;
17352 r__2 = c2.r;
17353 q__1.r = r__1, q__1.i = r__2;
17354 fooc_(&q__1);
17355// FFEINTRIN_imp_CMPLX_D //
17356 z__1.r = d1, z__1.i = d2;
17357 fooz_(&z__1);
17358// FFEINTRIN_imp_CMPLX_I //
17359 r__1 = (real) i1;
17360 r__2 = (real) i2;
17361 q__1.r = r__1, q__1.i = r__2;
17362 fooc_(&q__1);
17363// FFEINTRIN_imp_CMPLX_R //
17364 q__1.r = r1, q__1.i = r2;
17365 fooc_(&q__1);
17366// FFEINTRIN_imp_DBLE_C //
17367 d__1 = (doublereal) c1.r;
17368 food_(&d__1);
17369// FFEINTRIN_imp_DBLE_D //
17370 d__1 = d1;
17371 food_(&d__1);
17372// FFEINTRIN_imp_DBLE_I //
17373 d__1 = (doublereal) i1;
17374 food_(&d__1);
17375// FFEINTRIN_imp_DBLE_R //
17376 d__1 = (doublereal) r1;
17377 food_(&d__1);
17378// FFEINTRIN_imp_INT_C //
17379 i__1 = (integer) c1.r;
17380 fooi_(&i__1);
17381// FFEINTRIN_imp_INT_D //
17382 i__1 = (integer) d1;
17383 fooi_(&i__1);
17384// FFEINTRIN_imp_INT_I //
17385 i__1 = i1;
17386 fooi_(&i__1);
17387// FFEINTRIN_imp_INT_R //
17388 i__1 = (integer) r1;
17389 fooi_(&i__1);
17390// FFEINTRIN_imp_REAL_C //
17391 r__1 = c1.r;
17392 foor_(&r__1);
17393// FFEINTRIN_imp_REAL_D //
17394 r__1 = (real) d1;
17395 foor_(&r__1);
17396// FFEINTRIN_imp_REAL_I //
17397 r__1 = (real) i1;
17398 foor_(&r__1);
17399// FFEINTRIN_imp_REAL_R //
17400 r__1 = r1;
17401 foor_(&r__1);
17402
17403// FFEINTRIN_imp_INT_D: //
17404
17405// FFEINTRIN_specIDINT //
17406 i__1 = (integer) d1;
17407 fooi_(&i__1);
17408
17409// FFEINTRIN_imp_INT_R: //
17410
17411// FFEINTRIN_specIFIX //
17412 i__1 = (integer) r1;
17413 fooi_(&i__1);
17414// FFEINTRIN_specINT //
17415 i__1 = (integer) r1;
17416 fooi_(&i__1);
17417
17418// FFEINTRIN_imp_REAL_D: //
5ff904cd 17419
c7e4ee3a
CB
17420// FFEINTRIN_specSNGL //
17421 r__1 = (real) d1;
17422 foor_(&r__1);
5ff904cd 17423
c7e4ee3a 17424// FFEINTRIN_imp_REAL_I: //
5ff904cd 17425
c7e4ee3a
CB
17426// FFEINTRIN_specFLOAT //
17427 r__1 = (real) i1;
17428 foor_(&r__1);
17429// FFEINTRIN_specREAL //
17430 r__1 = (real) i1;
17431 foor_(&r__1);
5ff904cd 17432
c7e4ee3a 17433} // MAIN__ //
5ff904cd 17434
c7e4ee3a 17435-------- (end output file from f2c)
5ff904cd 17436
c7e4ee3a 17437*/
This page took 2.241674 seconds and 5 git commands to generate.