]> gcc.gnu.org Git - gcc.git/blame - gcc/f/com.c
regclass.c (reg_scan_mark_refs): Return immediately if passed a NULL_RTX as an argument.
[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.
deec641e 3 Contributed by James Craig Burley (burley@gnu.org).
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);
63 ffecom_start_compstmt_ ();
64 // for stmts and decls inside function, do appropriate things;
65 ffecom_end_compstmt_ ();
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
234/* ~~tree.h SHOULD declare this, because toplev.c and dwarfout.c reference
235 it. */
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,
305};
306ffeinfoKindtype ffecom_pointer_kind_ = FFEINFO_basictypeNONE;
307ffeinfoKindtype ffecom_label_kind_ = FFEINFO_basictypeNONE;
308
309int ffecom_f2c_typecode_[FFEINFO_basictype][FFEINFO_kindtype];
310tree ffecom_f2c_integer_type_node;
311tree ffecom_f2c_ptr_to_integer_type_node;
312tree ffecom_f2c_address_type_node;
313tree ffecom_f2c_real_type_node;
314tree ffecom_f2c_ptr_to_real_type_node;
315tree ffecom_f2c_doublereal_type_node;
316tree ffecom_f2c_complex_type_node;
317tree ffecom_f2c_doublecomplex_type_node;
318tree ffecom_f2c_longint_type_node;
319tree ffecom_f2c_logical_type_node;
320tree ffecom_f2c_flag_type_node;
321tree ffecom_f2c_ftnlen_type_node;
322tree ffecom_f2c_ftnlen_zero_node;
323tree ffecom_f2c_ftnlen_one_node;
324tree ffecom_f2c_ftnlen_two_node;
325tree ffecom_f2c_ptr_to_ftnlen_type_node;
326tree ffecom_f2c_ftnint_type_node;
327tree ffecom_f2c_ptr_to_ftnint_type_node;
328#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
329
330/* Simple definitions and enumerations. */
331
332#ifndef FFECOM_sizeMAXSTACKITEM
333#define FFECOM_sizeMAXSTACKITEM 32*1024 /* Keep user-declared things
334 larger than this # bytes
335 off stack if possible. */
336#endif
337
338/* For systems that have large enough stacks, they should define
339 this to 0, and here, for ease of use later on, we just undefine
340 it if it is 0. */
341
342#if FFECOM_sizeMAXSTACKITEM == 0
343#undef FFECOM_sizeMAXSTACKITEM
344#endif
345
346typedef enum
347 {
348 FFECOM_rttypeVOID_,
6d433196 349 FFECOM_rttypeVOIDSTAR_, /* C's `void *' type. */
795232f7
JL
350 FFECOM_rttypeFTNINT_, /* f2c's `ftnint' type. */
351 FFECOM_rttypeINTEGER_, /* f2c's `integer' type. */
352 FFECOM_rttypeLONGINT_, /* f2c's `longint' type. */
353 FFECOM_rttypeLOGICAL_, /* f2c's `logical' type. */
354 FFECOM_rttypeREAL_F2C_, /* f2c's `real' returned as `double'. */
355 FFECOM_rttypeREAL_GNU_, /* `real' returned as such. */
5ff904cd 356 FFECOM_rttypeCOMPLEX_F2C_, /* f2c's `complex' returned via 1st arg. */
795232f7 357 FFECOM_rttypeCOMPLEX_GNU_, /* f2c's `complex' returned directly. */
5ff904cd 358 FFECOM_rttypeDOUBLE_, /* C's `double' type. */
795232f7 359 FFECOM_rttypeDOUBLEREAL_, /* f2c's `doublereal' type. */
5ff904cd 360 FFECOM_rttypeDBLCMPLX_F2C_, /* f2c's `doublecomplex' returned via 1st arg. */
795232f7 361 FFECOM_rttypeDBLCMPLX_GNU_, /* f2c's `doublecomplex' returned directly. */
5ff904cd
JL
362 FFECOM_rttypeCHARACTER_, /* f2c `char *'/`ftnlen' pair. */
363 FFECOM_rttype_
364 } ffecomRttype_;
365
366/* Internal typedefs. */
367
368#if FFECOM_targetCURRENT == FFECOM_targetGCC
369typedef struct _ffecom_concat_list_ ffecomConcatList_;
370typedef struct _ffecom_temp_ *ffecomTemp_;
371#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
372
373/* Private include files. */
374
375
376/* Internal structure definitions. */
377
378#if FFECOM_targetCURRENT == FFECOM_targetGCC
379struct _ffecom_concat_list_
380 {
381 ffebld *exprs;
382 int count;
383 int max;
384 ffetargetCharacterSize minlen;
385 ffetargetCharacterSize maxlen;
386 };
387
388struct _ffecom_temp_
389 {
390 ffecomTemp_ next;
391 tree type; /* Base type (w/o size/array applied). */
392 tree t;
393 ffetargetCharacterSize size;
394 int elements;
395 bool in_use;
396 bool auto_pop;
397 };
398
399#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
400
401/* Static functions (internal). */
402
403#if FFECOM_targetCURRENT == FFECOM_targetGCC
404static tree ffecom_arglist_expr_ (char *argstring, ffebld args);
405static tree ffecom_widest_expr_type_ (ffebld list);
406static bool ffecom_overlap_ (tree dest_decl, tree dest_offset,
407 tree dest_size, tree source_tree,
408 ffebld source, bool scalar_arg);
409static bool ffecom_args_overlapping_ (tree dest_tree, ffebld dest,
410 tree args, tree callee_commons,
411 bool scalar_args);
412static tree ffecom_build_f2c_string_ (int i, char *s);
413static tree ffecom_call_ (tree fn, ffeinfoKindtype kt,
414 bool is_f2c_complex, tree type,
415 tree args, tree dest_tree,
416 ffebld dest, bool *dest_used,
417 tree callee_commons, bool scalar_args);
418static tree ffecom_call_binop_ (tree fn, ffeinfoKindtype kt,
419 bool is_f2c_complex, tree type,
420 ffebld left, ffebld right,
421 tree dest_tree, ffebld dest,
422 bool *dest_used, tree callee_commons,
423 bool scalar_args);
86fc7a6c
CB
424static void ffecom_char_args_x_ (tree *xitem, tree *length,
425 ffebld expr, bool with_null);
5ff904cd
JL
426static tree ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy);
427static tree ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s);
428static ffecomConcatList_
429 ffecom_concat_list_gather_ (ffecomConcatList_ catlist,
430 ffebld expr,
431 ffetargetCharacterSize max);
432static void ffecom_concat_list_kill_ (ffecomConcatList_ catlist);
433static ffecomConcatList_ ffecom_concat_list_new_ (ffebld expr,
434 ffetargetCharacterSize max);
435static void ffecom_debug_kludge_ (tree aggr, char *aggr_type, ffesymbol member,
436 tree member_type, ffetargetOffset offset);
437static void ffecom_do_entry_ (ffesymbol fn, int entrynum);
092a4ef8
RH
438static tree ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
439 bool *dest_used, bool assignp, bool widenp);
5ff904cd
JL
440static tree ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
441 ffebld dest, bool *dest_used);
442static tree ffecom_expr_power_integer_ (ffebld left, ffebld right);
443static void ffecom_expr_transform_ (ffebld expr);
444static void ffecom_f2c_make_type_ (tree *type, int tcode, char *name);
445static void ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
446 int code);
447static ffeglobal ffecom_finish_global_ (ffeglobal global);
448static ffesymbol ffecom_finish_symbol_transform_ (ffesymbol s);
449static tree ffecom_get_appended_identifier_ (char us, char *text);
450static tree ffecom_get_external_identifier_ (ffesymbol s);
451static tree ffecom_get_identifier_ (char *text);
452static tree ffecom_gen_sfuncdef_ (ffesymbol s,
453 ffeinfoBasictype bt,
454 ffeinfoKindtype kt);
455static char *ffecom_gfrt_args_ (ffecomGfrt ix);
456static tree ffecom_gfrt_tree_ (ffecomGfrt ix);
457static tree ffecom_init_zero_ (tree decl);
458static tree ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
459 tree *maybe_tree);
460static tree ffecom_intrinsic_len_ (ffebld expr);
461static void ffecom_let_char_ (tree dest_tree,
462 tree dest_length,
463 ffetargetCharacterSize dest_size,
464 ffebld source);
465static void ffecom_make_gfrt_ (ffecomGfrt ix);
466static void ffecom_member_phase1_ (ffestorag mst, ffestorag st);
467#ifdef SOMEONE_GETS_DEBUG_SUPPORT_WORKING
468static void ffecom_member_phase2_ (ffestorag mst, ffestorag st);
469#endif
470static void ffecom_push_dummy_decls_ (ffebld dumlist,
471 bool stmtfunc);
472static void ffecom_start_progunit_ (void);
473static ffesymbol ffecom_sym_transform_ (ffesymbol s);
474static ffesymbol ffecom_sym_transform_assign_ (ffesymbol s);
475static void ffecom_transform_common_ (ffesymbol s);
476static void ffecom_transform_equiv_ (ffestorag st);
477static tree ffecom_transform_namelist_ (ffesymbol s);
478static void ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
479 tree t);
480static void ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
481 tree *size, tree tree);
482static tree ffecom_tree_divide_ (tree tree_type, tree left, tree right,
483 tree dest_tree, ffebld dest,
484 bool *dest_used);
485static tree ffecom_type_localvar_ (ffesymbol s,
486 ffeinfoBasictype bt,
487 ffeinfoKindtype kt);
488static tree ffecom_type_namelist_ (void);
489#if 0
490static tree ffecom_type_permanent_copy_ (tree t);
491#endif
492static tree ffecom_type_vardesc_ (void);
493static tree ffecom_vardesc_ (ffebld expr);
494static tree ffecom_vardesc_array_ (ffesymbol s);
495static tree ffecom_vardesc_dims_ (ffesymbol s);
496#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
497
498/* These are static functions that parallel those found in the C front
499 end and thus have the same names. */
500
501#if FFECOM_targetCURRENT == FFECOM_targetGCC
502static void bison_rule_compstmt_ (void);
503static void bison_rule_pushlevel_ (void);
504static tree builtin_function (char *name, tree type,
505 enum built_in_function function_code,
506 char *library_name);
507static int duplicate_decls (tree newdecl, tree olddecl);
508static void finish_decl (tree decl, tree init, bool is_top_level);
509static void finish_function (int nested);
8f87a563 510static char *lang_printable_name (tree decl, int v);
5ff904cd
JL
511static tree lookup_name_current_level (tree name);
512static struct binding_level *make_binding_level (void);
513static void pop_f_function_context (void);
514static void push_f_function_context (void);
515static void push_parm_decl (tree parm);
516static tree pushdecl_top_level (tree decl);
517static tree storedecls (tree decls);
518static void store_parm_decls (int is_main_program);
519static tree start_decl (tree decl, bool is_top_level);
520static void start_function (tree name, tree type, int nested, int public);
521#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
522#if FFECOM_GCC_INCLUDE
523static void ffecom_file_ (char *name);
524static void ffecom_initialize_char_syntax_ (void);
525static void ffecom_close_include_ (FILE *f);
526static int ffecom_decode_include_option_ (char *spec);
527static FILE *ffecom_open_include_ (char *name, ffewhereLine l,
528 ffewhereColumn c);
529#endif /* FFECOM_GCC_INCLUDE */
530
531/* Static objects accessed by functions in this module. */
532
533static ffesymbol ffecom_primary_entry_ = NULL;
534static ffesymbol ffecom_nested_entry_ = NULL;
535static ffeinfoKind ffecom_primary_entry_kind_;
536static bool ffecom_primary_entry_is_proc_;
537#if FFECOM_targetCURRENT == FFECOM_targetGCC
538static tree ffecom_outer_function_decl_;
539static tree ffecom_previous_function_decl_;
540static tree ffecom_which_entrypoint_decl_;
541static ffecomTemp_ ffecom_latest_temp_;
542static int ffecom_pending_calls_ = 0;
543static tree ffecom_float_zero_ = NULL_TREE;
544static tree ffecom_float_half_ = NULL_TREE;
545static tree ffecom_double_zero_ = NULL_TREE;
546static tree ffecom_double_half_ = NULL_TREE;
547static tree ffecom_func_result_;/* For functions. */
548static tree ffecom_func_length_;/* For CHARACTER fns. */
549static ffebld ffecom_list_blockdata_;
550static ffebld ffecom_list_common_;
551static ffebld ffecom_master_arglist_;
552static ffeinfoBasictype ffecom_master_bt_;
553static ffeinfoKindtype ffecom_master_kt_;
554static ffetargetCharacterSize ffecom_master_size_;
555static int ffecom_num_fns_ = 0;
556static int ffecom_num_entrypoints_ = 0;
557static bool ffecom_is_altreturning_ = FALSE;
558static tree ffecom_multi_type_node_;
559static tree ffecom_multi_retval_;
560static tree
561 ffecom_multi_fields_[FFEINFO_basictype][FFEINFO_kindtype];
562static bool ffecom_member_namelisted_; /* _member_phase1_ namelisted? */
563static bool ffecom_doing_entry_ = FALSE;
564static bool ffecom_transform_only_dummies_ = FALSE;
565
566/* Holds pointer-to-function expressions. */
567
568static tree ffecom_gfrt_[FFECOM_gfrt]
569=
570{
571#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) NULL_TREE,
572#include "com-rt.def"
573#undef DEFGFRT
574};
575
576/* Holds the external names of the functions. */
577
578static char *ffecom_gfrt_name_[FFECOM_gfrt]
579=
580{
581#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) NAME,
582#include "com-rt.def"
583#undef DEFGFRT
584};
585
586/* Whether the function returns. */
587
588static bool ffecom_gfrt_volatile_[FFECOM_gfrt]
589=
590{
591#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) VOLATILE,
592#include "com-rt.def"
593#undef DEFGFRT
594};
595
596/* Whether the function returns type complex. */
597
598static bool ffecom_gfrt_complex_[FFECOM_gfrt]
599=
600{
601#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) COMPLEX,
602#include "com-rt.def"
603#undef DEFGFRT
604};
605
606/* Type code for the function return value. */
607
608static ffecomRttype_ ffecom_gfrt_type_[FFECOM_gfrt]
609=
610{
611#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) TYPE,
612#include "com-rt.def"
613#undef DEFGFRT
614};
615
616/* String of codes for the function's arguments. */
617
618static char *ffecom_gfrt_argstring_[FFECOM_gfrt]
619=
620{
621#define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) ARGS,
622#include "com-rt.def"
623#undef DEFGFRT
624};
625#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
626
627/* Internal macros. */
628
629#if FFECOM_targetCURRENT == FFECOM_targetGCC
630
631/* We let tm.h override the types used here, to handle trivial differences
632 such as the choice of unsigned int or long unsigned int for size_t.
633 When machines start needing nontrivial differences in the size type,
634 it would be best to do something here to figure out automatically
635 from other information what type to use. */
636
637/* NOTE: g77 currently doesn't use these; see setting of sizetype and
638 change that if you need to. -- jcb 09/01/91. */
639
5ff904cd
JL
640#define ffecom_concat_list_count_(catlist) ((catlist).count)
641#define ffecom_concat_list_expr_(catlist,i) ((catlist).exprs[(i)])
642#define ffecom_concat_list_maxlen_(catlist) ((catlist).maxlen)
643#define ffecom_concat_list_minlen_(catlist) ((catlist).minlen)
644
645#define ffecom_start_compstmt_ bison_rule_pushlevel_
646#define ffecom_end_compstmt_ bison_rule_compstmt_
647
86fc7a6c
CB
648#define ffecom_char_args_(i,l,e) ffecom_char_args_x_((i),(l),(e),FALSE)
649#define ffecom_char_args_with_null_(i,l,e) ffecom_char_args_x_((i),(l),(e),TRUE)
650
5ff904cd
JL
651/* For each binding contour we allocate a binding_level structure
652 * which records the names defined in that contour.
653 * Contours include:
654 * 0) the global one
655 * 1) one for each function definition,
656 * where internal declarations of the parameters appear.
657 *
658 * The current meaning of a name can be found by searching the levels from
659 * the current one out to the global one.
660 */
661
662/* Note that the information in the `names' component of the global contour
663 is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
664
665struct binding_level
666 {
667 /* A chain of _DECL nodes for all variables, constants, functions, and
668 typedef types. These are in the reverse of the order supplied. */
669 tree names;
670
671 /* For each level (except not the global one), a chain of BLOCK nodes for
672 all the levels that were entered and exited one level down. */
673 tree blocks;
674
675 /* The BLOCK node for this level, if one has been preallocated. If 0, the
676 BLOCK is allocated (if needed) when the level is popped. */
677 tree this_block;
678
679 /* The binding level which this one is contained in (inherits from). */
680 struct binding_level *level_chain;
681 };
682
683#define NULL_BINDING_LEVEL (struct binding_level *) NULL
684
685/* The binding level currently in effect. */
686
687static struct binding_level *current_binding_level;
688
689/* A chain of binding_level structures awaiting reuse. */
690
691static struct binding_level *free_binding_level;
692
693/* The outermost binding level, for names of file scope.
694 This is created when the compiler is started and exists
695 through the entire run. */
696
697static struct binding_level *global_binding_level;
698
699/* Binding level structures are initialized by copying this one. */
700
701static struct binding_level clear_binding_level
702=
703{NULL, NULL, NULL, NULL_BINDING_LEVEL};
704
705/* Language-dependent contents of an identifier. */
706
707struct lang_identifier
708 {
709 struct tree_identifier ignore;
710 tree global_value, local_value, label_value;
711 bool invented;
712 };
713
714/* Macros for access to language-specific slots in an identifier. */
715/* Each of these slots contains a DECL node or null. */
716
717/* This represents the value which the identifier has in the
718 file-scope namespace. */
719#define IDENTIFIER_GLOBAL_VALUE(NODE) \
720 (((struct lang_identifier *)(NODE))->global_value)
721/* This represents the value which the identifier has in the current
722 scope. */
723#define IDENTIFIER_LOCAL_VALUE(NODE) \
724 (((struct lang_identifier *)(NODE))->local_value)
725/* This represents the value which the identifier has as a label in
726 the current label scope. */
727#define IDENTIFIER_LABEL_VALUE(NODE) \
728 (((struct lang_identifier *)(NODE))->label_value)
729/* This is nonzero if the identifier was "made up" by g77 code. */
730#define IDENTIFIER_INVENTED(NODE) \
731 (((struct lang_identifier *)(NODE))->invented)
732
733/* In identifiers, C uses the following fields in a special way:
734 TREE_PUBLIC to record that there was a previous local extern decl.
735 TREE_USED to record that such a decl was used.
736 TREE_ADDRESSABLE to record that the address of such a decl was used. */
737
738/* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
739 that have names. Here so we can clear out their names' definitions
740 at the end of the function. */
741
742static tree named_labels;
743
744/* A list of LABEL_DECLs from outer contexts that are currently shadowed. */
745
746static tree shadowed_labels;
747
748#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
749\f
750
751/* This is like gcc's stabilize_reference -- in fact, most of the code
752 comes from that -- but it handles the situation where the reference
753 is going to have its subparts picked at, and it shouldn't change
754 (or trigger extra invocations of functions in the subtrees) due to
755 this. save_expr is a bit overzealous, because we don't need the
756 entire thing calculated and saved like a temp. So, for DECLs, no
757 change is needed, because these are stable aggregates, and ARRAY_REF
758 and such might well be stable too, but for things like calculations,
759 we do need to calculate a snapshot of a value before picking at it. */
760
761#if FFECOM_targetCURRENT == FFECOM_targetGCC
762static tree
763ffecom_stabilize_aggregate_ (tree ref)
764{
765 tree result;
766 enum tree_code code = TREE_CODE (ref);
767
768 switch (code)
769 {
770 case VAR_DECL:
771 case PARM_DECL:
772 case RESULT_DECL:
773 /* No action is needed in this case. */
774 return ref;
775
776 case NOP_EXPR:
777 case CONVERT_EXPR:
778 case FLOAT_EXPR:
779 case FIX_TRUNC_EXPR:
780 case FIX_FLOOR_EXPR:
781 case FIX_ROUND_EXPR:
782 case FIX_CEIL_EXPR:
783 result = build_nt (code, stabilize_reference (TREE_OPERAND (ref, 0)));
784 break;
785
786 case INDIRECT_REF:
787 result = build_nt (INDIRECT_REF,
788 stabilize_reference_1 (TREE_OPERAND (ref, 0)));
789 break;
790
791 case COMPONENT_REF:
792 result = build_nt (COMPONENT_REF,
793 stabilize_reference (TREE_OPERAND (ref, 0)),
794 TREE_OPERAND (ref, 1));
795 break;
796
797 case BIT_FIELD_REF:
798 result = build_nt (BIT_FIELD_REF,
799 stabilize_reference (TREE_OPERAND (ref, 0)),
800 stabilize_reference_1 (TREE_OPERAND (ref, 1)),
801 stabilize_reference_1 (TREE_OPERAND (ref, 2)));
802 break;
803
804 case ARRAY_REF:
805 result = build_nt (ARRAY_REF,
806 stabilize_reference (TREE_OPERAND (ref, 0)),
807 stabilize_reference_1 (TREE_OPERAND (ref, 1)));
808 break;
809
810 case COMPOUND_EXPR:
811 result = build_nt (COMPOUND_EXPR,
812 stabilize_reference_1 (TREE_OPERAND (ref, 0)),
813 stabilize_reference (TREE_OPERAND (ref, 1)));
814 break;
815
816 case RTL_EXPR:
817 result = build1 (INDIRECT_REF, TREE_TYPE (ref),
818 save_expr (build1 (ADDR_EXPR,
819 build_pointer_type (TREE_TYPE (ref)),
820 ref)));
821 break;
822
823
824 default:
825 return save_expr (ref);
826
827 case ERROR_MARK:
828 return error_mark_node;
829 }
830
831 TREE_TYPE (result) = TREE_TYPE (ref);
832 TREE_READONLY (result) = TREE_READONLY (ref);
833 TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (ref);
834 TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (ref);
835 TREE_RAISES (result) = TREE_RAISES (ref);
836
837 return result;
838}
839#endif
840
841/* A rip-off of gcc's convert.c convert_to_complex function,
842 reworked to handle complex implemented as C structures
843 (RECORD_TYPE with two fields, real and imaginary `r' and `i'). */
844
845#if FFECOM_targetCURRENT == FFECOM_targetGCC
846static tree
847ffecom_convert_to_complex_ (tree type, tree expr)
848{
849 register enum tree_code form = TREE_CODE (TREE_TYPE (expr));
850 tree subtype;
851
852 assert (TREE_CODE (type) == RECORD_TYPE);
853
854 subtype = TREE_TYPE (TYPE_FIELDS (type));
855
856 if (form == REAL_TYPE || form == INTEGER_TYPE || form == ENUMERAL_TYPE)
857 {
858 expr = convert (subtype, expr);
859 return ffecom_2 (COMPLEX_EXPR, type, expr,
860 convert (subtype, integer_zero_node));
861 }
862
863 if (form == RECORD_TYPE)
864 {
865 tree elt_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr)));
866 if (TYPE_MAIN_VARIANT (elt_type) == TYPE_MAIN_VARIANT (subtype))
867 return expr;
868 else
869 {
870 expr = save_expr (expr);
871 return ffecom_2 (COMPLEX_EXPR,
872 type,
873 convert (subtype,
874 ffecom_1 (REALPART_EXPR,
875 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
876 expr)),
877 convert (subtype,
878 ffecom_1 (IMAGPART_EXPR,
879 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
880 expr)));
881 }
882 }
883
884 if (form == POINTER_TYPE || form == REFERENCE_TYPE)
885 error ("pointer value used where a complex was expected");
886 else
887 error ("aggregate value used where a complex was expected");
888
889 return ffecom_2 (COMPLEX_EXPR, type,
890 convert (subtype, integer_zero_node),
891 convert (subtype, integer_zero_node));
892}
893#endif
894
895/* Like gcc's convert(), but crashes if widening might happen. */
896
897#if FFECOM_targetCURRENT == FFECOM_targetGCC
898static tree
899ffecom_convert_narrow_ (type, expr)
900 tree type, expr;
901{
902 register tree e = expr;
903 register enum tree_code code = TREE_CODE (type);
904
905 if (type == TREE_TYPE (e)
906 || TREE_CODE (e) == ERROR_MARK)
907 return e;
908 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
909 return fold (build1 (NOP_EXPR, type, e));
910 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
911 || code == ERROR_MARK)
912 return error_mark_node;
913 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
914 {
915 assert ("void value not ignored as it ought to be" == NULL);
916 return error_mark_node;
917 }
918 assert (code != VOID_TYPE);
919 if ((code != RECORD_TYPE)
920 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
921 assert ("converting COMPLEX to REAL" == NULL);
922 assert (code != ENUMERAL_TYPE);
923 if (code == INTEGER_TYPE)
924 {
a74de6ea
CB
925 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
926 && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)))
927 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
928 && (TYPE_PRECISION (type)
929 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
5ff904cd
JL
930 return fold (convert_to_integer (type, e));
931 }
932 if (code == POINTER_TYPE)
933 {
934 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
935 return fold (convert_to_pointer (type, e));
936 }
937 if (code == REAL_TYPE)
938 {
939 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
940 assert (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)));
941 return fold (convert_to_real (type, e));
942 }
943 if (code == COMPLEX_TYPE)
944 {
945 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
946 assert (TYPE_PRECISION (TREE_TYPE (type)) <= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
947 return fold (convert_to_complex (type, e));
948 }
949 if (code == RECORD_TYPE)
950 {
951 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
270fc4e8
CB
952 /* Check that at least the first field name agrees. */
953 assert (DECL_NAME (TYPE_FIELDS (type))
954 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
5ff904cd
JL
955 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
956 <= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
270fc4e8
CB
957 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
958 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
959 return e;
5ff904cd
JL
960 return fold (ffecom_convert_to_complex_ (type, e));
961 }
962
963 assert ("conversion to non-scalar type requested" == NULL);
964 return error_mark_node;
965}
966#endif
967
968/* Like gcc's convert(), but crashes if narrowing might happen. */
969
970#if FFECOM_targetCURRENT == FFECOM_targetGCC
971static tree
972ffecom_convert_widen_ (type, expr)
973 tree type, expr;
974{
975 register tree e = expr;
976 register enum tree_code code = TREE_CODE (type);
977
978 if (type == TREE_TYPE (e)
979 || TREE_CODE (e) == ERROR_MARK)
980 return e;
981 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
982 return fold (build1 (NOP_EXPR, type, e));
983 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
984 || code == ERROR_MARK)
985 return error_mark_node;
986 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
987 {
988 assert ("void value not ignored as it ought to be" == NULL);
989 return error_mark_node;
990 }
991 assert (code != VOID_TYPE);
992 if ((code != RECORD_TYPE)
993 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
994 assert ("narrowing COMPLEX to REAL" == NULL);
995 assert (code != ENUMERAL_TYPE);
996 if (code == INTEGER_TYPE)
997 {
a74de6ea
CB
998 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
999 && TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)))
1000 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1001 && (TYPE_PRECISION (type)
1002 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
5ff904cd
JL
1003 return fold (convert_to_integer (type, e));
1004 }
1005 if (code == POINTER_TYPE)
1006 {
1007 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1008 return fold (convert_to_pointer (type, e));
1009 }
1010 if (code == REAL_TYPE)
1011 {
1012 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1013 assert (TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)));
1014 return fold (convert_to_real (type, e));
1015 }
1016 if (code == COMPLEX_TYPE)
1017 {
1018 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1019 assert (TYPE_PRECISION (TREE_TYPE (type)) >= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1020 return fold (convert_to_complex (type, e));
1021 }
1022 if (code == RECORD_TYPE)
1023 {
1024 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
270fc4e8
CB
1025 /* Check that at least the first field name agrees. */
1026 assert (DECL_NAME (TYPE_FIELDS (type))
1027 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
5ff904cd
JL
1028 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1029 >= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
270fc4e8
CB
1030 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1031 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1032 return e;
5ff904cd
JL
1033 return fold (ffecom_convert_to_complex_ (type, e));
1034 }
1035
1036 assert ("conversion to non-scalar type requested" == NULL);
1037 return error_mark_node;
1038}
1039#endif
1040
1041/* Handles making a COMPLEX type, either the standard
1042 (but buggy?) gbe way, or the safer (but less elegant?)
1043 f2c way. */
1044
1045#if FFECOM_targetCURRENT == FFECOM_targetGCC
1046static tree
1047ffecom_make_complex_type_ (tree subtype)
1048{
1049 tree type;
1050 tree realfield;
1051 tree imagfield;
1052
1053 if (ffe_is_emulate_complex ())
1054 {
1055 type = make_node (RECORD_TYPE);
1056 realfield = ffecom_decl_field (type, NULL_TREE, "r", subtype);
1057 imagfield = ffecom_decl_field (type, realfield, "i", subtype);
1058 TYPE_FIELDS (type) = realfield;
1059 layout_type (type);
1060 }
1061 else
1062 {
1063 type = make_node (COMPLEX_TYPE);
1064 TREE_TYPE (type) = subtype;
1065 layout_type (type);
1066 }
1067
1068 return type;
1069}
1070#endif
1071
1072/* Chooses either the gbe or the f2c way to build a
1073 complex constant. */
1074
1075#if FFECOM_targetCURRENT == FFECOM_targetGCC
1076static tree
1077ffecom_build_complex_constant_ (tree type, tree realpart, tree imagpart)
1078{
1079 tree bothparts;
1080
1081 if (ffe_is_emulate_complex ())
1082 {
1083 bothparts = build_tree_list (TYPE_FIELDS (type), realpart);
1084 TREE_CHAIN (bothparts) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), imagpart);
1085 bothparts = build (CONSTRUCTOR, type, NULL_TREE, bothparts);
1086 }
1087 else
1088 {
1089 bothparts = build_complex (type, realpart, imagpart);
1090 }
1091
1092 return bothparts;
1093}
1094#endif
1095
1096#if FFECOM_targetCURRENT == FFECOM_targetGCC
1097static tree
1098ffecom_arglist_expr_ (char *c, ffebld expr)
1099{
1100 tree list;
1101 tree *plist = &list;
1102 tree trail = NULL_TREE; /* Append char length args here. */
1103 tree *ptrail = &trail;
1104 tree length;
1105 ffebld exprh;
1106 tree item;
1107 bool ptr = FALSE;
1108 tree wanted = NULL_TREE;
e2fa159e
JL
1109 static char zed[] = "0";
1110
1111 if (c == NULL)
1112 c = &zed[0];
5ff904cd
JL
1113
1114 while (expr != NULL)
1115 {
1116 if (*c != '\0')
1117 {
1118 ptr = FALSE;
1119 if (*c == '&')
1120 {
1121 ptr = TRUE;
1122 ++c;
1123 }
1124 switch (*(c++))
1125 {
1126 case '\0':
1127 ptr = TRUE;
1128 wanted = NULL_TREE;
1129 break;
1130
1131 case 'a':
1132 assert (ptr);
1133 wanted = NULL_TREE;
1134 break;
1135
1136 case 'c':
1137 wanted = ffecom_f2c_complex_type_node;
1138 break;
1139
1140 case 'd':
1141 wanted = ffecom_f2c_doublereal_type_node;
1142 break;
1143
1144 case 'e':
1145 wanted = ffecom_f2c_doublecomplex_type_node;
1146 break;
1147
1148 case 'f':
1149 wanted = ffecom_f2c_real_type_node;
1150 break;
1151
1152 case 'i':
1153 wanted = ffecom_f2c_integer_type_node;
1154 break;
1155
1156 case 'j':
1157 wanted = ffecom_f2c_longint_type_node;
1158 break;
1159
1160 default:
1161 assert ("bad argstring code" == NULL);
1162 wanted = NULL_TREE;
1163 break;
1164 }
1165 }
1166
1167 exprh = ffebld_head (expr);
1168 if (exprh == NULL)
1169 wanted = NULL_TREE;
1170
1171 if ((wanted == NULL_TREE)
1172 || (ptr
1173 && (TYPE_MODE
1174 (ffecom_tree_type[ffeinfo_basictype (ffebld_info (exprh))]
1175 [ffeinfo_kindtype (ffebld_info (exprh))])
1176 == TYPE_MODE (wanted))))
1177 *plist
1178 = build_tree_list (NULL_TREE,
1179 ffecom_arg_ptr_to_expr (exprh,
1180 &length));
1181 else
1182 {
1183 item = ffecom_arg_expr (exprh, &length);
1184 item = ffecom_convert_widen_ (wanted, item);
1185 if (ptr)
1186 {
1187 item = ffecom_1 (ADDR_EXPR,
1188 build_pointer_type (TREE_TYPE (item)),
1189 item);
1190 }
1191 *plist
1192 = build_tree_list (NULL_TREE,
1193 item);
1194 }
1195
1196 plist = &TREE_CHAIN (*plist);
1197 expr = ffebld_trail (expr);
1198 if (length != NULL_TREE)
1199 {
1200 *ptrail = build_tree_list (NULL_TREE, length);
1201 ptrail = &TREE_CHAIN (*ptrail);
1202 }
1203 }
1204
e2fa159e
JL
1205 /* We've run out of args in the call; if the implementation expects
1206 more, supply null pointers for them, which the implementation can
1207 check to see if an arg was omitted. */
1208
1209 while (*c != '\0' && *c != '0')
1210 {
1211 if (*c == '&')
1212 ++c;
1213 else
1214 assert ("missing arg to run-time routine!" == NULL);
1215
1216 switch (*(c++))
1217 {
1218 case '\0':
1219 case 'a':
1220 case 'c':
1221 case 'd':
1222 case 'e':
1223 case 'f':
1224 case 'i':
1225 case 'j':
1226 break;
1227
1228 default:
1229 assert ("bad arg string code" == NULL);
1230 break;
1231 }
1232 *plist
1233 = build_tree_list (NULL_TREE,
1234 null_pointer_node);
1235 plist = &TREE_CHAIN (*plist);
1236 }
1237
5ff904cd
JL
1238 *plist = trail;
1239
1240 return list;
1241}
1242#endif
1243
1244#if FFECOM_targetCURRENT == FFECOM_targetGCC
1245static tree
1246ffecom_widest_expr_type_ (ffebld list)
1247{
1248 ffebld item;
1249 ffebld widest = NULL;
1250 ffetype type;
1251 ffetype widest_type = NULL;
1252 tree t;
1253
1254 for (; list != NULL; list = ffebld_trail (list))
1255 {
1256 item = ffebld_head (list);
1257 if (item == NULL)
1258 continue;
1259 if ((widest != NULL)
1260 && (ffeinfo_basictype (ffebld_info (item))
1261 != ffeinfo_basictype (ffebld_info (widest))))
1262 continue;
1263 type = ffeinfo_type (ffeinfo_basictype (ffebld_info (item)),
1264 ffeinfo_kindtype (ffebld_info (item)));
1265 if ((widest == FFEINFO_kindtypeNONE)
1266 || (ffetype_size (type)
1267 > ffetype_size (widest_type)))
1268 {
1269 widest = item;
1270 widest_type = type;
1271 }
1272 }
1273
1274 assert (widest != NULL);
1275 t = ffecom_tree_type[ffeinfo_basictype (ffebld_info (widest))]
1276 [ffeinfo_kindtype (ffebld_info (widest))];
1277 assert (t != NULL_TREE);
1278 return t;
1279}
1280#endif
1281
1282/* Check whether dest and source might overlap. ffebld versions of these
1283 might or might not be passed, will be NULL if not.
1284
1285 The test is really whether source_tree is modifiable and, if modified,
1286 might overlap destination such that the value(s) in the destination might
1287 change before it is finally modified. dest_* are the canonized
1288 destination itself. */
1289
1290#if FFECOM_targetCURRENT == FFECOM_targetGCC
1291static bool
1292ffecom_overlap_ (tree dest_decl, tree dest_offset, tree dest_size,
1293 tree source_tree, ffebld source UNUSED,
1294 bool scalar_arg)
1295{
1296 tree source_decl;
1297 tree source_offset;
1298 tree source_size;
1299 tree t;
1300
1301 if (source_tree == NULL_TREE)
1302 return FALSE;
1303
1304 switch (TREE_CODE (source_tree))
1305 {
1306 case ERROR_MARK:
1307 case IDENTIFIER_NODE:
1308 case INTEGER_CST:
1309 case REAL_CST:
1310 case COMPLEX_CST:
1311 case STRING_CST:
1312 case CONST_DECL:
1313 case VAR_DECL:
1314 case RESULT_DECL:
1315 case FIELD_DECL:
1316 case MINUS_EXPR:
1317 case MULT_EXPR:
1318 case TRUNC_DIV_EXPR:
1319 case CEIL_DIV_EXPR:
1320 case FLOOR_DIV_EXPR:
1321 case ROUND_DIV_EXPR:
1322 case TRUNC_MOD_EXPR:
1323 case CEIL_MOD_EXPR:
1324 case FLOOR_MOD_EXPR:
1325 case ROUND_MOD_EXPR:
1326 case RDIV_EXPR:
1327 case EXACT_DIV_EXPR:
1328 case FIX_TRUNC_EXPR:
1329 case FIX_CEIL_EXPR:
1330 case FIX_FLOOR_EXPR:
1331 case FIX_ROUND_EXPR:
1332 case FLOAT_EXPR:
1333 case EXPON_EXPR:
1334 case NEGATE_EXPR:
1335 case MIN_EXPR:
1336 case MAX_EXPR:
1337 case ABS_EXPR:
1338 case FFS_EXPR:
1339 case LSHIFT_EXPR:
1340 case RSHIFT_EXPR:
1341 case LROTATE_EXPR:
1342 case RROTATE_EXPR:
1343 case BIT_IOR_EXPR:
1344 case BIT_XOR_EXPR:
1345 case BIT_AND_EXPR:
1346 case BIT_ANDTC_EXPR:
1347 case BIT_NOT_EXPR:
1348 case TRUTH_ANDIF_EXPR:
1349 case TRUTH_ORIF_EXPR:
1350 case TRUTH_AND_EXPR:
1351 case TRUTH_OR_EXPR:
1352 case TRUTH_XOR_EXPR:
1353 case TRUTH_NOT_EXPR:
1354 case LT_EXPR:
1355 case LE_EXPR:
1356 case GT_EXPR:
1357 case GE_EXPR:
1358 case EQ_EXPR:
1359 case NE_EXPR:
1360 case COMPLEX_EXPR:
1361 case CONJ_EXPR:
1362 case REALPART_EXPR:
1363 case IMAGPART_EXPR:
1364 case LABEL_EXPR:
1365 case COMPONENT_REF:
1366 return FALSE;
1367
1368 case COMPOUND_EXPR:
1369 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1370 TREE_OPERAND (source_tree, 1), NULL,
1371 scalar_arg);
1372
1373 case MODIFY_EXPR:
1374 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1375 TREE_OPERAND (source_tree, 0), NULL,
1376 scalar_arg);
1377
1378 case CONVERT_EXPR:
1379 case NOP_EXPR:
1380 case NON_LVALUE_EXPR:
1381 case PLUS_EXPR:
1382 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1383 return TRUE;
1384
1385 ffecom_tree_canonize_ptr_ (&source_decl, &source_offset,
1386 source_tree);
1387 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1388 break;
1389
1390 case COND_EXPR:
1391 return
1392 ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1393 TREE_OPERAND (source_tree, 1), NULL,
1394 scalar_arg)
1395 || ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1396 TREE_OPERAND (source_tree, 2), NULL,
1397 scalar_arg);
1398
1399
1400 case ADDR_EXPR:
1401 ffecom_tree_canonize_ref_ (&source_decl, &source_offset,
1402 &source_size,
1403 TREE_OPERAND (source_tree, 0));
1404 break;
1405
1406 case PARM_DECL:
1407 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1408 return TRUE;
1409
1410 source_decl = source_tree;
1411 source_offset = size_zero_node;
1412 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1413 break;
1414
1415 case SAVE_EXPR:
1416 case REFERENCE_EXPR:
1417 case PREDECREMENT_EXPR:
1418 case PREINCREMENT_EXPR:
1419 case POSTDECREMENT_EXPR:
1420 case POSTINCREMENT_EXPR:
1421 case INDIRECT_REF:
1422 case ARRAY_REF:
1423 case CALL_EXPR:
1424 default:
1425 return TRUE;
1426 }
1427
1428 /* Come here when source_decl, source_offset, and source_size filled
1429 in appropriately. */
1430
1431 if (source_decl == NULL_TREE)
1432 return FALSE; /* No decl involved, so no overlap. */
1433
1434 if (source_decl != dest_decl)
1435 return FALSE; /* Different decl, no overlap. */
1436
1437 if (TREE_CODE (dest_size) == ERROR_MARK)
1438 return TRUE; /* Assignment into entire assumed-size
1439 array? Shouldn't happen.... */
1440
1441 t = ffecom_2 (LE_EXPR, integer_type_node,
1442 ffecom_2 (PLUS_EXPR, TREE_TYPE (dest_offset),
1443 dest_offset,
1444 convert (TREE_TYPE (dest_offset),
1445 dest_size)),
1446 convert (TREE_TYPE (dest_offset),
1447 source_offset));
1448
1449 if (integer_onep (t))
1450 return FALSE; /* Destination precedes source. */
1451
1452 if (!scalar_arg
1453 || (source_size == NULL_TREE)
1454 || (TREE_CODE (source_size) == ERROR_MARK)
1455 || integer_zerop (source_size))
1456 return TRUE; /* No way to tell if dest follows source. */
1457
1458 t = ffecom_2 (LE_EXPR, integer_type_node,
1459 ffecom_2 (PLUS_EXPR, TREE_TYPE (source_offset),
1460 source_offset,
1461 convert (TREE_TYPE (source_offset),
1462 source_size)),
1463 convert (TREE_TYPE (source_offset),
1464 dest_offset));
1465
1466 if (integer_onep (t))
1467 return FALSE; /* Destination follows source. */
1468
1469 return TRUE; /* Destination and source overlap. */
1470}
1471#endif
1472
1473/* Check whether dest might overlap any of a list of arguments or is
1474 in a COMMON area the callee might know about (and thus modify). */
1475
1476#if FFECOM_targetCURRENT == FFECOM_targetGCC
1477static bool
1478ffecom_args_overlapping_ (tree dest_tree, ffebld dest UNUSED,
1479 tree args, tree callee_commons,
1480 bool scalar_args)
1481{
1482 tree arg;
1483 tree dest_decl;
1484 tree dest_offset;
1485 tree dest_size;
1486
1487 ffecom_tree_canonize_ref_ (&dest_decl, &dest_offset, &dest_size,
1488 dest_tree);
1489
1490 if (dest_decl == NULL_TREE)
1491 return FALSE; /* Seems unlikely! */
1492
1493 /* If the decl cannot be determined reliably, or if its in COMMON
1494 and the callee isn't known to not futz with COMMON via other
1495 means, overlap might happen. */
1496
1497 if ((TREE_CODE (dest_decl) == ERROR_MARK)
1498 || ((callee_commons != NULL_TREE)
1499 && TREE_PUBLIC (dest_decl)))
1500 return TRUE;
1501
1502 for (; args != NULL_TREE; args = TREE_CHAIN (args))
1503 {
1504 if (((arg = TREE_VALUE (args)) != NULL_TREE)
1505 && ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1506 arg, NULL, scalar_args))
1507 return TRUE;
1508 }
1509
1510 return FALSE;
1511}
1512#endif
1513
1514/* Build a string for a variable name as used by NAMELIST. This means that
1515 if we're using the f2c library, we build an uppercase string, since
1516 f2c does this. */
1517
1518#if FFECOM_targetCURRENT == FFECOM_targetGCC
1519static tree
1520ffecom_build_f2c_string_ (int i, char *s)
1521{
1522 if (!ffe_is_f2c_library ())
1523 return build_string (i, s);
1524
1525 {
1526 char *tmp;
1527 char *p;
1528 char *q;
1529 char space[34];
1530 tree t;
1531
1532 if (((size_t) i) > ARRAY_SIZE (space))
1533 tmp = malloc_new_ks (malloc_pool_image (), "f2c_string", i);
1534 else
1535 tmp = &space[0];
1536
1537 for (p = s, q = tmp; *p != '\0'; ++p, ++q)
1538 *q = ffesrc_toupper (*p);
1539 *q = '\0';
1540
1541 t = build_string (i, tmp);
1542
1543 if (((size_t) i) > ARRAY_SIZE (space))
1544 malloc_kill_ks (malloc_pool_image (), tmp, i);
1545
1546 return t;
1547 }
1548}
1549
1550#endif
1551/* Returns CALL_EXPR or equivalent with given type (pass NULL_TREE for
1552 type to just get whatever the function returns), handling the
1553 f2c value-returning convention, if required, by prepending
1554 to the arglist a pointer to a temporary to receive the return value. */
1555
1556#if FFECOM_targetCURRENT == FFECOM_targetGCC
1557static tree
1558ffecom_call_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1559 tree type, tree args, tree dest_tree,
1560 ffebld dest, bool *dest_used, tree callee_commons,
1561 bool scalar_args)
1562{
1563 tree item;
1564 tree tempvar;
1565
1566 if (dest_used != NULL)
1567 *dest_used = FALSE;
1568
1569 if (is_f2c_complex)
1570 {
1571 if ((dest_used == NULL)
1572 || (dest == NULL)
1573 || (ffeinfo_basictype (ffebld_info (dest))
1574 != FFEINFO_basictypeCOMPLEX)
1575 || (ffeinfo_kindtype (ffebld_info (dest)) != kt)
1576 || ((type != NULL_TREE) && (TREE_TYPE (dest_tree) != type))
1577 || ffecom_args_overlapping_ (dest_tree, dest, args,
1578 callee_commons,
1579 scalar_args))
1580 {
1581 tempvar = ffecom_push_tempvar (ffecom_tree_type
1582 [FFEINFO_basictypeCOMPLEX][kt],
1583 FFETARGET_charactersizeNONE,
1584 -1, TRUE);
1585 }
1586 else
1587 {
1588 *dest_used = TRUE;
1589 tempvar = dest_tree;
1590 type = NULL_TREE;
1591 }
1592
1593 item
1594 = build_tree_list (NULL_TREE,
1595 ffecom_1 (ADDR_EXPR,
1596 build_pointer_type (TREE_TYPE (tempvar)),
1597 tempvar));
1598 TREE_CHAIN (item) = args;
1599
1600 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1601 item, NULL_TREE);
1602
1603 if (tempvar != dest_tree)
1604 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item, tempvar);
1605 }
1606 else
1607 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1608 args, NULL_TREE);
1609
1610 if ((type != NULL_TREE) && (TREE_TYPE (item) != type))
1611 item = ffecom_convert_narrow_ (type, item);
1612
1613 return item;
1614}
1615#endif
1616
1617/* Given two arguments, transform them and make a call to the given
1618 function via ffecom_call_. */
1619
1620#if FFECOM_targetCURRENT == FFECOM_targetGCC
1621static tree
1622ffecom_call_binop_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1623 tree type, ffebld left, ffebld right,
1624 tree dest_tree, ffebld dest, bool *dest_used,
1625 tree callee_commons, bool scalar_args)
1626{
1627 tree left_tree;
1628 tree right_tree;
1629 tree left_length;
1630 tree right_length;
1631
1632 ffecom_push_calltemps ();
1633 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
1634 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
1635 ffecom_pop_calltemps ();
1636
1637 left_tree = build_tree_list (NULL_TREE, left_tree);
1638 right_tree = build_tree_list (NULL_TREE, right_tree);
1639 TREE_CHAIN (left_tree) = right_tree;
1640
1641 if (left_length != NULL_TREE)
1642 {
1643 left_length = build_tree_list (NULL_TREE, left_length);
1644 TREE_CHAIN (right_tree) = left_length;
1645 }
1646
1647 if (right_length != NULL_TREE)
1648 {
1649 right_length = build_tree_list (NULL_TREE, right_length);
1650 if (left_length != NULL_TREE)
1651 TREE_CHAIN (left_length) = right_length;
1652 else
1653 TREE_CHAIN (right_tree) = right_length;
1654 }
1655
1656 return ffecom_call_ (fn, kt, is_f2c_complex, type, left_tree,
1657 dest_tree, dest, dest_used, callee_commons,
1658 scalar_args);
1659}
1660#endif
1661
86fc7a6c 1662/* ffecom_char_args_x_ -- Return ptr/length args for char subexpression
5ff904cd
JL
1663
1664 tree ptr_arg;
1665 tree length_arg;
1666 ffebld expr;
86fc7a6c
CB
1667 bool with_null;
1668 ffecom_char_args_x_(&ptr_arg,&length_arg,expr,with_null);
5ff904cd
JL
1669
1670 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
1671 subexpressions by constructing the appropriate trees for the ptr-to-
1672 character-text and length-of-character-text arguments in a calling
86fc7a6c
CB
1673 sequence.
1674
1675 Note that if with_null is TRUE, and the expression is an opCONTER,
1676 a null byte is appended to the string. */
5ff904cd
JL
1677
1678#if FFECOM_targetCURRENT == FFECOM_targetGCC
1679static void
86fc7a6c 1680ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
5ff904cd
JL
1681{
1682 tree item;
1683 tree high;
1684 ffetargetCharacter1 val;
86fc7a6c 1685 ffetargetCharacterSize newlen;
5ff904cd
JL
1686
1687 switch (ffebld_op (expr))
1688 {
1689 case FFEBLD_opCONTER:
1690 val = ffebld_constant_character1 (ffebld_conter (expr));
86fc7a6c
CB
1691 newlen = ffetarget_length_character1 (val);
1692 if (with_null)
1693 {
1694 if (newlen != 0)
1695 ++newlen; /* begin FFETARGET-NULL-KLUDGE. */
1696 }
1697 *length = build_int_2 (newlen, 0);
5ff904cd 1698 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
86fc7a6c 1699 high = build_int_2 (newlen, 0);
5ff904cd 1700 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
86fc7a6c 1701 item = build_string (newlen, /* end FFETARGET-NULL-KLUDGE. */
5ff904cd
JL
1702 ffetarget_text_character1 (val));
1703 TREE_TYPE (item)
1704 = build_type_variant
1705 (build_array_type
1706 (char_type_node,
1707 build_range_type
1708 (ffecom_f2c_ftnlen_type_node,
1709 ffecom_f2c_ftnlen_one_node,
1710 high)),
1711 1, 0);
1712 TREE_CONSTANT (item) = 1;
1713 TREE_STATIC (item) = 1;
1714 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
1715 item);
1716 break;
1717
1718 case FFEBLD_opSYMTER:
1719 {
1720 ffesymbol s = ffebld_symter (expr);
1721
1722 item = ffesymbol_hook (s).decl_tree;
1723 if (item == NULL_TREE)
1724 {
1725 s = ffecom_sym_transform_ (s);
1726 item = ffesymbol_hook (s).decl_tree;
1727 }
1728 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
1729 {
1730 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
1731 *length = ffesymbol_hook (s).length_tree;
1732 else
1733 {
1734 *length = build_int_2 (ffesymbol_size (s), 0);
1735 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
1736 }
1737 }
1738 else if (item == error_mark_node)
1739 *length = error_mark_node;
1740 else /* FFEINFO_kindFUNCTION: */
1741 *length = NULL_TREE;
1742 if (!ffesymbol_hook (s).addr
1743 && (item != error_mark_node))
1744 item = ffecom_1 (ADDR_EXPR,
1745 build_pointer_type (TREE_TYPE (item)),
1746 item);
1747 }
1748 break;
1749
1750 case FFEBLD_opARRAYREF:
1751 {
1752 ffebld dims[FFECOM_dimensionsMAX];
1753 tree array;
1754 int i;
1755
1756 ffecom_push_calltemps ();
1757 ffecom_char_args_ (&item, length, ffebld_left (expr));
1758 ffecom_pop_calltemps ();
1759
1760 if (item == error_mark_node || *length == error_mark_node)
1761 {
1762 item = *length = error_mark_node;
1763 break;
1764 }
1765
1766 /* Build up ARRAY_REFs in reverse order (since we're column major
1767 here in Fortran land). */
1768
1769 for (i = 0, expr = ffebld_right (expr);
1770 expr != NULL;
1771 expr = ffebld_trail (expr))
1772 dims[i++] = ffebld_head (expr);
1773
1774 for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
1775 i >= 0;
1776 --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
1777 {
1778 item = ffecom_2 (PLUS_EXPR, build_pointer_type (TREE_TYPE (array)),
1779 item,
1780 size_binop (MULT_EXPR,
1781 size_in_bytes (TREE_TYPE (array)),
1782 size_binop (MINUS_EXPR,
1783 ffecom_expr (dims[i]),
1784 TYPE_MIN_VALUE (TYPE_DOMAIN (array)))));
1785 }
1786 }
1787 break;
1788
1789 case FFEBLD_opSUBSTR:
1790 {
1791 ffebld start;
1792 ffebld end;
1793 ffebld thing = ffebld_right (expr);
1794 tree start_tree;
1795 tree end_tree;
1796
1797 assert (ffebld_op (thing) == FFEBLD_opITEM);
1798 start = ffebld_head (thing);
1799 thing = ffebld_trail (thing);
1800 assert (ffebld_trail (thing) == NULL);
1801 end = ffebld_head (thing);
1802
1803 ffecom_push_calltemps ();
1804 ffecom_char_args_ (&item, length, ffebld_left (expr));
1805 ffecom_pop_calltemps ();
1806
1807 if (item == error_mark_node || *length == error_mark_node)
1808 {
1809 item = *length = error_mark_node;
1810 break;
1811 }
1812
1813 if (start == NULL)
1814 {
1815 if (end == NULL)
1816 ;
1817 else
1818 {
1819 end_tree = convert (ffecom_f2c_ftnlen_type_node,
1820 ffecom_expr (end));
1821
1822 if (end_tree == error_mark_node)
1823 {
1824 item = *length = error_mark_node;
1825 break;
1826 }
1827
1828 *length = end_tree;
1829 }
1830 }
1831 else
1832 {
1833 start_tree = convert (ffecom_f2c_ftnlen_type_node,
1834 ffecom_expr (start));
1835
1836 if (start_tree == error_mark_node)
1837 {
1838 item = *length = error_mark_node;
1839 break;
1840 }
1841
1842 start_tree = ffecom_save_tree (start_tree);
1843
1844 item = ffecom_2 (PLUS_EXPR, TREE_TYPE (item),
1845 item,
1846 ffecom_2 (MINUS_EXPR,
1847 TREE_TYPE (start_tree),
1848 start_tree,
1849 ffecom_f2c_ftnlen_one_node));
1850
1851 if (end == NULL)
1852 {
1853 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
1854 ffecom_f2c_ftnlen_one_node,
1855 ffecom_2 (MINUS_EXPR,
1856 ffecom_f2c_ftnlen_type_node,
1857 *length,
1858 start_tree));
1859 }
1860 else
1861 {
1862 end_tree = convert (ffecom_f2c_ftnlen_type_node,
1863 ffecom_expr (end));
1864
1865 if (end_tree == error_mark_node)
1866 {
1867 item = *length = error_mark_node;
1868 break;
1869 }
1870
1871 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
1872 ffecom_f2c_ftnlen_one_node,
1873 ffecom_2 (MINUS_EXPR,
1874 ffecom_f2c_ftnlen_type_node,
1875 end_tree, start_tree));
1876 }
1877 }
1878 }
1879 break;
1880
1881 case FFEBLD_opFUNCREF:
1882 {
1883 ffesymbol s = ffebld_symter (ffebld_left (expr));
1884 tree tempvar;
1885 tree args;
1886 ffetargetCharacterSize size = ffeinfo_size (ffebld_info (expr));
1887 ffecomGfrt ix;
1888
1889 if (size == FFETARGET_charactersizeNONE)
1890 size = 24; /* ~~~~ Kludge alert! This should someday be fixed. */
1891
1892 *length = build_int_2 (size, 0);
1893 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
1894
1895 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
1896 == FFEINFO_whereINTRINSIC)
1897 {
1898 if (size == 1)
1899 { /* Invocation of an intrinsic returning CHARACTER*1. */
1900 item = ffecom_expr_intrinsic_ (expr, NULL_TREE,
1901 NULL, NULL);
1902 break;
1903 }
1904 ix = ffeintrin_gfrt_direct (ffebld_symter_implementation (ffebld_left (expr)));
1905 assert (ix != FFECOM_gfrt);
1906 item = ffecom_gfrt_tree_ (ix);
1907 }
1908 else
1909 {
1910 ix = FFECOM_gfrt;
1911 item = ffesymbol_hook (s).decl_tree;
1912 if (item == NULL_TREE)
1913 {
1914 s = ffecom_sym_transform_ (s);
1915 item = ffesymbol_hook (s).decl_tree;
1916 }
1917 if (item == error_mark_node)
1918 {
1919 item = *length = error_mark_node;
1920 break;
1921 }
1922
1923 if (!ffesymbol_hook (s).addr)
1924 item = ffecom_1_fn (item);
1925 }
1926
1927 assert (ffecom_pending_calls_ != 0);
1928 tempvar = ffecom_push_tempvar (char_type_node, size, -1, TRUE);
1929 tempvar = ffecom_1 (ADDR_EXPR,
1930 build_pointer_type (TREE_TYPE (tempvar)),
1931 tempvar);
1932
1933 ffecom_push_calltemps ();
1934
1935 args = build_tree_list (NULL_TREE, tempvar);
1936
1937 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT) /* Sfunc args by value. */
1938 TREE_CHAIN (args) = ffecom_list_expr (ffebld_right (expr));
1939 else
1940 {
1941 TREE_CHAIN (args) = build_tree_list (NULL_TREE, *length);
1942 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
1943 {
1944 TREE_CHAIN (TREE_CHAIN (args))
1945 = ffecom_arglist_expr_ (ffecom_gfrt_args_ (ix),
1946 ffebld_right (expr));
1947 }
1948 else
1949 {
1950 TREE_CHAIN (TREE_CHAIN (args))
1951 = ffecom_list_ptr_to_expr (ffebld_right (expr));
1952 }
1953 }
1954
1955 item = ffecom_3s (CALL_EXPR,
1956 TREE_TYPE (TREE_TYPE (TREE_TYPE (item))),
1957 item, args, NULL_TREE);
1958 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item,
1959 tempvar);
1960
1961 ffecom_pop_calltemps ();
1962 }
1963 break;
1964
1965 case FFEBLD_opCONVERT:
1966
1967 ffecom_push_calltemps ();
1968 ffecom_char_args_ (&item, length, ffebld_left (expr));
1969 ffecom_pop_calltemps ();
1970
1971 if (item == error_mark_node || *length == error_mark_node)
1972 {
1973 item = *length = error_mark_node;
1974 break;
1975 }
1976
1977 if ((ffebld_size_known (ffebld_left (expr))
1978 == FFETARGET_charactersizeNONE)
1979 || (ffebld_size_known (ffebld_left (expr)) < (ffebld_size (expr))))
1980 { /* Possible blank-padding needed, copy into
1981 temporary. */
1982 tree tempvar;
1983 tree args;
1984 tree newlen;
1985
1986 assert (ffecom_pending_calls_ != 0);
1987 tempvar = ffecom_push_tempvar (char_type_node,
1988 ffebld_size (expr), -1, TRUE);
1989 tempvar = ffecom_1 (ADDR_EXPR,
1990 build_pointer_type (TREE_TYPE (tempvar)),
1991 tempvar);
1992
1993 newlen = build_int_2 (ffebld_size (expr), 0);
1994 TREE_TYPE (newlen) = ffecom_f2c_ftnlen_type_node;
1995
1996 args = build_tree_list (NULL_TREE, tempvar);
1997 TREE_CHAIN (args) = build_tree_list (NULL_TREE, item);
1998 TREE_CHAIN (TREE_CHAIN (args)) = build_tree_list (NULL_TREE, newlen);
1999 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (args)))
2000 = build_tree_list (NULL_TREE, *length);
2001
2002 item = ffecom_call_gfrt (FFECOM_gfrtCOPY, args);
2003 TREE_SIDE_EFFECTS (item) = 1;
2004 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), fold (item),
2005 tempvar);
2006 *length = newlen;
2007 }
2008 else
2009 { /* Just truncate the length. */
2010 *length = build_int_2 (ffebld_size (expr), 0);
2011 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2012 }
2013 break;
2014
2015 default:
2016 assert ("bad op for single char arg expr" == NULL);
2017 item = NULL_TREE;
2018 break;
2019 }
2020
2021 *xitem = item;
2022}
2023#endif
2024
2025/* Check the size of the type to be sure it doesn't overflow the
2026 "portable" capacities of the compiler back end. `dummy' types
2027 can generally overflow the normal sizes as long as the computations
2028 themselves don't overflow. A particular target of the back end
2029 must still enforce its size requirements, though, and the back
2030 end takes care of this in stor-layout.c. */
2031
2032#if FFECOM_targetCURRENT == FFECOM_targetGCC
2033static tree
2034ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy)
2035{
2036 if (TREE_CODE (type) == ERROR_MARK)
2037 return type;
2038
2039 if (TYPE_SIZE (type) == NULL_TREE)
2040 return type;
2041
2042 if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
2043 return type;
2044
2045 if ((tree_int_cst_sgn (TYPE_SIZE (type)) < 0)
2b0c2df0
CB
2046 || (!dummy && (((TREE_INT_CST_HIGH (TYPE_SIZE (type)) != 0))
2047 || TREE_OVERFLOW (TYPE_SIZE (type)))))
5ff904cd
JL
2048 {
2049 ffebad_start (FFEBAD_ARRAY_LARGE);
2050 ffebad_string (ffesymbol_text (s));
2051 ffebad_here (0, ffesymbol_where_line (s), ffesymbol_where_column (s));
2052 ffebad_finish ();
2053
2054 return error_mark_node;
2055 }
2056
2057 return type;
2058}
2059#endif
2060
2061/* Builds a length argument (PARM_DECL). Also wraps type in an array type
2062 where the dimension info is (1:size) where <size> is ffesymbol_size(s) if
2063 known, length_arg if not known (FFETARGET_charactersizeNONE). */
2064
2065#if FFECOM_targetCURRENT == FFECOM_targetGCC
2066static tree
2067ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s)
2068{
2069 ffetargetCharacterSize sz = ffesymbol_size (s);
2070 tree highval;
2071 tree tlen;
2072 tree type = *xtype;
2073
2074 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
2075 tlen = NULL_TREE; /* A statement function, no length passed. */
2076 else
2077 {
2078 if (ffesymbol_where (s) == FFEINFO_whereDUMMY)
2079 tlen = ffecom_get_invented_identifier ("__g77_length_%s",
2080 ffesymbol_text (s), 0);
2081 else
2082 tlen = ffecom_get_invented_identifier ("__g77_%s",
2083 "length", 0);
2084 tlen = build_decl (PARM_DECL, tlen, ffecom_f2c_ftnlen_type_node);
2085#if BUILT_FOR_270
2086 DECL_ARTIFICIAL (tlen) = 1;
2087#endif
2088 }
2089
2090 if (sz == FFETARGET_charactersizeNONE)
2091 {
2092 assert (tlen != NULL_TREE);
2b0c2df0 2093 highval = variable_size (tlen);
5ff904cd
JL
2094 }
2095 else
2096 {
2097 highval = build_int_2 (sz, 0);
2098 TREE_TYPE (highval) = ffecom_f2c_ftnlen_type_node;
2099 }
2100
2101 type = build_array_type (type,
2102 build_range_type (ffecom_f2c_ftnlen_type_node,
2103 ffecom_f2c_ftnlen_one_node,
2104 highval));
2105
2106 *xtype = type;
2107 return tlen;
2108}
2109
2110#endif
2111/* ffecom_concat_list_gather_ -- Gather list of concatenated string exprs
2112
2113 ffecomConcatList_ catlist;
2114 ffebld expr; // expr of CHARACTER basictype.
2115 ffetargetCharacterSize max; // max chars to gather or _...NONE if no max
2116 catlist = ffecom_concat_list_gather_(catlist,expr,max);
2117
2118 Scans expr for character subexpressions, updates and returns catlist
2119 accordingly. */
2120
2121#if FFECOM_targetCURRENT == FFECOM_targetGCC
2122static ffecomConcatList_
2123ffecom_concat_list_gather_ (ffecomConcatList_ catlist, ffebld expr,
2124 ffetargetCharacterSize max)
2125{
2126 ffetargetCharacterSize sz;
2127
2128recurse: /* :::::::::::::::::::: */
2129
2130 if (expr == NULL)
2131 return catlist;
2132
2133 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen >= max))
2134 return catlist; /* Don't append any more items. */
2135
2136 switch (ffebld_op (expr))
2137 {
2138 case FFEBLD_opCONTER:
2139 case FFEBLD_opSYMTER:
2140 case FFEBLD_opARRAYREF:
2141 case FFEBLD_opFUNCREF:
2142 case FFEBLD_opSUBSTR:
2143 case FFEBLD_opCONVERT: /* Callers should strip this off beforehand
2144 if they don't need to preserve it. */
2145 if (catlist.count == catlist.max)
2146 { /* Make a (larger) list. */
2147 ffebld *newx;
2148 int newmax;
2149
2150 newmax = (catlist.max == 0) ? 8 : catlist.max * 2;
2151 newx = malloc_new_ks (malloc_pool_image (), "catlist",
2152 newmax * sizeof (newx[0]));
2153 if (catlist.max != 0)
2154 {
2155 memcpy (newx, catlist.exprs, catlist.max * sizeof (newx[0]));
2156 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2157 catlist.max * sizeof (newx[0]));
2158 }
2159 catlist.max = newmax;
2160 catlist.exprs = newx;
2161 }
2162 if ((sz = ffebld_size_known (expr)) != FFETARGET_charactersizeNONE)
2163 catlist.minlen += sz;
2164 else
2165 ++catlist.minlen; /* Not true for F90; can be 0 length. */
2166 if ((sz = ffebld_size_max (expr)) == FFETARGET_charactersizeNONE)
2167 catlist.maxlen = sz;
2168 else
2169 catlist.maxlen += sz;
2170 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen > max))
2171 { /* This item overlaps (or is beyond) the end
2172 of the destination. */
2173 switch (ffebld_op (expr))
2174 {
2175 case FFEBLD_opCONTER:
2176 case FFEBLD_opSYMTER:
2177 case FFEBLD_opARRAYREF:
2178 case FFEBLD_opFUNCREF:
2179 case FFEBLD_opSUBSTR:
2180 break; /* ~~Do useful truncations here. */
2181
2182 default:
2183 assert ("op changed or inconsistent switches!" == NULL);
2184 break;
2185 }
2186 }
2187 catlist.exprs[catlist.count++] = expr;
2188 return catlist;
2189
2190 case FFEBLD_opPAREN:
2191 expr = ffebld_left (expr);
2192 goto recurse; /* :::::::::::::::::::: */
2193
2194 case FFEBLD_opCONCATENATE:
2195 catlist = ffecom_concat_list_gather_ (catlist, ffebld_left (expr), max);
2196 expr = ffebld_right (expr);
2197 goto recurse; /* :::::::::::::::::::: */
2198
2199#if 0 /* Breaks passing small actual arg to larger
2200 dummy arg of sfunc */
2201 case FFEBLD_opCONVERT:
2202 expr = ffebld_left (expr);
2203 {
2204 ffetargetCharacterSize cmax;
2205
2206 cmax = catlist.len + ffebld_size_known (expr);
2207
2208 if ((max == FFETARGET_charactersizeNONE) || (max > cmax))
2209 max = cmax;
2210 }
2211 goto recurse; /* :::::::::::::::::::: */
2212#endif
2213
2214 case FFEBLD_opANY:
2215 return catlist;
2216
2217 default:
2218 assert ("bad op in _gather_" == NULL);
2219 return catlist;
2220 }
2221}
2222
2223#endif
2224/* ffecom_concat_list_kill_ -- Kill list of concatenated string exprs
2225
2226 ffecomConcatList_ catlist;
2227 ffecom_concat_list_kill_(catlist);
2228
2229 Anything allocated within the list info is deallocated. */
2230
2231#if FFECOM_targetCURRENT == FFECOM_targetGCC
2232static void
2233ffecom_concat_list_kill_ (ffecomConcatList_ catlist)
2234{
2235 if (catlist.max != 0)
2236 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2237 catlist.max * sizeof (catlist.exprs[0]));
2238}
2239
2240#endif
2241/* ffecom_concat_list_new_ -- Make list of concatenated string exprs
2242
2243 ffecomConcatList_ catlist;
2244 ffebld expr; // Root expr of CHARACTER basictype.
2245 ffetargetCharacterSize max; // max chars to gather or _...NONE if no max
2246 catlist = ffecom_concat_list_new_(expr,max);
2247
2248 Returns a flattened list of concatenated subexpressions given a
2249 tree of such expressions. */
2250
2251#if FFECOM_targetCURRENT == FFECOM_targetGCC
2252static ffecomConcatList_
2253ffecom_concat_list_new_ (ffebld expr, ffetargetCharacterSize max)
2254{
2255 ffecomConcatList_ catlist;
2256
2257 catlist.maxlen = catlist.minlen = catlist.max = catlist.count = 0;
2258 return ffecom_concat_list_gather_ (catlist, expr, max);
2259}
2260
2261#endif
2262
2263/* Provide some kind of useful info on member of aggregate area,
2264 since current g77/gcc technology does not provide debug info
2265 on these members. */
2266
2267#if FFECOM_targetCURRENT == FFECOM_targetGCC
2268static void
2269ffecom_debug_kludge_ (tree aggr, char *aggr_type, ffesymbol member,
2270 tree member_type UNUSED, ffetargetOffset offset)
2271{
2272 tree value;
2273 tree decl;
2274 int len;
2275 char *buff;
2276 char space[120];
2277#if 0
2278 tree type_id;
2279
2280 for (type_id = member_type;
2281 TREE_CODE (type_id) != IDENTIFIER_NODE;
2282 )
2283 {
2284 switch (TREE_CODE (type_id))
2285 {
2286 case INTEGER_TYPE:
2287 case REAL_TYPE:
2288 type_id = TYPE_NAME (type_id);
2289 break;
2290
2291 case ARRAY_TYPE:
2292 case COMPLEX_TYPE:
2293 type_id = TREE_TYPE (type_id);
2294 break;
2295
2296 default:
2297 assert ("no IDENTIFIER_NODE for type!" == NULL);
2298 type_id = error_mark_node;
2299 break;
2300 }
2301 }
2302#endif
2303
2304 if (ffecom_transform_only_dummies_
2305 || !ffe_is_debug_kludge ())
2306 return; /* Can't do this yet, maybe later. */
2307
2308 len = 60
2309 + strlen (aggr_type)
2310 + IDENTIFIER_LENGTH (DECL_NAME (aggr));
2311#if 0
2312 + IDENTIFIER_LENGTH (type_id);
2313#endif
2314
2315 if (((size_t) len) >= ARRAY_SIZE (space))
2316 buff = malloc_new_ks (malloc_pool_image (), "debug_kludge", len + 1);
2317 else
2318 buff = &space[0];
2319
2320 sprintf (&buff[0], "At (%s) `%s' plus %ld bytes",
2321 aggr_type,
2322 IDENTIFIER_POINTER (DECL_NAME (aggr)),
2323 (long int) offset);
2324
2325 value = build_string (len, buff);
2326 TREE_TYPE (value)
2327 = build_type_variant (build_array_type (char_type_node,
2328 build_range_type
2329 (integer_type_node,
2330 integer_one_node,
2331 build_int_2 (strlen (buff), 0))),
2332 1, 0);
2333 decl = build_decl (VAR_DECL,
2334 ffecom_get_identifier_ (ffesymbol_text (member)),
2335 TREE_TYPE (value));
2336 TREE_CONSTANT (decl) = 1;
2337 TREE_STATIC (decl) = 1;
2338 DECL_INITIAL (decl) = error_mark_node;
2339 DECL_IN_SYSTEM_HEADER (decl) = 1; /* Don't let -Wunused complain. */
2340 decl = start_decl (decl, FALSE);
2341 finish_decl (decl, value, FALSE);
2342
2343 if (buff != &space[0])
2344 malloc_kill_ks (malloc_pool_image (), buff, len + 1);
2345}
2346#endif
2347
2348/* ffecom_do_entry_ -- Do compilation of a particular entrypoint
2349
2350 ffesymbol fn; // the SUBROUTINE, FUNCTION, or ENTRY symbol itself
2351 int i; // entry# for this entrypoint (used by master fn)
2352 ffecom_do_entrypoint_(s,i);
2353
2354 Makes a public entry point that calls our private master fn (already
2355 compiled). */
2356
2357#if FFECOM_targetCURRENT == FFECOM_targetGCC
2358static void
2359ffecom_do_entry_ (ffesymbol fn, int entrynum)
2360{
2361 ffebld item;
2362 tree type; /* Type of function. */
2363 tree multi_retval; /* Var holding return value (union). */
2364 tree result; /* Var holding result. */
2365 ffeinfoBasictype bt;
2366 ffeinfoKindtype kt;
2367 ffeglobal g;
2368 ffeglobalType gt;
2369 bool charfunc; /* All entry points return same type
2370 CHARACTER. */
2371 bool cmplxfunc; /* Use f2c way of returning COMPLEX. */
2372 bool multi; /* Master fn has multiple return types. */
2373 bool altreturning = FALSE; /* This entry point has alternate returns. */
2374 int yes;
44d2eabc
JL
2375 int old_lineno = lineno;
2376 char *old_input_filename = input_filename;
2377
2378 input_filename = ffesymbol_where_filename (fn);
2379 lineno = ffesymbol_where_filelinenum (fn);
5ff904cd
JL
2380
2381 /* c-parse.y indeed does call suspend_momentary and not only ignores the
2382 return value, but also never calls resume_momentary, when starting an
2383 outer function (see "fndef:", "setspecs:", and so on). So g77 does the
2384 same thing. It shouldn't be a problem since start_function calls
2385 temporary_allocation, but it might be necessary. If it causes a problem
2386 here, then maybe there's a bug lurking in gcc. NOTE: This identical
2387 comment appears twice in thist file. */
2388
2389 suspend_momentary ();
2390
2391 ffecom_doing_entry_ = TRUE; /* Don't bother with array dimensions. */
2392
2393 switch (ffecom_primary_entry_kind_)
2394 {
2395 case FFEINFO_kindFUNCTION:
2396
2397 /* Determine actual return type for function. */
2398
2399 gt = FFEGLOBAL_typeFUNC;
2400 bt = ffesymbol_basictype (fn);
2401 kt = ffesymbol_kindtype (fn);
2402 if (bt == FFEINFO_basictypeNONE)
2403 {
2404 ffeimplic_establish_symbol (fn);
2405 if (ffesymbol_funcresult (fn) != NULL)
2406 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
2407 bt = ffesymbol_basictype (fn);
2408 kt = ffesymbol_kindtype (fn);
2409 }
2410
2411 if (bt == FFEINFO_basictypeCHARACTER)
2412 charfunc = TRUE, cmplxfunc = FALSE;
2413 else if ((bt == FFEINFO_basictypeCOMPLEX)
2414 && ffesymbol_is_f2c (fn))
2415 charfunc = FALSE, cmplxfunc = TRUE;
2416 else
2417 charfunc = cmplxfunc = FALSE;
2418
2419 if (charfunc)
2420 type = ffecom_tree_fun_type_void;
2421 else if (ffesymbol_is_f2c (fn))
2422 type = ffecom_tree_fun_type[bt][kt];
2423 else
2424 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
2425
2426 if ((type == NULL_TREE)
2427 || (TREE_TYPE (type) == NULL_TREE))
2428 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
2429
2430 multi = (ffecom_master_bt_ == FFEINFO_basictypeNONE);
2431 break;
2432
2433 case FFEINFO_kindSUBROUTINE:
2434 gt = FFEGLOBAL_typeSUBR;
2435 bt = FFEINFO_basictypeNONE;
2436 kt = FFEINFO_kindtypeNONE;
2437 if (ffecom_is_altreturning_)
2438 { /* Am _I_ altreturning? */
2439 for (item = ffesymbol_dummyargs (fn);
2440 item != NULL;
2441 item = ffebld_trail (item))
2442 {
2443 if (ffebld_op (ffebld_head (item)) == FFEBLD_opSTAR)
2444 {
2445 altreturning = TRUE;
2446 break;
2447 }
2448 }
2449 if (altreturning)
2450 type = ffecom_tree_subr_type;
2451 else
2452 type = ffecom_tree_fun_type_void;
2453 }
2454 else
2455 type = ffecom_tree_fun_type_void;
2456 charfunc = FALSE;
2457 cmplxfunc = FALSE;
2458 multi = FALSE;
2459 break;
2460
2461 default:
2462 assert ("say what??" == NULL);
2463 /* Fall through. */
2464 case FFEINFO_kindANY:
2465 gt = FFEGLOBAL_typeANY;
2466 bt = FFEINFO_basictypeNONE;
2467 kt = FFEINFO_kindtypeNONE;
2468 type = error_mark_node;
2469 charfunc = FALSE;
2470 cmplxfunc = FALSE;
2471 multi = FALSE;
2472 break;
2473 }
2474
2475 /* build_decl uses the current lineno and input_filename to set the decl
2476 source info. So, I've putzed with ffestd and ffeste code to update that
2477 source info to point to the appropriate statement just before calling
2478 ffecom_do_entrypoint (which calls this fn). */
2479
2480 start_function (ffecom_get_external_identifier_ (fn),
2481 type,
2482 0, /* nested/inline */
2483 1); /* TREE_PUBLIC */
2484
2485 if (((g = ffesymbol_global (fn)) != NULL)
2486 && ((ffeglobal_type (g) == gt)
2487 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
2488 {
2489 ffeglobal_set_hook (g, current_function_decl);
2490 }
2491
2492 /* Reset args in master arg list so they get retransitioned. */
2493
2494 for (item = ffecom_master_arglist_;
2495 item != NULL;
2496 item = ffebld_trail (item))
2497 {
2498 ffebld arg;
2499 ffesymbol s;
2500
2501 arg = ffebld_head (item);
2502 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2503 continue; /* Alternate return or some such thing. */
2504 s = ffebld_symter (arg);
2505 ffesymbol_hook (s).decl_tree = NULL_TREE;
2506 ffesymbol_hook (s).length_tree = NULL_TREE;
2507 }
2508
2509 /* Build dummy arg list for this entry point. */
2510
2511 yes = suspend_momentary ();
2512
2513 if (charfunc || cmplxfunc)
2514 { /* Prepend arg for where result goes. */
2515 tree type;
2516 tree length;
2517
2518 if (charfunc)
2519 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
2520 else
2521 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
2522
2523 result = ffecom_get_invented_identifier ("__g77_%s",
2524 "result", 0);
2525
2526 /* Make length arg _and_ enhance type info for CHAR arg itself. */
2527
2528 if (charfunc)
2529 length = ffecom_char_enhance_arg_ (&type, fn);
2530 else
2531 length = NULL_TREE; /* Not ref'd if !charfunc. */
2532
2533 type = build_pointer_type (type);
2534 result = build_decl (PARM_DECL, result, type);
2535
2536 push_parm_decl (result);
2537 ffecom_func_result_ = result;
2538
2539 if (charfunc)
2540 {
2541 push_parm_decl (length);
2542 ffecom_func_length_ = length;
2543 }
2544 }
2545 else
2546 result = DECL_RESULT (current_function_decl);
2547
2548 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (fn), FALSE);
2549
2550 resume_momentary (yes);
2551
2552 store_parm_decls (0);
2553
2554 ffecom_start_compstmt_ ();
2555
2556 /* Make local var to hold return type for multi-type master fn. */
2557
2558 if (multi)
2559 {
2560 yes = suspend_momentary ();
2561
2562 multi_retval = ffecom_get_invented_identifier ("__g77_%s",
2563 "multi_retval", 0);
2564 multi_retval = build_decl (VAR_DECL, multi_retval,
2565 ffecom_multi_type_node_);
2566 multi_retval = start_decl (multi_retval, FALSE);
2567 finish_decl (multi_retval, NULL_TREE, FALSE);
2568
2569 resume_momentary (yes);
2570 }
2571 else
2572 multi_retval = NULL_TREE; /* Not actually ref'd if !multi. */
2573
2574 /* Here we emit the actual code for the entry point. */
2575
2576 {
2577 ffebld list;
2578 ffebld arg;
2579 ffesymbol s;
2580 tree arglist = NULL_TREE;
2581 tree *plist = &arglist;
2582 tree prepend;
2583 tree call;
2584 tree actarg;
2585 tree master_fn;
2586
2587 /* Prepare actual arg list based on master arg list. */
2588
2589 for (list = ffecom_master_arglist_;
2590 list != NULL;
2591 list = ffebld_trail (list))
2592 {
2593 arg = ffebld_head (list);
2594 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2595 continue;
2596 s = ffebld_symter (arg);
2597 if (ffesymbol_hook (s).decl_tree == NULL_TREE)
2598 actarg = null_pointer_node; /* We don't have this arg. */
2599 else
2600 actarg = ffesymbol_hook (s).decl_tree;
2601 *plist = build_tree_list (NULL_TREE, actarg);
2602 plist = &TREE_CHAIN (*plist);
2603 }
2604
2605 /* This code appends the length arguments for character
2606 variables/arrays. */
2607
2608 for (list = ffecom_master_arglist_;
2609 list != NULL;
2610 list = ffebld_trail (list))
2611 {
2612 arg = ffebld_head (list);
2613 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2614 continue;
2615 s = ffebld_symter (arg);
2616 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
2617 continue; /* Only looking for CHARACTER arguments. */
2618 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
2619 continue; /* Only looking for variables and arrays. */
2620 if (ffesymbol_hook (s).length_tree == NULL_TREE)
2621 actarg = ffecom_f2c_ftnlen_zero_node; /* We don't have this arg. */
2622 else
2623 actarg = ffesymbol_hook (s).length_tree;
2624 *plist = build_tree_list (NULL_TREE, actarg);
2625 plist = &TREE_CHAIN (*plist);
2626 }
2627
2628 /* Prepend character-value return info to actual arg list. */
2629
2630 if (charfunc)
2631 {
2632 prepend = build_tree_list (NULL_TREE, ffecom_func_result_);
2633 TREE_CHAIN (prepend)
2634 = build_tree_list (NULL_TREE, ffecom_func_length_);
2635 TREE_CHAIN (TREE_CHAIN (prepend)) = arglist;
2636 arglist = prepend;
2637 }
2638
2639 /* Prepend multi-type return value to actual arg list. */
2640
2641 if (multi)
2642 {
2643 prepend
2644 = build_tree_list (NULL_TREE,
2645 ffecom_1 (ADDR_EXPR,
2646 build_pointer_type (TREE_TYPE (multi_retval)),
2647 multi_retval));
2648 TREE_CHAIN (prepend) = arglist;
2649 arglist = prepend;
2650 }
2651
2652 /* Prepend my entry-point number to the actual arg list. */
2653
2654 prepend = build_tree_list (NULL_TREE, build_int_2 (entrynum, 0));
2655 TREE_CHAIN (prepend) = arglist;
2656 arglist = prepend;
2657
2658 /* Build the call to the master function. */
2659
2660 master_fn = ffecom_1_fn (ffecom_previous_function_decl_);
2661 call = ffecom_3s (CALL_EXPR,
2662 TREE_TYPE (TREE_TYPE (TREE_TYPE (master_fn))),
2663 master_fn, arglist, NULL_TREE);
2664
2665 /* Decide whether the master function is a function or subroutine, and
2666 handle the return value for my entry point. */
2667
2668 if (charfunc || ((ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
2669 && !altreturning))
2670 {
2671 expand_expr_stmt (call);
2672 expand_null_return ();
2673 }
2674 else if (multi && cmplxfunc)
2675 {
2676 expand_expr_stmt (call);
2677 result
2678 = ffecom_1 (INDIRECT_REF,
2679 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
2680 result);
2681 result = ffecom_modify (NULL_TREE, result,
2682 ffecom_2 (COMPONENT_REF, TREE_TYPE (result),
2683 multi_retval,
2684 ffecom_multi_fields_[bt][kt]));
2685 expand_expr_stmt (result);
2686 expand_null_return ();
2687 }
2688 else if (multi)
2689 {
2690 expand_expr_stmt (call);
2691 result
2692 = ffecom_modify (NULL_TREE, result,
2693 convert (TREE_TYPE (result),
2694 ffecom_2 (COMPONENT_REF,
2695 ffecom_tree_type[bt][kt],
2696 multi_retval,
2697 ffecom_multi_fields_[bt][kt])));
2698 expand_return (result);
2699 }
2700 else if (cmplxfunc)
2701 {
2702 result
2703 = ffecom_1 (INDIRECT_REF,
2704 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
2705 result);
2706 result = ffecom_modify (NULL_TREE, result, call);
2707 expand_expr_stmt (result);
2708 expand_null_return ();
2709 }
2710 else
2711 {
2712 result = ffecom_modify (NULL_TREE,
2713 result,
2714 convert (TREE_TYPE (result),
2715 call));
2716 expand_return (result);
2717 }
2718
2719 clear_momentary ();
2720 }
2721
2722 ffecom_end_compstmt_ ();
2723
2724 finish_function (0);
2725
44d2eabc
JL
2726 lineno = old_lineno;
2727 input_filename = old_input_filename;
2728
5ff904cd
JL
2729 ffecom_doing_entry_ = FALSE;
2730}
2731
2732#endif
2733/* Transform expr into gcc tree with possible destination
2734
2735 Recursive descent on expr while making corresponding tree nodes and
2736 attaching type info and such. If destination supplied and compatible
2737 with temporary that would be made in certain cases, temporary isn't
092a4ef8 2738 made, destination used instead, and dest_used flag set TRUE. */
5ff904cd
JL
2739
2740#if FFECOM_targetCURRENT == FFECOM_targetGCC
2741static tree
092a4ef8
RH
2742ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
2743 bool *dest_used, bool assignp, bool widenp)
5ff904cd
JL
2744{
2745 tree item;
2746 tree list;
2747 tree args;
2748 ffeinfoBasictype bt;
2749 ffeinfoKindtype kt;
2750 tree t;
5ff904cd 2751 tree dt; /* decl_tree for an ffesymbol. */
092a4ef8 2752 tree tree_type, tree_type_x;
af752698 2753 tree left, right;
5ff904cd
JL
2754 ffesymbol s;
2755 enum tree_code code;
2756
2757 assert (expr != NULL);
2758
2759 if (dest_used != NULL)
2760 *dest_used = FALSE;
2761
2762 bt = ffeinfo_basictype (ffebld_info (expr));
2763 kt = ffeinfo_kindtype (ffebld_info (expr));
af752698 2764 tree_type = ffecom_tree_type[bt][kt];
5ff904cd 2765
092a4ef8
RH
2766 /* Widen integral arithmetic as desired while preserving signedness. */
2767 tree_type_x = NULL_TREE;
2768 if (widenp && tree_type
2769 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
2770 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
2771 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
2772
5ff904cd
JL
2773 switch (ffebld_op (expr))
2774 {
2775 case FFEBLD_opACCTER:
5ff904cd
JL
2776 {
2777 ffebitCount i;
2778 ffebit bits = ffebld_accter_bits (expr);
2779 ffetargetOffset source_offset = 0;
a6fa6420 2780 ffetargetOffset dest_offset = ffebld_accter_pad (expr);
5ff904cd
JL
2781 tree purpose;
2782
a6fa6420
CB
2783 assert (dest_offset == 0
2784 || (bt == FFEINFO_basictypeCHARACTER
2785 && kt == FFEINFO_kindtypeCHARACTER1));
5ff904cd
JL
2786
2787 list = item = NULL;
2788 for (;;)
2789 {
2790 ffebldConstantUnion cu;
2791 ffebitCount length;
2792 bool value;
2793 ffebldConstantArray ca = ffebld_accter (expr);
2794
2795 ffebit_test (bits, source_offset, &value, &length);
2796 if (length == 0)
2797 break;
2798
2799 if (value)
2800 {
2801 for (i = 0; i < length; ++i)
2802 {
2803 cu = ffebld_constantarray_get (ca, bt, kt,
2804 source_offset + i);
2805
2806 t = ffecom_constantunion (&cu, bt, kt, tree_type);
2807
a6fa6420
CB
2808 if (i == 0
2809 && dest_offset != 0)
2810 purpose = build_int_2 (dest_offset, 0);
5ff904cd
JL
2811 else
2812 purpose = NULL_TREE;
2813
2814 if (list == NULL_TREE)
2815 list = item = build_tree_list (purpose, t);
2816 else
2817 {
2818 TREE_CHAIN (item) = build_tree_list (purpose, t);
2819 item = TREE_CHAIN (item);
2820 }
2821 }
2822 }
2823 source_offset += length;
a6fa6420 2824 dest_offset += length;
5ff904cd
JL
2825 }
2826 }
2827
a6fa6420
CB
2828 item = build_int_2 ((ffebld_accter_size (expr)
2829 + ffebld_accter_pad (expr)) - 1, 0);
5ff904cd
JL
2830 ffebit_kill (ffebld_accter_bits (expr));
2831 TREE_TYPE (item) = ffecom_integer_type_node;
2832 item
2833 = build_array_type
2834 (tree_type,
2835 build_range_type (ffecom_integer_type_node,
2836 ffecom_integer_zero_node,
2837 item));
2838 list = build (CONSTRUCTOR, item, NULL_TREE, list);
2839 TREE_CONSTANT (list) = 1;
2840 TREE_STATIC (list) = 1;
2841 return list;
2842
2843 case FFEBLD_opARRTER:
5ff904cd
JL
2844 {
2845 ffetargetOffset i;
2846
a6fa6420
CB
2847 list = NULL_TREE;
2848 if (ffebld_arrter_pad (expr) == 0)
2849 item = NULL_TREE;
2850 else
2851 {
2852 assert (bt == FFEINFO_basictypeCHARACTER
2853 && kt == FFEINFO_kindtypeCHARACTER1);
2854
2855 /* Becomes PURPOSE first time through loop. */
2856 item = build_int_2 (ffebld_arrter_pad (expr), 0);
2857 }
2858
5ff904cd
JL
2859 for (i = 0; i < ffebld_arrter_size (expr); ++i)
2860 {
2861 ffebldConstantUnion cu
2862 = ffebld_constantarray_get (ffebld_arrter (expr), bt, kt, i);
2863
2864 t = ffecom_constantunion (&cu, bt, kt, tree_type);
2865
2866 if (list == NULL_TREE)
a6fa6420
CB
2867 /* Assume item is PURPOSE first time through loop. */
2868 list = item = build_tree_list (item, t);
5ff904cd
JL
2869 else
2870 {
2871 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
2872 item = TREE_CHAIN (item);
2873 }
2874 }
2875 }
2876
a6fa6420
CB
2877 item = build_int_2 ((ffebld_arrter_size (expr)
2878 + ffebld_arrter_pad (expr)) - 1, 0);
5ff904cd
JL
2879 TREE_TYPE (item) = ffecom_integer_type_node;
2880 item
2881 = build_array_type
2882 (tree_type,
2883 build_range_type (ffecom_integer_type_node,
a6fa6420 2884 ffecom_integer_zero_node,
5ff904cd
JL
2885 item));
2886 list = build (CONSTRUCTOR, item, NULL_TREE, list);
2887 TREE_CONSTANT (list) = 1;
2888 TREE_STATIC (list) = 1;
2889 return list;
2890
2891 case FFEBLD_opCONTER:
c264f113 2892 assert (ffebld_conter_pad (expr) == 0);
5ff904cd
JL
2893 item
2894 = ffecom_constantunion (&ffebld_constant_union (ffebld_conter (expr)),
2895 bt, kt, tree_type);
2896 return item;
2897
2898 case FFEBLD_opSYMTER:
2899 if ((ffebld_symter_generic (expr) != FFEINTRIN_genNONE)
2900 || (ffebld_symter_specific (expr) != FFEINTRIN_specNONE))
2901 return ffecom_ptr_to_expr (expr); /* Same as %REF(intrinsic). */
2902 s = ffebld_symter (expr);
2903 t = ffesymbol_hook (s).decl_tree;
2904
2905 if (assignp)
2906 { /* ASSIGN'ed-label expr. */
2907 if (ffe_is_ugly_assign ())
2908 {
2909 /* User explicitly wants ASSIGN'ed variables to be at the same
2910 memory address as the variables when used in non-ASSIGN
2911 contexts. That can make old, arcane, non-standard code
2912 work, but don't try to do it when a pointer wouldn't fit
2913 in the normal variable (take other approach, and warn,
2914 instead). */
2915
2916 if (t == NULL_TREE)
2917 {
2918 s = ffecom_sym_transform_ (s);
2919 t = ffesymbol_hook (s).decl_tree;
2920 assert (t != NULL_TREE);
2921 }
2922
2923 if (t == error_mark_node)
2924 return t;
2925
2926 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (t)))
2927 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
2928 {
2929 if (ffesymbol_hook (s).addr)
2930 t = ffecom_1 (INDIRECT_REF,
2931 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
2932 return t;
2933 }
2934
2935 if (ffesymbol_hook (s).assign_tree == NULL_TREE)
2936 {
2937 ffebad_start_msg ("ASSIGN'ed label cannot fit into `%A' at %0 -- using wider sibling",
2938 FFEBAD_severityWARNING);
2939 ffebad_string (ffesymbol_text (s));
2940 ffebad_here (0, ffesymbol_where_line (s),
2941 ffesymbol_where_column (s));
2942 ffebad_finish ();
2943 }
2944 }
2945
2946 /* Don't use the normal variable's tree for ASSIGN, though mark
2947 it as in the system header (housekeeping). Use an explicit,
2948 specially created sibling that is known to be wide enough
2949 to hold pointers to labels. */
2950
2951 if (t != NULL_TREE
2952 && TREE_CODE (t) == VAR_DECL)
2953 DECL_IN_SYSTEM_HEADER (t) = 1; /* Don't let -Wunused complain. */
2954
2955 t = ffesymbol_hook (s).assign_tree;
2956 if (t == NULL_TREE)
2957 {
2958 s = ffecom_sym_transform_assign_ (s);
2959 t = ffesymbol_hook (s).assign_tree;
2960 assert (t != NULL_TREE);
2961 }
2962 }
2963 else
2964 {
2965 if (t == NULL_TREE)
2966 {
2967 s = ffecom_sym_transform_ (s);
2968 t = ffesymbol_hook (s).decl_tree;
2969 assert (t != NULL_TREE);
2970 }
2971 if (ffesymbol_hook (s).addr)
2972 t = ffecom_1 (INDIRECT_REF,
2973 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
2974 }
2975 return t;
2976
2977 case FFEBLD_opARRAYREF:
2978 {
2979 ffebld dims[FFECOM_dimensionsMAX];
2980#if FFECOM_FASTER_ARRAY_REFS
2981 tree array;
2982#endif
2983 int i;
2984
2985#if FFECOM_FASTER_ARRAY_REFS
2986 t = ffecom_ptr_to_expr (ffebld_left (expr));
2987#else
2988 t = ffecom_expr (ffebld_left (expr));
2989#endif
2990 if (t == error_mark_node)
2991 return t;
2992
2993 if ((ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereFLEETING)
2994 && !mark_addressable (t))
2995 return error_mark_node; /* Make sure non-const ref is to
2996 non-reg. */
2997
2998 /* Build up ARRAY_REFs in reverse order (since we're column major
2999 here in Fortran land). */
3000
3001 for (i = 0, expr = ffebld_right (expr);
3002 expr != NULL;
3003 expr = ffebld_trail (expr))
3004 dims[i++] = ffebld_head (expr);
3005
3006#if FFECOM_FASTER_ARRAY_REFS
3007 for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t)));
3008 i >= 0;
3009 --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
3010 t = ffecom_2 (PLUS_EXPR,
3011 build_pointer_type (TREE_TYPE (array)),
3012 t,
3013 size_binop (MULT_EXPR,
3014 size_in_bytes (TREE_TYPE (array)),
3015 size_binop (MINUS_EXPR,
3016 ffecom_expr (dims[i]),
3017 TYPE_MIN_VALUE (TYPE_DOMAIN (array)))));
3018 t = ffecom_1 (INDIRECT_REF,
3019 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))),
3020 t);
3021#else
3022 while (i > 0)
3023 t = ffecom_2 (ARRAY_REF,
3024 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))),
3025 t,
092a4ef8 3026 ffecom_expr_ (dims[--i], NULL, NULL, NULL, FALSE, TRUE));
5ff904cd
JL
3027#endif
3028
3029 return t;
3030 }
3031
3032 case FFEBLD_opUPLUS:
092a4ef8 3033 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
af752698 3034 return ffecom_1 (NOP_EXPR, tree_type, left);
5ff904cd
JL
3035
3036 case FFEBLD_opPAREN: /* ~~~Make sure Fortran rules respected here */
092a4ef8 3037 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
af752698 3038 return ffecom_1 (NOP_EXPR, tree_type, left);
5ff904cd
JL
3039
3040 case FFEBLD_opUMINUS:
092a4ef8 3041 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3042 if (tree_type_x)
3043 {
3044 tree_type = tree_type_x;
3045 left = convert (tree_type, left);
3046 }
3047 return ffecom_1 (NEGATE_EXPR, tree_type, left);
5ff904cd
JL
3048
3049 case FFEBLD_opADD:
092a4ef8
RH
3050 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3051 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3052 if (tree_type_x)
3053 {
3054 tree_type = tree_type_x;
3055 left = convert (tree_type, left);
3056 right = convert (tree_type, right);
3057 }
3058 return ffecom_2 (PLUS_EXPR, tree_type, left, right);
5ff904cd
JL
3059
3060 case FFEBLD_opSUBTRACT:
092a4ef8
RH
3061 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3062 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3063 if (tree_type_x)
3064 {
3065 tree_type = tree_type_x;
3066 left = convert (tree_type, left);
3067 right = convert (tree_type, right);
3068 }
3069 return ffecom_2 (MINUS_EXPR, tree_type, left, right);
5ff904cd
JL
3070
3071 case FFEBLD_opMULTIPLY:
092a4ef8
RH
3072 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3073 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3074 if (tree_type_x)
3075 {
3076 tree_type = tree_type_x;
3077 left = convert (tree_type, left);
3078 right = convert (tree_type, right);
3079 }
3080 return ffecom_2 (MULT_EXPR, tree_type, left, right);
5ff904cd
JL
3081
3082 case FFEBLD_opDIVIDE:
092a4ef8
RH
3083 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3084 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3085 if (tree_type_x)
3086 {
3087 tree_type = tree_type_x;
3088 left = convert (tree_type, left);
3089 right = convert (tree_type, right);
3090 }
3091 return ffecom_tree_divide_ (tree_type, left, right,
83ffecd2 3092 dest_tree, dest, dest_used);
5ff904cd
JL
3093
3094 case FFEBLD_opPOWER:
5ff904cd
JL
3095 {
3096 ffebld left = ffebld_left (expr);
3097 ffebld right = ffebld_right (expr);
3098 ffecomGfrt code;
3099 ffeinfoKindtype rtkt;
270fc4e8 3100 ffeinfoKindtype ltkt;
5ff904cd
JL
3101
3102 switch (ffeinfo_basictype (ffebld_info (right)))
3103 {
3104 case FFEINFO_basictypeINTEGER:
3105 if (1 || optimize)
3106 {
3107 item = ffecom_expr_power_integer_ (left, right);
3108 if (item != NULL_TREE)
3109 return item;
3110 }
3111
3112 rtkt = FFEINFO_kindtypeINTEGER1;
3113 switch (ffeinfo_basictype (ffebld_info (left)))
3114 {
3115 case FFEINFO_basictypeINTEGER:
3116 if ((ffeinfo_kindtype (ffebld_info (left))
3117 == FFEINFO_kindtypeINTEGER4)
3118 || (ffeinfo_kindtype (ffebld_info (right))
3119 == FFEINFO_kindtypeINTEGER4))
3120 {
3121 code = FFECOM_gfrtPOW_QQ;
270fc4e8 3122 ltkt = FFEINFO_kindtypeINTEGER4;
5ff904cd
JL
3123 rtkt = FFEINFO_kindtypeINTEGER4;
3124 }
3125 else
6a047254
CB
3126 {
3127 code = FFECOM_gfrtPOW_II;
3128 ltkt = FFEINFO_kindtypeINTEGER1;
3129 }
5ff904cd
JL
3130 break;
3131
3132 case FFEINFO_basictypeREAL:
3133 if (ffeinfo_kindtype (ffebld_info (left))
3134 == FFEINFO_kindtypeREAL1)
6a047254
CB
3135 {
3136 code = FFECOM_gfrtPOW_RI;
3137 ltkt = FFEINFO_kindtypeREAL1;
3138 }
5ff904cd 3139 else
6a047254
CB
3140 {
3141 code = FFECOM_gfrtPOW_DI;
3142 ltkt = FFEINFO_kindtypeREAL2;
3143 }
5ff904cd
JL
3144 break;
3145
3146 case FFEINFO_basictypeCOMPLEX:
3147 if (ffeinfo_kindtype (ffebld_info (left))
3148 == FFEINFO_kindtypeREAL1)
6a047254
CB
3149 {
3150 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
3151 ltkt = FFEINFO_kindtypeREAL1;
3152 }
5ff904cd 3153 else
6a047254
CB
3154 {
3155 code = FFECOM_gfrtPOW_ZI; /* Overlapping result okay. */
3156 ltkt = FFEINFO_kindtypeREAL2;
3157 }
5ff904cd
JL
3158 break;
3159
3160 default:
3161 assert ("bad pow_*i" == NULL);
3162 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
6a047254 3163 ltkt = FFEINFO_kindtypeREAL1;
5ff904cd
JL
3164 break;
3165 }
270fc4e8 3166 if (ffeinfo_kindtype (ffebld_info (left)) != ltkt)
5ff904cd 3167 left = ffeexpr_convert (left, NULL, NULL,
6a047254 3168 ffeinfo_basictype (ffebld_info (left)),
270fc4e8 3169 ltkt, 0,
5ff904cd
JL
3170 FFETARGET_charactersizeNONE,
3171 FFEEXPR_contextLET);
3172 if (ffeinfo_kindtype (ffebld_info (right)) != rtkt)
3173 right = ffeexpr_convert (right, NULL, NULL,
3174 FFEINFO_basictypeINTEGER,
3175 rtkt, 0,
3176 FFETARGET_charactersizeNONE,
3177 FFEEXPR_contextLET);
3178 break;
3179
3180 case FFEINFO_basictypeREAL:
3181 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3182 left = ffeexpr_convert (left, NULL, NULL, FFEINFO_basictypeREAL,
3183 FFEINFO_kindtypeREALDOUBLE, 0,
3184 FFETARGET_charactersizeNONE,
3185 FFEEXPR_contextLET);
3186 if (ffeinfo_kindtype (ffebld_info (right))
3187 == FFEINFO_kindtypeREAL1)
3188 right = ffeexpr_convert (right, NULL, NULL,
3189 FFEINFO_basictypeREAL,
3190 FFEINFO_kindtypeREALDOUBLE, 0,
3191 FFETARGET_charactersizeNONE,
3192 FFEEXPR_contextLET);
3193 code = FFECOM_gfrtPOW_DD;
3194 break;
3195
3196 case FFEINFO_basictypeCOMPLEX:
3197 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3198 left = ffeexpr_convert (left, NULL, NULL,
3199 FFEINFO_basictypeCOMPLEX,
3200 FFEINFO_kindtypeREALDOUBLE, 0,
3201 FFETARGET_charactersizeNONE,
3202 FFEEXPR_contextLET);
3203 if (ffeinfo_kindtype (ffebld_info (right))
3204 == FFEINFO_kindtypeREAL1)
3205 right = ffeexpr_convert (right, NULL, NULL,
3206 FFEINFO_basictypeCOMPLEX,
3207 FFEINFO_kindtypeREALDOUBLE, 0,
3208 FFETARGET_charactersizeNONE,
3209 FFEEXPR_contextLET);
3210 code = FFECOM_gfrtPOW_ZZ; /* Overlapping result okay. */
3211 break;
3212
3213 default:
3214 assert ("bad pow_x*" == NULL);
3215 code = FFECOM_gfrtPOW_II;
3216 break;
3217 }
3218 return ffecom_call_binop_ (ffecom_gfrt_tree_ (code),
3219 ffecom_gfrt_kindtype (code),
3220 (ffe_is_f2c_library ()
3221 && ffecom_gfrt_complex_[code]),
3222 tree_type, left, right,
3223 dest_tree, dest, dest_used,
3224 NULL_TREE, FALSE);
3225 }
3226
3227 case FFEBLD_opNOT:
5ff904cd
JL
3228 switch (bt)
3229 {
3230 case FFEINFO_basictypeLOGICAL:
83ffecd2 3231 item = ffecom_truth_value_invert (ffecom_expr (ffebld_left (expr)));
5ff904cd
JL
3232 return convert (tree_type, item);
3233
3234 case FFEINFO_basictypeINTEGER:
3235 return ffecom_1 (BIT_NOT_EXPR, tree_type,
3236 ffecom_expr (ffebld_left (expr)));
3237
3238 default:
3239 assert ("NOT bad basictype" == NULL);
3240 /* Fall through. */
3241 case FFEINFO_basictypeANY:
3242 return error_mark_node;
3243 }
3244 break;
3245
3246 case FFEBLD_opFUNCREF:
3247 assert (ffeinfo_basictype (ffebld_info (expr))
3248 != FFEINFO_basictypeCHARACTER);
3249 /* Fall through. */
3250 case FFEBLD_opSUBRREF:
5ff904cd
JL
3251 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
3252 == FFEINFO_whereINTRINSIC)
3253 { /* Invocation of an intrinsic. */
3254 item = ffecom_expr_intrinsic_ (expr, dest_tree, dest,
3255 dest_used);
3256 return item;
3257 }
3258 s = ffebld_symter (ffebld_left (expr));
3259 dt = ffesymbol_hook (s).decl_tree;
3260 if (dt == NULL_TREE)
3261 {
3262 s = ffecom_sym_transform_ (s);
3263 dt = ffesymbol_hook (s).decl_tree;
3264 }
3265 if (dt == error_mark_node)
3266 return dt;
3267
3268 if (ffesymbol_hook (s).addr)
3269 item = dt;
3270 else
3271 item = ffecom_1_fn (dt);
3272
3273 ffecom_push_calltemps ();
3274 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
3275 args = ffecom_list_expr (ffebld_right (expr));
3276 else
3277 args = ffecom_list_ptr_to_expr (ffebld_right (expr));
3278 ffecom_pop_calltemps ();
3279
3280 item = ffecom_call_ (item, kt,
3281 ffesymbol_is_f2c (s)
3282 && (bt == FFEINFO_basictypeCOMPLEX)
3283 && (ffesymbol_where (s)
3284 != FFEINFO_whereCONSTANT),
3285 tree_type,
3286 args,
3287 dest_tree, dest, dest_used,
3288 error_mark_node, FALSE);
3289 TREE_SIDE_EFFECTS (item) = 1;
3290 return item;
3291
3292 case FFEBLD_opAND:
5ff904cd
JL
3293 switch (bt)
3294 {
3295 case FFEINFO_basictypeLOGICAL:
3296 item
3297 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3298 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3299 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3300 return convert (tree_type, item);
3301
3302 case FFEINFO_basictypeINTEGER:
3303 return ffecom_2 (BIT_AND_EXPR, tree_type,
3304 ffecom_expr (ffebld_left (expr)),
3305 ffecom_expr (ffebld_right (expr)));
3306
3307 default:
3308 assert ("AND bad basictype" == NULL);
3309 /* Fall through. */
3310 case FFEINFO_basictypeANY:
3311 return error_mark_node;
3312 }
3313 break;
3314
3315 case FFEBLD_opOR:
5ff904cd
JL
3316 switch (bt)
3317 {
3318 case FFEINFO_basictypeLOGICAL:
3319 item
3320 = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
3321 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3322 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3323 return convert (tree_type, item);
3324
3325 case FFEINFO_basictypeINTEGER:
3326 return ffecom_2 (BIT_IOR_EXPR, tree_type,
3327 ffecom_expr (ffebld_left (expr)),
3328 ffecom_expr (ffebld_right (expr)));
3329
3330 default:
3331 assert ("OR bad basictype" == NULL);
3332 /* Fall through. */
3333 case FFEINFO_basictypeANY:
3334 return error_mark_node;
3335 }
3336 break;
3337
3338 case FFEBLD_opXOR:
3339 case FFEBLD_opNEQV:
5ff904cd
JL
3340 switch (bt)
3341 {
3342 case FFEINFO_basictypeLOGICAL:
3343 item
3344 = ffecom_2 (NE_EXPR, integer_type_node,
3345 ffecom_expr (ffebld_left (expr)),
3346 ffecom_expr (ffebld_right (expr)));
3347 return convert (tree_type, ffecom_truth_value (item));
3348
3349 case FFEINFO_basictypeINTEGER:
3350 return ffecom_2 (BIT_XOR_EXPR, tree_type,
3351 ffecom_expr (ffebld_left (expr)),
3352 ffecom_expr (ffebld_right (expr)));
3353
3354 default:
3355 assert ("XOR/NEQV bad basictype" == NULL);
3356 /* Fall through. */
3357 case FFEINFO_basictypeANY:
3358 return error_mark_node;
3359 }
3360 break;
3361
3362 case FFEBLD_opEQV:
5ff904cd
JL
3363 switch (bt)
3364 {
3365 case FFEINFO_basictypeLOGICAL:
3366 item
3367 = ffecom_2 (EQ_EXPR, integer_type_node,
3368 ffecom_expr (ffebld_left (expr)),
3369 ffecom_expr (ffebld_right (expr)));
3370 return convert (tree_type, ffecom_truth_value (item));
3371
3372 case FFEINFO_basictypeINTEGER:
3373 return
3374 ffecom_1 (BIT_NOT_EXPR, tree_type,
3375 ffecom_2 (BIT_XOR_EXPR, tree_type,
3376 ffecom_expr (ffebld_left (expr)),
3377 ffecom_expr (ffebld_right (expr))));
3378
3379 default:
3380 assert ("EQV bad basictype" == NULL);
3381 /* Fall through. */
3382 case FFEINFO_basictypeANY:
3383 return error_mark_node;
3384 }
3385 break;
3386
3387 case FFEBLD_opCONVERT:
3388 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opANY)
3389 return error_mark_node;
3390
5ff904cd
JL
3391 switch (bt)
3392 {
3393 case FFEINFO_basictypeLOGICAL:
3394 case FFEINFO_basictypeINTEGER:
3395 case FFEINFO_basictypeREAL:
3396 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3397
3398 case FFEINFO_basictypeCOMPLEX:
3399 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3400 {
3401 case FFEINFO_basictypeINTEGER:
3402 case FFEINFO_basictypeLOGICAL:
3403 case FFEINFO_basictypeREAL:
3404 item = ffecom_expr (ffebld_left (expr));
3405 if (item == error_mark_node)
3406 return error_mark_node;
3407 /* convert() takes care of converting to the subtype first,
3408 at least in gcc-2.7.2. */
3409 item = convert (tree_type, item);
3410 return item;
3411
3412 case FFEINFO_basictypeCOMPLEX:
3413 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3414
3415 default:
3416 assert ("CONVERT COMPLEX bad basictype" == NULL);
3417 /* Fall through. */
3418 case FFEINFO_basictypeANY:
3419 return error_mark_node;
3420 }
3421 break;
3422
3423 default:
3424 assert ("CONVERT bad basictype" == NULL);
3425 /* Fall through. */
3426 case FFEINFO_basictypeANY:
3427 return error_mark_node;
3428 }
3429 break;
3430
3431 case FFEBLD_opLT:
3432 code = LT_EXPR;
3433 goto relational; /* :::::::::::::::::::: */
3434
3435 case FFEBLD_opLE:
3436 code = LE_EXPR;
3437 goto relational; /* :::::::::::::::::::: */
3438
3439 case FFEBLD_opEQ:
3440 code = EQ_EXPR;
3441 goto relational; /* :::::::::::::::::::: */
3442
3443 case FFEBLD_opNE:
3444 code = NE_EXPR;
3445 goto relational; /* :::::::::::::::::::: */
3446
3447 case FFEBLD_opGT:
3448 code = GT_EXPR;
3449 goto relational; /* :::::::::::::::::::: */
3450
3451 case FFEBLD_opGE:
3452 code = GE_EXPR;
3453
3454 relational: /* :::::::::::::::::::: */
5ff904cd
JL
3455 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3456 {
3457 case FFEINFO_basictypeLOGICAL:
3458 case FFEINFO_basictypeINTEGER:
3459 case FFEINFO_basictypeREAL:
3460 item = ffecom_2 (code, integer_type_node,
3461 ffecom_expr (ffebld_left (expr)),
3462 ffecom_expr (ffebld_right (expr)));
3463 return convert (tree_type, item);
3464
3465 case FFEINFO_basictypeCOMPLEX:
3466 assert (code == EQ_EXPR || code == NE_EXPR);
3467 {
3468 tree real_type;
3469 tree arg1 = ffecom_expr (ffebld_left (expr));
3470 tree arg2 = ffecom_expr (ffebld_right (expr));
3471
3472 if (arg1 == error_mark_node || arg2 == error_mark_node)
3473 return error_mark_node;
3474
3475 arg1 = ffecom_save_tree (arg1);
3476 arg2 = ffecom_save_tree (arg2);
3477
3478 if (TREE_CODE (TREE_TYPE (arg1)) == COMPLEX_TYPE)
3479 {
3480 real_type = TREE_TYPE (TREE_TYPE (arg1));
3481 assert (real_type == TREE_TYPE (TREE_TYPE (arg2)));
3482 }
3483 else
3484 {
3485 real_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg1)));
3486 assert (real_type == TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg2))));
3487 }
3488
3489 item
3490 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3491 ffecom_2 (EQ_EXPR, integer_type_node,
3492 ffecom_1 (REALPART_EXPR, real_type, arg1),
3493 ffecom_1 (REALPART_EXPR, real_type, arg2)),
3494 ffecom_2 (EQ_EXPR, integer_type_node,
3495 ffecom_1 (IMAGPART_EXPR, real_type, arg1),
3496 ffecom_1 (IMAGPART_EXPR, real_type,
3497 arg2)));
3498 if (code == EQ_EXPR)
3499 item = ffecom_truth_value (item);
3500 else
3501 item = ffecom_truth_value_invert (item);
3502 return convert (tree_type, item);
3503 }
3504
3505 case FFEINFO_basictypeCHARACTER:
3506 ffecom_push_calltemps (); /* Even though we might not call. */
3507
3508 {
3509 ffebld left = ffebld_left (expr);
3510 ffebld right = ffebld_right (expr);
3511 tree left_tree;
3512 tree right_tree;
3513 tree left_length;
3514 tree right_length;
3515
3516 /* f2c run-time functions do the implicit blank-padding for us,
3517 so we don't usually have to implement blank-padding ourselves.
3518 (The exception is when we pass an argument to a separately
3519 compiled statement function -- if we know the arg is not the
3520 same length as the dummy, we must truncate or extend it. If
3521 we "inline" statement functions, that necessity goes away as
3522 well.)
3523
3524 Strip off the CONVERT operators that blank-pad. (Truncation by
3525 CONVERT shouldn't happen here, but it can happen in
3526 assignments.) */
3527
3528 while (ffebld_op (left) == FFEBLD_opCONVERT)
3529 left = ffebld_left (left);
3530 while (ffebld_op (right) == FFEBLD_opCONVERT)
3531 right = ffebld_left (right);
3532
3533 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
3534 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
3535
3536 if (left_tree == error_mark_node || left_length == error_mark_node
3537 || right_tree == error_mark_node
3538 || right_length == error_mark_node)
3539 {
3540 ffecom_pop_calltemps ();
3541 return error_mark_node;
3542 }
3543
3544 if ((ffebld_size_known (left) == 1)
3545 && (ffebld_size_known (right) == 1))
3546 {
3547 left_tree
3548 = ffecom_1 (INDIRECT_REF,
3549 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3550 left_tree);
3551 right_tree
3552 = ffecom_1 (INDIRECT_REF,
3553 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3554 right_tree);
3555
3556 item
3557 = ffecom_2 (code, integer_type_node,
3558 ffecom_2 (ARRAY_REF,
3559 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3560 left_tree,
3561 integer_one_node),
3562 ffecom_2 (ARRAY_REF,
3563 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3564 right_tree,
3565 integer_one_node));
3566 }
3567 else
3568 {
3569 item = build_tree_list (NULL_TREE, left_tree);
3570 TREE_CHAIN (item) = build_tree_list (NULL_TREE, right_tree);
3571 TREE_CHAIN (TREE_CHAIN (item)) = build_tree_list (NULL_TREE,
3572 left_length);
3573 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
3574 = build_tree_list (NULL_TREE, right_length);
3575 item = ffecom_call_gfrt (FFECOM_gfrtCMP, item);
3576 item = ffecom_2 (code, integer_type_node,
3577 item,
3578 convert (TREE_TYPE (item),
3579 integer_zero_node));
3580 }
3581 item = convert (tree_type, item);
3582 }
3583
3584 ffecom_pop_calltemps ();
3585 return item;
3586
3587 default:
3588 assert ("relational bad basictype" == NULL);
3589 /* Fall through. */
3590 case FFEINFO_basictypeANY:
3591 return error_mark_node;
3592 }
3593 break;
3594
3595 case FFEBLD_opPERCENT_LOC:
5ff904cd
JL
3596 item = ffecom_arg_ptr_to_expr (ffebld_left (expr), &list);
3597 return convert (tree_type, item);
3598
3599 case FFEBLD_opITEM:
3600 case FFEBLD_opSTAR:
3601 case FFEBLD_opBOUNDS:
3602 case FFEBLD_opREPEAT:
3603 case FFEBLD_opLABTER:
3604 case FFEBLD_opLABTOK:
3605 case FFEBLD_opIMPDO:
3606 case FFEBLD_opCONCATENATE:
3607 case FFEBLD_opSUBSTR:
3608 default:
3609 assert ("bad op" == NULL);
3610 /* Fall through. */
3611 case FFEBLD_opANY:
3612 return error_mark_node;
3613 }
3614
3615#if 1
3616 assert ("didn't think anything got here anymore!!" == NULL);
3617#else
3618 switch (ffebld_arity (expr))
3619 {
3620 case 2:
3621 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3622 TREE_OPERAND (item, 1) = ffecom_expr (ffebld_right (expr));
3623 if (TREE_OPERAND (item, 0) == error_mark_node
3624 || TREE_OPERAND (item, 1) == error_mark_node)
3625 return error_mark_node;
3626 break;
3627
3628 case 1:
3629 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3630 if (TREE_OPERAND (item, 0) == error_mark_node)
3631 return error_mark_node;
3632 break;
3633
3634 default:
3635 break;
3636 }
3637
3638 return fold (item);
3639#endif
3640}
3641
3642#endif
3643/* Returns the tree that does the intrinsic invocation.
3644
3645 Note: this function applies only to intrinsics returning
3646 CHARACTER*1 or non-CHARACTER results, and to intrinsic
3647 subroutines. */
3648
3649#if FFECOM_targetCURRENT == FFECOM_targetGCC
3650static tree
3651ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
3652 ffebld dest, bool *dest_used)
3653{
3654 tree expr_tree;
3655 tree saved_expr1; /* For those who need it. */
3656 tree saved_expr2; /* For those who need it. */
3657 ffeinfoBasictype bt;
3658 ffeinfoKindtype kt;
3659 tree tree_type;
3660 tree arg1_type;
3661 tree real_type; /* REAL type corresponding to COMPLEX. */
3662 tree tempvar;
3663 ffebld list = ffebld_right (expr); /* List of (some) args. */
3664 ffebld arg1; /* For handy reference. */
3665 ffebld arg2;
3666 ffebld arg3;
3667 ffeintrinImp codegen_imp;
3668 ffecomGfrt gfrt;
3669
3670 assert (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER);
3671
3672 if (dest_used != NULL)
3673 *dest_used = FALSE;
3674
3675 bt = ffeinfo_basictype (ffebld_info (expr));
3676 kt = ffeinfo_kindtype (ffebld_info (expr));
3677 tree_type = ffecom_tree_type[bt][kt];
3678
3679 if (list != NULL)
3680 {
3681 arg1 = ffebld_head (list);
3682 if (arg1 != NULL && ffebld_op (arg1) == FFEBLD_opANY)
3683 return error_mark_node;
3684 if ((list = ffebld_trail (list)) != NULL)
3685 {
3686 arg2 = ffebld_head (list);
3687 if (arg2 != NULL && ffebld_op (arg2) == FFEBLD_opANY)
3688 return error_mark_node;
3689 if ((list = ffebld_trail (list)) != NULL)
3690 {
3691 arg3 = ffebld_head (list);
3692 if (arg3 != NULL && ffebld_op (arg3) == FFEBLD_opANY)
3693 return error_mark_node;
3694 }
3695 else
3696 arg3 = NULL;
3697 }
3698 else
3699 arg2 = arg3 = NULL;
3700 }
3701 else
3702 arg1 = arg2 = arg3 = NULL;
3703
3704 /* <list> ends up at the opITEM of the 3rd arg, or NULL if there are < 3
3705 args. This is used by the MAX/MIN expansions. */
3706
3707 if (arg1 != NULL)
3708 arg1_type = ffecom_tree_type
3709 [ffeinfo_basictype (ffebld_info (arg1))]
3710 [ffeinfo_kindtype (ffebld_info (arg1))];
3711 else
3712 arg1_type = NULL_TREE; /* Really not needed, but might catch bugs
3713 here. */
3714
3715 /* There are several ways for each of the cases in the following switch
3716 statements to exit (from simplest to use to most complicated):
3717
3718 break; (when expr_tree == NULL)
3719
3720 A standard call is made to the specific intrinsic just as if it had been
3721 passed in as a dummy procedure and called as any old procedure. This
3722 method can produce slower code but in some cases it's the easiest way for
3723 now. However, if a (presumably faster) direct call is available,
3724 that is used, so this is the easiest way in many more cases now.
3725
3726 gfrt = FFECOM_gfrtWHATEVER;
3727 break;
3728
3729 gfrt contains the gfrt index of a library function to call, passing the
3730 argument(s) by value rather than by reference. Used when a more
3731 careful choice of library function is needed than that provided
3732 by the vanilla `break;'.
3733
3734 return expr_tree;
3735
3736 The expr_tree has been completely set up and is ready to be returned
3737 as is. No further actions are taken. Use this when the tree is not
3738 in the simple form for one of the arity_n labels. */
3739
3740 /* For info on how the switch statement cases were written, see the files
3741 enclosed in comments below the switch statement. */
3742
3743 codegen_imp = ffebld_symter_implementation (ffebld_left (expr));
3744 gfrt = ffeintrin_gfrt_direct (codegen_imp);
3745 if (gfrt == FFECOM_gfrt)
3746 gfrt = ffeintrin_gfrt_indirect (codegen_imp);
3747
3748 switch (codegen_imp)
3749 {
3750 case FFEINTRIN_impABS:
3751 case FFEINTRIN_impCABS:
3752 case FFEINTRIN_impCDABS:
3753 case FFEINTRIN_impDABS:
3754 case FFEINTRIN_impIABS:
3755 if (ffeinfo_basictype (ffebld_info (arg1))
3756 == FFEINFO_basictypeCOMPLEX)
3757 {
3758 if (kt == FFEINFO_kindtypeREAL1)
3759 gfrt = FFECOM_gfrtCABS;
3760 else if (kt == FFEINFO_kindtypeREAL2)
3761 gfrt = FFECOM_gfrtCDABS;
3762 break;
3763 }
3764 return ffecom_1 (ABS_EXPR, tree_type,
3765 convert (tree_type, ffecom_expr (arg1)));
3766
3767 case FFEINTRIN_impACOS:
3768 case FFEINTRIN_impDACOS:
3769 break;
3770
3771 case FFEINTRIN_impAIMAG:
3772 case FFEINTRIN_impDIMAG:
3773 case FFEINTRIN_impIMAGPART:
3774 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
3775 arg1_type = TREE_TYPE (arg1_type);
3776 else
3777 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
3778
3779 return
3780 convert (tree_type,
3781 ffecom_1 (IMAGPART_EXPR, arg1_type,
3782 ffecom_expr (arg1)));
3783
3784 case FFEINTRIN_impAINT:
3785 case FFEINTRIN_impDINT:
3786#if 0 /* ~~ someday implement FIX_TRUNC_EXPR
3787 yielding same type as arg */
3788 return ffecom_1 (FIX_TRUNC_EXPR, tree_type, ffecom_expr (arg1));
3789#else /* in the meantime, must use floor to avoid range problems with ints */
3790 /* r__1 = r1 >= 0 ? floor(r1) : -floor(-r1); */
3791 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
3792 return
3793 convert (tree_type,
3794 ffecom_3 (COND_EXPR, double_type_node,
3795 ffecom_truth_value
3796 (ffecom_2 (GE_EXPR, integer_type_node,
3797 saved_expr1,
3798 convert (arg1_type,
3799 ffecom_float_zero_))),
3800 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
3801 build_tree_list (NULL_TREE,
3802 convert (double_type_node,
3803 saved_expr1))),
3804 ffecom_1 (NEGATE_EXPR, double_type_node,
3805 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
3806 build_tree_list (NULL_TREE,
3807 convert (double_type_node,
3808 ffecom_1 (NEGATE_EXPR,
3809 arg1_type,
3810 saved_expr1))))
3811 ))
3812 );
3813#endif
3814
3815 case FFEINTRIN_impANINT:
3816 case FFEINTRIN_impDNINT:
3817#if 0 /* This way of doing it won't handle real
3818 numbers of large magnitudes. */
3819 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
3820 expr_tree = convert (tree_type,
3821 convert (integer_type_node,
3822 ffecom_3 (COND_EXPR, tree_type,
3823 ffecom_truth_value
3824 (ffecom_2 (GE_EXPR,
3825 integer_type_node,
3826 saved_expr1,
3827 ffecom_float_zero_)),
3828 ffecom_2 (PLUS_EXPR,
3829 tree_type,
3830 saved_expr1,
3831 ffecom_float_half_),
3832 ffecom_2 (MINUS_EXPR,
3833 tree_type,
3834 saved_expr1,
3835 ffecom_float_half_))));
3836 return expr_tree;
3837#else /* So we instead call floor. */
3838 /* r__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1) */
3839 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
3840 return
3841 convert (tree_type,
3842 ffecom_3 (COND_EXPR, double_type_node,
3843 ffecom_truth_value
3844 (ffecom_2 (GE_EXPR, integer_type_node,
3845 saved_expr1,
3846 convert (arg1_type,
3847 ffecom_float_zero_))),
3848 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
3849 build_tree_list (NULL_TREE,
3850 convert (double_type_node,
3851 ffecom_2 (PLUS_EXPR,
3852 arg1_type,
3853 saved_expr1,
3854 convert (arg1_type,
3855 ffecom_float_half_))))),
3856 ffecom_1 (NEGATE_EXPR, double_type_node,
3857 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
3858 build_tree_list (NULL_TREE,
3859 convert (double_type_node,
3860 ffecom_2 (MINUS_EXPR,
3861 arg1_type,
3862 convert (arg1_type,
3863 ffecom_float_half_),
3864 saved_expr1)))))
3865 )
3866 );
3867#endif
3868
3869 case FFEINTRIN_impASIN:
3870 case FFEINTRIN_impDASIN:
3871 case FFEINTRIN_impATAN:
3872 case FFEINTRIN_impDATAN:
3873 case FFEINTRIN_impATAN2:
3874 case FFEINTRIN_impDATAN2:
3875 break;
3876
3877 case FFEINTRIN_impCHAR:
3878 case FFEINTRIN_impACHAR:
3879 assert (ffecom_pending_calls_ != 0);
3880 tempvar = ffecom_push_tempvar (char_type_node,
3881 1, -1, TRUE);
3882 {
3883 tree tmv = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (tempvar)));
3884
3885 expr_tree = ffecom_modify (tmv,
3886 ffecom_2 (ARRAY_REF, tmv, tempvar,
3887 integer_one_node),
3888 convert (tmv, ffecom_expr (arg1)));
3889 }
3890 expr_tree = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar),
3891 expr_tree,
3892 tempvar);
3893 expr_tree = ffecom_1 (ADDR_EXPR,
3894 build_pointer_type (TREE_TYPE (expr_tree)),
3895 expr_tree);
3896 return expr_tree;
3897
3898 case FFEINTRIN_impCMPLX:
3899 case FFEINTRIN_impDCMPLX:
3900 if (arg2 == NULL)
3901 return
3902 convert (tree_type, ffecom_expr (arg1));
3903
3904 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
3905 return
3906 ffecom_2 (COMPLEX_EXPR, tree_type,
3907 convert (real_type, ffecom_expr (arg1)),
3908 convert (real_type,
3909 ffecom_expr (arg2)));
3910
3911 case FFEINTRIN_impCOMPLEX:
3912 return
3913 ffecom_2 (COMPLEX_EXPR, tree_type,
3914 ffecom_expr (arg1),
3915 ffecom_expr (arg2));
3916
3917 case FFEINTRIN_impCONJG:
3918 case FFEINTRIN_impDCONJG:
3919 {
3920 tree arg1_tree;
3921
3922 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
3923 arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
3924 return
3925 ffecom_2 (COMPLEX_EXPR, tree_type,
3926 ffecom_1 (REALPART_EXPR, real_type, arg1_tree),
3927 ffecom_1 (NEGATE_EXPR, real_type,
3928 ffecom_1 (IMAGPART_EXPR, real_type, arg1_tree)));
3929 }
3930
3931 case FFEINTRIN_impCOS:
3932 case FFEINTRIN_impCCOS:
3933 case FFEINTRIN_impCDCOS:
3934 case FFEINTRIN_impDCOS:
3935 if (bt == FFEINFO_basictypeCOMPLEX)
3936 {
3937 if (kt == FFEINFO_kindtypeREAL1)
3938 gfrt = FFECOM_gfrtCCOS; /* Overlapping result okay. */
3939 else if (kt == FFEINFO_kindtypeREAL2)
3940 gfrt = FFECOM_gfrtCDCOS; /* Overlapping result okay. */
3941 }
3942 break;
3943
3944 case FFEINTRIN_impCOSH:
3945 case FFEINTRIN_impDCOSH:
3946 break;
3947
3948 case FFEINTRIN_impDBLE:
3949 case FFEINTRIN_impDFLOAT:
3950 case FFEINTRIN_impDREAL:
3951 case FFEINTRIN_impFLOAT:
3952 case FFEINTRIN_impIDINT:
3953 case FFEINTRIN_impIFIX:
3954 case FFEINTRIN_impINT2:
3955 case FFEINTRIN_impINT8:
3956 case FFEINTRIN_impINT:
3957 case FFEINTRIN_impLONG:
3958 case FFEINTRIN_impREAL:
3959 case FFEINTRIN_impSHORT:
3960 case FFEINTRIN_impSNGL:
3961 return convert (tree_type, ffecom_expr (arg1));
3962
3963 case FFEINTRIN_impDIM:
3964 case FFEINTRIN_impDDIM:
3965 case FFEINTRIN_impIDIM:
3966 saved_expr1 = ffecom_save_tree (convert (tree_type,
3967 ffecom_expr (arg1)));
3968 saved_expr2 = ffecom_save_tree (convert (tree_type,
3969 ffecom_expr (arg2)));
3970 return
3971 ffecom_3 (COND_EXPR, tree_type,
3972 ffecom_truth_value
3973 (ffecom_2 (GT_EXPR, integer_type_node,
3974 saved_expr1,
3975 saved_expr2)),
3976 ffecom_2 (MINUS_EXPR, tree_type,
3977 saved_expr1,
3978 saved_expr2),
3979 convert (tree_type, ffecom_float_zero_));
3980
3981 case FFEINTRIN_impDPROD:
3982 return
3983 ffecom_2 (MULT_EXPR, tree_type,
3984 convert (tree_type, ffecom_expr (arg1)),
3985 convert (tree_type, ffecom_expr (arg2)));
3986
3987 case FFEINTRIN_impEXP:
3988 case FFEINTRIN_impCDEXP:
3989 case FFEINTRIN_impCEXP:
3990 case FFEINTRIN_impDEXP:
3991 if (bt == FFEINFO_basictypeCOMPLEX)
3992 {
3993 if (kt == FFEINFO_kindtypeREAL1)
3994 gfrt = FFECOM_gfrtCEXP; /* Overlapping result okay. */
3995 else if (kt == FFEINFO_kindtypeREAL2)
3996 gfrt = FFECOM_gfrtCDEXP; /* Overlapping result okay. */
3997 }
3998 break;
3999
4000 case FFEINTRIN_impICHAR:
4001 case FFEINTRIN_impIACHAR:
4002#if 0 /* The simple approach. */
4003 ffecom_char_args_ (&expr_tree, &saved_expr1 /* Ignored */ , arg1);
4004 expr_tree
4005 = ffecom_1 (INDIRECT_REF,
4006 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4007 expr_tree);
4008 expr_tree
4009 = ffecom_2 (ARRAY_REF,
4010 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4011 expr_tree,
4012 integer_one_node);
4013 return convert (tree_type, expr_tree);
4014#else /* The more interesting (and more optimal) approach. */
4015 expr_tree = ffecom_intrinsic_ichar_ (tree_type, arg1, &saved_expr1);
4016 expr_tree = ffecom_3 (COND_EXPR, tree_type,
4017 saved_expr1,
4018 expr_tree,
4019 convert (tree_type, integer_zero_node));
4020 return expr_tree;
4021#endif
4022
4023 case FFEINTRIN_impINDEX:
4024 break;
4025
4026 case FFEINTRIN_impLEN:
4027#if 0
4028 break; /* The simple approach. */
4029#else
4030 return ffecom_intrinsic_len_ (arg1); /* The more optimal approach. */
4031#endif
4032
4033 case FFEINTRIN_impLGE:
4034 case FFEINTRIN_impLGT:
4035 case FFEINTRIN_impLLE:
4036 case FFEINTRIN_impLLT:
4037 break;
4038
4039 case FFEINTRIN_impLOG:
4040 case FFEINTRIN_impALOG:
4041 case FFEINTRIN_impCDLOG:
4042 case FFEINTRIN_impCLOG:
4043 case FFEINTRIN_impDLOG:
4044 if (bt == FFEINFO_basictypeCOMPLEX)
4045 {
4046 if (kt == FFEINFO_kindtypeREAL1)
4047 gfrt = FFECOM_gfrtCLOG; /* Overlapping result okay. */
4048 else if (kt == FFEINFO_kindtypeREAL2)
4049 gfrt = FFECOM_gfrtCDLOG; /* Overlapping result okay. */
4050 }
4051 break;
4052
4053 case FFEINTRIN_impLOG10:
4054 case FFEINTRIN_impALOG10:
4055 case FFEINTRIN_impDLOG10:
4056 if (gfrt != FFECOM_gfrt)
4057 break; /* Already picked one, stick with it. */
4058
4059 if (kt == FFEINFO_kindtypeREAL1)
4060 gfrt = FFECOM_gfrtALOG10;
4061 else if (kt == FFEINFO_kindtypeREAL2)
4062 gfrt = FFECOM_gfrtDLOG10;
4063 break;
4064
4065 case FFEINTRIN_impMAX:
4066 case FFEINTRIN_impAMAX0:
4067 case FFEINTRIN_impAMAX1:
4068 case FFEINTRIN_impDMAX1:
4069 case FFEINTRIN_impMAX0:
4070 case FFEINTRIN_impMAX1:
4071 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4072 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4073 else
4074 arg1_type = tree_type;
4075 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4076 convert (arg1_type, ffecom_expr (arg1)),
4077 convert (arg1_type, ffecom_expr (arg2)));
4078 for (; list != NULL; list = ffebld_trail (list))
4079 {
4080 if ((ffebld_head (list) == NULL)
4081 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4082 continue;
4083 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4084 expr_tree,
4085 convert (arg1_type,
4086 ffecom_expr (ffebld_head (list))));
4087 }
4088 return convert (tree_type, expr_tree);
4089
4090 case FFEINTRIN_impMIN:
4091 case FFEINTRIN_impAMIN0:
4092 case FFEINTRIN_impAMIN1:
4093 case FFEINTRIN_impDMIN1:
4094 case FFEINTRIN_impMIN0:
4095 case FFEINTRIN_impMIN1:
4096 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4097 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4098 else
4099 arg1_type = tree_type;
4100 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4101 convert (arg1_type, ffecom_expr (arg1)),
4102 convert (arg1_type, ffecom_expr (arg2)));
4103 for (; list != NULL; list = ffebld_trail (list))
4104 {
4105 if ((ffebld_head (list) == NULL)
4106 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4107 continue;
4108 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4109 expr_tree,
4110 convert (arg1_type,
4111 ffecom_expr (ffebld_head (list))));
4112 }
4113 return convert (tree_type, expr_tree);
4114
4115 case FFEINTRIN_impMOD:
4116 case FFEINTRIN_impAMOD:
4117 case FFEINTRIN_impDMOD:
4118 if (bt != FFEINFO_basictypeREAL)
4119 return ffecom_2 (TRUNC_MOD_EXPR, tree_type,
4120 convert (tree_type, ffecom_expr (arg1)),
4121 convert (tree_type, ffecom_expr (arg2)));
4122
4123 if (kt == FFEINFO_kindtypeREAL1)
4124 gfrt = FFECOM_gfrtAMOD;
4125 else if (kt == FFEINFO_kindtypeREAL2)
4126 gfrt = FFECOM_gfrtDMOD;
4127 break;
4128
4129 case FFEINTRIN_impNINT:
4130 case FFEINTRIN_impIDNINT:
4131#if 0 /* ~~ ideally FIX_ROUND_EXPR would be
4132 implemented, but it ain't yet */
4133 return ffecom_1 (FIX_ROUND_EXPR, tree_type, ffecom_expr (arg1));
4134#else
4135 /* i__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1); */
4136 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4137 return
4138 convert (ffecom_integer_type_node,
4139 ffecom_3 (COND_EXPR, arg1_type,
4140 ffecom_truth_value
4141 (ffecom_2 (GE_EXPR, integer_type_node,
4142 saved_expr1,
4143 convert (arg1_type,
4144 ffecom_float_zero_))),
4145 ffecom_2 (PLUS_EXPR, arg1_type,
4146 saved_expr1,
4147 convert (arg1_type,
4148 ffecom_float_half_)),
4149 ffecom_2 (MINUS_EXPR, arg1_type,
4150 saved_expr1,
4151 convert (arg1_type,
4152 ffecom_float_half_))));
4153#endif
4154
4155 case FFEINTRIN_impSIGN:
4156 case FFEINTRIN_impDSIGN:
4157 case FFEINTRIN_impISIGN:
4158 {
4159 tree arg2_tree = ffecom_expr (arg2);
4160
4161 saved_expr1
4162 = ffecom_save_tree
4163 (ffecom_1 (ABS_EXPR, tree_type,
4164 convert (tree_type,
4165 ffecom_expr (arg1))));
4166 expr_tree
4167 = ffecom_3 (COND_EXPR, tree_type,
4168 ffecom_truth_value
4169 (ffecom_2 (GE_EXPR, integer_type_node,
4170 arg2_tree,
4171 convert (TREE_TYPE (arg2_tree),
4172 integer_zero_node))),
4173 saved_expr1,
4174 ffecom_1 (NEGATE_EXPR, tree_type, saved_expr1));
4175 /* Make sure SAVE_EXPRs get referenced early enough. */
4176 expr_tree
4177 = ffecom_2 (COMPOUND_EXPR, tree_type,
4178 convert (void_type_node, saved_expr1),
4179 expr_tree);
4180 }
4181 return expr_tree;
4182
4183 case FFEINTRIN_impSIN:
4184 case FFEINTRIN_impCDSIN:
4185 case FFEINTRIN_impCSIN:
4186 case FFEINTRIN_impDSIN:
4187 if (bt == FFEINFO_basictypeCOMPLEX)
4188 {
4189 if (kt == FFEINFO_kindtypeREAL1)
4190 gfrt = FFECOM_gfrtCSIN; /* Overlapping result okay. */
4191 else if (kt == FFEINFO_kindtypeREAL2)
4192 gfrt = FFECOM_gfrtCDSIN; /* Overlapping result okay. */
4193 }
4194 break;
4195
4196 case FFEINTRIN_impSINH:
4197 case FFEINTRIN_impDSINH:
4198 break;
4199
4200 case FFEINTRIN_impSQRT:
4201 case FFEINTRIN_impCDSQRT:
4202 case FFEINTRIN_impCSQRT:
4203 case FFEINTRIN_impDSQRT:
4204 if (bt == FFEINFO_basictypeCOMPLEX)
4205 {
4206 if (kt == FFEINFO_kindtypeREAL1)
4207 gfrt = FFECOM_gfrtCSQRT; /* Overlapping result okay. */
4208 else if (kt == FFEINFO_kindtypeREAL2)
4209 gfrt = FFECOM_gfrtCDSQRT; /* Overlapping result okay. */
4210 }
4211 break;
4212
4213 case FFEINTRIN_impTAN:
4214 case FFEINTRIN_impDTAN:
4215 case FFEINTRIN_impTANH:
4216 case FFEINTRIN_impDTANH:
4217 break;
4218
4219 case FFEINTRIN_impREALPART:
4220 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4221 arg1_type = TREE_TYPE (arg1_type);
4222 else
4223 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4224
4225 return
4226 convert (tree_type,
4227 ffecom_1 (REALPART_EXPR, arg1_type,
4228 ffecom_expr (arg1)));
4229
4230 case FFEINTRIN_impIAND:
4231 case FFEINTRIN_impAND:
4232 return ffecom_2 (BIT_AND_EXPR, tree_type,
4233 convert (tree_type,
4234 ffecom_expr (arg1)),
4235 convert (tree_type,
4236 ffecom_expr (arg2)));
4237
4238 case FFEINTRIN_impIOR:
4239 case FFEINTRIN_impOR:
4240 return ffecom_2 (BIT_IOR_EXPR, tree_type,
4241 convert (tree_type,
4242 ffecom_expr (arg1)),
4243 convert (tree_type,
4244 ffecom_expr (arg2)));
4245
4246 case FFEINTRIN_impIEOR:
4247 case FFEINTRIN_impXOR:
4248 return ffecom_2 (BIT_XOR_EXPR, tree_type,
4249 convert (tree_type,
4250 ffecom_expr (arg1)),
4251 convert (tree_type,
4252 ffecom_expr (arg2)));
4253
4254 case FFEINTRIN_impLSHIFT:
4255 return ffecom_2 (LSHIFT_EXPR, tree_type,
4256 ffecom_expr (arg1),
4257 convert (integer_type_node,
4258 ffecom_expr (arg2)));
4259
4260 case FFEINTRIN_impRSHIFT:
4261 return ffecom_2 (RSHIFT_EXPR, tree_type,
4262 ffecom_expr (arg1),
4263 convert (integer_type_node,
4264 ffecom_expr (arg2)));
4265
4266 case FFEINTRIN_impNOT:
4267 return ffecom_1 (BIT_NOT_EXPR, tree_type, ffecom_expr (arg1));
4268
4269 case FFEINTRIN_impBIT_SIZE:
4270 return convert (tree_type, TYPE_SIZE (arg1_type));
4271
4272 case FFEINTRIN_impBTEST:
4273 {
4274 ffetargetLogical1 true;
4275 ffetargetLogical1 false;
4276 tree true_tree;
4277 tree false_tree;
4278
4279 ffetarget_logical1 (&true, TRUE);
4280 ffetarget_logical1 (&false, FALSE);
4281 if (true == 1)
4282 true_tree = convert (tree_type, integer_one_node);
4283 else
4284 true_tree = convert (tree_type, build_int_2 (true, 0));
4285 if (false == 0)
4286 false_tree = convert (tree_type, integer_zero_node);
4287 else
4288 false_tree = convert (tree_type, build_int_2 (false, 0));
4289
4290 return
4291 ffecom_3 (COND_EXPR, tree_type,
4292 ffecom_truth_value
4293 (ffecom_2 (EQ_EXPR, integer_type_node,
4294 ffecom_2 (BIT_AND_EXPR, arg1_type,
4295 ffecom_expr (arg1),
4296 ffecom_2 (LSHIFT_EXPR, arg1_type,
4297 convert (arg1_type,
4298 integer_one_node),
4299 convert (integer_type_node,
4300 ffecom_expr (arg2)))),
4301 convert (arg1_type,
4302 integer_zero_node))),
4303 false_tree,
4304 true_tree);
4305 }
4306
4307 case FFEINTRIN_impIBCLR:
4308 return
4309 ffecom_2 (BIT_AND_EXPR, tree_type,
4310 ffecom_expr (arg1),
4311 ffecom_1 (BIT_NOT_EXPR, tree_type,
4312 ffecom_2 (LSHIFT_EXPR, tree_type,
4313 convert (tree_type,
4314 integer_one_node),
4315 convert (integer_type_node,
4316 ffecom_expr (arg2)))));
4317
4318 case FFEINTRIN_impIBITS:
4319 {
4320 tree arg3_tree = ffecom_save_tree (convert (integer_type_node,
4321 ffecom_expr (arg3)));
4322 tree uns_type
4323 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4324
4325 expr_tree
4326 = ffecom_2 (BIT_AND_EXPR, tree_type,
4327 ffecom_2 (RSHIFT_EXPR, tree_type,
4328 ffecom_expr (arg1),
4329 convert (integer_type_node,
4330 ffecom_expr (arg2))),
4331 convert (tree_type,
4332 ffecom_2 (RSHIFT_EXPR, uns_type,
4333 ffecom_1 (BIT_NOT_EXPR,
4334 uns_type,
4335 convert (uns_type,
4336 integer_zero_node)),
4337 ffecom_2 (MINUS_EXPR,
4338 integer_type_node,
4339 TYPE_SIZE (uns_type),
4340 arg3_tree))));
4341#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4342 expr_tree
4343 = ffecom_3 (COND_EXPR, tree_type,
4344 ffecom_truth_value
4345 (ffecom_2 (NE_EXPR, integer_type_node,
4346 arg3_tree,
4347 integer_zero_node)),
4348 expr_tree,
4349 convert (tree_type, integer_zero_node));
4350#endif
4351 }
4352 return expr_tree;
4353
4354 case FFEINTRIN_impIBSET:
4355 return
4356 ffecom_2 (BIT_IOR_EXPR, tree_type,
4357 ffecom_expr (arg1),
4358 ffecom_2 (LSHIFT_EXPR, tree_type,
4359 convert (tree_type, integer_one_node),
4360 convert (integer_type_node,
4361 ffecom_expr (arg2))));
4362
4363 case FFEINTRIN_impISHFT:
4364 {
4365 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4366 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4367 ffecom_expr (arg2)));
4368 tree uns_type
4369 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4370
4371 expr_tree
4372 = ffecom_3 (COND_EXPR, tree_type,
4373 ffecom_truth_value
4374 (ffecom_2 (GE_EXPR, integer_type_node,
4375 arg2_tree,
4376 integer_zero_node)),
4377 ffecom_2 (LSHIFT_EXPR, tree_type,
4378 arg1_tree,
4379 arg2_tree),
4380 convert (tree_type,
4381 ffecom_2 (RSHIFT_EXPR, uns_type,
4382 convert (uns_type, arg1_tree),
4383 ffecom_1 (NEGATE_EXPR,
4384 integer_type_node,
4385 arg2_tree))));
4386#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4387 expr_tree
4388 = ffecom_3 (COND_EXPR, tree_type,
4389 ffecom_truth_value
4390 (ffecom_2 (NE_EXPR, integer_type_node,
4391 arg2_tree,
4392 TYPE_SIZE (uns_type))),
4393 expr_tree,
4394 convert (tree_type, integer_zero_node));
4395#endif
4396 /* Make sure SAVE_EXPRs get referenced early enough. */
4397 expr_tree
4398 = ffecom_2 (COMPOUND_EXPR, tree_type,
4399 convert (void_type_node, arg1_tree),
4400 ffecom_2 (COMPOUND_EXPR, tree_type,
4401 convert (void_type_node, arg2_tree),
4402 expr_tree));
4403 }
4404 return expr_tree;
4405
4406 case FFEINTRIN_impISHFTC:
4407 {
4408 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4409 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4410 ffecom_expr (arg2)));
4411 tree arg3_tree = (arg3 == NULL) ? TYPE_SIZE (tree_type)
4412 : ffecom_save_tree (convert (integer_type_node, ffecom_expr (arg3)));
4413 tree shift_neg;
4414 tree shift_pos;
4415 tree mask_arg1;
4416 tree masked_arg1;
4417 tree uns_type
4418 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4419
4420 mask_arg1
4421 = ffecom_2 (LSHIFT_EXPR, tree_type,
4422 ffecom_1 (BIT_NOT_EXPR, tree_type,
4423 convert (tree_type, integer_zero_node)),
4424 arg3_tree);
4425#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4426 mask_arg1
4427 = ffecom_3 (COND_EXPR, tree_type,
4428 ffecom_truth_value
4429 (ffecom_2 (NE_EXPR, integer_type_node,
4430 arg3_tree,
4431 TYPE_SIZE (uns_type))),
4432 mask_arg1,
4433 convert (tree_type, integer_zero_node));
4434#endif
4435 mask_arg1 = ffecom_save_tree (mask_arg1);
4436 masked_arg1
4437 = ffecom_2 (BIT_AND_EXPR, tree_type,
4438 arg1_tree,
4439 ffecom_1 (BIT_NOT_EXPR, tree_type,
4440 mask_arg1));
4441 masked_arg1 = ffecom_save_tree (masked_arg1);
4442 shift_neg
4443 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4444 convert (tree_type,
4445 ffecom_2 (RSHIFT_EXPR, uns_type,
4446 convert (uns_type, masked_arg1),
4447 ffecom_1 (NEGATE_EXPR,
4448 integer_type_node,
4449 arg2_tree))),
4450 ffecom_2 (LSHIFT_EXPR, tree_type,
4451 arg1_tree,
4452 ffecom_2 (PLUS_EXPR, integer_type_node,
4453 arg2_tree,
4454 arg3_tree)));
4455 shift_pos
4456 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4457 ffecom_2 (LSHIFT_EXPR, tree_type,
4458 arg1_tree,
4459 arg2_tree),
4460 convert (tree_type,
4461 ffecom_2 (RSHIFT_EXPR, uns_type,
4462 convert (uns_type, masked_arg1),
4463 ffecom_2 (MINUS_EXPR,
4464 integer_type_node,
4465 arg3_tree,
4466 arg2_tree))));
4467 expr_tree
4468 = ffecom_3 (COND_EXPR, tree_type,
4469 ffecom_truth_value
4470 (ffecom_2 (LT_EXPR, integer_type_node,
4471 arg2_tree,
4472 integer_zero_node)),
4473 shift_neg,
4474 shift_pos);
4475 expr_tree
4476 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4477 ffecom_2 (BIT_AND_EXPR, tree_type,
4478 mask_arg1,
4479 arg1_tree),
4480 ffecom_2 (BIT_AND_EXPR, tree_type,
4481 ffecom_1 (BIT_NOT_EXPR, tree_type,
4482 mask_arg1),
4483 expr_tree));
4484 expr_tree
4485 = ffecom_3 (COND_EXPR, tree_type,
4486 ffecom_truth_value
4487 (ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
4488 ffecom_2 (EQ_EXPR, integer_type_node,
4489 ffecom_1 (ABS_EXPR,
4490 integer_type_node,
4491 arg2_tree),
4492 arg3_tree),
4493 ffecom_2 (EQ_EXPR, integer_type_node,
4494 arg2_tree,
4495 integer_zero_node))),
4496 arg1_tree,
4497 expr_tree);
4498 /* Make sure SAVE_EXPRs get referenced early enough. */
4499 expr_tree
4500 = ffecom_2 (COMPOUND_EXPR, tree_type,
4501 convert (void_type_node, arg1_tree),
4502 ffecom_2 (COMPOUND_EXPR, tree_type,
4503 convert (void_type_node, arg2_tree),
4504 ffecom_2 (COMPOUND_EXPR, tree_type,
4505 convert (void_type_node,
4506 mask_arg1),
4507 ffecom_2 (COMPOUND_EXPR, tree_type,
4508 convert (void_type_node,
4509 masked_arg1),
4510 expr_tree))));
4511 expr_tree
4512 = ffecom_2 (COMPOUND_EXPR, tree_type,
4513 convert (void_type_node,
4514 arg3_tree),
4515 expr_tree);
4516 }
4517 return expr_tree;
4518
4519 case FFEINTRIN_impLOC:
4520 {
4521 tree arg1_tree = ffecom_expr (arg1);
4522
4523 expr_tree
4524 = convert (tree_type,
4525 ffecom_1 (ADDR_EXPR,
4526 build_pointer_type (TREE_TYPE (arg1_tree)),
4527 arg1_tree));
4528 }
4529 return expr_tree;
4530
4531 case FFEINTRIN_impMVBITS:
4532 {
4533 tree arg1_tree;
4534 tree arg2_tree;
4535 tree arg3_tree;
4536 ffebld arg4 = ffebld_head (ffebld_trail (list));
4537 tree arg4_tree;
4538 tree arg4_type;
4539 ffebld arg5 = ffebld_head (ffebld_trail (ffebld_trail (list)));
4540 tree arg5_tree;
4541 tree prep_arg1;
4542 tree prep_arg4;
4543 tree arg5_plus_arg3;
4544
4545 ffecom_push_calltemps ();
4546
4547 arg2_tree = convert (integer_type_node,
4548 ffecom_expr (arg2));
4549 arg3_tree = ffecom_save_tree (convert (integer_type_node,
4550 ffecom_expr (arg3)));
4551 arg4_tree = ffecom_expr_rw (arg4);
4552 arg4_type = TREE_TYPE (arg4_tree);
4553
4554 arg1_tree = ffecom_save_tree (convert (arg4_type,
4555 ffecom_expr (arg1)));
4556
4557 arg5_tree = ffecom_save_tree (convert (integer_type_node,
4558 ffecom_expr (arg5)));
4559
4560 ffecom_pop_calltemps ();
4561
4562 prep_arg1
4563 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4564 ffecom_2 (BIT_AND_EXPR, arg4_type,
4565 ffecom_2 (RSHIFT_EXPR, arg4_type,
4566 arg1_tree,
4567 arg2_tree),
4568 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4569 ffecom_2 (LSHIFT_EXPR, arg4_type,
4570 ffecom_1 (BIT_NOT_EXPR,
4571 arg4_type,
4572 convert
4573 (arg4_type,
4574 integer_zero_node)),
4575 arg3_tree))),
4576 arg5_tree);
4577 arg5_plus_arg3
4578 = ffecom_save_tree (ffecom_2 (PLUS_EXPR, arg4_type,
4579 arg5_tree,
4580 arg3_tree));
4581 prep_arg4
4582 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4583 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4584 convert (arg4_type,
4585 integer_zero_node)),
4586 arg5_plus_arg3);
4587#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4588 prep_arg4
4589 = ffecom_3 (COND_EXPR, arg4_type,
4590 ffecom_truth_value
4591 (ffecom_2 (NE_EXPR, integer_type_node,
4592 arg5_plus_arg3,
4593 convert (TREE_TYPE (arg5_plus_arg3),
4594 TYPE_SIZE (arg4_type)))),
4595 prep_arg4,
4596 convert (arg4_type, integer_zero_node));
4597#endif
4598 prep_arg4
4599 = ffecom_2 (BIT_AND_EXPR, arg4_type,
4600 arg4_tree,
4601 ffecom_2 (BIT_IOR_EXPR, arg4_type,
4602 prep_arg4,
4603 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4604 ffecom_2 (LSHIFT_EXPR, arg4_type,
4605 ffecom_1 (BIT_NOT_EXPR,
4606 arg4_type,
4607 convert
4608 (arg4_type,
4609 integer_zero_node)),
4610 arg5_tree))));
4611 prep_arg1
4612 = ffecom_2 (BIT_IOR_EXPR, arg4_type,
4613 prep_arg1,
4614 prep_arg4);
4615#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4616 prep_arg1
4617 = ffecom_3 (COND_EXPR, arg4_type,
4618 ffecom_truth_value
4619 (ffecom_2 (NE_EXPR, integer_type_node,
4620 arg3_tree,
4621 convert (TREE_TYPE (arg3_tree),
4622 integer_zero_node))),
4623 prep_arg1,
4624 arg4_tree);
4625 prep_arg1
4626 = ffecom_3 (COND_EXPR, arg4_type,
4627 ffecom_truth_value
4628 (ffecom_2 (NE_EXPR, integer_type_node,
4629 arg3_tree,
4630 convert (TREE_TYPE (arg3_tree),
4631 TYPE_SIZE (arg4_type)))),
4632 prep_arg1,
4633 arg1_tree);
4634#endif
4635 expr_tree
4636 = ffecom_2s (MODIFY_EXPR, void_type_node,
4637 arg4_tree,
4638 prep_arg1);
4639 /* Make sure SAVE_EXPRs get referenced early enough. */
4640 expr_tree
4641 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4642 arg1_tree,
4643 ffecom_2 (COMPOUND_EXPR, void_type_node,
4644 arg3_tree,
4645 ffecom_2 (COMPOUND_EXPR, void_type_node,
4646 arg5_tree,
4647 ffecom_2 (COMPOUND_EXPR, void_type_node,
4648 arg5_plus_arg3,
4649 expr_tree))));
4650 expr_tree
4651 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4652 arg4_tree,
4653 expr_tree);
4654
4655 }
4656 return expr_tree;
4657
4658 case FFEINTRIN_impDERF:
4659 case FFEINTRIN_impERF:
4660 case FFEINTRIN_impDERFC:
4661 case FFEINTRIN_impERFC:
4662 break;
4663
4664 case FFEINTRIN_impIARGC:
4665 /* extern int xargc; i__1 = xargc - 1; */
4666 expr_tree = ffecom_2 (MINUS_EXPR, TREE_TYPE (ffecom_tree_xargc_),
4667 ffecom_tree_xargc_,
4668 convert (TREE_TYPE (ffecom_tree_xargc_),
4669 integer_one_node));
4670 return expr_tree;
4671
4672 case FFEINTRIN_impSIGNAL_func:
4673 case FFEINTRIN_impSIGNAL_subr:
4674 {
4675 tree arg1_tree;
4676 tree arg2_tree;
4677 tree arg3_tree;
4678
4679 ffecom_push_calltemps ();
4680
4681 arg1_tree = convert (ffecom_f2c_integer_type_node,
4682 ffecom_expr (arg1));
4683 arg1_tree = ffecom_1 (ADDR_EXPR,
4684 build_pointer_type (TREE_TYPE (arg1_tree)),
4685 arg1_tree);
4686
4687 /* Pass procedure as a pointer to it, anything else by value. */
4688 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4689 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4690 else
4691 arg2_tree = ffecom_ptr_to_expr (arg2);
4692 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4693 arg2_tree);
4694
4695 if (arg3 != NULL)
4696 arg3_tree = ffecom_expr_rw (arg3);
4697 else
4698 arg3_tree = NULL_TREE;
4699
4700 ffecom_pop_calltemps ();
4701
4702 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4703 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4704 TREE_CHAIN (arg1_tree) = arg2_tree;
4705
4706 expr_tree
4707 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4708 ffecom_gfrt_kindtype (gfrt),
4709 FALSE,
4710 ((codegen_imp == FFEINTRIN_impSIGNAL_subr) ?
4711 NULL_TREE :
4712 tree_type),
4713 arg1_tree,
4714 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
4715
4716 if (arg3_tree != NULL_TREE)
4717 expr_tree
4718 = ffecom_modify (NULL_TREE, arg3_tree,
4719 convert (TREE_TYPE (arg3_tree),
4720 expr_tree));
4721 }
4722 return expr_tree;
4723
4724 case FFEINTRIN_impALARM:
4725 {
4726 tree arg1_tree;
4727 tree arg2_tree;
4728 tree arg3_tree;
4729
4730 ffecom_push_calltemps ();
4731
4732 arg1_tree = convert (ffecom_f2c_integer_type_node,
4733 ffecom_expr (arg1));
4734 arg1_tree = ffecom_1 (ADDR_EXPR,
4735 build_pointer_type (TREE_TYPE (arg1_tree)),
4736 arg1_tree);
4737
4738 /* Pass procedure as a pointer to it, anything else by value. */
4739 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4740 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4741 else
4742 arg2_tree = ffecom_ptr_to_expr (arg2);
4743 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4744 arg2_tree);
4745
4746 if (arg3 != NULL)
4747 arg3_tree = ffecom_expr_rw (arg3);
4748 else
4749 arg3_tree = NULL_TREE;
4750
4751 ffecom_pop_calltemps ();
4752
4753 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4754 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4755 TREE_CHAIN (arg1_tree) = arg2_tree;
4756
4757 expr_tree
4758 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4759 ffecom_gfrt_kindtype (gfrt),
4760 FALSE,
4761 NULL_TREE,
4762 arg1_tree,
4763 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
4764
4765 if (arg3_tree != NULL_TREE)
4766 expr_tree
4767 = ffecom_modify (NULL_TREE, arg3_tree,
4768 convert (TREE_TYPE (arg3_tree),
4769 expr_tree));
4770 }
4771 return expr_tree;
4772
4773 case FFEINTRIN_impCHDIR_subr:
4774 case FFEINTRIN_impFDATE_subr:
4775 case FFEINTRIN_impFGET_subr:
4776 case FFEINTRIN_impFPUT_subr:
4777 case FFEINTRIN_impGETCWD_subr:
4778 case FFEINTRIN_impHOSTNM_subr:
4779 case FFEINTRIN_impSYSTEM_subr:
4780 case FFEINTRIN_impUNLINK_subr:
4781 {
4782 tree arg1_len = integer_zero_node;
4783 tree arg1_tree;
4784 tree arg2_tree;
4785
4786 ffecom_push_calltemps ();
4787
4788 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
4789
4790 if (arg2 != NULL)
4791 arg2_tree = ffecom_expr_rw (arg2);
4792 else
4793 arg2_tree = NULL_TREE;
4794
4795 ffecom_pop_calltemps ();
4796
4797 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4798 arg1_len = build_tree_list (NULL_TREE, arg1_len);
4799 TREE_CHAIN (arg1_tree) = arg1_len;
4800
4801 expr_tree
4802 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4803 ffecom_gfrt_kindtype (gfrt),
4804 FALSE,
4805 NULL_TREE,
4806 arg1_tree,
4807 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
4808
4809 if (arg2_tree != NULL_TREE)
4810 expr_tree
4811 = ffecom_modify (NULL_TREE, arg2_tree,
4812 convert (TREE_TYPE (arg2_tree),
4813 expr_tree));
4814 }
4815 return expr_tree;
4816
4817 case FFEINTRIN_impEXIT:
4818 if (arg1 != NULL)
4819 break;
4820
4821 expr_tree = build_tree_list (NULL_TREE,
4822 ffecom_1 (ADDR_EXPR,
4823 build_pointer_type
4824 (ffecom_integer_type_node),
4825 integer_zero_node));
4826
4827 return
4828 ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4829 ffecom_gfrt_kindtype (gfrt),
4830 FALSE,
4831 void_type_node,
4832 expr_tree,
4833 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
4834
4835 case FFEINTRIN_impFLUSH:
4836 if (arg1 == NULL)
4837 gfrt = FFECOM_gfrtFLUSH;
4838 else
4839 gfrt = FFECOM_gfrtFLUSH1;
4840 break;
4841
4842 case FFEINTRIN_impCHMOD_subr:
4843 case FFEINTRIN_impLINK_subr:
4844 case FFEINTRIN_impRENAME_subr:
4845 case FFEINTRIN_impSYMLNK_subr:
4846 {
4847 tree arg1_len = integer_zero_node;
4848 tree arg1_tree;
4849 tree arg2_len = integer_zero_node;
4850 tree arg2_tree;
4851 tree arg3_tree;
4852
4853 ffecom_push_calltemps ();
4854
4855 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
4856 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
4857 if (arg3 != NULL)
4858 arg3_tree = ffecom_expr_rw (arg3);
4859 else
4860 arg3_tree = NULL_TREE;
4861
4862 ffecom_pop_calltemps ();
4863
4864 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4865 arg1_len = build_tree_list (NULL_TREE, arg1_len);
4866 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4867 arg2_len = build_tree_list (NULL_TREE, arg2_len);
4868 TREE_CHAIN (arg1_tree) = arg2_tree;
4869 TREE_CHAIN (arg2_tree) = arg1_len;
4870 TREE_CHAIN (arg1_len) = arg2_len;
4871 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4872 ffecom_gfrt_kindtype (gfrt),
4873 FALSE,
4874 NULL_TREE,
4875 arg1_tree,
4876 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
4877 if (arg3_tree != NULL_TREE)
4878 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
4879 convert (TREE_TYPE (arg3_tree),
4880 expr_tree));
4881 }
4882 return expr_tree;
4883
4884 case FFEINTRIN_impLSTAT_subr:
4885 case FFEINTRIN_impSTAT_subr:
4886 {
4887 tree arg1_len = integer_zero_node;
4888 tree arg1_tree;
4889 tree arg2_tree;
4890 tree arg3_tree;
4891
4892 ffecom_push_calltemps ();
4893
4894 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
4895
4896 arg2_tree = ffecom_ptr_to_expr (arg2);
4897
4898 if (arg3 != NULL)
4899 arg3_tree = ffecom_expr_rw (arg3);
4900 else
4901 arg3_tree = NULL_TREE;
4902
4903 ffecom_pop_calltemps ();
4904
4905 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4906 arg1_len = build_tree_list (NULL_TREE, arg1_len);
4907 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4908 TREE_CHAIN (arg1_tree) = arg2_tree;
4909 TREE_CHAIN (arg2_tree) = arg1_len;
4910 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4911 ffecom_gfrt_kindtype (gfrt),
4912 FALSE,
4913 NULL_TREE,
4914 arg1_tree,
4915 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
4916 if (arg3_tree != NULL_TREE)
4917 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
4918 convert (TREE_TYPE (arg3_tree),
4919 expr_tree));
4920 }
4921 return expr_tree;
4922
4923 case FFEINTRIN_impFGETC_subr:
4924 case FFEINTRIN_impFPUTC_subr:
4925 {
4926 tree arg1_tree;
4927 tree arg2_tree;
4928 tree arg2_len = integer_zero_node;
4929 tree arg3_tree;
4930
4931 ffecom_push_calltemps ();
4932
4933 arg1_tree = convert (ffecom_f2c_integer_type_node,
4934 ffecom_expr (arg1));
4935 arg1_tree = ffecom_1 (ADDR_EXPR,
4936 build_pointer_type (TREE_TYPE (arg1_tree)),
4937 arg1_tree);
4938
4939 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
4940 arg3_tree = ffecom_expr_rw (arg3);
4941
4942 ffecom_pop_calltemps ();
4943
4944 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4945 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4946 arg2_len = build_tree_list (NULL_TREE, arg2_len);
4947 TREE_CHAIN (arg1_tree) = arg2_tree;
4948 TREE_CHAIN (arg2_tree) = arg2_len;
4949
4950 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4951 ffecom_gfrt_kindtype (gfrt),
4952 FALSE,
4953 NULL_TREE,
4954 arg1_tree,
4955 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
4956 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
4957 convert (TREE_TYPE (arg3_tree),
4958 expr_tree));
4959 }
4960 return expr_tree;
4961
4962 case FFEINTRIN_impFSTAT_subr:
4963 {
4964 tree arg1_tree;
4965 tree arg2_tree;
4966 tree arg3_tree;
4967
4968 ffecom_push_calltemps ();
4969
4970 arg1_tree = convert (ffecom_f2c_integer_type_node,
4971 ffecom_expr (arg1));
4972 arg1_tree = ffecom_1 (ADDR_EXPR,
4973 build_pointer_type (TREE_TYPE (arg1_tree)),
4974 arg1_tree);
4975
4976 arg2_tree = convert (ffecom_f2c_ptr_to_integer_type_node,
4977 ffecom_ptr_to_expr (arg2));
4978
4979 if (arg3 == NULL)
4980 arg3_tree = NULL_TREE;
4981 else
4982 arg3_tree = ffecom_expr_rw (arg3);
4983
4984 ffecom_pop_calltemps ();
4985
4986 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4987 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4988 TREE_CHAIN (arg1_tree) = arg2_tree;
4989 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4990 ffecom_gfrt_kindtype (gfrt),
4991 FALSE,
4992 NULL_TREE,
4993 arg1_tree,
4994 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
4995 if (arg3_tree != NULL_TREE) {
4996 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
4997 convert (TREE_TYPE (arg3_tree),
4998 expr_tree));
4999 }
5000 }
5001 return expr_tree;
5002
5003 case FFEINTRIN_impKILL_subr:
5004 {
5005 tree arg1_tree;
5006 tree arg2_tree;
5007 tree arg3_tree;
5008
5009 ffecom_push_calltemps ();
5010
5011 arg1_tree = convert (ffecom_f2c_integer_type_node,
5012 ffecom_expr (arg1));
5013 arg1_tree = ffecom_1 (ADDR_EXPR,
5014 build_pointer_type (TREE_TYPE (arg1_tree)),
5015 arg1_tree);
5016
5017 arg2_tree = convert (ffecom_f2c_integer_type_node,
5018 ffecom_expr (arg2));
5019 arg2_tree = ffecom_1 (ADDR_EXPR,
5020 build_pointer_type (TREE_TYPE (arg2_tree)),
5021 arg2_tree);
5022
5023 if (arg3 == NULL)
5024 arg3_tree = NULL_TREE;
5025 else
5026 arg3_tree = ffecom_expr_rw (arg3);
5027
5028 ffecom_pop_calltemps ();
5029
5030 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5031 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5032 TREE_CHAIN (arg1_tree) = arg2_tree;
5033 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5034 ffecom_gfrt_kindtype (gfrt),
5035 FALSE,
5036 NULL_TREE,
5037 arg1_tree,
5038 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
5039 if (arg3_tree != NULL_TREE) {
5040 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5041 convert (TREE_TYPE (arg3_tree),
5042 expr_tree));
5043 }
5044 }
5045 return expr_tree;
5046
5047 case FFEINTRIN_impCTIME_subr:
5048 case FFEINTRIN_impTTYNAM_subr:
5049 {
5050 tree arg1_len = integer_zero_node;
5051 tree arg1_tree;
5052 tree arg2_tree;
5053
5054 ffecom_push_calltemps ();
5055
5056 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5057
5058 arg2_tree = convert (((gfrt == FFEINTRIN_impCTIME_subr) ?
5059 ffecom_f2c_longint_type_node :
5060 ffecom_f2c_integer_type_node),
5061 ffecom_expr (arg2));
5062 arg2_tree = ffecom_1 (ADDR_EXPR,
5063 build_pointer_type (TREE_TYPE (arg2_tree)),
5064 arg2_tree);
5065
5066 ffecom_pop_calltemps ();
5067
5068 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5069 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5070 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5071 TREE_CHAIN (arg1_len) = arg2_tree;
5072 TREE_CHAIN (arg1_tree) = arg1_len;
5073
5074 expr_tree
5075 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5076 ffecom_gfrt_kindtype (gfrt),
5077 FALSE,
5078 NULL_TREE,
5079 arg1_tree,
5080 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
5081 }
5082 return expr_tree;
5083
5084 case FFEINTRIN_impIRAND:
5085 case FFEINTRIN_impRAND:
5086 /* Arg defaults to 0 (normal random case) */
5087 {
5088 tree arg1_tree;
5089
5090 if (arg1 == NULL)
5091 arg1_tree = ffecom_integer_zero_node;
5092 else
5093 arg1_tree = ffecom_expr (arg1);
5094 arg1_tree = convert (ffecom_f2c_integer_type_node,
5095 arg1_tree);
5096 arg1_tree = ffecom_1 (ADDR_EXPR,
5097 build_pointer_type (TREE_TYPE (arg1_tree)),
5098 arg1_tree);
5099 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5100
5101 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5102 ffecom_gfrt_kindtype (gfrt),
5103 FALSE,
5104 ((codegen_imp == FFEINTRIN_impIRAND) ?
5105 ffecom_f2c_integer_type_node :
5106 ffecom_f2c_doublereal_type_node),
5107 arg1_tree,
5108 dest_tree, dest, dest_used,
5109 NULL_TREE, TRUE);
5110 }
5111 return expr_tree;
5112
5113 case FFEINTRIN_impFTELL_subr:
5114 case FFEINTRIN_impUMASK_subr:
5115 {
5116 tree arg1_tree;
5117 tree arg2_tree;
5118
5119 ffecom_push_calltemps ();
5120
5121 arg1_tree = convert (ffecom_f2c_integer_type_node,
5122 ffecom_expr (arg1));
5123 arg1_tree = ffecom_1 (ADDR_EXPR,
5124 build_pointer_type (TREE_TYPE (arg1_tree)),
5125 arg1_tree);
5126
5127 if (arg2 == NULL)
5128 arg2_tree = NULL_TREE;
5129 else
5130 arg2_tree = ffecom_expr_rw (arg2);
5131
5132 ffecom_pop_calltemps ();
5133
5134 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5135 ffecom_gfrt_kindtype (gfrt),
5136 FALSE,
5137 NULL_TREE,
5138 build_tree_list (NULL_TREE, arg1_tree),
5139 NULL_TREE, NULL, NULL, NULL_TREE,
5140 TRUE);
5141 if (arg2_tree != NULL_TREE) {
5142 expr_tree = ffecom_modify (NULL_TREE, arg2_tree,
5143 convert (TREE_TYPE (arg2_tree),
5144 expr_tree));
5145 }
5146 }
5147 return expr_tree;
5148
5149 case FFEINTRIN_impCPU_TIME:
5150 case FFEINTRIN_impSECOND_subr:
5151 {
5152 tree arg1_tree;
5153
5154 ffecom_push_calltemps ();
5155
5156 arg1_tree = ffecom_expr_rw (arg1);
5157
5158 ffecom_pop_calltemps ();
5159
5160 expr_tree
5161 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5162 ffecom_gfrt_kindtype (gfrt),
5163 FALSE,
5164 NULL_TREE,
5165 NULL_TREE,
5166 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
5167
5168 expr_tree
5169 = ffecom_modify (NULL_TREE, arg1_tree,
5170 convert (TREE_TYPE (arg1_tree),
5171 expr_tree));
5172 }
5173 return expr_tree;
5174
5175 case FFEINTRIN_impDTIME_subr:
5176 case FFEINTRIN_impETIME_subr:
5177 {
5178 tree arg1_tree;
5179 tree arg2_tree;
5180
5181 ffecom_push_calltemps ();
5182
5183 arg1_tree = ffecom_expr_rw (arg1);
5184
5185 arg2_tree = ffecom_ptr_to_expr (arg2);
5186
5187 ffecom_pop_calltemps ();
5188
5189 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5190 ffecom_gfrt_kindtype (gfrt),
5191 FALSE,
5192 NULL_TREE,
5193 build_tree_list (NULL_TREE, arg2_tree),
5194 NULL_TREE, NULL, NULL, NULL_TREE,
5195 TRUE);
5196 expr_tree = ffecom_modify (NULL_TREE, arg1_tree,
5197 convert (TREE_TYPE (arg1_tree),
5198 expr_tree));
5199 }
5200 return expr_tree;
5201
5202 /* Straightforward calls of libf2c routines: */
5203 case FFEINTRIN_impABORT:
5204 case FFEINTRIN_impACCESS:
5205 case FFEINTRIN_impBESJ0:
5206 case FFEINTRIN_impBESJ1:
5207 case FFEINTRIN_impBESJN:
5208 case FFEINTRIN_impBESY0:
5209 case FFEINTRIN_impBESY1:
5210 case FFEINTRIN_impBESYN:
5211 case FFEINTRIN_impCHDIR_func:
5212 case FFEINTRIN_impCHMOD_func:
5213 case FFEINTRIN_impDATE:
9e8e701d 5214 case FFEINTRIN_impDATE_AND_TIME:
5ff904cd
JL
5215 case FFEINTRIN_impDBESJ0:
5216 case FFEINTRIN_impDBESJ1:
5217 case FFEINTRIN_impDBESJN:
5218 case FFEINTRIN_impDBESY0:
5219 case FFEINTRIN_impDBESY1:
5220 case FFEINTRIN_impDBESYN:
5221 case FFEINTRIN_impDTIME_func:
5222 case FFEINTRIN_impETIME_func:
5223 case FFEINTRIN_impFGETC_func:
5224 case FFEINTRIN_impFGET_func:
5225 case FFEINTRIN_impFNUM:
5226 case FFEINTRIN_impFPUTC_func:
5227 case FFEINTRIN_impFPUT_func:
5228 case FFEINTRIN_impFSEEK:
5229 case FFEINTRIN_impFSTAT_func:
5230 case FFEINTRIN_impFTELL_func:
5231 case FFEINTRIN_impGERROR:
5232 case FFEINTRIN_impGETARG:
5233 case FFEINTRIN_impGETCWD_func:
5234 case FFEINTRIN_impGETENV:
5235 case FFEINTRIN_impGETGID:
5236 case FFEINTRIN_impGETLOG:
5237 case FFEINTRIN_impGETPID:
5238 case FFEINTRIN_impGETUID:
5239 case FFEINTRIN_impGMTIME:
5240 case FFEINTRIN_impHOSTNM_func:
5241 case FFEINTRIN_impIDATE_unix:
5242 case FFEINTRIN_impIDATE_vxt:
5243 case FFEINTRIN_impIERRNO:
5244 case FFEINTRIN_impISATTY:
5245 case FFEINTRIN_impITIME:
5246 case FFEINTRIN_impKILL_func:
5247 case FFEINTRIN_impLINK_func:
5248 case FFEINTRIN_impLNBLNK:
5249 case FFEINTRIN_impLSTAT_func:
5250 case FFEINTRIN_impLTIME:
5251 case FFEINTRIN_impMCLOCK8:
5252 case FFEINTRIN_impMCLOCK:
5253 case FFEINTRIN_impPERROR:
5254 case FFEINTRIN_impRENAME_func:
5255 case FFEINTRIN_impSECNDS:
5256 case FFEINTRIN_impSECOND_func:
5257 case FFEINTRIN_impSLEEP:
5258 case FFEINTRIN_impSRAND:
5259 case FFEINTRIN_impSTAT_func:
5260 case FFEINTRIN_impSYMLNK_func:
5261 case FFEINTRIN_impSYSTEM_CLOCK:
5262 case FFEINTRIN_impSYSTEM_func:
5263 case FFEINTRIN_impTIME8:
5264 case FFEINTRIN_impTIME_unix:
5265 case FFEINTRIN_impTIME_vxt:
5266 case FFEINTRIN_impUMASK_func:
5267 case FFEINTRIN_impUNLINK_func:
5268 break;
5269
5270 case FFEINTRIN_impCTIME_func: /* CHARACTER functions not handled here. */
5271 case FFEINTRIN_impFDATE_func: /* CHARACTER functions not handled here. */
5272 case FFEINTRIN_impTTYNAM_func: /* CHARACTER functions not handled here. */
5273 case FFEINTRIN_impNONE:
5274 case FFEINTRIN_imp: /* Hush up gcc warning. */
5275 fprintf (stderr, "No %s implementation.\n",
5276 ffeintrin_name_implementation (ffebld_symter_implementation (ffebld_left (expr))));
5277 assert ("unimplemented intrinsic" == NULL);
5278 return error_mark_node;
5279 }
5280
5281 assert (gfrt != FFECOM_gfrt); /* Must have an implementation! */
5282
5283 ffecom_push_calltemps ();
5284 expr_tree = ffecom_arglist_expr_ (ffecom_gfrt_args_ (gfrt),
5285 ffebld_right (expr));
5286 ffecom_pop_calltemps ();
5287
5288 return ffecom_call_ (ffecom_gfrt_tree_ (gfrt), ffecom_gfrt_kindtype (gfrt),
5289 (ffe_is_f2c_library () && ffecom_gfrt_complex_[gfrt]),
5290 tree_type,
5291 expr_tree, dest_tree, dest, dest_used,
5292 NULL_TREE, TRUE);
5293
5294 /**INDENT* (Do not reformat this comment even with -fca option.)
5295 Data-gathering files: Given the source file listed below, compiled with
5296 f2c I obtained the output file listed after that, and from the output
5297 file I derived the above code.
5298
5299-------- (begin input file to f2c)
5300 implicit none
5301 character*10 A1,A2
5302 complex C1,C2
5303 integer I1,I2
5304 real R1,R2
5305 double precision D1,D2
5306C
5307 call getem(A1,A2,C1,C2,I1,I2,R1,R2,D1,D2)
5308c /
5309 call fooI(I1/I2)
5310 call fooR(R1/I1)
5311 call fooD(D1/I1)
5312 call fooC(C1/I1)
5313 call fooR(R1/R2)
5314 call fooD(R1/D1)
5315 call fooD(D1/D2)
5316 call fooD(D1/R1)
5317 call fooC(C1/C2)
5318 call fooC(C1/R1)
5319 call fooZ(C1/D1)
5320c **
5321 call fooI(I1**I2)
5322 call fooR(R1**I1)
5323 call fooD(D1**I1)
5324 call fooC(C1**I1)
5325 call fooR(R1**R2)
5326 call fooD(R1**D1)
5327 call fooD(D1**D2)
5328 call fooD(D1**R1)
5329 call fooC(C1**C2)
5330 call fooC(C1**R1)
5331 call fooZ(C1**D1)
5332c FFEINTRIN_impABS
5333 call fooR(ABS(R1))
5334c FFEINTRIN_impACOS
5335 call fooR(ACOS(R1))
5336c FFEINTRIN_impAIMAG
5337 call fooR(AIMAG(C1))
5338c FFEINTRIN_impAINT
5339 call fooR(AINT(R1))
5340c FFEINTRIN_impALOG
5341 call fooR(ALOG(R1))
5342c FFEINTRIN_impALOG10
5343 call fooR(ALOG10(R1))
5344c FFEINTRIN_impAMAX0
5345 call fooR(AMAX0(I1,I2))
5346c FFEINTRIN_impAMAX1
5347 call fooR(AMAX1(R1,R2))
5348c FFEINTRIN_impAMIN0
5349 call fooR(AMIN0(I1,I2))
5350c FFEINTRIN_impAMIN1
5351 call fooR(AMIN1(R1,R2))
5352c FFEINTRIN_impAMOD
5353 call fooR(AMOD(R1,R2))
5354c FFEINTRIN_impANINT
5355 call fooR(ANINT(R1))
5356c FFEINTRIN_impASIN
5357 call fooR(ASIN(R1))
5358c FFEINTRIN_impATAN
5359 call fooR(ATAN(R1))
5360c FFEINTRIN_impATAN2
5361 call fooR(ATAN2(R1,R2))
5362c FFEINTRIN_impCABS
5363 call fooR(CABS(C1))
5364c FFEINTRIN_impCCOS
5365 call fooC(CCOS(C1))
5366c FFEINTRIN_impCEXP
5367 call fooC(CEXP(C1))
5368c FFEINTRIN_impCHAR
5369 call fooA(CHAR(I1))
5370c FFEINTRIN_impCLOG
5371 call fooC(CLOG(C1))
5372c FFEINTRIN_impCONJG
5373 call fooC(CONJG(C1))
5374c FFEINTRIN_impCOS
5375 call fooR(COS(R1))
5376c FFEINTRIN_impCOSH
5377 call fooR(COSH(R1))
5378c FFEINTRIN_impCSIN
5379 call fooC(CSIN(C1))
5380c FFEINTRIN_impCSQRT
5381 call fooC(CSQRT(C1))
5382c FFEINTRIN_impDABS
5383 call fooD(DABS(D1))
5384c FFEINTRIN_impDACOS
5385 call fooD(DACOS(D1))
5386c FFEINTRIN_impDASIN
5387 call fooD(DASIN(D1))
5388c FFEINTRIN_impDATAN
5389 call fooD(DATAN(D1))
5390c FFEINTRIN_impDATAN2
5391 call fooD(DATAN2(D1,D2))
5392c FFEINTRIN_impDCOS
5393 call fooD(DCOS(D1))
5394c FFEINTRIN_impDCOSH
5395 call fooD(DCOSH(D1))
5396c FFEINTRIN_impDDIM
5397 call fooD(DDIM(D1,D2))
5398c FFEINTRIN_impDEXP
5399 call fooD(DEXP(D1))
5400c FFEINTRIN_impDIM
5401 call fooR(DIM(R1,R2))
5402c FFEINTRIN_impDINT
5403 call fooD(DINT(D1))
5404c FFEINTRIN_impDLOG
5405 call fooD(DLOG(D1))
5406c FFEINTRIN_impDLOG10
5407 call fooD(DLOG10(D1))
5408c FFEINTRIN_impDMAX1
5409 call fooD(DMAX1(D1,D2))
5410c FFEINTRIN_impDMIN1
5411 call fooD(DMIN1(D1,D2))
5412c FFEINTRIN_impDMOD
5413 call fooD(DMOD(D1,D2))
5414c FFEINTRIN_impDNINT
5415 call fooD(DNINT(D1))
5416c FFEINTRIN_impDPROD
5417 call fooD(DPROD(R1,R2))
5418c FFEINTRIN_impDSIGN
5419 call fooD(DSIGN(D1,D2))
5420c FFEINTRIN_impDSIN
5421 call fooD(DSIN(D1))
5422c FFEINTRIN_impDSINH
5423 call fooD(DSINH(D1))
5424c FFEINTRIN_impDSQRT
5425 call fooD(DSQRT(D1))
5426c FFEINTRIN_impDTAN
5427 call fooD(DTAN(D1))
5428c FFEINTRIN_impDTANH
5429 call fooD(DTANH(D1))
5430c FFEINTRIN_impEXP
5431 call fooR(EXP(R1))
5432c FFEINTRIN_impIABS
5433 call fooI(IABS(I1))
5434c FFEINTRIN_impICHAR
5435 call fooI(ICHAR(A1))
5436c FFEINTRIN_impIDIM
5437 call fooI(IDIM(I1,I2))
5438c FFEINTRIN_impIDNINT
5439 call fooI(IDNINT(D1))
5440c FFEINTRIN_impINDEX
5441 call fooI(INDEX(A1,A2))
5442c FFEINTRIN_impISIGN
5443 call fooI(ISIGN(I1,I2))
5444c FFEINTRIN_impLEN
5445 call fooI(LEN(A1))
5446c FFEINTRIN_impLGE
5447 call fooL(LGE(A1,A2))
5448c FFEINTRIN_impLGT
5449 call fooL(LGT(A1,A2))
5450c FFEINTRIN_impLLE
5451 call fooL(LLE(A1,A2))
5452c FFEINTRIN_impLLT
5453 call fooL(LLT(A1,A2))
5454c FFEINTRIN_impMAX0
5455 call fooI(MAX0(I1,I2))
5456c FFEINTRIN_impMAX1
5457 call fooI(MAX1(R1,R2))
5458c FFEINTRIN_impMIN0
5459 call fooI(MIN0(I1,I2))
5460c FFEINTRIN_impMIN1
5461 call fooI(MIN1(R1,R2))
5462c FFEINTRIN_impMOD
5463 call fooI(MOD(I1,I2))
5464c FFEINTRIN_impNINT
5465 call fooI(NINT(R1))
5466c FFEINTRIN_impSIGN
5467 call fooR(SIGN(R1,R2))
5468c FFEINTRIN_impSIN
5469 call fooR(SIN(R1))
5470c FFEINTRIN_impSINH
5471 call fooR(SINH(R1))
5472c FFEINTRIN_impSQRT
5473 call fooR(SQRT(R1))
5474c FFEINTRIN_impTAN
5475 call fooR(TAN(R1))
5476c FFEINTRIN_impTANH
5477 call fooR(TANH(R1))
5478c FFEINTRIN_imp_CMPLX_C
5479 call fooC(cmplx(C1,C2))
5480c FFEINTRIN_imp_CMPLX_D
5481 call fooZ(cmplx(D1,D2))
5482c FFEINTRIN_imp_CMPLX_I
5483 call fooC(cmplx(I1,I2))
5484c FFEINTRIN_imp_CMPLX_R
5485 call fooC(cmplx(R1,R2))
5486c FFEINTRIN_imp_DBLE_C
5487 call fooD(dble(C1))
5488c FFEINTRIN_imp_DBLE_D
5489 call fooD(dble(D1))
5490c FFEINTRIN_imp_DBLE_I
5491 call fooD(dble(I1))
5492c FFEINTRIN_imp_DBLE_R
5493 call fooD(dble(R1))
5494c FFEINTRIN_imp_INT_C
5495 call fooI(int(C1))
5496c FFEINTRIN_imp_INT_D
5497 call fooI(int(D1))
5498c FFEINTRIN_imp_INT_I
5499 call fooI(int(I1))
5500c FFEINTRIN_imp_INT_R
5501 call fooI(int(R1))
5502c FFEINTRIN_imp_REAL_C
5503 call fooR(real(C1))
5504c FFEINTRIN_imp_REAL_D
5505 call fooR(real(D1))
5506c FFEINTRIN_imp_REAL_I
5507 call fooR(real(I1))
5508c FFEINTRIN_imp_REAL_R
5509 call fooR(real(R1))
5510c
5511c FFEINTRIN_imp_INT_D:
5512c
5513c FFEINTRIN_specIDINT
5514 call fooI(IDINT(D1))
5515c
5516c FFEINTRIN_imp_INT_R:
5517c
5518c FFEINTRIN_specIFIX
5519 call fooI(IFIX(R1))
5520c FFEINTRIN_specINT
5521 call fooI(INT(R1))
5522c
5523c FFEINTRIN_imp_REAL_D:
5524c
5525c FFEINTRIN_specSNGL
5526 call fooR(SNGL(D1))
5527c
5528c FFEINTRIN_imp_REAL_I:
5529c
5530c FFEINTRIN_specFLOAT
5531 call fooR(FLOAT(I1))
5532c FFEINTRIN_specREAL
5533 call fooR(REAL(I1))
5534c
5535 end
5536-------- (end input file to f2c)
5537
5538-------- (begin output from providing above input file as input to:
5539-------- `f2c | gcc -E -C - | sed -e "s:/[*]*://:g" -e "s:[*]*[/]://:g" \
5540-------- -e "s:^#.*$::g"')
5541
5542// -- translated by f2c (version 19950223).
5543 You must link the resulting object file with the libraries:
5544 -lf2c -lm (in that order)
5545//
5546
5547
5548// f2c.h -- Standard Fortran to C header file //
5549
5550/// barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed."
5551
5552 - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) //
5553
5554
5555
5556
5557// F2C_INTEGER will normally be `int' but would be `long' on 16-bit systems //
5558// we assume short, float are OK //
5559typedef long int // long int // integer;
5560typedef char *address;
5561typedef short int shortint;
5562typedef float real;
5563typedef double doublereal;
5564typedef struct { real r, i; } complex;
5565typedef struct { doublereal r, i; } doublecomplex;
5566typedef long int // long int // logical;
5567typedef short int shortlogical;
5568typedef char logical1;
5569typedef char integer1;
5570// typedef long long longint; // // system-dependent //
5571
5572
5573
5574
5575// Extern is for use with -E //
5576
5577
5578
5579
5580// I/O stuff //
5581
5582
5583
5584
5585
5586
5587
5588
5589typedef long int // int or long int // flag;
5590typedef long int // int or long int // ftnlen;
5591typedef long int // int or long int // ftnint;
5592
5593
5594//external read, write//
5595typedef struct
5596{ flag cierr;
5597 ftnint ciunit;
5598 flag ciend;
5599 char *cifmt;
5600 ftnint cirec;
5601} cilist;
5602
5603//internal read, write//
5604typedef struct
5605{ flag icierr;
5606 char *iciunit;
5607 flag iciend;
5608 char *icifmt;
5609 ftnint icirlen;
5610 ftnint icirnum;
5611} icilist;
5612
5613//open//
5614typedef struct
5615{ flag oerr;
5616 ftnint ounit;
5617 char *ofnm;
5618 ftnlen ofnmlen;
5619 char *osta;
5620 char *oacc;
5621 char *ofm;
5622 ftnint orl;
5623 char *oblnk;
5624} olist;
5625
5626//close//
5627typedef struct
5628{ flag cerr;
5629 ftnint cunit;
5630 char *csta;
5631} cllist;
5632
5633//rewind, backspace, endfile//
5634typedef struct
5635{ flag aerr;
5636 ftnint aunit;
5637} alist;
5638
5639// inquire //
5640typedef struct
5641{ flag inerr;
5642 ftnint inunit;
5643 char *infile;
5644 ftnlen infilen;
5645 ftnint *inex; //parameters in standard's order//
5646 ftnint *inopen;
5647 ftnint *innum;
5648 ftnint *innamed;
5649 char *inname;
5650 ftnlen innamlen;
5651 char *inacc;
5652 ftnlen inacclen;
5653 char *inseq;
5654 ftnlen inseqlen;
5655 char *indir;
5656 ftnlen indirlen;
5657 char *infmt;
5658 ftnlen infmtlen;
5659 char *inform;
5660 ftnint informlen;
5661 char *inunf;
5662 ftnlen inunflen;
5663 ftnint *inrecl;
5664 ftnint *innrec;
5665 char *inblank;
5666 ftnlen inblanklen;
5667} inlist;
5668
5669
5670
5671union Multitype { // for multiple entry points //
5672 integer1 g;
5673 shortint h;
5674 integer i;
5675 // longint j; //
5676 real r;
5677 doublereal d;
5678 complex c;
5679 doublecomplex z;
5680 };
5681
5682typedef union Multitype Multitype;
5683
5684typedef long Long; // No longer used; formerly in Namelist //
5685
5686struct Vardesc { // for Namelist //
5687 char *name;
5688 char *addr;
5689 ftnlen *dims;
5690 int type;
5691 };
5692typedef struct Vardesc Vardesc;
5693
5694struct Namelist {
5695 char *name;
5696 Vardesc **vars;
5697 int nvars;
5698 };
5699typedef struct Namelist Namelist;
5700
5701
5702
5703
5704
5705
5706
5707
5708// procedure parameter types for -A and -C++ //
5709
5710
5711
5712
5713typedef int // Unknown procedure type // (*U_fp)();
5714typedef shortint (*J_fp)();
5715typedef integer (*I_fp)();
5716typedef real (*R_fp)();
5717typedef doublereal (*D_fp)(), (*E_fp)();
5718typedef // Complex // void (*C_fp)();
5719typedef // Double Complex // void (*Z_fp)();
5720typedef logical (*L_fp)();
5721typedef shortlogical (*K_fp)();
5722typedef // Character // void (*H_fp)();
5723typedef // Subroutine // int (*S_fp)();
5724
5725// E_fp is for real functions when -R is not specified //
5726typedef void C_f; // complex function //
5727typedef void H_f; // character function //
5728typedef void Z_f; // double complex function //
5729typedef doublereal E_f; // real function with -R not specified //
5730
5731// undef any lower-case symbols that your C compiler predefines, e.g.: //
5732
5733
5734// (No such symbols should be defined in a strict ANSI C compiler.
5735 We can avoid trouble with f2c-translated code by using
5736 gcc -ansi [-traditional].) //
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760// Main program // MAIN__()
5761{
5762 // System generated locals //
5763 integer i__1;
5764 real r__1, r__2;
5765 doublereal d__1, d__2;
5766 complex q__1;
5767 doublecomplex z__1, z__2, z__3;
5768 logical L__1;
5769 char ch__1[1];
5770
5771 // Builtin functions //
5772 void c_div();
5773 integer pow_ii();
5774 double pow_ri(), pow_di();
5775 void pow_ci();
5776 double pow_dd();
5777 void pow_zz();
5778 double acos(), r_imag(), r_int(), log(), r_lg10(), r_mod(), r_nint(),
5779 asin(), atan(), atan2(), c_abs();
5780 void c_cos(), c_exp(), c_log(), r_cnjg();
5781 double cos(), cosh();
5782 void c_sin(), c_sqrt();
5783 double d_dim(), exp(), r_dim(), d_int(), d_lg10(), d_mod(), d_nint(),
5784 d_sign(), sin(), sinh(), sqrt(), tan(), tanh();
5785 integer i_dim(), i_dnnt(), i_indx(), i_sign(), i_len();
5786 logical l_ge(), l_gt(), l_le(), l_lt();
5787 integer i_nint();
5788 double r_sign();
5789
5790 // Local variables //
5791 extern // Subroutine // int fooa_(), fooc_(), food_(), fooi_(), foor_(),
5792 fool_(), fooz_(), getem_();
5793 static char a1[10], a2[10];
5794 static complex c1, c2;
5795 static doublereal d1, d2;
5796 static integer i1, i2;
5797 static real r1, r2;
5798
5799
5800 getem_(a1, a2, &c1, &c2, &i1, &i2, &r1, &r2, &d1, &d2, 10L, 10L);
5801// / //
5802 i__1 = i1 / i2;
5803 fooi_(&i__1);
5804 r__1 = r1 / i1;
5805 foor_(&r__1);
5806 d__1 = d1 / i1;
5807 food_(&d__1);
5808 d__1 = (doublereal) i1;
5809 q__1.r = c1.r / d__1, q__1.i = c1.i / d__1;
5810 fooc_(&q__1);
5811 r__1 = r1 / r2;
5812 foor_(&r__1);
5813 d__1 = r1 / d1;
5814 food_(&d__1);
5815 d__1 = d1 / d2;
5816 food_(&d__1);
5817 d__1 = d1 / r1;
5818 food_(&d__1);
5819 c_div(&q__1, &c1, &c2);
5820 fooc_(&q__1);
5821 q__1.r = c1.r / r1, q__1.i = c1.i / r1;
5822 fooc_(&q__1);
5823 z__1.r = c1.r / d1, z__1.i = c1.i / d1;
5824 fooz_(&z__1);
5825// ** //
5826 i__1 = pow_ii(&i1, &i2);
5827 fooi_(&i__1);
5828 r__1 = pow_ri(&r1, &i1);
5829 foor_(&r__1);
5830 d__1 = pow_di(&d1, &i1);
5831 food_(&d__1);
5832 pow_ci(&q__1, &c1, &i1);
5833 fooc_(&q__1);
5834 d__1 = (doublereal) r1;
5835 d__2 = (doublereal) r2;
5836 r__1 = pow_dd(&d__1, &d__2);
5837 foor_(&r__1);
5838 d__2 = (doublereal) r1;
5839 d__1 = pow_dd(&d__2, &d1);
5840 food_(&d__1);
5841 d__1 = pow_dd(&d1, &d2);
5842 food_(&d__1);
5843 d__2 = (doublereal) r1;
5844 d__1 = pow_dd(&d1, &d__2);
5845 food_(&d__1);
5846 z__2.r = c1.r, z__2.i = c1.i;
5847 z__3.r = c2.r, z__3.i = c2.i;
5848 pow_zz(&z__1, &z__2, &z__3);
5849 q__1.r = z__1.r, q__1.i = z__1.i;
5850 fooc_(&q__1);
5851 z__2.r = c1.r, z__2.i = c1.i;
5852 z__3.r = r1, z__3.i = 0.;
5853 pow_zz(&z__1, &z__2, &z__3);
5854 q__1.r = z__1.r, q__1.i = z__1.i;
5855 fooc_(&q__1);
5856 z__2.r = c1.r, z__2.i = c1.i;
5857 z__3.r = d1, z__3.i = 0.;
5858 pow_zz(&z__1, &z__2, &z__3);
5859 fooz_(&z__1);
5860// FFEINTRIN_impABS //
5861 r__1 = (doublereal)(( r1 ) >= 0 ? ( r1 ) : -( r1 )) ;
5862 foor_(&r__1);
5863// FFEINTRIN_impACOS //
5864 r__1 = acos(r1);
5865 foor_(&r__1);
5866// FFEINTRIN_impAIMAG //
5867 r__1 = r_imag(&c1);
5868 foor_(&r__1);
5869// FFEINTRIN_impAINT //
5870 r__1 = r_int(&r1);
5871 foor_(&r__1);
5872// FFEINTRIN_impALOG //
5873 r__1 = log(r1);
5874 foor_(&r__1);
5875// FFEINTRIN_impALOG10 //
5876 r__1 = r_lg10(&r1);
5877 foor_(&r__1);
5878// FFEINTRIN_impAMAX0 //
5879 r__1 = (real) (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
5880 foor_(&r__1);
5881// FFEINTRIN_impAMAX1 //
5882 r__1 = (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
5883 foor_(&r__1);
5884// FFEINTRIN_impAMIN0 //
5885 r__1 = (real) (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
5886 foor_(&r__1);
5887// FFEINTRIN_impAMIN1 //
5888 r__1 = (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
5889 foor_(&r__1);
5890// FFEINTRIN_impAMOD //
5891 r__1 = r_mod(&r1, &r2);
5892 foor_(&r__1);
5893// FFEINTRIN_impANINT //
5894 r__1 = r_nint(&r1);
5895 foor_(&r__1);
5896// FFEINTRIN_impASIN //
5897 r__1 = asin(r1);
5898 foor_(&r__1);
5899// FFEINTRIN_impATAN //
5900 r__1 = atan(r1);
5901 foor_(&r__1);
5902// FFEINTRIN_impATAN2 //
5903 r__1 = atan2(r1, r2);
5904 foor_(&r__1);
5905// FFEINTRIN_impCABS //
5906 r__1 = c_abs(&c1);
5907 foor_(&r__1);
5908// FFEINTRIN_impCCOS //
5909 c_cos(&q__1, &c1);
5910 fooc_(&q__1);
5911// FFEINTRIN_impCEXP //
5912 c_exp(&q__1, &c1);
5913 fooc_(&q__1);
5914// FFEINTRIN_impCHAR //
5915 *(unsigned char *)&ch__1[0] = i1;
5916 fooa_(ch__1, 1L);
5917// FFEINTRIN_impCLOG //
5918 c_log(&q__1, &c1);
5919 fooc_(&q__1);
5920// FFEINTRIN_impCONJG //
5921 r_cnjg(&q__1, &c1);
5922 fooc_(&q__1);
5923// FFEINTRIN_impCOS //
5924 r__1 = cos(r1);
5925 foor_(&r__1);
5926// FFEINTRIN_impCOSH //
5927 r__1 = cosh(r1);
5928 foor_(&r__1);
5929// FFEINTRIN_impCSIN //
5930 c_sin(&q__1, &c1);
5931 fooc_(&q__1);
5932// FFEINTRIN_impCSQRT //
5933 c_sqrt(&q__1, &c1);
5934 fooc_(&q__1);
5935// FFEINTRIN_impDABS //
5936 d__1 = (( d1 ) >= 0 ? ( d1 ) : -( d1 )) ;
5937 food_(&d__1);
5938// FFEINTRIN_impDACOS //
5939 d__1 = acos(d1);
5940 food_(&d__1);
5941// FFEINTRIN_impDASIN //
5942 d__1 = asin(d1);
5943 food_(&d__1);
5944// FFEINTRIN_impDATAN //
5945 d__1 = atan(d1);
5946 food_(&d__1);
5947// FFEINTRIN_impDATAN2 //
5948 d__1 = atan2(d1, d2);
5949 food_(&d__1);
5950// FFEINTRIN_impDCOS //
5951 d__1 = cos(d1);
5952 food_(&d__1);
5953// FFEINTRIN_impDCOSH //
5954 d__1 = cosh(d1);
5955 food_(&d__1);
5956// FFEINTRIN_impDDIM //
5957 d__1 = d_dim(&d1, &d2);
5958 food_(&d__1);
5959// FFEINTRIN_impDEXP //
5960 d__1 = exp(d1);
5961 food_(&d__1);
5962// FFEINTRIN_impDIM //
5963 r__1 = r_dim(&r1, &r2);
5964 foor_(&r__1);
5965// FFEINTRIN_impDINT //
5966 d__1 = d_int(&d1);
5967 food_(&d__1);
5968// FFEINTRIN_impDLOG //
5969 d__1 = log(d1);
5970 food_(&d__1);
5971// FFEINTRIN_impDLOG10 //
5972 d__1 = d_lg10(&d1);
5973 food_(&d__1);
5974// FFEINTRIN_impDMAX1 //
5975 d__1 = (( d1 ) >= ( d2 ) ? ( d1 ) : ( d2 )) ;
5976 food_(&d__1);
5977// FFEINTRIN_impDMIN1 //
5978 d__1 = (( d1 ) <= ( d2 ) ? ( d1 ) : ( d2 )) ;
5979 food_(&d__1);
5980// FFEINTRIN_impDMOD //
5981 d__1 = d_mod(&d1, &d2);
5982 food_(&d__1);
5983// FFEINTRIN_impDNINT //
5984 d__1 = d_nint(&d1);
5985 food_(&d__1);
5986// FFEINTRIN_impDPROD //
5987 d__1 = (doublereal) r1 * r2;
5988 food_(&d__1);
5989// FFEINTRIN_impDSIGN //
5990 d__1 = d_sign(&d1, &d2);
5991 food_(&d__1);
5992// FFEINTRIN_impDSIN //
5993 d__1 = sin(d1);
5994 food_(&d__1);
5995// FFEINTRIN_impDSINH //
5996 d__1 = sinh(d1);
5997 food_(&d__1);
5998// FFEINTRIN_impDSQRT //
5999 d__1 = sqrt(d1);
6000 food_(&d__1);
6001// FFEINTRIN_impDTAN //
6002 d__1 = tan(d1);
6003 food_(&d__1);
6004// FFEINTRIN_impDTANH //
6005 d__1 = tanh(d1);
6006 food_(&d__1);
6007// FFEINTRIN_impEXP //
6008 r__1 = exp(r1);
6009 foor_(&r__1);
6010// FFEINTRIN_impIABS //
6011 i__1 = (( i1 ) >= 0 ? ( i1 ) : -( i1 )) ;
6012 fooi_(&i__1);
6013// FFEINTRIN_impICHAR //
6014 i__1 = *(unsigned char *)a1;
6015 fooi_(&i__1);
6016// FFEINTRIN_impIDIM //
6017 i__1 = i_dim(&i1, &i2);
6018 fooi_(&i__1);
6019// FFEINTRIN_impIDNINT //
6020 i__1 = i_dnnt(&d1);
6021 fooi_(&i__1);
6022// FFEINTRIN_impINDEX //
6023 i__1 = i_indx(a1, a2, 10L, 10L);
6024 fooi_(&i__1);
6025// FFEINTRIN_impISIGN //
6026 i__1 = i_sign(&i1, &i2);
6027 fooi_(&i__1);
6028// FFEINTRIN_impLEN //
6029 i__1 = i_len(a1, 10L);
6030 fooi_(&i__1);
6031// FFEINTRIN_impLGE //
6032 L__1 = l_ge(a1, a2, 10L, 10L);
6033 fool_(&L__1);
6034// FFEINTRIN_impLGT //
6035 L__1 = l_gt(a1, a2, 10L, 10L);
6036 fool_(&L__1);
6037// FFEINTRIN_impLLE //
6038 L__1 = l_le(a1, a2, 10L, 10L);
6039 fool_(&L__1);
6040// FFEINTRIN_impLLT //
6041 L__1 = l_lt(a1, a2, 10L, 10L);
6042 fool_(&L__1);
6043// FFEINTRIN_impMAX0 //
6044 i__1 = (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
6045 fooi_(&i__1);
6046// FFEINTRIN_impMAX1 //
6047 i__1 = (integer) (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
6048 fooi_(&i__1);
6049// FFEINTRIN_impMIN0 //
6050 i__1 = (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
6051 fooi_(&i__1);
6052// FFEINTRIN_impMIN1 //
6053 i__1 = (integer) (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
6054 fooi_(&i__1);
6055// FFEINTRIN_impMOD //
6056 i__1 = i1 % i2;
6057 fooi_(&i__1);
6058// FFEINTRIN_impNINT //
6059 i__1 = i_nint(&r1);
6060 fooi_(&i__1);
6061// FFEINTRIN_impSIGN //
6062 r__1 = r_sign(&r1, &r2);
6063 foor_(&r__1);
6064// FFEINTRIN_impSIN //
6065 r__1 = sin(r1);
6066 foor_(&r__1);
6067// FFEINTRIN_impSINH //
6068 r__1 = sinh(r1);
6069 foor_(&r__1);
6070// FFEINTRIN_impSQRT //
6071 r__1 = sqrt(r1);
6072 foor_(&r__1);
6073// FFEINTRIN_impTAN //
6074 r__1 = tan(r1);
6075 foor_(&r__1);
6076// FFEINTRIN_impTANH //
6077 r__1 = tanh(r1);
6078 foor_(&r__1);
6079// FFEINTRIN_imp_CMPLX_C //
6080 r__1 = c1.r;
6081 r__2 = c2.r;
6082 q__1.r = r__1, q__1.i = r__2;
6083 fooc_(&q__1);
6084// FFEINTRIN_imp_CMPLX_D //
6085 z__1.r = d1, z__1.i = d2;
6086 fooz_(&z__1);
6087// FFEINTRIN_imp_CMPLX_I //
6088 r__1 = (real) i1;
6089 r__2 = (real) i2;
6090 q__1.r = r__1, q__1.i = r__2;
6091 fooc_(&q__1);
6092// FFEINTRIN_imp_CMPLX_R //
6093 q__1.r = r1, q__1.i = r2;
6094 fooc_(&q__1);
6095// FFEINTRIN_imp_DBLE_C //
6096 d__1 = (doublereal) c1.r;
6097 food_(&d__1);
6098// FFEINTRIN_imp_DBLE_D //
6099 d__1 = d1;
6100 food_(&d__1);
6101// FFEINTRIN_imp_DBLE_I //
6102 d__1 = (doublereal) i1;
6103 food_(&d__1);
6104// FFEINTRIN_imp_DBLE_R //
6105 d__1 = (doublereal) r1;
6106 food_(&d__1);
6107// FFEINTRIN_imp_INT_C //
6108 i__1 = (integer) c1.r;
6109 fooi_(&i__1);
6110// FFEINTRIN_imp_INT_D //
6111 i__1 = (integer) d1;
6112 fooi_(&i__1);
6113// FFEINTRIN_imp_INT_I //
6114 i__1 = i1;
6115 fooi_(&i__1);
6116// FFEINTRIN_imp_INT_R //
6117 i__1 = (integer) r1;
6118 fooi_(&i__1);
6119// FFEINTRIN_imp_REAL_C //
6120 r__1 = c1.r;
6121 foor_(&r__1);
6122// FFEINTRIN_imp_REAL_D //
6123 r__1 = (real) d1;
6124 foor_(&r__1);
6125// FFEINTRIN_imp_REAL_I //
6126 r__1 = (real) i1;
6127 foor_(&r__1);
6128// FFEINTRIN_imp_REAL_R //
6129 r__1 = r1;
6130 foor_(&r__1);
6131
6132// FFEINTRIN_imp_INT_D: //
6133
6134// FFEINTRIN_specIDINT //
6135 i__1 = (integer) d1;
6136 fooi_(&i__1);
6137
6138// FFEINTRIN_imp_INT_R: //
6139
6140// FFEINTRIN_specIFIX //
6141 i__1 = (integer) r1;
6142 fooi_(&i__1);
6143// FFEINTRIN_specINT //
6144 i__1 = (integer) r1;
6145 fooi_(&i__1);
6146
6147// FFEINTRIN_imp_REAL_D: //
6148
6149// FFEINTRIN_specSNGL //
6150 r__1 = (real) d1;
6151 foor_(&r__1);
6152
6153// FFEINTRIN_imp_REAL_I: //
6154
6155// FFEINTRIN_specFLOAT //
6156 r__1 = (real) i1;
6157 foor_(&r__1);
6158// FFEINTRIN_specREAL //
6159 r__1 = (real) i1;
6160 foor_(&r__1);
6161
6162} // MAIN__ //
6163
6164-------- (end output file from f2c)
6165
6166*/
6167}
6168
6169#endif
6170/* For power (exponentiation) where right-hand operand is type INTEGER,
6171 generate in-line code to do it the fast way (which, if the operand
6172 is a constant, might just mean a series of multiplies). */
6173
6174#if FFECOM_targetCURRENT == FFECOM_targetGCC
6175static tree
6176ffecom_expr_power_integer_ (ffebld left, ffebld right)
6177{
6178 tree l = ffecom_expr (left);
6179 tree r = ffecom_expr (right);
6180 tree ltype = TREE_TYPE (l);
6181 tree rtype = TREE_TYPE (r);
6182 tree result = NULL_TREE;
6183
6184 if (l == error_mark_node
6185 || r == error_mark_node)
6186 return error_mark_node;
6187
6188 if (TREE_CODE (r) == INTEGER_CST)
6189 {
6190 int sgn = tree_int_cst_sgn (r);
6191
6192 if (sgn == 0)
6193 return convert (ltype, integer_one_node);
6194
6195 if ((TREE_CODE (ltype) == INTEGER_TYPE)
6196 && (sgn < 0))
6197 {
6198 /* Reciprocal of integer is either 0, -1, or 1, so after
6199 calculating that (which we leave to the back end to do
6200 or not do optimally), don't bother with any multiplying. */
6201
6202 result = ffecom_tree_divide_ (ltype,
6203 convert (ltype, integer_one_node),
6204 l,
6205 NULL_TREE, NULL, NULL);
6206 r = ffecom_1 (NEGATE_EXPR,
6207 rtype,
6208 r);
6209 if ((TREE_INT_CST_LOW (r) & 1) == 0)
6210 result = ffecom_1 (ABS_EXPR, rtype,
6211 result);
6212 }
6213
6214 /* Generate appropriate series of multiplies, preceded
6215 by divide if the exponent is negative. */
6216
6217 l = save_expr (l);
6218
6219 if (sgn < 0)
6220 {
6221 l = ffecom_tree_divide_ (ltype,
6222 convert (ltype, integer_one_node),
6223 l,
6224 NULL_TREE, NULL, NULL);
6225 r = ffecom_1 (NEGATE_EXPR, rtype, r);
6226 assert (TREE_CODE (r) == INTEGER_CST);
6227
6228 if (tree_int_cst_sgn (r) < 0)
6229 { /* The "most negative" number. */
6230 r = ffecom_1 (NEGATE_EXPR, rtype,
6231 ffecom_2 (RSHIFT_EXPR, rtype,
6232 r,
6233 integer_one_node));
6234 l = save_expr (l);
6235 l = ffecom_2 (MULT_EXPR, ltype,
6236 l,
6237 l);
6238 }
6239 }
6240
6241 for (;;)
6242 {
6243 if (TREE_INT_CST_LOW (r) & 1)
6244 {
6245 if (result == NULL_TREE)
6246 result = l;
6247 else
6248 result = ffecom_2 (MULT_EXPR, ltype,
6249 result,
6250 l);
6251 }
6252
6253 r = ffecom_2 (RSHIFT_EXPR, rtype,
6254 r,
6255 integer_one_node);
6256 if (integer_zerop (r))
6257 break;
6258 assert (TREE_CODE (r) == INTEGER_CST);
6259
6260 l = save_expr (l);
6261 l = ffecom_2 (MULT_EXPR, ltype,
6262 l,
6263 l);
6264 }
6265 return result;
6266 }
6267
6268 /* Though rhs isn't a constant, in-line code cannot be expanded
6269 while transforming dummies
6270 because the back end cannot be easily convinced to generate
6271 stores (MODIFY_EXPR), handle temporaries, and so on before
6272 all the appropriate rtx's have been generated for things like
6273 dummy args referenced in rhs -- which doesn't happen until
6274 store_parm_decls() is called (expand_function_start, I believe,
6275 does the actual rtx-stuffing of PARM_DECLs).
6276
6277 So, in this case, let the caller generate the call to the
6278 run-time-library function to evaluate the power for us. */
6279
6280 if (ffecom_transform_only_dummies_)
6281 return NULL_TREE;
6282
6283 /* Right-hand operand not a constant, expand in-line code to figure
6284 out how to do the multiplies, &c.
6285
6286 The returned expression is expressed this way in GNU C, where l and
6287 r are the "inputs":
6288
6289 ({ typeof (r) rtmp = r;
44d2eabc
JL
6290 typeof (l) ltmp = l;
6291 typeof (l) result;
5ff904cd
JL
6292
6293 if (rtmp == 0)
6294 result = 1;
6295 else
6296 {
6297 if ((basetypeof (l) == basetypeof (int))
6298 && (rtmp < 0))
6299 {
6300 result = ((typeof (l)) 1) / ltmp;
6301 if ((ltmp < 0) && (((-rtmp) & 1) == 0))
6302 result = -result;
6303 }
6304 else
6305 {
6306 result = 1;
6307 if ((basetypeof (l) != basetypeof (int))
6308 && (rtmp < 0))
6309 {
6310 ltmp = ((typeof (l)) 1) / ltmp;
6311 rtmp = -rtmp;
6312 if (rtmp < 0)
6313 {
6314 rtmp = -(rtmp >> 1);
6315 ltmp *= ltmp;
6316 }
6317 }
6318 for (;;)
6319 {
6320 if (rtmp & 1)
6321 result *= ltmp;
6322 if ((rtmp >>= 1) == 0)
6323 break;
6324 ltmp *= ltmp;
6325 }
6326 }
6327 }
6328 result;
6329 })
6330
6331 Note that some of the above is compile-time collapsable, such as
6332 the first part of the if statements that checks the base type of
6333 l against int. The if statements are phrased that way to suggest
6334 an easy way to generate the if/else constructs here, knowing that
6335 the back end should (and probably does) eliminate the resulting
6336 dead code (either the int case or the non-int case), something
6337 it couldn't do without the redundant phrasing, requiring explicit
6338 dead-code elimination here, which would be kind of difficult to
6339 read. */
6340
6341 {
6342 tree rtmp;
6343 tree ltmp;
6344 tree basetypeof_l_is_int;
6345 tree se;
6346
6347 basetypeof_l_is_int
6348 = build_int_2 ((TREE_CODE (ltype) == INTEGER_TYPE), 0);
6349
6350 se = expand_start_stmt_expr ();
6351 ffecom_push_calltemps ();
6352
6353 rtmp = ffecom_push_tempvar (rtype, FFETARGET_charactersizeNONE, -1,
6354 TRUE);
6355 ltmp = ffecom_push_tempvar (ltype, FFETARGET_charactersizeNONE, -1,
6356 TRUE);
6357 result = ffecom_push_tempvar (ltype, FFETARGET_charactersizeNONE, -1,
6358 TRUE);
6359
6360 expand_expr_stmt (ffecom_modify (void_type_node,
6361 rtmp,
6362 r));
6363 expand_expr_stmt (ffecom_modify (void_type_node,
6364 ltmp,
6365 l));
6366 expand_start_cond (ffecom_truth_value
6367 (ffecom_2 (EQ_EXPR, integer_type_node,
6368 rtmp,
6369 convert (rtype, integer_zero_node))),
6370 0);
6371 expand_expr_stmt (ffecom_modify (void_type_node,
6372 result,
6373 convert (ltype, integer_one_node)));
6374 expand_start_else ();
6375 if (!integer_zerop (basetypeof_l_is_int))
6376 {
6377 expand_start_cond (ffecom_2 (LT_EXPR, integer_type_node,
6378 rtmp,
6379 convert (rtype,
6380 integer_zero_node)),
6381 0);
6382 expand_expr_stmt (ffecom_modify (void_type_node,
6383 result,
6384 ffecom_tree_divide_
6385 (ltype,
6386 convert (ltype, integer_one_node),
6387 ltmp,
6388 NULL_TREE, NULL, NULL)));
6389 expand_start_cond (ffecom_truth_value
6390 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
6391 ffecom_2 (LT_EXPR, integer_type_node,
6392 ltmp,
6393 convert (ltype,
6394 integer_zero_node)),
6395 ffecom_2 (EQ_EXPR, integer_type_node,
6396 ffecom_2 (BIT_AND_EXPR,
6397 rtype,
6398 ffecom_1 (NEGATE_EXPR,
6399 rtype,
6400 rtmp),
6401 convert (rtype,
6402 integer_one_node)),
6403 convert (rtype,
6404 integer_zero_node)))),
6405 0);
6406 expand_expr_stmt (ffecom_modify (void_type_node,
6407 result,
6408 ffecom_1 (NEGATE_EXPR,
6409 ltype,
6410 result)));
6411 expand_end_cond ();
6412 expand_start_else ();
6413 }
6414 expand_expr_stmt (ffecom_modify (void_type_node,
6415 result,
6416 convert (ltype, integer_one_node)));
6417 expand_start_cond (ffecom_truth_value
6418 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
6419 ffecom_truth_value_invert
6420 (basetypeof_l_is_int),
6421 ffecom_2 (LT_EXPR, integer_type_node,
6422 rtmp,
6423 convert (rtype,
6424 integer_zero_node)))),
6425 0);
6426 expand_expr_stmt (ffecom_modify (void_type_node,
6427 ltmp,
6428 ffecom_tree_divide_
6429 (ltype,
6430 convert (ltype, integer_one_node),
6431 ltmp,
6432 NULL_TREE, NULL, NULL)));
6433 expand_expr_stmt (ffecom_modify (void_type_node,
6434 rtmp,
6435 ffecom_1 (NEGATE_EXPR, rtype,
6436 rtmp)));
6437 expand_start_cond (ffecom_truth_value
6438 (ffecom_2 (LT_EXPR, integer_type_node,
6439 rtmp,
6440 convert (rtype, integer_zero_node))),
6441 0);
6442 expand_expr_stmt (ffecom_modify (void_type_node,
6443 rtmp,
6444 ffecom_1 (NEGATE_EXPR, rtype,
6445 ffecom_2 (RSHIFT_EXPR,
6446 rtype,
6447 rtmp,
6448 integer_one_node))));
6449 expand_expr_stmt (ffecom_modify (void_type_node,
6450 ltmp,
6451 ffecom_2 (MULT_EXPR, ltype,
6452 ltmp,
6453 ltmp)));
6454 expand_end_cond ();
6455 expand_end_cond ();
6456 expand_start_loop (1);
6457 expand_start_cond (ffecom_truth_value
6458 (ffecom_2 (BIT_AND_EXPR, rtype,
6459 rtmp,
6460 convert (rtype, integer_one_node))),
6461 0);
6462 expand_expr_stmt (ffecom_modify (void_type_node,
6463 result,
6464 ffecom_2 (MULT_EXPR, ltype,
6465 result,
6466 ltmp)));
6467 expand_end_cond ();
6468 expand_exit_loop_if_false (NULL,
6469 ffecom_truth_value
6470 (ffecom_modify (rtype,
6471 rtmp,
6472 ffecom_2 (RSHIFT_EXPR,
6473 rtype,
6474 rtmp,
6475 integer_one_node))));
6476 expand_expr_stmt (ffecom_modify (void_type_node,
6477 ltmp,
6478 ffecom_2 (MULT_EXPR, ltype,
6479 ltmp,
6480 ltmp)));
6481 expand_end_loop ();
6482 expand_end_cond ();
6483 if (!integer_zerop (basetypeof_l_is_int))
6484 expand_end_cond ();
6485 expand_expr_stmt (result);
6486
6487 ffecom_pop_calltemps ();
6488 result = expand_end_stmt_expr (se);
6489 TREE_SIDE_EFFECTS (result) = 1;
6490 }
6491
6492 return result;
6493}
6494
6495#endif
6496/* ffecom_expr_transform_ -- Transform symbols in expr
6497
6498 ffebld expr; // FFE expression.
6499 ffecom_expr_transform_ (expr);
6500
6501 Recursive descent on expr while transforming any untransformed SYMTERs. */
6502
6503#if FFECOM_targetCURRENT == FFECOM_targetGCC
6504static void
6505ffecom_expr_transform_ (ffebld expr)
6506{
6507 tree t;
6508 ffesymbol s;
6509
6510tail_recurse: /* :::::::::::::::::::: */
6511
6512 if (expr == NULL)
6513 return;
6514
6515 switch (ffebld_op (expr))
6516 {
6517 case FFEBLD_opSYMTER:
6518 s = ffebld_symter (expr);
6519 t = ffesymbol_hook (s).decl_tree;
6520 if ((t == NULL_TREE)
6521 && ((ffesymbol_kind (s) != FFEINFO_kindNONE)
6522 || ((ffesymbol_where (s) != FFEINFO_whereNONE)
6523 && (ffesymbol_where (s) != FFEINFO_whereINTRINSIC))))
6524 {
6525 s = ffecom_sym_transform_ (s);
6526 t = ffesymbol_hook (s).decl_tree; /* Sfunc expr non-dummy,
6527 DIMENSION expr? */
6528 }
6529 break; /* Ok if (t == NULL) here. */
6530
6531 case FFEBLD_opITEM:
6532 ffecom_expr_transform_ (ffebld_head (expr));
6533 expr = ffebld_trail (expr);
6534 goto tail_recurse; /* :::::::::::::::::::: */
6535
6536 default:
6537 break;
6538 }
6539
6540 switch (ffebld_arity (expr))
6541 {
6542 case 2:
6543 ffecom_expr_transform_ (ffebld_left (expr));
6544 expr = ffebld_right (expr);
6545 goto tail_recurse; /* :::::::::::::::::::: */
6546
6547 case 1:
6548 expr = ffebld_left (expr);
6549 goto tail_recurse; /* :::::::::::::::::::: */
6550
6551 default:
6552 break;
6553 }
6554
6555 return;
6556}
6557
6558#endif
6559/* Make a type based on info in live f2c.h file. */
6560
6561#if FFECOM_targetCURRENT == FFECOM_targetGCC
6562static void
6563ffecom_f2c_make_type_ (tree *type, int tcode, char *name)
6564{
6565 switch (tcode)
6566 {
6567 case FFECOM_f2ccodeCHAR:
6568 *type = make_signed_type (CHAR_TYPE_SIZE);
6569 break;
6570
6571 case FFECOM_f2ccodeSHORT:
6572 *type = make_signed_type (SHORT_TYPE_SIZE);
6573 break;
6574
6575 case FFECOM_f2ccodeINT:
6576 *type = make_signed_type (INT_TYPE_SIZE);
6577 break;
6578
6579 case FFECOM_f2ccodeLONG:
6580 *type = make_signed_type (LONG_TYPE_SIZE);
6581 break;
6582
6583 case FFECOM_f2ccodeLONGLONG:
6584 *type = make_signed_type (LONG_LONG_TYPE_SIZE);
6585 break;
6586
6587 case FFECOM_f2ccodeCHARPTR:
6588 *type = build_pointer_type (DEFAULT_SIGNED_CHAR
6589 ? signed_char_type_node
6590 : unsigned_char_type_node);
6591 break;
6592
6593 case FFECOM_f2ccodeFLOAT:
6594 *type = make_node (REAL_TYPE);
6595 TYPE_PRECISION (*type) = FLOAT_TYPE_SIZE;
6596 layout_type (*type);
6597 break;
6598
6599 case FFECOM_f2ccodeDOUBLE:
6600 *type = make_node (REAL_TYPE);
6601 TYPE_PRECISION (*type) = DOUBLE_TYPE_SIZE;
6602 layout_type (*type);
6603 break;
6604
6605 case FFECOM_f2ccodeLONGDOUBLE:
6606 *type = make_node (REAL_TYPE);
6607 TYPE_PRECISION (*type) = LONG_DOUBLE_TYPE_SIZE;
6608 layout_type (*type);
6609 break;
6610
6611 case FFECOM_f2ccodeTWOREALS:
6612 *type = ffecom_make_complex_type_ (ffecom_f2c_real_type_node);
6613 break;
6614
6615 case FFECOM_f2ccodeTWODOUBLEREALS:
6616 *type = ffecom_make_complex_type_ (ffecom_f2c_doublereal_type_node);
6617 break;
6618
6619 default:
6620 assert ("unexpected FFECOM_f2ccodeXYZZY!" == NULL);
6621 *type = error_mark_node;
6622 return;
6623 }
6624
6625 pushdecl (build_decl (TYPE_DECL,
6626 ffecom_get_invented_identifier ("__g77_f2c_%s",
6627 name, 0),
6628 *type));
6629}
6630
6631#endif
6632#if FFECOM_targetCURRENT == FFECOM_targetGCC
6633/* Set the f2c list-directed-I/O code for whatever (integral) type has the
6634 given size. */
6635
6636static void
6637ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
6638 int code)
6639{
6640 int j;
6641 tree t;
6642
6643 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
6644 if (((t = ffecom_tree_type[bt][j]) != NULL_TREE)
6645 && (TREE_INT_CST_LOW (TYPE_SIZE (t)) == size))
6646 {
6647 assert (code != -1);
6648 ffecom_f2c_typecode_[bt][j] = code;
6649 code = -1;
6650 }
6651}
6652
6653#endif
6654/* Finish up globals after doing all program units in file
6655
6656 Need to handle only uninitialized COMMON areas. */
6657
6658#if FFECOM_targetCURRENT == FFECOM_targetGCC
6659static ffeglobal
6660ffecom_finish_global_ (ffeglobal global)
6661{
6662 tree cbtype;
6663 tree cbt;
6664 tree size;
6665
6666 if (ffeglobal_type (global) != FFEGLOBAL_typeCOMMON)
6667 return global;
6668
6669 if (ffeglobal_common_init (global))
6670 return global;
6671
6672 cbt = ffeglobal_hook (global);
6673 if ((cbt == NULL_TREE)
6674 || !ffeglobal_common_have_size (global))
6675 return global; /* No need to make common, never ref'd. */
6676
6677 suspend_momentary ();
6678
6679 DECL_EXTERNAL (cbt) = 0;
6680
6681 /* Give the array a size now. */
6682
a6fa6420
CB
6683 size = build_int_2 ((ffeglobal_common_size (global)
6684 + ffeglobal_common_pad (global)) - 1,
6685 0);
5ff904cd
JL
6686
6687 cbtype = TREE_TYPE (cbt);
6688 TYPE_DOMAIN (cbtype) = build_range_type (integer_type_node,
a6fa6420 6689 integer_zero_node,
5ff904cd
JL
6690 size);
6691 if (!TREE_TYPE (size))
6692 TREE_TYPE (size) = TYPE_DOMAIN (cbtype);
6693 layout_type (cbtype);
6694
6695 cbt = start_decl (cbt, FALSE);
6696 assert (cbt == ffeglobal_hook (global));
6697
6698 finish_decl (cbt, NULL_TREE, FALSE);
6699
6700 return global;
6701}
6702
6703#endif
6704/* Finish up any untransformed symbols. */
6705
6706#if FFECOM_targetCURRENT == FFECOM_targetGCC
6707static ffesymbol
6708ffecom_finish_symbol_transform_ (ffesymbol s)
6709{
56a0044b 6710 if ((s == NULL) || (TREE_CODE (current_function_decl) == ERROR_MARK))
5ff904cd
JL
6711 return s;
6712
6713 /* It's easy to know to transform an untransformed symbol, to make sure
6714 we put out debugging info for it. But COMMON variables, unlike
6715 EQUIVALENCE ones, aren't given declarations in addition to the
6716 tree expressions that specify offsets, because COMMON variables
6717 can be referenced in the outer scope where only dummy arguments
6718 (PARM_DECLs) should really be seen. To be safe, just don't do any
6719 VAR_DECLs for COMMON variables when we transform them for real
6720 use, and therefore we do all the VAR_DECL creating here. */
6721
6829256f
CB
6722 if (ffesymbol_hook (s).decl_tree == NULL_TREE)
6723 {
c3092235
CB
6724 if (ffesymbol_kind (s) != FFEINFO_kindNONE
6725 || (ffesymbol_where (s) != FFEINFO_whereNONE
6726 && ffesymbol_where (s) != FFEINFO_whereINTRINSIC
6727 && ffesymbol_where (s) != FFEINFO_whereDUMMY))
6829256f
CB
6728 /* Not transformed, and not CHARACTER*(*), and not a dummy
6729 argument, which can happen only if the entry point names
6730 it "rides in on" are all invalidated for other reasons. */
6731 s = ffecom_sym_transform_ (s);
6732 }
5ff904cd
JL
6733
6734 if ((ffesymbol_where (s) == FFEINFO_whereCOMMON)
6735 && (ffesymbol_hook (s).decl_tree != error_mark_node))
6736 {
6737#ifdef SOMEONE_GETS_DEBUG_SUPPORT_WORKING
6738 int yes = suspend_momentary ();
6739
6740 /* This isn't working, at least for dbxout. The .s file looks
6741 okay to me (burley), but in gdb 4.9 at least, the variables
6742 appear to reside somewhere outside of the common area, so
6743 it doesn't make sense to mislead anyone by generating the info
6744 on those variables until this is fixed. NOTE: Same problem
6745 with EQUIVALENCE, sadly...see similar #if later. */
6746 ffecom_member_phase2_ (ffesymbol_storage (ffesymbol_common (s)),
6747 ffesymbol_storage (s));
6748
6749 resume_momentary (yes);
6750#endif
6751 }
6752
6753 return s;
6754}
6755
6756#endif
6757/* Append underscore(s) to name before calling get_identifier. "us"
6758 is nonzero if the name already contains an underscore and thus
6759 needs two underscores appended. */
6760
6761#if FFECOM_targetCURRENT == FFECOM_targetGCC
6762static tree
6763ffecom_get_appended_identifier_ (char us, char *name)
6764{
6765 int i;
6766 char *newname;
6767 tree id;
6768
6769 newname = xmalloc ((i = strlen (name)) + 1
6770 + ffe_is_underscoring ()
6771 + us);
6772 memcpy (newname, name, i);
6773 newname[i] = '_';
6774 newname[i + us] = '_';
6775 newname[i + 1 + us] = '\0';
6776 id = get_identifier (newname);
6777
6778 free (newname);
6779
6780 return id;
6781}
6782
6783#endif
6784/* Decide whether to append underscore to name before calling
6785 get_identifier. */
6786
6787#if FFECOM_targetCURRENT == FFECOM_targetGCC
6788static tree
6789ffecom_get_external_identifier_ (ffesymbol s)
6790{
6791 char us;
6792 char *name = ffesymbol_text (s);
6793
6794 /* If name is a built-in name, just return it as is. */
6795
6796 if (!ffe_is_underscoring ()
6797 || (strcmp (name, FFETARGET_nameBLANK_COMMON) == 0)
6798#if FFETARGET_isENFORCED_MAIN_NAME
6799 || (strcmp (name, FFETARGET_nameENFORCED_NAME) == 0)
6800#else
6801 || (strcmp (name, FFETARGET_nameUNNAMED_MAIN) == 0)
6802#endif
6803 || (strcmp (name, FFETARGET_nameUNNAMED_BLOCK_DATA) == 0))
6804 return get_identifier (name);
6805
6806 us = ffe_is_second_underscore ()
6807 ? (strchr (name, '_') != NULL)
6808 : 0;
6809
6810 return ffecom_get_appended_identifier_ (us, name);
6811}
6812
6813#endif
6814/* Decide whether to append underscore to internal name before calling
6815 get_identifier.
6816
6817 This is for non-external, top-function-context names only. Transform
6818 identifier so it doesn't conflict with the transformed result
6819 of using a _different_ external name. E.g. if "CALL FOO" is
6820 transformed into "FOO_();", then the variable in "FOO_ = 3"
6821 must be transformed into something that does not conflict, since
6822 these two things should be independent.
6823
6824 The transformation is as follows. If the name does not contain
6825 an underscore, there is no possible conflict, so just return.
6826 If the name does contain an underscore, then transform it just
6827 like we transform an external identifier. */
6828
6829#if FFECOM_targetCURRENT == FFECOM_targetGCC
6830static tree
6831ffecom_get_identifier_ (char *name)
6832{
6833 /* If name does not contain an underscore, just return it as is. */
6834
6835 if (!ffe_is_underscoring ()
6836 || (strchr (name, '_') == NULL))
6837 return get_identifier (name);
6838
6839 return ffecom_get_appended_identifier_ (ffe_is_second_underscore (),
6840 name);
6841}
6842
6843#endif
6844/* ffecom_gen_sfuncdef_ -- Generate definition of statement function
6845
6846 tree t;
6847 ffesymbol s; // kindFUNCTION, whereIMMEDIATE.
6848 t = ffecom_gen_sfuncdef_(s,ffesymbol_basictype(s),
6849 ffesymbol_kindtype(s));
6850
6851 Call after setting up containing function and getting trees for all
6852 other symbols. */
6853
6854#if FFECOM_targetCURRENT == FFECOM_targetGCC
6855static tree
6856ffecom_gen_sfuncdef_ (ffesymbol s, ffeinfoBasictype bt, ffeinfoKindtype kt)
6857{
6858 ffebld expr = ffesymbol_sfexpr (s);
6859 tree type;
6860 tree func;
6861 tree result;
6862 bool charfunc = (bt == FFEINFO_basictypeCHARACTER);
6863 static bool recurse = FALSE;
6864 int yes;
6865 int old_lineno = lineno;
6866 char *old_input_filename = input_filename;
6867
6868 ffecom_nested_entry_ = s;
6869
6870 /* For now, we don't have a handy pointer to where the sfunc is actually
6871 defined, though that should be easy to add to an ffesymbol. (The
6872 token/where info available might well point to the place where the type
6873 of the sfunc is declared, especially if that precedes the place where
6874 the sfunc itself is defined, which is typically the case.) We should
6875 put out a null pointer rather than point somewhere wrong, but I want to
6876 see how it works at this point. */
6877
6878 input_filename = ffesymbol_where_filename (s);
6879 lineno = ffesymbol_where_filelinenum (s);
6880
6881 /* Pretransform the expression so any newly discovered things belong to the
6882 outer program unit, not to the statement function. */
6883
6884 ffecom_expr_transform_ (expr);
6885
6886 /* Make sure no recursive invocation of this fn (a specific case of failing
6887 to pretransform an sfunc's expression, i.e. where its expression
6888 references another untransformed sfunc) happens. */
6889
6890 assert (!recurse);
6891 recurse = TRUE;
6892
6893 yes = suspend_momentary ();
6894
6895 push_f_function_context ();
6896
6897 ffecom_push_calltemps ();
6898
6899 if (charfunc)
6900 type = void_type_node;
6901 else
6902 {
6903 type = ffecom_tree_type[bt][kt];
6904 if (type == NULL_TREE)
6905 type = integer_type_node; /* _sym_exec_transition reports
6906 error. */
6907 }
6908
6909 start_function (ffecom_get_identifier_ (ffesymbol_text (s)),
6910 build_function_type (type, NULL_TREE),
6911 1, /* nested/inline */
6912 0); /* TREE_PUBLIC */
6913
6914 /* We don't worry about COMPLEX return values here, because this is
6915 entirely internal to our code, and gcc has the ability to return COMPLEX
6916 directly as a value. */
6917
6918 yes = suspend_momentary ();
6919
6920 if (charfunc)
6921 { /* Prepend arg for where result goes. */
6922 tree type;
6923
6924 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
6925
6926 result = ffecom_get_invented_identifier ("__g77_%s",
6927 "result", 0);
6928
6929 ffecom_char_enhance_arg_ (&type, s); /* Ignore returned length. */
6930
6931 type = build_pointer_type (type);
6932 result = build_decl (PARM_DECL, result, type);
6933
6934 push_parm_decl (result);
6935 }
6936 else
6937 result = NULL_TREE; /* Not ref'd if !charfunc. */
6938
6939 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (s), TRUE);
6940
6941 resume_momentary (yes);
6942
6943 store_parm_decls (0);
6944
6945 ffecom_start_compstmt_ ();
6946
6947 if (expr != NULL)
6948 {
6949 if (charfunc)
6950 {
6951 ffetargetCharacterSize sz = ffesymbol_size (s);
6952 tree result_length;
6953
6954 result_length = build_int_2 (sz, 0);
6955 TREE_TYPE (result_length) = ffecom_f2c_ftnlen_type_node;
6956
6957 ffecom_let_char_ (result, result_length, sz, expr);
6958 expand_null_return ();
6959 }
6960 else
6961 expand_return (ffecom_modify (NULL_TREE,
6962 DECL_RESULT (current_function_decl),
6963 ffecom_expr (expr)));
6964
6965 clear_momentary ();
6966 }
6967
6968 ffecom_end_compstmt_ ();
6969
6970 func = current_function_decl;
6971 finish_function (1);
6972
6973 ffecom_pop_calltemps ();
6974
6975 pop_f_function_context ();
6976
6977 resume_momentary (yes);
6978
6979 recurse = FALSE;
6980
6981 lineno = old_lineno;
6982 input_filename = old_input_filename;
6983
6984 ffecom_nested_entry_ = NULL;
6985
6986 return func;
6987}
6988
6989#endif
6990
6991#if FFECOM_targetCURRENT == FFECOM_targetGCC
6992static char *
6993ffecom_gfrt_args_ (ffecomGfrt ix)
6994{
6995 return ffecom_gfrt_argstring_[ix];
6996}
6997
6998#endif
6999#if FFECOM_targetCURRENT == FFECOM_targetGCC
7000static tree
7001ffecom_gfrt_tree_ (ffecomGfrt ix)
7002{
7003 if (ffecom_gfrt_[ix] == NULL_TREE)
7004 ffecom_make_gfrt_ (ix);
7005
7006 return ffecom_1 (ADDR_EXPR,
7007 build_pointer_type (TREE_TYPE (ffecom_gfrt_[ix])),
7008 ffecom_gfrt_[ix]);
7009}
7010
7011#endif
7012/* Return initialize-to-zero expression for this VAR_DECL. */
7013
7014#if FFECOM_targetCURRENT == FFECOM_targetGCC
7015static tree
7016ffecom_init_zero_ (tree decl)
7017{
7018 tree init;
7019 int incremental = TREE_STATIC (decl);
7020 tree type = TREE_TYPE (decl);
7021
7022 if (incremental)
7023 {
7024 int momentary = suspend_momentary ();
7025 push_obstacks_nochange ();
7026 if (TREE_PERMANENT (decl))
7027 end_temporary_allocation ();
7028 make_decl_rtl (decl, NULL, TREE_PUBLIC (decl) ? 1 : 0);
7029 assemble_variable (decl, TREE_PUBLIC (decl) ? 1 : 0, 0, 1);
7030 pop_obstacks ();
7031 resume_momentary (momentary);
7032 }
7033
7034 push_momentary ();
7035
7036 if ((TREE_CODE (type) != ARRAY_TYPE)
7037 && (TREE_CODE (type) != RECORD_TYPE)
7038 && (TREE_CODE (type) != UNION_TYPE)
7039 && !incremental)
7040 init = convert (type, integer_zero_node);
7041 else if (!incremental)
7042 {
7043 int momentary = suspend_momentary ();
7044
7045 init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
7046 TREE_CONSTANT (init) = 1;
7047 TREE_STATIC (init) = 1;
7048
7049 resume_momentary (momentary);
7050 }
7051 else
7052 {
7053 int momentary = suspend_momentary ();
7054
7055 assemble_zeros (int_size_in_bytes (type));
7056 init = error_mark_node;
7057
7058 resume_momentary (momentary);
7059 }
7060
7061 pop_momentary_nofree ();
7062
7063 return init;
7064}
7065
7066#endif
7067#if FFECOM_targetCURRENT == FFECOM_targetGCC
7068static tree
7069ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
7070 tree *maybe_tree)
7071{
7072 tree expr_tree;
7073 tree length_tree;
7074
7075 switch (ffebld_op (arg))
7076 {
7077 case FFEBLD_opCONTER: /* For F90, check 0-length. */
7078 if (ffetarget_length_character1
7079 (ffebld_constant_character1
7080 (ffebld_conter (arg))) == 0)
7081 {
7082 *maybe_tree = integer_zero_node;
7083 return convert (tree_type, integer_zero_node);
7084 }
7085
7086 *maybe_tree = integer_one_node;
7087 expr_tree = build_int_2 (*ffetarget_text_character1
7088 (ffebld_constant_character1
7089 (ffebld_conter (arg))),
7090 0);
7091 TREE_TYPE (expr_tree) = tree_type;
7092 return expr_tree;
7093
7094 case FFEBLD_opSYMTER:
7095 case FFEBLD_opARRAYREF:
7096 case FFEBLD_opFUNCREF:
7097 case FFEBLD_opSUBSTR:
7098 ffecom_push_calltemps ();
7099 ffecom_char_args_ (&expr_tree, &length_tree, arg);
7100 ffecom_pop_calltemps ();
7101
7102 if ((expr_tree == error_mark_node)
7103 || (length_tree == error_mark_node))
7104 {
7105 *maybe_tree = error_mark_node;
7106 return error_mark_node;
7107 }
7108
7109 if (integer_zerop (length_tree))
7110 {
7111 *maybe_tree = integer_zero_node;
7112 return convert (tree_type, integer_zero_node);
7113 }
7114
7115 expr_tree
7116 = ffecom_1 (INDIRECT_REF,
7117 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
7118 expr_tree);
7119 expr_tree
7120 = ffecom_2 (ARRAY_REF,
7121 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
7122 expr_tree,
7123 integer_one_node);
7124 expr_tree = convert (tree_type, expr_tree);
7125
7126 if (TREE_CODE (length_tree) == INTEGER_CST)
7127 *maybe_tree = integer_one_node;
7128 else /* Must check length at run time. */
7129 *maybe_tree
7130 = ffecom_truth_value
7131 (ffecom_2 (GT_EXPR, integer_type_node,
7132 length_tree,
7133 ffecom_f2c_ftnlen_zero_node));
7134 return expr_tree;
7135
7136 case FFEBLD_opPAREN:
7137 case FFEBLD_opCONVERT:
7138 if (ffeinfo_size (ffebld_info (arg)) == 0)
7139 {
7140 *maybe_tree = integer_zero_node;
7141 return convert (tree_type, integer_zero_node);
7142 }
7143 return ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
7144 maybe_tree);
7145
7146 case FFEBLD_opCONCATENATE:
7147 {
7148 tree maybe_left;
7149 tree maybe_right;
7150 tree expr_left;
7151 tree expr_right;
7152
7153 expr_left = ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
7154 &maybe_left);
7155 expr_right = ffecom_intrinsic_ichar_ (tree_type, ffebld_right (arg),
7156 &maybe_right);
7157 *maybe_tree = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
7158 maybe_left,
7159 maybe_right);
7160 expr_tree = ffecom_3 (COND_EXPR, tree_type,
7161 maybe_left,
7162 expr_left,
7163 expr_right);
7164 return expr_tree;
7165 }
7166
7167 default:
7168 assert ("bad op in ICHAR" == NULL);
7169 return error_mark_node;
7170 }
7171}
7172
7173#endif
7174/* ffecom_intrinsic_len_ -- Return length info for char arg (LEN())
7175
7176 tree length_arg;
7177 ffebld expr;
7178 length_arg = ffecom_intrinsic_len_ (expr);
7179
7180 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
7181 subexpressions by constructing the appropriate tree for the
7182 length-of-character-text argument in a calling sequence. */
7183
7184#if FFECOM_targetCURRENT == FFECOM_targetGCC
7185static tree
7186ffecom_intrinsic_len_ (ffebld expr)
7187{
7188 ffetargetCharacter1 val;
7189 tree length;
7190
7191 switch (ffebld_op (expr))
7192 {
7193 case FFEBLD_opCONTER:
7194 val = ffebld_constant_character1 (ffebld_conter (expr));
7195 length = build_int_2 (ffetarget_length_character1 (val), 0);
7196 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
7197 break;
7198
7199 case FFEBLD_opSYMTER:
7200 {
7201 ffesymbol s = ffebld_symter (expr);
7202 tree item;
7203
7204 item = ffesymbol_hook (s).decl_tree;
7205 if (item == NULL_TREE)
7206 {
7207 s = ffecom_sym_transform_ (s);
7208 item = ffesymbol_hook (s).decl_tree;
7209 }
7210 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
7211 {
7212 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
7213 length = ffesymbol_hook (s).length_tree;
7214 else
7215 {
7216 length = build_int_2 (ffesymbol_size (s), 0);
7217 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
7218 }
7219 }
7220 else if (item == error_mark_node)
7221 length = error_mark_node;
7222 else /* FFEINFO_kindFUNCTION: */
7223 length = NULL_TREE;
7224 }
7225 break;
7226
7227 case FFEBLD_opARRAYREF:
7228 length = ffecom_intrinsic_len_ (ffebld_left (expr));
7229 break;
7230
7231 case FFEBLD_opSUBSTR:
7232 {
7233 ffebld start;
7234 ffebld end;
7235 ffebld thing = ffebld_right (expr);
7236 tree start_tree;
7237 tree end_tree;
7238
7239 assert (ffebld_op (thing) == FFEBLD_opITEM);
7240 start = ffebld_head (thing);
7241 thing = ffebld_trail (thing);
7242 assert (ffebld_trail (thing) == NULL);
7243 end = ffebld_head (thing);
7244
7245 length = ffecom_intrinsic_len_ (ffebld_left (expr));
7246
7247 if (length == error_mark_node)
7248 break;
7249
7250 if (start == NULL)
7251 {
7252 if (end == NULL)
7253 ;
7254 else
7255 {
7256 length = convert (ffecom_f2c_ftnlen_type_node,
7257 ffecom_expr (end));
7258 }
7259 }
7260 else
7261 {
7262 start_tree = convert (ffecom_f2c_ftnlen_type_node,
7263 ffecom_expr (start));
7264
7265 if (start_tree == error_mark_node)
7266 {
7267 length = error_mark_node;
7268 break;
7269 }
7270
7271 if (end == NULL)
7272 {
7273 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
7274 ffecom_f2c_ftnlen_one_node,
7275 ffecom_2 (MINUS_EXPR,
7276 ffecom_f2c_ftnlen_type_node,
7277 length,
7278 start_tree));
7279 }
7280 else
7281 {
7282 end_tree = convert (ffecom_f2c_ftnlen_type_node,
7283 ffecom_expr (end));
7284
7285 if (end_tree == error_mark_node)
7286 {
7287 length = error_mark_node;
7288 break;
7289 }
7290
7291 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
7292 ffecom_f2c_ftnlen_one_node,
7293 ffecom_2 (MINUS_EXPR,
7294 ffecom_f2c_ftnlen_type_node,
7295 end_tree, start_tree));
7296 }
7297 }
7298 }
7299 break;
7300
7301 case FFEBLD_opCONCATENATE:
7302 length
7303 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
7304 ffecom_intrinsic_len_ (ffebld_left (expr)),
7305 ffecom_intrinsic_len_ (ffebld_right (expr)));
7306 break;
7307
7308 case FFEBLD_opFUNCREF:
7309 case FFEBLD_opCONVERT:
7310 length = build_int_2 (ffebld_size (expr), 0);
7311 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
7312 break;
7313
7314 default:
7315 assert ("bad op for single char arg expr" == NULL);
7316 length = ffecom_f2c_ftnlen_zero_node;
7317 break;
7318 }
7319
7320 assert (length != NULL_TREE);
7321
7322 return length;
7323}
7324
7325#endif
7326/* ffecom_let_char_ -- Do assignment stuff for character type
7327
7328 tree dest_tree; // destination (ADDR_EXPR)
7329 tree dest_length; // length (INT_CST/INDIRECT_REF(PARM_DECL))
7330 ffetargetCharacterSize dest_size; // length
7331 ffebld source; // source expression
7332 ffecom_let_char_(dest_tree,dest_length,dest_size,source);
7333
7334 Generates code to do the assignment. Used by ordinary assignment
7335 statement handler ffecom_let_stmt and by statement-function
7336 handler to generate code for a statement function. */
7337
7338#if FFECOM_targetCURRENT == FFECOM_targetGCC
7339static void
7340ffecom_let_char_ (tree dest_tree, tree dest_length,
7341 ffetargetCharacterSize dest_size, ffebld source)
7342{
7343 ffecomConcatList_ catlist;
7344 tree source_length;
7345 tree source_tree;
7346 tree expr_tree;
7347
7348 if ((dest_tree == error_mark_node)
7349 || (dest_length == error_mark_node))
7350 return;
7351
7352 assert (dest_tree != NULL_TREE);
7353 assert (dest_length != NULL_TREE);
7354
7355 /* Source might be an opCONVERT, which just means it is a different size
7356 than the destination. Since the underlying implementation here handles
7357 that (directly or via the s_copy or s_cat run-time-library functions),
7358 we don't need the "convenience" of an opCONVERT that tells us to
7359 truncate or blank-pad, particularly since the resulting implementation
7360 would probably be slower than otherwise. */
7361
7362 while (ffebld_op (source) == FFEBLD_opCONVERT)
7363 source = ffebld_left (source);
7364
7365 catlist = ffecom_concat_list_new_ (source, dest_size);
7366 switch (ffecom_concat_list_count_ (catlist))
7367 {
7368 case 0: /* Shouldn't happen, but in case it does... */
7369 ffecom_concat_list_kill_ (catlist);
7370 source_tree = null_pointer_node;
7371 source_length = ffecom_f2c_ftnlen_zero_node;
7372 expr_tree = build_tree_list (NULL_TREE, dest_tree);
7373 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
7374 TREE_CHAIN (TREE_CHAIN (expr_tree))
7375 = build_tree_list (NULL_TREE, dest_length);
7376 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
7377 = build_tree_list (NULL_TREE, source_length);
7378
7379 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree);
7380 TREE_SIDE_EFFECTS (expr_tree) = 1;
7381
7382 expand_expr_stmt (expr_tree);
7383
7384 return;
7385
7386 case 1: /* The (fairly) easy case. */
7387 ffecom_char_args_ (&source_tree, &source_length,
7388 ffecom_concat_list_expr_ (catlist, 0));
7389 ffecom_concat_list_kill_ (catlist);
7390 assert (source_tree != NULL_TREE);
7391 assert (source_length != NULL_TREE);
7392
7393 if ((source_tree == error_mark_node)
7394 || (source_length == error_mark_node))
7395 return;
7396
7397 if (dest_size == 1)
7398 {
7399 dest_tree
7400 = ffecom_1 (INDIRECT_REF,
7401 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
7402 (dest_tree))),
7403 dest_tree);
7404 dest_tree
7405 = ffecom_2 (ARRAY_REF,
7406 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
7407 (dest_tree))),
7408 dest_tree,
7409 integer_one_node);
7410 source_tree
7411 = ffecom_1 (INDIRECT_REF,
7412 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
7413 (source_tree))),
7414 source_tree);
7415 source_tree
7416 = ffecom_2 (ARRAY_REF,
7417 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
7418 (source_tree))),
7419 source_tree,
7420 integer_one_node);
7421
7422 expr_tree = ffecom_modify (void_type_node, dest_tree, source_tree);
7423
7424 expand_expr_stmt (expr_tree);
7425
7426 return;
7427 }
7428
7429 expr_tree = build_tree_list (NULL_TREE, dest_tree);
7430 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
7431 TREE_CHAIN (TREE_CHAIN (expr_tree))
7432 = build_tree_list (NULL_TREE, dest_length);
7433 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
7434 = build_tree_list (NULL_TREE, source_length);
7435
7436 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree);
7437 TREE_SIDE_EFFECTS (expr_tree) = 1;
7438
7439 expand_expr_stmt (expr_tree);
7440
7441 return;
7442
7443 default: /* Must actually concatenate things. */
7444 break;
7445 }
7446
7447 /* Heavy-duty concatenation. */
7448
7449 {
7450 int count = ffecom_concat_list_count_ (catlist);
7451 int i;
7452 tree lengths;
7453 tree items;
7454 tree length_array;
7455 tree item_array;
7456 tree citem;
7457 tree clength;
7458
7459 length_array
7460 = lengths
7461 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
7462 FFETARGET_charactersizeNONE, count, TRUE);
7463 item_array = items = ffecom_push_tempvar (ffecom_f2c_address_type_node,
7464 FFETARGET_charactersizeNONE,
7465 count, TRUE);
7466
7467 for (i = 0; i < count; ++i)
7468 {
7469 ffecom_char_args_ (&citem, &clength,
7470 ffecom_concat_list_expr_ (catlist, i));
7471 if ((citem == error_mark_node)
7472 || (clength == error_mark_node))
7473 {
7474 ffecom_concat_list_kill_ (catlist);
7475 return;
7476 }
7477
7478 items
7479 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
7480 ffecom_modify (void_type_node,
7481 ffecom_2 (ARRAY_REF,
7482 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
7483 item_array,
7484 build_int_2 (i, 0)),
7485 citem),
7486 items);
7487 lengths
7488 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
7489 ffecom_modify (void_type_node,
7490 ffecom_2 (ARRAY_REF,
7491 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
7492 length_array,
7493 build_int_2 (i, 0)),
7494 clength),
7495 lengths);
7496 }
7497
7498 expr_tree = build_tree_list (NULL_TREE, dest_tree);
7499 TREE_CHAIN (expr_tree)
7500 = build_tree_list (NULL_TREE,
7501 ffecom_1 (ADDR_EXPR,
7502 build_pointer_type (TREE_TYPE (items)),
7503 items));
7504 TREE_CHAIN (TREE_CHAIN (expr_tree))
7505 = build_tree_list (NULL_TREE,
7506 ffecom_1 (ADDR_EXPR,
7507 build_pointer_type (TREE_TYPE (lengths)),
7508 lengths));
7509 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
7510 = build_tree_list
7511 (NULL_TREE,
7512 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
7513 convert (ffecom_f2c_ftnlen_type_node,
7514 build_int_2 (count, 0))));
7515 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree))))
7516 = build_tree_list (NULL_TREE, dest_length);
7517
7518 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCAT, expr_tree);
7519 TREE_SIDE_EFFECTS (expr_tree) = 1;
7520
7521 expand_expr_stmt (expr_tree);
7522 }
7523
7524 ffecom_concat_list_kill_ (catlist);
7525}
7526
7527#endif
7528/* ffecom_make_gfrt_ -- Make initial info for run-time routine
7529
7530 ffecomGfrt ix;
7531 ffecom_make_gfrt_(ix);
7532
7533 Assumes gfrt_[ix] is NULL_TREE, and replaces it with the FUNCTION_DECL
7534 for the indicated run-time routine (ix). */
7535
7536#if FFECOM_targetCURRENT == FFECOM_targetGCC
7537static void
7538ffecom_make_gfrt_ (ffecomGfrt ix)
7539{
7540 tree t;
7541 tree ttype;
7542
7543 push_obstacks_nochange ();
7544 end_temporary_allocation ();
7545
7546 switch (ffecom_gfrt_type_[ix])
7547 {
7548 case FFECOM_rttypeVOID_:
7549 ttype = void_type_node;
7550 break;
7551
6d433196
CB
7552 case FFECOM_rttypeVOIDSTAR_:
7553 ttype = TREE_TYPE (null_pointer_node); /* `void *'. */
7554 break;
7555
795232f7
JL
7556 case FFECOM_rttypeFTNINT_:
7557 ttype = ffecom_f2c_ftnint_type_node;
5ff904cd
JL
7558 break;
7559
7560 case FFECOM_rttypeINTEGER_:
7561 ttype = ffecom_f2c_integer_type_node;
7562 break;
7563
7564 case FFECOM_rttypeLONGINT_:
7565 ttype = ffecom_f2c_longint_type_node;
7566 break;
7567
7568 case FFECOM_rttypeLOGICAL_:
7569 ttype = ffecom_f2c_logical_type_node;
7570 break;
7571
7572 case FFECOM_rttypeREAL_F2C_:
795232f7 7573 ttype = double_type_node;
5ff904cd
JL
7574 break;
7575
7576 case FFECOM_rttypeREAL_GNU_:
795232f7 7577 ttype = float_type_node;
5ff904cd
JL
7578 break;
7579
7580 case FFECOM_rttypeCOMPLEX_F2C_:
7581 ttype = void_type_node;
7582 break;
7583
7584 case FFECOM_rttypeCOMPLEX_GNU_:
7585 ttype = ffecom_f2c_complex_type_node;
7586 break;
7587
7588 case FFECOM_rttypeDOUBLE_:
7589 ttype = double_type_node;
7590 break;
7591
795232f7
JL
7592 case FFECOM_rttypeDOUBLEREAL_:
7593 ttype = ffecom_f2c_doublereal_type_node;
7594 break;
7595
5ff904cd
JL
7596 case FFECOM_rttypeDBLCMPLX_F2C_:
7597 ttype = void_type_node;
7598 break;
7599
7600 case FFECOM_rttypeDBLCMPLX_GNU_:
7601 ttype = ffecom_f2c_doublecomplex_type_node;
7602 break;
7603
7604 case FFECOM_rttypeCHARACTER_:
7605 ttype = void_type_node;
7606 break;
7607
7608 default:
7609 ttype = NULL;
7610 assert ("bad rttype" == NULL);
7611 break;
7612 }
7613
7614 ttype = build_function_type (ttype, NULL_TREE);
7615 t = build_decl (FUNCTION_DECL,
7616 get_identifier (ffecom_gfrt_name_[ix]),
7617 ttype);
7618 DECL_EXTERNAL (t) = 1;
7619 TREE_PUBLIC (t) = 1;
7620 TREE_THIS_VOLATILE (t) = ffecom_gfrt_volatile_[ix] ? 1 : 0;
7621
7622 t = start_decl (t, TRUE);
7623
7624 finish_decl (t, NULL_TREE, TRUE);
7625
7626 resume_temporary_allocation ();
7627 pop_obstacks ();
7628
7629 ffecom_gfrt_[ix] = t;
7630}
7631
7632#endif
7633/* Phase 1 pass over each member of a COMMON/EQUIVALENCE group. */
7634
7635#if FFECOM_targetCURRENT == FFECOM_targetGCC
7636static void
7637ffecom_member_phase1_ (ffestorag mst UNUSED, ffestorag st)
7638{
7639 ffesymbol s = ffestorag_symbol (st);
7640
7641 if (ffesymbol_namelisted (s))
7642 ffecom_member_namelisted_ = TRUE;
7643}
7644
7645#endif
7646/* Phase 2 pass over each member of a COMMON/EQUIVALENCE group. Declare
7647 the member so debugger will see it. Otherwise nobody should be
7648 referencing the member. */
7649
7650#if FFECOM_targetCURRENT == FFECOM_targetGCC
7651#ifdef SOMEONE_GETS_DEBUG_SUPPORT_WORKING
7652static void
7653ffecom_member_phase2_ (ffestorag mst, ffestorag st)
7654{
7655 ffesymbol s;
7656 tree t;
7657 tree mt;
7658 tree type;
7659
7660 if ((mst == NULL)
7661 || ((mt = ffestorag_hook (mst)) == NULL)
7662 || (mt == error_mark_node))
7663 return;
7664
7665 if ((st == NULL)
7666 || ((s = ffestorag_symbol (st)) == NULL))
7667 return;
7668
7669 type = ffecom_type_localvar_ (s,
7670 ffesymbol_basictype (s),
7671 ffesymbol_kindtype (s));
7672 if (type == error_mark_node)
7673 return;
7674
7675 t = build_decl (VAR_DECL,
7676 ffecom_get_identifier_ (ffesymbol_text (s)),
7677 type);
7678
7679 TREE_STATIC (t) = TREE_STATIC (mt);
7680 DECL_INITIAL (t) = NULL_TREE;
7681 TREE_ASM_WRITTEN (t) = 1;
7682
7683 DECL_RTL (t)
7684 = gen_rtx (MEM, TYPE_MODE (type),
7685 plus_constant (XEXP (DECL_RTL (mt), 0),
7686 ffestorag_modulo (mst)
7687 + ffestorag_offset (st)
7688 - ffestorag_offset (mst)));
7689
7690 t = start_decl (t, FALSE);
7691
7692 finish_decl (t, NULL_TREE, FALSE);
7693}
7694
7695#endif
7696#endif
7697/* ffecom_push_dummy_decls_ -- Transform dummy args, push parm decls in order
7698
7699 Ignores STAR (alternate-return) dummies. All other get exec-transitioned
7700 (which generates their trees) and then their trees get push_parm_decl'd.
7701
7702 The second arg is TRUE if the dummies are for a statement function, in
7703 which case lengths are not pushed for character arguments (since they are
7704 always known by both the caller and the callee, though the code allows
7705 for someday permitting CHAR*(*) stmtfunc dummies). */
7706
7707#if FFECOM_targetCURRENT == FFECOM_targetGCC
7708static void
7709ffecom_push_dummy_decls_ (ffebld dummy_list, bool stmtfunc)
7710{
7711 ffebld dummy;
7712 ffebld dumlist;
7713 ffesymbol s;
7714 tree parm;
7715
7716 ffecom_transform_only_dummies_ = TRUE;
7717
7718 /* First push the parms corresponding to actual dummy "contents". */
7719
7720 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7721 {
7722 dummy = ffebld_head (dumlist);
7723 switch (ffebld_op (dummy))
7724 {
7725 case FFEBLD_opSTAR:
7726 case FFEBLD_opANY:
7727 continue; /* Forget alternate returns. */
7728
7729 default:
7730 break;
7731 }
7732 assert (ffebld_op (dummy) == FFEBLD_opSYMTER);
7733 s = ffebld_symter (dummy);
7734 parm = ffesymbol_hook (s).decl_tree;
7735 if (parm == NULL_TREE)
7736 {
7737 s = ffecom_sym_transform_ (s);
7738 parm = ffesymbol_hook (s).decl_tree;
7739 assert (parm != NULL_TREE);
7740 }
7741 if (parm != error_mark_node)
7742 push_parm_decl (parm);
7743 }
7744
7745 /* Then, for CHARACTER dummies, push the parms giving their lengths. */
7746
7747 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7748 {
7749 dummy = ffebld_head (dumlist);
7750 switch (ffebld_op (dummy))
7751 {
7752 case FFEBLD_opSTAR:
7753 case FFEBLD_opANY:
7754 continue; /* Forget alternate returns, they mean
7755 NOTHING! */
7756
7757 default:
7758 break;
7759 }
7760 s = ffebld_symter (dummy);
7761 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
7762 continue; /* Only looking for CHARACTER arguments. */
7763 if (stmtfunc && (ffesymbol_size (s) != FFETARGET_charactersizeNONE))
7764 continue; /* Stmtfunc arg with known size needs no
7765 length param. */
7766 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
7767 continue; /* Only looking for variables and arrays. */
7768 parm = ffesymbol_hook (s).length_tree;
7769 assert (parm != NULL_TREE);
7770 if (parm != error_mark_node)
7771 push_parm_decl (parm);
7772 }
7773
7774 ffecom_transform_only_dummies_ = FALSE;
7775}
7776
7777#endif
7778/* ffecom_start_progunit_ -- Beginning of program unit
7779
7780 Does GNU back end stuff necessary to teach it about the start of its
7781 equivalent of a Fortran program unit. */
7782
7783#if FFECOM_targetCURRENT == FFECOM_targetGCC
7784static void
7785ffecom_start_progunit_ ()
7786{
7787 ffesymbol fn = ffecom_primary_entry_;
7788 ffebld arglist;
7789 tree id; /* Identifier (name) of function. */
7790 tree type; /* Type of function. */
7791 tree result; /* Result of function. */
7792 ffeinfoBasictype bt;
7793 ffeinfoKindtype kt;
7794 ffeglobal g;
7795 ffeglobalType gt;
7796 ffeglobalType egt = FFEGLOBAL_type;
7797 bool charfunc;
7798 bool cmplxfunc;
7799 bool altentries = (ffecom_num_entrypoints_ != 0);
7800 bool multi
7801 = altentries
7802 && (ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
7803 && (ffecom_master_bt_ == FFEINFO_basictypeNONE);
7804 bool main_program = FALSE;
7805 int old_lineno = lineno;
7806 char *old_input_filename = input_filename;
7807 int yes;
7808
7809 assert (fn != NULL);
7810 assert (ffesymbol_hook (fn).decl_tree == NULL_TREE);
7811
7812 input_filename = ffesymbol_where_filename (fn);
7813 lineno = ffesymbol_where_filelinenum (fn);
7814
7815 /* c-parse.y indeed does call suspend_momentary and not only ignores the
7816 return value, but also never calls resume_momentary, when starting an
7817 outer function (see "fndef:", "setspecs:", and so on). So g77 does the
7818 same thing. It shouldn't be a problem since start_function calls
7819 temporary_allocation, but it might be necessary. If it causes a problem
7820 here, then maybe there's a bug lurking in gcc. NOTE: This identical
7821 comment appears twice in thist file. */
7822
7823 suspend_momentary ();
7824
7825 switch (ffecom_primary_entry_kind_)
7826 {
7827 case FFEINFO_kindPROGRAM:
7828 main_program = TRUE;
7829 gt = FFEGLOBAL_typeMAIN;
7830 bt = FFEINFO_basictypeNONE;
7831 kt = FFEINFO_kindtypeNONE;
7832 type = ffecom_tree_fun_type_void;
7833 charfunc = FALSE;
7834 cmplxfunc = FALSE;
7835 break;
7836
7837 case FFEINFO_kindBLOCKDATA:
7838 gt = FFEGLOBAL_typeBDATA;
7839 bt = FFEINFO_basictypeNONE;
7840 kt = FFEINFO_kindtypeNONE;
7841 type = ffecom_tree_fun_type_void;
7842 charfunc = FALSE;
7843 cmplxfunc = FALSE;
7844 break;
7845
7846 case FFEINFO_kindFUNCTION:
7847 gt = FFEGLOBAL_typeFUNC;
7848 egt = FFEGLOBAL_typeEXT;
7849 bt = ffesymbol_basictype (fn);
7850 kt = ffesymbol_kindtype (fn);
7851 if (bt == FFEINFO_basictypeNONE)
7852 {
7853 ffeimplic_establish_symbol (fn);
7854 if (ffesymbol_funcresult (fn) != NULL)
7855 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
7856 bt = ffesymbol_basictype (fn);
7857 kt = ffesymbol_kindtype (fn);
7858 }
7859
7860 if (multi)
7861 charfunc = cmplxfunc = FALSE;
7862 else if (bt == FFEINFO_basictypeCHARACTER)
7863 charfunc = TRUE, cmplxfunc = FALSE;
7864 else if ((bt == FFEINFO_basictypeCOMPLEX)
7865 && ffesymbol_is_f2c (fn)
7866 && !altentries)
7867 charfunc = FALSE, cmplxfunc = TRUE;
7868 else
7869 charfunc = cmplxfunc = FALSE;
7870
7871 if (multi || charfunc)
7872 type = ffecom_tree_fun_type_void;
7873 else if (ffesymbol_is_f2c (fn) && !altentries)
7874 type = ffecom_tree_fun_type[bt][kt];
7875 else
7876 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
7877
7878 if ((type == NULL_TREE)
7879 || (TREE_TYPE (type) == NULL_TREE))
7880 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
7881 break;
7882
7883 case FFEINFO_kindSUBROUTINE:
7884 gt = FFEGLOBAL_typeSUBR;
7885 egt = FFEGLOBAL_typeEXT;
7886 bt = FFEINFO_basictypeNONE;
7887 kt = FFEINFO_kindtypeNONE;
7888 if (ffecom_is_altreturning_)
7889 type = ffecom_tree_subr_type;
7890 else
7891 type = ffecom_tree_fun_type_void;
7892 charfunc = FALSE;
7893 cmplxfunc = FALSE;
7894 break;
7895
7896 default:
7897 assert ("say what??" == NULL);
7898 /* Fall through. */
7899 case FFEINFO_kindANY:
7900 gt = FFEGLOBAL_typeANY;
7901 bt = FFEINFO_basictypeNONE;
7902 kt = FFEINFO_kindtypeNONE;
7903 type = error_mark_node;
7904 charfunc = FALSE;
7905 cmplxfunc = FALSE;
7906 break;
7907 }
7908
7909 if (altentries)
44d2eabc
JL
7910 {
7911 id = ffecom_get_invented_identifier ("__g77_masterfun_%s",
7912 ffesymbol_text (fn),
7913 0);
44d2eabc 7914 }
5ff904cd
JL
7915#if FFETARGET_isENFORCED_MAIN
7916 else if (main_program)
7917 id = get_identifier (FFETARGET_nameENFORCED_MAIN_NAME);
7918#endif
7919 else
7920 id = ffecom_get_external_identifier_ (fn);
7921
7922 start_function (id,
7923 type,
7924 0, /* nested/inline */
7925 !altentries); /* TREE_PUBLIC */
7926
3cf0cea4
CB
7927 TREE_USED (current_function_decl) = 1; /* Avoid spurious warning if altentries. */
7928
5ff904cd
JL
7929 if (!altentries
7930 && ((g = ffesymbol_global (fn)) != NULL)
7931 && ((ffeglobal_type (g) == gt)
7932 || (ffeglobal_type (g) == egt)))
7933 {
7934 ffeglobal_set_hook (g, current_function_decl);
7935 }
7936
7937 yes = suspend_momentary ();
7938
7939 /* Arg handling needs exec-transitioned ffesymbols to work with. But
7940 exec-transitioning needs current_function_decl to be filled in. So we
7941 do these things in two phases. */
7942
7943 if (altentries)
7944 { /* 1st arg identifies which entrypoint. */
7945 ffecom_which_entrypoint_decl_
7946 = build_decl (PARM_DECL,
7947 ffecom_get_invented_identifier ("__g77_%s",
7948 "which_entrypoint",
7949 0),
7950 integer_type_node);
7951 push_parm_decl (ffecom_which_entrypoint_decl_);
7952 }
7953
7954 if (charfunc
7955 || cmplxfunc
7956 || multi)
7957 { /* Arg for result (return value). */
7958 tree type;
7959 tree length;
7960
7961 if (charfunc)
7962 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
7963 else if (cmplxfunc)
7964 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
7965 else
7966 type = ffecom_multi_type_node_;
7967
7968 result = ffecom_get_invented_identifier ("__g77_%s",
7969 "result", 0);
7970
7971 /* Make length arg _and_ enhance type info for CHAR arg itself. */
7972
7973 if (charfunc)
7974 length = ffecom_char_enhance_arg_ (&type, fn);
7975 else
7976 length = NULL_TREE; /* Not ref'd if !charfunc. */
7977
7978 type = build_pointer_type (type);
7979 result = build_decl (PARM_DECL, result, type);
7980
7981 push_parm_decl (result);
7982 if (multi)
7983 ffecom_multi_retval_ = result;
7984 else
7985 ffecom_func_result_ = result;
7986
7987 if (charfunc)
7988 {
7989 push_parm_decl (length);
7990 ffecom_func_length_ = length;
7991 }
7992 }
7993
7994 if (ffecom_primary_entry_is_proc_)
7995 {
7996 if (altentries)
7997 arglist = ffecom_master_arglist_;
7998 else
7999 arglist = ffesymbol_dummyargs (fn);
8000 ffecom_push_dummy_decls_ (arglist, FALSE);
8001 }
8002
8003 resume_momentary (yes);
8004
56a0044b
JL
8005 if (TREE_CODE (current_function_decl) != ERROR_MARK)
8006 store_parm_decls (main_program ? 1 : 0);
5ff904cd
JL
8007
8008 ffecom_start_compstmt_ ();
8009
8010 lineno = old_lineno;
8011 input_filename = old_input_filename;
8012
8013 /* This handles any symbols still untransformed, in case -g specified.
8014 This used to be done in ffecom_finish_progunit, but it turns out to
8015 be necessary to do it here so that statement functions are
8016 expanded before code. But don't bother for BLOCK DATA. */
8017
8018 if (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
8019 ffesymbol_drive (ffecom_finish_symbol_transform_);
8020}
8021
8022#endif
8023/* ffecom_sym_transform_ -- Transform FFE sym into backend sym
8024
8025 ffesymbol s;
8026 ffecom_sym_transform_(s);
8027
8028 The ffesymbol_hook info for s is updated with appropriate backend info
8029 on the symbol. */
8030
8031#if FFECOM_targetCURRENT == FFECOM_targetGCC
8032static ffesymbol
8033ffecom_sym_transform_ (ffesymbol s)
8034{
8035 tree t; /* Transformed thingy. */
8036 tree tlen; /* Length if CHAR*(*). */
8037 bool addr; /* Is t the address of the thingy? */
8038 ffeinfoBasictype bt;
8039 ffeinfoKindtype kt;
8040 ffeglobal g;
8041 int yes;
8042 int old_lineno = lineno;
8043 char *old_input_filename = input_filename;
8044
8045 if (ffesymbol_sfdummyparent (s) == NULL)
8046 {
8047 input_filename = ffesymbol_where_filename (s);
8048 lineno = ffesymbol_where_filelinenum (s);
8049 }
8050 else
8051 {
8052 ffesymbol sf = ffesymbol_sfdummyparent (s);
8053
8054 input_filename = ffesymbol_where_filename (sf);
8055 lineno = ffesymbol_where_filelinenum (sf);
8056 }
8057
8058 bt = ffeinfo_basictype (ffebld_info (s));
8059 kt = ffeinfo_kindtype (ffebld_info (s));
8060
8061 t = NULL_TREE;
8062 tlen = NULL_TREE;
8063 addr = FALSE;
8064
8065 switch (ffesymbol_kind (s))
8066 {
8067 case FFEINFO_kindNONE:
8068 switch (ffesymbol_where (s))
8069 {
8070 case FFEINFO_whereDUMMY: /* Subroutine or function. */
8071 assert (ffecom_transform_only_dummies_);
8072
8073 /* Before 0.4, this could be ENTITY/DUMMY, but see
8074 ffestu_sym_end_transition -- no longer true (in particular, if
8075 it could be an ENTITY, it _will_ be made one, so that
8076 possibility won't come through here). So we never make length
8077 arg for CHARACTER type. */
8078
8079 t = build_decl (PARM_DECL,
8080 ffecom_get_identifier_ (ffesymbol_text (s)),
8081 ffecom_tree_ptr_to_subr_type);
8082#if BUILT_FOR_270
8083 DECL_ARTIFICIAL (t) = 1;
8084#endif
8085 addr = TRUE;
8086 break;
8087
8088 case FFEINFO_whereGLOBAL: /* Subroutine or function. */
8089 assert (!ffecom_transform_only_dummies_);
8090
8091 if (((g = ffesymbol_global (s)) != NULL)
8092 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8093 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8094 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8095 && (ffeglobal_hook (g) != NULL_TREE)
8096 && ffe_is_globals ())
8097 {
8098 t = ffeglobal_hook (g);
8099 break;
8100 }
8101
8102 push_obstacks_nochange ();
8103 end_temporary_allocation ();
8104
8105 t = build_decl (FUNCTION_DECL,
8106 ffecom_get_external_identifier_ (s),
8107 ffecom_tree_subr_type); /* Assume subr. */
8108 DECL_EXTERNAL (t) = 1;
8109 TREE_PUBLIC (t) = 1;
8110
8111 t = start_decl (t, FALSE);
8112 finish_decl (t, NULL_TREE, FALSE);
8113
8114 if ((g != NULL)
8115 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8116 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8117 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8118 ffeglobal_set_hook (g, t);
8119
8120 resume_temporary_allocation ();
8121 pop_obstacks ();
8122
8123 break;
8124
8125 default:
8126 assert ("NONE where unexpected" == NULL);
8127 /* Fall through. */
8128 case FFEINFO_whereANY:
8129 break;
8130 }
8131 break;
8132
8133 case FFEINFO_kindENTITY:
8134 switch (ffeinfo_where (ffesymbol_info (s)))
8135 {
8136
8137 case FFEINFO_whereCONSTANT: /* ~~debugging info needed? */
8138 assert (!ffecom_transform_only_dummies_);
8139 t = error_mark_node; /* Shouldn't ever see this in expr. */
8140 break;
8141
8142 case FFEINFO_whereLOCAL:
8143 assert (!ffecom_transform_only_dummies_);
8144
8145 {
8146 ffestorag st = ffesymbol_storage (s);
8147 tree type;
8148
8149 if ((st != NULL)
8150 && (ffestorag_size (st) == 0))
8151 {
8152 t = error_mark_node;
8153 break;
8154 }
8155
8156 yes = suspend_momentary ();
8157 type = ffecom_type_localvar_ (s, bt, kt);
8158 resume_momentary (yes);
8159
8160 if (type == error_mark_node)
8161 {
8162 t = error_mark_node;
8163 break;
8164 }
8165
8166 if ((st != NULL)
8167 && (ffestorag_parent (st) != NULL))
8168 { /* Child of EQUIVALENCE parent. */
8169 ffestorag est;
8170 tree et;
8171 int yes;
8172 ffetargetOffset offset;
8173
8174 est = ffestorag_parent (st);
8175 ffecom_transform_equiv_ (est);
8176
8177 et = ffestorag_hook (est);
8178 assert (et != NULL_TREE);
8179
8180 if (! TREE_STATIC (et))
8181 put_var_into_stack (et);
8182
8183 yes = suspend_momentary ();
8184
8185 offset = ffestorag_modulo (est)
8186 + ffestorag_offset (ffesymbol_storage (s))
8187 - ffestorag_offset (est);
8188
8189 ffecom_debug_kludge_ (et, "EQUIVALENCE", s, type, offset);
8190
8191 /* (t_type *) (((char *) &et) + offset) */
8192
8193 t = convert (string_type_node, /* (char *) */
8194 ffecom_1 (ADDR_EXPR,
8195 build_pointer_type (TREE_TYPE (et)),
8196 et));
8197 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
8198 t,
8199 build_int_2 (offset, 0));
8200 t = convert (build_pointer_type (type),
8201 t);
8202
8203 addr = TRUE;
8204
8205 resume_momentary (yes);
8206 }
8207 else
8208 {
8209 tree initexpr;
8210 bool init = ffesymbol_is_init (s);
8211
8212 yes = suspend_momentary ();
8213
8214 t = build_decl (VAR_DECL,
8215 ffecom_get_identifier_ (ffesymbol_text (s)),
8216 type);
8217
8218 if (init
8219 || ffesymbol_namelisted (s)
8220#ifdef FFECOM_sizeMAXSTACKITEM
8221 || ((st != NULL)
8222 && (ffestorag_size (st) > FFECOM_sizeMAXSTACKITEM))
8223#endif
8224 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8225 && (ffecom_primary_entry_kind_
8226 != FFEINFO_kindBLOCKDATA)
8227 && (ffesymbol_is_save (s) || ffe_is_saveall ())))
8228 TREE_STATIC (t) = !ffesymbol_attr (s, FFESYMBOL_attrADJUSTABLE);
8229 else
8230 TREE_STATIC (t) = 0; /* No need to make static. */
8231
8232 if (init || ffe_is_init_local_zero ())
8233 DECL_INITIAL (t) = error_mark_node;
8234
8235 /* Keep -Wunused from complaining about var if it
8236 is used as sfunc arg or DATA implied-DO. */
8237 if (ffesymbol_attrs (s) & FFESYMBOL_attrsSFARG)
8238 DECL_IN_SYSTEM_HEADER (t) = 1;
8239
8240 t = start_decl (t, FALSE);
8241
8242 if (init)
8243 {
8244 if (ffesymbol_init (s) != NULL)
8245 initexpr = ffecom_expr (ffesymbol_init (s));
8246 else
8247 initexpr = ffecom_init_zero_ (t);
8248 }
8249 else if (ffe_is_init_local_zero ())
8250 initexpr = ffecom_init_zero_ (t);
8251 else
8252 initexpr = NULL_TREE; /* Not ref'd if !init. */
8253
8254 finish_decl (t, initexpr, FALSE);
8255
8256 if ((st != NULL) && (DECL_SIZE (t) != error_mark_node))
8257 {
8258 tree size_tree;
8259
8260 size_tree = size_binop (CEIL_DIV_EXPR,
8261 DECL_SIZE (t),
8262 size_int (BITS_PER_UNIT));
8263 assert (TREE_INT_CST_HIGH (size_tree) == 0);
8264 assert (TREE_INT_CST_LOW (size_tree) == ffestorag_size (st));
8265 }
8266
8267 resume_momentary (yes);
8268 }
8269 }
8270 break;
8271
8272 case FFEINFO_whereRESULT:
8273 assert (!ffecom_transform_only_dummies_);
8274
8275 if (bt == FFEINFO_basictypeCHARACTER)
8276 { /* Result is already in list of dummies, use
8277 it (& length). */
8278 t = ffecom_func_result_;
8279 tlen = ffecom_func_length_;
8280 addr = TRUE;
8281 break;
8282 }
8283 if ((ffecom_num_entrypoints_ == 0)
8284 && (bt == FFEINFO_basictypeCOMPLEX)
8285 && (ffesymbol_is_f2c (ffecom_primary_entry_)))
8286 { /* Result is already in list of dummies, use
8287 it. */
8288 t = ffecom_func_result_;
8289 addr = TRUE;
8290 break;
8291 }
8292 if (ffecom_func_result_ != NULL_TREE)
8293 {
8294 t = ffecom_func_result_;
8295 break;
8296 }
8297 if ((ffecom_num_entrypoints_ != 0)
8298 && (ffecom_master_bt_ == FFEINFO_basictypeNONE))
8299 {
8300 yes = suspend_momentary ();
8301
8302 assert (ffecom_multi_retval_ != NULL_TREE);
8303 t = ffecom_1 (INDIRECT_REF, ffecom_multi_type_node_,
8304 ffecom_multi_retval_);
8305 t = ffecom_2 (COMPONENT_REF, ffecom_tree_type[bt][kt],
8306 t, ffecom_multi_fields_[bt][kt]);
8307
8308 resume_momentary (yes);
8309 break;
8310 }
8311
8312 yes = suspend_momentary ();
8313
8314 t = build_decl (VAR_DECL,
8315 ffecom_get_identifier_ (ffesymbol_text (s)),
8316 ffecom_tree_type[bt][kt]);
8317 TREE_STATIC (t) = 0; /* Put result on stack. */
8318 t = start_decl (t, FALSE);
8319 finish_decl (t, NULL_TREE, FALSE);
8320
8321 ffecom_func_result_ = t;
8322
8323 resume_momentary (yes);
8324 break;
8325
8326 case FFEINFO_whereDUMMY:
8327 {
8328 tree type;
8329 ffebld dl;
8330 ffebld dim;
8331 tree low;
8332 tree high;
8333 tree old_sizes;
8334 bool adjustable = FALSE; /* Conditionally adjustable? */
8335
8336 type = ffecom_tree_type[bt][kt];
8337 if (ffesymbol_sfdummyparent (s) != NULL)
8338 {
8339 if (current_function_decl == ffecom_outer_function_decl_)
8340 { /* Exec transition before sfunc
8341 context; get it later. */
8342 break;
8343 }
8344 t = ffecom_get_identifier_ (ffesymbol_text
8345 (ffesymbol_sfdummyparent (s)));
8346 }
8347 else
8348 t = ffecom_get_identifier_ (ffesymbol_text (s));
8349
8350 assert (ffecom_transform_only_dummies_);
8351
8352 old_sizes = get_pending_sizes ();
8353 put_pending_sizes (old_sizes);
8354
8355 if (bt == FFEINFO_basictypeCHARACTER)
8356 tlen = ffecom_char_enhance_arg_ (&type, s);
8357 type = ffecom_check_size_overflow_ (s, type, TRUE);
8358
8359 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
8360 {
8361 if (type == error_mark_node)
8362 break;
8363
8364 dim = ffebld_head (dl);
8365 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
8366 if ((ffebld_left (dim) == NULL) || ffecom_doing_entry_)
8367 low = ffecom_integer_one_node;
8368 else
8369 low = ffecom_expr (ffebld_left (dim));
8370 assert (ffebld_right (dim) != NULL);
8371 if ((ffebld_op (ffebld_right (dim)) == FFEBLD_opSTAR)
8372 || ffecom_doing_entry_)
8342981f
RH
8373 {
8374 /* Used to just do high=low. But for ffecom_tree_
8375 canonize_ref_, it probably is important to correctly
8376 assess the size. E.g. given COMPLEX C(*),CFUNC and
8377 C(2)=CFUNC(C), overlap can happen, while it can't
8378 for, say, C(1)=CFUNC(C(2)). */
8379 /* Even more recently used to set to INT_MAX, but that
8380 broke when some overflow checking went into the back
8381 end. Now we just leave the upper bound unspecified. */
8382 high = NULL;
8383 }
5ff904cd
JL
8384 else
8385 high = ffecom_expr (ffebld_right (dim));
8386
8387 /* Determine whether array is conditionally adjustable,
8388 to decide whether back-end magic is needed.
8389
8390 Normally the front end uses the back-end function
8391 variable_size to wrap SAVE_EXPR's around expressions
8392 affecting the size/shape of an array so that the
8393 size/shape info doesn't change during execution
8394 of the compiled code even though variables and
8395 functions referenced in those expressions might.
8396
8397 variable_size also makes sure those saved expressions
8398 get evaluated immediately upon entry to the
8399 compiled procedure -- the front end normally doesn't
8400 have to worry about that.
8401
8402 However, there is a problem with this that affects
8403 g77's implementation of entry points, and that is
8404 that it is _not_ true that each invocation of the
8405 compiled procedure is permitted to evaluate
8406 array size/shape info -- because it is possible
8407 that, for some invocations, that info is invalid (in
8408 which case it is "promised" -- i.e. a violation of
8409 the Fortran standard -- that the compiled code
8410 won't reference the array or its size/shape
8411 during that particular invocation).
8412
8413 To phrase this in C terms, consider this gcc function:
8414
8415 void foo (int *n, float (*a)[*n])
8416 {
8417 // a is "pointer to array ...", fyi.
8418 }
8419
8420 Suppose that, for some invocations, it is permitted
8421 for a caller of foo to do this:
8422
8423 foo (NULL, NULL);
8424
8425 Now the _written_ code for foo can take such a call
8426 into account by either testing explicitly for whether
8427 (a == NULL) || (n == NULL) -- presumably it is
8428 not permitted to reference *a in various fashions
8429 if (n == NULL) I suppose -- or it can avoid it by
8430 looking at other info (other arguments, static/global
8431 data, etc.).
8432
8433 However, this won't work in gcc 2.5.8 because it'll
8434 automatically emit the code to save the "*n"
8435 expression, which'll yield a NULL dereference for
8436 the "foo (NULL, NULL)" call, something the code
8437 for foo cannot prevent.
8438
8439 g77 definitely needs to avoid executing such
8440 code anytime the pointer to the adjustable array
8441 is NULL, because even if its bounds expressions
8442 don't have any references to possible "absent"
8443 variables like "*n" -- say all variable references
8444 are to COMMON variables, i.e. global (though in C,
8445 local static could actually make sense) -- the
8446 expressions could yield other run-time problems
8447 for allowably "dead" values in those variables.
8448
8449 For example, let's consider a more complicated
8450 version of foo:
8451
8452 extern int i;
8453 extern int j;
8454
8455 void foo (float (*a)[i/j])
8456 {
8457 ...
8458 }
8459
8460 The above is (essentially) quite valid for Fortran
8461 but, again, for a call like "foo (NULL);", it is
8462 permitted for i and j to be undefined when the
8463 call is made. If j happened to be zero, for
8464 example, emitting the code to evaluate "i/j"
8465 could result in a run-time error.
8466
8467 Offhand, though I don't have my F77 or F90
8468 standards handy, it might even be valid for a
8469 bounds expression to contain a function reference,
8470 in which case I doubt it is permitted for an
8471 implementation to invoke that function in the
8472 Fortran case involved here (invocation of an
8473 alternate ENTRY point that doesn't have the adjustable
8474 array as one of its arguments).
8475
8476 So, the code that the compiler would normally emit
8477 to preevaluate the size/shape info for an
8478 adjustable array _must not_ be executed at run time
8479 in certain cases. Specifically, for Fortran,
8480 the case is when the pointer to the adjustable
8481 array == NULL. (For gnu-ish C, it might be nice
8482 for the source code itself to specify an expression
8483 that, if TRUE, inhibits execution of the code. Or
8484 reverse the sense for elegance.)
8485
8486 (Note that g77 could use a different test than NULL,
8487 actually, since it happens to always pass an
8488 integer to the called function that specifies which
8489 entry point is being invoked. Hmm, this might
8490 solve the next problem.)
8491
8492 One way a user could, I suppose, write "foo" so
8493 it works is to insert COND_EXPR's for the
8494 size/shape info so the dangerous stuff isn't
8495 actually done, as in:
8496
8497 void foo (int *n, float (*a)[(a == NULL) ? 0 : *n])
8498 {
8499 ...
8500 }
8501
8502 The next problem is that the front end needs to
8503 be able to tell the back end about the array's
8504 decl _before_ it tells it about the conditional
8505 expression to inhibit evaluation of size/shape info,
8506 as shown above.
8507
8508 To solve this, the front end needs to be able
8509 to give the back end the expression to inhibit
8510 generation of the preevaluation code _after_
8511 it makes the decl for the adjustable array.
8512
8513 Until then, the above example using the COND_EXPR
8514 doesn't pass muster with gcc because the "(a == NULL)"
8515 part has a reference to "a", which is still
8516 undefined at that point.
8517
8518 g77 will therefore use a different mechanism in the
8519 meantime. */
8520
8521 if (!adjustable
8522 && ((TREE_CODE (low) != INTEGER_CST)
8342981f 8523 || (high && TREE_CODE (high) != INTEGER_CST)))
5ff904cd
JL
8524 adjustable = TRUE;
8525
8526#if 0 /* Old approach -- see below. */
8527 if (TREE_CODE (low) != INTEGER_CST)
8528 low = ffecom_3 (COND_EXPR, integer_type_node,
8529 ffecom_adjarray_passed_ (s),
8530 low,
8531 ffecom_integer_zero_node);
8532
8342981f 8533 if (high && TREE_CODE (high) != INTEGER_CST)
5ff904cd
JL
8534 high = ffecom_3 (COND_EXPR, integer_type_node,
8535 ffecom_adjarray_passed_ (s),
8536 high,
8537 ffecom_integer_zero_node);
8538#endif
8539
8540 /* ~~~gcc/stor-layout.c/layout_type should do this,
8541 probably. Fixes 950302-1.f. */
8542
8543 if (TREE_CODE (low) != INTEGER_CST)
8544 low = variable_size (low);
8545
8546 /* ~~~similarly, this fixes dumb0.f. The C front end
8547 does this, which is why dumb0.c would work. */
8548
8342981f 8549 if (high && TREE_CODE (high) != INTEGER_CST)
5ff904cd
JL
8550 high = variable_size (high);
8551
8552 type
8553 = build_array_type
8554 (type,
8555 build_range_type (ffecom_integer_type_node,
8556 low, high));
8557 type = ffecom_check_size_overflow_ (s, type, TRUE);
8558 }
8559
8560 if (type == error_mark_node)
8561 {
8562 t = error_mark_node;
8563 break;
8564 }
8565
8566 if ((ffesymbol_sfdummyparent (s) == NULL)
8567 || (ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER))
8568 {
8569 type = build_pointer_type (type);
8570 addr = TRUE;
8571 }
8572
8573 t = build_decl (PARM_DECL, t, type);
8574#if BUILT_FOR_270
8575 DECL_ARTIFICIAL (t) = 1;
8576#endif
8577
8578 /* If this arg is present in every entry point's list of
8579 dummy args, then we're done. */
8580
8581 if (ffesymbol_numentries (s)
8582 == (ffecom_num_entrypoints_ + 1))
8583 break;
8584
8585#if 1
8586
8587 /* If variable_size in stor-layout has been called during
8588 the above, then get_pending_sizes should have the
8589 yet-to-be-evaluated saved expressions pending.
8590 Make the whole lot of them get emitted, conditionally
8591 on whether the array decl ("t" above) is not NULL. */
8592
8593 {
8594 tree sizes = get_pending_sizes ();
8595 tree tem;
8596
8597 for (tem = sizes;
8598 tem != old_sizes;
8599 tem = TREE_CHAIN (tem))
8600 {
8601 tree temv = TREE_VALUE (tem);
8602
8603 if (sizes == tem)
8604 sizes = temv;
8605 else
8606 sizes
8607 = ffecom_2 (COMPOUND_EXPR,
8608 TREE_TYPE (sizes),
8609 temv,
8610 sizes);
8611 }
8612
8613 if (sizes != tem)
8614 {
8615 sizes
8616 = ffecom_3 (COND_EXPR,
8617 TREE_TYPE (sizes),
8618 ffecom_2 (NE_EXPR,
8619 integer_type_node,
8620 t,
8621 null_pointer_node),
8622 sizes,
8623 convert (TREE_TYPE (sizes),
8624 integer_zero_node));
8625 sizes = ffecom_save_tree (sizes);
8626
8627 sizes
8628 = tree_cons (NULL_TREE, sizes, tem);
8629 }
8630
8631 if (sizes)
8632 put_pending_sizes (sizes);
8633 }
8634
8635#else
8636#if 0
8637 if (adjustable
8638 && (ffesymbol_numentries (s)
8639 != ffecom_num_entrypoints_ + 1))
8640 DECL_SOMETHING (t)
8641 = ffecom_2 (NE_EXPR, integer_type_node,
8642 t,
8643 null_pointer_node);
8644#else
8645#if 0
8646 if (adjustable
8647 && (ffesymbol_numentries (s)
8648 != ffecom_num_entrypoints_ + 1))
8649 {
8650 ffebad_start (FFEBAD_MISSING_ADJARRAY_UNSUPPORTED);
8651 ffebad_here (0, ffesymbol_where_line (s),
8652 ffesymbol_where_column (s));
8653 ffebad_string (ffesymbol_text (s));
8654 ffebad_finish ();
8655 }
8656#endif
8657#endif
8658#endif
8659 }
8660 break;
8661
8662 case FFEINFO_whereCOMMON:
8663 {
8664 ffesymbol cs;
8665 ffeglobal cg;
8666 tree ct;
8667 ffestorag st = ffesymbol_storage (s);
8668 tree type;
8669 int yes;
8670
8671 cs = ffesymbol_common (s); /* The COMMON area itself. */
8672 if (st != NULL) /* Else not laid out. */
8673 {
8674 ffecom_transform_common_ (cs);
8675 st = ffesymbol_storage (s);
8676 }
8677
8678 yes = suspend_momentary ();
8679
8680 type = ffecom_type_localvar_ (s, bt, kt);
8681
8682 cg = ffesymbol_global (cs); /* The global COMMON info. */
8683 if ((cg == NULL)
8684 || (ffeglobal_type (cg) != FFEGLOBAL_typeCOMMON))
8685 ct = NULL_TREE;
8686 else
8687 ct = ffeglobal_hook (cg); /* The common area's tree. */
8688
8689 if ((ct == NULL_TREE)
8690 || (st == NULL)
8691 || (type == error_mark_node))
8692 t = error_mark_node;
8693 else
8694 {
8695 ffetargetOffset offset;
8696 ffestorag cst;
8697
8698 cst = ffestorag_parent (st);
8699 assert (cst == ffesymbol_storage (cs));
8700
8701 offset = ffestorag_modulo (cst)
8702 + ffestorag_offset (st)
8703 - ffestorag_offset (cst);
8704
8705 ffecom_debug_kludge_ (ct, "COMMON", s, type, offset);
8706
8707 /* (t_type *) (((char *) &ct) + offset) */
8708
8709 t = convert (string_type_node, /* (char *) */
8710 ffecom_1 (ADDR_EXPR,
8711 build_pointer_type (TREE_TYPE (ct)),
8712 ct));
8713 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
8714 t,
8715 build_int_2 (offset, 0));
8716 t = convert (build_pointer_type (type),
8717 t);
8718
8719 addr = TRUE;
8720 }
8721
8722 resume_momentary (yes);
8723 }
8724 break;
8725
8726 case FFEINFO_whereIMMEDIATE:
8727 case FFEINFO_whereGLOBAL:
8728 case FFEINFO_whereFLEETING:
8729 case FFEINFO_whereFLEETING_CADDR:
8730 case FFEINFO_whereFLEETING_IADDR:
8731 case FFEINFO_whereINTRINSIC:
8732 case FFEINFO_whereCONSTANT_SUBOBJECT:
8733 default:
8734 assert ("ENTITY where unheard of" == NULL);
8735 /* Fall through. */
8736 case FFEINFO_whereANY:
8737 t = error_mark_node;
8738 break;
8739 }
8740 break;
8741
8742 case FFEINFO_kindFUNCTION:
8743 switch (ffeinfo_where (ffesymbol_info (s)))
8744 {
8745 case FFEINFO_whereLOCAL: /* Me. */
8746 assert (!ffecom_transform_only_dummies_);
8747 t = current_function_decl;
8748 break;
8749
8750 case FFEINFO_whereGLOBAL:
8751 assert (!ffecom_transform_only_dummies_);
8752
8753 if (((g = ffesymbol_global (s)) != NULL)
8754 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8755 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8756 && (ffeglobal_hook (g) != NULL_TREE)
8757 && ffe_is_globals ())
8758 {
8759 t = ffeglobal_hook (g);
8760 break;
8761 }
8762
8763 push_obstacks_nochange ();
8764 end_temporary_allocation ();
8765
8766 if (ffesymbol_is_f2c (s)
8767 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8768 t = ffecom_tree_fun_type[bt][kt];
8769 else
8770 t = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
8771
8772 t = build_decl (FUNCTION_DECL,
8773 ffecom_get_external_identifier_ (s),
8774 t);
8775 DECL_EXTERNAL (t) = 1;
8776 TREE_PUBLIC (t) = 1;
8777
8778 t = start_decl (t, FALSE);
8779 finish_decl (t, NULL_TREE, FALSE);
8780
8781 if ((g != NULL)
8782 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8783 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8784 ffeglobal_set_hook (g, t);
8785
8786 resume_temporary_allocation ();
8787 pop_obstacks ();
8788
8789 break;
8790
8791 case FFEINFO_whereDUMMY:
8792 assert (ffecom_transform_only_dummies_);
8793
8794 if (ffesymbol_is_f2c (s)
8795 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8796 t = ffecom_tree_ptr_to_fun_type[bt][kt];
8797 else
8798 t = build_pointer_type
8799 (build_function_type (ffecom_tree_type[bt][kt], NULL_TREE));
8800
8801 t = build_decl (PARM_DECL,
8802 ffecom_get_identifier_ (ffesymbol_text (s)),
8803 t);
8804#if BUILT_FOR_270
8805 DECL_ARTIFICIAL (t) = 1;
8806#endif
8807 addr = TRUE;
8808 break;
8809
8810 case FFEINFO_whereCONSTANT: /* Statement function. */
8811 assert (!ffecom_transform_only_dummies_);
8812 t = ffecom_gen_sfuncdef_ (s, bt, kt);
8813 break;
8814
8815 case FFEINFO_whereINTRINSIC:
8816 assert (!ffecom_transform_only_dummies_);
8817 break; /* Let actual references generate their
8818 decls. */
8819
8820 default:
8821 assert ("FUNCTION where unheard of" == NULL);
8822 /* Fall through. */
8823 case FFEINFO_whereANY:
8824 t = error_mark_node;
8825 break;
8826 }
8827 break;
8828
8829 case FFEINFO_kindSUBROUTINE:
8830 switch (ffeinfo_where (ffesymbol_info (s)))
8831 {
8832 case FFEINFO_whereLOCAL: /* Me. */
8833 assert (!ffecom_transform_only_dummies_);
8834 t = current_function_decl;
8835 break;
8836
8837 case FFEINFO_whereGLOBAL:
8838 assert (!ffecom_transform_only_dummies_);
8839
8840 if (((g = ffesymbol_global (s)) != NULL)
8841 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8842 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8843 && (ffeglobal_hook (g) != NULL_TREE)
8844 && ffe_is_globals ())
8845 {
8846 t = ffeglobal_hook (g);
8847 break;
8848 }
8849
8850 push_obstacks_nochange ();
8851 end_temporary_allocation ();
8852
8853 t = build_decl (FUNCTION_DECL,
8854 ffecom_get_external_identifier_ (s),
8855 ffecom_tree_subr_type);
8856 DECL_EXTERNAL (t) = 1;
8857 TREE_PUBLIC (t) = 1;
8858
8859 t = start_decl (t, FALSE);
8860 finish_decl (t, NULL_TREE, FALSE);
8861
8862 if ((g != NULL)
8863 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8864 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8865 ffeglobal_set_hook (g, t);
8866
8867 resume_temporary_allocation ();
8868 pop_obstacks ();
8869
8870 break;
8871
8872 case FFEINFO_whereDUMMY:
8873 assert (ffecom_transform_only_dummies_);
8874
8875 t = build_decl (PARM_DECL,
8876 ffecom_get_identifier_ (ffesymbol_text (s)),
8877 ffecom_tree_ptr_to_subr_type);
8878#if BUILT_FOR_270
8879 DECL_ARTIFICIAL (t) = 1;
8880#endif
8881 addr = TRUE;
8882 break;
8883
8884 case FFEINFO_whereINTRINSIC:
8885 assert (!ffecom_transform_only_dummies_);
8886 break; /* Let actual references generate their
8887 decls. */
8888
8889 default:
8890 assert ("SUBROUTINE where unheard of" == NULL);
8891 /* Fall through. */
8892 case FFEINFO_whereANY:
8893 t = error_mark_node;
8894 break;
8895 }
8896 break;
8897
8898 case FFEINFO_kindPROGRAM:
8899 switch (ffeinfo_where (ffesymbol_info (s)))
8900 {
8901 case FFEINFO_whereLOCAL: /* Me. */
8902 assert (!ffecom_transform_only_dummies_);
8903 t = current_function_decl;
8904 break;
8905
8906 case FFEINFO_whereCOMMON:
8907 case FFEINFO_whereDUMMY:
8908 case FFEINFO_whereGLOBAL:
8909 case FFEINFO_whereRESULT:
8910 case FFEINFO_whereFLEETING:
8911 case FFEINFO_whereFLEETING_CADDR:
8912 case FFEINFO_whereFLEETING_IADDR:
8913 case FFEINFO_whereIMMEDIATE:
8914 case FFEINFO_whereINTRINSIC:
8915 case FFEINFO_whereCONSTANT:
8916 case FFEINFO_whereCONSTANT_SUBOBJECT:
8917 default:
8918 assert ("PROGRAM where unheard of" == NULL);
8919 /* Fall through. */
8920 case FFEINFO_whereANY:
8921 t = error_mark_node;
8922 break;
8923 }
8924 break;
8925
8926 case FFEINFO_kindBLOCKDATA:
8927 switch (ffeinfo_where (ffesymbol_info (s)))
8928 {
8929 case FFEINFO_whereLOCAL: /* Me. */
8930 assert (!ffecom_transform_only_dummies_);
8931 t = current_function_decl;
8932 break;
8933
8934 case FFEINFO_whereGLOBAL:
8935 assert (!ffecom_transform_only_dummies_);
8936
8937 push_obstacks_nochange ();
8938 end_temporary_allocation ();
8939
8940 t = build_decl (FUNCTION_DECL,
8941 ffecom_get_external_identifier_ (s),
8942 ffecom_tree_blockdata_type);
8943 DECL_EXTERNAL (t) = 1;
8944 TREE_PUBLIC (t) = 1;
8945
8946 t = start_decl (t, FALSE);
8947 finish_decl (t, NULL_TREE, FALSE);
8948
8949 resume_temporary_allocation ();
8950 pop_obstacks ();
8951
8952 break;
8953
8954 case FFEINFO_whereCOMMON:
8955 case FFEINFO_whereDUMMY:
8956 case FFEINFO_whereRESULT:
8957 case FFEINFO_whereFLEETING:
8958 case FFEINFO_whereFLEETING_CADDR:
8959 case FFEINFO_whereFLEETING_IADDR:
8960 case FFEINFO_whereIMMEDIATE:
8961 case FFEINFO_whereINTRINSIC:
8962 case FFEINFO_whereCONSTANT:
8963 case FFEINFO_whereCONSTANT_SUBOBJECT:
8964 default:
8965 assert ("BLOCKDATA where unheard of" == NULL);
8966 /* Fall through. */
8967 case FFEINFO_whereANY:
8968 t = error_mark_node;
8969 break;
8970 }
8971 break;
8972
8973 case FFEINFO_kindCOMMON:
8974 switch (ffeinfo_where (ffesymbol_info (s)))
8975 {
8976 case FFEINFO_whereLOCAL:
8977 assert (!ffecom_transform_only_dummies_);
8978 ffecom_transform_common_ (s);
8979 break;
8980
8981 case FFEINFO_whereNONE:
8982 case FFEINFO_whereCOMMON:
8983 case FFEINFO_whereDUMMY:
8984 case FFEINFO_whereGLOBAL:
8985 case FFEINFO_whereRESULT:
8986 case FFEINFO_whereFLEETING:
8987 case FFEINFO_whereFLEETING_CADDR:
8988 case FFEINFO_whereFLEETING_IADDR:
8989 case FFEINFO_whereIMMEDIATE:
8990 case FFEINFO_whereINTRINSIC:
8991 case FFEINFO_whereCONSTANT:
8992 case FFEINFO_whereCONSTANT_SUBOBJECT:
8993 default:
8994 assert ("COMMON where unheard of" == NULL);
8995 /* Fall through. */
8996 case FFEINFO_whereANY:
8997 t = error_mark_node;
8998 break;
8999 }
9000 break;
9001
9002 case FFEINFO_kindCONSTRUCT:
9003 switch (ffeinfo_where (ffesymbol_info (s)))
9004 {
9005 case FFEINFO_whereLOCAL:
9006 assert (!ffecom_transform_only_dummies_);
9007 break;
9008
9009 case FFEINFO_whereNONE:
9010 case FFEINFO_whereCOMMON:
9011 case FFEINFO_whereDUMMY:
9012 case FFEINFO_whereGLOBAL:
9013 case FFEINFO_whereRESULT:
9014 case FFEINFO_whereFLEETING:
9015 case FFEINFO_whereFLEETING_CADDR:
9016 case FFEINFO_whereFLEETING_IADDR:
9017 case FFEINFO_whereIMMEDIATE:
9018 case FFEINFO_whereINTRINSIC:
9019 case FFEINFO_whereCONSTANT:
9020 case FFEINFO_whereCONSTANT_SUBOBJECT:
9021 default:
9022 assert ("CONSTRUCT where unheard of" == NULL);
9023 /* Fall through. */
9024 case FFEINFO_whereANY:
9025 t = error_mark_node;
9026 break;
9027 }
9028 break;
9029
9030 case FFEINFO_kindNAMELIST:
9031 switch (ffeinfo_where (ffesymbol_info (s)))
9032 {
9033 case FFEINFO_whereLOCAL:
9034 assert (!ffecom_transform_only_dummies_);
9035 t = ffecom_transform_namelist_ (s);
9036 break;
9037
9038 case FFEINFO_whereNONE:
9039 case FFEINFO_whereCOMMON:
9040 case FFEINFO_whereDUMMY:
9041 case FFEINFO_whereGLOBAL:
9042 case FFEINFO_whereRESULT:
9043 case FFEINFO_whereFLEETING:
9044 case FFEINFO_whereFLEETING_CADDR:
9045 case FFEINFO_whereFLEETING_IADDR:
9046 case FFEINFO_whereIMMEDIATE:
9047 case FFEINFO_whereINTRINSIC:
9048 case FFEINFO_whereCONSTANT:
9049 case FFEINFO_whereCONSTANT_SUBOBJECT:
9050 default:
9051 assert ("NAMELIST where unheard of" == NULL);
9052 /* Fall through. */
9053 case FFEINFO_whereANY:
9054 t = error_mark_node;
9055 break;
9056 }
9057 break;
9058
9059 default:
9060 assert ("kind unheard of" == NULL);
9061 /* Fall through. */
9062 case FFEINFO_kindANY:
9063 t = error_mark_node;
9064 break;
9065 }
9066
9067 ffesymbol_hook (s).decl_tree = t;
9068 ffesymbol_hook (s).length_tree = tlen;
9069 ffesymbol_hook (s).addr = addr;
9070
9071 lineno = old_lineno;
9072 input_filename = old_input_filename;
9073
9074 return s;
9075}
9076
9077#endif
9078/* Transform into ASSIGNable symbol.
9079
9080 Symbol has already been transformed, but for whatever reason, the
9081 resulting decl_tree has been deemed not usable for an ASSIGN target.
9082 (E.g. it isn't wide enough to hold a pointer.) So, here we invent
9083 another local symbol of type void * and stuff that in the assign_tree
9084 argument. The F77/F90 standards allow this implementation. */
9085
9086#if FFECOM_targetCURRENT == FFECOM_targetGCC
9087static ffesymbol
9088ffecom_sym_transform_assign_ (ffesymbol s)
9089{
9090 tree t; /* Transformed thingy. */
9091 int yes;
9092 int old_lineno = lineno;
9093 char *old_input_filename = input_filename;
9094
9095 if (ffesymbol_sfdummyparent (s) == NULL)
9096 {
9097 input_filename = ffesymbol_where_filename (s);
9098 lineno = ffesymbol_where_filelinenum (s);
9099 }
9100 else
9101 {
9102 ffesymbol sf = ffesymbol_sfdummyparent (s);
9103
9104 input_filename = ffesymbol_where_filename (sf);
9105 lineno = ffesymbol_where_filelinenum (sf);
9106 }
9107
9108 assert (!ffecom_transform_only_dummies_);
9109
9110 yes = suspend_momentary ();
9111
9112 t = build_decl (VAR_DECL,
9113 ffecom_get_invented_identifier ("__g77_ASSIGN_%s",
9114 ffesymbol_text (s),
9115 0),
9116 TREE_TYPE (null_pointer_node));
9117
9118 switch (ffesymbol_where (s))
9119 {
9120 case FFEINFO_whereLOCAL:
9121 /* Unlike for regular vars, SAVE status is easy to determine for
9122 ASSIGNed vars, since there's no initialization, there's no
9123 effective storage association (so "SAVE J" does not apply to
9124 K even given "EQUIVALENCE (J,K)"), there's no size issue
9125 to worry about, etc. */
9126 if ((ffesymbol_is_save (s) || ffe_is_saveall ())
9127 && (ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
9128 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA))
9129 TREE_STATIC (t) = 1; /* SAVEd in proc, make static. */
9130 else
9131 TREE_STATIC (t) = 0; /* No need to make static. */
9132 break;
9133
9134 case FFEINFO_whereCOMMON:
9135 TREE_STATIC (t) = 1; /* Assume COMMONs always SAVEd. */
9136 break;
9137
9138 case FFEINFO_whereDUMMY:
9139 /* Note that twinning a DUMMY means the caller won't see
9140 the ASSIGNed value. But both F77 and F90 allow implementations
9141 to do this, i.e. disallow Fortran code that would try and
9142 take advantage of actually putting a label into a variable
9143 via a dummy argument (or any other storage association, for
9144 that matter). */
9145 TREE_STATIC (t) = 0;
9146 break;
9147
9148 default:
9149 TREE_STATIC (t) = 0;
9150 break;
9151 }
9152
9153 t = start_decl (t, FALSE);
9154 finish_decl (t, NULL_TREE, FALSE);
9155
9156 resume_momentary (yes);
9157
9158 ffesymbol_hook (s).assign_tree = t;
9159
9160 lineno = old_lineno;
9161 input_filename = old_input_filename;
9162
9163 return s;
9164}
9165
9166#endif
9167/* Implement COMMON area in back end.
9168
9169 Because COMMON-based variables can be referenced in the dimension
9170 expressions of dummy (adjustable) arrays, and because dummies
9171 (in the gcc back end) need to be put in the outer binding level
9172 of a function (which has two binding levels, the outer holding
9173 the dummies and the inner holding the other vars), special care
9174 must be taken to handle COMMON areas.
9175
9176 The current strategy is basically to always tell the back end about
9177 the COMMON area as a top-level external reference to just a block
9178 of storage of the master type of that area (e.g. integer, real,
9179 character, whatever -- not a structure). As a distinct action,
9180 if initial values are provided, tell the back end about the area
9181 as a top-level non-external (initialized) area and remember not to
9182 allow further initialization or expansion of the area. Meanwhile,
9183 if no initialization happens at all, tell the back end about
9184 the largest size we've seen declared so the space does get reserved.
9185 (This function doesn't handle all that stuff, but it does some
9186 of the important things.)
9187
9188 Meanwhile, for COMMON variables themselves, just keep creating
9189 references like *((float *) (&common_area + offset)) each time
9190 we reference the variable. In other words, don't make a VAR_DECL
9191 or any kind of component reference (like we used to do before 0.4),
9192 though we might do that as well just for debugging purposes (and
9193 stuff the rtl with the appropriate offset expression). */
9194
9195#if FFECOM_targetCURRENT == FFECOM_targetGCC
9196static void
9197ffecom_transform_common_ (ffesymbol s)
9198{
9199 ffestorag st = ffesymbol_storage (s);
9200 ffeglobal g = ffesymbol_global (s);
9201 tree cbt;
9202 tree cbtype;
9203 tree init;
a6fa6420 9204 tree high;
5ff904cd
JL
9205 bool is_init = ffestorag_is_init (st);
9206
9207 assert (st != NULL);
9208
9209 if ((g == NULL)
9210 || (ffeglobal_type (g) != FFEGLOBAL_typeCOMMON))
9211 return;
9212
9213 /* First update the size of the area in global terms. */
9214
9215 ffeglobal_size_common (s, ffestorag_size (st));
9216
9217 if (!ffeglobal_common_init (g))
9218 is_init = FALSE; /* No explicit init, don't let erroneous joins init. */
9219
9220 cbt = ffeglobal_hook (g);
9221
9222 /* If we already have declared this common block for a previous program
9223 unit, and either we already initialized it or we don't have new
9224 initialization for it, just return what we have without changing it. */
9225
9226 if ((cbt != NULL_TREE)
9227 && (!is_init
9228 || !DECL_EXTERNAL (cbt)))
9229 return;
9230
9231 /* Process inits. */
9232
9233 if (is_init)
9234 {
9235 if (ffestorag_init (st) != NULL)
9236 {
a6fa6420
CB
9237 ffebld sexp;
9238
9239 /* Set the padding for the expression, so ffecom_expr
9240 knows to insert that many zeros. */
9241 switch (ffebld_op (sexp = ffestorag_init (st)))
9242 {
9243 case FFEBLD_opCONTER:
9244 ffebld_conter_set_pad (sexp, ffestorag_modulo (st));
9245 break;
9246
9247 case FFEBLD_opARRTER:
9248 ffebld_arrter_set_pad (sexp, ffestorag_modulo (st));
9249 break;
9250
9251 case FFEBLD_opACCTER:
9252 ffebld_accter_set_pad (sexp, ffestorag_modulo (st));
9253 break;
9254
9255 default:
9256 assert ("bad op for cmn init (pad)" == NULL);
9257 break;
9258 }
9259
9260 init = ffecom_expr (sexp);
5ff904cd
JL
9261 if (init == error_mark_node)
9262 { /* Hopefully the back end complained! */
9263 init = NULL_TREE;
9264 if (cbt != NULL_TREE)
9265 return;
9266 }
9267 }
9268 else
9269 init = error_mark_node;
9270 }
9271 else
9272 init = NULL_TREE;
9273
9274 push_obstacks_nochange ();
9275 end_temporary_allocation ();
9276
9277 /* cbtype must be permanently allocated! */
9278
a6fa6420
CB
9279 /* Allocate the MAX of the areas so far, seen filewide. */
9280 high = build_int_2 ((ffeglobal_common_size (g)
9281 + ffeglobal_common_pad (g)) - 1, 0);
9282 TREE_TYPE (high) = ffecom_integer_type_node;
9283
5ff904cd
JL
9284 if (init)
9285 cbtype = build_array_type (char_type_node,
9286 build_range_type (integer_type_node,
a6fa6420
CB
9287 integer_zero_node,
9288 high));
5ff904cd
JL
9289 else
9290 cbtype = build_array_type (char_type_node, NULL_TREE);
9291
9292 if (cbt == NULL_TREE)
9293 {
9294 cbt
9295 = build_decl (VAR_DECL,
9296 ffecom_get_external_identifier_ (s),
9297 cbtype);
9298 TREE_STATIC (cbt) = 1;
9299 TREE_PUBLIC (cbt) = 1;
9300 }
9301 else
9302 {
9303 assert (is_init);
9304 TREE_TYPE (cbt) = cbtype;
9305 }
9306 DECL_EXTERNAL (cbt) = init ? 0 : 1;
9307 DECL_INITIAL (cbt) = init ? error_mark_node : NULL_TREE;
9308
9309 cbt = start_decl (cbt, TRUE);
9310 if (ffeglobal_hook (g) != NULL)
9311 assert (cbt == ffeglobal_hook (g));
9312
9313 assert (!init || !DECL_EXTERNAL (cbt));
9314
9315 /* Make sure that any type can live in COMMON and be referenced
9316 without getting a bus error. We could pick the most restrictive
9317 alignment of all entities actually placed in the COMMON, but
9318 this seems easy enough. */
9319
9320 DECL_ALIGN (cbt) = BIGGEST_ALIGNMENT;
9321
9322 if (is_init && (ffestorag_init (st) == NULL))
9323 init = ffecom_init_zero_ (cbt);
9324
9325 finish_decl (cbt, init, TRUE);
9326
9327 if (is_init)
9328 ffestorag_set_init (st, ffebld_new_any ());
9329
9330 if (init)
9331 {
9332 tree size_tree;
9333
9334 assert (DECL_SIZE (cbt) != NULL_TREE);
9335 assert (TREE_CODE (DECL_SIZE (cbt)) == INTEGER_CST);
9336 size_tree = size_binop (CEIL_DIV_EXPR,
9337 DECL_SIZE (cbt),
9338 size_int (BITS_PER_UNIT));
9339 assert (TREE_INT_CST_HIGH (size_tree) == 0);
a6fa6420
CB
9340 assert (TREE_INT_CST_LOW (size_tree)
9341 == ffeglobal_common_size (g) + ffeglobal_common_pad (g));
5ff904cd
JL
9342 }
9343
9344 ffeglobal_set_hook (g, cbt);
9345
9346 ffestorag_set_hook (st, cbt);
9347
9348 resume_temporary_allocation ();
9349 pop_obstacks ();
9350}
9351
9352#endif
9353/* Make master area for local EQUIVALENCE. */
9354
9355#if FFECOM_targetCURRENT == FFECOM_targetGCC
9356static void
9357ffecom_transform_equiv_ (ffestorag eqst)
9358{
9359 tree eqt;
9360 tree eqtype;
9361 tree init;
9362 tree high;
9363 bool is_init = ffestorag_is_init (eqst);
9364 int yes;
9365
9366 assert (eqst != NULL);
9367
9368 eqt = ffestorag_hook (eqst);
9369
9370 if (eqt != NULL_TREE)
9371 return;
9372
9373 /* Process inits. */
9374
9375 if (is_init)
9376 {
9377 if (ffestorag_init (eqst) != NULL)
9378 {
a6fa6420
CB
9379 ffebld sexp;
9380
9381 /* Set the padding for the expression, so ffecom_expr
9382 knows to insert that many zeros. */
9383 switch (ffebld_op (sexp = ffestorag_init (eqst)))
9384 {
9385 case FFEBLD_opCONTER:
9386 ffebld_conter_set_pad (sexp, ffestorag_modulo (eqst));
9387 break;
9388
9389 case FFEBLD_opARRTER:
9390 ffebld_arrter_set_pad (sexp, ffestorag_modulo (eqst));
9391 break;
9392
9393 case FFEBLD_opACCTER:
9394 ffebld_accter_set_pad (sexp, ffestorag_modulo (eqst));
9395 break;
9396
9397 default:
9398 assert ("bad op for eqv init (pad)" == NULL);
9399 break;
9400 }
9401
9402 init = ffecom_expr (sexp);
5ff904cd
JL
9403 if (init == error_mark_node)
9404 init = NULL_TREE; /* Hopefully the back end complained! */
9405 }
9406 else
9407 init = error_mark_node;
9408 }
9409 else if (ffe_is_init_local_zero ())
9410 init = error_mark_node;
9411 else
9412 init = NULL_TREE;
9413
9414 ffecom_member_namelisted_ = FALSE;
9415 ffestorag_drive (ffestorag_list_equivs (eqst),
9416 &ffecom_member_phase1_,
9417 eqst);
9418
9419 yes = suspend_momentary ();
9420
a6fa6420
CB
9421 high = build_int_2 ((ffestorag_size (eqst)
9422 + ffestorag_modulo (eqst)) - 1, 0);
5ff904cd
JL
9423 TREE_TYPE (high) = ffecom_integer_type_node;
9424
9425 eqtype = build_array_type (char_type_node,
9426 build_range_type (ffecom_integer_type_node,
a6fa6420 9427 ffecom_integer_zero_node,
5ff904cd
JL
9428 high));
9429
9430 eqt = build_decl (VAR_DECL,
9431 ffecom_get_invented_identifier ("__g77_equiv_%s",
9432 ffesymbol_text
9433 (ffestorag_symbol
9434 (eqst)),
9435 0),
9436 eqtype);
9437 DECL_EXTERNAL (eqt) = 0;
9438 if (is_init
9439 || ffecom_member_namelisted_
9440#ifdef FFECOM_sizeMAXSTACKITEM
9441 || (ffestorag_size (eqst) > FFECOM_sizeMAXSTACKITEM)
9442#endif
9443 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
9444 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
9445 && (ffestorag_is_save (eqst) || ffe_is_saveall ())))
9446 TREE_STATIC (eqt) = 1;
9447 else
9448 TREE_STATIC (eqt) = 0;
9449 TREE_PUBLIC (eqt) = 0;
9450 DECL_CONTEXT (eqt) = current_function_decl;
9451 if (init)
9452 DECL_INITIAL (eqt) = error_mark_node;
9453 else
9454 DECL_INITIAL (eqt) = NULL_TREE;
9455
9456 eqt = start_decl (eqt, FALSE);
9457
5ff904cd
JL
9458 /* Make sure that any type can live in EQUIVALENCE and be referenced
9459 without getting a bus error. We could pick the most restrictive
9460 alignment of all entities actually placed in the EQUIVALENCE, but
9461 this seems easy enough. */
9462
9463 DECL_ALIGN (eqt) = BIGGEST_ALIGNMENT;
9464
9465 if ((!is_init && ffe_is_init_local_zero ())
9466 || (is_init && (ffestorag_init (eqst) == NULL)))
9467 init = ffecom_init_zero_ (eqt);
9468
9469 finish_decl (eqt, init, FALSE);
9470
9471 if (is_init)
9472 ffestorag_set_init (eqst, ffebld_new_any ());
9473
9474 {
9475 tree size_tree;
9476
9477 size_tree = size_binop (CEIL_DIV_EXPR,
9478 DECL_SIZE (eqt),
9479 size_int (BITS_PER_UNIT));
9480 assert (TREE_INT_CST_HIGH (size_tree) == 0);
a6fa6420
CB
9481 assert (TREE_INT_CST_LOW (size_tree)
9482 == ffestorag_size (eqst) + ffestorag_modulo (eqst));
5ff904cd
JL
9483 }
9484
9485 ffestorag_set_hook (eqst, eqt);
9486
9487#ifdef SOMEONE_GETS_DEBUG_SUPPORT_WORKING
9488 ffestorag_drive (ffestorag_list_equivs (eqst),
9489 &ffecom_member_phase2_,
9490 eqst);
9491#endif
9492
9493 resume_momentary (yes);
9494}
9495
9496#endif
9497/* Implement NAMELIST in back end. See f2c/format.c for more info. */
9498
9499#if FFECOM_targetCURRENT == FFECOM_targetGCC
9500static tree
9501ffecom_transform_namelist_ (ffesymbol s)
9502{
9503 tree nmlt;
9504 tree nmltype = ffecom_type_namelist_ ();
9505 tree nmlinits;
9506 tree nameinit;
9507 tree varsinit;
9508 tree nvarsinit;
9509 tree field;
9510 tree high;
9511 int yes;
9512 int i;
9513 static int mynumber = 0;
9514
9515 yes = suspend_momentary ();
9516
9517 nmlt = build_decl (VAR_DECL,
9518 ffecom_get_invented_identifier ("__g77_namelist_%d",
9519 NULL, mynumber++),
9520 nmltype);
9521 TREE_STATIC (nmlt) = 1;
9522 DECL_INITIAL (nmlt) = error_mark_node;
9523
9524 nmlt = start_decl (nmlt, FALSE);
9525
9526 /* Process inits. */
9527
9528 i = strlen (ffesymbol_text (s));
9529
9530 high = build_int_2 (i, 0);
9531 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
9532
9533 nameinit = ffecom_build_f2c_string_ (i + 1,
9534 ffesymbol_text (s));
9535 TREE_TYPE (nameinit)
9536 = build_type_variant
9537 (build_array_type
9538 (char_type_node,
9539 build_range_type (ffecom_f2c_ftnlen_type_node,
9540 ffecom_f2c_ftnlen_one_node,
9541 high)),
9542 1, 0);
9543 TREE_CONSTANT (nameinit) = 1;
9544 TREE_STATIC (nameinit) = 1;
9545 nameinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (nameinit)),
9546 nameinit);
9547
9548 varsinit = ffecom_vardesc_array_ (s);
9549 varsinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (varsinit)),
9550 varsinit);
9551 TREE_CONSTANT (varsinit) = 1;
9552 TREE_STATIC (varsinit) = 1;
9553
9554 {
9555 ffebld b;
9556
9557 for (i = 0, b = ffesymbol_namelist (s); b != NULL; b = ffebld_trail (b))
9558 ++i;
9559 }
9560 nvarsinit = build_int_2 (i, 0);
9561 TREE_TYPE (nvarsinit) = integer_type_node;
9562 TREE_CONSTANT (nvarsinit) = 1;
9563 TREE_STATIC (nvarsinit) = 1;
9564
9565 nmlinits = build_tree_list ((field = TYPE_FIELDS (nmltype)), nameinit);
9566 TREE_CHAIN (nmlinits) = build_tree_list ((field = TREE_CHAIN (field)),
9567 varsinit);
9568 TREE_CHAIN (TREE_CHAIN (nmlinits))
9569 = build_tree_list ((field = TREE_CHAIN (field)), nvarsinit);
9570
9571 nmlinits = build (CONSTRUCTOR, nmltype, NULL_TREE, nmlinits);
9572 TREE_CONSTANT (nmlinits) = 1;
9573 TREE_STATIC (nmlinits) = 1;
9574
9575 finish_decl (nmlt, nmlinits, FALSE);
9576
9577 nmlt = ffecom_1 (ADDR_EXPR, build_pointer_type (nmltype), nmlt);
9578
9579 resume_momentary (yes);
9580
9581 return nmlt;
9582}
9583
9584#endif
9585
9586/* A subroutine of ffecom_tree_canonize_ref_. The incoming tree is
9587 analyzed on the assumption it is calculating a pointer to be
9588 indirected through. It must return the proper decl and offset,
9589 taking into account different units of measurements for offsets. */
9590
9591#if FFECOM_targetCURRENT == FFECOM_targetGCC
9592static void
9593ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
9594 tree t)
9595{
9596 switch (TREE_CODE (t))
9597 {
9598 case NOP_EXPR:
9599 case CONVERT_EXPR:
9600 case NON_LVALUE_EXPR:
9601 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
9602 break;
9603
9604 case PLUS_EXPR:
9605 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
9606 if ((*decl == NULL_TREE)
9607 || (*decl == error_mark_node))
9608 break;
9609
9610 if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST)
9611 {
9612 /* An offset into COMMON. */
9613 *offset = size_binop (PLUS_EXPR,
9614 *offset,
9615 TREE_OPERAND (t, 1));
9616 /* Convert offset (presumably in bytes) into canonical units
9617 (presumably bits). */
9618 *offset = size_binop (MULT_EXPR,
c8bec8c8
R
9619 TYPE_SIZE (TREE_TYPE (TREE_TYPE (t))),
9620 *offset);
5ff904cd
JL
9621 break;
9622 }
9623 /* Not a COMMON reference, so an unrecognized pattern. */
9624 *decl = error_mark_node;
9625 break;
9626
9627 case PARM_DECL:
9628 *decl = t;
f861f674 9629 *offset = bitsize_int (0L, 0L);
5ff904cd
JL
9630 break;
9631
9632 case ADDR_EXPR:
9633 if (TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL)
9634 {
9635 /* A reference to COMMON. */
9636 *decl = TREE_OPERAND (t, 0);
f861f674 9637 *offset = bitsize_int (0L, 0L);
5ff904cd
JL
9638 break;
9639 }
9640 /* Fall through. */
9641 default:
9642 /* Not a COMMON reference, so an unrecognized pattern. */
9643 *decl = error_mark_node;
9644 break;
9645 }
9646}
9647#endif
9648
9649/* Given a tree that is possibly intended for use as an lvalue, return
9650 information representing a canonical view of that tree as a decl, an
9651 offset into that decl, and a size for the lvalue.
9652
9653 If there's no applicable decl, NULL_TREE is returned for the decl,
9654 and the other fields are left undefined.
9655
9656 If the tree doesn't fit the recognizable forms, an ERROR_MARK node
9657 is returned for the decl, and the other fields are left undefined.
9658
9659 Otherwise, the decl returned currently is either a VAR_DECL or a
9660 PARM_DECL.
9661
9662 The offset returned is always valid, but of course not necessarily
9663 a constant, and not necessarily converted into the appropriate
9664 type, leaving that up to the caller (so as to avoid that overhead
9665 if the decls being looked at are different anyway).
9666
9667 If the size cannot be determined (e.g. an adjustable array),
9668 an ERROR_MARK node is returned for the size. Otherwise, the
9669 size returned is valid, not necessarily a constant, and not
9670 necessarily converted into the appropriate type as with the
9671 offset.
9672
9673 Note that the offset and size expressions are expressed in the
9674 base storage units (usually bits) rather than in the units of
9675 the type of the decl, because two decls with different types
9676 might overlap but with apparently non-overlapping array offsets,
9677 whereas converting the array offsets to consistant offsets will
9678 reveal the overlap. */
9679
9680#if FFECOM_targetCURRENT == FFECOM_targetGCC
9681static void
9682ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
9683 tree *size, tree t)
9684{
9685 /* The default path is to report a nonexistant decl. */
9686 *decl = NULL_TREE;
9687
9688 if (t == NULL_TREE)
9689 return;
9690
9691 switch (TREE_CODE (t))
9692 {
9693 case ERROR_MARK:
9694 case IDENTIFIER_NODE:
9695 case INTEGER_CST:
9696 case REAL_CST:
9697 case COMPLEX_CST:
9698 case STRING_CST:
9699 case CONST_DECL:
9700 case PLUS_EXPR:
9701 case MINUS_EXPR:
9702 case MULT_EXPR:
9703 case TRUNC_DIV_EXPR:
9704 case CEIL_DIV_EXPR:
9705 case FLOOR_DIV_EXPR:
9706 case ROUND_DIV_EXPR:
9707 case TRUNC_MOD_EXPR:
9708 case CEIL_MOD_EXPR:
9709 case FLOOR_MOD_EXPR:
9710 case ROUND_MOD_EXPR:
9711 case RDIV_EXPR:
9712 case EXACT_DIV_EXPR:
9713 case FIX_TRUNC_EXPR:
9714 case FIX_CEIL_EXPR:
9715 case FIX_FLOOR_EXPR:
9716 case FIX_ROUND_EXPR:
9717 case FLOAT_EXPR:
9718 case EXPON_EXPR:
9719 case NEGATE_EXPR:
9720 case MIN_EXPR:
9721 case MAX_EXPR:
9722 case ABS_EXPR:
9723 case FFS_EXPR:
9724 case LSHIFT_EXPR:
9725 case RSHIFT_EXPR:
9726 case LROTATE_EXPR:
9727 case RROTATE_EXPR:
9728 case BIT_IOR_EXPR:
9729 case BIT_XOR_EXPR:
9730 case BIT_AND_EXPR:
9731 case BIT_ANDTC_EXPR:
9732 case BIT_NOT_EXPR:
9733 case TRUTH_ANDIF_EXPR:
9734 case TRUTH_ORIF_EXPR:
9735 case TRUTH_AND_EXPR:
9736 case TRUTH_OR_EXPR:
9737 case TRUTH_XOR_EXPR:
9738 case TRUTH_NOT_EXPR:
9739 case LT_EXPR:
9740 case LE_EXPR:
9741 case GT_EXPR:
9742 case GE_EXPR:
9743 case EQ_EXPR:
9744 case NE_EXPR:
9745 case COMPLEX_EXPR:
9746 case CONJ_EXPR:
9747 case REALPART_EXPR:
9748 case IMAGPART_EXPR:
9749 case LABEL_EXPR:
9750 case COMPONENT_REF:
9751 case COMPOUND_EXPR:
9752 case ADDR_EXPR:
9753 return;
9754
9755 case VAR_DECL:
9756 case PARM_DECL:
9757 *decl = t;
c8bec8c8 9758 *offset = bitsize_int (0L, 0L);
5ff904cd
JL
9759 *size = TYPE_SIZE (TREE_TYPE (t));
9760 return;
9761
9762 case ARRAY_REF:
9763 {
9764 tree array = TREE_OPERAND (t, 0);
9765 tree element = TREE_OPERAND (t, 1);
9766 tree init_offset;
9767
9768 if ((array == NULL_TREE)
9769 || (element == NULL_TREE))
9770 {
9771 *decl = error_mark_node;
9772 return;
9773 }
9774
9775 ffecom_tree_canonize_ref_ (decl, &init_offset, size,
9776 array);
9777 if ((*decl == NULL_TREE)
9778 || (*decl == error_mark_node))
9779 return;
9780
9781 *offset = size_binop (MULT_EXPR,
9782 TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))),
9783 size_binop (MINUS_EXPR,
9784 element,
9785 TYPE_MIN_VALUE
9786 (TYPE_DOMAIN
9787 (TREE_TYPE (array)))));
9788
9789 *offset = size_binop (PLUS_EXPR,
9790 init_offset,
9791 *offset);
9792
9793 *size = TYPE_SIZE (TREE_TYPE (t));
9794 return;
9795 }
9796
9797 case INDIRECT_REF:
9798
9799 /* Most of this code is to handle references to COMMON. And so
9800 far that is useful only for calling library functions, since
9801 external (user) functions might reference common areas. But
9802 even calling an external function, it's worthwhile to decode
9803 COMMON references because if not storing into COMMON, we don't
9804 want COMMON-based arguments to gratuitously force use of a
9805 temporary. */
9806
9807 *size = TYPE_SIZE (TREE_TYPE (t));
9808
9809 ffecom_tree_canonize_ptr_ (decl, offset,
9810 TREE_OPERAND (t, 0));
9811
9812 return;
9813
9814 case CONVERT_EXPR:
9815 case NOP_EXPR:
9816 case MODIFY_EXPR:
9817 case NON_LVALUE_EXPR:
9818 case RESULT_DECL:
9819 case FIELD_DECL:
9820 case COND_EXPR: /* More cases than we can handle. */
9821 case SAVE_EXPR:
9822 case REFERENCE_EXPR:
9823 case PREDECREMENT_EXPR:
9824 case PREINCREMENT_EXPR:
9825 case POSTDECREMENT_EXPR:
9826 case POSTINCREMENT_EXPR:
9827 case CALL_EXPR:
9828 default:
9829 *decl = error_mark_node;
9830 return;
9831 }
9832}
9833#endif
9834
9835/* Do divide operation appropriate to type of operands. */
9836
9837#if FFECOM_targetCURRENT == FFECOM_targetGCC
9838static tree
9839ffecom_tree_divide_ (tree tree_type, tree left, tree right,
9840 tree dest_tree, ffebld dest, bool *dest_used)
9841{
9842 if ((left == error_mark_node)
9843 || (right == error_mark_node))
9844 return error_mark_node;
9845
9846 switch (TREE_CODE (tree_type))
9847 {
9848 case INTEGER_TYPE:
9849 return ffecom_2 (TRUNC_DIV_EXPR, tree_type,
9850 left,
9851 right);
9852
9853 case COMPLEX_TYPE:
9854 {
9855 ffecomGfrt ix;
9856
9857 if (TREE_TYPE (tree_type)
9858 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9859 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9860 else
9861 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
9862
9863 left = ffecom_1 (ADDR_EXPR,
9864 build_pointer_type (TREE_TYPE (left)),
9865 left);
9866 left = build_tree_list (NULL_TREE, left);
9867 right = ffecom_1 (ADDR_EXPR,
9868 build_pointer_type (TREE_TYPE (right)),
9869 right);
9870 right = build_tree_list (NULL_TREE, right);
9871 TREE_CHAIN (left) = right;
9872
9873 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9874 ffecom_gfrt_kindtype (ix),
9875 ffe_is_f2c_library (),
9876 tree_type,
9877 left,
9878 dest_tree, dest, dest_used,
9879 NULL_TREE, TRUE);
9880 }
9881 break;
9882
9883 case RECORD_TYPE:
9884 {
9885 ffecomGfrt ix;
9886
9887 if (TREE_TYPE (TYPE_FIELDS (tree_type))
9888 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9889 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9890 else
9891 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
9892
9893 left = ffecom_1 (ADDR_EXPR,
9894 build_pointer_type (TREE_TYPE (left)),
9895 left);
9896 left = build_tree_list (NULL_TREE, left);
9897 right = ffecom_1 (ADDR_EXPR,
9898 build_pointer_type (TREE_TYPE (right)),
9899 right);
9900 right = build_tree_list (NULL_TREE, right);
9901 TREE_CHAIN (left) = right;
9902
9903 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9904 ffecom_gfrt_kindtype (ix),
9905 ffe_is_f2c_library (),
9906 tree_type,
9907 left,
9908 dest_tree, dest, dest_used,
9909 NULL_TREE, TRUE);
9910 }
9911 break;
9912
9913 default:
9914 return ffecom_2 (RDIV_EXPR, tree_type,
9915 left,
9916 right);
9917 }
9918}
9919
9920#endif
9921/* ffecom_type_localvar_ -- Build type info for non-dummy variable
9922
9923 tree type;
9924 ffesymbol s; // the variable's symbol
9925 ffeinfoBasictype bt; // it's basictype
9926 ffeinfoKindtype kt; // it's kindtype
9927
9928 type = ffecom_type_localvar_(s,bt,kt);
9929
9930 Handles static arrays, CHARACTER type, etc. */
9931
9932#if FFECOM_targetCURRENT == FFECOM_targetGCC
9933static tree
9934ffecom_type_localvar_ (ffesymbol s, ffeinfoBasictype bt,
9935 ffeinfoKindtype kt)
9936{
9937 tree type;
9938 ffebld dl;
9939 ffebld dim;
9940 tree lowt;
9941 tree hight;
9942
9943 type = ffecom_tree_type[bt][kt];
9944 if (bt == FFEINFO_basictypeCHARACTER)
9945 {
9946 hight = build_int_2 (ffesymbol_size (s), 0);
9947 TREE_TYPE (hight) = ffecom_f2c_ftnlen_type_node;
9948
9949 type
9950 = build_array_type
9951 (type,
9952 build_range_type (ffecom_f2c_ftnlen_type_node,
9953 ffecom_f2c_ftnlen_one_node,
9954 hight));
9955 type = ffecom_check_size_overflow_ (s, type, FALSE);
9956 }
9957
9958 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
9959 {
9960 if (type == error_mark_node)
9961 break;
9962
9963 dim = ffebld_head (dl);
9964 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
9965
9966 if (ffebld_left (dim) == NULL)
9967 lowt = integer_one_node;
9968 else
9969 lowt = ffecom_expr (ffebld_left (dim));
9970
9971 if (TREE_CODE (lowt) != INTEGER_CST)
9972 lowt = variable_size (lowt);
9973
9974 assert (ffebld_right (dim) != NULL);
9975 hight = ffecom_expr (ffebld_right (dim));
9976
9977 if (TREE_CODE (hight) != INTEGER_CST)
9978 hight = variable_size (hight);
9979
9980 type = build_array_type (type,
9981 build_range_type (ffecom_integer_type_node,
9982 lowt, hight));
9983 type = ffecom_check_size_overflow_ (s, type, FALSE);
9984 }
9985
9986 return type;
9987}
9988
9989#endif
9990/* Build Namelist type. */
9991
9992#if FFECOM_targetCURRENT == FFECOM_targetGCC
9993static tree
9994ffecom_type_namelist_ ()
9995{
9996 static tree type = NULL_TREE;
9997
9998 if (type == NULL_TREE)
9999 {
10000 static tree namefield, varsfield, nvarsfield;
10001 tree vardesctype;
10002
10003 vardesctype = ffecom_type_vardesc_ ();
10004
10005 push_obstacks_nochange ();
10006 end_temporary_allocation ();
10007
10008 type = make_node (RECORD_TYPE);
10009
10010 vardesctype = build_pointer_type (build_pointer_type (vardesctype));
10011
10012 namefield = ffecom_decl_field (type, NULL_TREE, "name",
10013 string_type_node);
10014 varsfield = ffecom_decl_field (type, namefield, "vars", vardesctype);
10015 nvarsfield = ffecom_decl_field (type, varsfield, "nvars",
10016 integer_type_node);
10017
10018 TYPE_FIELDS (type) = namefield;
10019 layout_type (type);
10020
10021 resume_temporary_allocation ();
10022 pop_obstacks ();
10023 }
10024
10025 return type;
10026}
10027
10028#endif
10029
10030/* Make a copy of a type, assuming caller has switched to the permanent
10031 obstacks and that the type is for an aggregate (array) initializer. */
10032
10033#if FFECOM_targetCURRENT == FFECOM_targetGCC && 0 /* Not used now. */
10034static tree
10035ffecom_type_permanent_copy_ (tree t)
10036{
10037 tree domain;
10038 tree max;
10039
10040 assert (TREE_TYPE (t) != NULL_TREE);
10041
10042 domain = TYPE_DOMAIN (t);
10043
10044 assert (TREE_CODE (t) == ARRAY_TYPE);
10045 assert (TREE_PERMANENT (TREE_TYPE (t)));
10046 assert (TREE_PERMANENT (TREE_TYPE (domain)));
10047 assert (TREE_PERMANENT (TYPE_MIN_VALUE (domain)));
10048
10049 max = TYPE_MAX_VALUE (domain);
10050 if (!TREE_PERMANENT (max))
10051 {
10052 assert (TREE_CODE (max) == INTEGER_CST);
10053
10054 max = build_int_2 (TREE_INT_CST_LOW (max), TREE_INT_CST_HIGH (max));
10055 TREE_TYPE (max) = TREE_TYPE (TYPE_MIN_VALUE (domain));
10056 }
10057
10058 return build_array_type (TREE_TYPE (t),
10059 build_range_type (TREE_TYPE (domain),
10060 TYPE_MIN_VALUE (domain),
10061 max));
10062}
10063#endif
10064
10065/* Build Vardesc type. */
10066
10067#if FFECOM_targetCURRENT == FFECOM_targetGCC
10068static tree
10069ffecom_type_vardesc_ ()
10070{
10071 static tree type = NULL_TREE;
10072 static tree namefield, addrfield, dimsfield, typefield;
10073
10074 if (type == NULL_TREE)
10075 {
10076 push_obstacks_nochange ();
10077 end_temporary_allocation ();
10078
10079 type = make_node (RECORD_TYPE);
10080
10081 namefield = ffecom_decl_field (type, NULL_TREE, "name",
10082 string_type_node);
10083 addrfield = ffecom_decl_field (type, namefield, "addr",
10084 string_type_node);
10085 dimsfield = ffecom_decl_field (type, addrfield, "dims",
39592813 10086 ffecom_f2c_ptr_to_ftnlen_type_node);
5ff904cd
JL
10087 typefield = ffecom_decl_field (type, dimsfield, "type",
10088 integer_type_node);
10089
10090 TYPE_FIELDS (type) = namefield;
10091 layout_type (type);
10092
10093 resume_temporary_allocation ();
10094 pop_obstacks ();
10095 }
10096
10097 return type;
10098}
10099
10100#endif
10101
10102#if FFECOM_targetCURRENT == FFECOM_targetGCC
10103static tree
10104ffecom_vardesc_ (ffebld expr)
10105{
10106 ffesymbol s;
10107
10108 assert (ffebld_op (expr) == FFEBLD_opSYMTER);
10109 s = ffebld_symter (expr);
10110
10111 if (ffesymbol_hook (s).vardesc_tree == NULL_TREE)
10112 {
10113 int i;
10114 tree vardesctype = ffecom_type_vardesc_ ();
10115 tree var;
10116 tree nameinit;
10117 tree dimsinit;
10118 tree addrinit;
10119 tree typeinit;
10120 tree field;
10121 tree varinits;
10122 int yes;
10123 static int mynumber = 0;
10124
10125 yes = suspend_momentary ();
10126
10127 var = build_decl (VAR_DECL,
10128 ffecom_get_invented_identifier ("__g77_vardesc_%d",
10129 NULL, mynumber++),
10130 vardesctype);
10131 TREE_STATIC (var) = 1;
10132 DECL_INITIAL (var) = error_mark_node;
10133
10134 var = start_decl (var, FALSE);
10135
10136 /* Process inits. */
10137
10138 nameinit = ffecom_build_f2c_string_ ((i = strlen (ffesymbol_text (s)))
10139 + 1,
10140 ffesymbol_text (s));
10141 TREE_TYPE (nameinit)
10142 = build_type_variant
10143 (build_array_type
10144 (char_type_node,
10145 build_range_type (integer_type_node,
10146 integer_one_node,
10147 build_int_2 (i, 0))),
10148 1, 0);
10149 TREE_CONSTANT (nameinit) = 1;
10150 TREE_STATIC (nameinit) = 1;
10151 nameinit = ffecom_1 (ADDR_EXPR,
10152 build_pointer_type (TREE_TYPE (nameinit)),
10153 nameinit);
10154
10155 addrinit = ffecom_arg_ptr_to_expr (expr, &typeinit);
10156
10157 dimsinit = ffecom_vardesc_dims_ (s);
10158
10159 if (typeinit == NULL_TREE)
10160 {
10161 ffeinfoBasictype bt = ffesymbol_basictype (s);
10162 ffeinfoKindtype kt = ffesymbol_kindtype (s);
10163 int tc = ffecom_f2c_typecode (bt, kt);
10164
10165 assert (tc != -1);
10166 typeinit = build_int_2 (tc, (tc < 0) ? -1 : 0);
10167 }
10168 else
10169 typeinit = ffecom_1 (NEGATE_EXPR, TREE_TYPE (typeinit), typeinit);
10170
10171 varinits = build_tree_list ((field = TYPE_FIELDS (vardesctype)),
10172 nameinit);
10173 TREE_CHAIN (varinits) = build_tree_list ((field = TREE_CHAIN (field)),
10174 addrinit);
10175 TREE_CHAIN (TREE_CHAIN (varinits))
10176 = build_tree_list ((field = TREE_CHAIN (field)), dimsinit);
10177 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (varinits)))
10178 = build_tree_list ((field = TREE_CHAIN (field)), typeinit);
10179
10180 varinits = build (CONSTRUCTOR, vardesctype, NULL_TREE, varinits);
10181 TREE_CONSTANT (varinits) = 1;
10182 TREE_STATIC (varinits) = 1;
10183
10184 finish_decl (var, varinits, FALSE);
10185
10186 var = ffecom_1 (ADDR_EXPR, build_pointer_type (vardesctype), var);
10187
10188 resume_momentary (yes);
10189
10190 ffesymbol_hook (s).vardesc_tree = var;
10191 }
10192
10193 return ffesymbol_hook (s).vardesc_tree;
10194}
10195
10196#endif
10197#if FFECOM_targetCURRENT == FFECOM_targetGCC
10198static tree
10199ffecom_vardesc_array_ (ffesymbol s)
10200{
10201 ffebld b;
10202 tree list;
10203 tree item = NULL_TREE;
10204 tree var;
10205 int i;
10206 int yes;
10207 static int mynumber = 0;
10208
10209 for (i = 0, list = NULL_TREE, b = ffesymbol_namelist (s);
10210 b != NULL;
10211 b = ffebld_trail (b), ++i)
10212 {
10213 tree t;
10214
10215 t = ffecom_vardesc_ (ffebld_head (b));
10216
10217 if (list == NULL_TREE)
10218 list = item = build_tree_list (NULL_TREE, t);
10219 else
10220 {
10221 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
10222 item = TREE_CHAIN (item);
10223 }
10224 }
10225
10226 yes = suspend_momentary ();
10227
10228 item = build_array_type (build_pointer_type (ffecom_type_vardesc_ ()),
10229 build_range_type (integer_type_node,
10230 integer_one_node,
10231 build_int_2 (i, 0)));
10232 list = build (CONSTRUCTOR, item, NULL_TREE, list);
10233 TREE_CONSTANT (list) = 1;
10234 TREE_STATIC (list) = 1;
10235
10236 var = ffecom_get_invented_identifier ("__g77_vardesc_array_%d", NULL,
10237 mynumber++);
10238 var = build_decl (VAR_DECL, var, item);
10239 TREE_STATIC (var) = 1;
10240 DECL_INITIAL (var) = error_mark_node;
10241 var = start_decl (var, FALSE);
10242 finish_decl (var, list, FALSE);
10243
10244 resume_momentary (yes);
10245
10246 return var;
10247}
10248
10249#endif
10250#if FFECOM_targetCURRENT == FFECOM_targetGCC
10251static tree
10252ffecom_vardesc_dims_ (ffesymbol s)
10253{
10254 if (ffesymbol_dims (s) == NULL)
10255 return convert (ffecom_f2c_ptr_to_ftnlen_type_node,
10256 integer_zero_node);
10257
10258 {
10259 ffebld b;
10260 ffebld e;
10261 tree list;
10262 tree backlist;
10263 tree item = NULL_TREE;
10264 tree var;
10265 int yes;
10266 tree numdim;
10267 tree numelem;
10268 tree baseoff = NULL_TREE;
10269 static int mynumber = 0;
10270
10271 numdim = build_int_2 ((int) ffesymbol_rank (s), 0);
10272 TREE_TYPE (numdim) = ffecom_f2c_ftnlen_type_node;
10273
10274 numelem = ffecom_expr (ffesymbol_arraysize (s));
10275 TREE_TYPE (numelem) = ffecom_f2c_ftnlen_type_node;
10276
10277 list = NULL_TREE;
10278 backlist = NULL_TREE;
10279 for (b = ffesymbol_dims (s), e = ffesymbol_extents (s);
10280 b != NULL;
10281 b = ffebld_trail (b), e = ffebld_trail (e))
10282 {
10283 tree t;
10284 tree low;
10285 tree back;
10286
10287 if (ffebld_trail (b) == NULL)
10288 t = NULL_TREE;
10289 else
10290 {
10291 t = convert (ffecom_f2c_ftnlen_type_node,
10292 ffecom_expr (ffebld_head (e)));
10293
10294 if (list == NULL_TREE)
10295 list = item = build_tree_list (NULL_TREE, t);
10296 else
10297 {
10298 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
10299 item = TREE_CHAIN (item);
10300 }
10301 }
10302
10303 if (ffebld_left (ffebld_head (b)) == NULL)
10304 low = ffecom_integer_one_node;
10305 else
10306 low = ffecom_expr (ffebld_left (ffebld_head (b)));
10307 low = convert (ffecom_f2c_ftnlen_type_node, low);
10308
10309 back = build_tree_list (low, t);
10310 TREE_CHAIN (back) = backlist;
10311 backlist = back;
10312 }
10313
10314 for (item = backlist; item != NULL_TREE; item = TREE_CHAIN (item))
10315 {
10316 if (TREE_VALUE (item) == NULL_TREE)
10317 baseoff = TREE_PURPOSE (item);
10318 else
10319 baseoff = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
10320 TREE_PURPOSE (item),
10321 ffecom_2 (MULT_EXPR,
10322 ffecom_f2c_ftnlen_type_node,
10323 TREE_VALUE (item),
10324 baseoff));
10325 }
10326
10327 /* backlist now dead, along with all TREE_PURPOSEs on it. */
10328
10329 baseoff = build_tree_list (NULL_TREE, baseoff);
10330 TREE_CHAIN (baseoff) = list;
10331
10332 numelem = build_tree_list (NULL_TREE, numelem);
10333 TREE_CHAIN (numelem) = baseoff;
10334
10335 numdim = build_tree_list (NULL_TREE, numdim);
10336 TREE_CHAIN (numdim) = numelem;
10337
10338 yes = suspend_momentary ();
10339
10340 item = build_array_type (ffecom_f2c_ftnlen_type_node,
10341 build_range_type (integer_type_node,
10342 integer_zero_node,
10343 build_int_2
10344 ((int) ffesymbol_rank (s)
10345 + 2, 0)));
10346 list = build (CONSTRUCTOR, item, NULL_TREE, numdim);
10347 TREE_CONSTANT (list) = 1;
10348 TREE_STATIC (list) = 1;
10349
10350 var = ffecom_get_invented_identifier ("__g77_dims_%d", NULL,
10351 mynumber++);
10352 var = build_decl (VAR_DECL, var, item);
10353 TREE_STATIC (var) = 1;
10354 DECL_INITIAL (var) = error_mark_node;
10355 var = start_decl (var, FALSE);
10356 finish_decl (var, list, FALSE);
10357
10358 var = ffecom_1 (ADDR_EXPR, build_pointer_type (item), var);
10359
10360 resume_momentary (yes);
10361
10362 return var;
10363 }
10364}
10365
10366#endif
10367/* Essentially does a "fold (build1 (code, type, node))" while checking
10368 for certain housekeeping things.
10369
10370 NOTE: for building an ADDR_EXPR around a FUNCTION_DECL, use
10371 ffecom_1_fn instead. */
10372
10373#if FFECOM_targetCURRENT == FFECOM_targetGCC
10374tree
10375ffecom_1 (enum tree_code code, tree type, tree node)
10376{
10377 tree item;
10378
10379 if ((node == error_mark_node)
10380 || (type == error_mark_node))
10381 return error_mark_node;
10382
10383 if (code == ADDR_EXPR)
10384 {
10385 if (!mark_addressable (node))
10386 assert ("can't mark_addressable this node!" == NULL);
10387 }
10388
10389 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
10390 {
10391 tree realtype;
10392
10393 case REALPART_EXPR:
10394 item = build (COMPONENT_REF, type, node, TYPE_FIELDS (TREE_TYPE (node)));
10395 break;
10396
10397 case IMAGPART_EXPR:
10398 item = build (COMPONENT_REF, type, node, TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (node))));
10399 break;
10400
10401
10402 case NEGATE_EXPR:
10403 if (TREE_CODE (type) != RECORD_TYPE)
10404 {
10405 item = build1 (code, type, node);
10406 break;
10407 }
10408 node = ffecom_stabilize_aggregate_ (node);
10409 realtype = TREE_TYPE (TYPE_FIELDS (type));
10410 item =
10411 ffecom_2 (COMPLEX_EXPR, type,
10412 ffecom_1 (NEGATE_EXPR, realtype,
10413 ffecom_1 (REALPART_EXPR, realtype,
10414 node)),
10415 ffecom_1 (NEGATE_EXPR, realtype,
10416 ffecom_1 (IMAGPART_EXPR, realtype,
10417 node)));
10418 break;
10419
10420 default:
10421 item = build1 (code, type, node);
10422 break;
10423 }
10424
10425 if (TREE_SIDE_EFFECTS (node))
10426 TREE_SIDE_EFFECTS (item) = 1;
10427 if ((code == ADDR_EXPR) && staticp (node))
10428 TREE_CONSTANT (item) = 1;
10429 return fold (item);
10430}
10431#endif
10432
10433/* Like ffecom_1 (ADDR_EXPR, TREE_TYPE (node), node), except
10434 handles TREE_CODE (node) == FUNCTION_DECL. In particular,
10435 does not set TREE_ADDRESSABLE (because calling an inline
10436 function does not mean the function needs to be separately
10437 compiled). */
10438
10439#if FFECOM_targetCURRENT == FFECOM_targetGCC
10440tree
10441ffecom_1_fn (tree node)
10442{
10443 tree item;
10444 tree type;
10445
10446 if (node == error_mark_node)
10447 return error_mark_node;
10448
10449 type = build_type_variant (TREE_TYPE (node),
10450 TREE_READONLY (node),
10451 TREE_THIS_VOLATILE (node));
10452 item = build1 (ADDR_EXPR,
10453 build_pointer_type (type), node);
10454 if (TREE_SIDE_EFFECTS (node))
10455 TREE_SIDE_EFFECTS (item) = 1;
10456 if (staticp (node))
10457 TREE_CONSTANT (item) = 1;
10458 return fold (item);
10459}
10460#endif
10461
10462/* Essentially does a "fold (build (code, type, node1, node2))" while
10463 checking for certain housekeeping things. */
10464
10465#if FFECOM_targetCURRENT == FFECOM_targetGCC
10466tree
10467ffecom_2 (enum tree_code code, tree type, tree node1,
10468 tree node2)
10469{
10470 tree item;
10471
10472 if ((node1 == error_mark_node)
10473 || (node2 == error_mark_node)
10474 || (type == error_mark_node))
10475 return error_mark_node;
10476
10477 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
10478 {
10479 tree a, b, c, d, realtype;
10480
10481 case CONJ_EXPR:
10482 assert ("no CONJ_EXPR support yet" == NULL);
10483 return error_mark_node;
10484
10485 case COMPLEX_EXPR:
10486 item = build_tree_list (TYPE_FIELDS (type), node1);
10487 TREE_CHAIN (item) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), node2);
10488 item = build (CONSTRUCTOR, type, NULL_TREE, item);
10489 break;
10490
10491 case PLUS_EXPR:
10492 if (TREE_CODE (type) != RECORD_TYPE)
10493 {
10494 item = build (code, type, node1, node2);
10495 break;
10496 }
10497 node1 = ffecom_stabilize_aggregate_ (node1);
10498 node2 = ffecom_stabilize_aggregate_ (node2);
10499 realtype = TREE_TYPE (TYPE_FIELDS (type));
10500 item =
10501 ffecom_2 (COMPLEX_EXPR, type,
10502 ffecom_2 (PLUS_EXPR, realtype,
10503 ffecom_1 (REALPART_EXPR, realtype,
10504 node1),
10505 ffecom_1 (REALPART_EXPR, realtype,
10506 node2)),
10507 ffecom_2 (PLUS_EXPR, realtype,
10508 ffecom_1 (IMAGPART_EXPR, realtype,
10509 node1),
10510 ffecom_1 (IMAGPART_EXPR, realtype,
10511 node2)));
10512 break;
10513
10514 case MINUS_EXPR:
10515 if (TREE_CODE (type) != RECORD_TYPE)
10516 {
10517 item = build (code, type, node1, node2);
10518 break;
10519 }
10520 node1 = ffecom_stabilize_aggregate_ (node1);
10521 node2 = ffecom_stabilize_aggregate_ (node2);
10522 realtype = TREE_TYPE (TYPE_FIELDS (type));
10523 item =
10524 ffecom_2 (COMPLEX_EXPR, type,
10525 ffecom_2 (MINUS_EXPR, realtype,
10526 ffecom_1 (REALPART_EXPR, realtype,
10527 node1),
10528 ffecom_1 (REALPART_EXPR, realtype,
10529 node2)),
10530 ffecom_2 (MINUS_EXPR, realtype,
10531 ffecom_1 (IMAGPART_EXPR, realtype,
10532 node1),
10533 ffecom_1 (IMAGPART_EXPR, realtype,
10534 node2)));
10535 break;
10536
10537 case MULT_EXPR:
10538 if (TREE_CODE (type) != RECORD_TYPE)
10539 {
10540 item = build (code, type, node1, node2);
10541 break;
10542 }
10543 node1 = ffecom_stabilize_aggregate_ (node1);
10544 node2 = ffecom_stabilize_aggregate_ (node2);
10545 realtype = TREE_TYPE (TYPE_FIELDS (type));
10546 a = save_expr (ffecom_1 (REALPART_EXPR, realtype,
10547 node1));
10548 b = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
10549 node1));
10550 c = save_expr (ffecom_1 (REALPART_EXPR, realtype,
10551 node2));
10552 d = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
10553 node2));
10554 item =
10555 ffecom_2 (COMPLEX_EXPR, type,
10556 ffecom_2 (MINUS_EXPR, realtype,
10557 ffecom_2 (MULT_EXPR, realtype,
10558 a,
10559 c),
10560 ffecom_2 (MULT_EXPR, realtype,
10561 b,
10562 d)),
10563 ffecom_2 (PLUS_EXPR, realtype,
10564 ffecom_2 (MULT_EXPR, realtype,
10565 a,
10566 d),
10567 ffecom_2 (MULT_EXPR, realtype,
10568 c,
10569 b)));
10570 break;
10571
10572 case EQ_EXPR:
10573 if ((TREE_CODE (node1) != RECORD_TYPE)
10574 && (TREE_CODE (node2) != RECORD_TYPE))
10575 {
10576 item = build (code, type, node1, node2);
10577 break;
10578 }
10579 assert (TREE_CODE (node1) == RECORD_TYPE);
10580 assert (TREE_CODE (node2) == RECORD_TYPE);
10581 node1 = ffecom_stabilize_aggregate_ (node1);
10582 node2 = ffecom_stabilize_aggregate_ (node2);
10583 realtype = TREE_TYPE (TYPE_FIELDS (type));
10584 item =
10585 ffecom_2 (TRUTH_ANDIF_EXPR, type,
10586 ffecom_2 (code, type,
10587 ffecom_1 (REALPART_EXPR, realtype,
10588 node1),
10589 ffecom_1 (REALPART_EXPR, realtype,
10590 node2)),
10591 ffecom_2 (code, type,
10592 ffecom_1 (IMAGPART_EXPR, realtype,
10593 node1),
10594 ffecom_1 (IMAGPART_EXPR, realtype,
10595 node2)));
10596 break;
10597
10598 case NE_EXPR:
10599 if ((TREE_CODE (node1) != RECORD_TYPE)
10600 && (TREE_CODE (node2) != RECORD_TYPE))
10601 {
10602 item = build (code, type, node1, node2);
10603 break;
10604 }
10605 assert (TREE_CODE (node1) == RECORD_TYPE);
10606 assert (TREE_CODE (node2) == RECORD_TYPE);
10607 node1 = ffecom_stabilize_aggregate_ (node1);
10608 node2 = ffecom_stabilize_aggregate_ (node2);
10609 realtype = TREE_TYPE (TYPE_FIELDS (type));
10610 item =
10611 ffecom_2 (TRUTH_ORIF_EXPR, type,
10612 ffecom_2 (code, type,
10613 ffecom_1 (REALPART_EXPR, realtype,
10614 node1),
10615 ffecom_1 (REALPART_EXPR, realtype,
10616 node2)),
10617 ffecom_2 (code, type,
10618 ffecom_1 (IMAGPART_EXPR, realtype,
10619 node1),
10620 ffecom_1 (IMAGPART_EXPR, realtype,
10621 node2)));
10622 break;
10623
10624 default:
10625 item = build (code, type, node1, node2);
10626 break;
10627 }
10628
10629 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2))
10630 TREE_SIDE_EFFECTS (item) = 1;
10631 return fold (item);
10632}
10633
10634#endif
10635/* ffecom_2pass_advise_entrypoint -- Advise that there's this entrypoint
10636
10637 ffesymbol s; // the ENTRY point itself
10638 if (ffecom_2pass_advise_entrypoint(s))
10639 // the ENTRY point has been accepted
10640
10641 Does whatever compiler needs to do when it learns about the entrypoint,
10642 like determine the return type of the master function, count the
10643 number of entrypoints, etc. Returns FALSE if the return type is
10644 not compatible with the return type(s) of other entrypoint(s).
10645
10646 NOTE: for every call to this fn that returns TRUE, _do_entrypoint must
10647 later (after _finish_progunit) be called with the same entrypoint(s)
10648 as passed to this fn for which TRUE was returned.
10649
10650 03-Jan-92 JCB 2.0
10651 Return FALSE if the return type conflicts with previous entrypoints. */
10652
10653#if FFECOM_targetCURRENT == FFECOM_targetGCC
10654bool
10655ffecom_2pass_advise_entrypoint (ffesymbol entry)
10656{
10657 ffebld list; /* opITEM. */
10658 ffebld mlist; /* opITEM. */
10659 ffebld plist; /* opITEM. */
10660 ffebld arg; /* ffebld_head(opITEM). */
10661 ffebld item; /* opITEM. */
10662 ffesymbol s; /* ffebld_symter(arg). */
10663 ffeinfoBasictype bt = ffesymbol_basictype (entry);
10664 ffeinfoKindtype kt = ffesymbol_kindtype (entry);
10665 ffetargetCharacterSize size = ffesymbol_size (entry);
10666 bool ok;
10667
10668 if (ffecom_num_entrypoints_ == 0)
10669 { /* First entrypoint, make list of main
10670 arglist's dummies. */
10671 assert (ffecom_primary_entry_ != NULL);
10672
10673 ffecom_master_bt_ = ffesymbol_basictype (ffecom_primary_entry_);
10674 ffecom_master_kt_ = ffesymbol_kindtype (ffecom_primary_entry_);
10675 ffecom_master_size_ = ffesymbol_size (ffecom_primary_entry_);
10676
10677 for (plist = NULL, list = ffesymbol_dummyargs (ffecom_primary_entry_);
10678 list != NULL;
10679 list = ffebld_trail (list))
10680 {
10681 arg = ffebld_head (list);
10682 if (ffebld_op (arg) != FFEBLD_opSYMTER)
10683 continue; /* Alternate return or some such thing. */
10684 item = ffebld_new_item (arg, NULL);
10685 if (plist == NULL)
10686 ffecom_master_arglist_ = item;
10687 else
10688 ffebld_set_trail (plist, item);
10689 plist = item;
10690 }
10691 }
10692
10693 /* If necessary, scan entry arglist for alternate returns. Do this scan
10694 apparently redundantly (it's done below to UNIONize the arglists) so
10695 that we don't complain about RETURN 1 if an offending ENTRY is the only
10696 one with an alternate return. */
10697
10698 if (!ffecom_is_altreturning_)
10699 {
10700 for (list = ffesymbol_dummyargs (entry);
10701 list != NULL;
10702 list = ffebld_trail (list))
10703 {
10704 arg = ffebld_head (list);
10705 if (ffebld_op (arg) == FFEBLD_opSTAR)
10706 {
10707 ffecom_is_altreturning_ = TRUE;
10708 break;
10709 }
10710 }
10711 }
10712
10713 /* Now check type compatibility. */
10714
10715 switch (ffecom_master_bt_)
10716 {
10717 case FFEINFO_basictypeNONE:
10718 ok = (bt != FFEINFO_basictypeCHARACTER);
10719 break;
10720
10721 case FFEINFO_basictypeCHARACTER:
10722 ok
10723 = (bt == FFEINFO_basictypeCHARACTER)
10724 && (kt == ffecom_master_kt_)
10725 && (size == ffecom_master_size_);
10726 break;
10727
10728 case FFEINFO_basictypeANY:
10729 return FALSE; /* Just don't bother. */
10730
10731 default:
10732 if (bt == FFEINFO_basictypeCHARACTER)
10733 {
10734 ok = FALSE;
10735 break;
10736 }
10737 ok = TRUE;
10738 if ((bt != ffecom_master_bt_) || (kt != ffecom_master_kt_))
10739 {
10740 ffecom_master_bt_ = FFEINFO_basictypeNONE;
10741 ffecom_master_kt_ = FFEINFO_kindtypeNONE;
10742 }
10743 break;
10744 }
10745
10746 if (!ok)
10747 {
10748 ffebad_start (FFEBAD_ENTRY_CONFLICTS);
10749 ffest_ffebad_here_current_stmt (0);
10750 ffebad_finish ();
10751 return FALSE; /* Can't handle entrypoint. */
10752 }
10753
10754 /* Entrypoint type compatible with previous types. */
10755
10756 ++ffecom_num_entrypoints_;
10757
10758 /* Master-arg-list = UNION(Master-arg-list,entry-arg-list). */
10759
10760 for (list = ffesymbol_dummyargs (entry);
10761 list != NULL;
10762 list = ffebld_trail (list))
10763 {
10764 arg = ffebld_head (list);
10765 if (ffebld_op (arg) != FFEBLD_opSYMTER)
10766 continue; /* Alternate return or some such thing. */
10767 s = ffebld_symter (arg);
10768 for (plist = NULL, mlist = ffecom_master_arglist_;
10769 mlist != NULL;
10770 plist = mlist, mlist = ffebld_trail (mlist))
10771 { /* plist points to previous item for easy
10772 appending of arg. */
10773 if (ffebld_symter (ffebld_head (mlist)) == s)
10774 break; /* Already have this arg in the master list. */
10775 }
10776 if (mlist != NULL)
10777 continue; /* Already have this arg in the master list. */
10778
10779 /* Append this arg to the master list. */
10780
10781 item = ffebld_new_item (arg, NULL);
10782 if (plist == NULL)
10783 ffecom_master_arglist_ = item;
10784 else
10785 ffebld_set_trail (plist, item);
10786 }
10787
10788 return TRUE;
10789}
10790
10791#endif
10792/* ffecom_2pass_do_entrypoint -- Do compilation of entrypoint
10793
10794 ffesymbol s; // the ENTRY point itself
10795 ffecom_2pass_do_entrypoint(s);
10796
10797 Does whatever compiler needs to do to make the entrypoint actually
10798 happen. Must be called for each entrypoint after
10799 ffecom_finish_progunit is called. */
10800
10801#if FFECOM_targetCURRENT == FFECOM_targetGCC
10802void
10803ffecom_2pass_do_entrypoint (ffesymbol entry)
10804{
10805 static int mfn_num = 0;
10806 static int ent_num;
10807
10808 if (mfn_num != ffecom_num_fns_)
10809 { /* First entrypoint for this program unit. */
10810 ent_num = 1;
10811 mfn_num = ffecom_num_fns_;
10812 ffecom_do_entry_ (ffecom_primary_entry_, 0);
10813 }
10814 else
10815 ++ent_num;
10816
10817 --ffecom_num_entrypoints_;
10818
10819 ffecom_do_entry_ (entry, ent_num);
10820}
10821
10822#endif
10823
10824/* Essentially does a "fold (build (code, type, node1, node2))" while
10825 checking for certain housekeeping things. Always sets
10826 TREE_SIDE_EFFECTS. */
10827
10828#if FFECOM_targetCURRENT == FFECOM_targetGCC
10829tree
10830ffecom_2s (enum tree_code code, tree type, tree node1,
10831 tree node2)
10832{
10833 tree item;
10834
10835 if ((node1 == error_mark_node)
10836 || (node2 == error_mark_node)
10837 || (type == error_mark_node))
10838 return error_mark_node;
10839
10840 item = build (code, type, node1, node2);
10841 TREE_SIDE_EFFECTS (item) = 1;
10842 return fold (item);
10843}
10844
10845#endif
10846/* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10847 checking for certain housekeeping things. */
10848
10849#if FFECOM_targetCURRENT == FFECOM_targetGCC
10850tree
10851ffecom_3 (enum tree_code code, tree type, tree node1,
10852 tree node2, tree node3)
10853{
10854 tree item;
10855
10856 if ((node1 == error_mark_node)
10857 || (node2 == error_mark_node)
10858 || (node3 == error_mark_node)
10859 || (type == error_mark_node))
10860 return error_mark_node;
10861
10862 item = build (code, type, node1, node2, node3);
10863 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2)
10864 || (node3 != NULL_TREE && TREE_SIDE_EFFECTS (node3)))
10865 TREE_SIDE_EFFECTS (item) = 1;
10866 return fold (item);
10867}
10868
10869#endif
10870/* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10871 checking for certain housekeeping things. Always sets
10872 TREE_SIDE_EFFECTS. */
10873
10874#if FFECOM_targetCURRENT == FFECOM_targetGCC
10875tree
10876ffecom_3s (enum tree_code code, tree type, tree node1,
10877 tree node2, tree node3)
10878{
10879 tree item;
10880
10881 if ((node1 == error_mark_node)
10882 || (node2 == error_mark_node)
10883 || (node3 == error_mark_node)
10884 || (type == error_mark_node))
10885 return error_mark_node;
10886
10887 item = build (code, type, node1, node2, node3);
10888 TREE_SIDE_EFFECTS (item) = 1;
10889 return fold (item);
10890}
10891
10892#endif
10893/* ffecom_arg_expr -- Transform argument expr into gcc tree
10894
10895 See use by ffecom_list_expr.
10896
10897 If expression is NULL, returns an integer zero tree. If it is not
10898 a CHARACTER expression, returns whatever ffecom_expr
10899 returns and sets the length return value to NULL_TREE. Otherwise
10900 generates code to evaluate the character expression, returns the proper
10901 pointer to the result, but does NOT set the length return value to a tree
10902 that specifies the length of the result. (In other words, the length
10903 variable is always set to NULL_TREE, because a length is never passed.)
10904
10905 21-Dec-91 JCB 1.1
10906 Don't set returned length, since nobody needs it (yet; someday if
10907 we allow CHARACTER*(*) dummies to statement functions, we'll need
10908 it). */
10909
10910#if FFECOM_targetCURRENT == FFECOM_targetGCC
10911tree
10912ffecom_arg_expr (ffebld expr, tree *length)
10913{
10914 tree ign;
10915
10916 *length = NULL_TREE;
10917
10918 if (expr == NULL)
10919 return integer_zero_node;
10920
10921 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10922 return ffecom_expr (expr);
10923
10924 return ffecom_arg_ptr_to_expr (expr, &ign);
10925}
10926
10927#endif
10928/* ffecom_arg_ptr_to_expr -- Transform argument expr into gcc tree
10929
10930 See use by ffecom_list_ptr_to_expr.
10931
10932 If expression is NULL, returns an integer zero tree. If it is not
10933 a CHARACTER expression, returns whatever ffecom_ptr_to_expr
10934 returns and sets the length return value to NULL_TREE. Otherwise
10935 generates code to evaluate the character expression, returns the proper
10936 pointer to the result, AND sets the length return value to a tree that
86fc7a6c
CB
10937 specifies the length of the result.
10938
10939 If the length argument is NULL, this is a slightly special
10940 case of building a FORMAT expression, that is, an expression that
10941 will be used at run time without regard to length. For the current
10942 implementation, which uses the libf2c library, this means it is nice
10943 to append a null byte to the end of the expression, where feasible,
10944 to make sure any diagnostic about the FORMAT string terminates at
10945 some useful point.
10946
10947 For now, treat %REF(char-expr) as the same as char-expr with a NULL
10948 length argument. This might even be seen as a feature, if a null
10949 byte can always be appended. */
5ff904cd
JL
10950
10951#if FFECOM_targetCURRENT == FFECOM_targetGCC
10952tree
10953ffecom_arg_ptr_to_expr (ffebld expr, tree *length)
10954{
10955 tree item;
10956 tree ign_length;
10957 ffecomConcatList_ catlist;
10958
86fc7a6c
CB
10959 if (length != NULL)
10960 *length = NULL_TREE;
5ff904cd
JL
10961
10962 if (expr == NULL)
10963 return integer_zero_node;
10964
10965 switch (ffebld_op (expr))
10966 {
10967 case FFEBLD_opPERCENT_VAL:
10968 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10969 return ffecom_expr (ffebld_left (expr));
10970 {
10971 tree temp_exp;
10972 tree temp_length;
10973
10974 temp_exp = ffecom_arg_ptr_to_expr (ffebld_left (expr), &temp_length);
10975 return ffecom_1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (temp_exp)),
10976 temp_exp);
10977 }
10978
10979 case FFEBLD_opPERCENT_REF:
10980 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10981 return ffecom_ptr_to_expr (ffebld_left (expr));
86fc7a6c
CB
10982 if (length != NULL)
10983 {
10984 ign_length = NULL_TREE;
10985 length = &ign_length;
10986 }
5ff904cd
JL
10987 expr = ffebld_left (expr);
10988 break;
10989
10990 case FFEBLD_opPERCENT_DESCR:
10991 switch (ffeinfo_basictype (ffebld_info (expr)))
10992 {
10993#ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10994 case FFEINFO_basictypeHOLLERITH:
10995#endif
10996 case FFEINFO_basictypeCHARACTER:
10997 break; /* Passed by descriptor anyway. */
10998
10999 default:
11000 item = ffecom_ptr_to_expr (expr);
11001 if (item != error_mark_node)
11002 *length = TYPE_SIZE (TREE_TYPE (TREE_TYPE (item)));
11003 break;
11004 }
11005 break;
11006
11007 default:
11008 break;
11009 }
11010
11011#ifdef PASS_HOLLERITH_BY_DESCRIPTOR
86fc7a6c
CB
11012 if ((ffeinfo_basictype (ffebld_info (expr)) == FFEINFO_basictypeHOLLERITH)
11013 && (length != NULL))
5ff904cd
JL
11014 { /* Pass Hollerith by descriptor. */
11015 ffetargetHollerith h;
11016
11017 assert (ffebld_op (expr) == FFEBLD_opCONTER);
11018 h = ffebld_cu_val_hollerith (ffebld_constant_union
11019 (ffebld_conter (expr)));
11020 *length
11021 = build_int_2 (h.length, 0);
11022 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
11023 }
11024#endif
11025
11026 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
11027 return ffecom_ptr_to_expr (expr);
11028
11029 assert (ffeinfo_kindtype (ffebld_info (expr))
11030 == FFEINFO_kindtypeCHARACTER1);
11031
11032 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
11033 switch (ffecom_concat_list_count_ (catlist))
11034 {
11035 case 0: /* Shouldn't happen, but in case it does... */
86fc7a6c
CB
11036 if (length != NULL)
11037 {
11038 *length = ffecom_f2c_ftnlen_zero_node;
11039 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
11040 }
5ff904cd
JL
11041 ffecom_concat_list_kill_ (catlist);
11042 return null_pointer_node;
11043
11044 case 1: /* The (fairly) easy case. */
86fc7a6c
CB
11045 if (length == NULL)
11046 ffecom_char_args_with_null_ (&item, &ign_length,
11047 ffecom_concat_list_expr_ (catlist, 0));
11048 else
11049 ffecom_char_args_ (&item, length,
11050 ffecom_concat_list_expr_ (catlist, 0));
5ff904cd
JL
11051 ffecom_concat_list_kill_ (catlist);
11052 assert (item != NULL_TREE);
11053 return item;
11054
11055 default: /* Must actually concatenate things. */
11056 break;
11057 }
11058
11059 {
11060 int count = ffecom_concat_list_count_ (catlist);
11061 int i;
11062 tree lengths;
11063 tree items;
11064 tree length_array;
11065 tree item_array;
11066 tree citem;
11067 tree clength;
11068 tree temporary;
11069 tree num;
11070 tree known_length;
11071 ffetargetCharacterSize sz;
11072
11073 length_array
11074 = lengths
11075 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
11076 FFETARGET_charactersizeNONE, count, TRUE);
11077 item_array
11078 = items
11079 = ffecom_push_tempvar (ffecom_f2c_address_type_node,
11080 FFETARGET_charactersizeNONE, count, TRUE);
11081
11082 known_length = ffecom_f2c_ftnlen_zero_node;
11083
11084 for (i = 0; i < count; ++i)
11085 {
86fc7a6c
CB
11086 if ((i == count)
11087 && (length == NULL))
11088 ffecom_char_args_with_null_ (&citem, &clength,
11089 ffecom_concat_list_expr_ (catlist, i));
11090 else
11091 ffecom_char_args_ (&citem, &clength,
11092 ffecom_concat_list_expr_ (catlist, i));
5ff904cd
JL
11093 if ((citem == error_mark_node)
11094 || (clength == error_mark_node))
11095 {
11096 ffecom_concat_list_kill_ (catlist);
11097 *length = error_mark_node;
11098 return error_mark_node;
11099 }
11100
11101 items
11102 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
11103 ffecom_modify (void_type_node,
11104 ffecom_2 (ARRAY_REF,
11105 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
11106 item_array,
11107 build_int_2 (i, 0)),
11108 citem),
11109 items);
11110 clength = ffecom_save_tree (clength);
86fc7a6c
CB
11111 if (length != NULL)
11112 known_length
11113 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
11114 known_length,
11115 clength);
5ff904cd
JL
11116 lengths
11117 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
11118 ffecom_modify (void_type_node,
11119 ffecom_2 (ARRAY_REF,
11120 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
11121 length_array,
11122 build_int_2 (i, 0)),
11123 clength),
11124 lengths);
11125 }
11126
11127 sz = ffecom_concat_list_maxlen_ (catlist);
11128 assert (sz != FFETARGET_charactersizeNONE);
11129
11130 temporary = ffecom_push_tempvar (char_type_node,
11131 sz, -1, TRUE);
11132 temporary = ffecom_1 (ADDR_EXPR,
11133 build_pointer_type (TREE_TYPE (temporary)),
11134 temporary);
11135
11136 item = build_tree_list (NULL_TREE, temporary);
11137 TREE_CHAIN (item)
11138 = build_tree_list (NULL_TREE,
11139 ffecom_1 (ADDR_EXPR,
11140 build_pointer_type (TREE_TYPE (items)),
11141 items));
11142 TREE_CHAIN (TREE_CHAIN (item))
11143 = build_tree_list (NULL_TREE,
11144 ffecom_1 (ADDR_EXPR,
11145 build_pointer_type (TREE_TYPE (lengths)),
11146 lengths));
11147 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
11148 = build_tree_list
11149 (NULL_TREE,
11150 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
11151 convert (ffecom_f2c_ftnlen_type_node,
11152 build_int_2 (count, 0))));
11153 num = build_int_2 (sz, 0);
11154 TREE_TYPE (num) = ffecom_f2c_ftnlen_type_node;
11155 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item))))
11156 = build_tree_list (NULL_TREE, num);
11157
11158 item = ffecom_call_gfrt (FFECOM_gfrtCAT, item);
11159 TREE_SIDE_EFFECTS (item) = 1;
11160 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (temporary),
11161 item,
11162 temporary);
11163
86fc7a6c
CB
11164 if (length != NULL)
11165 *length = known_length;
5ff904cd
JL
11166 }
11167
11168 ffecom_concat_list_kill_ (catlist);
11169 assert (item != NULL_TREE);
11170 return item;
11171}
11172
11173#endif
11174/* ffecom_call_gfrt -- Generate call to run-time function
11175
11176 tree expr;
11177 expr = ffecom_call_gfrt(FFECOM_gfrtSTOPNIL,NULL_TREE);
11178
11179 The first arg is the GNU Fortran Run-Time function index, the second
11180 arg is the list of arguments to pass to it. Returned is the expression
11181 (WITHOUT TREE_SIDE_EFFECTS set!) that makes the call and returns the
11182 result (which may be void). */
11183
11184#if FFECOM_targetCURRENT == FFECOM_targetGCC
11185tree
11186ffecom_call_gfrt (ffecomGfrt ix, tree args)
11187{
11188 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
11189 ffecom_gfrt_kindtype (ix),
11190 ffe_is_f2c_library () && ffecom_gfrt_complex_[ix],
11191 NULL_TREE, args, NULL_TREE, NULL,
11192 NULL, NULL_TREE, TRUE);
11193}
11194#endif
11195
11196/* ffecom_constantunion -- Transform constant-union to tree
11197
11198 ffebldConstantUnion cu; // the constant to transform
11199 ffeinfoBasictype bt; // its basic type
11200 ffeinfoKindtype kt; // its kind type
11201 tree tree_type; // ffecom_tree_type[bt][kt]
11202 ffecom_constantunion(&cu,bt,kt,tree_type); */
11203
11204#if FFECOM_targetCURRENT == FFECOM_targetGCC
11205tree
11206ffecom_constantunion (ffebldConstantUnion *cu, ffeinfoBasictype bt,
11207 ffeinfoKindtype kt, tree tree_type)
11208{
11209 tree item;
11210
11211 switch (bt)
11212 {
11213 case FFEINFO_basictypeINTEGER:
11214 {
11215 int val;
11216
11217 switch (kt)
11218 {
11219#if FFETARGET_okINTEGER1
11220 case FFEINFO_kindtypeINTEGER1:
11221 val = ffebld_cu_val_integer1 (*cu);
11222 break;
11223#endif
11224
11225#if FFETARGET_okINTEGER2
11226 case FFEINFO_kindtypeINTEGER2:
11227 val = ffebld_cu_val_integer2 (*cu);
11228 break;
11229#endif
11230
11231#if FFETARGET_okINTEGER3
11232 case FFEINFO_kindtypeINTEGER3:
11233 val = ffebld_cu_val_integer3 (*cu);
11234 break;
11235#endif
11236
11237#if FFETARGET_okINTEGER4
11238 case FFEINFO_kindtypeINTEGER4:
11239 val = ffebld_cu_val_integer4 (*cu);
11240 break;
11241#endif
11242
11243 default:
11244 assert ("bad INTEGER constant kind type" == NULL);
11245 /* Fall through. */
11246 case FFEINFO_kindtypeANY:
11247 return error_mark_node;
11248 }
11249 item = build_int_2 (val, (val < 0) ? -1 : 0);
11250 TREE_TYPE (item) = tree_type;
11251 }
11252 break;
11253
11254 case FFEINFO_basictypeLOGICAL:
11255 {
11256 int val;
11257
11258 switch (kt)
11259 {
11260#if FFETARGET_okLOGICAL1
11261 case FFEINFO_kindtypeLOGICAL1:
11262 val = ffebld_cu_val_logical1 (*cu);
11263 break;
11264#endif
11265
11266#if FFETARGET_okLOGICAL2
11267 case FFEINFO_kindtypeLOGICAL2:
11268 val = ffebld_cu_val_logical2 (*cu);
11269 break;
11270#endif
11271
11272#if FFETARGET_okLOGICAL3
11273 case FFEINFO_kindtypeLOGICAL3:
11274 val = ffebld_cu_val_logical3 (*cu);
11275 break;
11276#endif
11277
11278#if FFETARGET_okLOGICAL4
11279 case FFEINFO_kindtypeLOGICAL4:
11280 val = ffebld_cu_val_logical4 (*cu);
11281 break;
11282#endif
11283
11284 default:
11285 assert ("bad LOGICAL constant kind type" == NULL);
11286 /* Fall through. */
11287 case FFEINFO_kindtypeANY:
11288 return error_mark_node;
11289 }
11290 item = build_int_2 (val, (val < 0) ? -1 : 0);
11291 TREE_TYPE (item) = tree_type;
11292 }
11293 break;
11294
11295 case FFEINFO_basictypeREAL:
11296 {
11297 REAL_VALUE_TYPE val;
11298
11299 switch (kt)
11300 {
11301#if FFETARGET_okREAL1
11302 case FFEINFO_kindtypeREAL1:
11303 val = ffetarget_value_real1 (ffebld_cu_val_real1 (*cu));
11304 break;
11305#endif
11306
11307#if FFETARGET_okREAL2
11308 case FFEINFO_kindtypeREAL2:
11309 val = ffetarget_value_real2 (ffebld_cu_val_real2 (*cu));
11310 break;
11311#endif
11312
11313#if FFETARGET_okREAL3
11314 case FFEINFO_kindtypeREAL3:
11315 val = ffetarget_value_real3 (ffebld_cu_val_real3 (*cu));
11316 break;
11317#endif
11318
11319#if FFETARGET_okREAL4
11320 case FFEINFO_kindtypeREAL4:
11321 val = ffetarget_value_real4 (ffebld_cu_val_real4 (*cu));
11322 break;
11323#endif
11324
11325 default:
11326 assert ("bad REAL constant kind type" == NULL);
11327 /* Fall through. */
11328 case FFEINFO_kindtypeANY:
11329 return error_mark_node;
11330 }
11331 item = build_real (tree_type, val);
11332 }
11333 break;
11334
11335 case FFEINFO_basictypeCOMPLEX:
11336 {
11337 REAL_VALUE_TYPE real;
11338 REAL_VALUE_TYPE imag;
11339 tree el_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
11340
11341 switch (kt)
11342 {
11343#if FFETARGET_okCOMPLEX1
11344 case FFEINFO_kindtypeREAL1:
11345 real = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).real);
11346 imag = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).imaginary);
11347 break;
11348#endif
11349
11350#if FFETARGET_okCOMPLEX2
11351 case FFEINFO_kindtypeREAL2:
11352 real = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).real);
11353 imag = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).imaginary);
11354 break;
11355#endif
11356
11357#if FFETARGET_okCOMPLEX3
11358 case FFEINFO_kindtypeREAL3:
11359 real = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).real);
11360 imag = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).imaginary);
11361 break;
11362#endif
11363
11364#if FFETARGET_okCOMPLEX4
11365 case FFEINFO_kindtypeREAL4:
11366 real = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).real);
11367 imag = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).imaginary);
11368 break;
11369#endif
11370
11371 default:
11372 assert ("bad REAL constant kind type" == NULL);
11373 /* Fall through. */
11374 case FFEINFO_kindtypeANY:
11375 return error_mark_node;
11376 }
11377 item = ffecom_build_complex_constant_ (tree_type,
11378 build_real (el_type, real),
11379 build_real (el_type, imag));
11380 }
11381 break;
11382
11383 case FFEINFO_basictypeCHARACTER:
11384 { /* Happens only in DATA and similar contexts. */
11385 ffetargetCharacter1 val;
11386
11387 switch (kt)
11388 {
11389#if FFETARGET_okCHARACTER1
11390 case FFEINFO_kindtypeLOGICAL1:
11391 val = ffebld_cu_val_character1 (*cu);
11392 break;
11393#endif
11394
11395 default:
11396 assert ("bad CHARACTER constant kind type" == NULL);
11397 /* Fall through. */
11398 case FFEINFO_kindtypeANY:
11399 return error_mark_node;
11400 }
11401 item = build_string (ffetarget_length_character1 (val),
11402 ffetarget_text_character1 (val));
11403 TREE_TYPE (item)
11404 = build_type_variant (build_array_type (char_type_node,
11405 build_range_type
11406 (integer_type_node,
11407 integer_one_node,
11408 build_int_2
11409 (ffetarget_length_character1
11410 (val), 0))),
11411 1, 0);
11412 }
11413 break;
11414
11415 case FFEINFO_basictypeHOLLERITH:
11416 {
11417 ffetargetHollerith h;
11418
11419 h = ffebld_cu_val_hollerith (*cu);
11420
11421 /* If not at least as wide as default INTEGER, widen it. */
11422 if (h.length >= FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE)
11423 item = build_string (h.length, h.text);
11424 else
11425 {
11426 char str[FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE];
11427
11428 memcpy (str, h.text, h.length);
11429 memset (&str[h.length], ' ',
11430 FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE
11431 - h.length);
11432 item = build_string (FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE,
11433 str);
11434 }
11435 TREE_TYPE (item)
11436 = build_type_variant (build_array_type (char_type_node,
11437 build_range_type
11438 (integer_type_node,
11439 integer_one_node,
11440 build_int_2
11441 (h.length, 0))),
11442 1, 0);
11443 }
11444 break;
11445
11446 case FFEINFO_basictypeTYPELESS:
11447 {
11448 ffetargetInteger1 ival;
11449 ffetargetTypeless tless;
11450 ffebad error;
11451
11452 tless = ffebld_cu_val_typeless (*cu);
11453 error = ffetarget_convert_integer1_typeless (&ival, tless);
11454 assert (error == FFEBAD);
11455
11456 item = build_int_2 ((int) ival, 0);
11457 }
11458 break;
11459
11460 default:
11461 assert ("not yet on constant type" == NULL);
11462 /* Fall through. */
11463 case FFEINFO_basictypeANY:
11464 return error_mark_node;
11465 }
11466
11467 TREE_CONSTANT (item) = 1;
11468
11469 return item;
11470}
11471
11472#endif
11473
11474/* Handy way to make a field in a struct/union. */
11475
11476#if FFECOM_targetCURRENT == FFECOM_targetGCC
11477tree
11478ffecom_decl_field (tree context, tree prevfield,
11479 char *name, tree type)
11480{
11481 tree field;
11482
11483 field = build_decl (FIELD_DECL, get_identifier (name), type);
11484 DECL_CONTEXT (field) = context;
11485 DECL_FRAME_SIZE (field) = 0;
11486 if (prevfield != NULL_TREE)
11487 TREE_CHAIN (prevfield) = field;
11488
11489 return field;
11490}
11491
11492#endif
11493
11494void
11495ffecom_close_include (FILE *f)
11496{
11497#if FFECOM_GCC_INCLUDE
11498 ffecom_close_include_ (f);
11499#endif
11500}
11501
11502int
11503ffecom_decode_include_option (char *spec)
11504{
11505#if FFECOM_GCC_INCLUDE
11506 return ffecom_decode_include_option_ (spec);
11507#else
11508 return 1;
11509#endif
11510}
11511
11512/* ffecom_end_transition -- Perform end transition on all symbols
11513
11514 ffecom_end_transition();
11515
11516 Calls ffecom_sym_end_transition for each global and local symbol. */
11517
11518void
11519ffecom_end_transition ()
11520{
11521#if FFECOM_targetCURRENT == FFECOM_targetGCC
11522 ffebld item;
11523#endif
11524
11525 if (ffe_is_ffedebug ())
11526 fprintf (dmpout, "; end_stmt_transition\n");
11527
11528#if FFECOM_targetCURRENT == FFECOM_targetGCC
11529 ffecom_list_blockdata_ = NULL;
11530 ffecom_list_common_ = NULL;
11531#endif
11532
11533 ffesymbol_drive (ffecom_sym_end_transition);
11534 if (ffe_is_ffedebug ())
11535 {
11536 ffestorag_report ();
8b45da67 11537#if FFECOM_targetCURRENT == FFECOM_targetFFE
5ff904cd 11538 ffesymbol_report_all ();
8b45da67 11539#endif
5ff904cd
JL
11540 }
11541
11542#if FFECOM_targetCURRENT == FFECOM_targetGCC
11543 ffecom_start_progunit_ ();
11544
11545 for (item = ffecom_list_blockdata_;
11546 item != NULL;
11547 item = ffebld_trail (item))
11548 {
11549 ffebld callee;
11550 ffesymbol s;
11551 tree dt;
11552 tree t;
11553 tree var;
11554 int yes;
11555 static int number = 0;
11556
11557 callee = ffebld_head (item);
11558 s = ffebld_symter (callee);
11559 t = ffesymbol_hook (s).decl_tree;
11560 if (t == NULL_TREE)
11561 {
11562 s = ffecom_sym_transform_ (s);
11563 t = ffesymbol_hook (s).decl_tree;
11564 }
11565
11566 yes = suspend_momentary ();
11567
11568 dt = build_pointer_type (TREE_TYPE (t));
11569
11570 var = build_decl (VAR_DECL,
11571 ffecom_get_invented_identifier ("__g77_forceload_%d",
11572 NULL, number++),
11573 dt);
11574 DECL_EXTERNAL (var) = 0;
11575 TREE_STATIC (var) = 1;
11576 TREE_PUBLIC (var) = 0;
11577 DECL_INITIAL (var) = error_mark_node;
11578 TREE_USED (var) = 1;
11579
11580 var = start_decl (var, FALSE);
11581
11582 t = ffecom_1 (ADDR_EXPR, dt, t);
11583
11584 finish_decl (var, t, FALSE);
11585
11586 resume_momentary (yes);
11587 }
11588
11589 /* This handles any COMMON areas that weren't referenced but have, for
11590 example, important initial data. */
11591
11592 for (item = ffecom_list_common_;
11593 item != NULL;
11594 item = ffebld_trail (item))
11595 ffecom_transform_common_ (ffebld_symter (ffebld_head (item)));
11596
11597 ffecom_list_common_ = NULL;
11598#endif
11599}
11600
11601/* ffecom_exec_transition -- Perform exec transition on all symbols
11602
11603 ffecom_exec_transition();
11604
11605 Calls ffecom_sym_exec_transition for each global and local symbol.
11606 Make sure error updating not inhibited. */
11607
11608void
11609ffecom_exec_transition ()
11610{
11611 bool inhibited;
11612
11613 if (ffe_is_ffedebug ())
11614 fprintf (dmpout, "; exec_stmt_transition\n");
11615
11616 inhibited = ffebad_inhibit ();
11617 ffebad_set_inhibit (FALSE);
11618
11619 ffesymbol_drive (ffecom_sym_exec_transition); /* Don't retract! */
11620 ffeequiv_exec_transition (); /* Handle all pending EQUIVALENCEs. */
11621 if (ffe_is_ffedebug ())
11622 {
11623 ffestorag_report ();
8b45da67 11624#if FFECOM_targetCURRENT == FFECOM_targetFFE
5ff904cd 11625 ffesymbol_report_all ();
8b45da67 11626#endif
5ff904cd
JL
11627 }
11628
11629 if (inhibited)
11630 ffebad_set_inhibit (TRUE);
11631}
11632
11633/* ffecom_expand_let_stmt -- Compile let (assignment) statement
11634
11635 ffebld dest;
11636 ffebld source;
11637 ffecom_expand_let_stmt(dest,source);
11638
11639 Convert dest and source using ffecom_expr, then join them
11640 with an ASSIGN op and pass the whole thing to expand_expr_stmt. */
11641
11642#if FFECOM_targetCURRENT == FFECOM_targetGCC
11643void
11644ffecom_expand_let_stmt (ffebld dest, ffebld source)
11645{
11646 tree dest_tree;
11647 tree dest_length;
11648 tree source_tree;
11649 tree expr_tree;
11650
11651 if (ffeinfo_basictype (ffebld_info (dest)) != FFEINFO_basictypeCHARACTER)
11652 {
11653 bool dest_used;
11654
11655 dest_tree = ffecom_expr_rw (dest);
11656 if (dest_tree == error_mark_node)
11657 return;
11658
11659 if ((TREE_CODE (dest_tree) != VAR_DECL)
11660 || TREE_ADDRESSABLE (dest_tree))
092a4ef8
RH
11661 source_tree = ffecom_expr_ (source, dest_tree, dest, &dest_used,
11662 FALSE, FALSE);
5ff904cd
JL
11663 else
11664 {
11665 source_tree = ffecom_expr (source);
11666 dest_used = FALSE;
11667 }
11668 if (source_tree == error_mark_node)
11669 return;
11670
11671 if (dest_used)
11672 expr_tree = source_tree;
11673 else
11674 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11675 dest_tree,
11676 source_tree);
11677
11678 expand_expr_stmt (expr_tree);
11679 return;
11680 }
11681
11682 ffecom_push_calltemps ();
11683 ffecom_char_args_ (&dest_tree, &dest_length, dest);
11684 ffecom_let_char_ (dest_tree, dest_length, ffebld_size_known (dest),
11685 source);
11686 ffecom_pop_calltemps ();
11687}
11688
11689#endif
11690/* ffecom_expr -- Transform expr into gcc tree
11691
11692 tree t;
11693 ffebld expr; // FFE expression.
11694 tree = ffecom_expr(expr);
11695
11696 Recursive descent on expr while making corresponding tree nodes and
11697 attaching type info and such. */
11698
11699#if FFECOM_targetCURRENT == FFECOM_targetGCC
11700tree
11701ffecom_expr (ffebld expr)
11702{
092a4ef8 11703 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, FALSE, FALSE);
5ff904cd
JL
11704}
11705
11706#endif
11707/* Like ffecom_expr, but return tree usable for assigned GOTO or FORMAT. */
11708
11709#if FFECOM_targetCURRENT == FFECOM_targetGCC
11710tree
11711ffecom_expr_assign (ffebld expr)
11712{
092a4ef8 11713 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
5ff904cd
JL
11714}
11715
11716#endif
11717/* Like ffecom_expr_rw, but return tree usable for ASSIGN. */
11718
11719#if FFECOM_targetCURRENT == FFECOM_targetGCC
11720tree
11721ffecom_expr_assign_w (ffebld expr)
11722{
092a4ef8 11723 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
5ff904cd
JL
11724}
11725
11726#endif
11727/* Transform expr for use as into read/write tree and stabilize the
11728 reference. Not for use on CHARACTER expressions.
11729
11730 Recursive descent on expr while making corresponding tree nodes and
11731 attaching type info and such. */
11732
11733#if FFECOM_targetCURRENT == FFECOM_targetGCC
11734tree
11735ffecom_expr_rw (ffebld expr)
11736{
11737 assert (expr != NULL);
11738
11739 return stabilize_reference (ffecom_expr (expr));
11740}
11741
11742#endif
11743/* Do global stuff. */
11744
11745#if FFECOM_targetCURRENT == FFECOM_targetGCC
11746void
11747ffecom_finish_compile ()
11748{
11749 assert (ffecom_outer_function_decl_ == NULL_TREE);
11750 assert (current_function_decl == NULL_TREE);
11751
11752 ffeglobal_drive (ffecom_finish_global_);
11753}
11754
11755#endif
11756/* Public entry point for front end to access finish_decl. */
11757
11758#if FFECOM_targetCURRENT == FFECOM_targetGCC
11759void
11760ffecom_finish_decl (tree decl, tree init, bool is_top_level)
11761{
11762 assert (!is_top_level);
11763 finish_decl (decl, init, FALSE);
11764}
11765
11766#endif
11767/* Finish a program unit. */
11768
11769#if FFECOM_targetCURRENT == FFECOM_targetGCC
11770void
11771ffecom_finish_progunit ()
11772{
11773 ffecom_end_compstmt_ ();
11774
11775 ffecom_previous_function_decl_ = current_function_decl;
11776 ffecom_which_entrypoint_decl_ = NULL_TREE;
11777
11778 finish_function (0);
11779}
11780
11781#endif
11782/* Wrapper for get_identifier. pattern is like "...%s...", text is
11783 inserted into final name in place of "%s", or if text is NULL,
11784 pattern is like "...%d..." and text form of number is inserted
11785 in place of "%d". */
11786
11787#if FFECOM_targetCURRENT == FFECOM_targetGCC
11788tree
11789ffecom_get_invented_identifier (char *pattern, char *text, int number)
11790{
11791 tree decl;
11792 char *nam;
11793 mallocSize lenlen;
11794 char space[66];
11795
11796 if (text == NULL)
11797 lenlen = strlen (pattern) + 20;
11798 else
11799 lenlen = strlen (pattern) + strlen (text) - 1;
11800 if (lenlen > ARRAY_SIZE (space))
11801 nam = malloc_new_ks (malloc_pool_image (), pattern, lenlen);
11802 else
11803 nam = &space[0];
11804 if (text == NULL)
11805 sprintf (&nam[0], pattern, number);
11806 else
11807 sprintf (&nam[0], pattern, text);
11808 decl = get_identifier (nam);
11809 if (lenlen > ARRAY_SIZE (space))
11810 malloc_kill_ks (malloc_pool_image (), nam, lenlen);
11811
11812 IDENTIFIER_INVENTED (decl) = 1;
11813
11814 return decl;
11815}
11816
11817ffeinfoBasictype
11818ffecom_gfrt_basictype (ffecomGfrt gfrt)
11819{
11820 assert (gfrt < FFECOM_gfrt);
11821
11822 switch (ffecom_gfrt_type_[gfrt])
11823 {
11824 case FFECOM_rttypeVOID_:
6d433196 11825 case FFECOM_rttypeVOIDSTAR_:
5ff904cd
JL
11826 return FFEINFO_basictypeNONE;
11827
795232f7 11828 case FFECOM_rttypeFTNINT_:
5ff904cd
JL
11829 return FFEINFO_basictypeINTEGER;
11830
11831 case FFECOM_rttypeINTEGER_:
11832 return FFEINFO_basictypeINTEGER;
11833
11834 case FFECOM_rttypeLONGINT_:
11835 return FFEINFO_basictypeINTEGER;
11836
11837 case FFECOM_rttypeLOGICAL_:
11838 return FFEINFO_basictypeLOGICAL;
11839
11840 case FFECOM_rttypeREAL_F2C_:
11841 case FFECOM_rttypeREAL_GNU_:
11842 return FFEINFO_basictypeREAL;
11843
11844 case FFECOM_rttypeCOMPLEX_F2C_:
11845 case FFECOM_rttypeCOMPLEX_GNU_:
11846 return FFEINFO_basictypeCOMPLEX;
11847
11848 case FFECOM_rttypeDOUBLE_:
795232f7 11849 case FFECOM_rttypeDOUBLEREAL_:
5ff904cd
JL
11850 return FFEINFO_basictypeREAL;
11851
11852 case FFECOM_rttypeDBLCMPLX_F2C_:
11853 case FFECOM_rttypeDBLCMPLX_GNU_:
11854 return FFEINFO_basictypeCOMPLEX;
11855
11856 case FFECOM_rttypeCHARACTER_:
11857 return FFEINFO_basictypeCHARACTER;
11858
11859 default:
11860 return FFEINFO_basictypeANY;
11861 }
11862}
11863
11864ffeinfoKindtype
11865ffecom_gfrt_kindtype (ffecomGfrt gfrt)
11866{
11867 assert (gfrt < FFECOM_gfrt);
11868
11869 switch (ffecom_gfrt_type_[gfrt])
11870 {
11871 case FFECOM_rttypeVOID_:
6d433196 11872 case FFECOM_rttypeVOIDSTAR_:
5ff904cd
JL
11873 return FFEINFO_kindtypeNONE;
11874
795232f7 11875 case FFECOM_rttypeFTNINT_:
5ff904cd
JL
11876 return FFEINFO_kindtypeINTEGER1;
11877
11878 case FFECOM_rttypeINTEGER_:
11879 return FFEINFO_kindtypeINTEGER1;
11880
11881 case FFECOM_rttypeLONGINT_:
11882 return FFEINFO_kindtypeINTEGER4;
11883
11884 case FFECOM_rttypeLOGICAL_:
11885 return FFEINFO_kindtypeLOGICAL1;
11886
11887 case FFECOM_rttypeREAL_F2C_:
11888 case FFECOM_rttypeREAL_GNU_:
11889 return FFEINFO_kindtypeREAL1;
11890
11891 case FFECOM_rttypeCOMPLEX_F2C_:
11892 case FFECOM_rttypeCOMPLEX_GNU_:
11893 return FFEINFO_kindtypeREAL1;
11894
11895 case FFECOM_rttypeDOUBLE_:
795232f7 11896 case FFECOM_rttypeDOUBLEREAL_:
5ff904cd
JL
11897 return FFEINFO_kindtypeREAL2;
11898
11899 case FFECOM_rttypeDBLCMPLX_F2C_:
11900 case FFECOM_rttypeDBLCMPLX_GNU_:
11901 return FFEINFO_kindtypeREAL2;
11902
11903 case FFECOM_rttypeCHARACTER_:
11904 return FFEINFO_kindtypeCHARACTER1;
11905
11906 default:
11907 return FFEINFO_kindtypeANY;
11908 }
11909}
11910
11911void
11912ffecom_init_0 ()
11913{
11914 tree endlink;
11915 int i;
11916 int j;
11917 tree t;
11918 tree field;
11919 ffetype type;
11920 ffetype base_type;
11921
11922 /* This block of code comes from the now-obsolete cktyps.c. It checks
11923 whether the compiler environment is buggy in known ways, some of which
11924 would, if not explicitly checked here, result in subtle bugs in g77. */
11925
11926 if (ffe_is_do_internal_checks ())
11927 {
11928 static char names[][12]
11929 =
11930 {"bar", "bletch", "foo", "foobar"};
11931 char *name;
11932 unsigned long ul;
11933 double fl;
11934
11935 name = bsearch ("foo", &names[0], ARRAY_SIZE (names), sizeof (names[0]),
11936 (int (*)()) strcmp);
11937 if (name != (char *) &names[2])
11938 {
11939 assert ("bsearch doesn't work, #define FFEPROJ_BSEARCH 0 in proj.h"
11940 == NULL);
11941 abort ();
11942 }
11943
11944 ul = strtoul ("123456789", NULL, 10);
11945 if (ul != 123456789L)
11946 {
11947 assert ("strtoul doesn't have enough range, #define FFEPROJ_STRTOUL 0\
11948 in proj.h" == NULL);
11949 abort ();
11950 }
11951
11952 fl = atof ("56.789");
11953 if ((fl < 56.788) || (fl > 56.79))
11954 {
11955 assert ("atof not type double, fix your #include <stdio.h>"
11956 == NULL);
11957 abort ();
11958 }
11959 }
11960
092a4ef8
RH
11961 /* Set the sizetype before we do anything else. This _should_ be the
11962 first type we create. */
11963
11964 t = make_unsigned_type (POINTER_SIZE);
11965 assert (t == sizetype);
11966
5ff904cd
JL
11967#if FFECOM_GCC_INCLUDE
11968 ffecom_initialize_char_syntax_ ();
11969#endif
11970
11971 ffecom_outer_function_decl_ = NULL_TREE;
11972 current_function_decl = NULL_TREE;
11973 named_labels = NULL_TREE;
11974 current_binding_level = NULL_BINDING_LEVEL;
11975 free_binding_level = NULL_BINDING_LEVEL;
11976 pushlevel (0); /* make the binding_level structure for
11977 global names */
11978 global_binding_level = current_binding_level;
11979
11980 /* Define `int' and `char' first so that dbx will output them first. */
11981
11982 integer_type_node = make_signed_type (INT_TYPE_SIZE);
11983 pushdecl (build_decl (TYPE_DECL, get_identifier ("int"),
11984 integer_type_node));
11985
11986 char_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
11987 pushdecl (build_decl (TYPE_DECL, get_identifier ("char"),
11988 char_type_node));
11989
11990 long_integer_type_node = make_signed_type (LONG_TYPE_SIZE);
11991 pushdecl (build_decl (TYPE_DECL, get_identifier ("long int"),
11992 long_integer_type_node));
11993
11994 unsigned_type_node = make_unsigned_type (INT_TYPE_SIZE);
11995 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned int"),
11996 unsigned_type_node));
11997
11998 long_unsigned_type_node = make_unsigned_type (LONG_TYPE_SIZE);
11999 pushdecl (build_decl (TYPE_DECL, get_identifier ("long unsigned int"),
12000 long_unsigned_type_node));
12001
12002 long_long_integer_type_node = make_signed_type (LONG_LONG_TYPE_SIZE);
12003 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long int"),
12004 long_long_integer_type_node));
12005
12006 long_long_unsigned_type_node = make_unsigned_type (LONG_LONG_TYPE_SIZE);
12007 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"),
12008 long_long_unsigned_type_node));
12009
5ff904cd
JL
12010 error_mark_node = make_node (ERROR_MARK);
12011 TREE_TYPE (error_mark_node) = error_mark_node;
12012
12013 short_integer_type_node = make_signed_type (SHORT_TYPE_SIZE);
12014 pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"),
12015 short_integer_type_node));
12016
12017 short_unsigned_type_node = make_unsigned_type (SHORT_TYPE_SIZE);
12018 pushdecl (build_decl (TYPE_DECL, get_identifier ("short unsigned int"),
12019 short_unsigned_type_node));
12020
12021 /* Define both `signed char' and `unsigned char'. */
12022 signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE);
12023 pushdecl (build_decl (TYPE_DECL, get_identifier ("signed char"),
12024 signed_char_type_node));
12025
12026 unsigned_char_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
12027 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned char"),
12028 unsigned_char_type_node));
12029
12030 float_type_node = make_node (REAL_TYPE);
12031 TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE;
12032 layout_type (float_type_node);
12033 pushdecl (build_decl (TYPE_DECL, get_identifier ("float"),
12034 float_type_node));
12035
12036 double_type_node = make_node (REAL_TYPE);
12037 TYPE_PRECISION (double_type_node) = DOUBLE_TYPE_SIZE;
12038 layout_type (double_type_node);
12039 pushdecl (build_decl (TYPE_DECL, get_identifier ("double"),
12040 double_type_node));
12041
12042 long_double_type_node = make_node (REAL_TYPE);
12043 TYPE_PRECISION (long_double_type_node) = LONG_DOUBLE_TYPE_SIZE;
12044 layout_type (long_double_type_node);
12045 pushdecl (build_decl (TYPE_DECL, get_identifier ("long double"),
12046 long_double_type_node));
12047
12048 complex_integer_type_node = ffecom_make_complex_type_ (integer_type_node);
12049 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"),
12050 complex_integer_type_node));
12051
12052 complex_float_type_node = ffecom_make_complex_type_ (float_type_node);
12053 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"),
12054 complex_float_type_node));
12055
12056 complex_double_type_node = ffecom_make_complex_type_ (double_type_node);
12057 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"),
12058 complex_double_type_node));
12059
12060 complex_long_double_type_node = ffecom_make_complex_type_ (long_double_type_node);
12061 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"),
12062 complex_long_double_type_node));
12063
12064 integer_zero_node = build_int_2 (0, 0);
12065 TREE_TYPE (integer_zero_node) = integer_type_node;
12066 integer_one_node = build_int_2 (1, 0);
12067 TREE_TYPE (integer_one_node) = integer_type_node;
12068
12069 size_zero_node = build_int_2 (0, 0);
12070 TREE_TYPE (size_zero_node) = sizetype;
12071 size_one_node = build_int_2 (1, 0);
12072 TREE_TYPE (size_one_node) = sizetype;
12073
12074 void_type_node = make_node (VOID_TYPE);
12075 pushdecl (build_decl (TYPE_DECL, get_identifier ("void"),
12076 void_type_node));
12077 layout_type (void_type_node); /* Uses integer_zero_node */
12078 /* We are not going to have real types in C with less than byte alignment,
12079 so we might as well not have any types that claim to have it. */
12080 TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
12081
12082 null_pointer_node = build_int_2 (0, 0);
12083 TREE_TYPE (null_pointer_node) = build_pointer_type (void_type_node);
12084 layout_type (TREE_TYPE (null_pointer_node));
12085
12086 string_type_node = build_pointer_type (char_type_node);
12087
12088 ffecom_tree_fun_type_void
12089 = build_function_type (void_type_node, NULL_TREE);
12090
12091 ffecom_tree_ptr_to_fun_type_void
12092 = build_pointer_type (ffecom_tree_fun_type_void);
12093
12094 endlink = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
12095
12096 float_ftype_float
12097 = build_function_type (float_type_node,
12098 tree_cons (NULL_TREE, float_type_node, endlink));
12099
12100 double_ftype_double
12101 = build_function_type (double_type_node,
12102 tree_cons (NULL_TREE, double_type_node, endlink));
12103
12104 ldouble_ftype_ldouble
12105 = build_function_type (long_double_type_node,
12106 tree_cons (NULL_TREE, long_double_type_node,
12107 endlink));
12108
12109 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
12110 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
12111 {
12112 ffecom_tree_type[i][j] = NULL_TREE;
12113 ffecom_tree_fun_type[i][j] = NULL_TREE;
12114 ffecom_tree_ptr_to_fun_type[i][j] = NULL_TREE;
12115 ffecom_f2c_typecode_[i][j] = -1;
12116 }
12117
12118 /* Set up standard g77 types. Note that INTEGER and LOGICAL are set
12119 to size FLOAT_TYPE_SIZE because they have to be the same size as
12120 REAL, which also is FLOAT_TYPE_SIZE, according to the standard.
12121 Compiler options and other such stuff that change the ways these
12122 types are set should not affect this particular setup. */
12123
12124 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1]
12125 = t = make_signed_type (FLOAT_TYPE_SIZE);
12126 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer"),
12127 t));
12128 type = ffetype_new ();
12129 base_type = type;
12130 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER1,
12131 type);
12132 ffetype_set_ams (type,
12133 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12134 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12135 ffetype_set_star (base_type,
12136 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12137 type);
12138 ffetype_set_kind (base_type, 1, type);
12139 assert (ffetype_size (type) == sizeof (ffetargetInteger1));
12140
12141 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER1]
12142 = t = make_unsigned_type (FLOAT_TYPE_SIZE); /* HOLLERITH means unsigned. */
12143 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned"),
12144 t));
12145
12146 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER2]
12147 = t = make_signed_type (CHAR_TYPE_SIZE);
12148 pushdecl (build_decl (TYPE_DECL, get_identifier ("byte"),
12149 t));
12150 type = ffetype_new ();
12151 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER2,
12152 type);
12153 ffetype_set_ams (type,
12154 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12155 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12156 ffetype_set_star (base_type,
12157 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12158 type);
12159 ffetype_set_kind (base_type, 3, type);
12160 assert (ffetype_size (type) == sizeof (ffetargetInteger2));
12161
12162 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER2]
12163 = t = make_unsigned_type (CHAR_TYPE_SIZE);
12164 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned byte"),
12165 t));
12166
12167 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER3]
12168 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
12169 pushdecl (build_decl (TYPE_DECL, get_identifier ("word"),
12170 t));
12171 type = ffetype_new ();
12172 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER3,
12173 type);
12174 ffetype_set_ams (type,
12175 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12176 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12177 ffetype_set_star (base_type,
12178 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12179 type);
12180 ffetype_set_kind (base_type, 6, type);
12181 assert (ffetype_size (type) == sizeof (ffetargetInteger3));
12182
12183 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER3]
12184 = t = make_unsigned_type (CHAR_TYPE_SIZE * 2);
12185 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned word"),
12186 t));
12187
12188 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER4]
12189 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
12190 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer4"),
12191 t));
12192 type = ffetype_new ();
12193 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER4,
12194 type);
12195 ffetype_set_ams (type,
12196 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12197 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12198 ffetype_set_star (base_type,
12199 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12200 type);
12201 ffetype_set_kind (base_type, 2, type);
12202 assert (ffetype_size (type) == sizeof (ffetargetInteger4));
12203
12204 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER4]
12205 = t = make_unsigned_type (FLOAT_TYPE_SIZE * 2);
12206 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned4"),
12207 t));
12208
12209#if 0
12210 if (ffe_is_do_internal_checks ()
12211 && LONG_TYPE_SIZE != FLOAT_TYPE_SIZE
12212 && LONG_TYPE_SIZE != CHAR_TYPE_SIZE
12213 && LONG_TYPE_SIZE != SHORT_TYPE_SIZE
12214 && LONG_TYPE_SIZE != LONG_LONG_TYPE_SIZE)
12215 {
12216 fprintf (stderr, "Sorry, no g77 support for LONG_TYPE_SIZE (%d bits) yet.\n",
12217 LONG_TYPE_SIZE);
12218 }
12219#endif
12220
12221 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL1]
12222 = t = make_signed_type (FLOAT_TYPE_SIZE);
12223 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical"),
12224 t));
12225 type = ffetype_new ();
12226 base_type = type;
12227 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL1,
12228 type);
12229 ffetype_set_ams (type,
12230 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12231 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12232 ffetype_set_star (base_type,
12233 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12234 type);
12235 ffetype_set_kind (base_type, 1, type);
12236 assert (ffetype_size (type) == sizeof (ffetargetLogical1));
12237
12238 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL2]
12239 = t = make_signed_type (CHAR_TYPE_SIZE);
12240 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical2"),
12241 t));
12242 type = ffetype_new ();
12243 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL2,
12244 type);
12245 ffetype_set_ams (type,
12246 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12247 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12248 ffetype_set_star (base_type,
12249 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12250 type);
12251 ffetype_set_kind (base_type, 3, type);
12252 assert (ffetype_size (type) == sizeof (ffetargetLogical2));
12253
12254 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL3]
12255 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
12256 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical3"),
12257 t));
12258 type = ffetype_new ();
12259 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL3,
12260 type);
12261 ffetype_set_ams (type,
12262 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12263 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12264 ffetype_set_star (base_type,
12265 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12266 type);
12267 ffetype_set_kind (base_type, 6, type);
12268 assert (ffetype_size (type) == sizeof (ffetargetLogical3));
12269
12270 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL4]
12271 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
12272 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical4"),
12273 t));
12274 type = ffetype_new ();
12275 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL4,
12276 type);
12277 ffetype_set_ams (type,
12278 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12279 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12280 ffetype_set_star (base_type,
12281 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12282 type);
12283 ffetype_set_kind (base_type, 2, type);
12284 assert (ffetype_size (type) == sizeof (ffetargetLogical4));
12285
12286 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
12287 = t = make_node (REAL_TYPE);
12288 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE;
12289 pushdecl (build_decl (TYPE_DECL, get_identifier ("real"),
12290 t));
12291 layout_type (t);
12292 type = ffetype_new ();
12293 base_type = type;
12294 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREAL1,
12295 type);
12296 ffetype_set_ams (type,
12297 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12298 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12299 ffetype_set_star (base_type,
12300 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12301 type);
12302 ffetype_set_kind (base_type, 1, type);
12303 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
12304 = FFETARGET_f2cTYREAL;
12305 assert (ffetype_size (type) == sizeof (ffetargetReal1));
12306
12307 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREALDOUBLE]
12308 = t = make_node (REAL_TYPE);
12309 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE * 2; /* Always twice REAL. */
12310 pushdecl (build_decl (TYPE_DECL, get_identifier ("double precision"),
12311 t));
12312 layout_type (t);
12313 type = ffetype_new ();
12314 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREALDOUBLE,
12315 type);
12316 ffetype_set_ams (type,
12317 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12318 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12319 ffetype_set_star (base_type,
12320 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12321 type);
12322 ffetype_set_kind (base_type, 2, type);
12323 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]
12324 = FFETARGET_f2cTYDREAL;
12325 assert (ffetype_size (type) == sizeof (ffetargetReal2));
12326
12327 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
12328 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]);
12329 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex"),
12330 t));
12331 type = ffetype_new ();
12332 base_type = type;
12333 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREAL1,
12334 type);
12335 ffetype_set_ams (type,
12336 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12337 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12338 ffetype_set_star (base_type,
12339 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12340 type);
12341 ffetype_set_kind (base_type, 1, type);
12342 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
12343 = FFETARGET_f2cTYCOMPLEX;
12344 assert (ffetype_size (type) == sizeof (ffetargetComplex1));
12345
12346 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREALDOUBLE]
12347 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]);
12348 pushdecl (build_decl (TYPE_DECL, get_identifier ("double complex"),
12349 t));
12350 type = ffetype_new ();
12351 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREALDOUBLE,
12352 type);
12353 ffetype_set_ams (type,
12354 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12355 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12356 ffetype_set_star (base_type,
12357 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12358 type);
12359 ffetype_set_kind (base_type, 2,
12360 type);
12361 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL2]
12362 = FFETARGET_f2cTYDCOMPLEX;
12363 assert (ffetype_size (type) == sizeof (ffetargetComplex2));
12364
12365 /* Make function and ptr-to-function types for non-CHARACTER types. */
12366
12367 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
12368 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
12369 {
12370 if ((t = ffecom_tree_type[i][j]) != NULL_TREE)
12371 {
12372 if (i == FFEINFO_basictypeINTEGER)
12373 {
12374 /* Figure out the smallest INTEGER type that can hold
12375 a pointer on this machine. */
12376 if (GET_MODE_SIZE (TYPE_MODE (t))
12377 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
12378 {
12379 if ((ffecom_pointer_kind_ == FFEINFO_kindtypeNONE)
12380 || (GET_MODE_SIZE (TYPE_MODE (ffecom_tree_type[i][ffecom_pointer_kind_]))
12381 > GET_MODE_SIZE (TYPE_MODE (t))))
12382 ffecom_pointer_kind_ = j;
12383 }
12384 }
12385 else if (i == FFEINFO_basictypeCOMPLEX)
12386 t = void_type_node;
12387 /* For f2c compatibility, REAL functions are really
12388 implemented as DOUBLE PRECISION. */
12389 else if ((i == FFEINFO_basictypeREAL)
12390 && (j == FFEINFO_kindtypeREAL1))
12391 t = ffecom_tree_type
12392 [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2];
12393
12394 t = ffecom_tree_fun_type[i][j] = build_function_type (t,
12395 NULL_TREE);
12396 ffecom_tree_ptr_to_fun_type[i][j] = build_pointer_type (t);
12397 }
12398 }
12399
12400 /* Set up pointer types. */
12401
12402 if (ffecom_pointer_kind_ == FFEINFO_basictypeNONE)
12403 fatal ("no INTEGER type can hold a pointer on this configuration");
12404 else if (0 && ffe_is_do_internal_checks ())
12405 fprintf (stderr, "Pointer type kt=%d\n", ffecom_pointer_kind_);
5ff904cd
JL
12406 ffetype_set_kind (ffeinfo_type (FFEINFO_basictypeINTEGER,
12407 FFEINFO_kindtypeINTEGERDEFAULT),
a835e351
CB
12408 7,
12409 ffeinfo_type (FFEINFO_basictypeINTEGER,
12410 ffecom_pointer_kind_));
5ff904cd
JL
12411
12412 if (ffe_is_ugly_assign ())
12413 ffecom_label_kind_ = ffecom_pointer_kind_; /* Require ASSIGN etc to this. */
12414 else
12415 ffecom_label_kind_ = FFEINFO_kindtypeINTEGERDEFAULT;
12416 if (0 && ffe_is_do_internal_checks ())
12417 fprintf (stderr, "Label type kt=%d\n", ffecom_label_kind_);
12418
12419 ffecom_integer_type_node
12420 = ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1];
12421 ffecom_integer_zero_node = convert (ffecom_integer_type_node,
12422 integer_zero_node);
12423 ffecom_integer_one_node = convert (ffecom_integer_type_node,
12424 integer_one_node);
12425
12426 /* Yes, the "FLOAT_TYPE_SIZE" references below are intentional.
12427 Turns out that by TYLONG, runtime/libI77/lio.h really means
12428 "whatever size an ftnint is". For consistency and sanity,
12429 com.h and runtime/f2c.h.in agree that flag, ftnint, and ftlen
12430 all are INTEGER, which we also make out of whatever back-end
12431 integer type is FLOAT_TYPE_SIZE bits wide. This change, from
12432 LONG_TYPE_SIZE, for TYLONG and TYLOGICAL, was necessary to
12433 accommodate machines like the Alpha. Note that this suggests
12434 f2c and libf2c are missing a distinction perhaps needed on
12435 some machines between "int" and "long int". -- burley 0.5.5 950215 */
12436
12437 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, FLOAT_TYPE_SIZE,
12438 FFETARGET_f2cTYLONG);
12439 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, SHORT_TYPE_SIZE,
12440 FFETARGET_f2cTYSHORT);
12441 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, CHAR_TYPE_SIZE,
12442 FFETARGET_f2cTYINT1);
12443 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, LONG_LONG_TYPE_SIZE,
12444 FFETARGET_f2cTYQUAD);
12445 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, FLOAT_TYPE_SIZE,
12446 FFETARGET_f2cTYLOGICAL);
12447 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, SHORT_TYPE_SIZE,
12448 FFETARGET_f2cTYLOGICAL2);
12449 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, CHAR_TYPE_SIZE,
12450 FFETARGET_f2cTYLOGICAL1);
12451 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, LONG_LONG_TYPE_SIZE,
12452 FFETARGET_f2cTYQUAD /* ~~~ */);
12453
12454 /* CHARACTER stuff is all special-cased, so it is not handled in the above
12455 loop. CHARACTER items are built as arrays of unsigned char. */
12456
12457 ffecom_tree_type[FFEINFO_basictypeCHARACTER]
12458 [FFEINFO_kindtypeCHARACTER1] = t = char_type_node;
12459 type = ffetype_new ();
12460 base_type = type;
12461 ffeinfo_set_type (FFEINFO_basictypeCHARACTER,
12462 FFEINFO_kindtypeCHARACTER1,
12463 type);
12464 ffetype_set_ams (type,
12465 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12466 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12467 ffetype_set_kind (base_type, 1, type);
12468 assert (ffetype_size (type)
12469 == sizeof (((ffetargetCharacter1) { 0, NULL }).text[0]));
12470
12471 ffecom_tree_fun_type[FFEINFO_basictypeCHARACTER]
12472 [FFEINFO_kindtypeCHARACTER1] = ffecom_tree_fun_type_void;
12473 ffecom_tree_ptr_to_fun_type[FFEINFO_basictypeCHARACTER]
12474 [FFEINFO_kindtypeCHARACTER1]
12475 = ffecom_tree_ptr_to_fun_type_void;
12476 ffecom_f2c_typecode_[FFEINFO_basictypeCHARACTER][FFEINFO_kindtypeCHARACTER1]
12477 = FFETARGET_f2cTYCHAR;
12478
12479 ffecom_f2c_typecode_[FFEINFO_basictypeANY][FFEINFO_kindtypeANY]
12480 = 0;
12481
12482 /* Make multi-return-value type and fields. */
12483
12484 ffecom_multi_type_node_ = make_node (UNION_TYPE);
12485
12486 field = NULL_TREE;
12487
12488 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
12489 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
12490 {
12491 char name[30];
12492
12493 if (ffecom_tree_type[i][j] == NULL_TREE)
12494 continue; /* Not supported. */
12495 sprintf (&name[0], "bt_%s_kt_%s",
12496 ffeinfo_basictype_string ((ffeinfoBasictype) i),
12497 ffeinfo_kindtype_string ((ffeinfoKindtype) j));
12498 ffecom_multi_fields_[i][j] = build_decl (FIELD_DECL,
12499 get_identifier (name),
12500 ffecom_tree_type[i][j]);
12501 DECL_CONTEXT (ffecom_multi_fields_[i][j])
12502 = ffecom_multi_type_node_;
12503 DECL_FRAME_SIZE (ffecom_multi_fields_[i][j]) = 0;
12504 TREE_CHAIN (ffecom_multi_fields_[i][j]) = field;
12505 field = ffecom_multi_fields_[i][j];
12506 }
12507
12508 TYPE_FIELDS (ffecom_multi_type_node_) = field;
12509 layout_type (ffecom_multi_type_node_);
12510
12511 /* Subroutines usually return integer because they might have alternate
12512 returns. */
12513
12514 ffecom_tree_subr_type
12515 = build_function_type (integer_type_node, NULL_TREE);
12516 ffecom_tree_ptr_to_subr_type
12517 = build_pointer_type (ffecom_tree_subr_type);
12518 ffecom_tree_blockdata_type
12519 = build_function_type (void_type_node, NULL_TREE);
12520
12521 builtin_function ("__builtin_sqrtf", float_ftype_float,
12522 BUILT_IN_FSQRT, "sqrtf");
12523 builtin_function ("__builtin_fsqrt", double_ftype_double,
12524 BUILT_IN_FSQRT, "sqrt");
12525 builtin_function ("__builtin_sqrtl", ldouble_ftype_ldouble,
12526 BUILT_IN_FSQRT, "sqrtl");
12527 builtin_function ("__builtin_sinf", float_ftype_float,
12528 BUILT_IN_SIN, "sinf");
12529 builtin_function ("__builtin_sin", double_ftype_double,
12530 BUILT_IN_SIN, "sin");
12531 builtin_function ("__builtin_sinl", ldouble_ftype_ldouble,
12532 BUILT_IN_SIN, "sinl");
12533 builtin_function ("__builtin_cosf", float_ftype_float,
12534 BUILT_IN_COS, "cosf");
12535 builtin_function ("__builtin_cos", double_ftype_double,
12536 BUILT_IN_COS, "cos");
12537 builtin_function ("__builtin_cosl", ldouble_ftype_ldouble,
12538 BUILT_IN_COS, "cosl");
12539
12540#if BUILT_FOR_270
12541 pedantic_lvalues = FALSE;
12542#endif
12543
12544 ffecom_f2c_make_type_ (&ffecom_f2c_integer_type_node,
12545 FFECOM_f2cINTEGER,
12546 "integer");
12547 ffecom_f2c_make_type_ (&ffecom_f2c_address_type_node,
12548 FFECOM_f2cADDRESS,
12549 "address");
12550 ffecom_f2c_make_type_ (&ffecom_f2c_real_type_node,
12551 FFECOM_f2cREAL,
12552 "real");
12553 ffecom_f2c_make_type_ (&ffecom_f2c_doublereal_type_node,
12554 FFECOM_f2cDOUBLEREAL,
12555 "doublereal");
12556 ffecom_f2c_make_type_ (&ffecom_f2c_complex_type_node,
12557 FFECOM_f2cCOMPLEX,
12558 "complex");
12559 ffecom_f2c_make_type_ (&ffecom_f2c_doublecomplex_type_node,
12560 FFECOM_f2cDOUBLECOMPLEX,
12561 "doublecomplex");
12562 ffecom_f2c_make_type_ (&ffecom_f2c_longint_type_node,
12563 FFECOM_f2cLONGINT,
12564 "longint");
12565 ffecom_f2c_make_type_ (&ffecom_f2c_logical_type_node,
12566 FFECOM_f2cLOGICAL,
12567 "logical");
12568 ffecom_f2c_make_type_ (&ffecom_f2c_flag_type_node,
12569 FFECOM_f2cFLAG,
12570 "flag");
12571 ffecom_f2c_make_type_ (&ffecom_f2c_ftnlen_type_node,
12572 FFECOM_f2cFTNLEN,
12573 "ftnlen");
12574 ffecom_f2c_make_type_ (&ffecom_f2c_ftnint_type_node,
12575 FFECOM_f2cFTNINT,
12576 "ftnint");
12577
12578 ffecom_f2c_ftnlen_zero_node
12579 = convert (ffecom_f2c_ftnlen_type_node, integer_zero_node);
12580
12581 ffecom_f2c_ftnlen_one_node
12582 = convert (ffecom_f2c_ftnlen_type_node, integer_one_node);
12583
12584 ffecom_f2c_ftnlen_two_node = build_int_2 (2, 0);
12585 TREE_TYPE (ffecom_f2c_ftnlen_two_node) = ffecom_integer_type_node;
12586
12587 ffecom_f2c_ptr_to_ftnlen_type_node
12588 = build_pointer_type (ffecom_f2c_ftnlen_type_node);
12589
12590 ffecom_f2c_ptr_to_ftnint_type_node
12591 = build_pointer_type (ffecom_f2c_ftnint_type_node);
12592
12593 ffecom_f2c_ptr_to_integer_type_node
12594 = build_pointer_type (ffecom_f2c_integer_type_node);
12595
12596 ffecom_f2c_ptr_to_real_type_node
12597 = build_pointer_type (ffecom_f2c_real_type_node);
12598
12599 ffecom_float_zero_ = build_real (float_type_node, dconst0);
12600 ffecom_double_zero_ = build_real (double_type_node, dconst0);
12601 {
12602 REAL_VALUE_TYPE point_5;
12603
12604#ifdef REAL_ARITHMETIC
12605 REAL_ARITHMETIC (point_5, RDIV_EXPR, dconst1, dconst2);
12606#else
12607 point_5 = .5;
12608#endif
12609 ffecom_float_half_ = build_real (float_type_node, point_5);
12610 ffecom_double_half_ = build_real (double_type_node, point_5);
12611 }
12612
12613 /* Do "extern int xargc;". */
12614
12615 ffecom_tree_xargc_ = build_decl (VAR_DECL,
1ed565d7 12616 get_identifier ("f__xargc"),
5ff904cd
JL
12617 integer_type_node);
12618 DECL_EXTERNAL (ffecom_tree_xargc_) = 1;
12619 TREE_STATIC (ffecom_tree_xargc_) = 1;
12620 TREE_PUBLIC (ffecom_tree_xargc_) = 1;
12621 ffecom_tree_xargc_ = start_decl (ffecom_tree_xargc_, FALSE);
12622 finish_decl (ffecom_tree_xargc_, NULL_TREE, FALSE);
12623
12624#if 0 /* This is being fixed, and seems to be working now. */
12625 if ((FLOAT_TYPE_SIZE != 32)
12626 || (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))) != 32))
12627 {
12628 warning ("configuration: REAL, INTEGER, and LOGICAL are %d bits wide,",
12629 (int) FLOAT_TYPE_SIZE);
12630 warning ("and pointers are %d bits wide, but g77 doesn't yet work",
12631 (int) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))));
12632 warning ("properly unless they all are 32 bits wide.");
12633 warning ("Please keep this in mind before you report bugs. g77 should");
12634 warning ("support non-32-bit machines better as of version 0.6.");
12635 }
12636#endif
12637
12638#if 0 /* Code in ste.c that would crash has been commented out. */
12639 if (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
12640 < TYPE_PRECISION (string_type_node))
12641 /* I/O will probably crash. */
12642 warning ("configuration: char * holds %d bits, but ftnlen only %d",
12643 TYPE_PRECISION (string_type_node),
12644 TYPE_PRECISION (ffecom_f2c_ftnlen_type_node));
12645#endif
12646
12647#if 0 /* ASSIGN-related stuff has been changed to accommodate this. */
12648 if (TYPE_PRECISION (ffecom_integer_type_node)
12649 < TYPE_PRECISION (string_type_node))
12650 /* ASSIGN 10 TO I will crash. */
12651 warning ("configuration: char * holds %d bits, but INTEGER only %d --\n\
12652 ASSIGN statement might fail",
12653 TYPE_PRECISION (string_type_node),
12654 TYPE_PRECISION (ffecom_integer_type_node));
12655#endif
12656}
12657
12658#endif
12659/* ffecom_init_2 -- Initialize
12660
12661 ffecom_init_2(); */
12662
12663#if FFECOM_targetCURRENT == FFECOM_targetGCC
12664void
12665ffecom_init_2 ()
12666{
12667 assert (ffecom_outer_function_decl_ == NULL_TREE);
12668 assert (current_function_decl == NULL_TREE);
12669 assert (ffecom_which_entrypoint_decl_ == NULL_TREE);
12670
12671 ffecom_master_arglist_ = NULL;
12672 ++ffecom_num_fns_;
12673 ffecom_latest_temp_ = NULL;
12674 ffecom_primary_entry_ = NULL;
12675 ffecom_is_altreturning_ = FALSE;
12676 ffecom_func_result_ = NULL_TREE;
12677 ffecom_multi_retval_ = NULL_TREE;
12678}
12679
12680#endif
12681/* ffecom_list_expr -- Transform list of exprs into gcc tree
12682
12683 tree t;
12684 ffebld expr; // FFE opITEM list.
12685 tree = ffecom_list_expr(expr);
12686
12687 List of actual args is transformed into corresponding gcc backend list. */
12688
12689#if FFECOM_targetCURRENT == FFECOM_targetGCC
12690tree
12691ffecom_list_expr (ffebld expr)
12692{
12693 tree list;
12694 tree *plist = &list;
12695 tree trail = NULL_TREE; /* Append char length args here. */
12696 tree *ptrail = &trail;
12697 tree length;
12698
12699 while (expr != NULL)
12700 {
12701 *plist
12702 = build_tree_list (NULL_TREE, ffecom_arg_expr (ffebld_head (expr),
12703 &length));
12704 plist = &TREE_CHAIN (*plist);
12705 expr = ffebld_trail (expr);
12706 if (length != NULL_TREE)
12707 {
12708 *ptrail = build_tree_list (NULL_TREE, length);
12709 ptrail = &TREE_CHAIN (*ptrail);
12710 }
12711 }
12712
12713 *plist = trail;
12714
12715 return list;
12716}
12717
12718#endif
12719/* ffecom_list_ptr_to_expr -- Transform list of exprs into gcc tree
12720
12721 tree t;
12722 ffebld expr; // FFE opITEM list.
12723 tree = ffecom_list_ptr_to_expr(expr);
12724
12725 List of actual args is transformed into corresponding gcc backend list for
12726 use in calling an external procedure (vs. a statement function). */
12727
12728#if FFECOM_targetCURRENT == FFECOM_targetGCC
12729tree
12730ffecom_list_ptr_to_expr (ffebld expr)
12731{
12732 tree list;
12733 tree *plist = &list;
12734 tree trail = NULL_TREE; /* Append char length args here. */
12735 tree *ptrail = &trail;
12736 tree length;
12737
12738 while (expr != NULL)
12739 {
12740 *plist
12741 = build_tree_list (NULL_TREE,
12742 ffecom_arg_ptr_to_expr (ffebld_head (expr),
12743 &length));
12744 plist = &TREE_CHAIN (*plist);
12745 expr = ffebld_trail (expr);
12746 if (length != NULL_TREE)
12747 {
12748 *ptrail = build_tree_list (NULL_TREE, length);
12749 ptrail = &TREE_CHAIN (*ptrail);
12750 }
12751 }
12752
12753 *plist = trail;
12754
12755 return list;
12756}
12757
12758#endif
12759/* Obtain gcc's LABEL_DECL tree for label. */
12760
12761#if FFECOM_targetCURRENT == FFECOM_targetGCC
12762tree
12763ffecom_lookup_label (ffelab label)
12764{
12765 tree glabel;
12766
12767 if (ffelab_hook (label) == NULL_TREE)
12768 {
12769 char labelname[16];
12770
12771 switch (ffelab_type (label))
12772 {
12773 case FFELAB_typeLOOPEND:
12774 case FFELAB_typeNOTLOOP:
12775 case FFELAB_typeENDIF:
12776 sprintf (labelname, "%" ffelabValue_f "u", ffelab_value (label));
12777 glabel = build_decl (LABEL_DECL, get_identifier (labelname),
12778 void_type_node);
12779 DECL_CONTEXT (glabel) = current_function_decl;
12780 DECL_MODE (glabel) = VOIDmode;
12781 break;
12782
12783 case FFELAB_typeFORMAT:
12784 push_obstacks_nochange ();
12785 end_temporary_allocation ();
12786
12787 glabel = build_decl (VAR_DECL,
12788 ffecom_get_invented_identifier
12789 ("__g77_format_%d", NULL,
12790 (int) ffelab_value (label)),
12791 build_type_variant (build_array_type
12792 (char_type_node,
12793 NULL_TREE),
12794 1, 0));
12795 TREE_CONSTANT (glabel) = 1;
12796 TREE_STATIC (glabel) = 1;
12797 DECL_CONTEXT (glabel) = 0;
12798 DECL_INITIAL (glabel) = NULL;
12799 make_decl_rtl (glabel, NULL, 0);
12800 expand_decl (glabel);
12801
12802 resume_temporary_allocation ();
12803 pop_obstacks ();
12804
12805 break;
12806
12807 case FFELAB_typeANY:
12808 glabel = error_mark_node;
12809 break;
12810
12811 default:
12812 assert ("bad label type" == NULL);
12813 glabel = NULL;
12814 break;
12815 }
12816 ffelab_set_hook (label, glabel);
12817 }
12818 else
12819 {
12820 glabel = ffelab_hook (label);
12821 }
12822
12823 return glabel;
12824}
12825
12826#endif
12827/* Stabilizes the arguments. Don't use this if the lhs and rhs come from
12828 a single source specification (as in the fourth argument of MVBITS).
12829 If the type is NULL_TREE, the type of lhs is used to make the type of
12830 the MODIFY_EXPR. */
12831
12832#if FFECOM_targetCURRENT == FFECOM_targetGCC
12833tree
12834ffecom_modify (tree newtype, tree lhs,
12835 tree rhs)
12836{
12837 if (lhs == error_mark_node || rhs == error_mark_node)
12838 return error_mark_node;
12839
12840 if (newtype == NULL_TREE)
12841 newtype = TREE_TYPE (lhs);
12842
12843 if (TREE_SIDE_EFFECTS (lhs))
12844 lhs = stabilize_reference (lhs);
12845
12846 return ffecom_2s (MODIFY_EXPR, newtype, lhs, rhs);
12847}
12848
12849#endif
12850
12851/* Register source file name. */
12852
12853void
12854ffecom_file (char *name)
12855{
12856#if FFECOM_GCC_INCLUDE
12857 ffecom_file_ (name);
12858#endif
12859}
12860
12861/* ffecom_notify_init_storage -- An aggregate storage is now fully init'ed
12862
12863 ffestorag st;
12864 ffecom_notify_init_storage(st);
12865
12866 Gets called when all possible units in an aggregate storage area (a LOCAL
12867 with equivalences or a COMMON) have been initialized. The initialization
12868 info either is in ffestorag_init or, if that is NULL,
12869 ffestorag_accretion:
12870
12871 ffestorag_init may contain an opCONTER or opARRTER. opCONTER may occur
12872 even for an array if the array is one element in length!
12873
12874 ffestorag_accretion will contain an opACCTER. It is much like an
12875 opARRTER except it has an ffebit object in it instead of just a size.
12876 The back end can use the info in the ffebit object, if it wants, to
12877 reduce the amount of actual initialization, but in any case it should
12878 kill the ffebit object when done. Also, set accretion to NULL but
12879 init to a non-NULL value.
12880
12881 After performing initialization, DO NOT set init to NULL, because that'll
12882 tell the front end it is ok for more initialization to happen. Instead,
12883 set init to an opANY expression or some such thing that you can use to
12884 tell that you've already initialized the object.
12885
12886 27-Oct-91 JCB 1.1
12887 Support two-pass FFE. */
12888
12889void
12890ffecom_notify_init_storage (ffestorag st)
12891{
12892 ffebld init; /* The initialization expression. */
12893#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12894 ffetargetOffset size; /* The size of the entity. */
a6fa6420 12895 ffetargetAlign pad; /* Its initial padding. */
5ff904cd
JL
12896#endif
12897
12898 if (ffestorag_init (st) == NULL)
12899 {
12900 init = ffestorag_accretion (st);
12901 assert (init != NULL);
12902 ffestorag_set_accretion (st, NULL);
12903 ffestorag_set_accretes (st, 0);
12904
12905#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12906 /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12907 size = ffebld_accter_size (init);
a6fa6420 12908 pad = ffebld_accter_pad (init);
5ff904cd
JL
12909 ffebit_kill (ffebld_accter_bits (init));
12910 ffebld_set_op (init, FFEBLD_opARRTER);
12911 ffebld_set_arrter (init, ffebld_accter (init));
12912 ffebld_arrter_set_size (init, size);
a6fa6420 12913 ffebld_arrter_set_pad (init, size);
5ff904cd
JL
12914#endif
12915
12916#if FFECOM_TWOPASS
12917 ffestorag_set_init (st, init);
12918#endif
12919 }
12920#if FFECOM_ONEPASS
12921 else
12922 init = ffestorag_init (st);
12923#endif
12924
12925#if FFECOM_ONEPASS /* Process the inits, wipe 'em out. */
12926 ffestorag_set_init (st, ffebld_new_any ());
12927
12928 if (ffebld_op (init) == FFEBLD_opANY)
12929 return; /* Oh, we already did this! */
12930
12931#if FFECOM_targetCURRENT == FFECOM_targetFFE
12932 {
12933 ffesymbol s;
12934
12935 if (ffestorag_symbol (st) != NULL)
12936 s = ffestorag_symbol (st);
12937 else
12938 s = ffestorag_typesymbol (st);
12939
12940 fprintf (dmpout, "= initialize_storage \"%s\" ",
12941 (s != NULL) ? ffesymbol_text (s) : "(unnamed)");
12942 ffebld_dump (init);
12943 fputc ('\n', dmpout);
12944 }
12945#endif
12946
12947#endif /* if FFECOM_ONEPASS */
12948}
12949
12950/* ffecom_notify_init_symbol -- A symbol is now fully init'ed
12951
12952 ffesymbol s;
12953 ffecom_notify_init_symbol(s);
12954
12955 Gets called when all possible units in a symbol (not placed in COMMON
12956 or involved in EQUIVALENCE, unless it as yet has no ffestorag object)
12957 have been initialized. The initialization info either is in
12958 ffesymbol_init or, if that is NULL, ffesymbol_accretion:
12959
12960 ffesymbol_init may contain an opCONTER or opARRTER. opCONTER may occur
12961 even for an array if the array is one element in length!
12962
12963 ffesymbol_accretion will contain an opACCTER. It is much like an
12964 opARRTER except it has an ffebit object in it instead of just a size.
12965 The back end can use the info in the ffebit object, if it wants, to
12966 reduce the amount of actual initialization, but in any case it should
12967 kill the ffebit object when done. Also, set accretion to NULL but
12968 init to a non-NULL value.
12969
12970 After performing initialization, DO NOT set init to NULL, because that'll
12971 tell the front end it is ok for more initialization to happen. Instead,
12972 set init to an opANY expression or some such thing that you can use to
12973 tell that you've already initialized the object.
12974
12975 27-Oct-91 JCB 1.1
12976 Support two-pass FFE. */
12977
12978void
12979ffecom_notify_init_symbol (ffesymbol s)
12980{
12981 ffebld init; /* The initialization expression. */
12982#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12983 ffetargetOffset size; /* The size of the entity. */
a6fa6420 12984 ffetargetAlign pad; /* Its initial padding. */
5ff904cd
JL
12985#endif
12986
12987 if (ffesymbol_storage (s) == NULL)
12988 return; /* Do nothing until COMMON/EQUIVALENCE
12989 possibilities checked. */
12990
12991 if ((ffesymbol_init (s) == NULL)
12992 && ((init = ffesymbol_accretion (s)) != NULL))
12993 {
12994 ffesymbol_set_accretion (s, NULL);
12995 ffesymbol_set_accretes (s, 0);
12996
12997#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12998 /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12999 size = ffebld_accter_size (init);
a6fa6420 13000 pad = ffebld_accter_pad (init);
5ff904cd
JL
13001 ffebit_kill (ffebld_accter_bits (init));
13002 ffebld_set_op (init, FFEBLD_opARRTER);
13003 ffebld_set_arrter (init, ffebld_accter (init));
13004 ffebld_arrter_set_size (init, size);
a6fa6420 13005 ffebld_arrter_set_pad (init, size);
5ff904cd
JL
13006#endif
13007
13008#if FFECOM_TWOPASS
13009 ffesymbol_set_init (s, init);
13010#endif
13011 }
13012#if FFECOM_ONEPASS
13013 else
13014 init = ffesymbol_init (s);
13015#endif
13016
13017#if FFECOM_ONEPASS
13018 ffesymbol_set_init (s, ffebld_new_any ());
13019
13020 if (ffebld_op (init) == FFEBLD_opANY)
13021 return; /* Oh, we already did this! */
13022
13023#if FFECOM_targetCURRENT == FFECOM_targetFFE
13024 fprintf (dmpout, "= initialize_symbol \"%s\" ", ffesymbol_text (s));
13025 ffebld_dump (init);
13026 fputc ('\n', dmpout);
13027#endif
13028
13029#endif /* if FFECOM_ONEPASS */
13030}
13031
13032/* ffecom_notify_primary_entry -- Learn which is the primary entry point
13033
13034 ffesymbol s;
13035 ffecom_notify_primary_entry(s);
13036
13037 Gets called when implicit or explicit PROGRAM statement seen or when
13038 FUNCTION, SUBROUTINE, or BLOCK DATA statement seen, with the primary
13039 global symbol that serves as the entry point. */
13040
13041void
13042ffecom_notify_primary_entry (ffesymbol s)
13043{
13044 ffecom_primary_entry_ = s;
13045 ffecom_primary_entry_kind_ = ffesymbol_kind (s);
13046
13047 if ((ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
13048 || (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE))
13049 ffecom_primary_entry_is_proc_ = TRUE;
13050 else
13051 ffecom_primary_entry_is_proc_ = FALSE;
13052
13053 if (!ffe_is_silent ())
13054 {
13055 if (ffecom_primary_entry_kind_ == FFEINFO_kindPROGRAM)
13056 fprintf (stderr, "%s:\n", ffesymbol_text (s));
13057 else
13058 fprintf (stderr, " %s:\n", ffesymbol_text (s));
13059 }
13060
13061#if FFECOM_targetCURRENT == FFECOM_targetGCC
13062 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
13063 {
13064 ffebld list;
13065 ffebld arg;
13066
13067 for (list = ffesymbol_dummyargs (s);
13068 list != NULL;
13069 list = ffebld_trail (list))
13070 {
13071 arg = ffebld_head (list);
13072 if (ffebld_op (arg) == FFEBLD_opSTAR)
13073 {
13074 ffecom_is_altreturning_ = TRUE;
13075 break;
13076 }
13077 }
13078 }
13079#endif
13080}
13081
13082FILE *
13083ffecom_open_include (char *name, ffewhereLine l, ffewhereColumn c)
13084{
13085#if FFECOM_GCC_INCLUDE
13086 return ffecom_open_include_ (name, l, c);
13087#else
13088 return fopen (name, "r");
13089#endif
13090}
13091
13092/* Clean up after making automatically popped call-arg temps.
13093
13094 Call this in pairs with push_calltemps around calls to
13095 ffecom_arg_ptr_to_expr if the latter might use temporaries.
13096 Any temporaries made within the outermost sequence of
13097 push_calltemps and pop_calltemps, that are marked as "auto-pop"
13098 meaning they won't be explicitly popped (freed), are popped
13099 at this point so they can be reused later.
13100
13101 NOTE: when called by ffecom_gen_sfuncdef_, ffecom_pending_calls_
13102 should come in == 1, and all of the in-use auto-pop temps
13103 should have DECL_CONTEXT (temp->t) == current_function_decl.
13104 Moreover, these temps should _never_ be re-used in future
13105 calls to ffecom_push_tempvar -- since current_function_decl will
13106 never be the same again.
13107
13108 SO, it could be a minor win in terms of compile time to just
13109 strip these temps off the list. That is, if the above assumptions
13110 are correct, just remove from the list of temps any temp
13111 that is both in-use and has DECL_CONTEXT (temp->t)
13112 == current_function_decl, when called from ffecom_gen_sfuncdef_. */
13113
13114#if FFECOM_targetCURRENT == FFECOM_targetGCC
13115void
13116ffecom_pop_calltemps ()
13117{
13118 ffecomTemp_ temp;
13119
13120 assert (ffecom_pending_calls_ > 0);
13121
13122 if (--ffecom_pending_calls_ == 0)
13123 for (temp = ffecom_latest_temp_; temp != NULL; temp = temp->next)
13124 if (temp->auto_pop)
13125 temp->in_use = FALSE;
13126}
13127
13128#endif
13129/* Mark latest temp with given tree as no longer in use. */
13130
13131#if FFECOM_targetCURRENT == FFECOM_targetGCC
13132void
13133ffecom_pop_tempvar (tree t)
13134{
13135 ffecomTemp_ temp;
13136
13137 for (temp = ffecom_latest_temp_; temp != NULL; temp = temp->next)
13138 if (temp->in_use && (temp->t == t))
13139 {
13140 assert (!temp->auto_pop);
13141 temp->in_use = FALSE;
13142 return;
13143 }
13144 else
13145 assert (temp->t != t);
13146
13147 assert ("couldn't ffecom_pop_tempvar!" != NULL);
13148}
13149
13150#endif
13151/* ffecom_ptr_to_expr -- Transform expr into gcc tree with & in front
13152
13153 tree t;
13154 ffebld expr; // FFE expression.
13155 tree = ffecom_ptr_to_expr(expr);
13156
13157 Like ffecom_expr, but sticks address-of in front of most things. */
13158
13159#if FFECOM_targetCURRENT == FFECOM_targetGCC
13160tree
13161ffecom_ptr_to_expr (ffebld expr)
13162{
13163 tree item;
13164 ffeinfoBasictype bt;
13165 ffeinfoKindtype kt;
13166 ffesymbol s;
13167
13168 assert (expr != NULL);
13169
13170 switch (ffebld_op (expr))
13171 {
13172 case FFEBLD_opSYMTER:
13173 s = ffebld_symter (expr);
13174 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
13175 {
13176 ffecomGfrt ix;
13177
13178 ix = ffeintrin_gfrt_indirect (ffebld_symter_implementation (expr));
13179 assert (ix != FFECOM_gfrt);
13180 if ((item = ffecom_gfrt_[ix]) == NULL_TREE)
13181 {
13182 ffecom_make_gfrt_ (ix);
13183 item = ffecom_gfrt_[ix];
13184 }
13185 }
13186 else
13187 {
13188 item = ffesymbol_hook (s).decl_tree;
13189 if (item == NULL_TREE)
13190 {
13191 s = ffecom_sym_transform_ (s);
13192 item = ffesymbol_hook (s).decl_tree;
13193 }
13194 }
13195 assert (item != NULL);
13196 if (item == error_mark_node)
13197 return item;
13198 if (!ffesymbol_hook (s).addr)
13199 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
13200 item);
13201 return item;
13202
13203 case FFEBLD_opARRAYREF:
13204 {
13205 ffebld dims[FFECOM_dimensionsMAX];
13206 tree array;
13207 int i;
13208
13209 item = ffecom_ptr_to_expr (ffebld_left (expr));
13210
13211 if (item == error_mark_node)
13212 return item;
13213
13214 if ((ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereFLEETING)
13215 && !mark_addressable (item))
13216 return error_mark_node; /* Make sure non-const ref is to
13217 non-reg. */
13218
13219 /* Build up ARRAY_REFs in reverse order (since we're column major
13220 here in Fortran land). */
13221
13222 for (i = 0, expr = ffebld_right (expr);
13223 expr != NULL;
13224 expr = ffebld_trail (expr))
13225 dims[i++] = ffebld_head (expr);
13226
13227 for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
13228 i >= 0;
13229 --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
13230 {
8cd61d76
RH
13231 /* The initial subtraction should happen in the original type so
13232 that (possible) negative values are handled appropriately. */
5ff904cd
JL
13233 item
13234 = ffecom_2 (PLUS_EXPR,
13235 build_pointer_type (TREE_TYPE (array)),
13236 item,
13237 size_binop (MULT_EXPR,
13238 size_in_bytes (TREE_TYPE (array)),
e203760c
RH
13239 convert (sizetype,
13240 fold (build (MINUS_EXPR,
13241 TREE_TYPE (TYPE_MIN_VALUE (TYPE_DOMAIN (array))),
13242 ffecom_expr (dims[i]),
13243 TYPE_MIN_VALUE (TYPE_DOMAIN (array)))))));
5ff904cd
JL
13244 }
13245 }
13246 return item;
13247
13248 case FFEBLD_opCONTER:
13249
13250 bt = ffeinfo_basictype (ffebld_info (expr));
13251 kt = ffeinfo_kindtype (ffebld_info (expr));
13252
13253 item = ffecom_constantunion (&ffebld_constant_union
13254 (ffebld_conter (expr)), bt, kt,
13255 ffecom_tree_type[bt][kt]);
13256 if (item == error_mark_node)
13257 return error_mark_node;
13258 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
13259 item);
13260 return item;
13261
13262 case FFEBLD_opANY:
13263 return error_mark_node;
13264
13265 default:
13266 assert (ffecom_pending_calls_ > 0);
13267
13268 bt = ffeinfo_basictype (ffebld_info (expr));
13269 kt = ffeinfo_kindtype (ffebld_info (expr));
13270
13271 item = ffecom_expr (expr);
13272 if (item == error_mark_node)
13273 return error_mark_node;
13274
13275 /* The back end currently optimizes a bit too zealously for us, in that
13276 we fail JCB001 if the following block of code is omitted. It checks
13277 to see if the transformed expression is a symbol or array reference,
13278 and encloses it in a SAVE_EXPR if that is the case. */
13279
13280 STRIP_NOPS (item);
13281 if ((TREE_CODE (item) == VAR_DECL)
13282 || (TREE_CODE (item) == PARM_DECL)
13283 || (TREE_CODE (item) == RESULT_DECL)
13284 || (TREE_CODE (item) == INDIRECT_REF)
13285 || (TREE_CODE (item) == ARRAY_REF)
13286 || (TREE_CODE (item) == COMPONENT_REF)
13287#ifdef OFFSET_REF
13288 || (TREE_CODE (item) == OFFSET_REF)
13289#endif
13290 || (TREE_CODE (item) == BUFFER_REF)
13291 || (TREE_CODE (item) == REALPART_EXPR)
13292 || (TREE_CODE (item) == IMAGPART_EXPR))
13293 {
13294 item = ffecom_save_tree (item);
13295 }
13296
13297 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
13298 item);
13299 return item;
13300 }
13301
13302 assert ("fall-through error" == NULL);
13303 return error_mark_node;
13304}
13305
13306#endif
13307/* Prepare to make call-arg temps.
13308
13309 Call this in pairs with pop_calltemps around calls to
13310 ffecom_arg_ptr_to_expr if the latter might use temporaries. */
13311
13312#if FFECOM_targetCURRENT == FFECOM_targetGCC
13313void
13314ffecom_push_calltemps ()
13315{
13316 ffecom_pending_calls_++;
13317}
13318
13319#endif
13320/* Obtain a temp var with given data type.
13321
13322 Returns a VAR_DECL tree of a currently (that is, at the current
13323 statement being compiled) not in use and having the given data type,
13324 making a new one if necessary. size is FFETARGET_charactersizeNONE
13325 for a non-CHARACTER type or >= 0 for a CHARACTER type. elements is
13326 -1 for a scalar or > 0 for an array of type. auto_pop is TRUE if
13327 ffecom_pop_tempvar won't be called, meaning temp will be freed
13328 when #pending calls goes to zero. */
13329
13330#if FFECOM_targetCURRENT == FFECOM_targetGCC
13331tree
13332ffecom_push_tempvar (tree type, ffetargetCharacterSize size, int elements,
13333 bool auto_pop)
13334{
13335 ffecomTemp_ temp;
13336 int yes;
13337 tree t;
13338 static int mynumber;
13339
13340 assert (!auto_pop || (ffecom_pending_calls_ > 0));
13341
13342 if (type == error_mark_node)
13343 return error_mark_node;
13344
13345 for (temp = ffecom_latest_temp_; temp != NULL; temp = temp->next)
13346 {
13347 if (temp->in_use
13348 || (temp->type != type)
13349 || (temp->size != size)
13350 || (temp->elements != elements)
13351 || (DECL_CONTEXT (temp->t) != current_function_decl))
13352 continue;
13353
13354 temp->in_use = TRUE;
13355 temp->auto_pop = auto_pop;
13356 return temp->t;
13357 }
13358
13359 /* Create a new temp. */
13360
13361 yes = suspend_momentary ();
13362
13363 if (size != FFETARGET_charactersizeNONE)
13364 type = build_array_type (type,
13365 build_range_type (ffecom_f2c_ftnlen_type_node,
13366 ffecom_f2c_ftnlen_one_node,
13367 build_int_2 (size, 0)));
13368 if (elements != -1)
13369 type = build_array_type (type,
13370 build_range_type (integer_type_node,
13371 integer_zero_node,
13372 build_int_2 (elements - 1,
13373 0)));
13374 t = build_decl (VAR_DECL,
13375 ffecom_get_invented_identifier ("__g77_expr_%d", NULL,
13376 mynumber++),
13377 type);
5ff904cd 13378
6bf71635
CB
13379 /* This temp must be put in the same scope as the containing BLOCK
13380 (aka function), but for reasons that should be explained elsewhere,
13381 the GBE normally decides it should be in a "phantom BLOCK" associated
13382 with the expand_start_stmt_expr() call. So push the topmost
13383 sequence back onto the GBE's internal stack before telling it
13384 about the decl, then restore it afterwards. */
13385 push_topmost_sequence ();
5ff904cd 13386
6bf71635
CB
13387 t = start_decl (t, FALSE);
13388 finish_decl (t, NULL_TREE, FALSE);
5ff904cd 13389
6bf71635 13390 pop_topmost_sequence ();
5ff904cd
JL
13391
13392 resume_momentary (yes);
13393
13394 temp = malloc_new_kp (ffe_pool_program_unit (), "ffecomTemp_",
13395 sizeof (*temp));
13396
13397 temp->next = ffecom_latest_temp_;
13398 temp->type = type;
13399 temp->t = t;
13400 temp->size = size;
13401 temp->elements = elements;
13402 temp->in_use = TRUE;
13403 temp->auto_pop = auto_pop;
13404
13405 ffecom_latest_temp_ = temp;
13406
13407 return t;
13408}
13409
13410#endif
13411/* ffecom_return_expr -- Returns return-value expr given alt return expr
13412
13413 tree rtn; // NULL_TREE means use expand_null_return()
13414 ffebld expr; // NULL if no alt return expr to RETURN stmt
13415 rtn = ffecom_return_expr(expr);
13416
13417 Based on the program unit type and other info (like return function
13418 type, return master function type when alternate ENTRY points,
13419 whether subroutine has any alternate RETURN points, etc), returns the
13420 appropriate expression to be returned to the caller, or NULL_TREE
13421 meaning no return value or the caller expects it to be returned somewhere
13422 else (which is handled by other parts of this module). */
13423
13424#if FFECOM_targetCURRENT == FFECOM_targetGCC
13425tree
13426ffecom_return_expr (ffebld expr)
13427{
13428 tree rtn;
13429
13430 switch (ffecom_primary_entry_kind_)
13431 {
13432 case FFEINFO_kindPROGRAM:
13433 case FFEINFO_kindBLOCKDATA:
13434 rtn = NULL_TREE;
13435 break;
13436
13437 case FFEINFO_kindSUBROUTINE:
13438 if (!ffecom_is_altreturning_)
13439 rtn = NULL_TREE; /* No alt returns, never an expr. */
13440 else if (expr == NULL)
13441 rtn = integer_zero_node;
13442 else
13443 rtn = ffecom_expr (expr);
13444 break;
13445
13446 case FFEINFO_kindFUNCTION:
13447 if ((ffecom_multi_retval_ != NULL_TREE)
13448 || (ffesymbol_basictype (ffecom_primary_entry_)
13449 == FFEINFO_basictypeCHARACTER)
13450 || ((ffesymbol_basictype (ffecom_primary_entry_)
13451 == FFEINFO_basictypeCOMPLEX)
13452 && (ffecom_num_entrypoints_ == 0)
13453 && ffesymbol_is_f2c (ffecom_primary_entry_)))
13454 { /* Value is returned by direct assignment
13455 into (implicit) dummy. */
13456 rtn = NULL_TREE;
13457 break;
13458 }
13459 rtn = ffecom_func_result_;
13460#if 0
13461 /* Spurious error if RETURN happens before first reference! So elide
13462 this code. In particular, for debugging registry, rtn should always
13463 be non-null after all, but TREE_USED won't be set until we encounter
13464 a reference in the code. Perfectly okay (but weird) code that,
13465 e.g., has "GOTO 20;10 RETURN;20 RTN=0;GOTO 10", would result in
13466 this diagnostic for no reason. Have people use -O -Wuninitialized
13467 and leave it to the back end to find obviously weird cases. */
13468
13469 /* Used to "assert(rtn != NULL_TREE);" here, but it's kind of a valid
13470 situation; if the return value has never been referenced, it won't
13471 have a tree under 2pass mode. */
13472 if ((rtn == NULL_TREE)
13473 || !TREE_USED (rtn))
13474 {
13475 ffebad_start (FFEBAD_RETURN_VALUE_UNSET);
13476 ffebad_here (0, ffesymbol_where_line (ffecom_primary_entry_),
13477 ffesymbol_where_column (ffecom_primary_entry_));
13478 ffebad_string (ffesymbol_text (ffesymbol_funcresult
13479 (ffecom_primary_entry_)));
13480 ffebad_finish ();
13481 }
13482#endif
13483 break;
13484
13485 default:
13486 assert ("bad unit kind" == NULL);
13487 case FFEINFO_kindANY:
13488 rtn = error_mark_node;
13489 break;
13490 }
13491
13492 return rtn;
13493}
13494
13495#endif
13496/* Do save_expr only if tree is not error_mark_node. */
13497
13498#if FFECOM_targetCURRENT == FFECOM_targetGCC
a2977d2d
CB
13499tree
13500ffecom_save_tree (tree t)
5ff904cd
JL
13501{
13502 return save_expr (t);
13503}
13504#endif
13505
13506/* Public entry point for front end to access start_decl. */
13507
13508#if FFECOM_targetCURRENT == FFECOM_targetGCC
13509tree
13510ffecom_start_decl (tree decl, bool is_initialized)
13511{
13512 DECL_INITIAL (decl) = is_initialized ? error_mark_node : NULL_TREE;
13513 return start_decl (decl, FALSE);
13514}
13515
13516#endif
13517/* ffecom_sym_commit -- Symbol's state being committed to reality
13518
13519 ffesymbol s;
13520 ffecom_sym_commit(s);
13521
13522 Does whatever the backend needs when a symbol is committed after having
13523 been backtrackable for a period of time. */
13524
13525#if FFECOM_targetCURRENT == FFECOM_targetGCC
13526void
13527ffecom_sym_commit (ffesymbol s UNUSED)
13528{
13529 assert (!ffesymbol_retractable ());
13530}
13531
13532#endif
13533/* ffecom_sym_end_transition -- Perform end transition on all symbols
13534
13535 ffecom_sym_end_transition();
13536
13537 Does backend-specific stuff and also calls ffest_sym_end_transition
13538 to do the necessary FFE stuff.
13539
13540 Backtracking is never enabled when this fn is called, so don't worry
13541 about it. */
13542
13543ffesymbol
13544ffecom_sym_end_transition (ffesymbol s)
13545{
13546 ffestorag st;
13547
13548 assert (!ffesymbol_retractable ());
13549
13550 s = ffest_sym_end_transition (s);
13551
13552#if FFECOM_targetCURRENT == FFECOM_targetGCC
13553 if ((ffesymbol_kind (s) == FFEINFO_kindBLOCKDATA)
13554 && (ffesymbol_where (s) == FFEINFO_whereGLOBAL))
13555 {
13556 ffecom_list_blockdata_
13557 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13558 FFEINTRIN_specNONE,
13559 FFEINTRIN_impNONE),
13560 ffecom_list_blockdata_);
13561 }
13562#endif
13563
13564 /* This is where we finally notice that a symbol has partial initialization
13565 and finalize it. */
13566
13567 if (ffesymbol_accretion (s) != NULL)
13568 {
13569 assert (ffesymbol_init (s) == NULL);
13570 ffecom_notify_init_symbol (s);
13571 }
13572 else if (((st = ffesymbol_storage (s)) != NULL)
13573 && ((st = ffestorag_parent (st)) != NULL)
13574 && (ffestorag_accretion (st) != NULL))
13575 {
13576 assert (ffestorag_init (st) == NULL);
13577 ffecom_notify_init_storage (st);
13578 }
13579
13580#if FFECOM_targetCURRENT == FFECOM_targetGCC
13581 if ((ffesymbol_kind (s) == FFEINFO_kindCOMMON)
13582 && (ffesymbol_where (s) == FFEINFO_whereLOCAL)
13583 && (ffesymbol_storage (s) != NULL))
13584 {
13585 ffecom_list_common_
13586 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13587 FFEINTRIN_specNONE,
13588 FFEINTRIN_impNONE),
13589 ffecom_list_common_);
13590 }
13591#endif
13592
13593 return s;
13594}
13595
13596/* ffecom_sym_exec_transition -- Perform exec transition on all symbols
13597
13598 ffecom_sym_exec_transition();
13599
13600 Does backend-specific stuff and also calls ffest_sym_exec_transition
13601 to do the necessary FFE stuff.
13602
13603 See the long-winded description in ffecom_sym_learned for info
13604 on handling the situation where backtracking is inhibited. */
13605
13606ffesymbol
13607ffecom_sym_exec_transition (ffesymbol s)
13608{
13609 s = ffest_sym_exec_transition (s);
13610
13611 return s;
13612}
13613
13614/* ffecom_sym_learned -- Initial or more info gained on symbol after exec
13615
13616 ffesymbol s;
13617 s = ffecom_sym_learned(s);
13618
13619 Called when a new symbol is seen after the exec transition or when more
13620 info (perhaps) is gained for an UNCERTAIN symbol. The symbol state when
13621 it arrives here is that all its latest info is updated already, so its
13622 state may be UNCERTAIN or UNDERSTOOD, it might already have the hook
13623 field filled in if its gone through here or exec_transition first, and
13624 so on.
13625
13626 The backend probably wants to check ffesymbol_retractable() to see if
13627 backtracking is in effect. If so, the FFE's changes to the symbol may
13628 be retracted (undone) or committed (ratified), at which time the
13629 appropriate ffecom_sym_retract or _commit function will be called
13630 for that function.
13631
13632 If the backend has its own backtracking mechanism, great, use it so that
13633 committal is a simple operation. Though it doesn't make much difference,
13634 I suppose: the reason for tentative symbol evolution in the FFE is to
13635 enable error detection in weird incorrect statements early and to disable
13636 incorrect error detection on a correct statement. The backend is not
13637 likely to introduce any information that'll get involved in these
13638 considerations, so it is probably just fine that the implementation
13639 model for this fn and for _exec_transition is to not do anything
13640 (besides the required FFE stuff) if ffesymbol_retractable() returns TRUE
13641 and instead wait until ffecom_sym_commit is called (which it never
13642 will be as long as we're using ambiguity-detecting statement analysis in
13643 the FFE, which we are initially to shake out the code, but don't depend
13644 on this), otherwise go ahead and do whatever is needed.
13645
13646 In essence, then, when this fn and _exec_transition get called while
13647 backtracking is enabled, a general mechanism would be to flag which (or
13648 both) of these were called (and in what order? neat question as to what
13649 might happen that I'm too lame to think through right now) and then when
13650 _commit is called reproduce the original calling sequence, if any, for
13651 the two fns (at which point backtracking will, of course, be disabled). */
13652
13653ffesymbol
13654ffecom_sym_learned (ffesymbol s)
13655{
13656 ffestorag_exec_layout (s);
13657
13658 return s;
13659}
13660
13661/* ffecom_sym_retract -- Symbol's state being retracted from reality
13662
13663 ffesymbol s;
13664 ffecom_sym_retract(s);
13665
13666 Does whatever the backend needs when a symbol is retracted after having
13667 been backtrackable for a period of time. */
13668
13669#if FFECOM_targetCURRENT == FFECOM_targetGCC
13670void
13671ffecom_sym_retract (ffesymbol s UNUSED)
13672{
13673 assert (!ffesymbol_retractable ());
13674
13675#if 0 /* GCC doesn't commit any backtrackable sins,
13676 so nothing needed here. */
13677 switch (ffesymbol_hook (s).state)
13678 {
13679 case 0: /* nothing happened yet. */
13680 break;
13681
13682 case 1: /* exec transition happened. */
13683 break;
13684
13685 case 2: /* learned happened. */
13686 break;
13687
13688 case 3: /* learned then exec. */
13689 break;
13690
13691 case 4: /* exec then learned. */
13692 break;
13693
13694 default:
13695 assert ("bad hook state" == NULL);
13696 break;
13697 }
13698#endif
13699}
13700
13701#endif
13702/* Create temporary gcc label. */
13703
13704#if FFECOM_targetCURRENT == FFECOM_targetGCC
13705tree
13706ffecom_temp_label ()
13707{
13708 tree glabel;
13709 static int mynumber = 0;
13710
13711 glabel = build_decl (LABEL_DECL,
13712 ffecom_get_invented_identifier ("__g77_label_%d",
13713 NULL,
13714 mynumber++),
13715 void_type_node);
13716 DECL_CONTEXT (glabel) = current_function_decl;
13717 DECL_MODE (glabel) = VOIDmode;
13718
13719 return glabel;
13720}
13721
13722#endif
13723/* Return an expression that is usable as an arg in a conditional context
13724 (IF, DO WHILE, .NOT., and so on).
13725
13726 Use the one provided for the back end as of >2.6.0. */
13727
13728#if FFECOM_targetCURRENT == FFECOM_targetGCC
13729tree
13730ffecom_truth_value (tree expr)
13731{
13732 return truthvalue_conversion (expr);
13733}
13734
13735#endif
13736/* Return the inversion of a truth value (the inversion of what
13737 ffecom_truth_value builds).
13738
13739 Apparently invert_truthvalue, which is properly in the back end, is
13740 enough for now, so just use it. */
13741
13742#if FFECOM_targetCURRENT == FFECOM_targetGCC
13743tree
13744ffecom_truth_value_invert (tree expr)
13745{
13746 return invert_truthvalue (ffecom_truth_value (expr));
13747}
13748
13749#endif
13750/* Return PARM_DECL for arg#1 of master fn containing alternate ENTRY points
13751
13752 If the PARM_DECL already exists, return it, else create it. It's an
13753 integer_type_node argument for the master function that implements a
13754 subroutine or function with more than one entrypoint and is bound at
13755 run time with the entrypoint number (0 for SUBROUTINE/FUNCTION, 1 for
13756 first ENTRY statement, and so on). */
13757
13758#if FFECOM_targetCURRENT == FFECOM_targetGCC
13759tree
13760ffecom_which_entrypoint_decl ()
13761{
13762 assert (ffecom_which_entrypoint_decl_ != NULL_TREE);
13763
13764 return ffecom_which_entrypoint_decl_;
13765}
13766
13767#endif
13768\f
13769/* The following sections consists of private and public functions
13770 that have the same names and perform roughly the same functions
13771 as counterparts in the C front end. Changes in the C front end
13772 might affect how things should be done here. Only functions
13773 needed by the back end should be public here; the rest should
13774 be private (static in the C sense). Functions needed by other
13775 g77 front-end modules should be accessed by them via public
13776 ffecom_* names, which should themselves call private versions
13777 in this section so the private versions are easy to recognize
13778 when upgrading to a new gcc and finding interesting changes
13779 in the front end.
13780
13781 Functions named after rule "foo:" in c-parse.y are named
13782 "bison_rule_foo_" so they are easy to find. */
13783
13784#if FFECOM_targetCURRENT == FFECOM_targetGCC
13785
13786static void
13787bison_rule_compstmt_ ()
13788{
13789 emit_line_note (input_filename, lineno);
13790 expand_end_bindings (getdecls (), 1, 1);
13791 poplevel (1, 1, 0);
13792 pop_momentary ();
13793}
13794
13795static void
13796bison_rule_pushlevel_ ()
13797{
13798 emit_line_note (input_filename, lineno);
13799 pushlevel (0);
13800 clear_last_expr ();
13801 push_momentary ();
13802 expand_start_bindings (0);
13803}
13804
13805/* Return a definition for a builtin function named NAME and whose data type
13806 is TYPE. TYPE should be a function type with argument types.
13807 FUNCTION_CODE tells later passes how to compile calls to this function.
13808 See tree.h for its possible values.
13809
13810 If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
13811 the name to be called if we can't opencode the function. */
13812
13813static tree
13814builtin_function (char *name, tree type,
13815 enum built_in_function function_code, char *library_name)
13816{
13817 tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
13818 DECL_EXTERNAL (decl) = 1;
13819 TREE_PUBLIC (decl) = 1;
13820 if (library_name)
13821 DECL_ASSEMBLER_NAME (decl) = get_identifier (library_name);
13822 make_decl_rtl (decl, NULL_PTR, 1);
13823 pushdecl (decl);
13824 if (function_code != NOT_BUILT_IN)
13825 {
13826 DECL_BUILT_IN (decl) = 1;
13827 DECL_FUNCTION_CODE (decl) = function_code;
13828 }
13829
13830 return decl;
13831}
13832
13833/* Handle when a new declaration NEWDECL
13834 has the same name as an old one OLDDECL
13835 in the same binding contour.
13836 Prints an error message if appropriate.
13837
13838 If safely possible, alter OLDDECL to look like NEWDECL, and return 1.
13839 Otherwise, return 0. */
13840
13841static int
13842duplicate_decls (tree newdecl, tree olddecl)
13843{
13844 int types_match = 1;
13845 int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
13846 && DECL_INITIAL (newdecl) != 0);
13847 tree oldtype = TREE_TYPE (olddecl);
13848 tree newtype = TREE_TYPE (newdecl);
13849
13850 if (olddecl == newdecl)
13851 return 1;
13852
13853 if (TREE_CODE (newtype) == ERROR_MARK
13854 || TREE_CODE (oldtype) == ERROR_MARK)
13855 types_match = 0;
13856
13857 /* New decl is completely inconsistent with the old one =>
13858 tell caller to replace the old one.
13859 This is always an error except in the case of shadowing a builtin. */
13860 if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
13861 return 0;
13862
13863 /* For real parm decl following a forward decl,
13864 return 1 so old decl will be reused. */
13865 if (types_match && TREE_CODE (newdecl) == PARM_DECL
13866 && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
13867 return 1;
13868
13869 /* The new declaration is the same kind of object as the old one.
13870 The declarations may partially match. Print warnings if they don't
13871 match enough. Ultimately, copy most of the information from the new
13872 decl to the old one, and keep using the old one. */
13873
13874 if (TREE_CODE (olddecl) == FUNCTION_DECL
13875 && DECL_BUILT_IN (olddecl))
13876 {
13877 /* A function declaration for a built-in function. */
13878 if (!TREE_PUBLIC (newdecl))
13879 return 0;
13880 else if (!types_match)
13881 {
13882 /* Accept the return type of the new declaration if same modes. */
13883 tree oldreturntype = TREE_TYPE (TREE_TYPE (olddecl));
13884 tree newreturntype = TREE_TYPE (TREE_TYPE (newdecl));
13885
13886 /* Make sure we put the new type in the same obstack as the old ones.
13887 If the old types are not both in the same obstack, use the
13888 permanent one. */
13889 if (TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (newtype))
13890 push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
13891 else
13892 {
13893 push_obstacks_nochange ();
13894 end_temporary_allocation ();
13895 }
13896
13897 if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
13898 {
13899 /* Function types may be shared, so we can't just modify
13900 the return type of olddecl's function type. */
13901 tree newtype
13902 = build_function_type (newreturntype,
13903 TYPE_ARG_TYPES (TREE_TYPE (olddecl)));
13904
13905 types_match = 1;
13906 if (types_match)
13907 TREE_TYPE (olddecl) = newtype;
13908 }
13909
13910 pop_obstacks ();
13911 }
13912 if (!types_match)
13913 return 0;
13914 }
13915 else if (TREE_CODE (olddecl) == FUNCTION_DECL
13916 && DECL_SOURCE_LINE (olddecl) == 0)
13917 {
13918 /* A function declaration for a predeclared function
13919 that isn't actually built in. */
13920 if (!TREE_PUBLIC (newdecl))
13921 return 0;
13922 else if (!types_match)
13923 {
13924 /* If the types don't match, preserve volatility indication.
13925 Later on, we will discard everything else about the
13926 default declaration. */
13927 TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
13928 }
13929 }
13930
13931 /* Copy all the DECL_... slots specified in the new decl
13932 except for any that we copy here from the old type.
13933
13934 Past this point, we don't change OLDTYPE and NEWTYPE
13935 even if we change the types of NEWDECL and OLDDECL. */
13936
13937 if (types_match)
13938 {
13939 /* Make sure we put the new type in the same obstack as the old ones.
13940 If the old types are not both in the same obstack, use the permanent
13941 one. */
13942 if (TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (newtype))
13943 push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
13944 else
13945 {
13946 push_obstacks_nochange ();
13947 end_temporary_allocation ();
13948 }
13949
13950 /* Merge the data types specified in the two decls. */
13951 if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
13952 TREE_TYPE (newdecl)
13953 = TREE_TYPE (olddecl)
13954 = TREE_TYPE (newdecl);
13955
13956 /* Lay the type out, unless already done. */
13957 if (oldtype != TREE_TYPE (newdecl))
13958 {
13959 if (TREE_TYPE (newdecl) != error_mark_node)
13960 layout_type (TREE_TYPE (newdecl));
13961 if (TREE_CODE (newdecl) != FUNCTION_DECL
13962 && TREE_CODE (newdecl) != TYPE_DECL
13963 && TREE_CODE (newdecl) != CONST_DECL)
13964 layout_decl (newdecl, 0);
13965 }
13966 else
13967 {
13968 /* Since the type is OLDDECL's, make OLDDECL's size go with. */
13969 DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
13970 if (TREE_CODE (olddecl) != FUNCTION_DECL)
13971 if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
13972 DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
13973 }
13974
13975 /* Keep the old rtl since we can safely use it. */
13976 DECL_RTL (newdecl) = DECL_RTL (olddecl);
13977
13978 /* Merge the type qualifiers. */
13979 if (DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl)
13980 && !TREE_THIS_VOLATILE (newdecl))
13981 TREE_THIS_VOLATILE (olddecl) = 0;
13982 if (TREE_READONLY (newdecl))
13983 TREE_READONLY (olddecl) = 1;
13984 if (TREE_THIS_VOLATILE (newdecl))
13985 {
13986 TREE_THIS_VOLATILE (olddecl) = 1;
13987 if (TREE_CODE (newdecl) == VAR_DECL)
13988 make_var_volatile (newdecl);
13989 }
13990
13991 /* Keep source location of definition rather than declaration.
13992 Likewise, keep decl at outer scope. */
13993 if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
13994 || (DECL_CONTEXT (newdecl) != 0 && DECL_CONTEXT (olddecl) == 0))
13995 {
13996 DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
13997 DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl);
13998
13999 if (DECL_CONTEXT (olddecl) == 0
14000 && TREE_CODE (newdecl) != FUNCTION_DECL)
14001 DECL_CONTEXT (newdecl) = 0;
14002 }
14003
14004 /* Merge the unused-warning information. */
14005 if (DECL_IN_SYSTEM_HEADER (olddecl))
14006 DECL_IN_SYSTEM_HEADER (newdecl) = 1;
14007 else if (DECL_IN_SYSTEM_HEADER (newdecl))
14008 DECL_IN_SYSTEM_HEADER (olddecl) = 1;
14009
14010 /* Merge the initialization information. */
14011 if (DECL_INITIAL (newdecl) == 0)
14012 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
14013
14014 /* Merge the section attribute.
14015 We want to issue an error if the sections conflict but that must be
14016 done later in decl_attributes since we are called before attributes
14017 are assigned. */
14018 if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
14019 DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
14020
14021#if BUILT_FOR_270
14022 if (TREE_CODE (newdecl) == FUNCTION_DECL)
14023 {
14024 DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
14025 DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
14026 }
14027#endif
14028
14029 pop_obstacks ();
14030 }
14031 /* If cannot merge, then use the new type and qualifiers,
14032 and don't preserve the old rtl. */
14033 else
14034 {
14035 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
14036 TREE_READONLY (olddecl) = TREE_READONLY (newdecl);
14037 TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl);
14038 TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl);
14039 }
14040
14041 /* Merge the storage class information. */
14042 /* For functions, static overrides non-static. */
14043 if (TREE_CODE (newdecl) == FUNCTION_DECL)
14044 {
14045 TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
14046 /* This is since we don't automatically
14047 copy the attributes of NEWDECL into OLDDECL. */
14048 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
14049 /* If this clears `static', clear it in the identifier too. */
14050 if (! TREE_PUBLIC (olddecl))
14051 TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
14052 }
14053 if (DECL_EXTERNAL (newdecl))
14054 {
14055 TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
14056 DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
14057 /* An extern decl does not override previous storage class. */
14058 TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
14059 }
14060 else
14061 {
14062 TREE_STATIC (olddecl) = TREE_STATIC (newdecl);
14063 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
14064 }
14065
14066 /* If either decl says `inline', this fn is inline,
14067 unless its definition was passed already. */
14068 if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
14069 DECL_INLINE (olddecl) = 1;
14070 DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
14071
14072 /* Get rid of any built-in function if new arg types don't match it
14073 or if we have a function definition. */
14074 if (TREE_CODE (newdecl) == FUNCTION_DECL
14075 && DECL_BUILT_IN (olddecl)
14076 && (!types_match || new_is_definition))
14077 {
14078 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
14079 DECL_BUILT_IN (olddecl) = 0;
14080 }
14081
14082 /* If redeclaring a builtin function, and not a definition,
14083 it stays built in.
14084 Also preserve various other info from the definition. */
14085 if (TREE_CODE (newdecl) == FUNCTION_DECL && !new_is_definition)
14086 {
14087 if (DECL_BUILT_IN (olddecl))
14088 {
14089 DECL_BUILT_IN (newdecl) = 1;
14090 DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
14091 }
14092 else
14093 DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl);
14094
14095 DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
14096 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
14097 DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
14098 DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
14099 }
14100
14101 /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
14102 But preserve olddecl's DECL_UID. */
14103 {
14104 register unsigned olddecl_uid = DECL_UID (olddecl);
14105
34b8e428
JL
14106 memcpy ((char *) olddecl + sizeof (struct tree_common),
14107 (char *) newdecl + sizeof (struct tree_common),
14108 sizeof (struct tree_decl) - sizeof (struct tree_common));
5ff904cd
JL
14109 DECL_UID (olddecl) = olddecl_uid;
14110 }
14111
14112 return 1;
14113}
14114
14115/* Finish processing of a declaration;
14116 install its initial value.
14117 If the length of an array type is not known before,
14118 it must be determined now, from the initial value, or it is an error. */
14119
14120static void
14121finish_decl (tree decl, tree init, bool is_top_level)
14122{
14123 register tree type = TREE_TYPE (decl);
14124 int was_incomplete = (DECL_SIZE (decl) == 0);
14125 int temporary = allocation_temporary_p ();
14126 bool at_top_level = (current_binding_level == global_binding_level);
14127 bool top_level = is_top_level || at_top_level;
14128
14129 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
14130 level anyway. */
14131 assert (!is_top_level || !at_top_level);
14132
14133 if (TREE_CODE (decl) == PARM_DECL)
14134 assert (init == NULL_TREE);
14135 /* Remember that PARM_DECL doesn't have a DECL_INITIAL field per se -- it
14136 overlaps DECL_ARG_TYPE. */
14137 else if (init == NULL_TREE)
14138 assert (DECL_INITIAL (decl) == NULL_TREE);
14139 else
14140 assert (DECL_INITIAL (decl) == error_mark_node);
14141
14142 if (init != NULL_TREE)
14143 {
14144 if (TREE_CODE (decl) != TYPE_DECL)
14145 DECL_INITIAL (decl) = init;
14146 else
14147 {
14148 /* typedef foo = bar; store the type of bar as the type of foo. */
14149 TREE_TYPE (decl) = TREE_TYPE (init);
14150 DECL_INITIAL (decl) = init = 0;
14151 }
14152 }
14153
14154 /* Pop back to the obstack that is current for this binding level. This is
14155 because MAXINDEX, rtl, etc. to be made below must go in the permanent
14156 obstack. But don't discard the temporary data yet. */
14157 pop_obstacks ();
14158
14159 /* Deduce size of array from initialization, if not already known */
14160
14161 if (TREE_CODE (type) == ARRAY_TYPE
14162 && TYPE_DOMAIN (type) == 0
14163 && TREE_CODE (decl) != TYPE_DECL)
14164 {
14165 assert (top_level);
14166 assert (was_incomplete);
14167
14168 layout_decl (decl, 0);
14169 }
14170
14171 if (TREE_CODE (decl) == VAR_DECL)
14172 {
14173 if (DECL_SIZE (decl) == NULL_TREE
14174 && TYPE_SIZE (TREE_TYPE (decl)) != NULL_TREE)
14175 layout_decl (decl, 0);
14176
14177 if (DECL_SIZE (decl) == NULL_TREE
14178 && (TREE_STATIC (decl)
14179 ?
14180 /* A static variable with an incomplete type is an error if it is
14181 initialized. Also if it is not file scope. Otherwise, let it
14182 through, but if it is not `extern' then it may cause an error
14183 message later. */
14184 (DECL_INITIAL (decl) != 0 || DECL_CONTEXT (decl) != 0)
14185 :
14186 /* An automatic variable with an incomplete type is an error. */
14187 !DECL_EXTERNAL (decl)))
14188 {
14189 assert ("storage size not known" == NULL);
14190 abort ();
14191 }
14192
14193 if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
14194 && (DECL_SIZE (decl) != 0)
14195 && (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST))
14196 {
14197 assert ("storage size not constant" == NULL);
14198 abort ();
14199 }
14200 }
14201
14202 /* Output the assembler code and/or RTL code for variables and functions,
14203 unless the type is an undefined structure or union. If not, it will get
14204 done when the type is completed. */
14205
14206 if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
14207 {
14208 rest_of_decl_compilation (decl, NULL,
14209 DECL_CONTEXT (decl) == 0,
14210 0);
14211
14212 if (DECL_CONTEXT (decl) != 0)
14213 {
14214 /* Recompute the RTL of a local array now if it used to be an
14215 incomplete type. */
14216 if (was_incomplete
14217 && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
14218 {
14219 /* If we used it already as memory, it must stay in memory. */
14220 TREE_ADDRESSABLE (decl) = TREE_USED (decl);
14221 /* If it's still incomplete now, no init will save it. */
14222 if (DECL_SIZE (decl) == 0)
14223 DECL_INITIAL (decl) = 0;
14224 expand_decl (decl);
14225 }
14226 /* Compute and store the initial value. */
14227 if (TREE_CODE (decl) != FUNCTION_DECL)
14228 expand_decl_init (decl);
14229 }
14230 }
14231 else if (TREE_CODE (decl) == TYPE_DECL)
14232 {
14233 rest_of_decl_compilation (decl, NULL_PTR,
14234 DECL_CONTEXT (decl) == 0,
14235 0);
14236 }
14237
14238 /* This test used to include TREE_PERMANENT, however, we have the same
14239 problem with initializers at the function level. Such initializers get
14240 saved until the end of the function on the momentary_obstack. */
14241 if (!(TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))
14242 && temporary
14243 /* DECL_INITIAL is not defined in PARM_DECLs, since it shares space with
14244 DECL_ARG_TYPE. */
14245 && TREE_CODE (decl) != PARM_DECL)
14246 {
14247 /* We need to remember that this array HAD an initialization, but
14248 discard the actual temporary nodes, since we can't have a permanent
14249 node keep pointing to them. */
14250 /* We make an exception for inline functions, since it's normal for a
14251 local extern redeclaration of an inline function to have a copy of
14252 the top-level decl's DECL_INLINE. */
14253 if ((DECL_INITIAL (decl) != 0)
14254 && (DECL_INITIAL (decl) != error_mark_node))
14255 {
14256 /* If this is a const variable, then preserve the
14257 initializer instead of discarding it so that we can optimize
14258 references to it. */
14259 /* This test used to include TREE_STATIC, but this won't be set
14260 for function level initializers. */
14261 if (TREE_READONLY (decl))
14262 {
14263 preserve_initializer ();
14264 /* Hack? Set the permanent bit for something that is
14265 permanent, but not on the permenent obstack, so as to
14266 convince output_constant_def to make its rtl on the
14267 permanent obstack. */
14268 TREE_PERMANENT (DECL_INITIAL (decl)) = 1;
14269
14270 /* The initializer and DECL must have the same (or equivalent
14271 types), but if the initializer is a STRING_CST, its type
14272 might not be on the right obstack, so copy the type
14273 of DECL. */
14274 TREE_TYPE (DECL_INITIAL (decl)) = type;
14275 }
14276 else
14277 DECL_INITIAL (decl) = error_mark_node;
14278 }
14279 }
14280
14281 /* If requested, warn about definitions of large data objects. */
14282
14283 if (warn_larger_than
14284 && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
14285 && !DECL_EXTERNAL (decl))
14286 {
14287 register tree decl_size = DECL_SIZE (decl);
14288
14289 if (decl_size && TREE_CODE (decl_size) == INTEGER_CST)
14290 {
14291 unsigned units = TREE_INT_CST_LOW (decl_size) / BITS_PER_UNIT;
14292
14293 if (units > larger_than_size)
14294 warning_with_decl (decl, "size of `%s' is %u bytes", units);
14295 }
14296 }
14297
14298 /* If we have gone back from temporary to permanent allocation, actually
14299 free the temporary space that we no longer need. */
14300 if (temporary && !allocation_temporary_p ())
14301 permanent_allocation (0);
14302
14303 /* At the end of a declaration, throw away any variable type sizes of types
14304 defined inside that declaration. There is no use computing them in the
14305 following function definition. */
14306 if (current_binding_level == global_binding_level)
14307 get_pending_sizes ();
14308}
14309
14310/* Finish up a function declaration and compile that function
14311 all the way to assembler language output. The free the storage
14312 for the function definition.
14313
14314 This is called after parsing the body of the function definition.
14315
14316 NESTED is nonzero if the function being finished is nested in another. */
14317
14318static void
14319finish_function (int nested)
14320{
14321 register tree fndecl = current_function_decl;
14322
14323 assert (fndecl != NULL_TREE);
56a0044b
JL
14324 if (TREE_CODE (fndecl) != ERROR_MARK)
14325 {
14326 if (nested)
14327 assert (DECL_CONTEXT (fndecl) != NULL_TREE);
14328 else
14329 assert (DECL_CONTEXT (fndecl) == NULL_TREE);
14330 }
5ff904cd
JL
14331
14332/* TREE_READONLY (fndecl) = 1;
14333 This caused &foo to be of type ptr-to-const-function
14334 which then got a warning when stored in a ptr-to-function variable. */
14335
14336 poplevel (1, 0, 1);
5ff904cd 14337
56a0044b
JL
14338 if (TREE_CODE (fndecl) != ERROR_MARK)
14339 {
14340 BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
14341
14342 /* Must mark the RESULT_DECL as being in this function. */
5ff904cd 14343
56a0044b 14344 DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
5ff904cd 14345
56a0044b
JL
14346 /* Obey `register' declarations if `setjmp' is called in this fn. */
14347 /* Generate rtl for function exit. */
14348 expand_function_end (input_filename, lineno, 0);
5ff904cd 14349
56a0044b
JL
14350 /* So we can tell if jump_optimize sets it to 1. */
14351 can_reach_end = 0;
5ff904cd 14352
56a0044b
JL
14353 /* Run the optimizers and output the assembler code for this function. */
14354 rest_of_compilation (fndecl);
14355 }
5ff904cd
JL
14356
14357 /* Free all the tree nodes making up this function. */
14358 /* Switch back to allocating nodes permanently until we start another
14359 function. */
14360 if (!nested)
14361 permanent_allocation (1);
14362
56a0044b 14363 if (DECL_SAVED_INSNS (fndecl) == 0 && !nested && (TREE_CODE (fndecl) != ERROR_MARK))
5ff904cd
JL
14364 {
14365 /* Stop pointing to the local nodes about to be freed. */
14366 /* But DECL_INITIAL must remain nonzero so we know this was an actual
14367 function definition. */
14368 /* For a nested function, this is done in pop_f_function_context. */
14369 /* If rest_of_compilation set this to 0, leave it 0. */
14370 if (DECL_INITIAL (fndecl) != 0)
14371 DECL_INITIAL (fndecl) = error_mark_node;
14372 DECL_ARGUMENTS (fndecl) = 0;
14373 }
14374
14375 if (!nested)
14376 {
14377 /* Let the error reporting routines know that we're outside a function.
14378 For a nested function, this value is used in pop_c_function_context
14379 and then reset via pop_function_context. */
14380 ffecom_outer_function_decl_ = current_function_decl = NULL;
14381 }
14382}
14383
14384/* Plug-in replacement for identifying the name of a decl and, for a
14385 function, what we call it in diagnostics. For now, "program unit"
14386 should suffice, since it's a bit of a hassle to figure out which
14387 of several kinds of things it is. Note that it could conceivably
14388 be a statement function, which probably isn't really a program unit
14389 per se, but if that comes up, it should be easy to check (being a
14390 nested function and all). */
14391
14392static char *
8f87a563 14393lang_printable_name (tree decl, int v)
5ff904cd 14394{
b92f5cc0
JL
14395 /* Just to keep GCC quiet about the unused variable.
14396 In theory, differing values of V should produce different
14397 output. */
14398 switch (v)
14399 {
14400 default:
56a0044b
JL
14401 if (TREE_CODE (decl) == ERROR_MARK)
14402 return "erroneous code";
b92f5cc0
JL
14403 return IDENTIFIER_POINTER (DECL_NAME (decl));
14404 }
5ff904cd
JL
14405}
14406
14407/* g77's function to print out name of current function that caused
14408 an error. */
14409
14410#if BUILT_FOR_270
14411void
14412lang_print_error_function (file)
14413 char *file;
14414{
56a0044b 14415 static ffeglobal last_g = NULL;
5ff904cd 14416 static ffesymbol last_s = NULL;
56a0044b 14417 ffeglobal g;
5ff904cd
JL
14418 ffesymbol s;
14419 char *kind;
14420
56a0044b
JL
14421 if ((ffecom_primary_entry_ == NULL)
14422 || (ffesymbol_global (ffecom_primary_entry_) == NULL))
5ff904cd 14423 {
56a0044b 14424 g = NULL;
5ff904cd
JL
14425 s = NULL;
14426 kind = NULL;
14427 }
56a0044b 14428 else
5ff904cd 14429 {
56a0044b
JL
14430 g = ffesymbol_global (ffecom_primary_entry_);
14431 if (ffecom_nested_entry_ == NULL)
5ff904cd 14432 {
56a0044b
JL
14433 s = ffecom_primary_entry_;
14434 switch (ffesymbol_kind (s))
14435 {
14436 case FFEINFO_kindFUNCTION:
14437 kind = "function";
14438 break;
5ff904cd 14439
56a0044b
JL
14440 case FFEINFO_kindSUBROUTINE:
14441 kind = "subroutine";
14442 break;
5ff904cd 14443
56a0044b
JL
14444 case FFEINFO_kindPROGRAM:
14445 kind = "program";
14446 break;
5ff904cd 14447
56a0044b
JL
14448 case FFEINFO_kindBLOCKDATA:
14449 kind = "block-data";
14450 break;
5ff904cd 14451
56a0044b
JL
14452 default:
14453 kind = ffeinfo_kind_message (ffesymbol_kind (s));
14454 break;
14455 }
14456 }
14457 else
14458 {
14459 s = ffecom_nested_entry_;
14460 kind = "statement function";
5ff904cd 14461 }
5ff904cd
JL
14462 }
14463
56a0044b 14464 if ((last_g != g) || (last_s != s))
5ff904cd
JL
14465 {
14466 if (file)
14467 fprintf (stderr, "%s: ", file);
14468
14469 if (s == NULL)
14470 fprintf (stderr, "Outside of any program unit:\n");
14471 else
14472 {
14473 char *name = ffesymbol_text (s);
14474
14475 fprintf (stderr, "In %s `%s':\n", kind, name);
14476 }
14477
56a0044b 14478 last_g = g;
5ff904cd
JL
14479 last_s = s;
14480 }
14481}
14482#endif
14483
14484/* Similar to `lookup_name' but look only at current binding level. */
14485
14486static tree
14487lookup_name_current_level (tree name)
14488{
14489 register tree t;
14490
14491 if (current_binding_level == global_binding_level)
14492 return IDENTIFIER_GLOBAL_VALUE (name);
14493
14494 if (IDENTIFIER_LOCAL_VALUE (name) == 0)
14495 return 0;
14496
14497 for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
14498 if (DECL_NAME (t) == name)
14499 break;
14500
14501 return t;
14502}
14503
14504/* Create a new `struct binding_level'. */
14505
14506static struct binding_level *
14507make_binding_level ()
14508{
14509 /* NOSTRICT */
14510 return (struct binding_level *) xmalloc (sizeof (struct binding_level));
14511}
14512
14513/* Save and restore the variables in this file and elsewhere
14514 that keep track of the progress of compilation of the current function.
14515 Used for nested functions. */
14516
14517struct f_function
14518{
14519 struct f_function *next;
14520 tree named_labels;
14521 tree shadowed_labels;
14522 struct binding_level *binding_level;
14523};
14524
14525struct f_function *f_function_chain;
14526
14527/* Restore the variables used during compilation of a C function. */
14528
14529static void
14530pop_f_function_context ()
14531{
14532 struct f_function *p = f_function_chain;
14533 tree link;
14534
14535 /* Bring back all the labels that were shadowed. */
14536 for (link = shadowed_labels; link; link = TREE_CHAIN (link))
14537 if (DECL_NAME (TREE_VALUE (link)) != 0)
14538 IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)))
14539 = TREE_VALUE (link);
14540
14541 if (DECL_SAVED_INSNS (current_function_decl) == 0)
14542 {
14543 /* Stop pointing to the local nodes about to be freed. */
14544 /* But DECL_INITIAL must remain nonzero so we know this was an actual
14545 function definition. */
14546 DECL_INITIAL (current_function_decl) = error_mark_node;
14547 DECL_ARGUMENTS (current_function_decl) = 0;
14548 }
14549
14550 pop_function_context ();
14551
14552 f_function_chain = p->next;
14553
14554 named_labels = p->named_labels;
14555 shadowed_labels = p->shadowed_labels;
14556 current_binding_level = p->binding_level;
14557
14558 free (p);
14559}
14560
14561/* Save and reinitialize the variables
14562 used during compilation of a C function. */
14563
14564static void
14565push_f_function_context ()
14566{
14567 struct f_function *p
14568 = (struct f_function *) xmalloc (sizeof (struct f_function));
14569
14570 push_function_context ();
14571
14572 p->next = f_function_chain;
14573 f_function_chain = p;
14574
14575 p->named_labels = named_labels;
14576 p->shadowed_labels = shadowed_labels;
14577 p->binding_level = current_binding_level;
14578}
14579
14580static void
14581push_parm_decl (tree parm)
14582{
14583 int old_immediate_size_expand = immediate_size_expand;
14584
14585 /* Don't try computing parm sizes now -- wait till fn is called. */
14586
14587 immediate_size_expand = 0;
14588
14589 push_obstacks_nochange ();
14590
14591 /* Fill in arg stuff. */
14592
14593 DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
14594 DECL_ARG_TYPE_AS_WRITTEN (parm) = TREE_TYPE (parm);
14595 TREE_READONLY (parm) = 1; /* All implementation args are read-only. */
14596
14597 parm = pushdecl (parm);
14598
14599 immediate_size_expand = old_immediate_size_expand;
14600
14601 finish_decl (parm, NULL_TREE, FALSE);
14602}
14603
14604/* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, if appropriate. */
14605
14606static tree
14607pushdecl_top_level (x)
14608 tree x;
14609{
14610 register tree t;
14611 register struct binding_level *b = current_binding_level;
14612 register tree f = current_function_decl;
14613
14614 current_binding_level = global_binding_level;
14615 current_function_decl = NULL_TREE;
14616 t = pushdecl (x);
14617 current_binding_level = b;
14618 current_function_decl = f;
14619 return t;
14620}
14621
14622/* Store the list of declarations of the current level.
14623 This is done for the parameter declarations of a function being defined,
14624 after they are modified in the light of any missing parameters. */
14625
14626static tree
14627storedecls (decls)
14628 tree decls;
14629{
14630 return current_binding_level->names = decls;
14631}
14632
14633/* Store the parameter declarations into the current function declaration.
14634 This is called after parsing the parameter declarations, before
14635 digesting the body of the function.
14636
14637 For an old-style definition, modify the function's type
14638 to specify at least the number of arguments. */
14639
14640static void
14641store_parm_decls (int is_main_program UNUSED)
14642{
14643 register tree fndecl = current_function_decl;
14644
14645 /* This is a chain of PARM_DECLs from old-style parm declarations. */
14646 DECL_ARGUMENTS (fndecl) = storedecls (nreverse (getdecls ()));
14647
14648 /* Initialize the RTL code for the function. */
14649
14650 init_function_start (fndecl, input_filename, lineno);
14651
14652 /* Set up parameters and prepare for return, for the function. */
14653
14654 expand_function_start (fndecl, 0);
14655}
14656
14657static tree
14658start_decl (tree decl, bool is_top_level)
14659{
14660 register tree tem;
14661 bool at_top_level = (current_binding_level == global_binding_level);
14662 bool top_level = is_top_level || at_top_level;
14663
14664 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
14665 level anyway. */
14666 assert (!is_top_level || !at_top_level);
14667
14668 /* The corresponding pop_obstacks is in finish_decl. */
14669 push_obstacks_nochange ();
14670
14671 if (DECL_INITIAL (decl) != NULL_TREE)
14672 {
14673 assert (DECL_INITIAL (decl) == error_mark_node);
14674 assert (!DECL_EXTERNAL (decl));
14675 }
14676 else if (top_level)
14677 assert ((TREE_STATIC (decl) == 1) || DECL_EXTERNAL (decl) == 1);
14678
14679 /* For Fortran, we by default put things in .common when possible. */
14680 DECL_COMMON (decl) = 1;
14681
14682 /* Add this decl to the current binding level. TEM may equal DECL or it may
14683 be a previous decl of the same name. */
14684 if (is_top_level)
14685 tem = pushdecl_top_level (decl);
14686 else
14687 tem = pushdecl (decl);
14688
14689 /* For a local variable, define the RTL now. */
14690 if (!top_level
14691 /* But not if this is a duplicate decl and we preserved the rtl from the
14692 previous one (which may or may not happen). */
14693 && DECL_RTL (tem) == 0)
14694 {
14695 if (TYPE_SIZE (TREE_TYPE (tem)) != 0)
14696 expand_decl (tem);
14697 else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
14698 && DECL_INITIAL (tem) != 0)
14699 expand_decl (tem);
14700 }
14701
14702 if (DECL_INITIAL (tem) != NULL_TREE)
14703 {
14704 /* When parsing and digesting the initializer, use temporary storage.
14705 Do this even if we will ignore the value. */
14706 if (at_top_level)
14707 temporary_allocation ();
14708 }
14709
14710 return tem;
14711}
14712
14713/* Create the FUNCTION_DECL for a function definition.
14714 DECLSPECS and DECLARATOR are the parts of the declaration;
14715 they describe the function's name and the type it returns,
14716 but twisted together in a fashion that parallels the syntax of C.
14717
14718 This function creates a binding context for the function body
14719 as well as setting up the FUNCTION_DECL in current_function_decl.
14720
14721 Returns 1 on success. If the DECLARATOR is not suitable for a function
14722 (it defines a datum instead), we return 0, which tells
14723 yyparse to report a parse error.
14724
14725 NESTED is nonzero for a function nested within another function. */
14726
14727static void
14728start_function (tree name, tree type, int nested, int public)
14729{
14730 tree decl1;
14731 tree restype;
14732 int old_immediate_size_expand = immediate_size_expand;
14733
14734 named_labels = 0;
14735 shadowed_labels = 0;
14736
14737 /* Don't expand any sizes in the return type of the function. */
14738 immediate_size_expand = 0;
14739
14740 if (nested)
14741 {
14742 assert (!public);
14743 assert (current_function_decl != NULL_TREE);
14744 assert (DECL_CONTEXT (current_function_decl) == NULL_TREE);
14745 }
14746 else
14747 {
14748 assert (current_function_decl == NULL_TREE);
14749 }
14750
56a0044b
JL
14751 if (TREE_CODE (type) == ERROR_MARK)
14752 decl1 = current_function_decl = error_mark_node;
14753 else
14754 {
14755 decl1 = build_decl (FUNCTION_DECL,
14756 name,
14757 type);
14758 TREE_PUBLIC (decl1) = public ? 1 : 0;
14759 if (nested)
14760 DECL_INLINE (decl1) = 1;
14761 TREE_STATIC (decl1) = 1;
14762 DECL_EXTERNAL (decl1) = 0;
5ff904cd 14763
56a0044b 14764 announce_function (decl1);
5ff904cd 14765
56a0044b
JL
14766 /* Make the init_value nonzero so pushdecl knows this is not tentative.
14767 error_mark_node is replaced below (in poplevel) with the BLOCK. */
14768 DECL_INITIAL (decl1) = error_mark_node;
5ff904cd 14769
56a0044b
JL
14770 /* Record the decl so that the function name is defined. If we already have
14771 a decl for this name, and it is a FUNCTION_DECL, use the old decl. */
14772
14773 current_function_decl = pushdecl (decl1);
14774 }
5ff904cd 14775
5ff904cd
JL
14776 if (!nested)
14777 ffecom_outer_function_decl_ = current_function_decl;
14778
14779 pushlevel (0);
14780
56a0044b
JL
14781 if (TREE_CODE (current_function_decl) != ERROR_MARK)
14782 {
14783 make_function_rtl (current_function_decl);
5ff904cd 14784
56a0044b
JL
14785 restype = TREE_TYPE (TREE_TYPE (current_function_decl));
14786 DECL_RESULT (current_function_decl)
14787 = build_decl (RESULT_DECL, NULL_TREE, restype);
14788 }
5ff904cd
JL
14789
14790 if (!nested)
14791 /* Allocate further tree nodes temporarily during compilation of this
14792 function only. */
14793 temporary_allocation ();
14794
56a0044b 14795 if (!nested && (TREE_CODE (current_function_decl) != ERROR_MARK))
5ff904cd
JL
14796 TREE_ADDRESSABLE (current_function_decl) = 1;
14797
14798 immediate_size_expand = old_immediate_size_expand;
14799}
14800\f
14801/* Here are the public functions the GNU back end needs. */
14802
5ff904cd
JL
14803tree
14804convert (type, expr)
14805 tree type, expr;
14806{
14807 register tree e = expr;
14808 register enum tree_code code = TREE_CODE (type);
14809
14810 if (type == TREE_TYPE (e)
14811 || TREE_CODE (e) == ERROR_MARK)
14812 return e;
14813 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
14814 return fold (build1 (NOP_EXPR, type, e));
14815 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
14816 || code == ERROR_MARK)
14817 return error_mark_node;
14818 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
14819 {
14820 assert ("void value not ignored as it ought to be" == NULL);
14821 return error_mark_node;
14822 }
14823 if (code == VOID_TYPE)
14824 return build1 (CONVERT_EXPR, type, e);
14825 if ((code != RECORD_TYPE)
14826 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
14827 e = ffecom_1 (REALPART_EXPR, TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e))),
14828 e);
14829 if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
14830 return fold (convert_to_integer (type, e));
14831 if (code == POINTER_TYPE)
14832 return fold (convert_to_pointer (type, e));
14833 if (code == REAL_TYPE)
14834 return fold (convert_to_real (type, e));
14835 if (code == COMPLEX_TYPE)
14836 return fold (convert_to_complex (type, e));
14837 if (code == RECORD_TYPE)
14838 return fold (ffecom_convert_to_complex_ (type, e));
14839
14840 assert ("conversion to non-scalar type requested" == NULL);
14841 return error_mark_node;
14842}
14843
14844/* integrate_decl_tree calls this function, but since we don't use the
14845 DECL_LANG_SPECIFIC field, this is a no-op. */
14846
14847void
14848copy_lang_decl (node)
14849 tree node UNUSED;
14850{
14851}
14852
14853/* Return the list of declarations of the current level.
14854 Note that this list is in reverse order unless/until
14855 you nreverse it; and when you do nreverse it, you must
14856 store the result back using `storedecls' or you will lose. */
14857
14858tree
14859getdecls ()
14860{
14861 return current_binding_level->names;
14862}
14863
14864/* Nonzero if we are currently in the global binding level. */
14865
14866int
14867global_bindings_p ()
14868{
14869 return current_binding_level == global_binding_level;
14870}
14871
14872/* Insert BLOCK at the end of the list of subblocks of the
14873 current binding level. This is used when a BIND_EXPR is expanded,
14874 to handle the BLOCK node inside the BIND_EXPR. */
14875
14876void
14877incomplete_type_error (value, type)
14878 tree value UNUSED;
14879 tree type;
14880{
14881 if (TREE_CODE (type) == ERROR_MARK)
14882 return;
14883
14884 assert ("incomplete type?!?" == NULL);
14885}
14886
14887void
14888init_decl_processing ()
14889{
14890 malloc_init ();
14891 ffe_init_0 ();
14892}
14893
71b5e532 14894char *
77f77701
DB
14895init_parse (filename)
14896 char *filename;
5ff904cd
JL
14897{
14898#if BUILT_FOR_270
14899 extern void (*print_error_function) (char *);
14900#endif
14901
77f77701
DB
14902 /* Open input file. */
14903 if (filename == 0 || !strcmp (filename, "-"))
14904 {
14905 finput = stdin;
14906 filename = "stdin";
14907 }
14908 else
14909 finput = fopen (filename, "r");
14910 if (finput == 0)
14911 pfatal_with_name (filename);
14912
14913#ifdef IO_BUFFER_SIZE
14914 setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);
14915#endif
14916
5ff904cd
JL
14917 /* Make identifier nodes long enough for the language-specific slots. */
14918 set_identifier_size (sizeof (struct lang_identifier));
14919 decl_printable_name = lang_printable_name;
14920#if BUILT_FOR_270
14921 print_error_function = lang_print_error_function;
14922#endif
71b5e532
DB
14923
14924 return filename;
5ff904cd
JL
14925}
14926
77f77701
DB
14927void
14928finish_parse ()
14929{
14930 fclose (finput);
14931}
14932
5ff904cd
JL
14933void
14934insert_block (block)
14935 tree block;
14936{
14937 TREE_USED (block) = 1;
14938 current_binding_level->blocks
14939 = chainon (current_binding_level->blocks, block);
14940}
14941
14942int
ab9e0ff9
DB
14943lang_decode_option (argc, argv)
14944 int argc;
14945 char **argv;
5ff904cd 14946{
ab9e0ff9 14947 return ffe_decode_option (argc, argv);
5ff904cd
JL
14948}
14949
bc289659
ML
14950/* used by print-tree.c */
14951
14952void
14953lang_print_xnode (file, node, indent)
14954 FILE *file UNUSED;
14955 tree node UNUSED;
14956 int indent UNUSED;
14957{
14958}
14959
5ff904cd
JL
14960void
14961lang_finish ()
14962{
14963 ffe_terminate_0 ();
14964
14965 if (ffe_is_ffedebug ())
14966 malloc_pool_display (malloc_pool_image ());
14967}
14968
14969char *
14970lang_identify ()
14971{
14972 return "f77";
14973}
14974
f84639ba
RH
14975void
14976lang_init_options ()
14977{
14978 /* Set default options for Fortran. */
14979 flag_move_all_movables = 1;
14980 flag_reduce_all_givs = 1;
14981 flag_argument_noalias = 2;
14982}
14983
5ff904cd
JL
14984void
14985lang_init ()
14986{
5ff904cd
JL
14987 /* If the file is output from cpp, it should contain a first line
14988 `# 1 "real-filename"', and the current design of gcc (toplev.c
14989 in particular and the way it sets up information relied on by
14990 INCLUDE) requires that we read this now, and store the
14991 "real-filename" info in master_input_filename. Ask the lexer
14992 to try doing this. */
14993 ffelex_hash_kludge (finput);
14994}
14995
14996int
14997mark_addressable (exp)
14998 tree exp;
14999{
15000 register tree x = exp;
15001 while (1)
15002 switch (TREE_CODE (x))
15003 {
15004 case ADDR_EXPR:
15005 case COMPONENT_REF:
15006 case ARRAY_REF:
15007 x = TREE_OPERAND (x, 0);
15008 break;
15009
15010 case CONSTRUCTOR:
15011 TREE_ADDRESSABLE (x) = 1;
15012 return 1;
15013
15014 case VAR_DECL:
15015 case CONST_DECL:
15016 case PARM_DECL:
15017 case RESULT_DECL:
15018 if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)
15019 && DECL_NONLOCAL (x))
15020 {
15021 if (TREE_PUBLIC (x))
15022 {
15023 assert ("address of global register var requested" == NULL);
15024 return 0;
15025 }
15026 assert ("address of register variable requested" == NULL);
15027 }
15028 else if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x))
15029 {
15030 if (TREE_PUBLIC (x))
15031 {
15032 assert ("address of global register var requested" == NULL);
15033 return 0;
15034 }
15035 assert ("address of register var requested" == NULL);
15036 }
15037 put_var_into_stack (x);
15038
15039 /* drops in */
15040 case FUNCTION_DECL:
15041 TREE_ADDRESSABLE (x) = 1;
15042#if 0 /* poplevel deals with this now. */
15043 if (DECL_CONTEXT (x) == 0)
15044 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
15045#endif
15046
15047 default:
15048 return 1;
15049 }
15050}
15051
15052/* If DECL has a cleanup, build and return that cleanup here.
15053 This is a callback called by expand_expr. */
15054
15055tree
15056maybe_build_cleanup (decl)
15057 tree decl UNUSED;
15058{
15059 /* There are no cleanups in Fortran. */
15060 return NULL_TREE;
15061}
15062
15063/* Exit a binding level.
15064 Pop the level off, and restore the state of the identifier-decl mappings
15065 that were in effect when this level was entered.
15066
15067 If KEEP is nonzero, this level had explicit declarations, so
15068 and create a "block" (a BLOCK node) for the level
15069 to record its declarations and subblocks for symbol table output.
15070
15071 If FUNCTIONBODY is nonzero, this level is the body of a function,
15072 so create a block as if KEEP were set and also clear out all
15073 label names.
15074
15075 If REVERSE is nonzero, reverse the order of decls before putting
15076 them into the BLOCK. */
15077
15078tree
15079poplevel (keep, reverse, functionbody)
15080 int keep;
15081 int reverse;
15082 int functionbody;
15083{
15084 register tree link;
15085 /* The chain of decls was accumulated in reverse order. Put it into forward
15086 order, just for cleanliness. */
15087 tree decls;
15088 tree subblocks = current_binding_level->blocks;
15089 tree block = 0;
15090 tree decl;
15091 int block_previously_created;
15092
15093 /* Get the decls in the order they were written. Usually
15094 current_binding_level->names is in reverse order. But parameter decls
15095 were previously put in forward order. */
15096
15097 if (reverse)
15098 current_binding_level->names
15099 = decls = nreverse (current_binding_level->names);
15100 else
15101 decls = current_binding_level->names;
15102
15103 /* Output any nested inline functions within this block if they weren't
15104 already output. */
15105
15106 for (decl = decls; decl; decl = TREE_CHAIN (decl))
15107 if (TREE_CODE (decl) == FUNCTION_DECL
15108 && !TREE_ASM_WRITTEN (decl)
15109 && DECL_INITIAL (decl) != 0
15110 && TREE_ADDRESSABLE (decl))
15111 {
15112 /* If this decl was copied from a file-scope decl on account of a
15113 block-scope extern decl, propagate TREE_ADDRESSABLE to the
15114 file-scope decl. */
15115 if (DECL_ABSTRACT_ORIGIN (decl) != 0)
15116 TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
15117 else
15118 {
15119 push_function_context ();
15120 output_inline_function (decl);
15121 pop_function_context ();
15122 }
15123 }
15124
15125 /* If there were any declarations or structure tags in that level, or if
15126 this level is a function body, create a BLOCK to record them for the
15127 life of this function. */
15128
15129 block = 0;
15130 block_previously_created = (current_binding_level->this_block != 0);
15131 if (block_previously_created)
15132 block = current_binding_level->this_block;
15133 else if (keep || functionbody)
15134 block = make_node (BLOCK);
15135 if (block != 0)
15136 {
15137 BLOCK_VARS (block) = decls;
15138 BLOCK_SUBBLOCKS (block) = subblocks;
15139 remember_end_note (block);
15140 }
15141
15142 /* In each subblock, record that this is its superior. */
15143
15144 for (link = subblocks; link; link = TREE_CHAIN (link))
15145 BLOCK_SUPERCONTEXT (link) = block;
15146
15147 /* Clear out the meanings of the local variables of this level. */
15148
15149 for (link = decls; link; link = TREE_CHAIN (link))
15150 {
15151 if (DECL_NAME (link) != 0)
15152 {
15153 /* If the ident. was used or addressed via a local extern decl,
15154 don't forget that fact. */
15155 if (DECL_EXTERNAL (link))
15156 {
15157 if (TREE_USED (link))
15158 TREE_USED (DECL_NAME (link)) = 1;
15159 if (TREE_ADDRESSABLE (link))
15160 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
15161 }
15162 IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0;
15163 }
15164 }
15165
15166 /* If the level being exited is the top level of a function, check over all
15167 the labels, and clear out the current (function local) meanings of their
15168 names. */
15169
15170 if (functionbody)
15171 {
15172 /* If this is the top level block of a function, the vars are the
15173 function's parameters. Don't leave them in the BLOCK because they
15174 are found in the FUNCTION_DECL instead. */
15175
15176 BLOCK_VARS (block) = 0;
15177 }
15178
15179 /* Pop the current level, and free the structure for reuse. */
15180
15181 {
15182 register struct binding_level *level = current_binding_level;
15183 current_binding_level = current_binding_level->level_chain;
15184
15185 level->level_chain = free_binding_level;
15186 free_binding_level = level;
15187 }
15188
15189 /* Dispose of the block that we just made inside some higher level. */
15190 if (functionbody)
15191 DECL_INITIAL (current_function_decl) = block;
15192 else if (block)
15193 {
15194 if (!block_previously_created)
15195 current_binding_level->blocks
15196 = chainon (current_binding_level->blocks, block);
15197 }
15198 /* If we did not make a block for the level just exited, any blocks made
15199 for inner levels (since they cannot be recorded as subblocks in that
15200 level) must be carried forward so they will later become subblocks of
15201 something else. */
15202 else if (subblocks)
15203 current_binding_level->blocks
15204 = chainon (current_binding_level->blocks, subblocks);
15205
15206 /* Set the TYPE_CONTEXTs for all of the tagged types belonging to this
15207 binding contour so that they point to the appropriate construct, i.e.
15208 either to the current FUNCTION_DECL node, or else to the BLOCK node we
15209 just constructed.
15210
15211 Note that for tagged types whose scope is just the formal parameter list
15212 for some function type specification, we can't properly set their
15213 TYPE_CONTEXTs here, because we don't have a pointer to the appropriate
15214 FUNCTION_TYPE node readily available to us. For those cases, the
15215 TYPE_CONTEXTs of the relevant tagged type nodes get set in
15216 `grokdeclarator' as soon as we have created the FUNCTION_TYPE node which
15217 will represent the "scope" for these "parameter list local" tagged
15218 types. */
15219
15220 if (block)
15221 TREE_USED (block) = 1;
15222 return block;
15223}
15224
15225void
15226print_lang_decl (file, node, indent)
15227 FILE *file UNUSED;
15228 tree node UNUSED;
15229 int indent UNUSED;
15230{
15231}
15232
15233void
15234print_lang_identifier (file, node, indent)
15235 FILE *file;
15236 tree node;
15237 int indent;
15238{
15239 print_node (file, "global", IDENTIFIER_GLOBAL_VALUE (node), indent + 4);
15240 print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4);
15241}
15242
15243void
15244print_lang_statistics ()
15245{
15246}
15247
15248void
15249print_lang_type (file, node, indent)
15250 FILE *file UNUSED;
15251 tree node UNUSED;
15252 int indent UNUSED;
15253{
15254}
15255
15256/* Record a decl-node X as belonging to the current lexical scope.
15257 Check for errors (such as an incompatible declaration for the same
15258 name already seen in the same scope).
15259
15260 Returns either X or an old decl for the same name.
15261 If an old decl is returned, it may have been smashed
15262 to agree with what X says. */
15263
15264tree
15265pushdecl (x)
15266 tree x;
15267{
15268 register tree t;
15269 register tree name = DECL_NAME (x);
15270 register struct binding_level *b = current_binding_level;
15271
15272 if ((TREE_CODE (x) == FUNCTION_DECL)
15273 && (DECL_INITIAL (x) == 0)
15274 && DECL_EXTERNAL (x))
15275 DECL_CONTEXT (x) = NULL_TREE;
15276 else
15277 DECL_CONTEXT (x) = current_function_decl;
15278
15279 if (name)
15280 {
15281 if (IDENTIFIER_INVENTED (name))
15282 {
15283#if BUILT_FOR_270
15284 DECL_ARTIFICIAL (x) = 1;
15285#endif
15286 DECL_IN_SYSTEM_HEADER (x) = 1;
5ff904cd
JL
15287 }
15288
15289 t = lookup_name_current_level (name);
15290
15291 assert ((t == NULL_TREE) || (DECL_CONTEXT (x) == NULL_TREE));
15292
15293 /* Don't push non-parms onto list for parms until we understand
15294 why we're doing this and whether it works. */
15295
15296 assert ((b == global_binding_level)
15297 || !ffecom_transform_only_dummies_
15298 || TREE_CODE (x) == PARM_DECL);
15299
15300 if ((t != NULL_TREE) && duplicate_decls (x, t))
15301 return t;
15302
15303 /* If we are processing a typedef statement, generate a whole new
15304 ..._TYPE node (which will be just an variant of the existing
15305 ..._TYPE node with identical properties) and then install the
15306 TYPE_DECL node generated to represent the typedef name as the
15307 TYPE_NAME of this brand new (duplicate) ..._TYPE node.
15308
15309 The whole point here is to end up with a situation where each and every
15310 ..._TYPE node the compiler creates will be uniquely associated with
15311 AT MOST one node representing a typedef name. This way, even though
15312 the compiler substitutes corresponding ..._TYPE nodes for TYPE_DECL
15313 (i.e. "typedef name") nodes very early on, later parts of the
15314 compiler can always do the reverse translation and get back the
15315 corresponding typedef name. For example, given:
15316
15317 typedef struct S MY_TYPE; MY_TYPE object;
15318
15319 Later parts of the compiler might only know that `object' was of type
38e01259 15320 `struct S' if it were not for code just below. With this code
5ff904cd
JL
15321 however, later parts of the compiler see something like:
15322
15323 struct S' == struct S typedef struct S' MY_TYPE; struct S' object;
15324
15325 And they can then deduce (from the node for type struct S') that the
15326 original object declaration was:
15327
15328 MY_TYPE object;
15329
15330 Being able to do this is important for proper support of protoize, and
15331 also for generating precise symbolic debugging information which
15332 takes full account of the programmer's (typedef) vocabulary.
15333
15334 Obviously, we don't want to generate a duplicate ..._TYPE node if the
15335 TYPE_DECL node that we are now processing really represents a
15336 standard built-in type.
15337
15338 Since all standard types are effectively declared at line zero in the
15339 source file, we can easily check to see if we are working on a
15340 standard type by checking the current value of lineno. */
15341
15342 if (TREE_CODE (x) == TYPE_DECL)
15343 {
15344 if (DECL_SOURCE_LINE (x) == 0)
15345 {
15346 if (TYPE_NAME (TREE_TYPE (x)) == 0)
15347 TYPE_NAME (TREE_TYPE (x)) = x;
15348 }
15349 else if (TREE_TYPE (x) != error_mark_node)
15350 {
15351 tree tt = TREE_TYPE (x);
15352
15353 tt = build_type_copy (tt);
15354 TYPE_NAME (tt) = x;
15355 TREE_TYPE (x) = tt;
15356 }
15357 }
15358
15359 /* This name is new in its binding level. Install the new declaration
15360 and return it. */
15361 if (b == global_binding_level)
15362 IDENTIFIER_GLOBAL_VALUE (name) = x;
15363 else
15364 IDENTIFIER_LOCAL_VALUE (name) = x;
15365 }
15366
15367 /* Put decls on list in reverse order. We will reverse them later if
15368 necessary. */
15369 TREE_CHAIN (x) = b->names;
15370 b->names = x;
15371
15372 return x;
15373}
15374
15375/* Enter a new binding level.
15376 If TAG_TRANSPARENT is nonzero, do so only for the name space of variables,
15377 not for that of tags. */
15378
15379void
15380pushlevel (tag_transparent)
15381 int tag_transparent;
15382{
15383 register struct binding_level *newlevel = NULL_BINDING_LEVEL;
15384
15385 assert (!tag_transparent);
15386
15387 /* Reuse or create a struct for this binding level. */
15388
15389 if (free_binding_level)
15390 {
15391 newlevel = free_binding_level;
15392 free_binding_level = free_binding_level->level_chain;
15393 }
15394 else
15395 {
15396 newlevel = make_binding_level ();
15397 }
15398
15399 /* Add this level to the front of the chain (stack) of levels that are
15400 active. */
15401
15402 *newlevel = clear_binding_level;
15403 newlevel->level_chain = current_binding_level;
15404 current_binding_level = newlevel;
15405}
15406
15407/* Set the BLOCK node for the innermost scope
15408 (the one we are currently in). */
15409
15410void
15411set_block (block)
15412 register tree block;
15413{
15414 current_binding_level->this_block = block;
15415}
15416
15417/* ~~tree.h SHOULD declare this, because toplev.c references it. */
15418
15419/* Can't 'yydebug' a front end not generated by yacc/bison! */
15420
15421void
15422set_yydebug (value)
15423 int value;
15424{
15425 if (value)
15426 fprintf (stderr, "warning: no yacc/bison-generated output to debug!\n");
15427}
15428
15429tree
15430signed_or_unsigned_type (unsignedp, type)
15431 int unsignedp;
15432 tree type;
15433{
15434 tree type2;
15435
15436 if (! INTEGRAL_TYPE_P (type))
15437 return type;
15438 if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
15439 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15440 if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
15441 return unsignedp ? unsigned_type_node : integer_type_node;
15442 if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node))
15443 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15444 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node))
15445 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15446 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node))
15447 return (unsignedp ? long_long_unsigned_type_node
15448 : long_long_integer_type_node);
15449
15450 type2 = type_for_size (TYPE_PRECISION (type), unsignedp);
15451 if (type2 == NULL_TREE)
15452 return type;
15453
15454 return type2;
15455}
15456
15457tree
15458signed_type (type)
15459 tree type;
15460{
15461 tree type1 = TYPE_MAIN_VARIANT (type);
15462 ffeinfoKindtype kt;
15463 tree type2;
15464
15465 if (type1 == unsigned_char_type_node || type1 == char_type_node)
15466 return signed_char_type_node;
15467 if (type1 == unsigned_type_node)
15468 return integer_type_node;
15469 if (type1 == short_unsigned_type_node)
15470 return short_integer_type_node;
15471 if (type1 == long_unsigned_type_node)
15472 return long_integer_type_node;
15473 if (type1 == long_long_unsigned_type_node)
15474 return long_long_integer_type_node;
15475#if 0 /* gcc/c-* files only */
15476 if (type1 == unsigned_intDI_type_node)
15477 return intDI_type_node;
15478 if (type1 == unsigned_intSI_type_node)
15479 return intSI_type_node;
15480 if (type1 == unsigned_intHI_type_node)
15481 return intHI_type_node;
15482 if (type1 == unsigned_intQI_type_node)
15483 return intQI_type_node;
15484#endif
15485
15486 type2 = type_for_size (TYPE_PRECISION (type1), 0);
15487 if (type2 != NULL_TREE)
15488 return type2;
15489
15490 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15491 {
15492 type2 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
15493
15494 if (type1 == type2)
15495 return ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15496 }
15497
15498 return type;
15499}
15500
15501/* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
15502 or validate its data type for an `if' or `while' statement or ?..: exp.
15503
15504 This preparation consists of taking the ordinary
15505 representation of an expression expr and producing a valid tree
15506 boolean expression describing whether expr is nonzero. We could
15507 simply always do build_binary_op (NE_EXPR, expr, integer_zero_node, 1),
15508 but we optimize comparisons, &&, ||, and !.
15509
15510 The resulting type should always be `integer_type_node'. */
15511
15512tree
15513truthvalue_conversion (expr)
15514 tree expr;
15515{
15516 if (TREE_CODE (expr) == ERROR_MARK)
15517 return expr;
15518
15519#if 0 /* This appears to be wrong for C++. */
15520 /* These really should return error_mark_node after 2.4 is stable.
15521 But not all callers handle ERROR_MARK properly. */
15522 switch (TREE_CODE (TREE_TYPE (expr)))
15523 {
15524 case RECORD_TYPE:
15525 error ("struct type value used where scalar is required");
15526 return integer_zero_node;
15527
15528 case UNION_TYPE:
15529 error ("union type value used where scalar is required");
15530 return integer_zero_node;
15531
15532 case ARRAY_TYPE:
15533 error ("array type value used where scalar is required");
15534 return integer_zero_node;
15535
15536 default:
15537 break;
15538 }
15539#endif /* 0 */
15540
15541 switch (TREE_CODE (expr))
15542 {
15543 /* It is simpler and generates better code to have only TRUTH_*_EXPR
15544 or comparison expressions as truth values at this level. */
15545#if 0
15546 case COMPONENT_REF:
15547 /* A one-bit unsigned bit-field is already acceptable. */
15548 if (1 == TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (expr, 1)))
15549 && TREE_UNSIGNED (TREE_OPERAND (expr, 1)))
15550 return expr;
15551 break;
15552#endif
15553
15554 case EQ_EXPR:
15555 /* It is simpler and generates better code to have only TRUTH_*_EXPR
15556 or comparison expressions as truth values at this level. */
15557#if 0
15558 if (integer_zerop (TREE_OPERAND (expr, 1)))
15559 return build_unary_op (TRUTH_NOT_EXPR, TREE_OPERAND (expr, 0), 0);
15560#endif
15561 case NE_EXPR: case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
15562 case TRUTH_ANDIF_EXPR:
15563 case TRUTH_ORIF_EXPR:
15564 case TRUTH_AND_EXPR:
15565 case TRUTH_OR_EXPR:
15566 case TRUTH_XOR_EXPR:
15567 TREE_TYPE (expr) = integer_type_node;
15568 return expr;
15569
15570 case ERROR_MARK:
15571 return expr;
15572
15573 case INTEGER_CST:
15574 return integer_zerop (expr) ? integer_zero_node : integer_one_node;
15575
15576 case REAL_CST:
15577 return real_zerop (expr) ? integer_zero_node : integer_one_node;
15578
15579 case ADDR_EXPR:
15580 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0)))
15581 return build (COMPOUND_EXPR, integer_type_node,
15582 TREE_OPERAND (expr, 0), integer_one_node);
15583 else
15584 return integer_one_node;
15585
15586 case COMPLEX_EXPR:
15587 return ffecom_2 ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
15588 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15589 integer_type_node,
15590 truthvalue_conversion (TREE_OPERAND (expr, 0)),
15591 truthvalue_conversion (TREE_OPERAND (expr, 1)));
15592
15593 case NEGATE_EXPR:
15594 case ABS_EXPR:
15595 case FLOAT_EXPR:
15596 case FFS_EXPR:
15597 /* These don't change whether an object is non-zero or zero. */
15598 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15599
15600 case LROTATE_EXPR:
15601 case RROTATE_EXPR:
15602 /* These don't change whether an object is zero or non-zero, but
15603 we can't ignore them if their second arg has side-effects. */
15604 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
15605 return build (COMPOUND_EXPR, integer_type_node, TREE_OPERAND (expr, 1),
15606 truthvalue_conversion (TREE_OPERAND (expr, 0)));
15607 else
15608 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15609
15610 case COND_EXPR:
15611 /* Distribute the conversion into the arms of a COND_EXPR. */
15612 return fold (build (COND_EXPR, integer_type_node, TREE_OPERAND (expr, 0),
15613 truthvalue_conversion (TREE_OPERAND (expr, 1)),
15614 truthvalue_conversion (TREE_OPERAND (expr, 2))));
15615
15616 case CONVERT_EXPR:
15617 /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
15618 since that affects how `default_conversion' will behave. */
15619 if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE
15620 || TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
15621 break;
15622 /* fall through... */
15623 case NOP_EXPR:
15624 /* If this is widening the argument, we can ignore it. */
15625 if (TYPE_PRECISION (TREE_TYPE (expr))
15626 >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
15627 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15628 break;
15629
15630 case MINUS_EXPR:
15631 /* With IEEE arithmetic, x - x may not equal 0, so we can't optimize
15632 this case. */
15633 if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
15634 && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE)
15635 break;
15636 /* fall through... */
15637 case BIT_XOR_EXPR:
15638 /* This and MINUS_EXPR can be changed into a comparison of the
15639 two objects. */
15640 if (TREE_TYPE (TREE_OPERAND (expr, 0))
15641 == TREE_TYPE (TREE_OPERAND (expr, 1)))
15642 return ffecom_2 (NE_EXPR, integer_type_node,
15643 TREE_OPERAND (expr, 0),
15644 TREE_OPERAND (expr, 1));
15645 return ffecom_2 (NE_EXPR, integer_type_node,
15646 TREE_OPERAND (expr, 0),
15647 fold (build1 (NOP_EXPR,
15648 TREE_TYPE (TREE_OPERAND (expr, 0)),
15649 TREE_OPERAND (expr, 1))));
15650
15651 case BIT_AND_EXPR:
15652 if (integer_onep (TREE_OPERAND (expr, 1)))
15653 return expr;
15654 break;
15655
15656 case MODIFY_EXPR:
15657#if 0 /* No such thing in Fortran. */
15658 if (warn_parentheses && C_EXP_ORIGINAL_CODE (expr) == MODIFY_EXPR)
15659 warning ("suggest parentheses around assignment used as truth value");
15660#endif
15661 break;
15662
15663 default:
15664 break;
15665 }
15666
15667 if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
15668 return (ffecom_2
15669 ((TREE_SIDE_EFFECTS (expr)
15670 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15671 integer_type_node,
15672 truthvalue_conversion (ffecom_1 (REALPART_EXPR,
15673 TREE_TYPE (TREE_TYPE (expr)),
15674 expr)),
15675 truthvalue_conversion (ffecom_1 (IMAGPART_EXPR,
15676 TREE_TYPE (TREE_TYPE (expr)),
15677 expr))));
15678
15679 return ffecom_2 (NE_EXPR, integer_type_node,
15680 expr,
15681 convert (TREE_TYPE (expr), integer_zero_node));
15682}
15683
15684tree
15685type_for_mode (mode, unsignedp)
15686 enum machine_mode mode;
15687 int unsignedp;
15688{
15689 int i;
15690 int j;
15691 tree t;
15692
15693 if (mode == TYPE_MODE (integer_type_node))
15694 return unsignedp ? unsigned_type_node : integer_type_node;
15695
15696 if (mode == TYPE_MODE (signed_char_type_node))
15697 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15698
15699 if (mode == TYPE_MODE (short_integer_type_node))
15700 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15701
15702 if (mode == TYPE_MODE (long_integer_type_node))
15703 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15704
15705 if (mode == TYPE_MODE (long_long_integer_type_node))
15706 return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
15707
15708 if (mode == TYPE_MODE (float_type_node))
15709 return float_type_node;
15710
15711 if (mode == TYPE_MODE (double_type_node))
15712 return double_type_node;
15713
15714 if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
15715 return build_pointer_type (char_type_node);
15716
15717 if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
15718 return build_pointer_type (integer_type_node);
15719
15720 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
15721 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
15722 {
15723 if (((t = ffecom_tree_type[i][j]) != NULL_TREE)
15724 && (mode == TYPE_MODE (t)))
567f3d36
KG
15725 {
15726 if ((i == FFEINFO_basictypeINTEGER) && unsignedp)
15727 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][j];
15728 else
15729 return t;
15730 }
5ff904cd
JL
15731 }
15732
15733 return 0;
15734}
15735
15736tree
15737type_for_size (bits, unsignedp)
15738 unsigned bits;
15739 int unsignedp;
15740{
15741 ffeinfoKindtype kt;
15742 tree type_node;
15743
15744 if (bits == TYPE_PRECISION (integer_type_node))
15745 return unsignedp ? unsigned_type_node : integer_type_node;
15746
15747 if (bits == TYPE_PRECISION (signed_char_type_node))
15748 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15749
15750 if (bits == TYPE_PRECISION (short_integer_type_node))
15751 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15752
15753 if (bits == TYPE_PRECISION (long_integer_type_node))
15754 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15755
15756 if (bits == TYPE_PRECISION (long_long_integer_type_node))
15757 return (unsignedp ? long_long_unsigned_type_node
15758 : long_long_integer_type_node);
15759
15760 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15761 {
15762 type_node = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15763
15764 if ((type_node != NULL_TREE) && (bits == TYPE_PRECISION (type_node)))
15765 return unsignedp ? ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt]
15766 : type_node;
15767 }
15768
15769 return 0;
15770}
15771
15772tree
15773unsigned_type (type)
15774 tree type;
15775{
15776 tree type1 = TYPE_MAIN_VARIANT (type);
15777 ffeinfoKindtype kt;
15778 tree type2;
15779
15780 if (type1 == signed_char_type_node || type1 == char_type_node)
15781 return unsigned_char_type_node;
15782 if (type1 == integer_type_node)
15783 return unsigned_type_node;
15784 if (type1 == short_integer_type_node)
15785 return short_unsigned_type_node;
15786 if (type1 == long_integer_type_node)
15787 return long_unsigned_type_node;
15788 if (type1 == long_long_integer_type_node)
15789 return long_long_unsigned_type_node;
15790#if 0 /* gcc/c-* files only */
15791 if (type1 == intDI_type_node)
15792 return unsigned_intDI_type_node;
15793 if (type1 == intSI_type_node)
15794 return unsigned_intSI_type_node;
15795 if (type1 == intHI_type_node)
15796 return unsigned_intHI_type_node;
15797 if (type1 == intQI_type_node)
15798 return unsigned_intQI_type_node;
15799#endif
15800
15801 type2 = type_for_size (TYPE_PRECISION (type1), 1);
15802 if (type2 != NULL_TREE)
15803 return type2;
15804
15805 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15806 {
15807 type2 = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15808
15809 if (type1 == type2)
15810 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
15811 }
15812
15813 return type;
15814}
15815
15816#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
15817\f
15818#if FFECOM_GCC_INCLUDE
15819
15820/* From gcc/cccp.c, the code to handle -I. */
15821
15822/* Skip leading "./" from a directory name.
15823 This may yield the empty string, which represents the current directory. */
15824
15825static char *
15826skip_redundant_dir_prefix (char *dir)
15827{
15828 while (dir[0] == '.' && dir[1] == '/')
15829 for (dir += 2; *dir == '/'; dir++)
15830 continue;
15831 if (dir[0] == '.' && !dir[1])
15832 dir++;
15833 return dir;
15834}
15835
15836/* The file_name_map structure holds a mapping of file names for a
15837 particular directory. This mapping is read from the file named
15838 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
15839 map filenames on a file system with severe filename restrictions,
15840 such as DOS. The format of the file name map file is just a series
15841 of lines with two tokens on each line. The first token is the name
15842 to map, and the second token is the actual name to use. */
15843
15844struct file_name_map
15845{
15846 struct file_name_map *map_next;
15847 char *map_from;
15848 char *map_to;
15849};
15850
15851#define FILE_NAME_MAP_FILE "header.gcc"
15852
15853/* Current maximum length of directory names in the search path
15854 for include files. (Altered as we get more of them.) */
15855
15856static int max_include_len = 0;
15857
15858struct file_name_list
15859 {
15860 struct file_name_list *next;
15861 char *fname;
15862 /* Mapping of file names for this directory. */
15863 struct file_name_map *name_map;
15864 /* Non-zero if name_map is valid. */
15865 int got_name_map;
15866 };
15867
15868static struct file_name_list *include = NULL; /* First dir to search */
15869static struct file_name_list *last_include = NULL; /* Last in chain */
15870
15871/* I/O buffer structure.
15872 The `fname' field is nonzero for source files and #include files
15873 and for the dummy text used for -D and -U.
15874 It is zero for rescanning results of macro expansion
15875 and for expanding macro arguments. */
15876#define INPUT_STACK_MAX 400
15877static struct file_buf {
15878 char *fname;
15879 /* Filename specified with #line command. */
15880 char *nominal_fname;
15881 /* Record where in the search path this file was found.
15882 For #include_next. */
15883 struct file_name_list *dir;
15884 ffewhereLine line;
15885 ffewhereColumn column;
15886} instack[INPUT_STACK_MAX];
15887
15888static int last_error_tick = 0; /* Incremented each time we print it. */
15889static int input_file_stack_tick = 0; /* Incremented when status changes. */
15890
15891/* Current nesting level of input sources.
15892 `instack[indepth]' is the level currently being read. */
15893static int indepth = -1;
15894
15895typedef struct file_buf FILE_BUF;
15896
15897typedef unsigned char U_CHAR;
15898
15899/* table to tell if char can be part of a C identifier. */
15900U_CHAR is_idchar[256];
15901/* table to tell if char can be first char of a c identifier. */
15902U_CHAR is_idstart[256];
15903/* table to tell if c is horizontal space. */
15904U_CHAR is_hor_space[256];
15905/* table to tell if c is horizontal or vertical space. */
15906static U_CHAR is_space[256];
15907
15908#define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
15909#define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*p]) p++; } while (0)
15910
15911/* Nonzero means -I- has been seen,
15912 so don't look for #include "foo" the source-file directory. */
15913static int ignore_srcdir;
15914
15915#ifndef INCLUDE_LEN_FUDGE
15916#define INCLUDE_LEN_FUDGE 0
15917#endif
15918
15919static void append_include_chain (struct file_name_list *first,
15920 struct file_name_list *last);
15921static FILE *open_include_file (char *filename,
15922 struct file_name_list *searchptr);
15923static void print_containing_files (ffebadSeverity sev);
15924static char *skip_redundant_dir_prefix (char *);
15925static char *read_filename_string (int ch, FILE *f);
15926static struct file_name_map *read_name_map (char *dirname);
15927static char *savestring (char *input);
15928
15929/* Append a chain of `struct file_name_list's
15930 to the end of the main include chain.
15931 FIRST is the beginning of the chain to append, and LAST is the end. */
15932
15933static void
15934append_include_chain (first, last)
15935 struct file_name_list *first, *last;
15936{
15937 struct file_name_list *dir;
15938
15939 if (!first || !last)
15940 return;
15941
15942 if (include == 0)
15943 include = first;
15944 else
15945 last_include->next = first;
15946
15947 for (dir = first; ; dir = dir->next) {
15948 int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE;
15949 if (len > max_include_len)
15950 max_include_len = len;
15951 if (dir == last)
15952 break;
15953 }
15954
15955 last->next = NULL;
15956 last_include = last;
15957}
15958
15959/* Try to open include file FILENAME. SEARCHPTR is the directory
15960 being tried from the include file search path. This function maps
15961 filenames on file systems based on information read by
15962 read_name_map. */
15963
15964static FILE *
15965open_include_file (filename, searchptr)
15966 char *filename;
15967 struct file_name_list *searchptr;
15968{
15969 register struct file_name_map *map;
15970 register char *from;
15971 char *p, *dir;
15972
15973 if (searchptr && ! searchptr->got_name_map)
15974 {
15975 searchptr->name_map = read_name_map (searchptr->fname
15976 ? searchptr->fname : ".");
15977 searchptr->got_name_map = 1;
15978 }
15979
15980 /* First check the mapping for the directory we are using. */
15981 if (searchptr && searchptr->name_map)
15982 {
15983 from = filename;
15984 if (searchptr->fname)
15985 from += strlen (searchptr->fname) + 1;
15986 for (map = searchptr->name_map; map; map = map->map_next)
15987 {
15988 if (! strcmp (map->map_from, from))
15989 {
15990 /* Found a match. */
15991 return fopen (map->map_to, "r");
15992 }
15993 }
15994 }
15995
15996 /* Try to find a mapping file for the particular directory we are
15997 looking in. Thus #include <sys/types.h> will look up sys/types.h
15998 in /usr/include/header.gcc and look up types.h in
15999 /usr/include/sys/header.gcc. */
16000 p = rindex (filename, '/');
16001#ifdef DIR_SEPARATOR
16002 if (! p) p = rindex (filename, DIR_SEPARATOR);
16003 else {
16004 char *tmp = rindex (filename, DIR_SEPARATOR);
16005 if (tmp != NULL && tmp > p) p = tmp;
16006 }
16007#endif
16008 if (! p)
16009 p = filename;
16010 if (searchptr
16011 && searchptr->fname
16012 && strlen (searchptr->fname) == (size_t) (p - filename)
16013 && ! strncmp (searchptr->fname, filename, (int) (p - filename)))
16014 {
16015 /* FILENAME is in SEARCHPTR, which we've already checked. */
16016 return fopen (filename, "r");
16017 }
16018
16019 if (p == filename)
16020 {
16021 from = filename;
16022 map = read_name_map (".");
16023 }
16024 else
16025 {
16026 dir = (char *) xmalloc (p - filename + 1);
34b8e428 16027 memcpy (dir, filename, p - filename);
5ff904cd
JL
16028 dir[p - filename] = '\0';
16029 from = p + 1;
16030 map = read_name_map (dir);
16031 free (dir);
16032 }
16033 for (; map; map = map->map_next)
16034 if (! strcmp (map->map_from, from))
16035 return fopen (map->map_to, "r");
16036
16037 return fopen (filename, "r");
16038}
16039
16040/* Print the file names and line numbers of the #include
16041 commands which led to the current file. */
16042
16043static void
16044print_containing_files (ffebadSeverity sev)
16045{
16046 FILE_BUF *ip = NULL;
16047 int i;
16048 int first = 1;
16049 char *str1;
16050 char *str2;
16051
16052 /* If stack of files hasn't changed since we last printed
16053 this info, don't repeat it. */
16054 if (last_error_tick == input_file_stack_tick)
16055 return;
16056
16057 for (i = indepth; i >= 0; i--)
16058 if (instack[i].fname != NULL) {
16059 ip = &instack[i];
16060 break;
16061 }
16062
16063 /* Give up if we don't find a source file. */
16064 if (ip == NULL)
16065 return;
16066
16067 /* Find the other, outer source files. */
16068 for (i--; i >= 0; i--)
16069 if (instack[i].fname != NULL)
16070 {
16071 ip = &instack[i];
16072 if (first)
16073 {
16074 first = 0;
16075 str1 = "In file included";
16076 }
16077 else
16078 {
16079 str1 = "... ...";
16080 }
16081
16082 if (i == 1)
16083 str2 = ":";
16084 else
16085 str2 = "";
16086
16087 ffebad_start_msg ("%A from %B at %0%C", sev);
16088 ffebad_here (0, ip->line, ip->column);
16089 ffebad_string (str1);
16090 ffebad_string (ip->nominal_fname);
16091 ffebad_string (str2);
16092 ffebad_finish ();
16093 }
16094
16095 /* Record we have printed the status as of this time. */
16096 last_error_tick = input_file_stack_tick;
16097}
16098
16099/* Read a space delimited string of unlimited length from a stdio
16100 file. */
16101
16102static char *
16103read_filename_string (ch, f)
16104 int ch;
16105 FILE *f;
16106{
16107 char *alloc, *set;
16108 int len;
16109
16110 len = 20;
16111 set = alloc = xmalloc (len + 1);
16112 if (! is_space[ch])
16113 {
16114 *set++ = ch;
16115 while ((ch = getc (f)) != EOF && ! is_space[ch])
16116 {
16117 if (set - alloc == len)
16118 {
16119 len *= 2;
16120 alloc = xrealloc (alloc, len + 1);
16121 set = alloc + len / 2;
16122 }
16123 *set++ = ch;
16124 }
16125 }
16126 *set = '\0';
16127 ungetc (ch, f);
16128 return alloc;
16129}
16130
16131/* Read the file name map file for DIRNAME. */
16132
16133static struct file_name_map *
16134read_name_map (dirname)
16135 char *dirname;
16136{
16137 /* This structure holds a linked list of file name maps, one per
16138 directory. */
16139 struct file_name_map_list
16140 {
16141 struct file_name_map_list *map_list_next;
16142 char *map_list_name;
16143 struct file_name_map *map_list_map;
16144 };
16145 static struct file_name_map_list *map_list;
16146 register struct file_name_map_list *map_list_ptr;
16147 char *name;
16148 FILE *f;
16149 size_t dirlen;
16150 int separator_needed;
16151
16152 dirname = skip_redundant_dir_prefix (dirname);
16153
16154 for (map_list_ptr = map_list; map_list_ptr;
16155 map_list_ptr = map_list_ptr->map_list_next)
16156 if (! strcmp (map_list_ptr->map_list_name, dirname))
16157 return map_list_ptr->map_list_map;
16158
16159 map_list_ptr = ((struct file_name_map_list *)
16160 xmalloc (sizeof (struct file_name_map_list)));
16161 map_list_ptr->map_list_name = savestring (dirname);
16162 map_list_ptr->map_list_map = NULL;
16163
16164 dirlen = strlen (dirname);
16165 separator_needed = dirlen != 0 && dirname[dirlen - 1] != '/';
16166 name = (char *) xmalloc (dirlen + strlen (FILE_NAME_MAP_FILE) + 2);
16167 strcpy (name, dirname);
16168 name[dirlen] = '/';
16169 strcpy (name + dirlen + separator_needed, FILE_NAME_MAP_FILE);
16170 f = fopen (name, "r");
16171 free (name);
16172 if (!f)
16173 map_list_ptr->map_list_map = NULL;
16174 else
16175 {
16176 int ch;
16177
16178 while ((ch = getc (f)) != EOF)
16179 {
16180 char *from, *to;
16181 struct file_name_map *ptr;
16182
16183 if (is_space[ch])
16184 continue;
16185 from = read_filename_string (ch, f);
16186 while ((ch = getc (f)) != EOF && is_hor_space[ch])
16187 ;
16188 to = read_filename_string (ch, f);
16189
16190 ptr = ((struct file_name_map *)
16191 xmalloc (sizeof (struct file_name_map)));
16192 ptr->map_from = from;
16193
16194 /* Make the real filename absolute. */
16195 if (*to == '/')
16196 ptr->map_to = to;
16197 else
16198 {
16199 ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
16200 strcpy (ptr->map_to, dirname);
16201 ptr->map_to[dirlen] = '/';
16202 strcpy (ptr->map_to + dirlen + separator_needed, to);
16203 free (to);
16204 }
16205
16206 ptr->map_next = map_list_ptr->map_list_map;
16207 map_list_ptr->map_list_map = ptr;
16208
16209 while ((ch = getc (f)) != '\n')
16210 if (ch == EOF)
16211 break;
16212 }
16213 fclose (f);
16214 }
16215
16216 map_list_ptr->map_list_next = map_list;
16217 map_list = map_list_ptr;
16218
16219 return map_list_ptr->map_list_map;
16220}
16221
16222static char *
16223savestring (input)
16224 char *input;
16225{
16226 unsigned size = strlen (input);
16227 char *output = xmalloc (size + 1);
16228 strcpy (output, input);
16229 return output;
16230}
16231
16232static void
16233ffecom_file_ (char *name)
16234{
16235 FILE_BUF *fp;
16236
16237 /* Do partial setup of input buffer for the sake of generating
16238 early #line directives (when -g is in effect). */
16239
16240 fp = &instack[++indepth];
34b8e428 16241 memset ((char *) fp, 0, sizeof (FILE_BUF));
5ff904cd
JL
16242 if (name == NULL)
16243 name = "";
16244 fp->nominal_fname = fp->fname = name;
16245}
16246
16247/* Initialize syntactic classifications of characters. */
16248
16249static void
16250ffecom_initialize_char_syntax_ ()
16251{
16252 register int i;
16253
16254 /*
16255 * Set up is_idchar and is_idstart tables. These should be
16256 * faster than saying (is_alpha (c) || c == '_'), etc.
16257 * Set up these things before calling any routines tthat
16258 * refer to them.
16259 */
16260 for (i = 'a'; i <= 'z'; i++) {
16261 is_idchar[i - 'a' + 'A'] = 1;
16262 is_idchar[i] = 1;
16263 is_idstart[i - 'a' + 'A'] = 1;
16264 is_idstart[i] = 1;
16265 }
16266 for (i = '0'; i <= '9'; i++)
16267 is_idchar[i] = 1;
16268 is_idchar['_'] = 1;
16269 is_idstart['_'] = 1;
16270
16271 /* horizontal space table */
16272 is_hor_space[' '] = 1;
16273 is_hor_space['\t'] = 1;
16274 is_hor_space['\v'] = 1;
16275 is_hor_space['\f'] = 1;
16276 is_hor_space['\r'] = 1;
16277
16278 is_space[' '] = 1;
16279 is_space['\t'] = 1;
16280 is_space['\v'] = 1;
16281 is_space['\f'] = 1;
16282 is_space['\n'] = 1;
16283 is_space['\r'] = 1;
16284}
16285
16286static void
16287ffecom_close_include_ (FILE *f)
16288{
16289 fclose (f);
16290
16291 indepth--;
16292 input_file_stack_tick++;
16293
16294 ffewhere_line_kill (instack[indepth].line);
16295 ffewhere_column_kill (instack[indepth].column);
16296}
16297
16298static int
16299ffecom_decode_include_option_ (char *spec)
16300{
16301 struct file_name_list *dirtmp;
16302
16303 if (! ignore_srcdir && !strcmp (spec, "-"))
16304 ignore_srcdir = 1;
16305 else
16306 {
16307 dirtmp = (struct file_name_list *)
16308 xmalloc (sizeof (struct file_name_list));
16309 dirtmp->next = 0; /* New one goes on the end */
16310 if (spec[0] != 0)
16311 dirtmp->fname = spec;
16312 else
16313 fatal ("Directory name must immediately follow -I option with no intervening spaces, as in `-Idir', not `-I dir'");
16314 dirtmp->got_name_map = 0;
16315 append_include_chain (dirtmp, dirtmp);
16316 }
16317 return 1;
16318}
16319
16320/* Open INCLUDEd file. */
16321
16322static FILE *
16323ffecom_open_include_ (char *name, ffewhereLine l, ffewhereColumn c)
16324{
16325 char *fbeg = name;
16326 size_t flen = strlen (fbeg);
16327 struct file_name_list *search_start = include; /* Chain of dirs to search */
16328 struct file_name_list dsp[1]; /* First in chain, if #include "..." */
16329 struct file_name_list *searchptr = 0;
16330 char *fname; /* Dynamically allocated fname buffer */
16331 FILE *f;
16332 FILE_BUF *fp;
16333
16334 if (flen == 0)
16335 return NULL;
16336
16337 dsp[0].fname = NULL;
16338
16339 /* If -I- was specified, don't search current dir, only spec'd ones. */
16340 if (!ignore_srcdir)
16341 {
16342 for (fp = &instack[indepth]; fp >= instack; fp--)
16343 {
16344 int n;
16345 char *ep;
16346 char *nam;
16347
16348 if ((nam = fp->nominal_fname) != NULL)
16349 {
16350 /* Found a named file. Figure out dir of the file,
16351 and put it in front of the search list. */
16352 dsp[0].next = search_start;
16353 search_start = dsp;
16354#ifndef VMS
16355 ep = rindex (nam, '/');
16356#ifdef DIR_SEPARATOR
16357 if (ep == NULL) ep = rindex (nam, DIR_SEPARATOR);
16358 else {
16359 char *tmp = rindex (nam, DIR_SEPARATOR);
16360 if (tmp != NULL && tmp > ep) ep = tmp;
16361 }
16362#endif
16363#else /* VMS */
16364 ep = rindex (nam, ']');
16365 if (ep == NULL) ep = rindex (nam, '>');
16366 if (ep == NULL) ep = rindex (nam, ':');
16367 if (ep != NULL) ep++;
16368#endif /* VMS */
16369 if (ep != NULL)
16370 {
16371 n = ep - nam;
16372 dsp[0].fname = (char *) xmalloc (n + 1);
16373 strncpy (dsp[0].fname, nam, n);
16374 dsp[0].fname[n] = '\0';
16375 if (n + INCLUDE_LEN_FUDGE > max_include_len)
16376 max_include_len = n + INCLUDE_LEN_FUDGE;
16377 }
16378 else
16379 dsp[0].fname = NULL; /* Current directory */
16380 dsp[0].got_name_map = 0;
16381 break;
16382 }
16383 }
16384 }
16385
16386 /* Allocate this permanently, because it gets stored in the definitions
16387 of macros. */
16388 fname = xmalloc (max_include_len + flen + 4);
16389 /* + 2 above for slash and terminating null. */
16390 /* + 2 added for '.h' on VMS (to support '#include filename') (NOT USED
16391 for g77 yet). */
16392
16393 /* If specified file name is absolute, just open it. */
16394
16395 if (*fbeg == '/'
16396#ifdef DIR_SEPARATOR
16397 || *fbeg == DIR_SEPARATOR
16398#endif
16399 )
16400 {
16401 strncpy (fname, (char *) fbeg, flen);
16402 fname[flen] = 0;
16403 f = open_include_file (fname, NULL_PTR);
16404 }
16405 else
16406 {
16407 f = NULL;
16408
16409 /* Search directory path, trying to open the file.
16410 Copy each filename tried into FNAME. */
16411
16412 for (searchptr = search_start; searchptr; searchptr = searchptr->next)
16413 {
16414 if (searchptr->fname)
16415 {
16416 /* The empty string in a search path is ignored.
16417 This makes it possible to turn off entirely
16418 a standard piece of the list. */
16419 if (searchptr->fname[0] == 0)
16420 continue;
16421 strcpy (fname, skip_redundant_dir_prefix (searchptr->fname));
16422 if (fname[0] && fname[strlen (fname) - 1] != '/')
16423 strcat (fname, "/");
16424 fname[strlen (fname) + flen] = 0;
16425 }
16426 else
16427 fname[0] = 0;
16428
16429 strncat (fname, fbeg, flen);
16430#ifdef VMS
16431 /* Change this 1/2 Unix 1/2 VMS file specification into a
16432 full VMS file specification */
16433 if (searchptr->fname && (searchptr->fname[0] != 0))
16434 {
16435 /* Fix up the filename */
16436 hack_vms_include_specification (fname);
16437 }
16438 else
16439 {
16440 /* This is a normal VMS filespec, so use it unchanged. */
16441 strncpy (fname, (char *) fbeg, flen);
16442 fname[flen] = 0;
16443#if 0 /* Not for g77. */
16444 /* if it's '#include filename', add the missing .h */
16445 if (index (fname, '.') == NULL)
16446 strcat (fname, ".h");
16447#endif
16448 }
16449#endif /* VMS */
16450 f = open_include_file (fname, searchptr);
16451#ifdef EACCES
16452 if (f == NULL && errno == EACCES)
16453 {
16454 print_containing_files (FFEBAD_severityWARNING);
16455 ffebad_start_msg ("At %0, INCLUDE file %A exists, but is not readable",
16456 FFEBAD_severityWARNING);
16457 ffebad_string (fname);
16458 ffebad_here (0, l, c);
16459 ffebad_finish ();
16460 }
16461#endif
16462 if (f != NULL)
16463 break;
16464 }
16465 }
16466
16467 if (f == NULL)
16468 {
16469 /* A file that was not found. */
16470
16471 strncpy (fname, (char *) fbeg, flen);
16472 fname[flen] = 0;
16473 print_containing_files (ffebad_severity (FFEBAD_OPEN_INCLUDE));
16474 ffebad_start (FFEBAD_OPEN_INCLUDE);
16475 ffebad_here (0, l, c);
16476 ffebad_string (fname);
16477 ffebad_finish ();
16478 }
16479
16480 if (dsp[0].fname != NULL)
16481 free (dsp[0].fname);
16482
16483 if (f == NULL)
16484 return NULL;
16485
16486 if (indepth >= (INPUT_STACK_MAX - 1))
16487 {
16488 print_containing_files (FFEBAD_severityFATAL);
16489 ffebad_start_msg ("At %0, INCLUDE nesting too deep",
16490 FFEBAD_severityFATAL);
16491 ffebad_string (fname);
16492 ffebad_here (0, l, c);
16493 ffebad_finish ();
16494 return NULL;
16495 }
16496
16497 instack[indepth].line = ffewhere_line_use (l);
16498 instack[indepth].column = ffewhere_column_use (c);
16499
16500 fp = &instack[indepth + 1];
34b8e428 16501 memset ((char *) fp, 0, sizeof (FILE_BUF));
5ff904cd
JL
16502 fp->nominal_fname = fp->fname = fname;
16503 fp->dir = searchptr;
16504
16505 indepth++;
16506 input_file_stack_tick++;
16507
16508 return f;
16509}
16510#endif /* FFECOM_GCC_INCLUDE */
This page took 1.778623 seconds and 5 git commands to generate.