]> gcc.gnu.org Git - gcc.git/blame - gcc/f/com.c
970816-3.f: New test from Craig.
[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 {
925 assert (TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE);
926 assert (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)));
927 return fold (convert_to_integer (type, e));
928 }
929 if (code == POINTER_TYPE)
930 {
931 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
932 return fold (convert_to_pointer (type, e));
933 }
934 if (code == REAL_TYPE)
935 {
936 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
937 assert (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)));
938 return fold (convert_to_real (type, e));
939 }
940 if (code == COMPLEX_TYPE)
941 {
942 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
943 assert (TYPE_PRECISION (TREE_TYPE (type)) <= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
944 return fold (convert_to_complex (type, e));
945 }
946 if (code == RECORD_TYPE)
947 {
948 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
270fc4e8
CB
949 /* Check that at least the first field name agrees. */
950 assert (DECL_NAME (TYPE_FIELDS (type))
951 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
5ff904cd
JL
952 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
953 <= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
270fc4e8
CB
954 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
955 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
956 return e;
5ff904cd
JL
957 return fold (ffecom_convert_to_complex_ (type, e));
958 }
959
960 assert ("conversion to non-scalar type requested" == NULL);
961 return error_mark_node;
962}
963#endif
964
965/* Like gcc's convert(), but crashes if narrowing might happen. */
966
967#if FFECOM_targetCURRENT == FFECOM_targetGCC
968static tree
969ffecom_convert_widen_ (type, expr)
970 tree type, expr;
971{
972 register tree e = expr;
973 register enum tree_code code = TREE_CODE (type);
974
975 if (type == TREE_TYPE (e)
976 || TREE_CODE (e) == ERROR_MARK)
977 return e;
978 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
979 return fold (build1 (NOP_EXPR, type, e));
980 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
981 || code == ERROR_MARK)
982 return error_mark_node;
983 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
984 {
985 assert ("void value not ignored as it ought to be" == NULL);
986 return error_mark_node;
987 }
988 assert (code != VOID_TYPE);
989 if ((code != RECORD_TYPE)
990 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
991 assert ("narrowing COMPLEX to REAL" == NULL);
992 assert (code != ENUMERAL_TYPE);
993 if (code == INTEGER_TYPE)
994 {
995 assert (TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE);
996 assert (TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)));
997 return fold (convert_to_integer (type, e));
998 }
999 if (code == POINTER_TYPE)
1000 {
1001 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1002 return fold (convert_to_pointer (type, e));
1003 }
1004 if (code == REAL_TYPE)
1005 {
1006 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1007 assert (TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)));
1008 return fold (convert_to_real (type, e));
1009 }
1010 if (code == COMPLEX_TYPE)
1011 {
1012 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1013 assert (TYPE_PRECISION (TREE_TYPE (type)) >= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1014 return fold (convert_to_complex (type, e));
1015 }
1016 if (code == RECORD_TYPE)
1017 {
1018 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
270fc4e8
CB
1019 /* Check that at least the first field name agrees. */
1020 assert (DECL_NAME (TYPE_FIELDS (type))
1021 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
5ff904cd
JL
1022 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1023 >= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
270fc4e8
CB
1024 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1025 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1026 return e;
5ff904cd
JL
1027 return fold (ffecom_convert_to_complex_ (type, e));
1028 }
1029
1030 assert ("conversion to non-scalar type requested" == NULL);
1031 return error_mark_node;
1032}
1033#endif
1034
1035/* Handles making a COMPLEX type, either the standard
1036 (but buggy?) gbe way, or the safer (but less elegant?)
1037 f2c way. */
1038
1039#if FFECOM_targetCURRENT == FFECOM_targetGCC
1040static tree
1041ffecom_make_complex_type_ (tree subtype)
1042{
1043 tree type;
1044 tree realfield;
1045 tree imagfield;
1046
1047 if (ffe_is_emulate_complex ())
1048 {
1049 type = make_node (RECORD_TYPE);
1050 realfield = ffecom_decl_field (type, NULL_TREE, "r", subtype);
1051 imagfield = ffecom_decl_field (type, realfield, "i", subtype);
1052 TYPE_FIELDS (type) = realfield;
1053 layout_type (type);
1054 }
1055 else
1056 {
1057 type = make_node (COMPLEX_TYPE);
1058 TREE_TYPE (type) = subtype;
1059 layout_type (type);
1060 }
1061
1062 return type;
1063}
1064#endif
1065
1066/* Chooses either the gbe or the f2c way to build a
1067 complex constant. */
1068
1069#if FFECOM_targetCURRENT == FFECOM_targetGCC
1070static tree
1071ffecom_build_complex_constant_ (tree type, tree realpart, tree imagpart)
1072{
1073 tree bothparts;
1074
1075 if (ffe_is_emulate_complex ())
1076 {
1077 bothparts = build_tree_list (TYPE_FIELDS (type), realpart);
1078 TREE_CHAIN (bothparts) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), imagpart);
1079 bothparts = build (CONSTRUCTOR, type, NULL_TREE, bothparts);
1080 }
1081 else
1082 {
1083 bothparts = build_complex (type, realpart, imagpart);
1084 }
1085
1086 return bothparts;
1087}
1088#endif
1089
1090#if FFECOM_targetCURRENT == FFECOM_targetGCC
1091static tree
1092ffecom_arglist_expr_ (char *c, ffebld expr)
1093{
1094 tree list;
1095 tree *plist = &list;
1096 tree trail = NULL_TREE; /* Append char length args here. */
1097 tree *ptrail = &trail;
1098 tree length;
1099 ffebld exprh;
1100 tree item;
1101 bool ptr = FALSE;
1102 tree wanted = NULL_TREE;
e2fa159e
JL
1103 static char zed[] = "0";
1104
1105 if (c == NULL)
1106 c = &zed[0];
5ff904cd
JL
1107
1108 while (expr != NULL)
1109 {
1110 if (*c != '\0')
1111 {
1112 ptr = FALSE;
1113 if (*c == '&')
1114 {
1115 ptr = TRUE;
1116 ++c;
1117 }
1118 switch (*(c++))
1119 {
1120 case '\0':
1121 ptr = TRUE;
1122 wanted = NULL_TREE;
1123 break;
1124
1125 case 'a':
1126 assert (ptr);
1127 wanted = NULL_TREE;
1128 break;
1129
1130 case 'c':
1131 wanted = ffecom_f2c_complex_type_node;
1132 break;
1133
1134 case 'd':
1135 wanted = ffecom_f2c_doublereal_type_node;
1136 break;
1137
1138 case 'e':
1139 wanted = ffecom_f2c_doublecomplex_type_node;
1140 break;
1141
1142 case 'f':
1143 wanted = ffecom_f2c_real_type_node;
1144 break;
1145
1146 case 'i':
1147 wanted = ffecom_f2c_integer_type_node;
1148 break;
1149
1150 case 'j':
1151 wanted = ffecom_f2c_longint_type_node;
1152 break;
1153
1154 default:
1155 assert ("bad argstring code" == NULL);
1156 wanted = NULL_TREE;
1157 break;
1158 }
1159 }
1160
1161 exprh = ffebld_head (expr);
1162 if (exprh == NULL)
1163 wanted = NULL_TREE;
1164
1165 if ((wanted == NULL_TREE)
1166 || (ptr
1167 && (TYPE_MODE
1168 (ffecom_tree_type[ffeinfo_basictype (ffebld_info (exprh))]
1169 [ffeinfo_kindtype (ffebld_info (exprh))])
1170 == TYPE_MODE (wanted))))
1171 *plist
1172 = build_tree_list (NULL_TREE,
1173 ffecom_arg_ptr_to_expr (exprh,
1174 &length));
1175 else
1176 {
1177 item = ffecom_arg_expr (exprh, &length);
1178 item = ffecom_convert_widen_ (wanted, item);
1179 if (ptr)
1180 {
1181 item = ffecom_1 (ADDR_EXPR,
1182 build_pointer_type (TREE_TYPE (item)),
1183 item);
1184 }
1185 *plist
1186 = build_tree_list (NULL_TREE,
1187 item);
1188 }
1189
1190 plist = &TREE_CHAIN (*plist);
1191 expr = ffebld_trail (expr);
1192 if (length != NULL_TREE)
1193 {
1194 *ptrail = build_tree_list (NULL_TREE, length);
1195 ptrail = &TREE_CHAIN (*ptrail);
1196 }
1197 }
1198
e2fa159e
JL
1199 /* We've run out of args in the call; if the implementation expects
1200 more, supply null pointers for them, which the implementation can
1201 check to see if an arg was omitted. */
1202
1203 while (*c != '\0' && *c != '0')
1204 {
1205 if (*c == '&')
1206 ++c;
1207 else
1208 assert ("missing arg to run-time routine!" == NULL);
1209
1210 switch (*(c++))
1211 {
1212 case '\0':
1213 case 'a':
1214 case 'c':
1215 case 'd':
1216 case 'e':
1217 case 'f':
1218 case 'i':
1219 case 'j':
1220 break;
1221
1222 default:
1223 assert ("bad arg string code" == NULL);
1224 break;
1225 }
1226 *plist
1227 = build_tree_list (NULL_TREE,
1228 null_pointer_node);
1229 plist = &TREE_CHAIN (*plist);
1230 }
1231
5ff904cd
JL
1232 *plist = trail;
1233
1234 return list;
1235}
1236#endif
1237
1238#if FFECOM_targetCURRENT == FFECOM_targetGCC
1239static tree
1240ffecom_widest_expr_type_ (ffebld list)
1241{
1242 ffebld item;
1243 ffebld widest = NULL;
1244 ffetype type;
1245 ffetype widest_type = NULL;
1246 tree t;
1247
1248 for (; list != NULL; list = ffebld_trail (list))
1249 {
1250 item = ffebld_head (list);
1251 if (item == NULL)
1252 continue;
1253 if ((widest != NULL)
1254 && (ffeinfo_basictype (ffebld_info (item))
1255 != ffeinfo_basictype (ffebld_info (widest))))
1256 continue;
1257 type = ffeinfo_type (ffeinfo_basictype (ffebld_info (item)),
1258 ffeinfo_kindtype (ffebld_info (item)));
1259 if ((widest == FFEINFO_kindtypeNONE)
1260 || (ffetype_size (type)
1261 > ffetype_size (widest_type)))
1262 {
1263 widest = item;
1264 widest_type = type;
1265 }
1266 }
1267
1268 assert (widest != NULL);
1269 t = ffecom_tree_type[ffeinfo_basictype (ffebld_info (widest))]
1270 [ffeinfo_kindtype (ffebld_info (widest))];
1271 assert (t != NULL_TREE);
1272 return t;
1273}
1274#endif
1275
1276/* Check whether dest and source might overlap. ffebld versions of these
1277 might or might not be passed, will be NULL if not.
1278
1279 The test is really whether source_tree is modifiable and, if modified,
1280 might overlap destination such that the value(s) in the destination might
1281 change before it is finally modified. dest_* are the canonized
1282 destination itself. */
1283
1284#if FFECOM_targetCURRENT == FFECOM_targetGCC
1285static bool
1286ffecom_overlap_ (tree dest_decl, tree dest_offset, tree dest_size,
1287 tree source_tree, ffebld source UNUSED,
1288 bool scalar_arg)
1289{
1290 tree source_decl;
1291 tree source_offset;
1292 tree source_size;
1293 tree t;
1294
1295 if (source_tree == NULL_TREE)
1296 return FALSE;
1297
1298 switch (TREE_CODE (source_tree))
1299 {
1300 case ERROR_MARK:
1301 case IDENTIFIER_NODE:
1302 case INTEGER_CST:
1303 case REAL_CST:
1304 case COMPLEX_CST:
1305 case STRING_CST:
1306 case CONST_DECL:
1307 case VAR_DECL:
1308 case RESULT_DECL:
1309 case FIELD_DECL:
1310 case MINUS_EXPR:
1311 case MULT_EXPR:
1312 case TRUNC_DIV_EXPR:
1313 case CEIL_DIV_EXPR:
1314 case FLOOR_DIV_EXPR:
1315 case ROUND_DIV_EXPR:
1316 case TRUNC_MOD_EXPR:
1317 case CEIL_MOD_EXPR:
1318 case FLOOR_MOD_EXPR:
1319 case ROUND_MOD_EXPR:
1320 case RDIV_EXPR:
1321 case EXACT_DIV_EXPR:
1322 case FIX_TRUNC_EXPR:
1323 case FIX_CEIL_EXPR:
1324 case FIX_FLOOR_EXPR:
1325 case FIX_ROUND_EXPR:
1326 case FLOAT_EXPR:
1327 case EXPON_EXPR:
1328 case NEGATE_EXPR:
1329 case MIN_EXPR:
1330 case MAX_EXPR:
1331 case ABS_EXPR:
1332 case FFS_EXPR:
1333 case LSHIFT_EXPR:
1334 case RSHIFT_EXPR:
1335 case LROTATE_EXPR:
1336 case RROTATE_EXPR:
1337 case BIT_IOR_EXPR:
1338 case BIT_XOR_EXPR:
1339 case BIT_AND_EXPR:
1340 case BIT_ANDTC_EXPR:
1341 case BIT_NOT_EXPR:
1342 case TRUTH_ANDIF_EXPR:
1343 case TRUTH_ORIF_EXPR:
1344 case TRUTH_AND_EXPR:
1345 case TRUTH_OR_EXPR:
1346 case TRUTH_XOR_EXPR:
1347 case TRUTH_NOT_EXPR:
1348 case LT_EXPR:
1349 case LE_EXPR:
1350 case GT_EXPR:
1351 case GE_EXPR:
1352 case EQ_EXPR:
1353 case NE_EXPR:
1354 case COMPLEX_EXPR:
1355 case CONJ_EXPR:
1356 case REALPART_EXPR:
1357 case IMAGPART_EXPR:
1358 case LABEL_EXPR:
1359 case COMPONENT_REF:
1360 return FALSE;
1361
1362 case COMPOUND_EXPR:
1363 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1364 TREE_OPERAND (source_tree, 1), NULL,
1365 scalar_arg);
1366
1367 case MODIFY_EXPR:
1368 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1369 TREE_OPERAND (source_tree, 0), NULL,
1370 scalar_arg);
1371
1372 case CONVERT_EXPR:
1373 case NOP_EXPR:
1374 case NON_LVALUE_EXPR:
1375 case PLUS_EXPR:
1376 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1377 return TRUE;
1378
1379 ffecom_tree_canonize_ptr_ (&source_decl, &source_offset,
1380 source_tree);
1381 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1382 break;
1383
1384 case COND_EXPR:
1385 return
1386 ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1387 TREE_OPERAND (source_tree, 1), NULL,
1388 scalar_arg)
1389 || ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1390 TREE_OPERAND (source_tree, 2), NULL,
1391 scalar_arg);
1392
1393
1394 case ADDR_EXPR:
1395 ffecom_tree_canonize_ref_ (&source_decl, &source_offset,
1396 &source_size,
1397 TREE_OPERAND (source_tree, 0));
1398 break;
1399
1400 case PARM_DECL:
1401 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1402 return TRUE;
1403
1404 source_decl = source_tree;
1405 source_offset = size_zero_node;
1406 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1407 break;
1408
1409 case SAVE_EXPR:
1410 case REFERENCE_EXPR:
1411 case PREDECREMENT_EXPR:
1412 case PREINCREMENT_EXPR:
1413 case POSTDECREMENT_EXPR:
1414 case POSTINCREMENT_EXPR:
1415 case INDIRECT_REF:
1416 case ARRAY_REF:
1417 case CALL_EXPR:
1418 default:
1419 return TRUE;
1420 }
1421
1422 /* Come here when source_decl, source_offset, and source_size filled
1423 in appropriately. */
1424
1425 if (source_decl == NULL_TREE)
1426 return FALSE; /* No decl involved, so no overlap. */
1427
1428 if (source_decl != dest_decl)
1429 return FALSE; /* Different decl, no overlap. */
1430
1431 if (TREE_CODE (dest_size) == ERROR_MARK)
1432 return TRUE; /* Assignment into entire assumed-size
1433 array? Shouldn't happen.... */
1434
1435 t = ffecom_2 (LE_EXPR, integer_type_node,
1436 ffecom_2 (PLUS_EXPR, TREE_TYPE (dest_offset),
1437 dest_offset,
1438 convert (TREE_TYPE (dest_offset),
1439 dest_size)),
1440 convert (TREE_TYPE (dest_offset),
1441 source_offset));
1442
1443 if (integer_onep (t))
1444 return FALSE; /* Destination precedes source. */
1445
1446 if (!scalar_arg
1447 || (source_size == NULL_TREE)
1448 || (TREE_CODE (source_size) == ERROR_MARK)
1449 || integer_zerop (source_size))
1450 return TRUE; /* No way to tell if dest follows source. */
1451
1452 t = ffecom_2 (LE_EXPR, integer_type_node,
1453 ffecom_2 (PLUS_EXPR, TREE_TYPE (source_offset),
1454 source_offset,
1455 convert (TREE_TYPE (source_offset),
1456 source_size)),
1457 convert (TREE_TYPE (source_offset),
1458 dest_offset));
1459
1460 if (integer_onep (t))
1461 return FALSE; /* Destination follows source. */
1462
1463 return TRUE; /* Destination and source overlap. */
1464}
1465#endif
1466
1467/* Check whether dest might overlap any of a list of arguments or is
1468 in a COMMON area the callee might know about (and thus modify). */
1469
1470#if FFECOM_targetCURRENT == FFECOM_targetGCC
1471static bool
1472ffecom_args_overlapping_ (tree dest_tree, ffebld dest UNUSED,
1473 tree args, tree callee_commons,
1474 bool scalar_args)
1475{
1476 tree arg;
1477 tree dest_decl;
1478 tree dest_offset;
1479 tree dest_size;
1480
1481 ffecom_tree_canonize_ref_ (&dest_decl, &dest_offset, &dest_size,
1482 dest_tree);
1483
1484 if (dest_decl == NULL_TREE)
1485 return FALSE; /* Seems unlikely! */
1486
1487 /* If the decl cannot be determined reliably, or if its in COMMON
1488 and the callee isn't known to not futz with COMMON via other
1489 means, overlap might happen. */
1490
1491 if ((TREE_CODE (dest_decl) == ERROR_MARK)
1492 || ((callee_commons != NULL_TREE)
1493 && TREE_PUBLIC (dest_decl)))
1494 return TRUE;
1495
1496 for (; args != NULL_TREE; args = TREE_CHAIN (args))
1497 {
1498 if (((arg = TREE_VALUE (args)) != NULL_TREE)
1499 && ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1500 arg, NULL, scalar_args))
1501 return TRUE;
1502 }
1503
1504 return FALSE;
1505}
1506#endif
1507
1508/* Build a string for a variable name as used by NAMELIST. This means that
1509 if we're using the f2c library, we build an uppercase string, since
1510 f2c does this. */
1511
1512#if FFECOM_targetCURRENT == FFECOM_targetGCC
1513static tree
1514ffecom_build_f2c_string_ (int i, char *s)
1515{
1516 if (!ffe_is_f2c_library ())
1517 return build_string (i, s);
1518
1519 {
1520 char *tmp;
1521 char *p;
1522 char *q;
1523 char space[34];
1524 tree t;
1525
1526 if (((size_t) i) > ARRAY_SIZE (space))
1527 tmp = malloc_new_ks (malloc_pool_image (), "f2c_string", i);
1528 else
1529 tmp = &space[0];
1530
1531 for (p = s, q = tmp; *p != '\0'; ++p, ++q)
1532 *q = ffesrc_toupper (*p);
1533 *q = '\0';
1534
1535 t = build_string (i, tmp);
1536
1537 if (((size_t) i) > ARRAY_SIZE (space))
1538 malloc_kill_ks (malloc_pool_image (), tmp, i);
1539
1540 return t;
1541 }
1542}
1543
1544#endif
1545/* Returns CALL_EXPR or equivalent with given type (pass NULL_TREE for
1546 type to just get whatever the function returns), handling the
1547 f2c value-returning convention, if required, by prepending
1548 to the arglist a pointer to a temporary to receive the return value. */
1549
1550#if FFECOM_targetCURRENT == FFECOM_targetGCC
1551static tree
1552ffecom_call_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1553 tree type, tree args, tree dest_tree,
1554 ffebld dest, bool *dest_used, tree callee_commons,
1555 bool scalar_args)
1556{
1557 tree item;
1558 tree tempvar;
1559
1560 if (dest_used != NULL)
1561 *dest_used = FALSE;
1562
1563 if (is_f2c_complex)
1564 {
1565 if ((dest_used == NULL)
1566 || (dest == NULL)
1567 || (ffeinfo_basictype (ffebld_info (dest))
1568 != FFEINFO_basictypeCOMPLEX)
1569 || (ffeinfo_kindtype (ffebld_info (dest)) != kt)
1570 || ((type != NULL_TREE) && (TREE_TYPE (dest_tree) != type))
1571 || ffecom_args_overlapping_ (dest_tree, dest, args,
1572 callee_commons,
1573 scalar_args))
1574 {
1575 tempvar = ffecom_push_tempvar (ffecom_tree_type
1576 [FFEINFO_basictypeCOMPLEX][kt],
1577 FFETARGET_charactersizeNONE,
1578 -1, TRUE);
1579 }
1580 else
1581 {
1582 *dest_used = TRUE;
1583 tempvar = dest_tree;
1584 type = NULL_TREE;
1585 }
1586
1587 item
1588 = build_tree_list (NULL_TREE,
1589 ffecom_1 (ADDR_EXPR,
1590 build_pointer_type (TREE_TYPE (tempvar)),
1591 tempvar));
1592 TREE_CHAIN (item) = args;
1593
1594 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1595 item, NULL_TREE);
1596
1597 if (tempvar != dest_tree)
1598 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item, tempvar);
1599 }
1600 else
1601 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1602 args, NULL_TREE);
1603
1604 if ((type != NULL_TREE) && (TREE_TYPE (item) != type))
1605 item = ffecom_convert_narrow_ (type, item);
1606
1607 return item;
1608}
1609#endif
1610
1611/* Given two arguments, transform them and make a call to the given
1612 function via ffecom_call_. */
1613
1614#if FFECOM_targetCURRENT == FFECOM_targetGCC
1615static tree
1616ffecom_call_binop_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1617 tree type, ffebld left, ffebld right,
1618 tree dest_tree, ffebld dest, bool *dest_used,
1619 tree callee_commons, bool scalar_args)
1620{
1621 tree left_tree;
1622 tree right_tree;
1623 tree left_length;
1624 tree right_length;
1625
1626 ffecom_push_calltemps ();
1627 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
1628 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
1629 ffecom_pop_calltemps ();
1630
1631 left_tree = build_tree_list (NULL_TREE, left_tree);
1632 right_tree = build_tree_list (NULL_TREE, right_tree);
1633 TREE_CHAIN (left_tree) = right_tree;
1634
1635 if (left_length != NULL_TREE)
1636 {
1637 left_length = build_tree_list (NULL_TREE, left_length);
1638 TREE_CHAIN (right_tree) = left_length;
1639 }
1640
1641 if (right_length != NULL_TREE)
1642 {
1643 right_length = build_tree_list (NULL_TREE, right_length);
1644 if (left_length != NULL_TREE)
1645 TREE_CHAIN (left_length) = right_length;
1646 else
1647 TREE_CHAIN (right_tree) = right_length;
1648 }
1649
1650 return ffecom_call_ (fn, kt, is_f2c_complex, type, left_tree,
1651 dest_tree, dest, dest_used, callee_commons,
1652 scalar_args);
1653}
1654#endif
1655
86fc7a6c 1656/* ffecom_char_args_x_ -- Return ptr/length args for char subexpression
5ff904cd
JL
1657
1658 tree ptr_arg;
1659 tree length_arg;
1660 ffebld expr;
86fc7a6c
CB
1661 bool with_null;
1662 ffecom_char_args_x_(&ptr_arg,&length_arg,expr,with_null);
5ff904cd
JL
1663
1664 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
1665 subexpressions by constructing the appropriate trees for the ptr-to-
1666 character-text and length-of-character-text arguments in a calling
86fc7a6c
CB
1667 sequence.
1668
1669 Note that if with_null is TRUE, and the expression is an opCONTER,
1670 a null byte is appended to the string. */
5ff904cd
JL
1671
1672#if FFECOM_targetCURRENT == FFECOM_targetGCC
1673static void
86fc7a6c 1674ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
5ff904cd
JL
1675{
1676 tree item;
1677 tree high;
1678 ffetargetCharacter1 val;
86fc7a6c 1679 ffetargetCharacterSize newlen;
5ff904cd
JL
1680
1681 switch (ffebld_op (expr))
1682 {
1683 case FFEBLD_opCONTER:
1684 val = ffebld_constant_character1 (ffebld_conter (expr));
86fc7a6c
CB
1685 newlen = ffetarget_length_character1 (val);
1686 if (with_null)
1687 {
1688 if (newlen != 0)
1689 ++newlen; /* begin FFETARGET-NULL-KLUDGE. */
1690 }
1691 *length = build_int_2 (newlen, 0);
5ff904cd 1692 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
86fc7a6c 1693 high = build_int_2 (newlen, 0);
5ff904cd 1694 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
86fc7a6c 1695 item = build_string (newlen, /* end FFETARGET-NULL-KLUDGE. */
5ff904cd
JL
1696 ffetarget_text_character1 (val));
1697 TREE_TYPE (item)
1698 = build_type_variant
1699 (build_array_type
1700 (char_type_node,
1701 build_range_type
1702 (ffecom_f2c_ftnlen_type_node,
1703 ffecom_f2c_ftnlen_one_node,
1704 high)),
1705 1, 0);
1706 TREE_CONSTANT (item) = 1;
1707 TREE_STATIC (item) = 1;
1708 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
1709 item);
1710 break;
1711
1712 case FFEBLD_opSYMTER:
1713 {
1714 ffesymbol s = ffebld_symter (expr);
1715
1716 item = ffesymbol_hook (s).decl_tree;
1717 if (item == NULL_TREE)
1718 {
1719 s = ffecom_sym_transform_ (s);
1720 item = ffesymbol_hook (s).decl_tree;
1721 }
1722 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
1723 {
1724 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
1725 *length = ffesymbol_hook (s).length_tree;
1726 else
1727 {
1728 *length = build_int_2 (ffesymbol_size (s), 0);
1729 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
1730 }
1731 }
1732 else if (item == error_mark_node)
1733 *length = error_mark_node;
1734 else /* FFEINFO_kindFUNCTION: */
1735 *length = NULL_TREE;
1736 if (!ffesymbol_hook (s).addr
1737 && (item != error_mark_node))
1738 item = ffecom_1 (ADDR_EXPR,
1739 build_pointer_type (TREE_TYPE (item)),
1740 item);
1741 }
1742 break;
1743
1744 case FFEBLD_opARRAYREF:
1745 {
1746 ffebld dims[FFECOM_dimensionsMAX];
1747 tree array;
1748 int i;
1749
1750 ffecom_push_calltemps ();
1751 ffecom_char_args_ (&item, length, ffebld_left (expr));
1752 ffecom_pop_calltemps ();
1753
1754 if (item == error_mark_node || *length == error_mark_node)
1755 {
1756 item = *length = error_mark_node;
1757 break;
1758 }
1759
1760 /* Build up ARRAY_REFs in reverse order (since we're column major
1761 here in Fortran land). */
1762
1763 for (i = 0, expr = ffebld_right (expr);
1764 expr != NULL;
1765 expr = ffebld_trail (expr))
1766 dims[i++] = ffebld_head (expr);
1767
1768 for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
1769 i >= 0;
1770 --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
1771 {
1772 item = ffecom_2 (PLUS_EXPR, build_pointer_type (TREE_TYPE (array)),
1773 item,
1774 size_binop (MULT_EXPR,
1775 size_in_bytes (TREE_TYPE (array)),
1776 size_binop (MINUS_EXPR,
1777 ffecom_expr (dims[i]),
1778 TYPE_MIN_VALUE (TYPE_DOMAIN (array)))));
1779 }
1780 }
1781 break;
1782
1783 case FFEBLD_opSUBSTR:
1784 {
1785 ffebld start;
1786 ffebld end;
1787 ffebld thing = ffebld_right (expr);
1788 tree start_tree;
1789 tree end_tree;
1790
1791 assert (ffebld_op (thing) == FFEBLD_opITEM);
1792 start = ffebld_head (thing);
1793 thing = ffebld_trail (thing);
1794 assert (ffebld_trail (thing) == NULL);
1795 end = ffebld_head (thing);
1796
1797 ffecom_push_calltemps ();
1798 ffecom_char_args_ (&item, length, ffebld_left (expr));
1799 ffecom_pop_calltemps ();
1800
1801 if (item == error_mark_node || *length == error_mark_node)
1802 {
1803 item = *length = error_mark_node;
1804 break;
1805 }
1806
1807 if (start == NULL)
1808 {
1809 if (end == NULL)
1810 ;
1811 else
1812 {
1813 end_tree = convert (ffecom_f2c_ftnlen_type_node,
1814 ffecom_expr (end));
1815
1816 if (end_tree == error_mark_node)
1817 {
1818 item = *length = error_mark_node;
1819 break;
1820 }
1821
1822 *length = end_tree;
1823 }
1824 }
1825 else
1826 {
1827 start_tree = convert (ffecom_f2c_ftnlen_type_node,
1828 ffecom_expr (start));
1829
1830 if (start_tree == error_mark_node)
1831 {
1832 item = *length = error_mark_node;
1833 break;
1834 }
1835
1836 start_tree = ffecom_save_tree (start_tree);
1837
1838 item = ffecom_2 (PLUS_EXPR, TREE_TYPE (item),
1839 item,
1840 ffecom_2 (MINUS_EXPR,
1841 TREE_TYPE (start_tree),
1842 start_tree,
1843 ffecom_f2c_ftnlen_one_node));
1844
1845 if (end == NULL)
1846 {
1847 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
1848 ffecom_f2c_ftnlen_one_node,
1849 ffecom_2 (MINUS_EXPR,
1850 ffecom_f2c_ftnlen_type_node,
1851 *length,
1852 start_tree));
1853 }
1854 else
1855 {
1856 end_tree = convert (ffecom_f2c_ftnlen_type_node,
1857 ffecom_expr (end));
1858
1859 if (end_tree == error_mark_node)
1860 {
1861 item = *length = error_mark_node;
1862 break;
1863 }
1864
1865 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
1866 ffecom_f2c_ftnlen_one_node,
1867 ffecom_2 (MINUS_EXPR,
1868 ffecom_f2c_ftnlen_type_node,
1869 end_tree, start_tree));
1870 }
1871 }
1872 }
1873 break;
1874
1875 case FFEBLD_opFUNCREF:
1876 {
1877 ffesymbol s = ffebld_symter (ffebld_left (expr));
1878 tree tempvar;
1879 tree args;
1880 ffetargetCharacterSize size = ffeinfo_size (ffebld_info (expr));
1881 ffecomGfrt ix;
1882
1883 if (size == FFETARGET_charactersizeNONE)
1884 size = 24; /* ~~~~ Kludge alert! This should someday be fixed. */
1885
1886 *length = build_int_2 (size, 0);
1887 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
1888
1889 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
1890 == FFEINFO_whereINTRINSIC)
1891 {
1892 if (size == 1)
1893 { /* Invocation of an intrinsic returning CHARACTER*1. */
1894 item = ffecom_expr_intrinsic_ (expr, NULL_TREE,
1895 NULL, NULL);
1896 break;
1897 }
1898 ix = ffeintrin_gfrt_direct (ffebld_symter_implementation (ffebld_left (expr)));
1899 assert (ix != FFECOM_gfrt);
1900 item = ffecom_gfrt_tree_ (ix);
1901 }
1902 else
1903 {
1904 ix = FFECOM_gfrt;
1905 item = ffesymbol_hook (s).decl_tree;
1906 if (item == NULL_TREE)
1907 {
1908 s = ffecom_sym_transform_ (s);
1909 item = ffesymbol_hook (s).decl_tree;
1910 }
1911 if (item == error_mark_node)
1912 {
1913 item = *length = error_mark_node;
1914 break;
1915 }
1916
1917 if (!ffesymbol_hook (s).addr)
1918 item = ffecom_1_fn (item);
1919 }
1920
1921 assert (ffecom_pending_calls_ != 0);
1922 tempvar = ffecom_push_tempvar (char_type_node, size, -1, TRUE);
1923 tempvar = ffecom_1 (ADDR_EXPR,
1924 build_pointer_type (TREE_TYPE (tempvar)),
1925 tempvar);
1926
1927 ffecom_push_calltemps ();
1928
1929 args = build_tree_list (NULL_TREE, tempvar);
1930
1931 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT) /* Sfunc args by value. */
1932 TREE_CHAIN (args) = ffecom_list_expr (ffebld_right (expr));
1933 else
1934 {
1935 TREE_CHAIN (args) = build_tree_list (NULL_TREE, *length);
1936 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
1937 {
1938 TREE_CHAIN (TREE_CHAIN (args))
1939 = ffecom_arglist_expr_ (ffecom_gfrt_args_ (ix),
1940 ffebld_right (expr));
1941 }
1942 else
1943 {
1944 TREE_CHAIN (TREE_CHAIN (args))
1945 = ffecom_list_ptr_to_expr (ffebld_right (expr));
1946 }
1947 }
1948
1949 item = ffecom_3s (CALL_EXPR,
1950 TREE_TYPE (TREE_TYPE (TREE_TYPE (item))),
1951 item, args, NULL_TREE);
1952 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item,
1953 tempvar);
1954
1955 ffecom_pop_calltemps ();
1956 }
1957 break;
1958
1959 case FFEBLD_opCONVERT:
1960
1961 ffecom_push_calltemps ();
1962 ffecom_char_args_ (&item, length, ffebld_left (expr));
1963 ffecom_pop_calltemps ();
1964
1965 if (item == error_mark_node || *length == error_mark_node)
1966 {
1967 item = *length = error_mark_node;
1968 break;
1969 }
1970
1971 if ((ffebld_size_known (ffebld_left (expr))
1972 == FFETARGET_charactersizeNONE)
1973 || (ffebld_size_known (ffebld_left (expr)) < (ffebld_size (expr))))
1974 { /* Possible blank-padding needed, copy into
1975 temporary. */
1976 tree tempvar;
1977 tree args;
1978 tree newlen;
1979
1980 assert (ffecom_pending_calls_ != 0);
1981 tempvar = ffecom_push_tempvar (char_type_node,
1982 ffebld_size (expr), -1, TRUE);
1983 tempvar = ffecom_1 (ADDR_EXPR,
1984 build_pointer_type (TREE_TYPE (tempvar)),
1985 tempvar);
1986
1987 newlen = build_int_2 (ffebld_size (expr), 0);
1988 TREE_TYPE (newlen) = ffecom_f2c_ftnlen_type_node;
1989
1990 args = build_tree_list (NULL_TREE, tempvar);
1991 TREE_CHAIN (args) = build_tree_list (NULL_TREE, item);
1992 TREE_CHAIN (TREE_CHAIN (args)) = build_tree_list (NULL_TREE, newlen);
1993 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (args)))
1994 = build_tree_list (NULL_TREE, *length);
1995
1996 item = ffecom_call_gfrt (FFECOM_gfrtCOPY, args);
1997 TREE_SIDE_EFFECTS (item) = 1;
1998 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), fold (item),
1999 tempvar);
2000 *length = newlen;
2001 }
2002 else
2003 { /* Just truncate the length. */
2004 *length = build_int_2 (ffebld_size (expr), 0);
2005 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2006 }
2007 break;
2008
2009 default:
2010 assert ("bad op for single char arg expr" == NULL);
2011 item = NULL_TREE;
2012 break;
2013 }
2014
2015 *xitem = item;
2016}
2017#endif
2018
2019/* Check the size of the type to be sure it doesn't overflow the
2020 "portable" capacities of the compiler back end. `dummy' types
2021 can generally overflow the normal sizes as long as the computations
2022 themselves don't overflow. A particular target of the back end
2023 must still enforce its size requirements, though, and the back
2024 end takes care of this in stor-layout.c. */
2025
2026#if FFECOM_targetCURRENT == FFECOM_targetGCC
2027static tree
2028ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy)
2029{
2030 if (TREE_CODE (type) == ERROR_MARK)
2031 return type;
2032
2033 if (TYPE_SIZE (type) == NULL_TREE)
2034 return type;
2035
2036 if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
2037 return type;
2038
2039 if ((tree_int_cst_sgn (TYPE_SIZE (type)) < 0)
2b0c2df0
CB
2040 || (!dummy && (((TREE_INT_CST_HIGH (TYPE_SIZE (type)) != 0))
2041 || TREE_OVERFLOW (TYPE_SIZE (type)))))
5ff904cd
JL
2042 {
2043 ffebad_start (FFEBAD_ARRAY_LARGE);
2044 ffebad_string (ffesymbol_text (s));
2045 ffebad_here (0, ffesymbol_where_line (s), ffesymbol_where_column (s));
2046 ffebad_finish ();
2047
2048 return error_mark_node;
2049 }
2050
2051 return type;
2052}
2053#endif
2054
2055/* Builds a length argument (PARM_DECL). Also wraps type in an array type
2056 where the dimension info is (1:size) where <size> is ffesymbol_size(s) if
2057 known, length_arg if not known (FFETARGET_charactersizeNONE). */
2058
2059#if FFECOM_targetCURRENT == FFECOM_targetGCC
2060static tree
2061ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s)
2062{
2063 ffetargetCharacterSize sz = ffesymbol_size (s);
2064 tree highval;
2065 tree tlen;
2066 tree type = *xtype;
2067
2068 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
2069 tlen = NULL_TREE; /* A statement function, no length passed. */
2070 else
2071 {
2072 if (ffesymbol_where (s) == FFEINFO_whereDUMMY)
2073 tlen = ffecom_get_invented_identifier ("__g77_length_%s",
2074 ffesymbol_text (s), 0);
2075 else
2076 tlen = ffecom_get_invented_identifier ("__g77_%s",
2077 "length", 0);
2078 tlen = build_decl (PARM_DECL, tlen, ffecom_f2c_ftnlen_type_node);
2079#if BUILT_FOR_270
2080 DECL_ARTIFICIAL (tlen) = 1;
2081#endif
2082 }
2083
2084 if (sz == FFETARGET_charactersizeNONE)
2085 {
2086 assert (tlen != NULL_TREE);
2b0c2df0 2087 highval = variable_size (tlen);
5ff904cd
JL
2088 }
2089 else
2090 {
2091 highval = build_int_2 (sz, 0);
2092 TREE_TYPE (highval) = ffecom_f2c_ftnlen_type_node;
2093 }
2094
2095 type = build_array_type (type,
2096 build_range_type (ffecom_f2c_ftnlen_type_node,
2097 ffecom_f2c_ftnlen_one_node,
2098 highval));
2099
2100 *xtype = type;
2101 return tlen;
2102}
2103
2104#endif
2105/* ffecom_concat_list_gather_ -- Gather list of concatenated string exprs
2106
2107 ffecomConcatList_ catlist;
2108 ffebld expr; // expr of CHARACTER basictype.
2109 ffetargetCharacterSize max; // max chars to gather or _...NONE if no max
2110 catlist = ffecom_concat_list_gather_(catlist,expr,max);
2111
2112 Scans expr for character subexpressions, updates and returns catlist
2113 accordingly. */
2114
2115#if FFECOM_targetCURRENT == FFECOM_targetGCC
2116static ffecomConcatList_
2117ffecom_concat_list_gather_ (ffecomConcatList_ catlist, ffebld expr,
2118 ffetargetCharacterSize max)
2119{
2120 ffetargetCharacterSize sz;
2121
2122recurse: /* :::::::::::::::::::: */
2123
2124 if (expr == NULL)
2125 return catlist;
2126
2127 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen >= max))
2128 return catlist; /* Don't append any more items. */
2129
2130 switch (ffebld_op (expr))
2131 {
2132 case FFEBLD_opCONTER:
2133 case FFEBLD_opSYMTER:
2134 case FFEBLD_opARRAYREF:
2135 case FFEBLD_opFUNCREF:
2136 case FFEBLD_opSUBSTR:
2137 case FFEBLD_opCONVERT: /* Callers should strip this off beforehand
2138 if they don't need to preserve it. */
2139 if (catlist.count == catlist.max)
2140 { /* Make a (larger) list. */
2141 ffebld *newx;
2142 int newmax;
2143
2144 newmax = (catlist.max == 0) ? 8 : catlist.max * 2;
2145 newx = malloc_new_ks (malloc_pool_image (), "catlist",
2146 newmax * sizeof (newx[0]));
2147 if (catlist.max != 0)
2148 {
2149 memcpy (newx, catlist.exprs, catlist.max * sizeof (newx[0]));
2150 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2151 catlist.max * sizeof (newx[0]));
2152 }
2153 catlist.max = newmax;
2154 catlist.exprs = newx;
2155 }
2156 if ((sz = ffebld_size_known (expr)) != FFETARGET_charactersizeNONE)
2157 catlist.minlen += sz;
2158 else
2159 ++catlist.minlen; /* Not true for F90; can be 0 length. */
2160 if ((sz = ffebld_size_max (expr)) == FFETARGET_charactersizeNONE)
2161 catlist.maxlen = sz;
2162 else
2163 catlist.maxlen += sz;
2164 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen > max))
2165 { /* This item overlaps (or is beyond) the end
2166 of the destination. */
2167 switch (ffebld_op (expr))
2168 {
2169 case FFEBLD_opCONTER:
2170 case FFEBLD_opSYMTER:
2171 case FFEBLD_opARRAYREF:
2172 case FFEBLD_opFUNCREF:
2173 case FFEBLD_opSUBSTR:
2174 break; /* ~~Do useful truncations here. */
2175
2176 default:
2177 assert ("op changed or inconsistent switches!" == NULL);
2178 break;
2179 }
2180 }
2181 catlist.exprs[catlist.count++] = expr;
2182 return catlist;
2183
2184 case FFEBLD_opPAREN:
2185 expr = ffebld_left (expr);
2186 goto recurse; /* :::::::::::::::::::: */
2187
2188 case FFEBLD_opCONCATENATE:
2189 catlist = ffecom_concat_list_gather_ (catlist, ffebld_left (expr), max);
2190 expr = ffebld_right (expr);
2191 goto recurse; /* :::::::::::::::::::: */
2192
2193#if 0 /* Breaks passing small actual arg to larger
2194 dummy arg of sfunc */
2195 case FFEBLD_opCONVERT:
2196 expr = ffebld_left (expr);
2197 {
2198 ffetargetCharacterSize cmax;
2199
2200 cmax = catlist.len + ffebld_size_known (expr);
2201
2202 if ((max == FFETARGET_charactersizeNONE) || (max > cmax))
2203 max = cmax;
2204 }
2205 goto recurse; /* :::::::::::::::::::: */
2206#endif
2207
2208 case FFEBLD_opANY:
2209 return catlist;
2210
2211 default:
2212 assert ("bad op in _gather_" == NULL);
2213 return catlist;
2214 }
2215}
2216
2217#endif
2218/* ffecom_concat_list_kill_ -- Kill list of concatenated string exprs
2219
2220 ffecomConcatList_ catlist;
2221 ffecom_concat_list_kill_(catlist);
2222
2223 Anything allocated within the list info is deallocated. */
2224
2225#if FFECOM_targetCURRENT == FFECOM_targetGCC
2226static void
2227ffecom_concat_list_kill_ (ffecomConcatList_ catlist)
2228{
2229 if (catlist.max != 0)
2230 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2231 catlist.max * sizeof (catlist.exprs[0]));
2232}
2233
2234#endif
2235/* ffecom_concat_list_new_ -- Make list of concatenated string exprs
2236
2237 ffecomConcatList_ catlist;
2238 ffebld expr; // Root expr of CHARACTER basictype.
2239 ffetargetCharacterSize max; // max chars to gather or _...NONE if no max
2240 catlist = ffecom_concat_list_new_(expr,max);
2241
2242 Returns a flattened list of concatenated subexpressions given a
2243 tree of such expressions. */
2244
2245#if FFECOM_targetCURRENT == FFECOM_targetGCC
2246static ffecomConcatList_
2247ffecom_concat_list_new_ (ffebld expr, ffetargetCharacterSize max)
2248{
2249 ffecomConcatList_ catlist;
2250
2251 catlist.maxlen = catlist.minlen = catlist.max = catlist.count = 0;
2252 return ffecom_concat_list_gather_ (catlist, expr, max);
2253}
2254
2255#endif
2256
2257/* Provide some kind of useful info on member of aggregate area,
2258 since current g77/gcc technology does not provide debug info
2259 on these members. */
2260
2261#if FFECOM_targetCURRENT == FFECOM_targetGCC
2262static void
2263ffecom_debug_kludge_ (tree aggr, char *aggr_type, ffesymbol member,
2264 tree member_type UNUSED, ffetargetOffset offset)
2265{
2266 tree value;
2267 tree decl;
2268 int len;
2269 char *buff;
2270 char space[120];
2271#if 0
2272 tree type_id;
2273
2274 for (type_id = member_type;
2275 TREE_CODE (type_id) != IDENTIFIER_NODE;
2276 )
2277 {
2278 switch (TREE_CODE (type_id))
2279 {
2280 case INTEGER_TYPE:
2281 case REAL_TYPE:
2282 type_id = TYPE_NAME (type_id);
2283 break;
2284
2285 case ARRAY_TYPE:
2286 case COMPLEX_TYPE:
2287 type_id = TREE_TYPE (type_id);
2288 break;
2289
2290 default:
2291 assert ("no IDENTIFIER_NODE for type!" == NULL);
2292 type_id = error_mark_node;
2293 break;
2294 }
2295 }
2296#endif
2297
2298 if (ffecom_transform_only_dummies_
2299 || !ffe_is_debug_kludge ())
2300 return; /* Can't do this yet, maybe later. */
2301
2302 len = 60
2303 + strlen (aggr_type)
2304 + IDENTIFIER_LENGTH (DECL_NAME (aggr));
2305#if 0
2306 + IDENTIFIER_LENGTH (type_id);
2307#endif
2308
2309 if (((size_t) len) >= ARRAY_SIZE (space))
2310 buff = malloc_new_ks (malloc_pool_image (), "debug_kludge", len + 1);
2311 else
2312 buff = &space[0];
2313
2314 sprintf (&buff[0], "At (%s) `%s' plus %ld bytes",
2315 aggr_type,
2316 IDENTIFIER_POINTER (DECL_NAME (aggr)),
2317 (long int) offset);
2318
2319 value = build_string (len, buff);
2320 TREE_TYPE (value)
2321 = build_type_variant (build_array_type (char_type_node,
2322 build_range_type
2323 (integer_type_node,
2324 integer_one_node,
2325 build_int_2 (strlen (buff), 0))),
2326 1, 0);
2327 decl = build_decl (VAR_DECL,
2328 ffecom_get_identifier_ (ffesymbol_text (member)),
2329 TREE_TYPE (value));
2330 TREE_CONSTANT (decl) = 1;
2331 TREE_STATIC (decl) = 1;
2332 DECL_INITIAL (decl) = error_mark_node;
2333 DECL_IN_SYSTEM_HEADER (decl) = 1; /* Don't let -Wunused complain. */
2334 decl = start_decl (decl, FALSE);
2335 finish_decl (decl, value, FALSE);
2336
2337 if (buff != &space[0])
2338 malloc_kill_ks (malloc_pool_image (), buff, len + 1);
2339}
2340#endif
2341
2342/* ffecom_do_entry_ -- Do compilation of a particular entrypoint
2343
2344 ffesymbol fn; // the SUBROUTINE, FUNCTION, or ENTRY symbol itself
2345 int i; // entry# for this entrypoint (used by master fn)
2346 ffecom_do_entrypoint_(s,i);
2347
2348 Makes a public entry point that calls our private master fn (already
2349 compiled). */
2350
2351#if FFECOM_targetCURRENT == FFECOM_targetGCC
2352static void
2353ffecom_do_entry_ (ffesymbol fn, int entrynum)
2354{
2355 ffebld item;
2356 tree type; /* Type of function. */
2357 tree multi_retval; /* Var holding return value (union). */
2358 tree result; /* Var holding result. */
2359 ffeinfoBasictype bt;
2360 ffeinfoKindtype kt;
2361 ffeglobal g;
2362 ffeglobalType gt;
2363 bool charfunc; /* All entry points return same type
2364 CHARACTER. */
2365 bool cmplxfunc; /* Use f2c way of returning COMPLEX. */
2366 bool multi; /* Master fn has multiple return types. */
2367 bool altreturning = FALSE; /* This entry point has alternate returns. */
2368 int yes;
44d2eabc
JL
2369 int old_lineno = lineno;
2370 char *old_input_filename = input_filename;
2371
2372 input_filename = ffesymbol_where_filename (fn);
2373 lineno = ffesymbol_where_filelinenum (fn);
5ff904cd
JL
2374
2375 /* c-parse.y indeed does call suspend_momentary and not only ignores the
2376 return value, but also never calls resume_momentary, when starting an
2377 outer function (see "fndef:", "setspecs:", and so on). So g77 does the
2378 same thing. It shouldn't be a problem since start_function calls
2379 temporary_allocation, but it might be necessary. If it causes a problem
2380 here, then maybe there's a bug lurking in gcc. NOTE: This identical
2381 comment appears twice in thist file. */
2382
2383 suspend_momentary ();
2384
2385 ffecom_doing_entry_ = TRUE; /* Don't bother with array dimensions. */
2386
2387 switch (ffecom_primary_entry_kind_)
2388 {
2389 case FFEINFO_kindFUNCTION:
2390
2391 /* Determine actual return type for function. */
2392
2393 gt = FFEGLOBAL_typeFUNC;
2394 bt = ffesymbol_basictype (fn);
2395 kt = ffesymbol_kindtype (fn);
2396 if (bt == FFEINFO_basictypeNONE)
2397 {
2398 ffeimplic_establish_symbol (fn);
2399 if (ffesymbol_funcresult (fn) != NULL)
2400 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
2401 bt = ffesymbol_basictype (fn);
2402 kt = ffesymbol_kindtype (fn);
2403 }
2404
2405 if (bt == FFEINFO_basictypeCHARACTER)
2406 charfunc = TRUE, cmplxfunc = FALSE;
2407 else if ((bt == FFEINFO_basictypeCOMPLEX)
2408 && ffesymbol_is_f2c (fn))
2409 charfunc = FALSE, cmplxfunc = TRUE;
2410 else
2411 charfunc = cmplxfunc = FALSE;
2412
2413 if (charfunc)
2414 type = ffecom_tree_fun_type_void;
2415 else if (ffesymbol_is_f2c (fn))
2416 type = ffecom_tree_fun_type[bt][kt];
2417 else
2418 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
2419
2420 if ((type == NULL_TREE)
2421 || (TREE_TYPE (type) == NULL_TREE))
2422 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
2423
2424 multi = (ffecom_master_bt_ == FFEINFO_basictypeNONE);
2425 break;
2426
2427 case FFEINFO_kindSUBROUTINE:
2428 gt = FFEGLOBAL_typeSUBR;
2429 bt = FFEINFO_basictypeNONE;
2430 kt = FFEINFO_kindtypeNONE;
2431 if (ffecom_is_altreturning_)
2432 { /* Am _I_ altreturning? */
2433 for (item = ffesymbol_dummyargs (fn);
2434 item != NULL;
2435 item = ffebld_trail (item))
2436 {
2437 if (ffebld_op (ffebld_head (item)) == FFEBLD_opSTAR)
2438 {
2439 altreturning = TRUE;
2440 break;
2441 }
2442 }
2443 if (altreturning)
2444 type = ffecom_tree_subr_type;
2445 else
2446 type = ffecom_tree_fun_type_void;
2447 }
2448 else
2449 type = ffecom_tree_fun_type_void;
2450 charfunc = FALSE;
2451 cmplxfunc = FALSE;
2452 multi = FALSE;
2453 break;
2454
2455 default:
2456 assert ("say what??" == NULL);
2457 /* Fall through. */
2458 case FFEINFO_kindANY:
2459 gt = FFEGLOBAL_typeANY;
2460 bt = FFEINFO_basictypeNONE;
2461 kt = FFEINFO_kindtypeNONE;
2462 type = error_mark_node;
2463 charfunc = FALSE;
2464 cmplxfunc = FALSE;
2465 multi = FALSE;
2466 break;
2467 }
2468
2469 /* build_decl uses the current lineno and input_filename to set the decl
2470 source info. So, I've putzed with ffestd and ffeste code to update that
2471 source info to point to the appropriate statement just before calling
2472 ffecom_do_entrypoint (which calls this fn). */
2473
2474 start_function (ffecom_get_external_identifier_ (fn),
2475 type,
2476 0, /* nested/inline */
2477 1); /* TREE_PUBLIC */
2478
2479 if (((g = ffesymbol_global (fn)) != NULL)
2480 && ((ffeglobal_type (g) == gt)
2481 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
2482 {
2483 ffeglobal_set_hook (g, current_function_decl);
2484 }
2485
2486 /* Reset args in master arg list so they get retransitioned. */
2487
2488 for (item = ffecom_master_arglist_;
2489 item != NULL;
2490 item = ffebld_trail (item))
2491 {
2492 ffebld arg;
2493 ffesymbol s;
2494
2495 arg = ffebld_head (item);
2496 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2497 continue; /* Alternate return or some such thing. */
2498 s = ffebld_symter (arg);
2499 ffesymbol_hook (s).decl_tree = NULL_TREE;
2500 ffesymbol_hook (s).length_tree = NULL_TREE;
2501 }
2502
2503 /* Build dummy arg list for this entry point. */
2504
2505 yes = suspend_momentary ();
2506
2507 if (charfunc || cmplxfunc)
2508 { /* Prepend arg for where result goes. */
2509 tree type;
2510 tree length;
2511
2512 if (charfunc)
2513 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
2514 else
2515 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
2516
2517 result = ffecom_get_invented_identifier ("__g77_%s",
2518 "result", 0);
2519
2520 /* Make length arg _and_ enhance type info for CHAR arg itself. */
2521
2522 if (charfunc)
2523 length = ffecom_char_enhance_arg_ (&type, fn);
2524 else
2525 length = NULL_TREE; /* Not ref'd if !charfunc. */
2526
2527 type = build_pointer_type (type);
2528 result = build_decl (PARM_DECL, result, type);
2529
2530 push_parm_decl (result);
2531 ffecom_func_result_ = result;
2532
2533 if (charfunc)
2534 {
2535 push_parm_decl (length);
2536 ffecom_func_length_ = length;
2537 }
2538 }
2539 else
2540 result = DECL_RESULT (current_function_decl);
2541
2542 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (fn), FALSE);
2543
2544 resume_momentary (yes);
2545
2546 store_parm_decls (0);
2547
2548 ffecom_start_compstmt_ ();
2549
2550 /* Make local var to hold return type for multi-type master fn. */
2551
2552 if (multi)
2553 {
2554 yes = suspend_momentary ();
2555
2556 multi_retval = ffecom_get_invented_identifier ("__g77_%s",
2557 "multi_retval", 0);
2558 multi_retval = build_decl (VAR_DECL, multi_retval,
2559 ffecom_multi_type_node_);
2560 multi_retval = start_decl (multi_retval, FALSE);
2561 finish_decl (multi_retval, NULL_TREE, FALSE);
2562
2563 resume_momentary (yes);
2564 }
2565 else
2566 multi_retval = NULL_TREE; /* Not actually ref'd if !multi. */
2567
2568 /* Here we emit the actual code for the entry point. */
2569
2570 {
2571 ffebld list;
2572 ffebld arg;
2573 ffesymbol s;
2574 tree arglist = NULL_TREE;
2575 tree *plist = &arglist;
2576 tree prepend;
2577 tree call;
2578 tree actarg;
2579 tree master_fn;
2580
2581 /* Prepare actual arg list based on master arg list. */
2582
2583 for (list = ffecom_master_arglist_;
2584 list != NULL;
2585 list = ffebld_trail (list))
2586 {
2587 arg = ffebld_head (list);
2588 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2589 continue;
2590 s = ffebld_symter (arg);
2591 if (ffesymbol_hook (s).decl_tree == NULL_TREE)
2592 actarg = null_pointer_node; /* We don't have this arg. */
2593 else
2594 actarg = ffesymbol_hook (s).decl_tree;
2595 *plist = build_tree_list (NULL_TREE, actarg);
2596 plist = &TREE_CHAIN (*plist);
2597 }
2598
2599 /* This code appends the length arguments for character
2600 variables/arrays. */
2601
2602 for (list = ffecom_master_arglist_;
2603 list != NULL;
2604 list = ffebld_trail (list))
2605 {
2606 arg = ffebld_head (list);
2607 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2608 continue;
2609 s = ffebld_symter (arg);
2610 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
2611 continue; /* Only looking for CHARACTER arguments. */
2612 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
2613 continue; /* Only looking for variables and arrays. */
2614 if (ffesymbol_hook (s).length_tree == NULL_TREE)
2615 actarg = ffecom_f2c_ftnlen_zero_node; /* We don't have this arg. */
2616 else
2617 actarg = ffesymbol_hook (s).length_tree;
2618 *plist = build_tree_list (NULL_TREE, actarg);
2619 plist = &TREE_CHAIN (*plist);
2620 }
2621
2622 /* Prepend character-value return info to actual arg list. */
2623
2624 if (charfunc)
2625 {
2626 prepend = build_tree_list (NULL_TREE, ffecom_func_result_);
2627 TREE_CHAIN (prepend)
2628 = build_tree_list (NULL_TREE, ffecom_func_length_);
2629 TREE_CHAIN (TREE_CHAIN (prepend)) = arglist;
2630 arglist = prepend;
2631 }
2632
2633 /* Prepend multi-type return value to actual arg list. */
2634
2635 if (multi)
2636 {
2637 prepend
2638 = build_tree_list (NULL_TREE,
2639 ffecom_1 (ADDR_EXPR,
2640 build_pointer_type (TREE_TYPE (multi_retval)),
2641 multi_retval));
2642 TREE_CHAIN (prepend) = arglist;
2643 arglist = prepend;
2644 }
2645
2646 /* Prepend my entry-point number to the actual arg list. */
2647
2648 prepend = build_tree_list (NULL_TREE, build_int_2 (entrynum, 0));
2649 TREE_CHAIN (prepend) = arglist;
2650 arglist = prepend;
2651
2652 /* Build the call to the master function. */
2653
2654 master_fn = ffecom_1_fn (ffecom_previous_function_decl_);
2655 call = ffecom_3s (CALL_EXPR,
2656 TREE_TYPE (TREE_TYPE (TREE_TYPE (master_fn))),
2657 master_fn, arglist, NULL_TREE);
2658
2659 /* Decide whether the master function is a function or subroutine, and
2660 handle the return value for my entry point. */
2661
2662 if (charfunc || ((ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
2663 && !altreturning))
2664 {
2665 expand_expr_stmt (call);
2666 expand_null_return ();
2667 }
2668 else if (multi && cmplxfunc)
2669 {
2670 expand_expr_stmt (call);
2671 result
2672 = ffecom_1 (INDIRECT_REF,
2673 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
2674 result);
2675 result = ffecom_modify (NULL_TREE, result,
2676 ffecom_2 (COMPONENT_REF, TREE_TYPE (result),
2677 multi_retval,
2678 ffecom_multi_fields_[bt][kt]));
2679 expand_expr_stmt (result);
2680 expand_null_return ();
2681 }
2682 else if (multi)
2683 {
2684 expand_expr_stmt (call);
2685 result
2686 = ffecom_modify (NULL_TREE, result,
2687 convert (TREE_TYPE (result),
2688 ffecom_2 (COMPONENT_REF,
2689 ffecom_tree_type[bt][kt],
2690 multi_retval,
2691 ffecom_multi_fields_[bt][kt])));
2692 expand_return (result);
2693 }
2694 else if (cmplxfunc)
2695 {
2696 result
2697 = ffecom_1 (INDIRECT_REF,
2698 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
2699 result);
2700 result = ffecom_modify (NULL_TREE, result, call);
2701 expand_expr_stmt (result);
2702 expand_null_return ();
2703 }
2704 else
2705 {
2706 result = ffecom_modify (NULL_TREE,
2707 result,
2708 convert (TREE_TYPE (result),
2709 call));
2710 expand_return (result);
2711 }
2712
2713 clear_momentary ();
2714 }
2715
2716 ffecom_end_compstmt_ ();
2717
2718 finish_function (0);
2719
44d2eabc
JL
2720 lineno = old_lineno;
2721 input_filename = old_input_filename;
2722
5ff904cd
JL
2723 ffecom_doing_entry_ = FALSE;
2724}
2725
2726#endif
2727/* Transform expr into gcc tree with possible destination
2728
2729 Recursive descent on expr while making corresponding tree nodes and
2730 attaching type info and such. If destination supplied and compatible
2731 with temporary that would be made in certain cases, temporary isn't
092a4ef8 2732 made, destination used instead, and dest_used flag set TRUE. */
5ff904cd
JL
2733
2734#if FFECOM_targetCURRENT == FFECOM_targetGCC
2735static tree
092a4ef8
RH
2736ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
2737 bool *dest_used, bool assignp, bool widenp)
5ff904cd
JL
2738{
2739 tree item;
2740 tree list;
2741 tree args;
2742 ffeinfoBasictype bt;
2743 ffeinfoKindtype kt;
2744 tree t;
5ff904cd 2745 tree dt; /* decl_tree for an ffesymbol. */
092a4ef8 2746 tree tree_type, tree_type_x;
af752698 2747 tree left, right;
5ff904cd
JL
2748 ffesymbol s;
2749 enum tree_code code;
2750
2751 assert (expr != NULL);
2752
2753 if (dest_used != NULL)
2754 *dest_used = FALSE;
2755
2756 bt = ffeinfo_basictype (ffebld_info (expr));
2757 kt = ffeinfo_kindtype (ffebld_info (expr));
af752698 2758 tree_type = ffecom_tree_type[bt][kt];
5ff904cd 2759
092a4ef8
RH
2760 /* Widen integral arithmetic as desired while preserving signedness. */
2761 tree_type_x = NULL_TREE;
2762 if (widenp && tree_type
2763 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
2764 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
2765 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
2766
5ff904cd
JL
2767 switch (ffebld_op (expr))
2768 {
2769 case FFEBLD_opACCTER:
5ff904cd
JL
2770 {
2771 ffebitCount i;
2772 ffebit bits = ffebld_accter_bits (expr);
2773 ffetargetOffset source_offset = 0;
a6fa6420 2774 ffetargetOffset dest_offset = ffebld_accter_pad (expr);
5ff904cd
JL
2775 tree purpose;
2776
a6fa6420
CB
2777 assert (dest_offset == 0
2778 || (bt == FFEINFO_basictypeCHARACTER
2779 && kt == FFEINFO_kindtypeCHARACTER1));
5ff904cd
JL
2780
2781 list = item = NULL;
2782 for (;;)
2783 {
2784 ffebldConstantUnion cu;
2785 ffebitCount length;
2786 bool value;
2787 ffebldConstantArray ca = ffebld_accter (expr);
2788
2789 ffebit_test (bits, source_offset, &value, &length);
2790 if (length == 0)
2791 break;
2792
2793 if (value)
2794 {
2795 for (i = 0; i < length; ++i)
2796 {
2797 cu = ffebld_constantarray_get (ca, bt, kt,
2798 source_offset + i);
2799
2800 t = ffecom_constantunion (&cu, bt, kt, tree_type);
2801
a6fa6420
CB
2802 if (i == 0
2803 && dest_offset != 0)
2804 purpose = build_int_2 (dest_offset, 0);
5ff904cd
JL
2805 else
2806 purpose = NULL_TREE;
2807
2808 if (list == NULL_TREE)
2809 list = item = build_tree_list (purpose, t);
2810 else
2811 {
2812 TREE_CHAIN (item) = build_tree_list (purpose, t);
2813 item = TREE_CHAIN (item);
2814 }
2815 }
2816 }
2817 source_offset += length;
a6fa6420 2818 dest_offset += length;
5ff904cd
JL
2819 }
2820 }
2821
a6fa6420
CB
2822 item = build_int_2 ((ffebld_accter_size (expr)
2823 + ffebld_accter_pad (expr)) - 1, 0);
5ff904cd
JL
2824 ffebit_kill (ffebld_accter_bits (expr));
2825 TREE_TYPE (item) = ffecom_integer_type_node;
2826 item
2827 = build_array_type
2828 (tree_type,
2829 build_range_type (ffecom_integer_type_node,
2830 ffecom_integer_zero_node,
2831 item));
2832 list = build (CONSTRUCTOR, item, NULL_TREE, list);
2833 TREE_CONSTANT (list) = 1;
2834 TREE_STATIC (list) = 1;
2835 return list;
2836
2837 case FFEBLD_opARRTER:
5ff904cd
JL
2838 {
2839 ffetargetOffset i;
2840
a6fa6420
CB
2841 list = NULL_TREE;
2842 if (ffebld_arrter_pad (expr) == 0)
2843 item = NULL_TREE;
2844 else
2845 {
2846 assert (bt == FFEINFO_basictypeCHARACTER
2847 && kt == FFEINFO_kindtypeCHARACTER1);
2848
2849 /* Becomes PURPOSE first time through loop. */
2850 item = build_int_2 (ffebld_arrter_pad (expr), 0);
2851 }
2852
5ff904cd
JL
2853 for (i = 0; i < ffebld_arrter_size (expr); ++i)
2854 {
2855 ffebldConstantUnion cu
2856 = ffebld_constantarray_get (ffebld_arrter (expr), bt, kt, i);
2857
2858 t = ffecom_constantunion (&cu, bt, kt, tree_type);
2859
2860 if (list == NULL_TREE)
a6fa6420
CB
2861 /* Assume item is PURPOSE first time through loop. */
2862 list = item = build_tree_list (item, t);
5ff904cd
JL
2863 else
2864 {
2865 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
2866 item = TREE_CHAIN (item);
2867 }
2868 }
2869 }
2870
a6fa6420
CB
2871 item = build_int_2 ((ffebld_arrter_size (expr)
2872 + ffebld_arrter_pad (expr)) - 1, 0);
5ff904cd
JL
2873 TREE_TYPE (item) = ffecom_integer_type_node;
2874 item
2875 = build_array_type
2876 (tree_type,
2877 build_range_type (ffecom_integer_type_node,
a6fa6420 2878 ffecom_integer_zero_node,
5ff904cd
JL
2879 item));
2880 list = build (CONSTRUCTOR, item, NULL_TREE, list);
2881 TREE_CONSTANT (list) = 1;
2882 TREE_STATIC (list) = 1;
2883 return list;
2884
2885 case FFEBLD_opCONTER:
5ff904cd
JL
2886 item
2887 = ffecom_constantunion (&ffebld_constant_union (ffebld_conter (expr)),
2888 bt, kt, tree_type);
2889 return item;
2890
2891 case FFEBLD_opSYMTER:
2892 if ((ffebld_symter_generic (expr) != FFEINTRIN_genNONE)
2893 || (ffebld_symter_specific (expr) != FFEINTRIN_specNONE))
2894 return ffecom_ptr_to_expr (expr); /* Same as %REF(intrinsic). */
2895 s = ffebld_symter (expr);
2896 t = ffesymbol_hook (s).decl_tree;
2897
2898 if (assignp)
2899 { /* ASSIGN'ed-label expr. */
2900 if (ffe_is_ugly_assign ())
2901 {
2902 /* User explicitly wants ASSIGN'ed variables to be at the same
2903 memory address as the variables when used in non-ASSIGN
2904 contexts. That can make old, arcane, non-standard code
2905 work, but don't try to do it when a pointer wouldn't fit
2906 in the normal variable (take other approach, and warn,
2907 instead). */
2908
2909 if (t == NULL_TREE)
2910 {
2911 s = ffecom_sym_transform_ (s);
2912 t = ffesymbol_hook (s).decl_tree;
2913 assert (t != NULL_TREE);
2914 }
2915
2916 if (t == error_mark_node)
2917 return t;
2918
2919 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (t)))
2920 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
2921 {
2922 if (ffesymbol_hook (s).addr)
2923 t = ffecom_1 (INDIRECT_REF,
2924 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
2925 return t;
2926 }
2927
2928 if (ffesymbol_hook (s).assign_tree == NULL_TREE)
2929 {
2930 ffebad_start_msg ("ASSIGN'ed label cannot fit into `%A' at %0 -- using wider sibling",
2931 FFEBAD_severityWARNING);
2932 ffebad_string (ffesymbol_text (s));
2933 ffebad_here (0, ffesymbol_where_line (s),
2934 ffesymbol_where_column (s));
2935 ffebad_finish ();
2936 }
2937 }
2938
2939 /* Don't use the normal variable's tree for ASSIGN, though mark
2940 it as in the system header (housekeeping). Use an explicit,
2941 specially created sibling that is known to be wide enough
2942 to hold pointers to labels. */
2943
2944 if (t != NULL_TREE
2945 && TREE_CODE (t) == VAR_DECL)
2946 DECL_IN_SYSTEM_HEADER (t) = 1; /* Don't let -Wunused complain. */
2947
2948 t = ffesymbol_hook (s).assign_tree;
2949 if (t == NULL_TREE)
2950 {
2951 s = ffecom_sym_transform_assign_ (s);
2952 t = ffesymbol_hook (s).assign_tree;
2953 assert (t != NULL_TREE);
2954 }
2955 }
2956 else
2957 {
2958 if (t == NULL_TREE)
2959 {
2960 s = ffecom_sym_transform_ (s);
2961 t = ffesymbol_hook (s).decl_tree;
2962 assert (t != NULL_TREE);
2963 }
2964 if (ffesymbol_hook (s).addr)
2965 t = ffecom_1 (INDIRECT_REF,
2966 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
2967 }
2968 return t;
2969
2970 case FFEBLD_opARRAYREF:
2971 {
2972 ffebld dims[FFECOM_dimensionsMAX];
2973#if FFECOM_FASTER_ARRAY_REFS
2974 tree array;
2975#endif
2976 int i;
2977
2978#if FFECOM_FASTER_ARRAY_REFS
2979 t = ffecom_ptr_to_expr (ffebld_left (expr));
2980#else
2981 t = ffecom_expr (ffebld_left (expr));
2982#endif
2983 if (t == error_mark_node)
2984 return t;
2985
2986 if ((ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereFLEETING)
2987 && !mark_addressable (t))
2988 return error_mark_node; /* Make sure non-const ref is to
2989 non-reg. */
2990
2991 /* Build up ARRAY_REFs in reverse order (since we're column major
2992 here in Fortran land). */
2993
2994 for (i = 0, expr = ffebld_right (expr);
2995 expr != NULL;
2996 expr = ffebld_trail (expr))
2997 dims[i++] = ffebld_head (expr);
2998
2999#if FFECOM_FASTER_ARRAY_REFS
3000 for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t)));
3001 i >= 0;
3002 --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
3003 t = ffecom_2 (PLUS_EXPR,
3004 build_pointer_type (TREE_TYPE (array)),
3005 t,
3006 size_binop (MULT_EXPR,
3007 size_in_bytes (TREE_TYPE (array)),
3008 size_binop (MINUS_EXPR,
3009 ffecom_expr (dims[i]),
3010 TYPE_MIN_VALUE (TYPE_DOMAIN (array)))));
3011 t = ffecom_1 (INDIRECT_REF,
3012 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))),
3013 t);
3014#else
3015 while (i > 0)
3016 t = ffecom_2 (ARRAY_REF,
3017 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))),
3018 t,
092a4ef8 3019 ffecom_expr_ (dims[--i], NULL, NULL, NULL, FALSE, TRUE));
5ff904cd
JL
3020#endif
3021
3022 return t;
3023 }
3024
3025 case FFEBLD_opUPLUS:
092a4ef8 3026 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
af752698 3027 return ffecom_1 (NOP_EXPR, tree_type, left);
5ff904cd
JL
3028
3029 case FFEBLD_opPAREN: /* ~~~Make sure Fortran rules respected here */
092a4ef8 3030 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
af752698 3031 return ffecom_1 (NOP_EXPR, tree_type, left);
5ff904cd
JL
3032
3033 case FFEBLD_opUMINUS:
092a4ef8 3034 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3035 if (tree_type_x)
3036 {
3037 tree_type = tree_type_x;
3038 left = convert (tree_type, left);
3039 }
3040 return ffecom_1 (NEGATE_EXPR, tree_type, left);
5ff904cd
JL
3041
3042 case FFEBLD_opADD:
092a4ef8
RH
3043 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3044 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3045 if (tree_type_x)
3046 {
3047 tree_type = tree_type_x;
3048 left = convert (tree_type, left);
3049 right = convert (tree_type, right);
3050 }
3051 return ffecom_2 (PLUS_EXPR, tree_type, left, right);
5ff904cd
JL
3052
3053 case FFEBLD_opSUBTRACT:
092a4ef8
RH
3054 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3055 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3056 if (tree_type_x)
3057 {
3058 tree_type = tree_type_x;
3059 left = convert (tree_type, left);
3060 right = convert (tree_type, right);
3061 }
3062 return ffecom_2 (MINUS_EXPR, tree_type, left, right);
5ff904cd
JL
3063
3064 case FFEBLD_opMULTIPLY:
092a4ef8
RH
3065 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3066 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3067 if (tree_type_x)
3068 {
3069 tree_type = tree_type_x;
3070 left = convert (tree_type, left);
3071 right = convert (tree_type, right);
3072 }
3073 return ffecom_2 (MULT_EXPR, tree_type, left, right);
5ff904cd
JL
3074
3075 case FFEBLD_opDIVIDE:
092a4ef8
RH
3076 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3077 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
af752698
RH
3078 if (tree_type_x)
3079 {
3080 tree_type = tree_type_x;
3081 left = convert (tree_type, left);
3082 right = convert (tree_type, right);
3083 }
3084 return ffecom_tree_divide_ (tree_type, left, right,
83ffecd2 3085 dest_tree, dest, dest_used);
5ff904cd
JL
3086
3087 case FFEBLD_opPOWER:
5ff904cd
JL
3088 {
3089 ffebld left = ffebld_left (expr);
3090 ffebld right = ffebld_right (expr);
3091 ffecomGfrt code;
3092 ffeinfoKindtype rtkt;
270fc4e8 3093 ffeinfoKindtype ltkt;
5ff904cd
JL
3094
3095 switch (ffeinfo_basictype (ffebld_info (right)))
3096 {
3097 case FFEINFO_basictypeINTEGER:
3098 if (1 || optimize)
3099 {
3100 item = ffecom_expr_power_integer_ (left, right);
3101 if (item != NULL_TREE)
3102 return item;
3103 }
3104
3105 rtkt = FFEINFO_kindtypeINTEGER1;
3106 switch (ffeinfo_basictype (ffebld_info (left)))
3107 {
3108 case FFEINFO_basictypeINTEGER:
3109 if ((ffeinfo_kindtype (ffebld_info (left))
3110 == FFEINFO_kindtypeINTEGER4)
3111 || (ffeinfo_kindtype (ffebld_info (right))
3112 == FFEINFO_kindtypeINTEGER4))
3113 {
3114 code = FFECOM_gfrtPOW_QQ;
270fc4e8 3115 ltkt = FFEINFO_kindtypeINTEGER4;
5ff904cd
JL
3116 rtkt = FFEINFO_kindtypeINTEGER4;
3117 }
3118 else
6a047254
CB
3119 {
3120 code = FFECOM_gfrtPOW_II;
3121 ltkt = FFEINFO_kindtypeINTEGER1;
3122 }
5ff904cd
JL
3123 break;
3124
3125 case FFEINFO_basictypeREAL:
3126 if (ffeinfo_kindtype (ffebld_info (left))
3127 == FFEINFO_kindtypeREAL1)
6a047254
CB
3128 {
3129 code = FFECOM_gfrtPOW_RI;
3130 ltkt = FFEINFO_kindtypeREAL1;
3131 }
5ff904cd 3132 else
6a047254
CB
3133 {
3134 code = FFECOM_gfrtPOW_DI;
3135 ltkt = FFEINFO_kindtypeREAL2;
3136 }
5ff904cd
JL
3137 break;
3138
3139 case FFEINFO_basictypeCOMPLEX:
3140 if (ffeinfo_kindtype (ffebld_info (left))
3141 == FFEINFO_kindtypeREAL1)
6a047254
CB
3142 {
3143 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
3144 ltkt = FFEINFO_kindtypeREAL1;
3145 }
5ff904cd 3146 else
6a047254
CB
3147 {
3148 code = FFECOM_gfrtPOW_ZI; /* Overlapping result okay. */
3149 ltkt = FFEINFO_kindtypeREAL2;
3150 }
5ff904cd
JL
3151 break;
3152
3153 default:
3154 assert ("bad pow_*i" == NULL);
3155 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
6a047254 3156 ltkt = FFEINFO_kindtypeREAL1;
5ff904cd
JL
3157 break;
3158 }
270fc4e8 3159 if (ffeinfo_kindtype (ffebld_info (left)) != ltkt)
5ff904cd 3160 left = ffeexpr_convert (left, NULL, NULL,
6a047254 3161 ffeinfo_basictype (ffebld_info (left)),
270fc4e8 3162 ltkt, 0,
5ff904cd
JL
3163 FFETARGET_charactersizeNONE,
3164 FFEEXPR_contextLET);
3165 if (ffeinfo_kindtype (ffebld_info (right)) != rtkt)
3166 right = ffeexpr_convert (right, NULL, NULL,
3167 FFEINFO_basictypeINTEGER,
3168 rtkt, 0,
3169 FFETARGET_charactersizeNONE,
3170 FFEEXPR_contextLET);
3171 break;
3172
3173 case FFEINFO_basictypeREAL:
3174 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3175 left = ffeexpr_convert (left, NULL, NULL, FFEINFO_basictypeREAL,
3176 FFEINFO_kindtypeREALDOUBLE, 0,
3177 FFETARGET_charactersizeNONE,
3178 FFEEXPR_contextLET);
3179 if (ffeinfo_kindtype (ffebld_info (right))
3180 == FFEINFO_kindtypeREAL1)
3181 right = ffeexpr_convert (right, NULL, NULL,
3182 FFEINFO_basictypeREAL,
3183 FFEINFO_kindtypeREALDOUBLE, 0,
3184 FFETARGET_charactersizeNONE,
3185 FFEEXPR_contextLET);
3186 code = FFECOM_gfrtPOW_DD;
3187 break;
3188
3189 case FFEINFO_basictypeCOMPLEX:
3190 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3191 left = ffeexpr_convert (left, NULL, NULL,
3192 FFEINFO_basictypeCOMPLEX,
3193 FFEINFO_kindtypeREALDOUBLE, 0,
3194 FFETARGET_charactersizeNONE,
3195 FFEEXPR_contextLET);
3196 if (ffeinfo_kindtype (ffebld_info (right))
3197 == FFEINFO_kindtypeREAL1)
3198 right = ffeexpr_convert (right, NULL, NULL,
3199 FFEINFO_basictypeCOMPLEX,
3200 FFEINFO_kindtypeREALDOUBLE, 0,
3201 FFETARGET_charactersizeNONE,
3202 FFEEXPR_contextLET);
3203 code = FFECOM_gfrtPOW_ZZ; /* Overlapping result okay. */
3204 break;
3205
3206 default:
3207 assert ("bad pow_x*" == NULL);
3208 code = FFECOM_gfrtPOW_II;
3209 break;
3210 }
3211 return ffecom_call_binop_ (ffecom_gfrt_tree_ (code),
3212 ffecom_gfrt_kindtype (code),
3213 (ffe_is_f2c_library ()
3214 && ffecom_gfrt_complex_[code]),
3215 tree_type, left, right,
3216 dest_tree, dest, dest_used,
3217 NULL_TREE, FALSE);
3218 }
3219
3220 case FFEBLD_opNOT:
5ff904cd
JL
3221 switch (bt)
3222 {
3223 case FFEINFO_basictypeLOGICAL:
83ffecd2 3224 item = ffecom_truth_value_invert (ffecom_expr (ffebld_left (expr)));
5ff904cd
JL
3225 return convert (tree_type, item);
3226
3227 case FFEINFO_basictypeINTEGER:
3228 return ffecom_1 (BIT_NOT_EXPR, tree_type,
3229 ffecom_expr (ffebld_left (expr)));
3230
3231 default:
3232 assert ("NOT bad basictype" == NULL);
3233 /* Fall through. */
3234 case FFEINFO_basictypeANY:
3235 return error_mark_node;
3236 }
3237 break;
3238
3239 case FFEBLD_opFUNCREF:
3240 assert (ffeinfo_basictype (ffebld_info (expr))
3241 != FFEINFO_basictypeCHARACTER);
3242 /* Fall through. */
3243 case FFEBLD_opSUBRREF:
5ff904cd
JL
3244 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
3245 == FFEINFO_whereINTRINSIC)
3246 { /* Invocation of an intrinsic. */
3247 item = ffecom_expr_intrinsic_ (expr, dest_tree, dest,
3248 dest_used);
3249 return item;
3250 }
3251 s = ffebld_symter (ffebld_left (expr));
3252 dt = ffesymbol_hook (s).decl_tree;
3253 if (dt == NULL_TREE)
3254 {
3255 s = ffecom_sym_transform_ (s);
3256 dt = ffesymbol_hook (s).decl_tree;
3257 }
3258 if (dt == error_mark_node)
3259 return dt;
3260
3261 if (ffesymbol_hook (s).addr)
3262 item = dt;
3263 else
3264 item = ffecom_1_fn (dt);
3265
3266 ffecom_push_calltemps ();
3267 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
3268 args = ffecom_list_expr (ffebld_right (expr));
3269 else
3270 args = ffecom_list_ptr_to_expr (ffebld_right (expr));
3271 ffecom_pop_calltemps ();
3272
3273 item = ffecom_call_ (item, kt,
3274 ffesymbol_is_f2c (s)
3275 && (bt == FFEINFO_basictypeCOMPLEX)
3276 && (ffesymbol_where (s)
3277 != FFEINFO_whereCONSTANT),
3278 tree_type,
3279 args,
3280 dest_tree, dest, dest_used,
3281 error_mark_node, FALSE);
3282 TREE_SIDE_EFFECTS (item) = 1;
3283 return item;
3284
3285 case FFEBLD_opAND:
5ff904cd
JL
3286 switch (bt)
3287 {
3288 case FFEINFO_basictypeLOGICAL:
3289 item
3290 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3291 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3292 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3293 return convert (tree_type, item);
3294
3295 case FFEINFO_basictypeINTEGER:
3296 return ffecom_2 (BIT_AND_EXPR, tree_type,
3297 ffecom_expr (ffebld_left (expr)),
3298 ffecom_expr (ffebld_right (expr)));
3299
3300 default:
3301 assert ("AND bad basictype" == NULL);
3302 /* Fall through. */
3303 case FFEINFO_basictypeANY:
3304 return error_mark_node;
3305 }
3306 break;
3307
3308 case FFEBLD_opOR:
5ff904cd
JL
3309 switch (bt)
3310 {
3311 case FFEINFO_basictypeLOGICAL:
3312 item
3313 = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
3314 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3315 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3316 return convert (tree_type, item);
3317
3318 case FFEINFO_basictypeINTEGER:
3319 return ffecom_2 (BIT_IOR_EXPR, tree_type,
3320 ffecom_expr (ffebld_left (expr)),
3321 ffecom_expr (ffebld_right (expr)));
3322
3323 default:
3324 assert ("OR bad basictype" == NULL);
3325 /* Fall through. */
3326 case FFEINFO_basictypeANY:
3327 return error_mark_node;
3328 }
3329 break;
3330
3331 case FFEBLD_opXOR:
3332 case FFEBLD_opNEQV:
5ff904cd
JL
3333 switch (bt)
3334 {
3335 case FFEINFO_basictypeLOGICAL:
3336 item
3337 = ffecom_2 (NE_EXPR, integer_type_node,
3338 ffecom_expr (ffebld_left (expr)),
3339 ffecom_expr (ffebld_right (expr)));
3340 return convert (tree_type, ffecom_truth_value (item));
3341
3342 case FFEINFO_basictypeINTEGER:
3343 return ffecom_2 (BIT_XOR_EXPR, tree_type,
3344 ffecom_expr (ffebld_left (expr)),
3345 ffecom_expr (ffebld_right (expr)));
3346
3347 default:
3348 assert ("XOR/NEQV bad basictype" == NULL);
3349 /* Fall through. */
3350 case FFEINFO_basictypeANY:
3351 return error_mark_node;
3352 }
3353 break;
3354
3355 case FFEBLD_opEQV:
5ff904cd
JL
3356 switch (bt)
3357 {
3358 case FFEINFO_basictypeLOGICAL:
3359 item
3360 = ffecom_2 (EQ_EXPR, integer_type_node,
3361 ffecom_expr (ffebld_left (expr)),
3362 ffecom_expr (ffebld_right (expr)));
3363 return convert (tree_type, ffecom_truth_value (item));
3364
3365 case FFEINFO_basictypeINTEGER:
3366 return
3367 ffecom_1 (BIT_NOT_EXPR, tree_type,
3368 ffecom_2 (BIT_XOR_EXPR, tree_type,
3369 ffecom_expr (ffebld_left (expr)),
3370 ffecom_expr (ffebld_right (expr))));
3371
3372 default:
3373 assert ("EQV bad basictype" == NULL);
3374 /* Fall through. */
3375 case FFEINFO_basictypeANY:
3376 return error_mark_node;
3377 }
3378 break;
3379
3380 case FFEBLD_opCONVERT:
3381 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opANY)
3382 return error_mark_node;
3383
5ff904cd
JL
3384 switch (bt)
3385 {
3386 case FFEINFO_basictypeLOGICAL:
3387 case FFEINFO_basictypeINTEGER:
3388 case FFEINFO_basictypeREAL:
3389 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3390
3391 case FFEINFO_basictypeCOMPLEX:
3392 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3393 {
3394 case FFEINFO_basictypeINTEGER:
3395 case FFEINFO_basictypeLOGICAL:
3396 case FFEINFO_basictypeREAL:
3397 item = ffecom_expr (ffebld_left (expr));
3398 if (item == error_mark_node)
3399 return error_mark_node;
3400 /* convert() takes care of converting to the subtype first,
3401 at least in gcc-2.7.2. */
3402 item = convert (tree_type, item);
3403 return item;
3404
3405 case FFEINFO_basictypeCOMPLEX:
3406 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3407
3408 default:
3409 assert ("CONVERT COMPLEX bad basictype" == NULL);
3410 /* Fall through. */
3411 case FFEINFO_basictypeANY:
3412 return error_mark_node;
3413 }
3414 break;
3415
3416 default:
3417 assert ("CONVERT bad basictype" == NULL);
3418 /* Fall through. */
3419 case FFEINFO_basictypeANY:
3420 return error_mark_node;
3421 }
3422 break;
3423
3424 case FFEBLD_opLT:
3425 code = LT_EXPR;
3426 goto relational; /* :::::::::::::::::::: */
3427
3428 case FFEBLD_opLE:
3429 code = LE_EXPR;
3430 goto relational; /* :::::::::::::::::::: */
3431
3432 case FFEBLD_opEQ:
3433 code = EQ_EXPR;
3434 goto relational; /* :::::::::::::::::::: */
3435
3436 case FFEBLD_opNE:
3437 code = NE_EXPR;
3438 goto relational; /* :::::::::::::::::::: */
3439
3440 case FFEBLD_opGT:
3441 code = GT_EXPR;
3442 goto relational; /* :::::::::::::::::::: */
3443
3444 case FFEBLD_opGE:
3445 code = GE_EXPR;
3446
3447 relational: /* :::::::::::::::::::: */
5ff904cd
JL
3448 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3449 {
3450 case FFEINFO_basictypeLOGICAL:
3451 case FFEINFO_basictypeINTEGER:
3452 case FFEINFO_basictypeREAL:
3453 item = ffecom_2 (code, integer_type_node,
3454 ffecom_expr (ffebld_left (expr)),
3455 ffecom_expr (ffebld_right (expr)));
3456 return convert (tree_type, item);
3457
3458 case FFEINFO_basictypeCOMPLEX:
3459 assert (code == EQ_EXPR || code == NE_EXPR);
3460 {
3461 tree real_type;
3462 tree arg1 = ffecom_expr (ffebld_left (expr));
3463 tree arg2 = ffecom_expr (ffebld_right (expr));
3464
3465 if (arg1 == error_mark_node || arg2 == error_mark_node)
3466 return error_mark_node;
3467
3468 arg1 = ffecom_save_tree (arg1);
3469 arg2 = ffecom_save_tree (arg2);
3470
3471 if (TREE_CODE (TREE_TYPE (arg1)) == COMPLEX_TYPE)
3472 {
3473 real_type = TREE_TYPE (TREE_TYPE (arg1));
3474 assert (real_type == TREE_TYPE (TREE_TYPE (arg2)));
3475 }
3476 else
3477 {
3478 real_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg1)));
3479 assert (real_type == TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg2))));
3480 }
3481
3482 item
3483 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3484 ffecom_2 (EQ_EXPR, integer_type_node,
3485 ffecom_1 (REALPART_EXPR, real_type, arg1),
3486 ffecom_1 (REALPART_EXPR, real_type, arg2)),
3487 ffecom_2 (EQ_EXPR, integer_type_node,
3488 ffecom_1 (IMAGPART_EXPR, real_type, arg1),
3489 ffecom_1 (IMAGPART_EXPR, real_type,
3490 arg2)));
3491 if (code == EQ_EXPR)
3492 item = ffecom_truth_value (item);
3493 else
3494 item = ffecom_truth_value_invert (item);
3495 return convert (tree_type, item);
3496 }
3497
3498 case FFEINFO_basictypeCHARACTER:
3499 ffecom_push_calltemps (); /* Even though we might not call. */
3500
3501 {
3502 ffebld left = ffebld_left (expr);
3503 ffebld right = ffebld_right (expr);
3504 tree left_tree;
3505 tree right_tree;
3506 tree left_length;
3507 tree right_length;
3508
3509 /* f2c run-time functions do the implicit blank-padding for us,
3510 so we don't usually have to implement blank-padding ourselves.
3511 (The exception is when we pass an argument to a separately
3512 compiled statement function -- if we know the arg is not the
3513 same length as the dummy, we must truncate or extend it. If
3514 we "inline" statement functions, that necessity goes away as
3515 well.)
3516
3517 Strip off the CONVERT operators that blank-pad. (Truncation by
3518 CONVERT shouldn't happen here, but it can happen in
3519 assignments.) */
3520
3521 while (ffebld_op (left) == FFEBLD_opCONVERT)
3522 left = ffebld_left (left);
3523 while (ffebld_op (right) == FFEBLD_opCONVERT)
3524 right = ffebld_left (right);
3525
3526 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
3527 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
3528
3529 if (left_tree == error_mark_node || left_length == error_mark_node
3530 || right_tree == error_mark_node
3531 || right_length == error_mark_node)
3532 {
3533 ffecom_pop_calltemps ();
3534 return error_mark_node;
3535 }
3536
3537 if ((ffebld_size_known (left) == 1)
3538 && (ffebld_size_known (right) == 1))
3539 {
3540 left_tree
3541 = ffecom_1 (INDIRECT_REF,
3542 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3543 left_tree);
3544 right_tree
3545 = ffecom_1 (INDIRECT_REF,
3546 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3547 right_tree);
3548
3549 item
3550 = ffecom_2 (code, integer_type_node,
3551 ffecom_2 (ARRAY_REF,
3552 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3553 left_tree,
3554 integer_one_node),
3555 ffecom_2 (ARRAY_REF,
3556 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3557 right_tree,
3558 integer_one_node));
3559 }
3560 else
3561 {
3562 item = build_tree_list (NULL_TREE, left_tree);
3563 TREE_CHAIN (item) = build_tree_list (NULL_TREE, right_tree);
3564 TREE_CHAIN (TREE_CHAIN (item)) = build_tree_list (NULL_TREE,
3565 left_length);
3566 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
3567 = build_tree_list (NULL_TREE, right_length);
3568 item = ffecom_call_gfrt (FFECOM_gfrtCMP, item);
3569 item = ffecom_2 (code, integer_type_node,
3570 item,
3571 convert (TREE_TYPE (item),
3572 integer_zero_node));
3573 }
3574 item = convert (tree_type, item);
3575 }
3576
3577 ffecom_pop_calltemps ();
3578 return item;
3579
3580 default:
3581 assert ("relational bad basictype" == NULL);
3582 /* Fall through. */
3583 case FFEINFO_basictypeANY:
3584 return error_mark_node;
3585 }
3586 break;
3587
3588 case FFEBLD_opPERCENT_LOC:
5ff904cd
JL
3589 item = ffecom_arg_ptr_to_expr (ffebld_left (expr), &list);
3590 return convert (tree_type, item);
3591
3592 case FFEBLD_opITEM:
3593 case FFEBLD_opSTAR:
3594 case FFEBLD_opBOUNDS:
3595 case FFEBLD_opREPEAT:
3596 case FFEBLD_opLABTER:
3597 case FFEBLD_opLABTOK:
3598 case FFEBLD_opIMPDO:
3599 case FFEBLD_opCONCATENATE:
3600 case FFEBLD_opSUBSTR:
3601 default:
3602 assert ("bad op" == NULL);
3603 /* Fall through. */
3604 case FFEBLD_opANY:
3605 return error_mark_node;
3606 }
3607
3608#if 1
3609 assert ("didn't think anything got here anymore!!" == NULL);
3610#else
3611 switch (ffebld_arity (expr))
3612 {
3613 case 2:
3614 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3615 TREE_OPERAND (item, 1) = ffecom_expr (ffebld_right (expr));
3616 if (TREE_OPERAND (item, 0) == error_mark_node
3617 || TREE_OPERAND (item, 1) == error_mark_node)
3618 return error_mark_node;
3619 break;
3620
3621 case 1:
3622 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3623 if (TREE_OPERAND (item, 0) == error_mark_node)
3624 return error_mark_node;
3625 break;
3626
3627 default:
3628 break;
3629 }
3630
3631 return fold (item);
3632#endif
3633}
3634
3635#endif
3636/* Returns the tree that does the intrinsic invocation.
3637
3638 Note: this function applies only to intrinsics returning
3639 CHARACTER*1 or non-CHARACTER results, and to intrinsic
3640 subroutines. */
3641
3642#if FFECOM_targetCURRENT == FFECOM_targetGCC
3643static tree
3644ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
3645 ffebld dest, bool *dest_used)
3646{
3647 tree expr_tree;
3648 tree saved_expr1; /* For those who need it. */
3649 tree saved_expr2; /* For those who need it. */
3650 ffeinfoBasictype bt;
3651 ffeinfoKindtype kt;
3652 tree tree_type;
3653 tree arg1_type;
3654 tree real_type; /* REAL type corresponding to COMPLEX. */
3655 tree tempvar;
3656 ffebld list = ffebld_right (expr); /* List of (some) args. */
3657 ffebld arg1; /* For handy reference. */
3658 ffebld arg2;
3659 ffebld arg3;
3660 ffeintrinImp codegen_imp;
3661 ffecomGfrt gfrt;
3662
3663 assert (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER);
3664
3665 if (dest_used != NULL)
3666 *dest_used = FALSE;
3667
3668 bt = ffeinfo_basictype (ffebld_info (expr));
3669 kt = ffeinfo_kindtype (ffebld_info (expr));
3670 tree_type = ffecom_tree_type[bt][kt];
3671
3672 if (list != NULL)
3673 {
3674 arg1 = ffebld_head (list);
3675 if (arg1 != NULL && ffebld_op (arg1) == FFEBLD_opANY)
3676 return error_mark_node;
3677 if ((list = ffebld_trail (list)) != NULL)
3678 {
3679 arg2 = ffebld_head (list);
3680 if (arg2 != NULL && ffebld_op (arg2) == FFEBLD_opANY)
3681 return error_mark_node;
3682 if ((list = ffebld_trail (list)) != NULL)
3683 {
3684 arg3 = ffebld_head (list);
3685 if (arg3 != NULL && ffebld_op (arg3) == FFEBLD_opANY)
3686 return error_mark_node;
3687 }
3688 else
3689 arg3 = NULL;
3690 }
3691 else
3692 arg2 = arg3 = NULL;
3693 }
3694 else
3695 arg1 = arg2 = arg3 = NULL;
3696
3697 /* <list> ends up at the opITEM of the 3rd arg, or NULL if there are < 3
3698 args. This is used by the MAX/MIN expansions. */
3699
3700 if (arg1 != NULL)
3701 arg1_type = ffecom_tree_type
3702 [ffeinfo_basictype (ffebld_info (arg1))]
3703 [ffeinfo_kindtype (ffebld_info (arg1))];
3704 else
3705 arg1_type = NULL_TREE; /* Really not needed, but might catch bugs
3706 here. */
3707
3708 /* There are several ways for each of the cases in the following switch
3709 statements to exit (from simplest to use to most complicated):
3710
3711 break; (when expr_tree == NULL)
3712
3713 A standard call is made to the specific intrinsic just as if it had been
3714 passed in as a dummy procedure and called as any old procedure. This
3715 method can produce slower code but in some cases it's the easiest way for
3716 now. However, if a (presumably faster) direct call is available,
3717 that is used, so this is the easiest way in many more cases now.
3718
3719 gfrt = FFECOM_gfrtWHATEVER;
3720 break;
3721
3722 gfrt contains the gfrt index of a library function to call, passing the
3723 argument(s) by value rather than by reference. Used when a more
3724 careful choice of library function is needed than that provided
3725 by the vanilla `break;'.
3726
3727 return expr_tree;
3728
3729 The expr_tree has been completely set up and is ready to be returned
3730 as is. No further actions are taken. Use this when the tree is not
3731 in the simple form for one of the arity_n labels. */
3732
3733 /* For info on how the switch statement cases were written, see the files
3734 enclosed in comments below the switch statement. */
3735
3736 codegen_imp = ffebld_symter_implementation (ffebld_left (expr));
3737 gfrt = ffeintrin_gfrt_direct (codegen_imp);
3738 if (gfrt == FFECOM_gfrt)
3739 gfrt = ffeintrin_gfrt_indirect (codegen_imp);
3740
3741 switch (codegen_imp)
3742 {
3743 case FFEINTRIN_impABS:
3744 case FFEINTRIN_impCABS:
3745 case FFEINTRIN_impCDABS:
3746 case FFEINTRIN_impDABS:
3747 case FFEINTRIN_impIABS:
3748 if (ffeinfo_basictype (ffebld_info (arg1))
3749 == FFEINFO_basictypeCOMPLEX)
3750 {
3751 if (kt == FFEINFO_kindtypeREAL1)
3752 gfrt = FFECOM_gfrtCABS;
3753 else if (kt == FFEINFO_kindtypeREAL2)
3754 gfrt = FFECOM_gfrtCDABS;
3755 break;
3756 }
3757 return ffecom_1 (ABS_EXPR, tree_type,
3758 convert (tree_type, ffecom_expr (arg1)));
3759
3760 case FFEINTRIN_impACOS:
3761 case FFEINTRIN_impDACOS:
3762 break;
3763
3764 case FFEINTRIN_impAIMAG:
3765 case FFEINTRIN_impDIMAG:
3766 case FFEINTRIN_impIMAGPART:
3767 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
3768 arg1_type = TREE_TYPE (arg1_type);
3769 else
3770 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
3771
3772 return
3773 convert (tree_type,
3774 ffecom_1 (IMAGPART_EXPR, arg1_type,
3775 ffecom_expr (arg1)));
3776
3777 case FFEINTRIN_impAINT:
3778 case FFEINTRIN_impDINT:
3779#if 0 /* ~~ someday implement FIX_TRUNC_EXPR
3780 yielding same type as arg */
3781 return ffecom_1 (FIX_TRUNC_EXPR, tree_type, ffecom_expr (arg1));
3782#else /* in the meantime, must use floor to avoid range problems with ints */
3783 /* r__1 = r1 >= 0 ? floor(r1) : -floor(-r1); */
3784 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
3785 return
3786 convert (tree_type,
3787 ffecom_3 (COND_EXPR, double_type_node,
3788 ffecom_truth_value
3789 (ffecom_2 (GE_EXPR, integer_type_node,
3790 saved_expr1,
3791 convert (arg1_type,
3792 ffecom_float_zero_))),
3793 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
3794 build_tree_list (NULL_TREE,
3795 convert (double_type_node,
3796 saved_expr1))),
3797 ffecom_1 (NEGATE_EXPR, double_type_node,
3798 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
3799 build_tree_list (NULL_TREE,
3800 convert (double_type_node,
3801 ffecom_1 (NEGATE_EXPR,
3802 arg1_type,
3803 saved_expr1))))
3804 ))
3805 );
3806#endif
3807
3808 case FFEINTRIN_impANINT:
3809 case FFEINTRIN_impDNINT:
3810#if 0 /* This way of doing it won't handle real
3811 numbers of large magnitudes. */
3812 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
3813 expr_tree = convert (tree_type,
3814 convert (integer_type_node,
3815 ffecom_3 (COND_EXPR, tree_type,
3816 ffecom_truth_value
3817 (ffecom_2 (GE_EXPR,
3818 integer_type_node,
3819 saved_expr1,
3820 ffecom_float_zero_)),
3821 ffecom_2 (PLUS_EXPR,
3822 tree_type,
3823 saved_expr1,
3824 ffecom_float_half_),
3825 ffecom_2 (MINUS_EXPR,
3826 tree_type,
3827 saved_expr1,
3828 ffecom_float_half_))));
3829 return expr_tree;
3830#else /* So we instead call floor. */
3831 /* r__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1) */
3832 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
3833 return
3834 convert (tree_type,
3835 ffecom_3 (COND_EXPR, double_type_node,
3836 ffecom_truth_value
3837 (ffecom_2 (GE_EXPR, integer_type_node,
3838 saved_expr1,
3839 convert (arg1_type,
3840 ffecom_float_zero_))),
3841 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
3842 build_tree_list (NULL_TREE,
3843 convert (double_type_node,
3844 ffecom_2 (PLUS_EXPR,
3845 arg1_type,
3846 saved_expr1,
3847 convert (arg1_type,
3848 ffecom_float_half_))))),
3849 ffecom_1 (NEGATE_EXPR, double_type_node,
3850 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
3851 build_tree_list (NULL_TREE,
3852 convert (double_type_node,
3853 ffecom_2 (MINUS_EXPR,
3854 arg1_type,
3855 convert (arg1_type,
3856 ffecom_float_half_),
3857 saved_expr1)))))
3858 )
3859 );
3860#endif
3861
3862 case FFEINTRIN_impASIN:
3863 case FFEINTRIN_impDASIN:
3864 case FFEINTRIN_impATAN:
3865 case FFEINTRIN_impDATAN:
3866 case FFEINTRIN_impATAN2:
3867 case FFEINTRIN_impDATAN2:
3868 break;
3869
3870 case FFEINTRIN_impCHAR:
3871 case FFEINTRIN_impACHAR:
3872 assert (ffecom_pending_calls_ != 0);
3873 tempvar = ffecom_push_tempvar (char_type_node,
3874 1, -1, TRUE);
3875 {
3876 tree tmv = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (tempvar)));
3877
3878 expr_tree = ffecom_modify (tmv,
3879 ffecom_2 (ARRAY_REF, tmv, tempvar,
3880 integer_one_node),
3881 convert (tmv, ffecom_expr (arg1)));
3882 }
3883 expr_tree = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar),
3884 expr_tree,
3885 tempvar);
3886 expr_tree = ffecom_1 (ADDR_EXPR,
3887 build_pointer_type (TREE_TYPE (expr_tree)),
3888 expr_tree);
3889 return expr_tree;
3890
3891 case FFEINTRIN_impCMPLX:
3892 case FFEINTRIN_impDCMPLX:
3893 if (arg2 == NULL)
3894 return
3895 convert (tree_type, ffecom_expr (arg1));
3896
3897 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
3898 return
3899 ffecom_2 (COMPLEX_EXPR, tree_type,
3900 convert (real_type, ffecom_expr (arg1)),
3901 convert (real_type,
3902 ffecom_expr (arg2)));
3903
3904 case FFEINTRIN_impCOMPLEX:
3905 return
3906 ffecom_2 (COMPLEX_EXPR, tree_type,
3907 ffecom_expr (arg1),
3908 ffecom_expr (arg2));
3909
3910 case FFEINTRIN_impCONJG:
3911 case FFEINTRIN_impDCONJG:
3912 {
3913 tree arg1_tree;
3914
3915 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
3916 arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
3917 return
3918 ffecom_2 (COMPLEX_EXPR, tree_type,
3919 ffecom_1 (REALPART_EXPR, real_type, arg1_tree),
3920 ffecom_1 (NEGATE_EXPR, real_type,
3921 ffecom_1 (IMAGPART_EXPR, real_type, arg1_tree)));
3922 }
3923
3924 case FFEINTRIN_impCOS:
3925 case FFEINTRIN_impCCOS:
3926 case FFEINTRIN_impCDCOS:
3927 case FFEINTRIN_impDCOS:
3928 if (bt == FFEINFO_basictypeCOMPLEX)
3929 {
3930 if (kt == FFEINFO_kindtypeREAL1)
3931 gfrt = FFECOM_gfrtCCOS; /* Overlapping result okay. */
3932 else if (kt == FFEINFO_kindtypeREAL2)
3933 gfrt = FFECOM_gfrtCDCOS; /* Overlapping result okay. */
3934 }
3935 break;
3936
3937 case FFEINTRIN_impCOSH:
3938 case FFEINTRIN_impDCOSH:
3939 break;
3940
3941 case FFEINTRIN_impDBLE:
3942 case FFEINTRIN_impDFLOAT:
3943 case FFEINTRIN_impDREAL:
3944 case FFEINTRIN_impFLOAT:
3945 case FFEINTRIN_impIDINT:
3946 case FFEINTRIN_impIFIX:
3947 case FFEINTRIN_impINT2:
3948 case FFEINTRIN_impINT8:
3949 case FFEINTRIN_impINT:
3950 case FFEINTRIN_impLONG:
3951 case FFEINTRIN_impREAL:
3952 case FFEINTRIN_impSHORT:
3953 case FFEINTRIN_impSNGL:
3954 return convert (tree_type, ffecom_expr (arg1));
3955
3956 case FFEINTRIN_impDIM:
3957 case FFEINTRIN_impDDIM:
3958 case FFEINTRIN_impIDIM:
3959 saved_expr1 = ffecom_save_tree (convert (tree_type,
3960 ffecom_expr (arg1)));
3961 saved_expr2 = ffecom_save_tree (convert (tree_type,
3962 ffecom_expr (arg2)));
3963 return
3964 ffecom_3 (COND_EXPR, tree_type,
3965 ffecom_truth_value
3966 (ffecom_2 (GT_EXPR, integer_type_node,
3967 saved_expr1,
3968 saved_expr2)),
3969 ffecom_2 (MINUS_EXPR, tree_type,
3970 saved_expr1,
3971 saved_expr2),
3972 convert (tree_type, ffecom_float_zero_));
3973
3974 case FFEINTRIN_impDPROD:
3975 return
3976 ffecom_2 (MULT_EXPR, tree_type,
3977 convert (tree_type, ffecom_expr (arg1)),
3978 convert (tree_type, ffecom_expr (arg2)));
3979
3980 case FFEINTRIN_impEXP:
3981 case FFEINTRIN_impCDEXP:
3982 case FFEINTRIN_impCEXP:
3983 case FFEINTRIN_impDEXP:
3984 if (bt == FFEINFO_basictypeCOMPLEX)
3985 {
3986 if (kt == FFEINFO_kindtypeREAL1)
3987 gfrt = FFECOM_gfrtCEXP; /* Overlapping result okay. */
3988 else if (kt == FFEINFO_kindtypeREAL2)
3989 gfrt = FFECOM_gfrtCDEXP; /* Overlapping result okay. */
3990 }
3991 break;
3992
3993 case FFEINTRIN_impICHAR:
3994 case FFEINTRIN_impIACHAR:
3995#if 0 /* The simple approach. */
3996 ffecom_char_args_ (&expr_tree, &saved_expr1 /* Ignored */ , arg1);
3997 expr_tree
3998 = ffecom_1 (INDIRECT_REF,
3999 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4000 expr_tree);
4001 expr_tree
4002 = ffecom_2 (ARRAY_REF,
4003 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4004 expr_tree,
4005 integer_one_node);
4006 return convert (tree_type, expr_tree);
4007#else /* The more interesting (and more optimal) approach. */
4008 expr_tree = ffecom_intrinsic_ichar_ (tree_type, arg1, &saved_expr1);
4009 expr_tree = ffecom_3 (COND_EXPR, tree_type,
4010 saved_expr1,
4011 expr_tree,
4012 convert (tree_type, integer_zero_node));
4013 return expr_tree;
4014#endif
4015
4016 case FFEINTRIN_impINDEX:
4017 break;
4018
4019 case FFEINTRIN_impLEN:
4020#if 0
4021 break; /* The simple approach. */
4022#else
4023 return ffecom_intrinsic_len_ (arg1); /* The more optimal approach. */
4024#endif
4025
4026 case FFEINTRIN_impLGE:
4027 case FFEINTRIN_impLGT:
4028 case FFEINTRIN_impLLE:
4029 case FFEINTRIN_impLLT:
4030 break;
4031
4032 case FFEINTRIN_impLOG:
4033 case FFEINTRIN_impALOG:
4034 case FFEINTRIN_impCDLOG:
4035 case FFEINTRIN_impCLOG:
4036 case FFEINTRIN_impDLOG:
4037 if (bt == FFEINFO_basictypeCOMPLEX)
4038 {
4039 if (kt == FFEINFO_kindtypeREAL1)
4040 gfrt = FFECOM_gfrtCLOG; /* Overlapping result okay. */
4041 else if (kt == FFEINFO_kindtypeREAL2)
4042 gfrt = FFECOM_gfrtCDLOG; /* Overlapping result okay. */
4043 }
4044 break;
4045
4046 case FFEINTRIN_impLOG10:
4047 case FFEINTRIN_impALOG10:
4048 case FFEINTRIN_impDLOG10:
4049 if (gfrt != FFECOM_gfrt)
4050 break; /* Already picked one, stick with it. */
4051
4052 if (kt == FFEINFO_kindtypeREAL1)
4053 gfrt = FFECOM_gfrtALOG10;
4054 else if (kt == FFEINFO_kindtypeREAL2)
4055 gfrt = FFECOM_gfrtDLOG10;
4056 break;
4057
4058 case FFEINTRIN_impMAX:
4059 case FFEINTRIN_impAMAX0:
4060 case FFEINTRIN_impAMAX1:
4061 case FFEINTRIN_impDMAX1:
4062 case FFEINTRIN_impMAX0:
4063 case FFEINTRIN_impMAX1:
4064 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4065 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4066 else
4067 arg1_type = tree_type;
4068 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4069 convert (arg1_type, ffecom_expr (arg1)),
4070 convert (arg1_type, ffecom_expr (arg2)));
4071 for (; list != NULL; list = ffebld_trail (list))
4072 {
4073 if ((ffebld_head (list) == NULL)
4074 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4075 continue;
4076 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4077 expr_tree,
4078 convert (arg1_type,
4079 ffecom_expr (ffebld_head (list))));
4080 }
4081 return convert (tree_type, expr_tree);
4082
4083 case FFEINTRIN_impMIN:
4084 case FFEINTRIN_impAMIN0:
4085 case FFEINTRIN_impAMIN1:
4086 case FFEINTRIN_impDMIN1:
4087 case FFEINTRIN_impMIN0:
4088 case FFEINTRIN_impMIN1:
4089 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4090 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4091 else
4092 arg1_type = tree_type;
4093 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4094 convert (arg1_type, ffecom_expr (arg1)),
4095 convert (arg1_type, ffecom_expr (arg2)));
4096 for (; list != NULL; list = ffebld_trail (list))
4097 {
4098 if ((ffebld_head (list) == NULL)
4099 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4100 continue;
4101 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4102 expr_tree,
4103 convert (arg1_type,
4104 ffecom_expr (ffebld_head (list))));
4105 }
4106 return convert (tree_type, expr_tree);
4107
4108 case FFEINTRIN_impMOD:
4109 case FFEINTRIN_impAMOD:
4110 case FFEINTRIN_impDMOD:
4111 if (bt != FFEINFO_basictypeREAL)
4112 return ffecom_2 (TRUNC_MOD_EXPR, tree_type,
4113 convert (tree_type, ffecom_expr (arg1)),
4114 convert (tree_type, ffecom_expr (arg2)));
4115
4116 if (kt == FFEINFO_kindtypeREAL1)
4117 gfrt = FFECOM_gfrtAMOD;
4118 else if (kt == FFEINFO_kindtypeREAL2)
4119 gfrt = FFECOM_gfrtDMOD;
4120 break;
4121
4122 case FFEINTRIN_impNINT:
4123 case FFEINTRIN_impIDNINT:
4124#if 0 /* ~~ ideally FIX_ROUND_EXPR would be
4125 implemented, but it ain't yet */
4126 return ffecom_1 (FIX_ROUND_EXPR, tree_type, ffecom_expr (arg1));
4127#else
4128 /* i__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1); */
4129 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4130 return
4131 convert (ffecom_integer_type_node,
4132 ffecom_3 (COND_EXPR, arg1_type,
4133 ffecom_truth_value
4134 (ffecom_2 (GE_EXPR, integer_type_node,
4135 saved_expr1,
4136 convert (arg1_type,
4137 ffecom_float_zero_))),
4138 ffecom_2 (PLUS_EXPR, arg1_type,
4139 saved_expr1,
4140 convert (arg1_type,
4141 ffecom_float_half_)),
4142 ffecom_2 (MINUS_EXPR, arg1_type,
4143 saved_expr1,
4144 convert (arg1_type,
4145 ffecom_float_half_))));
4146#endif
4147
4148 case FFEINTRIN_impSIGN:
4149 case FFEINTRIN_impDSIGN:
4150 case FFEINTRIN_impISIGN:
4151 {
4152 tree arg2_tree = ffecom_expr (arg2);
4153
4154 saved_expr1
4155 = ffecom_save_tree
4156 (ffecom_1 (ABS_EXPR, tree_type,
4157 convert (tree_type,
4158 ffecom_expr (arg1))));
4159 expr_tree
4160 = ffecom_3 (COND_EXPR, tree_type,
4161 ffecom_truth_value
4162 (ffecom_2 (GE_EXPR, integer_type_node,
4163 arg2_tree,
4164 convert (TREE_TYPE (arg2_tree),
4165 integer_zero_node))),
4166 saved_expr1,
4167 ffecom_1 (NEGATE_EXPR, tree_type, saved_expr1));
4168 /* Make sure SAVE_EXPRs get referenced early enough. */
4169 expr_tree
4170 = ffecom_2 (COMPOUND_EXPR, tree_type,
4171 convert (void_type_node, saved_expr1),
4172 expr_tree);
4173 }
4174 return expr_tree;
4175
4176 case FFEINTRIN_impSIN:
4177 case FFEINTRIN_impCDSIN:
4178 case FFEINTRIN_impCSIN:
4179 case FFEINTRIN_impDSIN:
4180 if (bt == FFEINFO_basictypeCOMPLEX)
4181 {
4182 if (kt == FFEINFO_kindtypeREAL1)
4183 gfrt = FFECOM_gfrtCSIN; /* Overlapping result okay. */
4184 else if (kt == FFEINFO_kindtypeREAL2)
4185 gfrt = FFECOM_gfrtCDSIN; /* Overlapping result okay. */
4186 }
4187 break;
4188
4189 case FFEINTRIN_impSINH:
4190 case FFEINTRIN_impDSINH:
4191 break;
4192
4193 case FFEINTRIN_impSQRT:
4194 case FFEINTRIN_impCDSQRT:
4195 case FFEINTRIN_impCSQRT:
4196 case FFEINTRIN_impDSQRT:
4197 if (bt == FFEINFO_basictypeCOMPLEX)
4198 {
4199 if (kt == FFEINFO_kindtypeREAL1)
4200 gfrt = FFECOM_gfrtCSQRT; /* Overlapping result okay. */
4201 else if (kt == FFEINFO_kindtypeREAL2)
4202 gfrt = FFECOM_gfrtCDSQRT; /* Overlapping result okay. */
4203 }
4204 break;
4205
4206 case FFEINTRIN_impTAN:
4207 case FFEINTRIN_impDTAN:
4208 case FFEINTRIN_impTANH:
4209 case FFEINTRIN_impDTANH:
4210 break;
4211
4212 case FFEINTRIN_impREALPART:
4213 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4214 arg1_type = TREE_TYPE (arg1_type);
4215 else
4216 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4217
4218 return
4219 convert (tree_type,
4220 ffecom_1 (REALPART_EXPR, arg1_type,
4221 ffecom_expr (arg1)));
4222
4223 case FFEINTRIN_impIAND:
4224 case FFEINTRIN_impAND:
4225 return ffecom_2 (BIT_AND_EXPR, tree_type,
4226 convert (tree_type,
4227 ffecom_expr (arg1)),
4228 convert (tree_type,
4229 ffecom_expr (arg2)));
4230
4231 case FFEINTRIN_impIOR:
4232 case FFEINTRIN_impOR:
4233 return ffecom_2 (BIT_IOR_EXPR, tree_type,
4234 convert (tree_type,
4235 ffecom_expr (arg1)),
4236 convert (tree_type,
4237 ffecom_expr (arg2)));
4238
4239 case FFEINTRIN_impIEOR:
4240 case FFEINTRIN_impXOR:
4241 return ffecom_2 (BIT_XOR_EXPR, tree_type,
4242 convert (tree_type,
4243 ffecom_expr (arg1)),
4244 convert (tree_type,
4245 ffecom_expr (arg2)));
4246
4247 case FFEINTRIN_impLSHIFT:
4248 return ffecom_2 (LSHIFT_EXPR, tree_type,
4249 ffecom_expr (arg1),
4250 convert (integer_type_node,
4251 ffecom_expr (arg2)));
4252
4253 case FFEINTRIN_impRSHIFT:
4254 return ffecom_2 (RSHIFT_EXPR, tree_type,
4255 ffecom_expr (arg1),
4256 convert (integer_type_node,
4257 ffecom_expr (arg2)));
4258
4259 case FFEINTRIN_impNOT:
4260 return ffecom_1 (BIT_NOT_EXPR, tree_type, ffecom_expr (arg1));
4261
4262 case FFEINTRIN_impBIT_SIZE:
4263 return convert (tree_type, TYPE_SIZE (arg1_type));
4264
4265 case FFEINTRIN_impBTEST:
4266 {
4267 ffetargetLogical1 true;
4268 ffetargetLogical1 false;
4269 tree true_tree;
4270 tree false_tree;
4271
4272 ffetarget_logical1 (&true, TRUE);
4273 ffetarget_logical1 (&false, FALSE);
4274 if (true == 1)
4275 true_tree = convert (tree_type, integer_one_node);
4276 else
4277 true_tree = convert (tree_type, build_int_2 (true, 0));
4278 if (false == 0)
4279 false_tree = convert (tree_type, integer_zero_node);
4280 else
4281 false_tree = convert (tree_type, build_int_2 (false, 0));
4282
4283 return
4284 ffecom_3 (COND_EXPR, tree_type,
4285 ffecom_truth_value
4286 (ffecom_2 (EQ_EXPR, integer_type_node,
4287 ffecom_2 (BIT_AND_EXPR, arg1_type,
4288 ffecom_expr (arg1),
4289 ffecom_2 (LSHIFT_EXPR, arg1_type,
4290 convert (arg1_type,
4291 integer_one_node),
4292 convert (integer_type_node,
4293 ffecom_expr (arg2)))),
4294 convert (arg1_type,
4295 integer_zero_node))),
4296 false_tree,
4297 true_tree);
4298 }
4299
4300 case FFEINTRIN_impIBCLR:
4301 return
4302 ffecom_2 (BIT_AND_EXPR, tree_type,
4303 ffecom_expr (arg1),
4304 ffecom_1 (BIT_NOT_EXPR, tree_type,
4305 ffecom_2 (LSHIFT_EXPR, tree_type,
4306 convert (tree_type,
4307 integer_one_node),
4308 convert (integer_type_node,
4309 ffecom_expr (arg2)))));
4310
4311 case FFEINTRIN_impIBITS:
4312 {
4313 tree arg3_tree = ffecom_save_tree (convert (integer_type_node,
4314 ffecom_expr (arg3)));
4315 tree uns_type
4316 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4317
4318 expr_tree
4319 = ffecom_2 (BIT_AND_EXPR, tree_type,
4320 ffecom_2 (RSHIFT_EXPR, tree_type,
4321 ffecom_expr (arg1),
4322 convert (integer_type_node,
4323 ffecom_expr (arg2))),
4324 convert (tree_type,
4325 ffecom_2 (RSHIFT_EXPR, uns_type,
4326 ffecom_1 (BIT_NOT_EXPR,
4327 uns_type,
4328 convert (uns_type,
4329 integer_zero_node)),
4330 ffecom_2 (MINUS_EXPR,
4331 integer_type_node,
4332 TYPE_SIZE (uns_type),
4333 arg3_tree))));
4334#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4335 expr_tree
4336 = ffecom_3 (COND_EXPR, tree_type,
4337 ffecom_truth_value
4338 (ffecom_2 (NE_EXPR, integer_type_node,
4339 arg3_tree,
4340 integer_zero_node)),
4341 expr_tree,
4342 convert (tree_type, integer_zero_node));
4343#endif
4344 }
4345 return expr_tree;
4346
4347 case FFEINTRIN_impIBSET:
4348 return
4349 ffecom_2 (BIT_IOR_EXPR, tree_type,
4350 ffecom_expr (arg1),
4351 ffecom_2 (LSHIFT_EXPR, tree_type,
4352 convert (tree_type, integer_one_node),
4353 convert (integer_type_node,
4354 ffecom_expr (arg2))));
4355
4356 case FFEINTRIN_impISHFT:
4357 {
4358 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4359 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4360 ffecom_expr (arg2)));
4361 tree uns_type
4362 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4363
4364 expr_tree
4365 = ffecom_3 (COND_EXPR, tree_type,
4366 ffecom_truth_value
4367 (ffecom_2 (GE_EXPR, integer_type_node,
4368 arg2_tree,
4369 integer_zero_node)),
4370 ffecom_2 (LSHIFT_EXPR, tree_type,
4371 arg1_tree,
4372 arg2_tree),
4373 convert (tree_type,
4374 ffecom_2 (RSHIFT_EXPR, uns_type,
4375 convert (uns_type, arg1_tree),
4376 ffecom_1 (NEGATE_EXPR,
4377 integer_type_node,
4378 arg2_tree))));
4379#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4380 expr_tree
4381 = ffecom_3 (COND_EXPR, tree_type,
4382 ffecom_truth_value
4383 (ffecom_2 (NE_EXPR, integer_type_node,
4384 arg2_tree,
4385 TYPE_SIZE (uns_type))),
4386 expr_tree,
4387 convert (tree_type, integer_zero_node));
4388#endif
4389 /* Make sure SAVE_EXPRs get referenced early enough. */
4390 expr_tree
4391 = ffecom_2 (COMPOUND_EXPR, tree_type,
4392 convert (void_type_node, arg1_tree),
4393 ffecom_2 (COMPOUND_EXPR, tree_type,
4394 convert (void_type_node, arg2_tree),
4395 expr_tree));
4396 }
4397 return expr_tree;
4398
4399 case FFEINTRIN_impISHFTC:
4400 {
4401 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4402 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4403 ffecom_expr (arg2)));
4404 tree arg3_tree = (arg3 == NULL) ? TYPE_SIZE (tree_type)
4405 : ffecom_save_tree (convert (integer_type_node, ffecom_expr (arg3)));
4406 tree shift_neg;
4407 tree shift_pos;
4408 tree mask_arg1;
4409 tree masked_arg1;
4410 tree uns_type
4411 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4412
4413 mask_arg1
4414 = ffecom_2 (LSHIFT_EXPR, tree_type,
4415 ffecom_1 (BIT_NOT_EXPR, tree_type,
4416 convert (tree_type, integer_zero_node)),
4417 arg3_tree);
4418#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4419 mask_arg1
4420 = ffecom_3 (COND_EXPR, tree_type,
4421 ffecom_truth_value
4422 (ffecom_2 (NE_EXPR, integer_type_node,
4423 arg3_tree,
4424 TYPE_SIZE (uns_type))),
4425 mask_arg1,
4426 convert (tree_type, integer_zero_node));
4427#endif
4428 mask_arg1 = ffecom_save_tree (mask_arg1);
4429 masked_arg1
4430 = ffecom_2 (BIT_AND_EXPR, tree_type,
4431 arg1_tree,
4432 ffecom_1 (BIT_NOT_EXPR, tree_type,
4433 mask_arg1));
4434 masked_arg1 = ffecom_save_tree (masked_arg1);
4435 shift_neg
4436 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4437 convert (tree_type,
4438 ffecom_2 (RSHIFT_EXPR, uns_type,
4439 convert (uns_type, masked_arg1),
4440 ffecom_1 (NEGATE_EXPR,
4441 integer_type_node,
4442 arg2_tree))),
4443 ffecom_2 (LSHIFT_EXPR, tree_type,
4444 arg1_tree,
4445 ffecom_2 (PLUS_EXPR, integer_type_node,
4446 arg2_tree,
4447 arg3_tree)));
4448 shift_pos
4449 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4450 ffecom_2 (LSHIFT_EXPR, tree_type,
4451 arg1_tree,
4452 arg2_tree),
4453 convert (tree_type,
4454 ffecom_2 (RSHIFT_EXPR, uns_type,
4455 convert (uns_type, masked_arg1),
4456 ffecom_2 (MINUS_EXPR,
4457 integer_type_node,
4458 arg3_tree,
4459 arg2_tree))));
4460 expr_tree
4461 = ffecom_3 (COND_EXPR, tree_type,
4462 ffecom_truth_value
4463 (ffecom_2 (LT_EXPR, integer_type_node,
4464 arg2_tree,
4465 integer_zero_node)),
4466 shift_neg,
4467 shift_pos);
4468 expr_tree
4469 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4470 ffecom_2 (BIT_AND_EXPR, tree_type,
4471 mask_arg1,
4472 arg1_tree),
4473 ffecom_2 (BIT_AND_EXPR, tree_type,
4474 ffecom_1 (BIT_NOT_EXPR, tree_type,
4475 mask_arg1),
4476 expr_tree));
4477 expr_tree
4478 = ffecom_3 (COND_EXPR, tree_type,
4479 ffecom_truth_value
4480 (ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
4481 ffecom_2 (EQ_EXPR, integer_type_node,
4482 ffecom_1 (ABS_EXPR,
4483 integer_type_node,
4484 arg2_tree),
4485 arg3_tree),
4486 ffecom_2 (EQ_EXPR, integer_type_node,
4487 arg2_tree,
4488 integer_zero_node))),
4489 arg1_tree,
4490 expr_tree);
4491 /* Make sure SAVE_EXPRs get referenced early enough. */
4492 expr_tree
4493 = ffecom_2 (COMPOUND_EXPR, tree_type,
4494 convert (void_type_node, arg1_tree),
4495 ffecom_2 (COMPOUND_EXPR, tree_type,
4496 convert (void_type_node, arg2_tree),
4497 ffecom_2 (COMPOUND_EXPR, tree_type,
4498 convert (void_type_node,
4499 mask_arg1),
4500 ffecom_2 (COMPOUND_EXPR, tree_type,
4501 convert (void_type_node,
4502 masked_arg1),
4503 expr_tree))));
4504 expr_tree
4505 = ffecom_2 (COMPOUND_EXPR, tree_type,
4506 convert (void_type_node,
4507 arg3_tree),
4508 expr_tree);
4509 }
4510 return expr_tree;
4511
4512 case FFEINTRIN_impLOC:
4513 {
4514 tree arg1_tree = ffecom_expr (arg1);
4515
4516 expr_tree
4517 = convert (tree_type,
4518 ffecom_1 (ADDR_EXPR,
4519 build_pointer_type (TREE_TYPE (arg1_tree)),
4520 arg1_tree));
4521 }
4522 return expr_tree;
4523
4524 case FFEINTRIN_impMVBITS:
4525 {
4526 tree arg1_tree;
4527 tree arg2_tree;
4528 tree arg3_tree;
4529 ffebld arg4 = ffebld_head (ffebld_trail (list));
4530 tree arg4_tree;
4531 tree arg4_type;
4532 ffebld arg5 = ffebld_head (ffebld_trail (ffebld_trail (list)));
4533 tree arg5_tree;
4534 tree prep_arg1;
4535 tree prep_arg4;
4536 tree arg5_plus_arg3;
4537
4538 ffecom_push_calltemps ();
4539
4540 arg2_tree = convert (integer_type_node,
4541 ffecom_expr (arg2));
4542 arg3_tree = ffecom_save_tree (convert (integer_type_node,
4543 ffecom_expr (arg3)));
4544 arg4_tree = ffecom_expr_rw (arg4);
4545 arg4_type = TREE_TYPE (arg4_tree);
4546
4547 arg1_tree = ffecom_save_tree (convert (arg4_type,
4548 ffecom_expr (arg1)));
4549
4550 arg5_tree = ffecom_save_tree (convert (integer_type_node,
4551 ffecom_expr (arg5)));
4552
4553 ffecom_pop_calltemps ();
4554
4555 prep_arg1
4556 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4557 ffecom_2 (BIT_AND_EXPR, arg4_type,
4558 ffecom_2 (RSHIFT_EXPR, arg4_type,
4559 arg1_tree,
4560 arg2_tree),
4561 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4562 ffecom_2 (LSHIFT_EXPR, arg4_type,
4563 ffecom_1 (BIT_NOT_EXPR,
4564 arg4_type,
4565 convert
4566 (arg4_type,
4567 integer_zero_node)),
4568 arg3_tree))),
4569 arg5_tree);
4570 arg5_plus_arg3
4571 = ffecom_save_tree (ffecom_2 (PLUS_EXPR, arg4_type,
4572 arg5_tree,
4573 arg3_tree));
4574 prep_arg4
4575 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4576 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4577 convert (arg4_type,
4578 integer_zero_node)),
4579 arg5_plus_arg3);
4580#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4581 prep_arg4
4582 = ffecom_3 (COND_EXPR, arg4_type,
4583 ffecom_truth_value
4584 (ffecom_2 (NE_EXPR, integer_type_node,
4585 arg5_plus_arg3,
4586 convert (TREE_TYPE (arg5_plus_arg3),
4587 TYPE_SIZE (arg4_type)))),
4588 prep_arg4,
4589 convert (arg4_type, integer_zero_node));
4590#endif
4591 prep_arg4
4592 = ffecom_2 (BIT_AND_EXPR, arg4_type,
4593 arg4_tree,
4594 ffecom_2 (BIT_IOR_EXPR, arg4_type,
4595 prep_arg4,
4596 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4597 ffecom_2 (LSHIFT_EXPR, arg4_type,
4598 ffecom_1 (BIT_NOT_EXPR,
4599 arg4_type,
4600 convert
4601 (arg4_type,
4602 integer_zero_node)),
4603 arg5_tree))));
4604 prep_arg1
4605 = ffecom_2 (BIT_IOR_EXPR, arg4_type,
4606 prep_arg1,
4607 prep_arg4);
4608#if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4609 prep_arg1
4610 = ffecom_3 (COND_EXPR, arg4_type,
4611 ffecom_truth_value
4612 (ffecom_2 (NE_EXPR, integer_type_node,
4613 arg3_tree,
4614 convert (TREE_TYPE (arg3_tree),
4615 integer_zero_node))),
4616 prep_arg1,
4617 arg4_tree);
4618 prep_arg1
4619 = ffecom_3 (COND_EXPR, arg4_type,
4620 ffecom_truth_value
4621 (ffecom_2 (NE_EXPR, integer_type_node,
4622 arg3_tree,
4623 convert (TREE_TYPE (arg3_tree),
4624 TYPE_SIZE (arg4_type)))),
4625 prep_arg1,
4626 arg1_tree);
4627#endif
4628 expr_tree
4629 = ffecom_2s (MODIFY_EXPR, void_type_node,
4630 arg4_tree,
4631 prep_arg1);
4632 /* Make sure SAVE_EXPRs get referenced early enough. */
4633 expr_tree
4634 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4635 arg1_tree,
4636 ffecom_2 (COMPOUND_EXPR, void_type_node,
4637 arg3_tree,
4638 ffecom_2 (COMPOUND_EXPR, void_type_node,
4639 arg5_tree,
4640 ffecom_2 (COMPOUND_EXPR, void_type_node,
4641 arg5_plus_arg3,
4642 expr_tree))));
4643 expr_tree
4644 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4645 arg4_tree,
4646 expr_tree);
4647
4648 }
4649 return expr_tree;
4650
4651 case FFEINTRIN_impDERF:
4652 case FFEINTRIN_impERF:
4653 case FFEINTRIN_impDERFC:
4654 case FFEINTRIN_impERFC:
4655 break;
4656
4657 case FFEINTRIN_impIARGC:
4658 /* extern int xargc; i__1 = xargc - 1; */
4659 expr_tree = ffecom_2 (MINUS_EXPR, TREE_TYPE (ffecom_tree_xargc_),
4660 ffecom_tree_xargc_,
4661 convert (TREE_TYPE (ffecom_tree_xargc_),
4662 integer_one_node));
4663 return expr_tree;
4664
4665 case FFEINTRIN_impSIGNAL_func:
4666 case FFEINTRIN_impSIGNAL_subr:
4667 {
4668 tree arg1_tree;
4669 tree arg2_tree;
4670 tree arg3_tree;
4671
4672 ffecom_push_calltemps ();
4673
4674 arg1_tree = convert (ffecom_f2c_integer_type_node,
4675 ffecom_expr (arg1));
4676 arg1_tree = ffecom_1 (ADDR_EXPR,
4677 build_pointer_type (TREE_TYPE (arg1_tree)),
4678 arg1_tree);
4679
4680 /* Pass procedure as a pointer to it, anything else by value. */
4681 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4682 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4683 else
4684 arg2_tree = ffecom_ptr_to_expr (arg2);
4685 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4686 arg2_tree);
4687
4688 if (arg3 != NULL)
4689 arg3_tree = ffecom_expr_rw (arg3);
4690 else
4691 arg3_tree = NULL_TREE;
4692
4693 ffecom_pop_calltemps ();
4694
4695 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4696 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4697 TREE_CHAIN (arg1_tree) = arg2_tree;
4698
4699 expr_tree
4700 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4701 ffecom_gfrt_kindtype (gfrt),
4702 FALSE,
4703 ((codegen_imp == FFEINTRIN_impSIGNAL_subr) ?
4704 NULL_TREE :
4705 tree_type),
4706 arg1_tree,
4707 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
4708
4709 if (arg3_tree != NULL_TREE)
4710 expr_tree
4711 = ffecom_modify (NULL_TREE, arg3_tree,
4712 convert (TREE_TYPE (arg3_tree),
4713 expr_tree));
4714 }
4715 return expr_tree;
4716
4717 case FFEINTRIN_impALARM:
4718 {
4719 tree arg1_tree;
4720 tree arg2_tree;
4721 tree arg3_tree;
4722
4723 ffecom_push_calltemps ();
4724
4725 arg1_tree = convert (ffecom_f2c_integer_type_node,
4726 ffecom_expr (arg1));
4727 arg1_tree = ffecom_1 (ADDR_EXPR,
4728 build_pointer_type (TREE_TYPE (arg1_tree)),
4729 arg1_tree);
4730
4731 /* Pass procedure as a pointer to it, anything else by value. */
4732 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4733 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4734 else
4735 arg2_tree = ffecom_ptr_to_expr (arg2);
4736 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4737 arg2_tree);
4738
4739 if (arg3 != NULL)
4740 arg3_tree = ffecom_expr_rw (arg3);
4741 else
4742 arg3_tree = NULL_TREE;
4743
4744 ffecom_pop_calltemps ();
4745
4746 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4747 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4748 TREE_CHAIN (arg1_tree) = arg2_tree;
4749
4750 expr_tree
4751 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4752 ffecom_gfrt_kindtype (gfrt),
4753 FALSE,
4754 NULL_TREE,
4755 arg1_tree,
4756 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
4757
4758 if (arg3_tree != NULL_TREE)
4759 expr_tree
4760 = ffecom_modify (NULL_TREE, arg3_tree,
4761 convert (TREE_TYPE (arg3_tree),
4762 expr_tree));
4763 }
4764 return expr_tree;
4765
4766 case FFEINTRIN_impCHDIR_subr:
4767 case FFEINTRIN_impFDATE_subr:
4768 case FFEINTRIN_impFGET_subr:
4769 case FFEINTRIN_impFPUT_subr:
4770 case FFEINTRIN_impGETCWD_subr:
4771 case FFEINTRIN_impHOSTNM_subr:
4772 case FFEINTRIN_impSYSTEM_subr:
4773 case FFEINTRIN_impUNLINK_subr:
4774 {
4775 tree arg1_len = integer_zero_node;
4776 tree arg1_tree;
4777 tree arg2_tree;
4778
4779 ffecom_push_calltemps ();
4780
4781 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
4782
4783 if (arg2 != NULL)
4784 arg2_tree = ffecom_expr_rw (arg2);
4785 else
4786 arg2_tree = NULL_TREE;
4787
4788 ffecom_pop_calltemps ();
4789
4790 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4791 arg1_len = build_tree_list (NULL_TREE, arg1_len);
4792 TREE_CHAIN (arg1_tree) = arg1_len;
4793
4794 expr_tree
4795 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4796 ffecom_gfrt_kindtype (gfrt),
4797 FALSE,
4798 NULL_TREE,
4799 arg1_tree,
4800 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
4801
4802 if (arg2_tree != NULL_TREE)
4803 expr_tree
4804 = ffecom_modify (NULL_TREE, arg2_tree,
4805 convert (TREE_TYPE (arg2_tree),
4806 expr_tree));
4807 }
4808 return expr_tree;
4809
4810 case FFEINTRIN_impEXIT:
4811 if (arg1 != NULL)
4812 break;
4813
4814 expr_tree = build_tree_list (NULL_TREE,
4815 ffecom_1 (ADDR_EXPR,
4816 build_pointer_type
4817 (ffecom_integer_type_node),
4818 integer_zero_node));
4819
4820 return
4821 ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4822 ffecom_gfrt_kindtype (gfrt),
4823 FALSE,
4824 void_type_node,
4825 expr_tree,
4826 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
4827
4828 case FFEINTRIN_impFLUSH:
4829 if (arg1 == NULL)
4830 gfrt = FFECOM_gfrtFLUSH;
4831 else
4832 gfrt = FFECOM_gfrtFLUSH1;
4833 break;
4834
4835 case FFEINTRIN_impCHMOD_subr:
4836 case FFEINTRIN_impLINK_subr:
4837 case FFEINTRIN_impRENAME_subr:
4838 case FFEINTRIN_impSYMLNK_subr:
4839 {
4840 tree arg1_len = integer_zero_node;
4841 tree arg1_tree;
4842 tree arg2_len = integer_zero_node;
4843 tree arg2_tree;
4844 tree arg3_tree;
4845
4846 ffecom_push_calltemps ();
4847
4848 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
4849 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
4850 if (arg3 != NULL)
4851 arg3_tree = ffecom_expr_rw (arg3);
4852 else
4853 arg3_tree = NULL_TREE;
4854
4855 ffecom_pop_calltemps ();
4856
4857 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4858 arg1_len = build_tree_list (NULL_TREE, arg1_len);
4859 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4860 arg2_len = build_tree_list (NULL_TREE, arg2_len);
4861 TREE_CHAIN (arg1_tree) = arg2_tree;
4862 TREE_CHAIN (arg2_tree) = arg1_len;
4863 TREE_CHAIN (arg1_len) = arg2_len;
4864 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4865 ffecom_gfrt_kindtype (gfrt),
4866 FALSE,
4867 NULL_TREE,
4868 arg1_tree,
4869 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
4870 if (arg3_tree != NULL_TREE)
4871 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
4872 convert (TREE_TYPE (arg3_tree),
4873 expr_tree));
4874 }
4875 return expr_tree;
4876
4877 case FFEINTRIN_impLSTAT_subr:
4878 case FFEINTRIN_impSTAT_subr:
4879 {
4880 tree arg1_len = integer_zero_node;
4881 tree arg1_tree;
4882 tree arg2_tree;
4883 tree arg3_tree;
4884
4885 ffecom_push_calltemps ();
4886
4887 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
4888
4889 arg2_tree = ffecom_ptr_to_expr (arg2);
4890
4891 if (arg3 != NULL)
4892 arg3_tree = ffecom_expr_rw (arg3);
4893 else
4894 arg3_tree = NULL_TREE;
4895
4896 ffecom_pop_calltemps ();
4897
4898 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4899 arg1_len = build_tree_list (NULL_TREE, arg1_len);
4900 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4901 TREE_CHAIN (arg1_tree) = arg2_tree;
4902 TREE_CHAIN (arg2_tree) = arg1_len;
4903 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4904 ffecom_gfrt_kindtype (gfrt),
4905 FALSE,
4906 NULL_TREE,
4907 arg1_tree,
4908 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
4909 if (arg3_tree != NULL_TREE)
4910 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
4911 convert (TREE_TYPE (arg3_tree),
4912 expr_tree));
4913 }
4914 return expr_tree;
4915
4916 case FFEINTRIN_impFGETC_subr:
4917 case FFEINTRIN_impFPUTC_subr:
4918 {
4919 tree arg1_tree;
4920 tree arg2_tree;
4921 tree arg2_len = integer_zero_node;
4922 tree arg3_tree;
4923
4924 ffecom_push_calltemps ();
4925
4926 arg1_tree = convert (ffecom_f2c_integer_type_node,
4927 ffecom_expr (arg1));
4928 arg1_tree = ffecom_1 (ADDR_EXPR,
4929 build_pointer_type (TREE_TYPE (arg1_tree)),
4930 arg1_tree);
4931
4932 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
4933 arg3_tree = ffecom_expr_rw (arg3);
4934
4935 ffecom_pop_calltemps ();
4936
4937 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4938 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4939 arg2_len = build_tree_list (NULL_TREE, arg2_len);
4940 TREE_CHAIN (arg1_tree) = arg2_tree;
4941 TREE_CHAIN (arg2_tree) = arg2_len;
4942
4943 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4944 ffecom_gfrt_kindtype (gfrt),
4945 FALSE,
4946 NULL_TREE,
4947 arg1_tree,
4948 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
4949 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
4950 convert (TREE_TYPE (arg3_tree),
4951 expr_tree));
4952 }
4953 return expr_tree;
4954
4955 case FFEINTRIN_impFSTAT_subr:
4956 {
4957 tree arg1_tree;
4958 tree arg2_tree;
4959 tree arg3_tree;
4960
4961 ffecom_push_calltemps ();
4962
4963 arg1_tree = convert (ffecom_f2c_integer_type_node,
4964 ffecom_expr (arg1));
4965 arg1_tree = ffecom_1 (ADDR_EXPR,
4966 build_pointer_type (TREE_TYPE (arg1_tree)),
4967 arg1_tree);
4968
4969 arg2_tree = convert (ffecom_f2c_ptr_to_integer_type_node,
4970 ffecom_ptr_to_expr (arg2));
4971
4972 if (arg3 == NULL)
4973 arg3_tree = NULL_TREE;
4974 else
4975 arg3_tree = ffecom_expr_rw (arg3);
4976
4977 ffecom_pop_calltemps ();
4978
4979 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4980 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4981 TREE_CHAIN (arg1_tree) = arg2_tree;
4982 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4983 ffecom_gfrt_kindtype (gfrt),
4984 FALSE,
4985 NULL_TREE,
4986 arg1_tree,
4987 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
4988 if (arg3_tree != NULL_TREE) {
4989 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
4990 convert (TREE_TYPE (arg3_tree),
4991 expr_tree));
4992 }
4993 }
4994 return expr_tree;
4995
4996 case FFEINTRIN_impKILL_subr:
4997 {
4998 tree arg1_tree;
4999 tree arg2_tree;
5000 tree arg3_tree;
5001
5002 ffecom_push_calltemps ();
5003
5004 arg1_tree = convert (ffecom_f2c_integer_type_node,
5005 ffecom_expr (arg1));
5006 arg1_tree = ffecom_1 (ADDR_EXPR,
5007 build_pointer_type (TREE_TYPE (arg1_tree)),
5008 arg1_tree);
5009
5010 arg2_tree = convert (ffecom_f2c_integer_type_node,
5011 ffecom_expr (arg2));
5012 arg2_tree = ffecom_1 (ADDR_EXPR,
5013 build_pointer_type (TREE_TYPE (arg2_tree)),
5014 arg2_tree);
5015
5016 if (arg3 == NULL)
5017 arg3_tree = NULL_TREE;
5018 else
5019 arg3_tree = ffecom_expr_rw (arg3);
5020
5021 ffecom_pop_calltemps ();
5022
5023 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5024 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5025 TREE_CHAIN (arg1_tree) = arg2_tree;
5026 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5027 ffecom_gfrt_kindtype (gfrt),
5028 FALSE,
5029 NULL_TREE,
5030 arg1_tree,
5031 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
5032 if (arg3_tree != NULL_TREE) {
5033 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5034 convert (TREE_TYPE (arg3_tree),
5035 expr_tree));
5036 }
5037 }
5038 return expr_tree;
5039
5040 case FFEINTRIN_impCTIME_subr:
5041 case FFEINTRIN_impTTYNAM_subr:
5042 {
5043 tree arg1_len = integer_zero_node;
5044 tree arg1_tree;
5045 tree arg2_tree;
5046
5047 ffecom_push_calltemps ();
5048
5049 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5050
5051 arg2_tree = convert (((gfrt == FFEINTRIN_impCTIME_subr) ?
5052 ffecom_f2c_longint_type_node :
5053 ffecom_f2c_integer_type_node),
5054 ffecom_expr (arg2));
5055 arg2_tree = ffecom_1 (ADDR_EXPR,
5056 build_pointer_type (TREE_TYPE (arg2_tree)),
5057 arg2_tree);
5058
5059 ffecom_pop_calltemps ();
5060
5061 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5062 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5063 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5064 TREE_CHAIN (arg1_len) = arg2_tree;
5065 TREE_CHAIN (arg1_tree) = arg1_len;
5066
5067 expr_tree
5068 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5069 ffecom_gfrt_kindtype (gfrt),
5070 FALSE,
5071 NULL_TREE,
5072 arg1_tree,
5073 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
5074 }
5075 return expr_tree;
5076
5077 case FFEINTRIN_impIRAND:
5078 case FFEINTRIN_impRAND:
5079 /* Arg defaults to 0 (normal random case) */
5080 {
5081 tree arg1_tree;
5082
5083 if (arg1 == NULL)
5084 arg1_tree = ffecom_integer_zero_node;
5085 else
5086 arg1_tree = ffecom_expr (arg1);
5087 arg1_tree = convert (ffecom_f2c_integer_type_node,
5088 arg1_tree);
5089 arg1_tree = ffecom_1 (ADDR_EXPR,
5090 build_pointer_type (TREE_TYPE (arg1_tree)),
5091 arg1_tree);
5092 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5093
5094 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5095 ffecom_gfrt_kindtype (gfrt),
5096 FALSE,
5097 ((codegen_imp == FFEINTRIN_impIRAND) ?
5098 ffecom_f2c_integer_type_node :
5099 ffecom_f2c_doublereal_type_node),
5100 arg1_tree,
5101 dest_tree, dest, dest_used,
5102 NULL_TREE, TRUE);
5103 }
5104 return expr_tree;
5105
5106 case FFEINTRIN_impFTELL_subr:
5107 case FFEINTRIN_impUMASK_subr:
5108 {
5109 tree arg1_tree;
5110 tree arg2_tree;
5111
5112 ffecom_push_calltemps ();
5113
5114 arg1_tree = convert (ffecom_f2c_integer_type_node,
5115 ffecom_expr (arg1));
5116 arg1_tree = ffecom_1 (ADDR_EXPR,
5117 build_pointer_type (TREE_TYPE (arg1_tree)),
5118 arg1_tree);
5119
5120 if (arg2 == NULL)
5121 arg2_tree = NULL_TREE;
5122 else
5123 arg2_tree = ffecom_expr_rw (arg2);
5124
5125 ffecom_pop_calltemps ();
5126
5127 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5128 ffecom_gfrt_kindtype (gfrt),
5129 FALSE,
5130 NULL_TREE,
5131 build_tree_list (NULL_TREE, arg1_tree),
5132 NULL_TREE, NULL, NULL, NULL_TREE,
5133 TRUE);
5134 if (arg2_tree != NULL_TREE) {
5135 expr_tree = ffecom_modify (NULL_TREE, arg2_tree,
5136 convert (TREE_TYPE (arg2_tree),
5137 expr_tree));
5138 }
5139 }
5140 return expr_tree;
5141
5142 case FFEINTRIN_impCPU_TIME:
5143 case FFEINTRIN_impSECOND_subr:
5144 {
5145 tree arg1_tree;
5146
5147 ffecom_push_calltemps ();
5148
5149 arg1_tree = ffecom_expr_rw (arg1);
5150
5151 ffecom_pop_calltemps ();
5152
5153 expr_tree
5154 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5155 ffecom_gfrt_kindtype (gfrt),
5156 FALSE,
5157 NULL_TREE,
5158 NULL_TREE,
5159 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
5160
5161 expr_tree
5162 = ffecom_modify (NULL_TREE, arg1_tree,
5163 convert (TREE_TYPE (arg1_tree),
5164 expr_tree));
5165 }
5166 return expr_tree;
5167
5168 case FFEINTRIN_impDTIME_subr:
5169 case FFEINTRIN_impETIME_subr:
5170 {
5171 tree arg1_tree;
5172 tree arg2_tree;
5173
5174 ffecom_push_calltemps ();
5175
5176 arg1_tree = ffecom_expr_rw (arg1);
5177
5178 arg2_tree = ffecom_ptr_to_expr (arg2);
5179
5180 ffecom_pop_calltemps ();
5181
5182 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5183 ffecom_gfrt_kindtype (gfrt),
5184 FALSE,
5185 NULL_TREE,
5186 build_tree_list (NULL_TREE, arg2_tree),
5187 NULL_TREE, NULL, NULL, NULL_TREE,
5188 TRUE);
5189 expr_tree = ffecom_modify (NULL_TREE, arg1_tree,
5190 convert (TREE_TYPE (arg1_tree),
5191 expr_tree));
5192 }
5193 return expr_tree;
5194
5195 /* Straightforward calls of libf2c routines: */
5196 case FFEINTRIN_impABORT:
5197 case FFEINTRIN_impACCESS:
5198 case FFEINTRIN_impBESJ0:
5199 case FFEINTRIN_impBESJ1:
5200 case FFEINTRIN_impBESJN:
5201 case FFEINTRIN_impBESY0:
5202 case FFEINTRIN_impBESY1:
5203 case FFEINTRIN_impBESYN:
5204 case FFEINTRIN_impCHDIR_func:
5205 case FFEINTRIN_impCHMOD_func:
5206 case FFEINTRIN_impDATE:
9e8e701d 5207 case FFEINTRIN_impDATE_AND_TIME:
5ff904cd
JL
5208 case FFEINTRIN_impDBESJ0:
5209 case FFEINTRIN_impDBESJ1:
5210 case FFEINTRIN_impDBESJN:
5211 case FFEINTRIN_impDBESY0:
5212 case FFEINTRIN_impDBESY1:
5213 case FFEINTRIN_impDBESYN:
5214 case FFEINTRIN_impDTIME_func:
5215 case FFEINTRIN_impETIME_func:
5216 case FFEINTRIN_impFGETC_func:
5217 case FFEINTRIN_impFGET_func:
5218 case FFEINTRIN_impFNUM:
5219 case FFEINTRIN_impFPUTC_func:
5220 case FFEINTRIN_impFPUT_func:
5221 case FFEINTRIN_impFSEEK:
5222 case FFEINTRIN_impFSTAT_func:
5223 case FFEINTRIN_impFTELL_func:
5224 case FFEINTRIN_impGERROR:
5225 case FFEINTRIN_impGETARG:
5226 case FFEINTRIN_impGETCWD_func:
5227 case FFEINTRIN_impGETENV:
5228 case FFEINTRIN_impGETGID:
5229 case FFEINTRIN_impGETLOG:
5230 case FFEINTRIN_impGETPID:
5231 case FFEINTRIN_impGETUID:
5232 case FFEINTRIN_impGMTIME:
5233 case FFEINTRIN_impHOSTNM_func:
5234 case FFEINTRIN_impIDATE_unix:
5235 case FFEINTRIN_impIDATE_vxt:
5236 case FFEINTRIN_impIERRNO:
5237 case FFEINTRIN_impISATTY:
5238 case FFEINTRIN_impITIME:
5239 case FFEINTRIN_impKILL_func:
5240 case FFEINTRIN_impLINK_func:
5241 case FFEINTRIN_impLNBLNK:
5242 case FFEINTRIN_impLSTAT_func:
5243 case FFEINTRIN_impLTIME:
5244 case FFEINTRIN_impMCLOCK8:
5245 case FFEINTRIN_impMCLOCK:
5246 case FFEINTRIN_impPERROR:
5247 case FFEINTRIN_impRENAME_func:
5248 case FFEINTRIN_impSECNDS:
5249 case FFEINTRIN_impSECOND_func:
5250 case FFEINTRIN_impSLEEP:
5251 case FFEINTRIN_impSRAND:
5252 case FFEINTRIN_impSTAT_func:
5253 case FFEINTRIN_impSYMLNK_func:
5254 case FFEINTRIN_impSYSTEM_CLOCK:
5255 case FFEINTRIN_impSYSTEM_func:
5256 case FFEINTRIN_impTIME8:
5257 case FFEINTRIN_impTIME_unix:
5258 case FFEINTRIN_impTIME_vxt:
5259 case FFEINTRIN_impUMASK_func:
5260 case FFEINTRIN_impUNLINK_func:
5261 break;
5262
5263 case FFEINTRIN_impCTIME_func: /* CHARACTER functions not handled here. */
5264 case FFEINTRIN_impFDATE_func: /* CHARACTER functions not handled here. */
5265 case FFEINTRIN_impTTYNAM_func: /* CHARACTER functions not handled here. */
5266 case FFEINTRIN_impNONE:
5267 case FFEINTRIN_imp: /* Hush up gcc warning. */
5268 fprintf (stderr, "No %s implementation.\n",
5269 ffeintrin_name_implementation (ffebld_symter_implementation (ffebld_left (expr))));
5270 assert ("unimplemented intrinsic" == NULL);
5271 return error_mark_node;
5272 }
5273
5274 assert (gfrt != FFECOM_gfrt); /* Must have an implementation! */
5275
5276 ffecom_push_calltemps ();
5277 expr_tree = ffecom_arglist_expr_ (ffecom_gfrt_args_ (gfrt),
5278 ffebld_right (expr));
5279 ffecom_pop_calltemps ();
5280
5281 return ffecom_call_ (ffecom_gfrt_tree_ (gfrt), ffecom_gfrt_kindtype (gfrt),
5282 (ffe_is_f2c_library () && ffecom_gfrt_complex_[gfrt]),
5283 tree_type,
5284 expr_tree, dest_tree, dest, dest_used,
5285 NULL_TREE, TRUE);
5286
5287 /**INDENT* (Do not reformat this comment even with -fca option.)
5288 Data-gathering files: Given the source file listed below, compiled with
5289 f2c I obtained the output file listed after that, and from the output
5290 file I derived the above code.
5291
5292-------- (begin input file to f2c)
5293 implicit none
5294 character*10 A1,A2
5295 complex C1,C2
5296 integer I1,I2
5297 real R1,R2
5298 double precision D1,D2
5299C
5300 call getem(A1,A2,C1,C2,I1,I2,R1,R2,D1,D2)
5301c /
5302 call fooI(I1/I2)
5303 call fooR(R1/I1)
5304 call fooD(D1/I1)
5305 call fooC(C1/I1)
5306 call fooR(R1/R2)
5307 call fooD(R1/D1)
5308 call fooD(D1/D2)
5309 call fooD(D1/R1)
5310 call fooC(C1/C2)
5311 call fooC(C1/R1)
5312 call fooZ(C1/D1)
5313c **
5314 call fooI(I1**I2)
5315 call fooR(R1**I1)
5316 call fooD(D1**I1)
5317 call fooC(C1**I1)
5318 call fooR(R1**R2)
5319 call fooD(R1**D1)
5320 call fooD(D1**D2)
5321 call fooD(D1**R1)
5322 call fooC(C1**C2)
5323 call fooC(C1**R1)
5324 call fooZ(C1**D1)
5325c FFEINTRIN_impABS
5326 call fooR(ABS(R1))
5327c FFEINTRIN_impACOS
5328 call fooR(ACOS(R1))
5329c FFEINTRIN_impAIMAG
5330 call fooR(AIMAG(C1))
5331c FFEINTRIN_impAINT
5332 call fooR(AINT(R1))
5333c FFEINTRIN_impALOG
5334 call fooR(ALOG(R1))
5335c FFEINTRIN_impALOG10
5336 call fooR(ALOG10(R1))
5337c FFEINTRIN_impAMAX0
5338 call fooR(AMAX0(I1,I2))
5339c FFEINTRIN_impAMAX1
5340 call fooR(AMAX1(R1,R2))
5341c FFEINTRIN_impAMIN0
5342 call fooR(AMIN0(I1,I2))
5343c FFEINTRIN_impAMIN1
5344 call fooR(AMIN1(R1,R2))
5345c FFEINTRIN_impAMOD
5346 call fooR(AMOD(R1,R2))
5347c FFEINTRIN_impANINT
5348 call fooR(ANINT(R1))
5349c FFEINTRIN_impASIN
5350 call fooR(ASIN(R1))
5351c FFEINTRIN_impATAN
5352 call fooR(ATAN(R1))
5353c FFEINTRIN_impATAN2
5354 call fooR(ATAN2(R1,R2))
5355c FFEINTRIN_impCABS
5356 call fooR(CABS(C1))
5357c FFEINTRIN_impCCOS
5358 call fooC(CCOS(C1))
5359c FFEINTRIN_impCEXP
5360 call fooC(CEXP(C1))
5361c FFEINTRIN_impCHAR
5362 call fooA(CHAR(I1))
5363c FFEINTRIN_impCLOG
5364 call fooC(CLOG(C1))
5365c FFEINTRIN_impCONJG
5366 call fooC(CONJG(C1))
5367c FFEINTRIN_impCOS
5368 call fooR(COS(R1))
5369c FFEINTRIN_impCOSH
5370 call fooR(COSH(R1))
5371c FFEINTRIN_impCSIN
5372 call fooC(CSIN(C1))
5373c FFEINTRIN_impCSQRT
5374 call fooC(CSQRT(C1))
5375c FFEINTRIN_impDABS
5376 call fooD(DABS(D1))
5377c FFEINTRIN_impDACOS
5378 call fooD(DACOS(D1))
5379c FFEINTRIN_impDASIN
5380 call fooD(DASIN(D1))
5381c FFEINTRIN_impDATAN
5382 call fooD(DATAN(D1))
5383c FFEINTRIN_impDATAN2
5384 call fooD(DATAN2(D1,D2))
5385c FFEINTRIN_impDCOS
5386 call fooD(DCOS(D1))
5387c FFEINTRIN_impDCOSH
5388 call fooD(DCOSH(D1))
5389c FFEINTRIN_impDDIM
5390 call fooD(DDIM(D1,D2))
5391c FFEINTRIN_impDEXP
5392 call fooD(DEXP(D1))
5393c FFEINTRIN_impDIM
5394 call fooR(DIM(R1,R2))
5395c FFEINTRIN_impDINT
5396 call fooD(DINT(D1))
5397c FFEINTRIN_impDLOG
5398 call fooD(DLOG(D1))
5399c FFEINTRIN_impDLOG10
5400 call fooD(DLOG10(D1))
5401c FFEINTRIN_impDMAX1
5402 call fooD(DMAX1(D1,D2))
5403c FFEINTRIN_impDMIN1
5404 call fooD(DMIN1(D1,D2))
5405c FFEINTRIN_impDMOD
5406 call fooD(DMOD(D1,D2))
5407c FFEINTRIN_impDNINT
5408 call fooD(DNINT(D1))
5409c FFEINTRIN_impDPROD
5410 call fooD(DPROD(R1,R2))
5411c FFEINTRIN_impDSIGN
5412 call fooD(DSIGN(D1,D2))
5413c FFEINTRIN_impDSIN
5414 call fooD(DSIN(D1))
5415c FFEINTRIN_impDSINH
5416 call fooD(DSINH(D1))
5417c FFEINTRIN_impDSQRT
5418 call fooD(DSQRT(D1))
5419c FFEINTRIN_impDTAN
5420 call fooD(DTAN(D1))
5421c FFEINTRIN_impDTANH
5422 call fooD(DTANH(D1))
5423c FFEINTRIN_impEXP
5424 call fooR(EXP(R1))
5425c FFEINTRIN_impIABS
5426 call fooI(IABS(I1))
5427c FFEINTRIN_impICHAR
5428 call fooI(ICHAR(A1))
5429c FFEINTRIN_impIDIM
5430 call fooI(IDIM(I1,I2))
5431c FFEINTRIN_impIDNINT
5432 call fooI(IDNINT(D1))
5433c FFEINTRIN_impINDEX
5434 call fooI(INDEX(A1,A2))
5435c FFEINTRIN_impISIGN
5436 call fooI(ISIGN(I1,I2))
5437c FFEINTRIN_impLEN
5438 call fooI(LEN(A1))
5439c FFEINTRIN_impLGE
5440 call fooL(LGE(A1,A2))
5441c FFEINTRIN_impLGT
5442 call fooL(LGT(A1,A2))
5443c FFEINTRIN_impLLE
5444 call fooL(LLE(A1,A2))
5445c FFEINTRIN_impLLT
5446 call fooL(LLT(A1,A2))
5447c FFEINTRIN_impMAX0
5448 call fooI(MAX0(I1,I2))
5449c FFEINTRIN_impMAX1
5450 call fooI(MAX1(R1,R2))
5451c FFEINTRIN_impMIN0
5452 call fooI(MIN0(I1,I2))
5453c FFEINTRIN_impMIN1
5454 call fooI(MIN1(R1,R2))
5455c FFEINTRIN_impMOD
5456 call fooI(MOD(I1,I2))
5457c FFEINTRIN_impNINT
5458 call fooI(NINT(R1))
5459c FFEINTRIN_impSIGN
5460 call fooR(SIGN(R1,R2))
5461c FFEINTRIN_impSIN
5462 call fooR(SIN(R1))
5463c FFEINTRIN_impSINH
5464 call fooR(SINH(R1))
5465c FFEINTRIN_impSQRT
5466 call fooR(SQRT(R1))
5467c FFEINTRIN_impTAN
5468 call fooR(TAN(R1))
5469c FFEINTRIN_impTANH
5470 call fooR(TANH(R1))
5471c FFEINTRIN_imp_CMPLX_C
5472 call fooC(cmplx(C1,C2))
5473c FFEINTRIN_imp_CMPLX_D
5474 call fooZ(cmplx(D1,D2))
5475c FFEINTRIN_imp_CMPLX_I
5476 call fooC(cmplx(I1,I2))
5477c FFEINTRIN_imp_CMPLX_R
5478 call fooC(cmplx(R1,R2))
5479c FFEINTRIN_imp_DBLE_C
5480 call fooD(dble(C1))
5481c FFEINTRIN_imp_DBLE_D
5482 call fooD(dble(D1))
5483c FFEINTRIN_imp_DBLE_I
5484 call fooD(dble(I1))
5485c FFEINTRIN_imp_DBLE_R
5486 call fooD(dble(R1))
5487c FFEINTRIN_imp_INT_C
5488 call fooI(int(C1))
5489c FFEINTRIN_imp_INT_D
5490 call fooI(int(D1))
5491c FFEINTRIN_imp_INT_I
5492 call fooI(int(I1))
5493c FFEINTRIN_imp_INT_R
5494 call fooI(int(R1))
5495c FFEINTRIN_imp_REAL_C
5496 call fooR(real(C1))
5497c FFEINTRIN_imp_REAL_D
5498 call fooR(real(D1))
5499c FFEINTRIN_imp_REAL_I
5500 call fooR(real(I1))
5501c FFEINTRIN_imp_REAL_R
5502 call fooR(real(R1))
5503c
5504c FFEINTRIN_imp_INT_D:
5505c
5506c FFEINTRIN_specIDINT
5507 call fooI(IDINT(D1))
5508c
5509c FFEINTRIN_imp_INT_R:
5510c
5511c FFEINTRIN_specIFIX
5512 call fooI(IFIX(R1))
5513c FFEINTRIN_specINT
5514 call fooI(INT(R1))
5515c
5516c FFEINTRIN_imp_REAL_D:
5517c
5518c FFEINTRIN_specSNGL
5519 call fooR(SNGL(D1))
5520c
5521c FFEINTRIN_imp_REAL_I:
5522c
5523c FFEINTRIN_specFLOAT
5524 call fooR(FLOAT(I1))
5525c FFEINTRIN_specREAL
5526 call fooR(REAL(I1))
5527c
5528 end
5529-------- (end input file to f2c)
5530
5531-------- (begin output from providing above input file as input to:
5532-------- `f2c | gcc -E -C - | sed -e "s:/[*]*://:g" -e "s:[*]*[/]://:g" \
5533-------- -e "s:^#.*$::g"')
5534
5535// -- translated by f2c (version 19950223).
5536 You must link the resulting object file with the libraries:
5537 -lf2c -lm (in that order)
5538//
5539
5540
5541// f2c.h -- Standard Fortran to C header file //
5542
5543/// barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed."
5544
5545 - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) //
5546
5547
5548
5549
5550// F2C_INTEGER will normally be `int' but would be `long' on 16-bit systems //
5551// we assume short, float are OK //
5552typedef long int // long int // integer;
5553typedef char *address;
5554typedef short int shortint;
5555typedef float real;
5556typedef double doublereal;
5557typedef struct { real r, i; } complex;
5558typedef struct { doublereal r, i; } doublecomplex;
5559typedef long int // long int // logical;
5560typedef short int shortlogical;
5561typedef char logical1;
5562typedef char integer1;
5563// typedef long long longint; // // system-dependent //
5564
5565
5566
5567
5568// Extern is for use with -E //
5569
5570
5571
5572
5573// I/O stuff //
5574
5575
5576
5577
5578
5579
5580
5581
5582typedef long int // int or long int // flag;
5583typedef long int // int or long int // ftnlen;
5584typedef long int // int or long int // ftnint;
5585
5586
5587//external read, write//
5588typedef struct
5589{ flag cierr;
5590 ftnint ciunit;
5591 flag ciend;
5592 char *cifmt;
5593 ftnint cirec;
5594} cilist;
5595
5596//internal read, write//
5597typedef struct
5598{ flag icierr;
5599 char *iciunit;
5600 flag iciend;
5601 char *icifmt;
5602 ftnint icirlen;
5603 ftnint icirnum;
5604} icilist;
5605
5606//open//
5607typedef struct
5608{ flag oerr;
5609 ftnint ounit;
5610 char *ofnm;
5611 ftnlen ofnmlen;
5612 char *osta;
5613 char *oacc;
5614 char *ofm;
5615 ftnint orl;
5616 char *oblnk;
5617} olist;
5618
5619//close//
5620typedef struct
5621{ flag cerr;
5622 ftnint cunit;
5623 char *csta;
5624} cllist;
5625
5626//rewind, backspace, endfile//
5627typedef struct
5628{ flag aerr;
5629 ftnint aunit;
5630} alist;
5631
5632// inquire //
5633typedef struct
5634{ flag inerr;
5635 ftnint inunit;
5636 char *infile;
5637 ftnlen infilen;
5638 ftnint *inex; //parameters in standard's order//
5639 ftnint *inopen;
5640 ftnint *innum;
5641 ftnint *innamed;
5642 char *inname;
5643 ftnlen innamlen;
5644 char *inacc;
5645 ftnlen inacclen;
5646 char *inseq;
5647 ftnlen inseqlen;
5648 char *indir;
5649 ftnlen indirlen;
5650 char *infmt;
5651 ftnlen infmtlen;
5652 char *inform;
5653 ftnint informlen;
5654 char *inunf;
5655 ftnlen inunflen;
5656 ftnint *inrecl;
5657 ftnint *innrec;
5658 char *inblank;
5659 ftnlen inblanklen;
5660} inlist;
5661
5662
5663
5664union Multitype { // for multiple entry points //
5665 integer1 g;
5666 shortint h;
5667 integer i;
5668 // longint j; //
5669 real r;
5670 doublereal d;
5671 complex c;
5672 doublecomplex z;
5673 };
5674
5675typedef union Multitype Multitype;
5676
5677typedef long Long; // No longer used; formerly in Namelist //
5678
5679struct Vardesc { // for Namelist //
5680 char *name;
5681 char *addr;
5682 ftnlen *dims;
5683 int type;
5684 };
5685typedef struct Vardesc Vardesc;
5686
5687struct Namelist {
5688 char *name;
5689 Vardesc **vars;
5690 int nvars;
5691 };
5692typedef struct Namelist Namelist;
5693
5694
5695
5696
5697
5698
5699
5700
5701// procedure parameter types for -A and -C++ //
5702
5703
5704
5705
5706typedef int // Unknown procedure type // (*U_fp)();
5707typedef shortint (*J_fp)();
5708typedef integer (*I_fp)();
5709typedef real (*R_fp)();
5710typedef doublereal (*D_fp)(), (*E_fp)();
5711typedef // Complex // void (*C_fp)();
5712typedef // Double Complex // void (*Z_fp)();
5713typedef logical (*L_fp)();
5714typedef shortlogical (*K_fp)();
5715typedef // Character // void (*H_fp)();
5716typedef // Subroutine // int (*S_fp)();
5717
5718// E_fp is for real functions when -R is not specified //
5719typedef void C_f; // complex function //
5720typedef void H_f; // character function //
5721typedef void Z_f; // double complex function //
5722typedef doublereal E_f; // real function with -R not specified //
5723
5724// undef any lower-case symbols that your C compiler predefines, e.g.: //
5725
5726
5727// (No such symbols should be defined in a strict ANSI C compiler.
5728 We can avoid trouble with f2c-translated code by using
5729 gcc -ansi [-traditional].) //
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753// Main program // MAIN__()
5754{
5755 // System generated locals //
5756 integer i__1;
5757 real r__1, r__2;
5758 doublereal d__1, d__2;
5759 complex q__1;
5760 doublecomplex z__1, z__2, z__3;
5761 logical L__1;
5762 char ch__1[1];
5763
5764 // Builtin functions //
5765 void c_div();
5766 integer pow_ii();
5767 double pow_ri(), pow_di();
5768 void pow_ci();
5769 double pow_dd();
5770 void pow_zz();
5771 double acos(), r_imag(), r_int(), log(), r_lg10(), r_mod(), r_nint(),
5772 asin(), atan(), atan2(), c_abs();
5773 void c_cos(), c_exp(), c_log(), r_cnjg();
5774 double cos(), cosh();
5775 void c_sin(), c_sqrt();
5776 double d_dim(), exp(), r_dim(), d_int(), d_lg10(), d_mod(), d_nint(),
5777 d_sign(), sin(), sinh(), sqrt(), tan(), tanh();
5778 integer i_dim(), i_dnnt(), i_indx(), i_sign(), i_len();
5779 logical l_ge(), l_gt(), l_le(), l_lt();
5780 integer i_nint();
5781 double r_sign();
5782
5783 // Local variables //
5784 extern // Subroutine // int fooa_(), fooc_(), food_(), fooi_(), foor_(),
5785 fool_(), fooz_(), getem_();
5786 static char a1[10], a2[10];
5787 static complex c1, c2;
5788 static doublereal d1, d2;
5789 static integer i1, i2;
5790 static real r1, r2;
5791
5792
5793 getem_(a1, a2, &c1, &c2, &i1, &i2, &r1, &r2, &d1, &d2, 10L, 10L);
5794// / //
5795 i__1 = i1 / i2;
5796 fooi_(&i__1);
5797 r__1 = r1 / i1;
5798 foor_(&r__1);
5799 d__1 = d1 / i1;
5800 food_(&d__1);
5801 d__1 = (doublereal) i1;
5802 q__1.r = c1.r / d__1, q__1.i = c1.i / d__1;
5803 fooc_(&q__1);
5804 r__1 = r1 / r2;
5805 foor_(&r__1);
5806 d__1 = r1 / d1;
5807 food_(&d__1);
5808 d__1 = d1 / d2;
5809 food_(&d__1);
5810 d__1 = d1 / r1;
5811 food_(&d__1);
5812 c_div(&q__1, &c1, &c2);
5813 fooc_(&q__1);
5814 q__1.r = c1.r / r1, q__1.i = c1.i / r1;
5815 fooc_(&q__1);
5816 z__1.r = c1.r / d1, z__1.i = c1.i / d1;
5817 fooz_(&z__1);
5818// ** //
5819 i__1 = pow_ii(&i1, &i2);
5820 fooi_(&i__1);
5821 r__1 = pow_ri(&r1, &i1);
5822 foor_(&r__1);
5823 d__1 = pow_di(&d1, &i1);
5824 food_(&d__1);
5825 pow_ci(&q__1, &c1, &i1);
5826 fooc_(&q__1);
5827 d__1 = (doublereal) r1;
5828 d__2 = (doublereal) r2;
5829 r__1 = pow_dd(&d__1, &d__2);
5830 foor_(&r__1);
5831 d__2 = (doublereal) r1;
5832 d__1 = pow_dd(&d__2, &d1);
5833 food_(&d__1);
5834 d__1 = pow_dd(&d1, &d2);
5835 food_(&d__1);
5836 d__2 = (doublereal) r1;
5837 d__1 = pow_dd(&d1, &d__2);
5838 food_(&d__1);
5839 z__2.r = c1.r, z__2.i = c1.i;
5840 z__3.r = c2.r, z__3.i = c2.i;
5841 pow_zz(&z__1, &z__2, &z__3);
5842 q__1.r = z__1.r, q__1.i = z__1.i;
5843 fooc_(&q__1);
5844 z__2.r = c1.r, z__2.i = c1.i;
5845 z__3.r = r1, z__3.i = 0.;
5846 pow_zz(&z__1, &z__2, &z__3);
5847 q__1.r = z__1.r, q__1.i = z__1.i;
5848 fooc_(&q__1);
5849 z__2.r = c1.r, z__2.i = c1.i;
5850 z__3.r = d1, z__3.i = 0.;
5851 pow_zz(&z__1, &z__2, &z__3);
5852 fooz_(&z__1);
5853// FFEINTRIN_impABS //
5854 r__1 = (doublereal)(( r1 ) >= 0 ? ( r1 ) : -( r1 )) ;
5855 foor_(&r__1);
5856// FFEINTRIN_impACOS //
5857 r__1 = acos(r1);
5858 foor_(&r__1);
5859// FFEINTRIN_impAIMAG //
5860 r__1 = r_imag(&c1);
5861 foor_(&r__1);
5862// FFEINTRIN_impAINT //
5863 r__1 = r_int(&r1);
5864 foor_(&r__1);
5865// FFEINTRIN_impALOG //
5866 r__1 = log(r1);
5867 foor_(&r__1);
5868// FFEINTRIN_impALOG10 //
5869 r__1 = r_lg10(&r1);
5870 foor_(&r__1);
5871// FFEINTRIN_impAMAX0 //
5872 r__1 = (real) (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
5873 foor_(&r__1);
5874// FFEINTRIN_impAMAX1 //
5875 r__1 = (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
5876 foor_(&r__1);
5877// FFEINTRIN_impAMIN0 //
5878 r__1 = (real) (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
5879 foor_(&r__1);
5880// FFEINTRIN_impAMIN1 //
5881 r__1 = (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
5882 foor_(&r__1);
5883// FFEINTRIN_impAMOD //
5884 r__1 = r_mod(&r1, &r2);
5885 foor_(&r__1);
5886// FFEINTRIN_impANINT //
5887 r__1 = r_nint(&r1);
5888 foor_(&r__1);
5889// FFEINTRIN_impASIN //
5890 r__1 = asin(r1);
5891 foor_(&r__1);
5892// FFEINTRIN_impATAN //
5893 r__1 = atan(r1);
5894 foor_(&r__1);
5895// FFEINTRIN_impATAN2 //
5896 r__1 = atan2(r1, r2);
5897 foor_(&r__1);
5898// FFEINTRIN_impCABS //
5899 r__1 = c_abs(&c1);
5900 foor_(&r__1);
5901// FFEINTRIN_impCCOS //
5902 c_cos(&q__1, &c1);
5903 fooc_(&q__1);
5904// FFEINTRIN_impCEXP //
5905 c_exp(&q__1, &c1);
5906 fooc_(&q__1);
5907// FFEINTRIN_impCHAR //
5908 *(unsigned char *)&ch__1[0] = i1;
5909 fooa_(ch__1, 1L);
5910// FFEINTRIN_impCLOG //
5911 c_log(&q__1, &c1);
5912 fooc_(&q__1);
5913// FFEINTRIN_impCONJG //
5914 r_cnjg(&q__1, &c1);
5915 fooc_(&q__1);
5916// FFEINTRIN_impCOS //
5917 r__1 = cos(r1);
5918 foor_(&r__1);
5919// FFEINTRIN_impCOSH //
5920 r__1 = cosh(r1);
5921 foor_(&r__1);
5922// FFEINTRIN_impCSIN //
5923 c_sin(&q__1, &c1);
5924 fooc_(&q__1);
5925// FFEINTRIN_impCSQRT //
5926 c_sqrt(&q__1, &c1);
5927 fooc_(&q__1);
5928// FFEINTRIN_impDABS //
5929 d__1 = (( d1 ) >= 0 ? ( d1 ) : -( d1 )) ;
5930 food_(&d__1);
5931// FFEINTRIN_impDACOS //
5932 d__1 = acos(d1);
5933 food_(&d__1);
5934// FFEINTRIN_impDASIN //
5935 d__1 = asin(d1);
5936 food_(&d__1);
5937// FFEINTRIN_impDATAN //
5938 d__1 = atan(d1);
5939 food_(&d__1);
5940// FFEINTRIN_impDATAN2 //
5941 d__1 = atan2(d1, d2);
5942 food_(&d__1);
5943// FFEINTRIN_impDCOS //
5944 d__1 = cos(d1);
5945 food_(&d__1);
5946// FFEINTRIN_impDCOSH //
5947 d__1 = cosh(d1);
5948 food_(&d__1);
5949// FFEINTRIN_impDDIM //
5950 d__1 = d_dim(&d1, &d2);
5951 food_(&d__1);
5952// FFEINTRIN_impDEXP //
5953 d__1 = exp(d1);
5954 food_(&d__1);
5955// FFEINTRIN_impDIM //
5956 r__1 = r_dim(&r1, &r2);
5957 foor_(&r__1);
5958// FFEINTRIN_impDINT //
5959 d__1 = d_int(&d1);
5960 food_(&d__1);
5961// FFEINTRIN_impDLOG //
5962 d__1 = log(d1);
5963 food_(&d__1);
5964// FFEINTRIN_impDLOG10 //
5965 d__1 = d_lg10(&d1);
5966 food_(&d__1);
5967// FFEINTRIN_impDMAX1 //
5968 d__1 = (( d1 ) >= ( d2 ) ? ( d1 ) : ( d2 )) ;
5969 food_(&d__1);
5970// FFEINTRIN_impDMIN1 //
5971 d__1 = (( d1 ) <= ( d2 ) ? ( d1 ) : ( d2 )) ;
5972 food_(&d__1);
5973// FFEINTRIN_impDMOD //
5974 d__1 = d_mod(&d1, &d2);
5975 food_(&d__1);
5976// FFEINTRIN_impDNINT //
5977 d__1 = d_nint(&d1);
5978 food_(&d__1);
5979// FFEINTRIN_impDPROD //
5980 d__1 = (doublereal) r1 * r2;
5981 food_(&d__1);
5982// FFEINTRIN_impDSIGN //
5983 d__1 = d_sign(&d1, &d2);
5984 food_(&d__1);
5985// FFEINTRIN_impDSIN //
5986 d__1 = sin(d1);
5987 food_(&d__1);
5988// FFEINTRIN_impDSINH //
5989 d__1 = sinh(d1);
5990 food_(&d__1);
5991// FFEINTRIN_impDSQRT //
5992 d__1 = sqrt(d1);
5993 food_(&d__1);
5994// FFEINTRIN_impDTAN //
5995 d__1 = tan(d1);
5996 food_(&d__1);
5997// FFEINTRIN_impDTANH //
5998 d__1 = tanh(d1);
5999 food_(&d__1);
6000// FFEINTRIN_impEXP //
6001 r__1 = exp(r1);
6002 foor_(&r__1);
6003// FFEINTRIN_impIABS //
6004 i__1 = (( i1 ) >= 0 ? ( i1 ) : -( i1 )) ;
6005 fooi_(&i__1);
6006// FFEINTRIN_impICHAR //
6007 i__1 = *(unsigned char *)a1;
6008 fooi_(&i__1);
6009// FFEINTRIN_impIDIM //
6010 i__1 = i_dim(&i1, &i2);
6011 fooi_(&i__1);
6012// FFEINTRIN_impIDNINT //
6013 i__1 = i_dnnt(&d1);
6014 fooi_(&i__1);
6015// FFEINTRIN_impINDEX //
6016 i__1 = i_indx(a1, a2, 10L, 10L);
6017 fooi_(&i__1);
6018// FFEINTRIN_impISIGN //
6019 i__1 = i_sign(&i1, &i2);
6020 fooi_(&i__1);
6021// FFEINTRIN_impLEN //
6022 i__1 = i_len(a1, 10L);
6023 fooi_(&i__1);
6024// FFEINTRIN_impLGE //
6025 L__1 = l_ge(a1, a2, 10L, 10L);
6026 fool_(&L__1);
6027// FFEINTRIN_impLGT //
6028 L__1 = l_gt(a1, a2, 10L, 10L);
6029 fool_(&L__1);
6030// FFEINTRIN_impLLE //
6031 L__1 = l_le(a1, a2, 10L, 10L);
6032 fool_(&L__1);
6033// FFEINTRIN_impLLT //
6034 L__1 = l_lt(a1, a2, 10L, 10L);
6035 fool_(&L__1);
6036// FFEINTRIN_impMAX0 //
6037 i__1 = (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
6038 fooi_(&i__1);
6039// FFEINTRIN_impMAX1 //
6040 i__1 = (integer) (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
6041 fooi_(&i__1);
6042// FFEINTRIN_impMIN0 //
6043 i__1 = (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
6044 fooi_(&i__1);
6045// FFEINTRIN_impMIN1 //
6046 i__1 = (integer) (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
6047 fooi_(&i__1);
6048// FFEINTRIN_impMOD //
6049 i__1 = i1 % i2;
6050 fooi_(&i__1);
6051// FFEINTRIN_impNINT //
6052 i__1 = i_nint(&r1);
6053 fooi_(&i__1);
6054// FFEINTRIN_impSIGN //
6055 r__1 = r_sign(&r1, &r2);
6056 foor_(&r__1);
6057// FFEINTRIN_impSIN //
6058 r__1 = sin(r1);
6059 foor_(&r__1);
6060// FFEINTRIN_impSINH //
6061 r__1 = sinh(r1);
6062 foor_(&r__1);
6063// FFEINTRIN_impSQRT //
6064 r__1 = sqrt(r1);
6065 foor_(&r__1);
6066// FFEINTRIN_impTAN //
6067 r__1 = tan(r1);
6068 foor_(&r__1);
6069// FFEINTRIN_impTANH //
6070 r__1 = tanh(r1);
6071 foor_(&r__1);
6072// FFEINTRIN_imp_CMPLX_C //
6073 r__1 = c1.r;
6074 r__2 = c2.r;
6075 q__1.r = r__1, q__1.i = r__2;
6076 fooc_(&q__1);
6077// FFEINTRIN_imp_CMPLX_D //
6078 z__1.r = d1, z__1.i = d2;
6079 fooz_(&z__1);
6080// FFEINTRIN_imp_CMPLX_I //
6081 r__1 = (real) i1;
6082 r__2 = (real) i2;
6083 q__1.r = r__1, q__1.i = r__2;
6084 fooc_(&q__1);
6085// FFEINTRIN_imp_CMPLX_R //
6086 q__1.r = r1, q__1.i = r2;
6087 fooc_(&q__1);
6088// FFEINTRIN_imp_DBLE_C //
6089 d__1 = (doublereal) c1.r;
6090 food_(&d__1);
6091// FFEINTRIN_imp_DBLE_D //
6092 d__1 = d1;
6093 food_(&d__1);
6094// FFEINTRIN_imp_DBLE_I //
6095 d__1 = (doublereal) i1;
6096 food_(&d__1);
6097// FFEINTRIN_imp_DBLE_R //
6098 d__1 = (doublereal) r1;
6099 food_(&d__1);
6100// FFEINTRIN_imp_INT_C //
6101 i__1 = (integer) c1.r;
6102 fooi_(&i__1);
6103// FFEINTRIN_imp_INT_D //
6104 i__1 = (integer) d1;
6105 fooi_(&i__1);
6106// FFEINTRIN_imp_INT_I //
6107 i__1 = i1;
6108 fooi_(&i__1);
6109// FFEINTRIN_imp_INT_R //
6110 i__1 = (integer) r1;
6111 fooi_(&i__1);
6112// FFEINTRIN_imp_REAL_C //
6113 r__1 = c1.r;
6114 foor_(&r__1);
6115// FFEINTRIN_imp_REAL_D //
6116 r__1 = (real) d1;
6117 foor_(&r__1);
6118// FFEINTRIN_imp_REAL_I //
6119 r__1 = (real) i1;
6120 foor_(&r__1);
6121// FFEINTRIN_imp_REAL_R //
6122 r__1 = r1;
6123 foor_(&r__1);
6124
6125// FFEINTRIN_imp_INT_D: //
6126
6127// FFEINTRIN_specIDINT //
6128 i__1 = (integer) d1;
6129 fooi_(&i__1);
6130
6131// FFEINTRIN_imp_INT_R: //
6132
6133// FFEINTRIN_specIFIX //
6134 i__1 = (integer) r1;
6135 fooi_(&i__1);
6136// FFEINTRIN_specINT //
6137 i__1 = (integer) r1;
6138 fooi_(&i__1);
6139
6140// FFEINTRIN_imp_REAL_D: //
6141
6142// FFEINTRIN_specSNGL //
6143 r__1 = (real) d1;
6144 foor_(&r__1);
6145
6146// FFEINTRIN_imp_REAL_I: //
6147
6148// FFEINTRIN_specFLOAT //
6149 r__1 = (real) i1;
6150 foor_(&r__1);
6151// FFEINTRIN_specREAL //
6152 r__1 = (real) i1;
6153 foor_(&r__1);
6154
6155} // MAIN__ //
6156
6157-------- (end output file from f2c)
6158
6159*/
6160}
6161
6162#endif
6163/* For power (exponentiation) where right-hand operand is type INTEGER,
6164 generate in-line code to do it the fast way (which, if the operand
6165 is a constant, might just mean a series of multiplies). */
6166
6167#if FFECOM_targetCURRENT == FFECOM_targetGCC
6168static tree
6169ffecom_expr_power_integer_ (ffebld left, ffebld right)
6170{
6171 tree l = ffecom_expr (left);
6172 tree r = ffecom_expr (right);
6173 tree ltype = TREE_TYPE (l);
6174 tree rtype = TREE_TYPE (r);
6175 tree result = NULL_TREE;
6176
6177 if (l == error_mark_node
6178 || r == error_mark_node)
6179 return error_mark_node;
6180
6181 if (TREE_CODE (r) == INTEGER_CST)
6182 {
6183 int sgn = tree_int_cst_sgn (r);
6184
6185 if (sgn == 0)
6186 return convert (ltype, integer_one_node);
6187
6188 if ((TREE_CODE (ltype) == INTEGER_TYPE)
6189 && (sgn < 0))
6190 {
6191 /* Reciprocal of integer is either 0, -1, or 1, so after
6192 calculating that (which we leave to the back end to do
6193 or not do optimally), don't bother with any multiplying. */
6194
6195 result = ffecom_tree_divide_ (ltype,
6196 convert (ltype, integer_one_node),
6197 l,
6198 NULL_TREE, NULL, NULL);
6199 r = ffecom_1 (NEGATE_EXPR,
6200 rtype,
6201 r);
6202 if ((TREE_INT_CST_LOW (r) & 1) == 0)
6203 result = ffecom_1 (ABS_EXPR, rtype,
6204 result);
6205 }
6206
6207 /* Generate appropriate series of multiplies, preceded
6208 by divide if the exponent is negative. */
6209
6210 l = save_expr (l);
6211
6212 if (sgn < 0)
6213 {
6214 l = ffecom_tree_divide_ (ltype,
6215 convert (ltype, integer_one_node),
6216 l,
6217 NULL_TREE, NULL, NULL);
6218 r = ffecom_1 (NEGATE_EXPR, rtype, r);
6219 assert (TREE_CODE (r) == INTEGER_CST);
6220
6221 if (tree_int_cst_sgn (r) < 0)
6222 { /* The "most negative" number. */
6223 r = ffecom_1 (NEGATE_EXPR, rtype,
6224 ffecom_2 (RSHIFT_EXPR, rtype,
6225 r,
6226 integer_one_node));
6227 l = save_expr (l);
6228 l = ffecom_2 (MULT_EXPR, ltype,
6229 l,
6230 l);
6231 }
6232 }
6233
6234 for (;;)
6235 {
6236 if (TREE_INT_CST_LOW (r) & 1)
6237 {
6238 if (result == NULL_TREE)
6239 result = l;
6240 else
6241 result = ffecom_2 (MULT_EXPR, ltype,
6242 result,
6243 l);
6244 }
6245
6246 r = ffecom_2 (RSHIFT_EXPR, rtype,
6247 r,
6248 integer_one_node);
6249 if (integer_zerop (r))
6250 break;
6251 assert (TREE_CODE (r) == INTEGER_CST);
6252
6253 l = save_expr (l);
6254 l = ffecom_2 (MULT_EXPR, ltype,
6255 l,
6256 l);
6257 }
6258 return result;
6259 }
6260
6261 /* Though rhs isn't a constant, in-line code cannot be expanded
6262 while transforming dummies
6263 because the back end cannot be easily convinced to generate
6264 stores (MODIFY_EXPR), handle temporaries, and so on before
6265 all the appropriate rtx's have been generated for things like
6266 dummy args referenced in rhs -- which doesn't happen until
6267 store_parm_decls() is called (expand_function_start, I believe,
6268 does the actual rtx-stuffing of PARM_DECLs).
6269
6270 So, in this case, let the caller generate the call to the
6271 run-time-library function to evaluate the power for us. */
6272
6273 if (ffecom_transform_only_dummies_)
6274 return NULL_TREE;
6275
6276 /* Right-hand operand not a constant, expand in-line code to figure
6277 out how to do the multiplies, &c.
6278
6279 The returned expression is expressed this way in GNU C, where l and
6280 r are the "inputs":
6281
6282 ({ typeof (r) rtmp = r;
44d2eabc
JL
6283 typeof (l) ltmp = l;
6284 typeof (l) result;
5ff904cd
JL
6285
6286 if (rtmp == 0)
6287 result = 1;
6288 else
6289 {
6290 if ((basetypeof (l) == basetypeof (int))
6291 && (rtmp < 0))
6292 {
6293 result = ((typeof (l)) 1) / ltmp;
6294 if ((ltmp < 0) && (((-rtmp) & 1) == 0))
6295 result = -result;
6296 }
6297 else
6298 {
6299 result = 1;
6300 if ((basetypeof (l) != basetypeof (int))
6301 && (rtmp < 0))
6302 {
6303 ltmp = ((typeof (l)) 1) / ltmp;
6304 rtmp = -rtmp;
6305 if (rtmp < 0)
6306 {
6307 rtmp = -(rtmp >> 1);
6308 ltmp *= ltmp;
6309 }
6310 }
6311 for (;;)
6312 {
6313 if (rtmp & 1)
6314 result *= ltmp;
6315 if ((rtmp >>= 1) == 0)
6316 break;
6317 ltmp *= ltmp;
6318 }
6319 }
6320 }
6321 result;
6322 })
6323
6324 Note that some of the above is compile-time collapsable, such as
6325 the first part of the if statements that checks the base type of
6326 l against int. The if statements are phrased that way to suggest
6327 an easy way to generate the if/else constructs here, knowing that
6328 the back end should (and probably does) eliminate the resulting
6329 dead code (either the int case or the non-int case), something
6330 it couldn't do without the redundant phrasing, requiring explicit
6331 dead-code elimination here, which would be kind of difficult to
6332 read. */
6333
6334 {
6335 tree rtmp;
6336 tree ltmp;
6337 tree basetypeof_l_is_int;
6338 tree se;
6339
6340 basetypeof_l_is_int
6341 = build_int_2 ((TREE_CODE (ltype) == INTEGER_TYPE), 0);
6342
6343 se = expand_start_stmt_expr ();
6344 ffecom_push_calltemps ();
6345
6346 rtmp = ffecom_push_tempvar (rtype, FFETARGET_charactersizeNONE, -1,
6347 TRUE);
6348 ltmp = ffecom_push_tempvar (ltype, FFETARGET_charactersizeNONE, -1,
6349 TRUE);
6350 result = ffecom_push_tempvar (ltype, FFETARGET_charactersizeNONE, -1,
6351 TRUE);
6352
6353 expand_expr_stmt (ffecom_modify (void_type_node,
6354 rtmp,
6355 r));
6356 expand_expr_stmt (ffecom_modify (void_type_node,
6357 ltmp,
6358 l));
6359 expand_start_cond (ffecom_truth_value
6360 (ffecom_2 (EQ_EXPR, integer_type_node,
6361 rtmp,
6362 convert (rtype, integer_zero_node))),
6363 0);
6364 expand_expr_stmt (ffecom_modify (void_type_node,
6365 result,
6366 convert (ltype, integer_one_node)));
6367 expand_start_else ();
6368 if (!integer_zerop (basetypeof_l_is_int))
6369 {
6370 expand_start_cond (ffecom_2 (LT_EXPR, integer_type_node,
6371 rtmp,
6372 convert (rtype,
6373 integer_zero_node)),
6374 0);
6375 expand_expr_stmt (ffecom_modify (void_type_node,
6376 result,
6377 ffecom_tree_divide_
6378 (ltype,
6379 convert (ltype, integer_one_node),
6380 ltmp,
6381 NULL_TREE, NULL, NULL)));
6382 expand_start_cond (ffecom_truth_value
6383 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
6384 ffecom_2 (LT_EXPR, integer_type_node,
6385 ltmp,
6386 convert (ltype,
6387 integer_zero_node)),
6388 ffecom_2 (EQ_EXPR, integer_type_node,
6389 ffecom_2 (BIT_AND_EXPR,
6390 rtype,
6391 ffecom_1 (NEGATE_EXPR,
6392 rtype,
6393 rtmp),
6394 convert (rtype,
6395 integer_one_node)),
6396 convert (rtype,
6397 integer_zero_node)))),
6398 0);
6399 expand_expr_stmt (ffecom_modify (void_type_node,
6400 result,
6401 ffecom_1 (NEGATE_EXPR,
6402 ltype,
6403 result)));
6404 expand_end_cond ();
6405 expand_start_else ();
6406 }
6407 expand_expr_stmt (ffecom_modify (void_type_node,
6408 result,
6409 convert (ltype, integer_one_node)));
6410 expand_start_cond (ffecom_truth_value
6411 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
6412 ffecom_truth_value_invert
6413 (basetypeof_l_is_int),
6414 ffecom_2 (LT_EXPR, integer_type_node,
6415 rtmp,
6416 convert (rtype,
6417 integer_zero_node)))),
6418 0);
6419 expand_expr_stmt (ffecom_modify (void_type_node,
6420 ltmp,
6421 ffecom_tree_divide_
6422 (ltype,
6423 convert (ltype, integer_one_node),
6424 ltmp,
6425 NULL_TREE, NULL, NULL)));
6426 expand_expr_stmt (ffecom_modify (void_type_node,
6427 rtmp,
6428 ffecom_1 (NEGATE_EXPR, rtype,
6429 rtmp)));
6430 expand_start_cond (ffecom_truth_value
6431 (ffecom_2 (LT_EXPR, integer_type_node,
6432 rtmp,
6433 convert (rtype, integer_zero_node))),
6434 0);
6435 expand_expr_stmt (ffecom_modify (void_type_node,
6436 rtmp,
6437 ffecom_1 (NEGATE_EXPR, rtype,
6438 ffecom_2 (RSHIFT_EXPR,
6439 rtype,
6440 rtmp,
6441 integer_one_node))));
6442 expand_expr_stmt (ffecom_modify (void_type_node,
6443 ltmp,
6444 ffecom_2 (MULT_EXPR, ltype,
6445 ltmp,
6446 ltmp)));
6447 expand_end_cond ();
6448 expand_end_cond ();
6449 expand_start_loop (1);
6450 expand_start_cond (ffecom_truth_value
6451 (ffecom_2 (BIT_AND_EXPR, rtype,
6452 rtmp,
6453 convert (rtype, integer_one_node))),
6454 0);
6455 expand_expr_stmt (ffecom_modify (void_type_node,
6456 result,
6457 ffecom_2 (MULT_EXPR, ltype,
6458 result,
6459 ltmp)));
6460 expand_end_cond ();
6461 expand_exit_loop_if_false (NULL,
6462 ffecom_truth_value
6463 (ffecom_modify (rtype,
6464 rtmp,
6465 ffecom_2 (RSHIFT_EXPR,
6466 rtype,
6467 rtmp,
6468 integer_one_node))));
6469 expand_expr_stmt (ffecom_modify (void_type_node,
6470 ltmp,
6471 ffecom_2 (MULT_EXPR, ltype,
6472 ltmp,
6473 ltmp)));
6474 expand_end_loop ();
6475 expand_end_cond ();
6476 if (!integer_zerop (basetypeof_l_is_int))
6477 expand_end_cond ();
6478 expand_expr_stmt (result);
6479
6480 ffecom_pop_calltemps ();
6481 result = expand_end_stmt_expr (se);
6482 TREE_SIDE_EFFECTS (result) = 1;
6483 }
6484
6485 return result;
6486}
6487
6488#endif
6489/* ffecom_expr_transform_ -- Transform symbols in expr
6490
6491 ffebld expr; // FFE expression.
6492 ffecom_expr_transform_ (expr);
6493
6494 Recursive descent on expr while transforming any untransformed SYMTERs. */
6495
6496#if FFECOM_targetCURRENT == FFECOM_targetGCC
6497static void
6498ffecom_expr_transform_ (ffebld expr)
6499{
6500 tree t;
6501 ffesymbol s;
6502
6503tail_recurse: /* :::::::::::::::::::: */
6504
6505 if (expr == NULL)
6506 return;
6507
6508 switch (ffebld_op (expr))
6509 {
6510 case FFEBLD_opSYMTER:
6511 s = ffebld_symter (expr);
6512 t = ffesymbol_hook (s).decl_tree;
6513 if ((t == NULL_TREE)
6514 && ((ffesymbol_kind (s) != FFEINFO_kindNONE)
6515 || ((ffesymbol_where (s) != FFEINFO_whereNONE)
6516 && (ffesymbol_where (s) != FFEINFO_whereINTRINSIC))))
6517 {
6518 s = ffecom_sym_transform_ (s);
6519 t = ffesymbol_hook (s).decl_tree; /* Sfunc expr non-dummy,
6520 DIMENSION expr? */
6521 }
6522 break; /* Ok if (t == NULL) here. */
6523
6524 case FFEBLD_opITEM:
6525 ffecom_expr_transform_ (ffebld_head (expr));
6526 expr = ffebld_trail (expr);
6527 goto tail_recurse; /* :::::::::::::::::::: */
6528
6529 default:
6530 break;
6531 }
6532
6533 switch (ffebld_arity (expr))
6534 {
6535 case 2:
6536 ffecom_expr_transform_ (ffebld_left (expr));
6537 expr = ffebld_right (expr);
6538 goto tail_recurse; /* :::::::::::::::::::: */
6539
6540 case 1:
6541 expr = ffebld_left (expr);
6542 goto tail_recurse; /* :::::::::::::::::::: */
6543
6544 default:
6545 break;
6546 }
6547
6548 return;
6549}
6550
6551#endif
6552/* Make a type based on info in live f2c.h file. */
6553
6554#if FFECOM_targetCURRENT == FFECOM_targetGCC
6555static void
6556ffecom_f2c_make_type_ (tree *type, int tcode, char *name)
6557{
6558 switch (tcode)
6559 {
6560 case FFECOM_f2ccodeCHAR:
6561 *type = make_signed_type (CHAR_TYPE_SIZE);
6562 break;
6563
6564 case FFECOM_f2ccodeSHORT:
6565 *type = make_signed_type (SHORT_TYPE_SIZE);
6566 break;
6567
6568 case FFECOM_f2ccodeINT:
6569 *type = make_signed_type (INT_TYPE_SIZE);
6570 break;
6571
6572 case FFECOM_f2ccodeLONG:
6573 *type = make_signed_type (LONG_TYPE_SIZE);
6574 break;
6575
6576 case FFECOM_f2ccodeLONGLONG:
6577 *type = make_signed_type (LONG_LONG_TYPE_SIZE);
6578 break;
6579
6580 case FFECOM_f2ccodeCHARPTR:
6581 *type = build_pointer_type (DEFAULT_SIGNED_CHAR
6582 ? signed_char_type_node
6583 : unsigned_char_type_node);
6584 break;
6585
6586 case FFECOM_f2ccodeFLOAT:
6587 *type = make_node (REAL_TYPE);
6588 TYPE_PRECISION (*type) = FLOAT_TYPE_SIZE;
6589 layout_type (*type);
6590 break;
6591
6592 case FFECOM_f2ccodeDOUBLE:
6593 *type = make_node (REAL_TYPE);
6594 TYPE_PRECISION (*type) = DOUBLE_TYPE_SIZE;
6595 layout_type (*type);
6596 break;
6597
6598 case FFECOM_f2ccodeLONGDOUBLE:
6599 *type = make_node (REAL_TYPE);
6600 TYPE_PRECISION (*type) = LONG_DOUBLE_TYPE_SIZE;
6601 layout_type (*type);
6602 break;
6603
6604 case FFECOM_f2ccodeTWOREALS:
6605 *type = ffecom_make_complex_type_ (ffecom_f2c_real_type_node);
6606 break;
6607
6608 case FFECOM_f2ccodeTWODOUBLEREALS:
6609 *type = ffecom_make_complex_type_ (ffecom_f2c_doublereal_type_node);
6610 break;
6611
6612 default:
6613 assert ("unexpected FFECOM_f2ccodeXYZZY!" == NULL);
6614 *type = error_mark_node;
6615 return;
6616 }
6617
6618 pushdecl (build_decl (TYPE_DECL,
6619 ffecom_get_invented_identifier ("__g77_f2c_%s",
6620 name, 0),
6621 *type));
6622}
6623
6624#endif
6625#if FFECOM_targetCURRENT == FFECOM_targetGCC
6626/* Set the f2c list-directed-I/O code for whatever (integral) type has the
6627 given size. */
6628
6629static void
6630ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
6631 int code)
6632{
6633 int j;
6634 tree t;
6635
6636 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
6637 if (((t = ffecom_tree_type[bt][j]) != NULL_TREE)
6638 && (TREE_INT_CST_LOW (TYPE_SIZE (t)) == size))
6639 {
6640 assert (code != -1);
6641 ffecom_f2c_typecode_[bt][j] = code;
6642 code = -1;
6643 }
6644}
6645
6646#endif
6647/* Finish up globals after doing all program units in file
6648
6649 Need to handle only uninitialized COMMON areas. */
6650
6651#if FFECOM_targetCURRENT == FFECOM_targetGCC
6652static ffeglobal
6653ffecom_finish_global_ (ffeglobal global)
6654{
6655 tree cbtype;
6656 tree cbt;
6657 tree size;
6658
6659 if (ffeglobal_type (global) != FFEGLOBAL_typeCOMMON)
6660 return global;
6661
6662 if (ffeglobal_common_init (global))
6663 return global;
6664
6665 cbt = ffeglobal_hook (global);
6666 if ((cbt == NULL_TREE)
6667 || !ffeglobal_common_have_size (global))
6668 return global; /* No need to make common, never ref'd. */
6669
6670 suspend_momentary ();
6671
6672 DECL_EXTERNAL (cbt) = 0;
6673
6674 /* Give the array a size now. */
6675
a6fa6420
CB
6676 size = build_int_2 ((ffeglobal_common_size (global)
6677 + ffeglobal_common_pad (global)) - 1,
6678 0);
5ff904cd
JL
6679
6680 cbtype = TREE_TYPE (cbt);
6681 TYPE_DOMAIN (cbtype) = build_range_type (integer_type_node,
a6fa6420 6682 integer_zero_node,
5ff904cd
JL
6683 size);
6684 if (!TREE_TYPE (size))
6685 TREE_TYPE (size) = TYPE_DOMAIN (cbtype);
6686 layout_type (cbtype);
6687
6688 cbt = start_decl (cbt, FALSE);
6689 assert (cbt == ffeglobal_hook (global));
6690
6691 finish_decl (cbt, NULL_TREE, FALSE);
6692
6693 return global;
6694}
6695
6696#endif
6697/* Finish up any untransformed symbols. */
6698
6699#if FFECOM_targetCURRENT == FFECOM_targetGCC
6700static ffesymbol
6701ffecom_finish_symbol_transform_ (ffesymbol s)
6702{
56a0044b 6703 if ((s == NULL) || (TREE_CODE (current_function_decl) == ERROR_MARK))
5ff904cd
JL
6704 return s;
6705
6706 /* It's easy to know to transform an untransformed symbol, to make sure
6707 we put out debugging info for it. But COMMON variables, unlike
6708 EQUIVALENCE ones, aren't given declarations in addition to the
6709 tree expressions that specify offsets, because COMMON variables
6710 can be referenced in the outer scope where only dummy arguments
6711 (PARM_DECLs) should really be seen. To be safe, just don't do any
6712 VAR_DECLs for COMMON variables when we transform them for real
6713 use, and therefore we do all the VAR_DECL creating here. */
6714
6829256f
CB
6715 if (ffesymbol_hook (s).decl_tree == NULL_TREE)
6716 {
6717 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT
6718 && (ffesymbol_kind (s) == FFEINFO_kindFUNCTION
6719 || ffesymbol_kind (s) == FFEINFO_kindSUBROUTINE))
6720 {
6721 /* An unreferenced statement function. If this refers to
6722 an undeclared array, it'll look like a reference to
6723 an external function that might not exist. Even if it
6724 does refer to an non-existent function, it seems silly
6725 to force a linker error when the function won't actually
6726 be called. But before the 1998-05-15 change to egcs/gcc
6727 toplev.c by Mark Mitchell, to fix other problems, this
6728 didn't actually happen, since gcc would defer nested
6729 functions to be compiled later only if needed. With that
6730 change, it makes sense to simply avoid telling the back
6731 end about the statement (nested) function at all. But
6732 if -Wunused is specified, might as well warn about it. */
6733
6734 if (warn_unused)
6735 {
6736 ffebad_start (FFEBAD_SFUNC_UNUSED);
6737 ffebad_string (ffesymbol_text (s));
6738 ffebad_here (0, ffesymbol_where_line (s), ffesymbol_where_column (s));
6739 ffebad_finish ();
6740 }
6741 }
6742 else if (ffesymbol_kind (s) != FFEINFO_kindNONE
6743 || (ffesymbol_where (s) != FFEINFO_whereNONE
6744 && ffesymbol_where (s) != FFEINFO_whereINTRINSIC
6745 && ffesymbol_where (s) != FFEINFO_whereDUMMY))
6746 /* Not transformed, and not CHARACTER*(*), and not a dummy
6747 argument, which can happen only if the entry point names
6748 it "rides in on" are all invalidated for other reasons. */
6749 s = ffecom_sym_transform_ (s);
6750 }
5ff904cd
JL
6751
6752 if ((ffesymbol_where (s) == FFEINFO_whereCOMMON)
6753 && (ffesymbol_hook (s).decl_tree != error_mark_node))
6754 {
6755#ifdef SOMEONE_GETS_DEBUG_SUPPORT_WORKING
6756 int yes = suspend_momentary ();
6757
6758 /* This isn't working, at least for dbxout. The .s file looks
6759 okay to me (burley), but in gdb 4.9 at least, the variables
6760 appear to reside somewhere outside of the common area, so
6761 it doesn't make sense to mislead anyone by generating the info
6762 on those variables until this is fixed. NOTE: Same problem
6763 with EQUIVALENCE, sadly...see similar #if later. */
6764 ffecom_member_phase2_ (ffesymbol_storage (ffesymbol_common (s)),
6765 ffesymbol_storage (s));
6766
6767 resume_momentary (yes);
6768#endif
6769 }
6770
6771 return s;
6772}
6773
6774#endif
6775/* Append underscore(s) to name before calling get_identifier. "us"
6776 is nonzero if the name already contains an underscore and thus
6777 needs two underscores appended. */
6778
6779#if FFECOM_targetCURRENT == FFECOM_targetGCC
6780static tree
6781ffecom_get_appended_identifier_ (char us, char *name)
6782{
6783 int i;
6784 char *newname;
6785 tree id;
6786
6787 newname = xmalloc ((i = strlen (name)) + 1
6788 + ffe_is_underscoring ()
6789 + us);
6790 memcpy (newname, name, i);
6791 newname[i] = '_';
6792 newname[i + us] = '_';
6793 newname[i + 1 + us] = '\0';
6794 id = get_identifier (newname);
6795
6796 free (newname);
6797
6798 return id;
6799}
6800
6801#endif
6802/* Decide whether to append underscore to name before calling
6803 get_identifier. */
6804
6805#if FFECOM_targetCURRENT == FFECOM_targetGCC
6806static tree
6807ffecom_get_external_identifier_ (ffesymbol s)
6808{
6809 char us;
6810 char *name = ffesymbol_text (s);
6811
6812 /* If name is a built-in name, just return it as is. */
6813
6814 if (!ffe_is_underscoring ()
6815 || (strcmp (name, FFETARGET_nameBLANK_COMMON) == 0)
6816#if FFETARGET_isENFORCED_MAIN_NAME
6817 || (strcmp (name, FFETARGET_nameENFORCED_NAME) == 0)
6818#else
6819 || (strcmp (name, FFETARGET_nameUNNAMED_MAIN) == 0)
6820#endif
6821 || (strcmp (name, FFETARGET_nameUNNAMED_BLOCK_DATA) == 0))
6822 return get_identifier (name);
6823
6824 us = ffe_is_second_underscore ()
6825 ? (strchr (name, '_') != NULL)
6826 : 0;
6827
6828 return ffecom_get_appended_identifier_ (us, name);
6829}
6830
6831#endif
6832/* Decide whether to append underscore to internal name before calling
6833 get_identifier.
6834
6835 This is for non-external, top-function-context names only. Transform
6836 identifier so it doesn't conflict with the transformed result
6837 of using a _different_ external name. E.g. if "CALL FOO" is
6838 transformed into "FOO_();", then the variable in "FOO_ = 3"
6839 must be transformed into something that does not conflict, since
6840 these two things should be independent.
6841
6842 The transformation is as follows. If the name does not contain
6843 an underscore, there is no possible conflict, so just return.
6844 If the name does contain an underscore, then transform it just
6845 like we transform an external identifier. */
6846
6847#if FFECOM_targetCURRENT == FFECOM_targetGCC
6848static tree
6849ffecom_get_identifier_ (char *name)
6850{
6851 /* If name does not contain an underscore, just return it as is. */
6852
6853 if (!ffe_is_underscoring ()
6854 || (strchr (name, '_') == NULL))
6855 return get_identifier (name);
6856
6857 return ffecom_get_appended_identifier_ (ffe_is_second_underscore (),
6858 name);
6859}
6860
6861#endif
6862/* ffecom_gen_sfuncdef_ -- Generate definition of statement function
6863
6864 tree t;
6865 ffesymbol s; // kindFUNCTION, whereIMMEDIATE.
6866 t = ffecom_gen_sfuncdef_(s,ffesymbol_basictype(s),
6867 ffesymbol_kindtype(s));
6868
6869 Call after setting up containing function and getting trees for all
6870 other symbols. */
6871
6872#if FFECOM_targetCURRENT == FFECOM_targetGCC
6873static tree
6874ffecom_gen_sfuncdef_ (ffesymbol s, ffeinfoBasictype bt, ffeinfoKindtype kt)
6875{
6876 ffebld expr = ffesymbol_sfexpr (s);
6877 tree type;
6878 tree func;
6879 tree result;
6880 bool charfunc = (bt == FFEINFO_basictypeCHARACTER);
6881 static bool recurse = FALSE;
6882 int yes;
6883 int old_lineno = lineno;
6884 char *old_input_filename = input_filename;
6885
6886 ffecom_nested_entry_ = s;
6887
6888 /* For now, we don't have a handy pointer to where the sfunc is actually
6889 defined, though that should be easy to add to an ffesymbol. (The
6890 token/where info available might well point to the place where the type
6891 of the sfunc is declared, especially if that precedes the place where
6892 the sfunc itself is defined, which is typically the case.) We should
6893 put out a null pointer rather than point somewhere wrong, but I want to
6894 see how it works at this point. */
6895
6896 input_filename = ffesymbol_where_filename (s);
6897 lineno = ffesymbol_where_filelinenum (s);
6898
6899 /* Pretransform the expression so any newly discovered things belong to the
6900 outer program unit, not to the statement function. */
6901
6902 ffecom_expr_transform_ (expr);
6903
6904 /* Make sure no recursive invocation of this fn (a specific case of failing
6905 to pretransform an sfunc's expression, i.e. where its expression
6906 references another untransformed sfunc) happens. */
6907
6908 assert (!recurse);
6909 recurse = TRUE;
6910
6911 yes = suspend_momentary ();
6912
6913 push_f_function_context ();
6914
6915 ffecom_push_calltemps ();
6916
6917 if (charfunc)
6918 type = void_type_node;
6919 else
6920 {
6921 type = ffecom_tree_type[bt][kt];
6922 if (type == NULL_TREE)
6923 type = integer_type_node; /* _sym_exec_transition reports
6924 error. */
6925 }
6926
6927 start_function (ffecom_get_identifier_ (ffesymbol_text (s)),
6928 build_function_type (type, NULL_TREE),
6929 1, /* nested/inline */
6930 0); /* TREE_PUBLIC */
6931
6932 /* We don't worry about COMPLEX return values here, because this is
6933 entirely internal to our code, and gcc has the ability to return COMPLEX
6934 directly as a value. */
6935
6936 yes = suspend_momentary ();
6937
6938 if (charfunc)
6939 { /* Prepend arg for where result goes. */
6940 tree type;
6941
6942 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
6943
6944 result = ffecom_get_invented_identifier ("__g77_%s",
6945 "result", 0);
6946
6947 ffecom_char_enhance_arg_ (&type, s); /* Ignore returned length. */
6948
6949 type = build_pointer_type (type);
6950 result = build_decl (PARM_DECL, result, type);
6951
6952 push_parm_decl (result);
6953 }
6954 else
6955 result = NULL_TREE; /* Not ref'd if !charfunc. */
6956
6957 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (s), TRUE);
6958
6959 resume_momentary (yes);
6960
6961 store_parm_decls (0);
6962
6963 ffecom_start_compstmt_ ();
6964
6965 if (expr != NULL)
6966 {
6967 if (charfunc)
6968 {
6969 ffetargetCharacterSize sz = ffesymbol_size (s);
6970 tree result_length;
6971
6972 result_length = build_int_2 (sz, 0);
6973 TREE_TYPE (result_length) = ffecom_f2c_ftnlen_type_node;
6974
6975 ffecom_let_char_ (result, result_length, sz, expr);
6976 expand_null_return ();
6977 }
6978 else
6979 expand_return (ffecom_modify (NULL_TREE,
6980 DECL_RESULT (current_function_decl),
6981 ffecom_expr (expr)));
6982
6983 clear_momentary ();
6984 }
6985
6986 ffecom_end_compstmt_ ();
6987
6988 func = current_function_decl;
6989 finish_function (1);
6990
6991 ffecom_pop_calltemps ();
6992
6993 pop_f_function_context ();
6994
6995 resume_momentary (yes);
6996
6997 recurse = FALSE;
6998
6999 lineno = old_lineno;
7000 input_filename = old_input_filename;
7001
7002 ffecom_nested_entry_ = NULL;
7003
7004 return func;
7005}
7006
7007#endif
7008
7009#if FFECOM_targetCURRENT == FFECOM_targetGCC
7010static char *
7011ffecom_gfrt_args_ (ffecomGfrt ix)
7012{
7013 return ffecom_gfrt_argstring_[ix];
7014}
7015
7016#endif
7017#if FFECOM_targetCURRENT == FFECOM_targetGCC
7018static tree
7019ffecom_gfrt_tree_ (ffecomGfrt ix)
7020{
7021 if (ffecom_gfrt_[ix] == NULL_TREE)
7022 ffecom_make_gfrt_ (ix);
7023
7024 return ffecom_1 (ADDR_EXPR,
7025 build_pointer_type (TREE_TYPE (ffecom_gfrt_[ix])),
7026 ffecom_gfrt_[ix]);
7027}
7028
7029#endif
7030/* Return initialize-to-zero expression for this VAR_DECL. */
7031
7032#if FFECOM_targetCURRENT == FFECOM_targetGCC
7033static tree
7034ffecom_init_zero_ (tree decl)
7035{
7036 tree init;
7037 int incremental = TREE_STATIC (decl);
7038 tree type = TREE_TYPE (decl);
7039
7040 if (incremental)
7041 {
7042 int momentary = suspend_momentary ();
7043 push_obstacks_nochange ();
7044 if (TREE_PERMANENT (decl))
7045 end_temporary_allocation ();
7046 make_decl_rtl (decl, NULL, TREE_PUBLIC (decl) ? 1 : 0);
7047 assemble_variable (decl, TREE_PUBLIC (decl) ? 1 : 0, 0, 1);
7048 pop_obstacks ();
7049 resume_momentary (momentary);
7050 }
7051
7052 push_momentary ();
7053
7054 if ((TREE_CODE (type) != ARRAY_TYPE)
7055 && (TREE_CODE (type) != RECORD_TYPE)
7056 && (TREE_CODE (type) != UNION_TYPE)
7057 && !incremental)
7058 init = convert (type, integer_zero_node);
7059 else if (!incremental)
7060 {
7061 int momentary = suspend_momentary ();
7062
7063 init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
7064 TREE_CONSTANT (init) = 1;
7065 TREE_STATIC (init) = 1;
7066
7067 resume_momentary (momentary);
7068 }
7069 else
7070 {
7071 int momentary = suspend_momentary ();
7072
7073 assemble_zeros (int_size_in_bytes (type));
7074 init = error_mark_node;
7075
7076 resume_momentary (momentary);
7077 }
7078
7079 pop_momentary_nofree ();
7080
7081 return init;
7082}
7083
7084#endif
7085#if FFECOM_targetCURRENT == FFECOM_targetGCC
7086static tree
7087ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
7088 tree *maybe_tree)
7089{
7090 tree expr_tree;
7091 tree length_tree;
7092
7093 switch (ffebld_op (arg))
7094 {
7095 case FFEBLD_opCONTER: /* For F90, check 0-length. */
7096 if (ffetarget_length_character1
7097 (ffebld_constant_character1
7098 (ffebld_conter (arg))) == 0)
7099 {
7100 *maybe_tree = integer_zero_node;
7101 return convert (tree_type, integer_zero_node);
7102 }
7103
7104 *maybe_tree = integer_one_node;
7105 expr_tree = build_int_2 (*ffetarget_text_character1
7106 (ffebld_constant_character1
7107 (ffebld_conter (arg))),
7108 0);
7109 TREE_TYPE (expr_tree) = tree_type;
7110 return expr_tree;
7111
7112 case FFEBLD_opSYMTER:
7113 case FFEBLD_opARRAYREF:
7114 case FFEBLD_opFUNCREF:
7115 case FFEBLD_opSUBSTR:
7116 ffecom_push_calltemps ();
7117 ffecom_char_args_ (&expr_tree, &length_tree, arg);
7118 ffecom_pop_calltemps ();
7119
7120 if ((expr_tree == error_mark_node)
7121 || (length_tree == error_mark_node))
7122 {
7123 *maybe_tree = error_mark_node;
7124 return error_mark_node;
7125 }
7126
7127 if (integer_zerop (length_tree))
7128 {
7129 *maybe_tree = integer_zero_node;
7130 return convert (tree_type, integer_zero_node);
7131 }
7132
7133 expr_tree
7134 = ffecom_1 (INDIRECT_REF,
7135 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
7136 expr_tree);
7137 expr_tree
7138 = ffecom_2 (ARRAY_REF,
7139 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
7140 expr_tree,
7141 integer_one_node);
7142 expr_tree = convert (tree_type, expr_tree);
7143
7144 if (TREE_CODE (length_tree) == INTEGER_CST)
7145 *maybe_tree = integer_one_node;
7146 else /* Must check length at run time. */
7147 *maybe_tree
7148 = ffecom_truth_value
7149 (ffecom_2 (GT_EXPR, integer_type_node,
7150 length_tree,
7151 ffecom_f2c_ftnlen_zero_node));
7152 return expr_tree;
7153
7154 case FFEBLD_opPAREN:
7155 case FFEBLD_opCONVERT:
7156 if (ffeinfo_size (ffebld_info (arg)) == 0)
7157 {
7158 *maybe_tree = integer_zero_node;
7159 return convert (tree_type, integer_zero_node);
7160 }
7161 return ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
7162 maybe_tree);
7163
7164 case FFEBLD_opCONCATENATE:
7165 {
7166 tree maybe_left;
7167 tree maybe_right;
7168 tree expr_left;
7169 tree expr_right;
7170
7171 expr_left = ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
7172 &maybe_left);
7173 expr_right = ffecom_intrinsic_ichar_ (tree_type, ffebld_right (arg),
7174 &maybe_right);
7175 *maybe_tree = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
7176 maybe_left,
7177 maybe_right);
7178 expr_tree = ffecom_3 (COND_EXPR, tree_type,
7179 maybe_left,
7180 expr_left,
7181 expr_right);
7182 return expr_tree;
7183 }
7184
7185 default:
7186 assert ("bad op in ICHAR" == NULL);
7187 return error_mark_node;
7188 }
7189}
7190
7191#endif
7192/* ffecom_intrinsic_len_ -- Return length info for char arg (LEN())
7193
7194 tree length_arg;
7195 ffebld expr;
7196 length_arg = ffecom_intrinsic_len_ (expr);
7197
7198 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
7199 subexpressions by constructing the appropriate tree for the
7200 length-of-character-text argument in a calling sequence. */
7201
7202#if FFECOM_targetCURRENT == FFECOM_targetGCC
7203static tree
7204ffecom_intrinsic_len_ (ffebld expr)
7205{
7206 ffetargetCharacter1 val;
7207 tree length;
7208
7209 switch (ffebld_op (expr))
7210 {
7211 case FFEBLD_opCONTER:
7212 val = ffebld_constant_character1 (ffebld_conter (expr));
7213 length = build_int_2 (ffetarget_length_character1 (val), 0);
7214 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
7215 break;
7216
7217 case FFEBLD_opSYMTER:
7218 {
7219 ffesymbol s = ffebld_symter (expr);
7220 tree item;
7221
7222 item = ffesymbol_hook (s).decl_tree;
7223 if (item == NULL_TREE)
7224 {
7225 s = ffecom_sym_transform_ (s);
7226 item = ffesymbol_hook (s).decl_tree;
7227 }
7228 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
7229 {
7230 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
7231 length = ffesymbol_hook (s).length_tree;
7232 else
7233 {
7234 length = build_int_2 (ffesymbol_size (s), 0);
7235 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
7236 }
7237 }
7238 else if (item == error_mark_node)
7239 length = error_mark_node;
7240 else /* FFEINFO_kindFUNCTION: */
7241 length = NULL_TREE;
7242 }
7243 break;
7244
7245 case FFEBLD_opARRAYREF:
7246 length = ffecom_intrinsic_len_ (ffebld_left (expr));
7247 break;
7248
7249 case FFEBLD_opSUBSTR:
7250 {
7251 ffebld start;
7252 ffebld end;
7253 ffebld thing = ffebld_right (expr);
7254 tree start_tree;
7255 tree end_tree;
7256
7257 assert (ffebld_op (thing) == FFEBLD_opITEM);
7258 start = ffebld_head (thing);
7259 thing = ffebld_trail (thing);
7260 assert (ffebld_trail (thing) == NULL);
7261 end = ffebld_head (thing);
7262
7263 length = ffecom_intrinsic_len_ (ffebld_left (expr));
7264
7265 if (length == error_mark_node)
7266 break;
7267
7268 if (start == NULL)
7269 {
7270 if (end == NULL)
7271 ;
7272 else
7273 {
7274 length = convert (ffecom_f2c_ftnlen_type_node,
7275 ffecom_expr (end));
7276 }
7277 }
7278 else
7279 {
7280 start_tree = convert (ffecom_f2c_ftnlen_type_node,
7281 ffecom_expr (start));
7282
7283 if (start_tree == error_mark_node)
7284 {
7285 length = error_mark_node;
7286 break;
7287 }
7288
7289 if (end == NULL)
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 length,
7296 start_tree));
7297 }
7298 else
7299 {
7300 end_tree = convert (ffecom_f2c_ftnlen_type_node,
7301 ffecom_expr (end));
7302
7303 if (end_tree == error_mark_node)
7304 {
7305 length = error_mark_node;
7306 break;
7307 }
7308
7309 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
7310 ffecom_f2c_ftnlen_one_node,
7311 ffecom_2 (MINUS_EXPR,
7312 ffecom_f2c_ftnlen_type_node,
7313 end_tree, start_tree));
7314 }
7315 }
7316 }
7317 break;
7318
7319 case FFEBLD_opCONCATENATE:
7320 length
7321 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
7322 ffecom_intrinsic_len_ (ffebld_left (expr)),
7323 ffecom_intrinsic_len_ (ffebld_right (expr)));
7324 break;
7325
7326 case FFEBLD_opFUNCREF:
7327 case FFEBLD_opCONVERT:
7328 length = build_int_2 (ffebld_size (expr), 0);
7329 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
7330 break;
7331
7332 default:
7333 assert ("bad op for single char arg expr" == NULL);
7334 length = ffecom_f2c_ftnlen_zero_node;
7335 break;
7336 }
7337
7338 assert (length != NULL_TREE);
7339
7340 return length;
7341}
7342
7343#endif
7344/* ffecom_let_char_ -- Do assignment stuff for character type
7345
7346 tree dest_tree; // destination (ADDR_EXPR)
7347 tree dest_length; // length (INT_CST/INDIRECT_REF(PARM_DECL))
7348 ffetargetCharacterSize dest_size; // length
7349 ffebld source; // source expression
7350 ffecom_let_char_(dest_tree,dest_length,dest_size,source);
7351
7352 Generates code to do the assignment. Used by ordinary assignment
7353 statement handler ffecom_let_stmt and by statement-function
7354 handler to generate code for a statement function. */
7355
7356#if FFECOM_targetCURRENT == FFECOM_targetGCC
7357static void
7358ffecom_let_char_ (tree dest_tree, tree dest_length,
7359 ffetargetCharacterSize dest_size, ffebld source)
7360{
7361 ffecomConcatList_ catlist;
7362 tree source_length;
7363 tree source_tree;
7364 tree expr_tree;
7365
7366 if ((dest_tree == error_mark_node)
7367 || (dest_length == error_mark_node))
7368 return;
7369
7370 assert (dest_tree != NULL_TREE);
7371 assert (dest_length != NULL_TREE);
7372
7373 /* Source might be an opCONVERT, which just means it is a different size
7374 than the destination. Since the underlying implementation here handles
7375 that (directly or via the s_copy or s_cat run-time-library functions),
7376 we don't need the "convenience" of an opCONVERT that tells us to
7377 truncate or blank-pad, particularly since the resulting implementation
7378 would probably be slower than otherwise. */
7379
7380 while (ffebld_op (source) == FFEBLD_opCONVERT)
7381 source = ffebld_left (source);
7382
7383 catlist = ffecom_concat_list_new_ (source, dest_size);
7384 switch (ffecom_concat_list_count_ (catlist))
7385 {
7386 case 0: /* Shouldn't happen, but in case it does... */
7387 ffecom_concat_list_kill_ (catlist);
7388 source_tree = null_pointer_node;
7389 source_length = ffecom_f2c_ftnlen_zero_node;
7390 expr_tree = build_tree_list (NULL_TREE, dest_tree);
7391 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
7392 TREE_CHAIN (TREE_CHAIN (expr_tree))
7393 = build_tree_list (NULL_TREE, dest_length);
7394 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
7395 = build_tree_list (NULL_TREE, source_length);
7396
7397 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree);
7398 TREE_SIDE_EFFECTS (expr_tree) = 1;
7399
7400 expand_expr_stmt (expr_tree);
7401
7402 return;
7403
7404 case 1: /* The (fairly) easy case. */
7405 ffecom_char_args_ (&source_tree, &source_length,
7406 ffecom_concat_list_expr_ (catlist, 0));
7407 ffecom_concat_list_kill_ (catlist);
7408 assert (source_tree != NULL_TREE);
7409 assert (source_length != NULL_TREE);
7410
7411 if ((source_tree == error_mark_node)
7412 || (source_length == error_mark_node))
7413 return;
7414
7415 if (dest_size == 1)
7416 {
7417 dest_tree
7418 = ffecom_1 (INDIRECT_REF,
7419 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
7420 (dest_tree))),
7421 dest_tree);
7422 dest_tree
7423 = ffecom_2 (ARRAY_REF,
7424 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
7425 (dest_tree))),
7426 dest_tree,
7427 integer_one_node);
7428 source_tree
7429 = ffecom_1 (INDIRECT_REF,
7430 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
7431 (source_tree))),
7432 source_tree);
7433 source_tree
7434 = ffecom_2 (ARRAY_REF,
7435 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
7436 (source_tree))),
7437 source_tree,
7438 integer_one_node);
7439
7440 expr_tree = ffecom_modify (void_type_node, dest_tree, source_tree);
7441
7442 expand_expr_stmt (expr_tree);
7443
7444 return;
7445 }
7446
7447 expr_tree = build_tree_list (NULL_TREE, dest_tree);
7448 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
7449 TREE_CHAIN (TREE_CHAIN (expr_tree))
7450 = build_tree_list (NULL_TREE, dest_length);
7451 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
7452 = build_tree_list (NULL_TREE, source_length);
7453
7454 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree);
7455 TREE_SIDE_EFFECTS (expr_tree) = 1;
7456
7457 expand_expr_stmt (expr_tree);
7458
7459 return;
7460
7461 default: /* Must actually concatenate things. */
7462 break;
7463 }
7464
7465 /* Heavy-duty concatenation. */
7466
7467 {
7468 int count = ffecom_concat_list_count_ (catlist);
7469 int i;
7470 tree lengths;
7471 tree items;
7472 tree length_array;
7473 tree item_array;
7474 tree citem;
7475 tree clength;
7476
7477 length_array
7478 = lengths
7479 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
7480 FFETARGET_charactersizeNONE, count, TRUE);
7481 item_array = items = ffecom_push_tempvar (ffecom_f2c_address_type_node,
7482 FFETARGET_charactersizeNONE,
7483 count, TRUE);
7484
7485 for (i = 0; i < count; ++i)
7486 {
7487 ffecom_char_args_ (&citem, &clength,
7488 ffecom_concat_list_expr_ (catlist, i));
7489 if ((citem == error_mark_node)
7490 || (clength == error_mark_node))
7491 {
7492 ffecom_concat_list_kill_ (catlist);
7493 return;
7494 }
7495
7496 items
7497 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
7498 ffecom_modify (void_type_node,
7499 ffecom_2 (ARRAY_REF,
7500 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
7501 item_array,
7502 build_int_2 (i, 0)),
7503 citem),
7504 items);
7505 lengths
7506 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
7507 ffecom_modify (void_type_node,
7508 ffecom_2 (ARRAY_REF,
7509 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
7510 length_array,
7511 build_int_2 (i, 0)),
7512 clength),
7513 lengths);
7514 }
7515
7516 expr_tree = build_tree_list (NULL_TREE, dest_tree);
7517 TREE_CHAIN (expr_tree)
7518 = build_tree_list (NULL_TREE,
7519 ffecom_1 (ADDR_EXPR,
7520 build_pointer_type (TREE_TYPE (items)),
7521 items));
7522 TREE_CHAIN (TREE_CHAIN (expr_tree))
7523 = build_tree_list (NULL_TREE,
7524 ffecom_1 (ADDR_EXPR,
7525 build_pointer_type (TREE_TYPE (lengths)),
7526 lengths));
7527 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
7528 = build_tree_list
7529 (NULL_TREE,
7530 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
7531 convert (ffecom_f2c_ftnlen_type_node,
7532 build_int_2 (count, 0))));
7533 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree))))
7534 = build_tree_list (NULL_TREE, dest_length);
7535
7536 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCAT, expr_tree);
7537 TREE_SIDE_EFFECTS (expr_tree) = 1;
7538
7539 expand_expr_stmt (expr_tree);
7540 }
7541
7542 ffecom_concat_list_kill_ (catlist);
7543}
7544
7545#endif
7546/* ffecom_make_gfrt_ -- Make initial info for run-time routine
7547
7548 ffecomGfrt ix;
7549 ffecom_make_gfrt_(ix);
7550
7551 Assumes gfrt_[ix] is NULL_TREE, and replaces it with the FUNCTION_DECL
7552 for the indicated run-time routine (ix). */
7553
7554#if FFECOM_targetCURRENT == FFECOM_targetGCC
7555static void
7556ffecom_make_gfrt_ (ffecomGfrt ix)
7557{
7558 tree t;
7559 tree ttype;
7560
7561 push_obstacks_nochange ();
7562 end_temporary_allocation ();
7563
7564 switch (ffecom_gfrt_type_[ix])
7565 {
7566 case FFECOM_rttypeVOID_:
7567 ttype = void_type_node;
7568 break;
7569
6d433196
CB
7570 case FFECOM_rttypeVOIDSTAR_:
7571 ttype = TREE_TYPE (null_pointer_node); /* `void *'. */
7572 break;
7573
795232f7
JL
7574 case FFECOM_rttypeFTNINT_:
7575 ttype = ffecom_f2c_ftnint_type_node;
5ff904cd
JL
7576 break;
7577
7578 case FFECOM_rttypeINTEGER_:
7579 ttype = ffecom_f2c_integer_type_node;
7580 break;
7581
7582 case FFECOM_rttypeLONGINT_:
7583 ttype = ffecom_f2c_longint_type_node;
7584 break;
7585
7586 case FFECOM_rttypeLOGICAL_:
7587 ttype = ffecom_f2c_logical_type_node;
7588 break;
7589
7590 case FFECOM_rttypeREAL_F2C_:
795232f7 7591 ttype = double_type_node;
5ff904cd
JL
7592 break;
7593
7594 case FFECOM_rttypeREAL_GNU_:
795232f7 7595 ttype = float_type_node;
5ff904cd
JL
7596 break;
7597
7598 case FFECOM_rttypeCOMPLEX_F2C_:
7599 ttype = void_type_node;
7600 break;
7601
7602 case FFECOM_rttypeCOMPLEX_GNU_:
7603 ttype = ffecom_f2c_complex_type_node;
7604 break;
7605
7606 case FFECOM_rttypeDOUBLE_:
7607 ttype = double_type_node;
7608 break;
7609
795232f7
JL
7610 case FFECOM_rttypeDOUBLEREAL_:
7611 ttype = ffecom_f2c_doublereal_type_node;
7612 break;
7613
5ff904cd
JL
7614 case FFECOM_rttypeDBLCMPLX_F2C_:
7615 ttype = void_type_node;
7616 break;
7617
7618 case FFECOM_rttypeDBLCMPLX_GNU_:
7619 ttype = ffecom_f2c_doublecomplex_type_node;
7620 break;
7621
7622 case FFECOM_rttypeCHARACTER_:
7623 ttype = void_type_node;
7624 break;
7625
7626 default:
7627 ttype = NULL;
7628 assert ("bad rttype" == NULL);
7629 break;
7630 }
7631
7632 ttype = build_function_type (ttype, NULL_TREE);
7633 t = build_decl (FUNCTION_DECL,
7634 get_identifier (ffecom_gfrt_name_[ix]),
7635 ttype);
7636 DECL_EXTERNAL (t) = 1;
7637 TREE_PUBLIC (t) = 1;
7638 TREE_THIS_VOLATILE (t) = ffecom_gfrt_volatile_[ix] ? 1 : 0;
7639
7640 t = start_decl (t, TRUE);
7641
7642 finish_decl (t, NULL_TREE, TRUE);
7643
7644 resume_temporary_allocation ();
7645 pop_obstacks ();
7646
7647 ffecom_gfrt_[ix] = t;
7648}
7649
7650#endif
7651/* Phase 1 pass over each member of a COMMON/EQUIVALENCE group. */
7652
7653#if FFECOM_targetCURRENT == FFECOM_targetGCC
7654static void
7655ffecom_member_phase1_ (ffestorag mst UNUSED, ffestorag st)
7656{
7657 ffesymbol s = ffestorag_symbol (st);
7658
7659 if (ffesymbol_namelisted (s))
7660 ffecom_member_namelisted_ = TRUE;
7661}
7662
7663#endif
7664/* Phase 2 pass over each member of a COMMON/EQUIVALENCE group. Declare
7665 the member so debugger will see it. Otherwise nobody should be
7666 referencing the member. */
7667
7668#if FFECOM_targetCURRENT == FFECOM_targetGCC
7669#ifdef SOMEONE_GETS_DEBUG_SUPPORT_WORKING
7670static void
7671ffecom_member_phase2_ (ffestorag mst, ffestorag st)
7672{
7673 ffesymbol s;
7674 tree t;
7675 tree mt;
7676 tree type;
7677
7678 if ((mst == NULL)
7679 || ((mt = ffestorag_hook (mst)) == NULL)
7680 || (mt == error_mark_node))
7681 return;
7682
7683 if ((st == NULL)
7684 || ((s = ffestorag_symbol (st)) == NULL))
7685 return;
7686
7687 type = ffecom_type_localvar_ (s,
7688 ffesymbol_basictype (s),
7689 ffesymbol_kindtype (s));
7690 if (type == error_mark_node)
7691 return;
7692
7693 t = build_decl (VAR_DECL,
7694 ffecom_get_identifier_ (ffesymbol_text (s)),
7695 type);
7696
7697 TREE_STATIC (t) = TREE_STATIC (mt);
7698 DECL_INITIAL (t) = NULL_TREE;
7699 TREE_ASM_WRITTEN (t) = 1;
7700
7701 DECL_RTL (t)
7702 = gen_rtx (MEM, TYPE_MODE (type),
7703 plus_constant (XEXP (DECL_RTL (mt), 0),
7704 ffestorag_modulo (mst)
7705 + ffestorag_offset (st)
7706 - ffestorag_offset (mst)));
7707
7708 t = start_decl (t, FALSE);
7709
7710 finish_decl (t, NULL_TREE, FALSE);
7711}
7712
7713#endif
7714#endif
7715/* ffecom_push_dummy_decls_ -- Transform dummy args, push parm decls in order
7716
7717 Ignores STAR (alternate-return) dummies. All other get exec-transitioned
7718 (which generates their trees) and then their trees get push_parm_decl'd.
7719
7720 The second arg is TRUE if the dummies are for a statement function, in
7721 which case lengths are not pushed for character arguments (since they are
7722 always known by both the caller and the callee, though the code allows
7723 for someday permitting CHAR*(*) stmtfunc dummies). */
7724
7725#if FFECOM_targetCURRENT == FFECOM_targetGCC
7726static void
7727ffecom_push_dummy_decls_ (ffebld dummy_list, bool stmtfunc)
7728{
7729 ffebld dummy;
7730 ffebld dumlist;
7731 ffesymbol s;
7732 tree parm;
7733
7734 ffecom_transform_only_dummies_ = TRUE;
7735
7736 /* First push the parms corresponding to actual dummy "contents". */
7737
7738 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7739 {
7740 dummy = ffebld_head (dumlist);
7741 switch (ffebld_op (dummy))
7742 {
7743 case FFEBLD_opSTAR:
7744 case FFEBLD_opANY:
7745 continue; /* Forget alternate returns. */
7746
7747 default:
7748 break;
7749 }
7750 assert (ffebld_op (dummy) == FFEBLD_opSYMTER);
7751 s = ffebld_symter (dummy);
7752 parm = ffesymbol_hook (s).decl_tree;
7753 if (parm == NULL_TREE)
7754 {
7755 s = ffecom_sym_transform_ (s);
7756 parm = ffesymbol_hook (s).decl_tree;
7757 assert (parm != NULL_TREE);
7758 }
7759 if (parm != error_mark_node)
7760 push_parm_decl (parm);
7761 }
7762
7763 /* Then, for CHARACTER dummies, push the parms giving their lengths. */
7764
7765 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7766 {
7767 dummy = ffebld_head (dumlist);
7768 switch (ffebld_op (dummy))
7769 {
7770 case FFEBLD_opSTAR:
7771 case FFEBLD_opANY:
7772 continue; /* Forget alternate returns, they mean
7773 NOTHING! */
7774
7775 default:
7776 break;
7777 }
7778 s = ffebld_symter (dummy);
7779 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
7780 continue; /* Only looking for CHARACTER arguments. */
7781 if (stmtfunc && (ffesymbol_size (s) != FFETARGET_charactersizeNONE))
7782 continue; /* Stmtfunc arg with known size needs no
7783 length param. */
7784 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
7785 continue; /* Only looking for variables and arrays. */
7786 parm = ffesymbol_hook (s).length_tree;
7787 assert (parm != NULL_TREE);
7788 if (parm != error_mark_node)
7789 push_parm_decl (parm);
7790 }
7791
7792 ffecom_transform_only_dummies_ = FALSE;
7793}
7794
7795#endif
7796/* ffecom_start_progunit_ -- Beginning of program unit
7797
7798 Does GNU back end stuff necessary to teach it about the start of its
7799 equivalent of a Fortran program unit. */
7800
7801#if FFECOM_targetCURRENT == FFECOM_targetGCC
7802static void
7803ffecom_start_progunit_ ()
7804{
7805 ffesymbol fn = ffecom_primary_entry_;
7806 ffebld arglist;
7807 tree id; /* Identifier (name) of function. */
7808 tree type; /* Type of function. */
7809 tree result; /* Result of function. */
7810 ffeinfoBasictype bt;
7811 ffeinfoKindtype kt;
7812 ffeglobal g;
7813 ffeglobalType gt;
7814 ffeglobalType egt = FFEGLOBAL_type;
7815 bool charfunc;
7816 bool cmplxfunc;
7817 bool altentries = (ffecom_num_entrypoints_ != 0);
7818 bool multi
7819 = altentries
7820 && (ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
7821 && (ffecom_master_bt_ == FFEINFO_basictypeNONE);
7822 bool main_program = FALSE;
7823 int old_lineno = lineno;
7824 char *old_input_filename = input_filename;
7825 int yes;
7826
7827 assert (fn != NULL);
7828 assert (ffesymbol_hook (fn).decl_tree == NULL_TREE);
7829
7830 input_filename = ffesymbol_where_filename (fn);
7831 lineno = ffesymbol_where_filelinenum (fn);
7832
7833 /* c-parse.y indeed does call suspend_momentary and not only ignores the
7834 return value, but also never calls resume_momentary, when starting an
7835 outer function (see "fndef:", "setspecs:", and so on). So g77 does the
7836 same thing. It shouldn't be a problem since start_function calls
7837 temporary_allocation, but it might be necessary. If it causes a problem
7838 here, then maybe there's a bug lurking in gcc. NOTE: This identical
7839 comment appears twice in thist file. */
7840
7841 suspend_momentary ();
7842
7843 switch (ffecom_primary_entry_kind_)
7844 {
7845 case FFEINFO_kindPROGRAM:
7846 main_program = TRUE;
7847 gt = FFEGLOBAL_typeMAIN;
7848 bt = FFEINFO_basictypeNONE;
7849 kt = FFEINFO_kindtypeNONE;
7850 type = ffecom_tree_fun_type_void;
7851 charfunc = FALSE;
7852 cmplxfunc = FALSE;
7853 break;
7854
7855 case FFEINFO_kindBLOCKDATA:
7856 gt = FFEGLOBAL_typeBDATA;
7857 bt = FFEINFO_basictypeNONE;
7858 kt = FFEINFO_kindtypeNONE;
7859 type = ffecom_tree_fun_type_void;
7860 charfunc = FALSE;
7861 cmplxfunc = FALSE;
7862 break;
7863
7864 case FFEINFO_kindFUNCTION:
7865 gt = FFEGLOBAL_typeFUNC;
7866 egt = FFEGLOBAL_typeEXT;
7867 bt = ffesymbol_basictype (fn);
7868 kt = ffesymbol_kindtype (fn);
7869 if (bt == FFEINFO_basictypeNONE)
7870 {
7871 ffeimplic_establish_symbol (fn);
7872 if (ffesymbol_funcresult (fn) != NULL)
7873 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
7874 bt = ffesymbol_basictype (fn);
7875 kt = ffesymbol_kindtype (fn);
7876 }
7877
7878 if (multi)
7879 charfunc = cmplxfunc = FALSE;
7880 else if (bt == FFEINFO_basictypeCHARACTER)
7881 charfunc = TRUE, cmplxfunc = FALSE;
7882 else if ((bt == FFEINFO_basictypeCOMPLEX)
7883 && ffesymbol_is_f2c (fn)
7884 && !altentries)
7885 charfunc = FALSE, cmplxfunc = TRUE;
7886 else
7887 charfunc = cmplxfunc = FALSE;
7888
7889 if (multi || charfunc)
7890 type = ffecom_tree_fun_type_void;
7891 else if (ffesymbol_is_f2c (fn) && !altentries)
7892 type = ffecom_tree_fun_type[bt][kt];
7893 else
7894 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
7895
7896 if ((type == NULL_TREE)
7897 || (TREE_TYPE (type) == NULL_TREE))
7898 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
7899 break;
7900
7901 case FFEINFO_kindSUBROUTINE:
7902 gt = FFEGLOBAL_typeSUBR;
7903 egt = FFEGLOBAL_typeEXT;
7904 bt = FFEINFO_basictypeNONE;
7905 kt = FFEINFO_kindtypeNONE;
7906 if (ffecom_is_altreturning_)
7907 type = ffecom_tree_subr_type;
7908 else
7909 type = ffecom_tree_fun_type_void;
7910 charfunc = FALSE;
7911 cmplxfunc = FALSE;
7912 break;
7913
7914 default:
7915 assert ("say what??" == NULL);
7916 /* Fall through. */
7917 case FFEINFO_kindANY:
7918 gt = FFEGLOBAL_typeANY;
7919 bt = FFEINFO_basictypeNONE;
7920 kt = FFEINFO_kindtypeNONE;
7921 type = error_mark_node;
7922 charfunc = FALSE;
7923 cmplxfunc = FALSE;
7924 break;
7925 }
7926
7927 if (altentries)
44d2eabc
JL
7928 {
7929 id = ffecom_get_invented_identifier ("__g77_masterfun_%s",
7930 ffesymbol_text (fn),
7931 0);
44d2eabc 7932 }
5ff904cd
JL
7933#if FFETARGET_isENFORCED_MAIN
7934 else if (main_program)
7935 id = get_identifier (FFETARGET_nameENFORCED_MAIN_NAME);
7936#endif
7937 else
7938 id = ffecom_get_external_identifier_ (fn);
7939
7940 start_function (id,
7941 type,
7942 0, /* nested/inline */
7943 !altentries); /* TREE_PUBLIC */
7944
3cf0cea4
CB
7945 TREE_USED (current_function_decl) = 1; /* Avoid spurious warning if altentries. */
7946
5ff904cd
JL
7947 if (!altentries
7948 && ((g = ffesymbol_global (fn)) != NULL)
7949 && ((ffeglobal_type (g) == gt)
7950 || (ffeglobal_type (g) == egt)))
7951 {
7952 ffeglobal_set_hook (g, current_function_decl);
7953 }
7954
7955 yes = suspend_momentary ();
7956
7957 /* Arg handling needs exec-transitioned ffesymbols to work with. But
7958 exec-transitioning needs current_function_decl to be filled in. So we
7959 do these things in two phases. */
7960
7961 if (altentries)
7962 { /* 1st arg identifies which entrypoint. */
7963 ffecom_which_entrypoint_decl_
7964 = build_decl (PARM_DECL,
7965 ffecom_get_invented_identifier ("__g77_%s",
7966 "which_entrypoint",
7967 0),
7968 integer_type_node);
7969 push_parm_decl (ffecom_which_entrypoint_decl_);
7970 }
7971
7972 if (charfunc
7973 || cmplxfunc
7974 || multi)
7975 { /* Arg for result (return value). */
7976 tree type;
7977 tree length;
7978
7979 if (charfunc)
7980 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
7981 else if (cmplxfunc)
7982 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
7983 else
7984 type = ffecom_multi_type_node_;
7985
7986 result = ffecom_get_invented_identifier ("__g77_%s",
7987 "result", 0);
7988
7989 /* Make length arg _and_ enhance type info for CHAR arg itself. */
7990
7991 if (charfunc)
7992 length = ffecom_char_enhance_arg_ (&type, fn);
7993 else
7994 length = NULL_TREE; /* Not ref'd if !charfunc. */
7995
7996 type = build_pointer_type (type);
7997 result = build_decl (PARM_DECL, result, type);
7998
7999 push_parm_decl (result);
8000 if (multi)
8001 ffecom_multi_retval_ = result;
8002 else
8003 ffecom_func_result_ = result;
8004
8005 if (charfunc)
8006 {
8007 push_parm_decl (length);
8008 ffecom_func_length_ = length;
8009 }
8010 }
8011
8012 if (ffecom_primary_entry_is_proc_)
8013 {
8014 if (altentries)
8015 arglist = ffecom_master_arglist_;
8016 else
8017 arglist = ffesymbol_dummyargs (fn);
8018 ffecom_push_dummy_decls_ (arglist, FALSE);
8019 }
8020
8021 resume_momentary (yes);
8022
56a0044b
JL
8023 if (TREE_CODE (current_function_decl) != ERROR_MARK)
8024 store_parm_decls (main_program ? 1 : 0);
5ff904cd
JL
8025
8026 ffecom_start_compstmt_ ();
8027
8028 lineno = old_lineno;
8029 input_filename = old_input_filename;
8030
8031 /* This handles any symbols still untransformed, in case -g specified.
8032 This used to be done in ffecom_finish_progunit, but it turns out to
8033 be necessary to do it here so that statement functions are
8034 expanded before code. But don't bother for BLOCK DATA. */
8035
8036 if (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
8037 ffesymbol_drive (ffecom_finish_symbol_transform_);
8038}
8039
8040#endif
8041/* ffecom_sym_transform_ -- Transform FFE sym into backend sym
8042
8043 ffesymbol s;
8044 ffecom_sym_transform_(s);
8045
8046 The ffesymbol_hook info for s is updated with appropriate backend info
8047 on the symbol. */
8048
8049#if FFECOM_targetCURRENT == FFECOM_targetGCC
8050static ffesymbol
8051ffecom_sym_transform_ (ffesymbol s)
8052{
8053 tree t; /* Transformed thingy. */
8054 tree tlen; /* Length if CHAR*(*). */
8055 bool addr; /* Is t the address of the thingy? */
8056 ffeinfoBasictype bt;
8057 ffeinfoKindtype kt;
8058 ffeglobal g;
8059 int yes;
8060 int old_lineno = lineno;
8061 char *old_input_filename = input_filename;
8062
8063 if (ffesymbol_sfdummyparent (s) == NULL)
8064 {
8065 input_filename = ffesymbol_where_filename (s);
8066 lineno = ffesymbol_where_filelinenum (s);
8067 }
8068 else
8069 {
8070 ffesymbol sf = ffesymbol_sfdummyparent (s);
8071
8072 input_filename = ffesymbol_where_filename (sf);
8073 lineno = ffesymbol_where_filelinenum (sf);
8074 }
8075
8076 bt = ffeinfo_basictype (ffebld_info (s));
8077 kt = ffeinfo_kindtype (ffebld_info (s));
8078
8079 t = NULL_TREE;
8080 tlen = NULL_TREE;
8081 addr = FALSE;
8082
8083 switch (ffesymbol_kind (s))
8084 {
8085 case FFEINFO_kindNONE:
8086 switch (ffesymbol_where (s))
8087 {
8088 case FFEINFO_whereDUMMY: /* Subroutine or function. */
8089 assert (ffecom_transform_only_dummies_);
8090
8091 /* Before 0.4, this could be ENTITY/DUMMY, but see
8092 ffestu_sym_end_transition -- no longer true (in particular, if
8093 it could be an ENTITY, it _will_ be made one, so that
8094 possibility won't come through here). So we never make length
8095 arg for CHARACTER type. */
8096
8097 t = build_decl (PARM_DECL,
8098 ffecom_get_identifier_ (ffesymbol_text (s)),
8099 ffecom_tree_ptr_to_subr_type);
8100#if BUILT_FOR_270
8101 DECL_ARTIFICIAL (t) = 1;
8102#endif
8103 addr = TRUE;
8104 break;
8105
8106 case FFEINFO_whereGLOBAL: /* Subroutine or function. */
8107 assert (!ffecom_transform_only_dummies_);
8108
8109 if (((g = ffesymbol_global (s)) != NULL)
8110 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8111 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8112 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8113 && (ffeglobal_hook (g) != NULL_TREE)
8114 && ffe_is_globals ())
8115 {
8116 t = ffeglobal_hook (g);
8117 break;
8118 }
8119
8120 push_obstacks_nochange ();
8121 end_temporary_allocation ();
8122
8123 t = build_decl (FUNCTION_DECL,
8124 ffecom_get_external_identifier_ (s),
8125 ffecom_tree_subr_type); /* Assume subr. */
8126 DECL_EXTERNAL (t) = 1;
8127 TREE_PUBLIC (t) = 1;
8128
8129 t = start_decl (t, FALSE);
8130 finish_decl (t, NULL_TREE, FALSE);
8131
8132 if ((g != NULL)
8133 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8134 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8135 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8136 ffeglobal_set_hook (g, t);
8137
8138 resume_temporary_allocation ();
8139 pop_obstacks ();
8140
8141 break;
8142
8143 default:
8144 assert ("NONE where unexpected" == NULL);
8145 /* Fall through. */
8146 case FFEINFO_whereANY:
8147 break;
8148 }
8149 break;
8150
8151 case FFEINFO_kindENTITY:
8152 switch (ffeinfo_where (ffesymbol_info (s)))
8153 {
8154
8155 case FFEINFO_whereCONSTANT: /* ~~debugging info needed? */
8156 assert (!ffecom_transform_only_dummies_);
8157 t = error_mark_node; /* Shouldn't ever see this in expr. */
8158 break;
8159
8160 case FFEINFO_whereLOCAL:
8161 assert (!ffecom_transform_only_dummies_);
8162
8163 {
8164 ffestorag st = ffesymbol_storage (s);
8165 tree type;
8166
8167 if ((st != NULL)
8168 && (ffestorag_size (st) == 0))
8169 {
8170 t = error_mark_node;
8171 break;
8172 }
8173
8174 yes = suspend_momentary ();
8175 type = ffecom_type_localvar_ (s, bt, kt);
8176 resume_momentary (yes);
8177
8178 if (type == error_mark_node)
8179 {
8180 t = error_mark_node;
8181 break;
8182 }
8183
8184 if ((st != NULL)
8185 && (ffestorag_parent (st) != NULL))
8186 { /* Child of EQUIVALENCE parent. */
8187 ffestorag est;
8188 tree et;
8189 int yes;
8190 ffetargetOffset offset;
8191
8192 est = ffestorag_parent (st);
8193 ffecom_transform_equiv_ (est);
8194
8195 et = ffestorag_hook (est);
8196 assert (et != NULL_TREE);
8197
8198 if (! TREE_STATIC (et))
8199 put_var_into_stack (et);
8200
8201 yes = suspend_momentary ();
8202
8203 offset = ffestorag_modulo (est)
8204 + ffestorag_offset (ffesymbol_storage (s))
8205 - ffestorag_offset (est);
8206
8207 ffecom_debug_kludge_ (et, "EQUIVALENCE", s, type, offset);
8208
8209 /* (t_type *) (((char *) &et) + offset) */
8210
8211 t = convert (string_type_node, /* (char *) */
8212 ffecom_1 (ADDR_EXPR,
8213 build_pointer_type (TREE_TYPE (et)),
8214 et));
8215 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
8216 t,
8217 build_int_2 (offset, 0));
8218 t = convert (build_pointer_type (type),
8219 t);
8220
8221 addr = TRUE;
8222
8223 resume_momentary (yes);
8224 }
8225 else
8226 {
8227 tree initexpr;
8228 bool init = ffesymbol_is_init (s);
8229
8230 yes = suspend_momentary ();
8231
8232 t = build_decl (VAR_DECL,
8233 ffecom_get_identifier_ (ffesymbol_text (s)),
8234 type);
8235
8236 if (init
8237 || ffesymbol_namelisted (s)
8238#ifdef FFECOM_sizeMAXSTACKITEM
8239 || ((st != NULL)
8240 && (ffestorag_size (st) > FFECOM_sizeMAXSTACKITEM))
8241#endif
8242 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8243 && (ffecom_primary_entry_kind_
8244 != FFEINFO_kindBLOCKDATA)
8245 && (ffesymbol_is_save (s) || ffe_is_saveall ())))
8246 TREE_STATIC (t) = !ffesymbol_attr (s, FFESYMBOL_attrADJUSTABLE);
8247 else
8248 TREE_STATIC (t) = 0; /* No need to make static. */
8249
8250 if (init || ffe_is_init_local_zero ())
8251 DECL_INITIAL (t) = error_mark_node;
8252
8253 /* Keep -Wunused from complaining about var if it
8254 is used as sfunc arg or DATA implied-DO. */
8255 if (ffesymbol_attrs (s) & FFESYMBOL_attrsSFARG)
8256 DECL_IN_SYSTEM_HEADER (t) = 1;
8257
8258 t = start_decl (t, FALSE);
8259
8260 if (init)
8261 {
8262 if (ffesymbol_init (s) != NULL)
8263 initexpr = ffecom_expr (ffesymbol_init (s));
8264 else
8265 initexpr = ffecom_init_zero_ (t);
8266 }
8267 else if (ffe_is_init_local_zero ())
8268 initexpr = ffecom_init_zero_ (t);
8269 else
8270 initexpr = NULL_TREE; /* Not ref'd if !init. */
8271
8272 finish_decl (t, initexpr, FALSE);
8273
8274 if ((st != NULL) && (DECL_SIZE (t) != error_mark_node))
8275 {
8276 tree size_tree;
8277
8278 size_tree = size_binop (CEIL_DIV_EXPR,
8279 DECL_SIZE (t),
8280 size_int (BITS_PER_UNIT));
8281 assert (TREE_INT_CST_HIGH (size_tree) == 0);
8282 assert (TREE_INT_CST_LOW (size_tree) == ffestorag_size (st));
8283 }
8284
8285 resume_momentary (yes);
8286 }
8287 }
8288 break;
8289
8290 case FFEINFO_whereRESULT:
8291 assert (!ffecom_transform_only_dummies_);
8292
8293 if (bt == FFEINFO_basictypeCHARACTER)
8294 { /* Result is already in list of dummies, use
8295 it (& length). */
8296 t = ffecom_func_result_;
8297 tlen = ffecom_func_length_;
8298 addr = TRUE;
8299 break;
8300 }
8301 if ((ffecom_num_entrypoints_ == 0)
8302 && (bt == FFEINFO_basictypeCOMPLEX)
8303 && (ffesymbol_is_f2c (ffecom_primary_entry_)))
8304 { /* Result is already in list of dummies, use
8305 it. */
8306 t = ffecom_func_result_;
8307 addr = TRUE;
8308 break;
8309 }
8310 if (ffecom_func_result_ != NULL_TREE)
8311 {
8312 t = ffecom_func_result_;
8313 break;
8314 }
8315 if ((ffecom_num_entrypoints_ != 0)
8316 && (ffecom_master_bt_ == FFEINFO_basictypeNONE))
8317 {
8318 yes = suspend_momentary ();
8319
8320 assert (ffecom_multi_retval_ != NULL_TREE);
8321 t = ffecom_1 (INDIRECT_REF, ffecom_multi_type_node_,
8322 ffecom_multi_retval_);
8323 t = ffecom_2 (COMPONENT_REF, ffecom_tree_type[bt][kt],
8324 t, ffecom_multi_fields_[bt][kt]);
8325
8326 resume_momentary (yes);
8327 break;
8328 }
8329
8330 yes = suspend_momentary ();
8331
8332 t = build_decl (VAR_DECL,
8333 ffecom_get_identifier_ (ffesymbol_text (s)),
8334 ffecom_tree_type[bt][kt]);
8335 TREE_STATIC (t) = 0; /* Put result on stack. */
8336 t = start_decl (t, FALSE);
8337 finish_decl (t, NULL_TREE, FALSE);
8338
8339 ffecom_func_result_ = t;
8340
8341 resume_momentary (yes);
8342 break;
8343
8344 case FFEINFO_whereDUMMY:
8345 {
8346 tree type;
8347 ffebld dl;
8348 ffebld dim;
8349 tree low;
8350 tree high;
8351 tree old_sizes;
8352 bool adjustable = FALSE; /* Conditionally adjustable? */
8353
8354 type = ffecom_tree_type[bt][kt];
8355 if (ffesymbol_sfdummyparent (s) != NULL)
8356 {
8357 if (current_function_decl == ffecom_outer_function_decl_)
8358 { /* Exec transition before sfunc
8359 context; get it later. */
8360 break;
8361 }
8362 t = ffecom_get_identifier_ (ffesymbol_text
8363 (ffesymbol_sfdummyparent (s)));
8364 }
8365 else
8366 t = ffecom_get_identifier_ (ffesymbol_text (s));
8367
8368 assert (ffecom_transform_only_dummies_);
8369
8370 old_sizes = get_pending_sizes ();
8371 put_pending_sizes (old_sizes);
8372
8373 if (bt == FFEINFO_basictypeCHARACTER)
8374 tlen = ffecom_char_enhance_arg_ (&type, s);
8375 type = ffecom_check_size_overflow_ (s, type, TRUE);
8376
8377 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
8378 {
8379 if (type == error_mark_node)
8380 break;
8381
8382 dim = ffebld_head (dl);
8383 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
8384 if ((ffebld_left (dim) == NULL) || ffecom_doing_entry_)
8385 low = ffecom_integer_one_node;
8386 else
8387 low = ffecom_expr (ffebld_left (dim));
8388 assert (ffebld_right (dim) != NULL);
8389 if ((ffebld_op (ffebld_right (dim)) == FFEBLD_opSTAR)
8390 || ffecom_doing_entry_)
8342981f
RH
8391 {
8392 /* Used to just do high=low. But for ffecom_tree_
8393 canonize_ref_, it probably is important to correctly
8394 assess the size. E.g. given COMPLEX C(*),CFUNC and
8395 C(2)=CFUNC(C), overlap can happen, while it can't
8396 for, say, C(1)=CFUNC(C(2)). */
8397 /* Even more recently used to set to INT_MAX, but that
8398 broke when some overflow checking went into the back
8399 end. Now we just leave the upper bound unspecified. */
8400 high = NULL;
8401 }
5ff904cd
JL
8402 else
8403 high = ffecom_expr (ffebld_right (dim));
8404
8405 /* Determine whether array is conditionally adjustable,
8406 to decide whether back-end magic is needed.
8407
8408 Normally the front end uses the back-end function
8409 variable_size to wrap SAVE_EXPR's around expressions
8410 affecting the size/shape of an array so that the
8411 size/shape info doesn't change during execution
8412 of the compiled code even though variables and
8413 functions referenced in those expressions might.
8414
8415 variable_size also makes sure those saved expressions
8416 get evaluated immediately upon entry to the
8417 compiled procedure -- the front end normally doesn't
8418 have to worry about that.
8419
8420 However, there is a problem with this that affects
8421 g77's implementation of entry points, and that is
8422 that it is _not_ true that each invocation of the
8423 compiled procedure is permitted to evaluate
8424 array size/shape info -- because it is possible
8425 that, for some invocations, that info is invalid (in
8426 which case it is "promised" -- i.e. a violation of
8427 the Fortran standard -- that the compiled code
8428 won't reference the array or its size/shape
8429 during that particular invocation).
8430
8431 To phrase this in C terms, consider this gcc function:
8432
8433 void foo (int *n, float (*a)[*n])
8434 {
8435 // a is "pointer to array ...", fyi.
8436 }
8437
8438 Suppose that, for some invocations, it is permitted
8439 for a caller of foo to do this:
8440
8441 foo (NULL, NULL);
8442
8443 Now the _written_ code for foo can take such a call
8444 into account by either testing explicitly for whether
8445 (a == NULL) || (n == NULL) -- presumably it is
8446 not permitted to reference *a in various fashions
8447 if (n == NULL) I suppose -- or it can avoid it by
8448 looking at other info (other arguments, static/global
8449 data, etc.).
8450
8451 However, this won't work in gcc 2.5.8 because it'll
8452 automatically emit the code to save the "*n"
8453 expression, which'll yield a NULL dereference for
8454 the "foo (NULL, NULL)" call, something the code
8455 for foo cannot prevent.
8456
8457 g77 definitely needs to avoid executing such
8458 code anytime the pointer to the adjustable array
8459 is NULL, because even if its bounds expressions
8460 don't have any references to possible "absent"
8461 variables like "*n" -- say all variable references
8462 are to COMMON variables, i.e. global (though in C,
8463 local static could actually make sense) -- the
8464 expressions could yield other run-time problems
8465 for allowably "dead" values in those variables.
8466
8467 For example, let's consider a more complicated
8468 version of foo:
8469
8470 extern int i;
8471 extern int j;
8472
8473 void foo (float (*a)[i/j])
8474 {
8475 ...
8476 }
8477
8478 The above is (essentially) quite valid for Fortran
8479 but, again, for a call like "foo (NULL);", it is
8480 permitted for i and j to be undefined when the
8481 call is made. If j happened to be zero, for
8482 example, emitting the code to evaluate "i/j"
8483 could result in a run-time error.
8484
8485 Offhand, though I don't have my F77 or F90
8486 standards handy, it might even be valid for a
8487 bounds expression to contain a function reference,
8488 in which case I doubt it is permitted for an
8489 implementation to invoke that function in the
8490 Fortran case involved here (invocation of an
8491 alternate ENTRY point that doesn't have the adjustable
8492 array as one of its arguments).
8493
8494 So, the code that the compiler would normally emit
8495 to preevaluate the size/shape info for an
8496 adjustable array _must not_ be executed at run time
8497 in certain cases. Specifically, for Fortran,
8498 the case is when the pointer to the adjustable
8499 array == NULL. (For gnu-ish C, it might be nice
8500 for the source code itself to specify an expression
8501 that, if TRUE, inhibits execution of the code. Or
8502 reverse the sense for elegance.)
8503
8504 (Note that g77 could use a different test than NULL,
8505 actually, since it happens to always pass an
8506 integer to the called function that specifies which
8507 entry point is being invoked. Hmm, this might
8508 solve the next problem.)
8509
8510 One way a user could, I suppose, write "foo" so
8511 it works is to insert COND_EXPR's for the
8512 size/shape info so the dangerous stuff isn't
8513 actually done, as in:
8514
8515 void foo (int *n, float (*a)[(a == NULL) ? 0 : *n])
8516 {
8517 ...
8518 }
8519
8520 The next problem is that the front end needs to
8521 be able to tell the back end about the array's
8522 decl _before_ it tells it about the conditional
8523 expression to inhibit evaluation of size/shape info,
8524 as shown above.
8525
8526 To solve this, the front end needs to be able
8527 to give the back end the expression to inhibit
8528 generation of the preevaluation code _after_
8529 it makes the decl for the adjustable array.
8530
8531 Until then, the above example using the COND_EXPR
8532 doesn't pass muster with gcc because the "(a == NULL)"
8533 part has a reference to "a", which is still
8534 undefined at that point.
8535
8536 g77 will therefore use a different mechanism in the
8537 meantime. */
8538
8539 if (!adjustable
8540 && ((TREE_CODE (low) != INTEGER_CST)
8342981f 8541 || (high && TREE_CODE (high) != INTEGER_CST)))
5ff904cd
JL
8542 adjustable = TRUE;
8543
8544#if 0 /* Old approach -- see below. */
8545 if (TREE_CODE (low) != INTEGER_CST)
8546 low = ffecom_3 (COND_EXPR, integer_type_node,
8547 ffecom_adjarray_passed_ (s),
8548 low,
8549 ffecom_integer_zero_node);
8550
8342981f 8551 if (high && TREE_CODE (high) != INTEGER_CST)
5ff904cd
JL
8552 high = ffecom_3 (COND_EXPR, integer_type_node,
8553 ffecom_adjarray_passed_ (s),
8554 high,
8555 ffecom_integer_zero_node);
8556#endif
8557
8558 /* ~~~gcc/stor-layout.c/layout_type should do this,
8559 probably. Fixes 950302-1.f. */
8560
8561 if (TREE_CODE (low) != INTEGER_CST)
8562 low = variable_size (low);
8563
8564 /* ~~~similarly, this fixes dumb0.f. The C front end
8565 does this, which is why dumb0.c would work. */
8566
8342981f 8567 if (high && TREE_CODE (high) != INTEGER_CST)
5ff904cd
JL
8568 high = variable_size (high);
8569
8570 type
8571 = build_array_type
8572 (type,
8573 build_range_type (ffecom_integer_type_node,
8574 low, high));
8575 type = ffecom_check_size_overflow_ (s, type, TRUE);
8576 }
8577
8578 if (type == error_mark_node)
8579 {
8580 t = error_mark_node;
8581 break;
8582 }
8583
8584 if ((ffesymbol_sfdummyparent (s) == NULL)
8585 || (ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER))
8586 {
8587 type = build_pointer_type (type);
8588 addr = TRUE;
8589 }
8590
8591 t = build_decl (PARM_DECL, t, type);
8592#if BUILT_FOR_270
8593 DECL_ARTIFICIAL (t) = 1;
8594#endif
8595
8596 /* If this arg is present in every entry point's list of
8597 dummy args, then we're done. */
8598
8599 if (ffesymbol_numentries (s)
8600 == (ffecom_num_entrypoints_ + 1))
8601 break;
8602
8603#if 1
8604
8605 /* If variable_size in stor-layout has been called during
8606 the above, then get_pending_sizes should have the
8607 yet-to-be-evaluated saved expressions pending.
8608 Make the whole lot of them get emitted, conditionally
8609 on whether the array decl ("t" above) is not NULL. */
8610
8611 {
8612 tree sizes = get_pending_sizes ();
8613 tree tem;
8614
8615 for (tem = sizes;
8616 tem != old_sizes;
8617 tem = TREE_CHAIN (tem))
8618 {
8619 tree temv = TREE_VALUE (tem);
8620
8621 if (sizes == tem)
8622 sizes = temv;
8623 else
8624 sizes
8625 = ffecom_2 (COMPOUND_EXPR,
8626 TREE_TYPE (sizes),
8627 temv,
8628 sizes);
8629 }
8630
8631 if (sizes != tem)
8632 {
8633 sizes
8634 = ffecom_3 (COND_EXPR,
8635 TREE_TYPE (sizes),
8636 ffecom_2 (NE_EXPR,
8637 integer_type_node,
8638 t,
8639 null_pointer_node),
8640 sizes,
8641 convert (TREE_TYPE (sizes),
8642 integer_zero_node));
8643 sizes = ffecom_save_tree (sizes);
8644
8645 sizes
8646 = tree_cons (NULL_TREE, sizes, tem);
8647 }
8648
8649 if (sizes)
8650 put_pending_sizes (sizes);
8651 }
8652
8653#else
8654#if 0
8655 if (adjustable
8656 && (ffesymbol_numentries (s)
8657 != ffecom_num_entrypoints_ + 1))
8658 DECL_SOMETHING (t)
8659 = ffecom_2 (NE_EXPR, integer_type_node,
8660 t,
8661 null_pointer_node);
8662#else
8663#if 0
8664 if (adjustable
8665 && (ffesymbol_numentries (s)
8666 != ffecom_num_entrypoints_ + 1))
8667 {
8668 ffebad_start (FFEBAD_MISSING_ADJARRAY_UNSUPPORTED);
8669 ffebad_here (0, ffesymbol_where_line (s),
8670 ffesymbol_where_column (s));
8671 ffebad_string (ffesymbol_text (s));
8672 ffebad_finish ();
8673 }
8674#endif
8675#endif
8676#endif
8677 }
8678 break;
8679
8680 case FFEINFO_whereCOMMON:
8681 {
8682 ffesymbol cs;
8683 ffeglobal cg;
8684 tree ct;
8685 ffestorag st = ffesymbol_storage (s);
8686 tree type;
8687 int yes;
8688
8689 cs = ffesymbol_common (s); /* The COMMON area itself. */
8690 if (st != NULL) /* Else not laid out. */
8691 {
8692 ffecom_transform_common_ (cs);
8693 st = ffesymbol_storage (s);
8694 }
8695
8696 yes = suspend_momentary ();
8697
8698 type = ffecom_type_localvar_ (s, bt, kt);
8699
8700 cg = ffesymbol_global (cs); /* The global COMMON info. */
8701 if ((cg == NULL)
8702 || (ffeglobal_type (cg) != FFEGLOBAL_typeCOMMON))
8703 ct = NULL_TREE;
8704 else
8705 ct = ffeglobal_hook (cg); /* The common area's tree. */
8706
8707 if ((ct == NULL_TREE)
8708 || (st == NULL)
8709 || (type == error_mark_node))
8710 t = error_mark_node;
8711 else
8712 {
8713 ffetargetOffset offset;
8714 ffestorag cst;
8715
8716 cst = ffestorag_parent (st);
8717 assert (cst == ffesymbol_storage (cs));
8718
8719 offset = ffestorag_modulo (cst)
8720 + ffestorag_offset (st)
8721 - ffestorag_offset (cst);
8722
8723 ffecom_debug_kludge_ (ct, "COMMON", s, type, offset);
8724
8725 /* (t_type *) (((char *) &ct) + offset) */
8726
8727 t = convert (string_type_node, /* (char *) */
8728 ffecom_1 (ADDR_EXPR,
8729 build_pointer_type (TREE_TYPE (ct)),
8730 ct));
8731 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
8732 t,
8733 build_int_2 (offset, 0));
8734 t = convert (build_pointer_type (type),
8735 t);
8736
8737 addr = TRUE;
8738 }
8739
8740 resume_momentary (yes);
8741 }
8742 break;
8743
8744 case FFEINFO_whereIMMEDIATE:
8745 case FFEINFO_whereGLOBAL:
8746 case FFEINFO_whereFLEETING:
8747 case FFEINFO_whereFLEETING_CADDR:
8748 case FFEINFO_whereFLEETING_IADDR:
8749 case FFEINFO_whereINTRINSIC:
8750 case FFEINFO_whereCONSTANT_SUBOBJECT:
8751 default:
8752 assert ("ENTITY where unheard of" == NULL);
8753 /* Fall through. */
8754 case FFEINFO_whereANY:
8755 t = error_mark_node;
8756 break;
8757 }
8758 break;
8759
8760 case FFEINFO_kindFUNCTION:
8761 switch (ffeinfo_where (ffesymbol_info (s)))
8762 {
8763 case FFEINFO_whereLOCAL: /* Me. */
8764 assert (!ffecom_transform_only_dummies_);
8765 t = current_function_decl;
8766 break;
8767
8768 case FFEINFO_whereGLOBAL:
8769 assert (!ffecom_transform_only_dummies_);
8770
8771 if (((g = ffesymbol_global (s)) != NULL)
8772 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8773 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8774 && (ffeglobal_hook (g) != NULL_TREE)
8775 && ffe_is_globals ())
8776 {
8777 t = ffeglobal_hook (g);
8778 break;
8779 }
8780
8781 push_obstacks_nochange ();
8782 end_temporary_allocation ();
8783
8784 if (ffesymbol_is_f2c (s)
8785 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8786 t = ffecom_tree_fun_type[bt][kt];
8787 else
8788 t = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
8789
8790 t = build_decl (FUNCTION_DECL,
8791 ffecom_get_external_identifier_ (s),
8792 t);
8793 DECL_EXTERNAL (t) = 1;
8794 TREE_PUBLIC (t) = 1;
8795
8796 t = start_decl (t, FALSE);
8797 finish_decl (t, NULL_TREE, FALSE);
8798
8799 if ((g != NULL)
8800 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8801 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8802 ffeglobal_set_hook (g, t);
8803
8804 resume_temporary_allocation ();
8805 pop_obstacks ();
8806
8807 break;
8808
8809 case FFEINFO_whereDUMMY:
8810 assert (ffecom_transform_only_dummies_);
8811
8812 if (ffesymbol_is_f2c (s)
8813 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8814 t = ffecom_tree_ptr_to_fun_type[bt][kt];
8815 else
8816 t = build_pointer_type
8817 (build_function_type (ffecom_tree_type[bt][kt], NULL_TREE));
8818
8819 t = build_decl (PARM_DECL,
8820 ffecom_get_identifier_ (ffesymbol_text (s)),
8821 t);
8822#if BUILT_FOR_270
8823 DECL_ARTIFICIAL (t) = 1;
8824#endif
8825 addr = TRUE;
8826 break;
8827
8828 case FFEINFO_whereCONSTANT: /* Statement function. */
8829 assert (!ffecom_transform_only_dummies_);
8830 t = ffecom_gen_sfuncdef_ (s, bt, kt);
8831 break;
8832
8833 case FFEINFO_whereINTRINSIC:
8834 assert (!ffecom_transform_only_dummies_);
8835 break; /* Let actual references generate their
8836 decls. */
8837
8838 default:
8839 assert ("FUNCTION where unheard of" == NULL);
8840 /* Fall through. */
8841 case FFEINFO_whereANY:
8842 t = error_mark_node;
8843 break;
8844 }
8845 break;
8846
8847 case FFEINFO_kindSUBROUTINE:
8848 switch (ffeinfo_where (ffesymbol_info (s)))
8849 {
8850 case FFEINFO_whereLOCAL: /* Me. */
8851 assert (!ffecom_transform_only_dummies_);
8852 t = current_function_decl;
8853 break;
8854
8855 case FFEINFO_whereGLOBAL:
8856 assert (!ffecom_transform_only_dummies_);
8857
8858 if (((g = ffesymbol_global (s)) != NULL)
8859 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8860 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8861 && (ffeglobal_hook (g) != NULL_TREE)
8862 && ffe_is_globals ())
8863 {
8864 t = ffeglobal_hook (g);
8865 break;
8866 }
8867
8868 push_obstacks_nochange ();
8869 end_temporary_allocation ();
8870
8871 t = build_decl (FUNCTION_DECL,
8872 ffecom_get_external_identifier_ (s),
8873 ffecom_tree_subr_type);
8874 DECL_EXTERNAL (t) = 1;
8875 TREE_PUBLIC (t) = 1;
8876
8877 t = start_decl (t, FALSE);
8878 finish_decl (t, NULL_TREE, FALSE);
8879
8880 if ((g != NULL)
8881 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8882 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8883 ffeglobal_set_hook (g, t);
8884
8885 resume_temporary_allocation ();
8886 pop_obstacks ();
8887
8888 break;
8889
8890 case FFEINFO_whereDUMMY:
8891 assert (ffecom_transform_only_dummies_);
8892
8893 t = build_decl (PARM_DECL,
8894 ffecom_get_identifier_ (ffesymbol_text (s)),
8895 ffecom_tree_ptr_to_subr_type);
8896#if BUILT_FOR_270
8897 DECL_ARTIFICIAL (t) = 1;
8898#endif
8899 addr = TRUE;
8900 break;
8901
8902 case FFEINFO_whereINTRINSIC:
8903 assert (!ffecom_transform_only_dummies_);
8904 break; /* Let actual references generate their
8905 decls. */
8906
8907 default:
8908 assert ("SUBROUTINE where unheard of" == NULL);
8909 /* Fall through. */
8910 case FFEINFO_whereANY:
8911 t = error_mark_node;
8912 break;
8913 }
8914 break;
8915
8916 case FFEINFO_kindPROGRAM:
8917 switch (ffeinfo_where (ffesymbol_info (s)))
8918 {
8919 case FFEINFO_whereLOCAL: /* Me. */
8920 assert (!ffecom_transform_only_dummies_);
8921 t = current_function_decl;
8922 break;
8923
8924 case FFEINFO_whereCOMMON:
8925 case FFEINFO_whereDUMMY:
8926 case FFEINFO_whereGLOBAL:
8927 case FFEINFO_whereRESULT:
8928 case FFEINFO_whereFLEETING:
8929 case FFEINFO_whereFLEETING_CADDR:
8930 case FFEINFO_whereFLEETING_IADDR:
8931 case FFEINFO_whereIMMEDIATE:
8932 case FFEINFO_whereINTRINSIC:
8933 case FFEINFO_whereCONSTANT:
8934 case FFEINFO_whereCONSTANT_SUBOBJECT:
8935 default:
8936 assert ("PROGRAM where unheard of" == NULL);
8937 /* Fall through. */
8938 case FFEINFO_whereANY:
8939 t = error_mark_node;
8940 break;
8941 }
8942 break;
8943
8944 case FFEINFO_kindBLOCKDATA:
8945 switch (ffeinfo_where (ffesymbol_info (s)))
8946 {
8947 case FFEINFO_whereLOCAL: /* Me. */
8948 assert (!ffecom_transform_only_dummies_);
8949 t = current_function_decl;
8950 break;
8951
8952 case FFEINFO_whereGLOBAL:
8953 assert (!ffecom_transform_only_dummies_);
8954
8955 push_obstacks_nochange ();
8956 end_temporary_allocation ();
8957
8958 t = build_decl (FUNCTION_DECL,
8959 ffecom_get_external_identifier_ (s),
8960 ffecom_tree_blockdata_type);
8961 DECL_EXTERNAL (t) = 1;
8962 TREE_PUBLIC (t) = 1;
8963
8964 t = start_decl (t, FALSE);
8965 finish_decl (t, NULL_TREE, FALSE);
8966
8967 resume_temporary_allocation ();
8968 pop_obstacks ();
8969
8970 break;
8971
8972 case FFEINFO_whereCOMMON:
8973 case FFEINFO_whereDUMMY:
8974 case FFEINFO_whereRESULT:
8975 case FFEINFO_whereFLEETING:
8976 case FFEINFO_whereFLEETING_CADDR:
8977 case FFEINFO_whereFLEETING_IADDR:
8978 case FFEINFO_whereIMMEDIATE:
8979 case FFEINFO_whereINTRINSIC:
8980 case FFEINFO_whereCONSTANT:
8981 case FFEINFO_whereCONSTANT_SUBOBJECT:
8982 default:
8983 assert ("BLOCKDATA where unheard of" == NULL);
8984 /* Fall through. */
8985 case FFEINFO_whereANY:
8986 t = error_mark_node;
8987 break;
8988 }
8989 break;
8990
8991 case FFEINFO_kindCOMMON:
8992 switch (ffeinfo_where (ffesymbol_info (s)))
8993 {
8994 case FFEINFO_whereLOCAL:
8995 assert (!ffecom_transform_only_dummies_);
8996 ffecom_transform_common_ (s);
8997 break;
8998
8999 case FFEINFO_whereNONE:
9000 case FFEINFO_whereCOMMON:
9001 case FFEINFO_whereDUMMY:
9002 case FFEINFO_whereGLOBAL:
9003 case FFEINFO_whereRESULT:
9004 case FFEINFO_whereFLEETING:
9005 case FFEINFO_whereFLEETING_CADDR:
9006 case FFEINFO_whereFLEETING_IADDR:
9007 case FFEINFO_whereIMMEDIATE:
9008 case FFEINFO_whereINTRINSIC:
9009 case FFEINFO_whereCONSTANT:
9010 case FFEINFO_whereCONSTANT_SUBOBJECT:
9011 default:
9012 assert ("COMMON where unheard of" == NULL);
9013 /* Fall through. */
9014 case FFEINFO_whereANY:
9015 t = error_mark_node;
9016 break;
9017 }
9018 break;
9019
9020 case FFEINFO_kindCONSTRUCT:
9021 switch (ffeinfo_where (ffesymbol_info (s)))
9022 {
9023 case FFEINFO_whereLOCAL:
9024 assert (!ffecom_transform_only_dummies_);
9025 break;
9026
9027 case FFEINFO_whereNONE:
9028 case FFEINFO_whereCOMMON:
9029 case FFEINFO_whereDUMMY:
9030 case FFEINFO_whereGLOBAL:
9031 case FFEINFO_whereRESULT:
9032 case FFEINFO_whereFLEETING:
9033 case FFEINFO_whereFLEETING_CADDR:
9034 case FFEINFO_whereFLEETING_IADDR:
9035 case FFEINFO_whereIMMEDIATE:
9036 case FFEINFO_whereINTRINSIC:
9037 case FFEINFO_whereCONSTANT:
9038 case FFEINFO_whereCONSTANT_SUBOBJECT:
9039 default:
9040 assert ("CONSTRUCT where unheard of" == NULL);
9041 /* Fall through. */
9042 case FFEINFO_whereANY:
9043 t = error_mark_node;
9044 break;
9045 }
9046 break;
9047
9048 case FFEINFO_kindNAMELIST:
9049 switch (ffeinfo_where (ffesymbol_info (s)))
9050 {
9051 case FFEINFO_whereLOCAL:
9052 assert (!ffecom_transform_only_dummies_);
9053 t = ffecom_transform_namelist_ (s);
9054 break;
9055
9056 case FFEINFO_whereNONE:
9057 case FFEINFO_whereCOMMON:
9058 case FFEINFO_whereDUMMY:
9059 case FFEINFO_whereGLOBAL:
9060 case FFEINFO_whereRESULT:
9061 case FFEINFO_whereFLEETING:
9062 case FFEINFO_whereFLEETING_CADDR:
9063 case FFEINFO_whereFLEETING_IADDR:
9064 case FFEINFO_whereIMMEDIATE:
9065 case FFEINFO_whereINTRINSIC:
9066 case FFEINFO_whereCONSTANT:
9067 case FFEINFO_whereCONSTANT_SUBOBJECT:
9068 default:
9069 assert ("NAMELIST where unheard of" == NULL);
9070 /* Fall through. */
9071 case FFEINFO_whereANY:
9072 t = error_mark_node;
9073 break;
9074 }
9075 break;
9076
9077 default:
9078 assert ("kind unheard of" == NULL);
9079 /* Fall through. */
9080 case FFEINFO_kindANY:
9081 t = error_mark_node;
9082 break;
9083 }
9084
9085 ffesymbol_hook (s).decl_tree = t;
9086 ffesymbol_hook (s).length_tree = tlen;
9087 ffesymbol_hook (s).addr = addr;
9088
9089 lineno = old_lineno;
9090 input_filename = old_input_filename;
9091
9092 return s;
9093}
9094
9095#endif
9096/* Transform into ASSIGNable symbol.
9097
9098 Symbol has already been transformed, but for whatever reason, the
9099 resulting decl_tree has been deemed not usable for an ASSIGN target.
9100 (E.g. it isn't wide enough to hold a pointer.) So, here we invent
9101 another local symbol of type void * and stuff that in the assign_tree
9102 argument. The F77/F90 standards allow this implementation. */
9103
9104#if FFECOM_targetCURRENT == FFECOM_targetGCC
9105static ffesymbol
9106ffecom_sym_transform_assign_ (ffesymbol s)
9107{
9108 tree t; /* Transformed thingy. */
9109 int yes;
9110 int old_lineno = lineno;
9111 char *old_input_filename = input_filename;
9112
9113 if (ffesymbol_sfdummyparent (s) == NULL)
9114 {
9115 input_filename = ffesymbol_where_filename (s);
9116 lineno = ffesymbol_where_filelinenum (s);
9117 }
9118 else
9119 {
9120 ffesymbol sf = ffesymbol_sfdummyparent (s);
9121
9122 input_filename = ffesymbol_where_filename (sf);
9123 lineno = ffesymbol_where_filelinenum (sf);
9124 }
9125
9126 assert (!ffecom_transform_only_dummies_);
9127
9128 yes = suspend_momentary ();
9129
9130 t = build_decl (VAR_DECL,
9131 ffecom_get_invented_identifier ("__g77_ASSIGN_%s",
9132 ffesymbol_text (s),
9133 0),
9134 TREE_TYPE (null_pointer_node));
9135
9136 switch (ffesymbol_where (s))
9137 {
9138 case FFEINFO_whereLOCAL:
9139 /* Unlike for regular vars, SAVE status is easy to determine for
9140 ASSIGNed vars, since there's no initialization, there's no
9141 effective storage association (so "SAVE J" does not apply to
9142 K even given "EQUIVALENCE (J,K)"), there's no size issue
9143 to worry about, etc. */
9144 if ((ffesymbol_is_save (s) || ffe_is_saveall ())
9145 && (ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
9146 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA))
9147 TREE_STATIC (t) = 1; /* SAVEd in proc, make static. */
9148 else
9149 TREE_STATIC (t) = 0; /* No need to make static. */
9150 break;
9151
9152 case FFEINFO_whereCOMMON:
9153 TREE_STATIC (t) = 1; /* Assume COMMONs always SAVEd. */
9154 break;
9155
9156 case FFEINFO_whereDUMMY:
9157 /* Note that twinning a DUMMY means the caller won't see
9158 the ASSIGNed value. But both F77 and F90 allow implementations
9159 to do this, i.e. disallow Fortran code that would try and
9160 take advantage of actually putting a label into a variable
9161 via a dummy argument (or any other storage association, for
9162 that matter). */
9163 TREE_STATIC (t) = 0;
9164 break;
9165
9166 default:
9167 TREE_STATIC (t) = 0;
9168 break;
9169 }
9170
9171 t = start_decl (t, FALSE);
9172 finish_decl (t, NULL_TREE, FALSE);
9173
9174 resume_momentary (yes);
9175
9176 ffesymbol_hook (s).assign_tree = t;
9177
9178 lineno = old_lineno;
9179 input_filename = old_input_filename;
9180
9181 return s;
9182}
9183
9184#endif
9185/* Implement COMMON area in back end.
9186
9187 Because COMMON-based variables can be referenced in the dimension
9188 expressions of dummy (adjustable) arrays, and because dummies
9189 (in the gcc back end) need to be put in the outer binding level
9190 of a function (which has two binding levels, the outer holding
9191 the dummies and the inner holding the other vars), special care
9192 must be taken to handle COMMON areas.
9193
9194 The current strategy is basically to always tell the back end about
9195 the COMMON area as a top-level external reference to just a block
9196 of storage of the master type of that area (e.g. integer, real,
9197 character, whatever -- not a structure). As a distinct action,
9198 if initial values are provided, tell the back end about the area
9199 as a top-level non-external (initialized) area and remember not to
9200 allow further initialization or expansion of the area. Meanwhile,
9201 if no initialization happens at all, tell the back end about
9202 the largest size we've seen declared so the space does get reserved.
9203 (This function doesn't handle all that stuff, but it does some
9204 of the important things.)
9205
9206 Meanwhile, for COMMON variables themselves, just keep creating
9207 references like *((float *) (&common_area + offset)) each time
9208 we reference the variable. In other words, don't make a VAR_DECL
9209 or any kind of component reference (like we used to do before 0.4),
9210 though we might do that as well just for debugging purposes (and
9211 stuff the rtl with the appropriate offset expression). */
9212
9213#if FFECOM_targetCURRENT == FFECOM_targetGCC
9214static void
9215ffecom_transform_common_ (ffesymbol s)
9216{
9217 ffestorag st = ffesymbol_storage (s);
9218 ffeglobal g = ffesymbol_global (s);
9219 tree cbt;
9220 tree cbtype;
9221 tree init;
a6fa6420 9222 tree high;
5ff904cd
JL
9223 bool is_init = ffestorag_is_init (st);
9224
9225 assert (st != NULL);
9226
9227 if ((g == NULL)
9228 || (ffeglobal_type (g) != FFEGLOBAL_typeCOMMON))
9229 return;
9230
9231 /* First update the size of the area in global terms. */
9232
9233 ffeglobal_size_common (s, ffestorag_size (st));
9234
9235 if (!ffeglobal_common_init (g))
9236 is_init = FALSE; /* No explicit init, don't let erroneous joins init. */
9237
9238 cbt = ffeglobal_hook (g);
9239
9240 /* If we already have declared this common block for a previous program
9241 unit, and either we already initialized it or we don't have new
9242 initialization for it, just return what we have without changing it. */
9243
9244 if ((cbt != NULL_TREE)
9245 && (!is_init
9246 || !DECL_EXTERNAL (cbt)))
9247 return;
9248
9249 /* Process inits. */
9250
9251 if (is_init)
9252 {
9253 if (ffestorag_init (st) != NULL)
9254 {
a6fa6420
CB
9255 ffebld sexp;
9256
9257 /* Set the padding for the expression, so ffecom_expr
9258 knows to insert that many zeros. */
9259 switch (ffebld_op (sexp = ffestorag_init (st)))
9260 {
9261 case FFEBLD_opCONTER:
9262 ffebld_conter_set_pad (sexp, ffestorag_modulo (st));
9263 break;
9264
9265 case FFEBLD_opARRTER:
9266 ffebld_arrter_set_pad (sexp, ffestorag_modulo (st));
9267 break;
9268
9269 case FFEBLD_opACCTER:
9270 ffebld_accter_set_pad (sexp, ffestorag_modulo (st));
9271 break;
9272
9273 default:
9274 assert ("bad op for cmn init (pad)" == NULL);
9275 break;
9276 }
9277
9278 init = ffecom_expr (sexp);
5ff904cd
JL
9279 if (init == error_mark_node)
9280 { /* Hopefully the back end complained! */
9281 init = NULL_TREE;
9282 if (cbt != NULL_TREE)
9283 return;
9284 }
9285 }
9286 else
9287 init = error_mark_node;
9288 }
9289 else
9290 init = NULL_TREE;
9291
9292 push_obstacks_nochange ();
9293 end_temporary_allocation ();
9294
9295 /* cbtype must be permanently allocated! */
9296
a6fa6420
CB
9297 /* Allocate the MAX of the areas so far, seen filewide. */
9298 high = build_int_2 ((ffeglobal_common_size (g)
9299 + ffeglobal_common_pad (g)) - 1, 0);
9300 TREE_TYPE (high) = ffecom_integer_type_node;
9301
5ff904cd
JL
9302 if (init)
9303 cbtype = build_array_type (char_type_node,
9304 build_range_type (integer_type_node,
a6fa6420
CB
9305 integer_zero_node,
9306 high));
5ff904cd
JL
9307 else
9308 cbtype = build_array_type (char_type_node, NULL_TREE);
9309
9310 if (cbt == NULL_TREE)
9311 {
9312 cbt
9313 = build_decl (VAR_DECL,
9314 ffecom_get_external_identifier_ (s),
9315 cbtype);
9316 TREE_STATIC (cbt) = 1;
9317 TREE_PUBLIC (cbt) = 1;
9318 }
9319 else
9320 {
9321 assert (is_init);
9322 TREE_TYPE (cbt) = cbtype;
9323 }
9324 DECL_EXTERNAL (cbt) = init ? 0 : 1;
9325 DECL_INITIAL (cbt) = init ? error_mark_node : NULL_TREE;
9326
9327 cbt = start_decl (cbt, TRUE);
9328 if (ffeglobal_hook (g) != NULL)
9329 assert (cbt == ffeglobal_hook (g));
9330
9331 assert (!init || !DECL_EXTERNAL (cbt));
9332
9333 /* Make sure that any type can live in COMMON and be referenced
9334 without getting a bus error. We could pick the most restrictive
9335 alignment of all entities actually placed in the COMMON, but
9336 this seems easy enough. */
9337
9338 DECL_ALIGN (cbt) = BIGGEST_ALIGNMENT;
9339
9340 if (is_init && (ffestorag_init (st) == NULL))
9341 init = ffecom_init_zero_ (cbt);
9342
9343 finish_decl (cbt, init, TRUE);
9344
9345 if (is_init)
9346 ffestorag_set_init (st, ffebld_new_any ());
9347
9348 if (init)
9349 {
9350 tree size_tree;
9351
9352 assert (DECL_SIZE (cbt) != NULL_TREE);
9353 assert (TREE_CODE (DECL_SIZE (cbt)) == INTEGER_CST);
9354 size_tree = size_binop (CEIL_DIV_EXPR,
9355 DECL_SIZE (cbt),
9356 size_int (BITS_PER_UNIT));
9357 assert (TREE_INT_CST_HIGH (size_tree) == 0);
a6fa6420
CB
9358 assert (TREE_INT_CST_LOW (size_tree)
9359 == ffeglobal_common_size (g) + ffeglobal_common_pad (g));
5ff904cd
JL
9360 }
9361
9362 ffeglobal_set_hook (g, cbt);
9363
9364 ffestorag_set_hook (st, cbt);
9365
9366 resume_temporary_allocation ();
9367 pop_obstacks ();
9368}
9369
9370#endif
9371/* Make master area for local EQUIVALENCE. */
9372
9373#if FFECOM_targetCURRENT == FFECOM_targetGCC
9374static void
9375ffecom_transform_equiv_ (ffestorag eqst)
9376{
9377 tree eqt;
9378 tree eqtype;
9379 tree init;
9380 tree high;
9381 bool is_init = ffestorag_is_init (eqst);
9382 int yes;
9383
9384 assert (eqst != NULL);
9385
9386 eqt = ffestorag_hook (eqst);
9387
9388 if (eqt != NULL_TREE)
9389 return;
9390
9391 /* Process inits. */
9392
9393 if (is_init)
9394 {
9395 if (ffestorag_init (eqst) != NULL)
9396 {
a6fa6420
CB
9397 ffebld sexp;
9398
9399 /* Set the padding for the expression, so ffecom_expr
9400 knows to insert that many zeros. */
9401 switch (ffebld_op (sexp = ffestorag_init (eqst)))
9402 {
9403 case FFEBLD_opCONTER:
9404 ffebld_conter_set_pad (sexp, ffestorag_modulo (eqst));
9405 break;
9406
9407 case FFEBLD_opARRTER:
9408 ffebld_arrter_set_pad (sexp, ffestorag_modulo (eqst));
9409 break;
9410
9411 case FFEBLD_opACCTER:
9412 ffebld_accter_set_pad (sexp, ffestorag_modulo (eqst));
9413 break;
9414
9415 default:
9416 assert ("bad op for eqv init (pad)" == NULL);
9417 break;
9418 }
9419
9420 init = ffecom_expr (sexp);
5ff904cd
JL
9421 if (init == error_mark_node)
9422 init = NULL_TREE; /* Hopefully the back end complained! */
9423 }
9424 else
9425 init = error_mark_node;
9426 }
9427 else if (ffe_is_init_local_zero ())
9428 init = error_mark_node;
9429 else
9430 init = NULL_TREE;
9431
9432 ffecom_member_namelisted_ = FALSE;
9433 ffestorag_drive (ffestorag_list_equivs (eqst),
9434 &ffecom_member_phase1_,
9435 eqst);
9436
9437 yes = suspend_momentary ();
9438
a6fa6420
CB
9439 high = build_int_2 ((ffestorag_size (eqst)
9440 + ffestorag_modulo (eqst)) - 1, 0);
5ff904cd
JL
9441 TREE_TYPE (high) = ffecom_integer_type_node;
9442
9443 eqtype = build_array_type (char_type_node,
9444 build_range_type (ffecom_integer_type_node,
a6fa6420 9445 ffecom_integer_zero_node,
5ff904cd
JL
9446 high));
9447
9448 eqt = build_decl (VAR_DECL,
9449 ffecom_get_invented_identifier ("__g77_equiv_%s",
9450 ffesymbol_text
9451 (ffestorag_symbol
9452 (eqst)),
9453 0),
9454 eqtype);
9455 DECL_EXTERNAL (eqt) = 0;
9456 if (is_init
9457 || ffecom_member_namelisted_
9458#ifdef FFECOM_sizeMAXSTACKITEM
9459 || (ffestorag_size (eqst) > FFECOM_sizeMAXSTACKITEM)
9460#endif
9461 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
9462 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
9463 && (ffestorag_is_save (eqst) || ffe_is_saveall ())))
9464 TREE_STATIC (eqt) = 1;
9465 else
9466 TREE_STATIC (eqt) = 0;
9467 TREE_PUBLIC (eqt) = 0;
9468 DECL_CONTEXT (eqt) = current_function_decl;
9469 if (init)
9470 DECL_INITIAL (eqt) = error_mark_node;
9471 else
9472 DECL_INITIAL (eqt) = NULL_TREE;
9473
9474 eqt = start_decl (eqt, FALSE);
9475
5ff904cd
JL
9476 /* Make sure that any type can live in EQUIVALENCE and be referenced
9477 without getting a bus error. We could pick the most restrictive
9478 alignment of all entities actually placed in the EQUIVALENCE, but
9479 this seems easy enough. */
9480
9481 DECL_ALIGN (eqt) = BIGGEST_ALIGNMENT;
9482
9483 if ((!is_init && ffe_is_init_local_zero ())
9484 || (is_init && (ffestorag_init (eqst) == NULL)))
9485 init = ffecom_init_zero_ (eqt);
9486
9487 finish_decl (eqt, init, FALSE);
9488
9489 if (is_init)
9490 ffestorag_set_init (eqst, ffebld_new_any ());
9491
9492 {
9493 tree size_tree;
9494
9495 size_tree = size_binop (CEIL_DIV_EXPR,
9496 DECL_SIZE (eqt),
9497 size_int (BITS_PER_UNIT));
9498 assert (TREE_INT_CST_HIGH (size_tree) == 0);
a6fa6420
CB
9499 assert (TREE_INT_CST_LOW (size_tree)
9500 == ffestorag_size (eqst) + ffestorag_modulo (eqst));
5ff904cd
JL
9501 }
9502
9503 ffestorag_set_hook (eqst, eqt);
9504
9505#ifdef SOMEONE_GETS_DEBUG_SUPPORT_WORKING
9506 ffestorag_drive (ffestorag_list_equivs (eqst),
9507 &ffecom_member_phase2_,
9508 eqst);
9509#endif
9510
9511 resume_momentary (yes);
9512}
9513
9514#endif
9515/* Implement NAMELIST in back end. See f2c/format.c for more info. */
9516
9517#if FFECOM_targetCURRENT == FFECOM_targetGCC
9518static tree
9519ffecom_transform_namelist_ (ffesymbol s)
9520{
9521 tree nmlt;
9522 tree nmltype = ffecom_type_namelist_ ();
9523 tree nmlinits;
9524 tree nameinit;
9525 tree varsinit;
9526 tree nvarsinit;
9527 tree field;
9528 tree high;
9529 int yes;
9530 int i;
9531 static int mynumber = 0;
9532
9533 yes = suspend_momentary ();
9534
9535 nmlt = build_decl (VAR_DECL,
9536 ffecom_get_invented_identifier ("__g77_namelist_%d",
9537 NULL, mynumber++),
9538 nmltype);
9539 TREE_STATIC (nmlt) = 1;
9540 DECL_INITIAL (nmlt) = error_mark_node;
9541
9542 nmlt = start_decl (nmlt, FALSE);
9543
9544 /* Process inits. */
9545
9546 i = strlen (ffesymbol_text (s));
9547
9548 high = build_int_2 (i, 0);
9549 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
9550
9551 nameinit = ffecom_build_f2c_string_ (i + 1,
9552 ffesymbol_text (s));
9553 TREE_TYPE (nameinit)
9554 = build_type_variant
9555 (build_array_type
9556 (char_type_node,
9557 build_range_type (ffecom_f2c_ftnlen_type_node,
9558 ffecom_f2c_ftnlen_one_node,
9559 high)),
9560 1, 0);
9561 TREE_CONSTANT (nameinit) = 1;
9562 TREE_STATIC (nameinit) = 1;
9563 nameinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (nameinit)),
9564 nameinit);
9565
9566 varsinit = ffecom_vardesc_array_ (s);
9567 varsinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (varsinit)),
9568 varsinit);
9569 TREE_CONSTANT (varsinit) = 1;
9570 TREE_STATIC (varsinit) = 1;
9571
9572 {
9573 ffebld b;
9574
9575 for (i = 0, b = ffesymbol_namelist (s); b != NULL; b = ffebld_trail (b))
9576 ++i;
9577 }
9578 nvarsinit = build_int_2 (i, 0);
9579 TREE_TYPE (nvarsinit) = integer_type_node;
9580 TREE_CONSTANT (nvarsinit) = 1;
9581 TREE_STATIC (nvarsinit) = 1;
9582
9583 nmlinits = build_tree_list ((field = TYPE_FIELDS (nmltype)), nameinit);
9584 TREE_CHAIN (nmlinits) = build_tree_list ((field = TREE_CHAIN (field)),
9585 varsinit);
9586 TREE_CHAIN (TREE_CHAIN (nmlinits))
9587 = build_tree_list ((field = TREE_CHAIN (field)), nvarsinit);
9588
9589 nmlinits = build (CONSTRUCTOR, nmltype, NULL_TREE, nmlinits);
9590 TREE_CONSTANT (nmlinits) = 1;
9591 TREE_STATIC (nmlinits) = 1;
9592
9593 finish_decl (nmlt, nmlinits, FALSE);
9594
9595 nmlt = ffecom_1 (ADDR_EXPR, build_pointer_type (nmltype), nmlt);
9596
9597 resume_momentary (yes);
9598
9599 return nmlt;
9600}
9601
9602#endif
9603
9604/* A subroutine of ffecom_tree_canonize_ref_. The incoming tree is
9605 analyzed on the assumption it is calculating a pointer to be
9606 indirected through. It must return the proper decl and offset,
9607 taking into account different units of measurements for offsets. */
9608
9609#if FFECOM_targetCURRENT == FFECOM_targetGCC
9610static void
9611ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
9612 tree t)
9613{
9614 switch (TREE_CODE (t))
9615 {
9616 case NOP_EXPR:
9617 case CONVERT_EXPR:
9618 case NON_LVALUE_EXPR:
9619 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
9620 break;
9621
9622 case PLUS_EXPR:
9623 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
9624 if ((*decl == NULL_TREE)
9625 || (*decl == error_mark_node))
9626 break;
9627
9628 if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST)
9629 {
9630 /* An offset into COMMON. */
9631 *offset = size_binop (PLUS_EXPR,
9632 *offset,
9633 TREE_OPERAND (t, 1));
9634 /* Convert offset (presumably in bytes) into canonical units
9635 (presumably bits). */
9636 *offset = size_binop (MULT_EXPR,
c8bec8c8
R
9637 TYPE_SIZE (TREE_TYPE (TREE_TYPE (t))),
9638 *offset);
5ff904cd
JL
9639 break;
9640 }
9641 /* Not a COMMON reference, so an unrecognized pattern. */
9642 *decl = error_mark_node;
9643 break;
9644
9645 case PARM_DECL:
9646 *decl = t;
f861f674 9647 *offset = bitsize_int (0L, 0L);
5ff904cd
JL
9648 break;
9649
9650 case ADDR_EXPR:
9651 if (TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL)
9652 {
9653 /* A reference to COMMON. */
9654 *decl = TREE_OPERAND (t, 0);
f861f674 9655 *offset = bitsize_int (0L, 0L);
5ff904cd
JL
9656 break;
9657 }
9658 /* Fall through. */
9659 default:
9660 /* Not a COMMON reference, so an unrecognized pattern. */
9661 *decl = error_mark_node;
9662 break;
9663 }
9664}
9665#endif
9666
9667/* Given a tree that is possibly intended for use as an lvalue, return
9668 information representing a canonical view of that tree as a decl, an
9669 offset into that decl, and a size for the lvalue.
9670
9671 If there's no applicable decl, NULL_TREE is returned for the decl,
9672 and the other fields are left undefined.
9673
9674 If the tree doesn't fit the recognizable forms, an ERROR_MARK node
9675 is returned for the decl, and the other fields are left undefined.
9676
9677 Otherwise, the decl returned currently is either a VAR_DECL or a
9678 PARM_DECL.
9679
9680 The offset returned is always valid, but of course not necessarily
9681 a constant, and not necessarily converted into the appropriate
9682 type, leaving that up to the caller (so as to avoid that overhead
9683 if the decls being looked at are different anyway).
9684
9685 If the size cannot be determined (e.g. an adjustable array),
9686 an ERROR_MARK node is returned for the size. Otherwise, the
9687 size returned is valid, not necessarily a constant, and not
9688 necessarily converted into the appropriate type as with the
9689 offset.
9690
9691 Note that the offset and size expressions are expressed in the
9692 base storage units (usually bits) rather than in the units of
9693 the type of the decl, because two decls with different types
9694 might overlap but with apparently non-overlapping array offsets,
9695 whereas converting the array offsets to consistant offsets will
9696 reveal the overlap. */
9697
9698#if FFECOM_targetCURRENT == FFECOM_targetGCC
9699static void
9700ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
9701 tree *size, tree t)
9702{
9703 /* The default path is to report a nonexistant decl. */
9704 *decl = NULL_TREE;
9705
9706 if (t == NULL_TREE)
9707 return;
9708
9709 switch (TREE_CODE (t))
9710 {
9711 case ERROR_MARK:
9712 case IDENTIFIER_NODE:
9713 case INTEGER_CST:
9714 case REAL_CST:
9715 case COMPLEX_CST:
9716 case STRING_CST:
9717 case CONST_DECL:
9718 case PLUS_EXPR:
9719 case MINUS_EXPR:
9720 case MULT_EXPR:
9721 case TRUNC_DIV_EXPR:
9722 case CEIL_DIV_EXPR:
9723 case FLOOR_DIV_EXPR:
9724 case ROUND_DIV_EXPR:
9725 case TRUNC_MOD_EXPR:
9726 case CEIL_MOD_EXPR:
9727 case FLOOR_MOD_EXPR:
9728 case ROUND_MOD_EXPR:
9729 case RDIV_EXPR:
9730 case EXACT_DIV_EXPR:
9731 case FIX_TRUNC_EXPR:
9732 case FIX_CEIL_EXPR:
9733 case FIX_FLOOR_EXPR:
9734 case FIX_ROUND_EXPR:
9735 case FLOAT_EXPR:
9736 case EXPON_EXPR:
9737 case NEGATE_EXPR:
9738 case MIN_EXPR:
9739 case MAX_EXPR:
9740 case ABS_EXPR:
9741 case FFS_EXPR:
9742 case LSHIFT_EXPR:
9743 case RSHIFT_EXPR:
9744 case LROTATE_EXPR:
9745 case RROTATE_EXPR:
9746 case BIT_IOR_EXPR:
9747 case BIT_XOR_EXPR:
9748 case BIT_AND_EXPR:
9749 case BIT_ANDTC_EXPR:
9750 case BIT_NOT_EXPR:
9751 case TRUTH_ANDIF_EXPR:
9752 case TRUTH_ORIF_EXPR:
9753 case TRUTH_AND_EXPR:
9754 case TRUTH_OR_EXPR:
9755 case TRUTH_XOR_EXPR:
9756 case TRUTH_NOT_EXPR:
9757 case LT_EXPR:
9758 case LE_EXPR:
9759 case GT_EXPR:
9760 case GE_EXPR:
9761 case EQ_EXPR:
9762 case NE_EXPR:
9763 case COMPLEX_EXPR:
9764 case CONJ_EXPR:
9765 case REALPART_EXPR:
9766 case IMAGPART_EXPR:
9767 case LABEL_EXPR:
9768 case COMPONENT_REF:
9769 case COMPOUND_EXPR:
9770 case ADDR_EXPR:
9771 return;
9772
9773 case VAR_DECL:
9774 case PARM_DECL:
9775 *decl = t;
c8bec8c8 9776 *offset = bitsize_int (0L, 0L);
5ff904cd
JL
9777 *size = TYPE_SIZE (TREE_TYPE (t));
9778 return;
9779
9780 case ARRAY_REF:
9781 {
9782 tree array = TREE_OPERAND (t, 0);
9783 tree element = TREE_OPERAND (t, 1);
9784 tree init_offset;
9785
9786 if ((array == NULL_TREE)
9787 || (element == NULL_TREE))
9788 {
9789 *decl = error_mark_node;
9790 return;
9791 }
9792
9793 ffecom_tree_canonize_ref_ (decl, &init_offset, size,
9794 array);
9795 if ((*decl == NULL_TREE)
9796 || (*decl == error_mark_node))
9797 return;
9798
9799 *offset = size_binop (MULT_EXPR,
9800 TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))),
9801 size_binop (MINUS_EXPR,
9802 element,
9803 TYPE_MIN_VALUE
9804 (TYPE_DOMAIN
9805 (TREE_TYPE (array)))));
9806
9807 *offset = size_binop (PLUS_EXPR,
9808 init_offset,
9809 *offset);
9810
9811 *size = TYPE_SIZE (TREE_TYPE (t));
9812 return;
9813 }
9814
9815 case INDIRECT_REF:
9816
9817 /* Most of this code is to handle references to COMMON. And so
9818 far that is useful only for calling library functions, since
9819 external (user) functions might reference common areas. But
9820 even calling an external function, it's worthwhile to decode
9821 COMMON references because if not storing into COMMON, we don't
9822 want COMMON-based arguments to gratuitously force use of a
9823 temporary. */
9824
9825 *size = TYPE_SIZE (TREE_TYPE (t));
9826
9827 ffecom_tree_canonize_ptr_ (decl, offset,
9828 TREE_OPERAND (t, 0));
9829
9830 return;
9831
9832 case CONVERT_EXPR:
9833 case NOP_EXPR:
9834 case MODIFY_EXPR:
9835 case NON_LVALUE_EXPR:
9836 case RESULT_DECL:
9837 case FIELD_DECL:
9838 case COND_EXPR: /* More cases than we can handle. */
9839 case SAVE_EXPR:
9840 case REFERENCE_EXPR:
9841 case PREDECREMENT_EXPR:
9842 case PREINCREMENT_EXPR:
9843 case POSTDECREMENT_EXPR:
9844 case POSTINCREMENT_EXPR:
9845 case CALL_EXPR:
9846 default:
9847 *decl = error_mark_node;
9848 return;
9849 }
9850}
9851#endif
9852
9853/* Do divide operation appropriate to type of operands. */
9854
9855#if FFECOM_targetCURRENT == FFECOM_targetGCC
9856static tree
9857ffecom_tree_divide_ (tree tree_type, tree left, tree right,
9858 tree dest_tree, ffebld dest, bool *dest_used)
9859{
9860 if ((left == error_mark_node)
9861 || (right == error_mark_node))
9862 return error_mark_node;
9863
9864 switch (TREE_CODE (tree_type))
9865 {
9866 case INTEGER_TYPE:
9867 return ffecom_2 (TRUNC_DIV_EXPR, tree_type,
9868 left,
9869 right);
9870
9871 case COMPLEX_TYPE:
9872 {
9873 ffecomGfrt ix;
9874
9875 if (TREE_TYPE (tree_type)
9876 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9877 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9878 else
9879 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
9880
9881 left = ffecom_1 (ADDR_EXPR,
9882 build_pointer_type (TREE_TYPE (left)),
9883 left);
9884 left = build_tree_list (NULL_TREE, left);
9885 right = ffecom_1 (ADDR_EXPR,
9886 build_pointer_type (TREE_TYPE (right)),
9887 right);
9888 right = build_tree_list (NULL_TREE, right);
9889 TREE_CHAIN (left) = right;
9890
9891 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9892 ffecom_gfrt_kindtype (ix),
9893 ffe_is_f2c_library (),
9894 tree_type,
9895 left,
9896 dest_tree, dest, dest_used,
9897 NULL_TREE, TRUE);
9898 }
9899 break;
9900
9901 case RECORD_TYPE:
9902 {
9903 ffecomGfrt ix;
9904
9905 if (TREE_TYPE (TYPE_FIELDS (tree_type))
9906 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9907 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9908 else
9909 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
9910
9911 left = ffecom_1 (ADDR_EXPR,
9912 build_pointer_type (TREE_TYPE (left)),
9913 left);
9914 left = build_tree_list (NULL_TREE, left);
9915 right = ffecom_1 (ADDR_EXPR,
9916 build_pointer_type (TREE_TYPE (right)),
9917 right);
9918 right = build_tree_list (NULL_TREE, right);
9919 TREE_CHAIN (left) = right;
9920
9921 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9922 ffecom_gfrt_kindtype (ix),
9923 ffe_is_f2c_library (),
9924 tree_type,
9925 left,
9926 dest_tree, dest, dest_used,
9927 NULL_TREE, TRUE);
9928 }
9929 break;
9930
9931 default:
9932 return ffecom_2 (RDIV_EXPR, tree_type,
9933 left,
9934 right);
9935 }
9936}
9937
9938#endif
9939/* ffecom_type_localvar_ -- Build type info for non-dummy variable
9940
9941 tree type;
9942 ffesymbol s; // the variable's symbol
9943 ffeinfoBasictype bt; // it's basictype
9944 ffeinfoKindtype kt; // it's kindtype
9945
9946 type = ffecom_type_localvar_(s,bt,kt);
9947
9948 Handles static arrays, CHARACTER type, etc. */
9949
9950#if FFECOM_targetCURRENT == FFECOM_targetGCC
9951static tree
9952ffecom_type_localvar_ (ffesymbol s, ffeinfoBasictype bt,
9953 ffeinfoKindtype kt)
9954{
9955 tree type;
9956 ffebld dl;
9957 ffebld dim;
9958 tree lowt;
9959 tree hight;
9960
9961 type = ffecom_tree_type[bt][kt];
9962 if (bt == FFEINFO_basictypeCHARACTER)
9963 {
9964 hight = build_int_2 (ffesymbol_size (s), 0);
9965 TREE_TYPE (hight) = ffecom_f2c_ftnlen_type_node;
9966
9967 type
9968 = build_array_type
9969 (type,
9970 build_range_type (ffecom_f2c_ftnlen_type_node,
9971 ffecom_f2c_ftnlen_one_node,
9972 hight));
9973 type = ffecom_check_size_overflow_ (s, type, FALSE);
9974 }
9975
9976 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
9977 {
9978 if (type == error_mark_node)
9979 break;
9980
9981 dim = ffebld_head (dl);
9982 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
9983
9984 if (ffebld_left (dim) == NULL)
9985 lowt = integer_one_node;
9986 else
9987 lowt = ffecom_expr (ffebld_left (dim));
9988
9989 if (TREE_CODE (lowt) != INTEGER_CST)
9990 lowt = variable_size (lowt);
9991
9992 assert (ffebld_right (dim) != NULL);
9993 hight = ffecom_expr (ffebld_right (dim));
9994
9995 if (TREE_CODE (hight) != INTEGER_CST)
9996 hight = variable_size (hight);
9997
9998 type = build_array_type (type,
9999 build_range_type (ffecom_integer_type_node,
10000 lowt, hight));
10001 type = ffecom_check_size_overflow_ (s, type, FALSE);
10002 }
10003
10004 return type;
10005}
10006
10007#endif
10008/* Build Namelist type. */
10009
10010#if FFECOM_targetCURRENT == FFECOM_targetGCC
10011static tree
10012ffecom_type_namelist_ ()
10013{
10014 static tree type = NULL_TREE;
10015
10016 if (type == NULL_TREE)
10017 {
10018 static tree namefield, varsfield, nvarsfield;
10019 tree vardesctype;
10020
10021 vardesctype = ffecom_type_vardesc_ ();
10022
10023 push_obstacks_nochange ();
10024 end_temporary_allocation ();
10025
10026 type = make_node (RECORD_TYPE);
10027
10028 vardesctype = build_pointer_type (build_pointer_type (vardesctype));
10029
10030 namefield = ffecom_decl_field (type, NULL_TREE, "name",
10031 string_type_node);
10032 varsfield = ffecom_decl_field (type, namefield, "vars", vardesctype);
10033 nvarsfield = ffecom_decl_field (type, varsfield, "nvars",
10034 integer_type_node);
10035
10036 TYPE_FIELDS (type) = namefield;
10037 layout_type (type);
10038
10039 resume_temporary_allocation ();
10040 pop_obstacks ();
10041 }
10042
10043 return type;
10044}
10045
10046#endif
10047
10048/* Make a copy of a type, assuming caller has switched to the permanent
10049 obstacks and that the type is for an aggregate (array) initializer. */
10050
10051#if FFECOM_targetCURRENT == FFECOM_targetGCC && 0 /* Not used now. */
10052static tree
10053ffecom_type_permanent_copy_ (tree t)
10054{
10055 tree domain;
10056 tree max;
10057
10058 assert (TREE_TYPE (t) != NULL_TREE);
10059
10060 domain = TYPE_DOMAIN (t);
10061
10062 assert (TREE_CODE (t) == ARRAY_TYPE);
10063 assert (TREE_PERMANENT (TREE_TYPE (t)));
10064 assert (TREE_PERMANENT (TREE_TYPE (domain)));
10065 assert (TREE_PERMANENT (TYPE_MIN_VALUE (domain)));
10066
10067 max = TYPE_MAX_VALUE (domain);
10068 if (!TREE_PERMANENT (max))
10069 {
10070 assert (TREE_CODE (max) == INTEGER_CST);
10071
10072 max = build_int_2 (TREE_INT_CST_LOW (max), TREE_INT_CST_HIGH (max));
10073 TREE_TYPE (max) = TREE_TYPE (TYPE_MIN_VALUE (domain));
10074 }
10075
10076 return build_array_type (TREE_TYPE (t),
10077 build_range_type (TREE_TYPE (domain),
10078 TYPE_MIN_VALUE (domain),
10079 max));
10080}
10081#endif
10082
10083/* Build Vardesc type. */
10084
10085#if FFECOM_targetCURRENT == FFECOM_targetGCC
10086static tree
10087ffecom_type_vardesc_ ()
10088{
10089 static tree type = NULL_TREE;
10090 static tree namefield, addrfield, dimsfield, typefield;
10091
10092 if (type == NULL_TREE)
10093 {
10094 push_obstacks_nochange ();
10095 end_temporary_allocation ();
10096
10097 type = make_node (RECORD_TYPE);
10098
10099 namefield = ffecom_decl_field (type, NULL_TREE, "name",
10100 string_type_node);
10101 addrfield = ffecom_decl_field (type, namefield, "addr",
10102 string_type_node);
10103 dimsfield = ffecom_decl_field (type, addrfield, "dims",
39592813 10104 ffecom_f2c_ptr_to_ftnlen_type_node);
5ff904cd
JL
10105 typefield = ffecom_decl_field (type, dimsfield, "type",
10106 integer_type_node);
10107
10108 TYPE_FIELDS (type) = namefield;
10109 layout_type (type);
10110
10111 resume_temporary_allocation ();
10112 pop_obstacks ();
10113 }
10114
10115 return type;
10116}
10117
10118#endif
10119
10120#if FFECOM_targetCURRENT == FFECOM_targetGCC
10121static tree
10122ffecom_vardesc_ (ffebld expr)
10123{
10124 ffesymbol s;
10125
10126 assert (ffebld_op (expr) == FFEBLD_opSYMTER);
10127 s = ffebld_symter (expr);
10128
10129 if (ffesymbol_hook (s).vardesc_tree == NULL_TREE)
10130 {
10131 int i;
10132 tree vardesctype = ffecom_type_vardesc_ ();
10133 tree var;
10134 tree nameinit;
10135 tree dimsinit;
10136 tree addrinit;
10137 tree typeinit;
10138 tree field;
10139 tree varinits;
10140 int yes;
10141 static int mynumber = 0;
10142
10143 yes = suspend_momentary ();
10144
10145 var = build_decl (VAR_DECL,
10146 ffecom_get_invented_identifier ("__g77_vardesc_%d",
10147 NULL, mynumber++),
10148 vardesctype);
10149 TREE_STATIC (var) = 1;
10150 DECL_INITIAL (var) = error_mark_node;
10151
10152 var = start_decl (var, FALSE);
10153
10154 /* Process inits. */
10155
10156 nameinit = ffecom_build_f2c_string_ ((i = strlen (ffesymbol_text (s)))
10157 + 1,
10158 ffesymbol_text (s));
10159 TREE_TYPE (nameinit)
10160 = build_type_variant
10161 (build_array_type
10162 (char_type_node,
10163 build_range_type (integer_type_node,
10164 integer_one_node,
10165 build_int_2 (i, 0))),
10166 1, 0);
10167 TREE_CONSTANT (nameinit) = 1;
10168 TREE_STATIC (nameinit) = 1;
10169 nameinit = ffecom_1 (ADDR_EXPR,
10170 build_pointer_type (TREE_TYPE (nameinit)),
10171 nameinit);
10172
10173 addrinit = ffecom_arg_ptr_to_expr (expr, &typeinit);
10174
10175 dimsinit = ffecom_vardesc_dims_ (s);
10176
10177 if (typeinit == NULL_TREE)
10178 {
10179 ffeinfoBasictype bt = ffesymbol_basictype (s);
10180 ffeinfoKindtype kt = ffesymbol_kindtype (s);
10181 int tc = ffecom_f2c_typecode (bt, kt);
10182
10183 assert (tc != -1);
10184 typeinit = build_int_2 (tc, (tc < 0) ? -1 : 0);
10185 }
10186 else
10187 typeinit = ffecom_1 (NEGATE_EXPR, TREE_TYPE (typeinit), typeinit);
10188
10189 varinits = build_tree_list ((field = TYPE_FIELDS (vardesctype)),
10190 nameinit);
10191 TREE_CHAIN (varinits) = build_tree_list ((field = TREE_CHAIN (field)),
10192 addrinit);
10193 TREE_CHAIN (TREE_CHAIN (varinits))
10194 = build_tree_list ((field = TREE_CHAIN (field)), dimsinit);
10195 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (varinits)))
10196 = build_tree_list ((field = TREE_CHAIN (field)), typeinit);
10197
10198 varinits = build (CONSTRUCTOR, vardesctype, NULL_TREE, varinits);
10199 TREE_CONSTANT (varinits) = 1;
10200 TREE_STATIC (varinits) = 1;
10201
10202 finish_decl (var, varinits, FALSE);
10203
10204 var = ffecom_1 (ADDR_EXPR, build_pointer_type (vardesctype), var);
10205
10206 resume_momentary (yes);
10207
10208 ffesymbol_hook (s).vardesc_tree = var;
10209 }
10210
10211 return ffesymbol_hook (s).vardesc_tree;
10212}
10213
10214#endif
10215#if FFECOM_targetCURRENT == FFECOM_targetGCC
10216static tree
10217ffecom_vardesc_array_ (ffesymbol s)
10218{
10219 ffebld b;
10220 tree list;
10221 tree item = NULL_TREE;
10222 tree var;
10223 int i;
10224 int yes;
10225 static int mynumber = 0;
10226
10227 for (i = 0, list = NULL_TREE, b = ffesymbol_namelist (s);
10228 b != NULL;
10229 b = ffebld_trail (b), ++i)
10230 {
10231 tree t;
10232
10233 t = ffecom_vardesc_ (ffebld_head (b));
10234
10235 if (list == NULL_TREE)
10236 list = item = build_tree_list (NULL_TREE, t);
10237 else
10238 {
10239 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
10240 item = TREE_CHAIN (item);
10241 }
10242 }
10243
10244 yes = suspend_momentary ();
10245
10246 item = build_array_type (build_pointer_type (ffecom_type_vardesc_ ()),
10247 build_range_type (integer_type_node,
10248 integer_one_node,
10249 build_int_2 (i, 0)));
10250 list = build (CONSTRUCTOR, item, NULL_TREE, list);
10251 TREE_CONSTANT (list) = 1;
10252 TREE_STATIC (list) = 1;
10253
10254 var = ffecom_get_invented_identifier ("__g77_vardesc_array_%d", NULL,
10255 mynumber++);
10256 var = build_decl (VAR_DECL, var, item);
10257 TREE_STATIC (var) = 1;
10258 DECL_INITIAL (var) = error_mark_node;
10259 var = start_decl (var, FALSE);
10260 finish_decl (var, list, FALSE);
10261
10262 resume_momentary (yes);
10263
10264 return var;
10265}
10266
10267#endif
10268#if FFECOM_targetCURRENT == FFECOM_targetGCC
10269static tree
10270ffecom_vardesc_dims_ (ffesymbol s)
10271{
10272 if (ffesymbol_dims (s) == NULL)
10273 return convert (ffecom_f2c_ptr_to_ftnlen_type_node,
10274 integer_zero_node);
10275
10276 {
10277 ffebld b;
10278 ffebld e;
10279 tree list;
10280 tree backlist;
10281 tree item = NULL_TREE;
10282 tree var;
10283 int yes;
10284 tree numdim;
10285 tree numelem;
10286 tree baseoff = NULL_TREE;
10287 static int mynumber = 0;
10288
10289 numdim = build_int_2 ((int) ffesymbol_rank (s), 0);
10290 TREE_TYPE (numdim) = ffecom_f2c_ftnlen_type_node;
10291
10292 numelem = ffecom_expr (ffesymbol_arraysize (s));
10293 TREE_TYPE (numelem) = ffecom_f2c_ftnlen_type_node;
10294
10295 list = NULL_TREE;
10296 backlist = NULL_TREE;
10297 for (b = ffesymbol_dims (s), e = ffesymbol_extents (s);
10298 b != NULL;
10299 b = ffebld_trail (b), e = ffebld_trail (e))
10300 {
10301 tree t;
10302 tree low;
10303 tree back;
10304
10305 if (ffebld_trail (b) == NULL)
10306 t = NULL_TREE;
10307 else
10308 {
10309 t = convert (ffecom_f2c_ftnlen_type_node,
10310 ffecom_expr (ffebld_head (e)));
10311
10312 if (list == NULL_TREE)
10313 list = item = build_tree_list (NULL_TREE, t);
10314 else
10315 {
10316 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
10317 item = TREE_CHAIN (item);
10318 }
10319 }
10320
10321 if (ffebld_left (ffebld_head (b)) == NULL)
10322 low = ffecom_integer_one_node;
10323 else
10324 low = ffecom_expr (ffebld_left (ffebld_head (b)));
10325 low = convert (ffecom_f2c_ftnlen_type_node, low);
10326
10327 back = build_tree_list (low, t);
10328 TREE_CHAIN (back) = backlist;
10329 backlist = back;
10330 }
10331
10332 for (item = backlist; item != NULL_TREE; item = TREE_CHAIN (item))
10333 {
10334 if (TREE_VALUE (item) == NULL_TREE)
10335 baseoff = TREE_PURPOSE (item);
10336 else
10337 baseoff = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
10338 TREE_PURPOSE (item),
10339 ffecom_2 (MULT_EXPR,
10340 ffecom_f2c_ftnlen_type_node,
10341 TREE_VALUE (item),
10342 baseoff));
10343 }
10344
10345 /* backlist now dead, along with all TREE_PURPOSEs on it. */
10346
10347 baseoff = build_tree_list (NULL_TREE, baseoff);
10348 TREE_CHAIN (baseoff) = list;
10349
10350 numelem = build_tree_list (NULL_TREE, numelem);
10351 TREE_CHAIN (numelem) = baseoff;
10352
10353 numdim = build_tree_list (NULL_TREE, numdim);
10354 TREE_CHAIN (numdim) = numelem;
10355
10356 yes = suspend_momentary ();
10357
10358 item = build_array_type (ffecom_f2c_ftnlen_type_node,
10359 build_range_type (integer_type_node,
10360 integer_zero_node,
10361 build_int_2
10362 ((int) ffesymbol_rank (s)
10363 + 2, 0)));
10364 list = build (CONSTRUCTOR, item, NULL_TREE, numdim);
10365 TREE_CONSTANT (list) = 1;
10366 TREE_STATIC (list) = 1;
10367
10368 var = ffecom_get_invented_identifier ("__g77_dims_%d", NULL,
10369 mynumber++);
10370 var = build_decl (VAR_DECL, var, item);
10371 TREE_STATIC (var) = 1;
10372 DECL_INITIAL (var) = error_mark_node;
10373 var = start_decl (var, FALSE);
10374 finish_decl (var, list, FALSE);
10375
10376 var = ffecom_1 (ADDR_EXPR, build_pointer_type (item), var);
10377
10378 resume_momentary (yes);
10379
10380 return var;
10381 }
10382}
10383
10384#endif
10385/* Essentially does a "fold (build1 (code, type, node))" while checking
10386 for certain housekeeping things.
10387
10388 NOTE: for building an ADDR_EXPR around a FUNCTION_DECL, use
10389 ffecom_1_fn instead. */
10390
10391#if FFECOM_targetCURRENT == FFECOM_targetGCC
10392tree
10393ffecom_1 (enum tree_code code, tree type, tree node)
10394{
10395 tree item;
10396
10397 if ((node == error_mark_node)
10398 || (type == error_mark_node))
10399 return error_mark_node;
10400
10401 if (code == ADDR_EXPR)
10402 {
10403 if (!mark_addressable (node))
10404 assert ("can't mark_addressable this node!" == NULL);
10405 }
10406
10407 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
10408 {
10409 tree realtype;
10410
10411 case REALPART_EXPR:
10412 item = build (COMPONENT_REF, type, node, TYPE_FIELDS (TREE_TYPE (node)));
10413 break;
10414
10415 case IMAGPART_EXPR:
10416 item = build (COMPONENT_REF, type, node, TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (node))));
10417 break;
10418
10419
10420 case NEGATE_EXPR:
10421 if (TREE_CODE (type) != RECORD_TYPE)
10422 {
10423 item = build1 (code, type, node);
10424 break;
10425 }
10426 node = ffecom_stabilize_aggregate_ (node);
10427 realtype = TREE_TYPE (TYPE_FIELDS (type));
10428 item =
10429 ffecom_2 (COMPLEX_EXPR, type,
10430 ffecom_1 (NEGATE_EXPR, realtype,
10431 ffecom_1 (REALPART_EXPR, realtype,
10432 node)),
10433 ffecom_1 (NEGATE_EXPR, realtype,
10434 ffecom_1 (IMAGPART_EXPR, realtype,
10435 node)));
10436 break;
10437
10438 default:
10439 item = build1 (code, type, node);
10440 break;
10441 }
10442
10443 if (TREE_SIDE_EFFECTS (node))
10444 TREE_SIDE_EFFECTS (item) = 1;
10445 if ((code == ADDR_EXPR) && staticp (node))
10446 TREE_CONSTANT (item) = 1;
10447 return fold (item);
10448}
10449#endif
10450
10451/* Like ffecom_1 (ADDR_EXPR, TREE_TYPE (node), node), except
10452 handles TREE_CODE (node) == FUNCTION_DECL. In particular,
10453 does not set TREE_ADDRESSABLE (because calling an inline
10454 function does not mean the function needs to be separately
10455 compiled). */
10456
10457#if FFECOM_targetCURRENT == FFECOM_targetGCC
10458tree
10459ffecom_1_fn (tree node)
10460{
10461 tree item;
10462 tree type;
10463
10464 if (node == error_mark_node)
10465 return error_mark_node;
10466
10467 type = build_type_variant (TREE_TYPE (node),
10468 TREE_READONLY (node),
10469 TREE_THIS_VOLATILE (node));
10470 item = build1 (ADDR_EXPR,
10471 build_pointer_type (type), node);
10472 if (TREE_SIDE_EFFECTS (node))
10473 TREE_SIDE_EFFECTS (item) = 1;
10474 if (staticp (node))
10475 TREE_CONSTANT (item) = 1;
10476 return fold (item);
10477}
10478#endif
10479
10480/* Essentially does a "fold (build (code, type, node1, node2))" while
10481 checking for certain housekeeping things. */
10482
10483#if FFECOM_targetCURRENT == FFECOM_targetGCC
10484tree
10485ffecom_2 (enum tree_code code, tree type, tree node1,
10486 tree node2)
10487{
10488 tree item;
10489
10490 if ((node1 == error_mark_node)
10491 || (node2 == error_mark_node)
10492 || (type == error_mark_node))
10493 return error_mark_node;
10494
10495 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
10496 {
10497 tree a, b, c, d, realtype;
10498
10499 case CONJ_EXPR:
10500 assert ("no CONJ_EXPR support yet" == NULL);
10501 return error_mark_node;
10502
10503 case COMPLEX_EXPR:
10504 item = build_tree_list (TYPE_FIELDS (type), node1);
10505 TREE_CHAIN (item) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), node2);
10506 item = build (CONSTRUCTOR, type, NULL_TREE, item);
10507 break;
10508
10509 case PLUS_EXPR:
10510 if (TREE_CODE (type) != RECORD_TYPE)
10511 {
10512 item = build (code, type, node1, node2);
10513 break;
10514 }
10515 node1 = ffecom_stabilize_aggregate_ (node1);
10516 node2 = ffecom_stabilize_aggregate_ (node2);
10517 realtype = TREE_TYPE (TYPE_FIELDS (type));
10518 item =
10519 ffecom_2 (COMPLEX_EXPR, type,
10520 ffecom_2 (PLUS_EXPR, realtype,
10521 ffecom_1 (REALPART_EXPR, realtype,
10522 node1),
10523 ffecom_1 (REALPART_EXPR, realtype,
10524 node2)),
10525 ffecom_2 (PLUS_EXPR, realtype,
10526 ffecom_1 (IMAGPART_EXPR, realtype,
10527 node1),
10528 ffecom_1 (IMAGPART_EXPR, realtype,
10529 node2)));
10530 break;
10531
10532 case MINUS_EXPR:
10533 if (TREE_CODE (type) != RECORD_TYPE)
10534 {
10535 item = build (code, type, node1, node2);
10536 break;
10537 }
10538 node1 = ffecom_stabilize_aggregate_ (node1);
10539 node2 = ffecom_stabilize_aggregate_ (node2);
10540 realtype = TREE_TYPE (TYPE_FIELDS (type));
10541 item =
10542 ffecom_2 (COMPLEX_EXPR, type,
10543 ffecom_2 (MINUS_EXPR, realtype,
10544 ffecom_1 (REALPART_EXPR, realtype,
10545 node1),
10546 ffecom_1 (REALPART_EXPR, realtype,
10547 node2)),
10548 ffecom_2 (MINUS_EXPR, realtype,
10549 ffecom_1 (IMAGPART_EXPR, realtype,
10550 node1),
10551 ffecom_1 (IMAGPART_EXPR, realtype,
10552 node2)));
10553 break;
10554
10555 case MULT_EXPR:
10556 if (TREE_CODE (type) != RECORD_TYPE)
10557 {
10558 item = build (code, type, node1, node2);
10559 break;
10560 }
10561 node1 = ffecom_stabilize_aggregate_ (node1);
10562 node2 = ffecom_stabilize_aggregate_ (node2);
10563 realtype = TREE_TYPE (TYPE_FIELDS (type));
10564 a = save_expr (ffecom_1 (REALPART_EXPR, realtype,
10565 node1));
10566 b = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
10567 node1));
10568 c = save_expr (ffecom_1 (REALPART_EXPR, realtype,
10569 node2));
10570 d = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
10571 node2));
10572 item =
10573 ffecom_2 (COMPLEX_EXPR, type,
10574 ffecom_2 (MINUS_EXPR, realtype,
10575 ffecom_2 (MULT_EXPR, realtype,
10576 a,
10577 c),
10578 ffecom_2 (MULT_EXPR, realtype,
10579 b,
10580 d)),
10581 ffecom_2 (PLUS_EXPR, realtype,
10582 ffecom_2 (MULT_EXPR, realtype,
10583 a,
10584 d),
10585 ffecom_2 (MULT_EXPR, realtype,
10586 c,
10587 b)));
10588 break;
10589
10590 case EQ_EXPR:
10591 if ((TREE_CODE (node1) != RECORD_TYPE)
10592 && (TREE_CODE (node2) != RECORD_TYPE))
10593 {
10594 item = build (code, type, node1, node2);
10595 break;
10596 }
10597 assert (TREE_CODE (node1) == RECORD_TYPE);
10598 assert (TREE_CODE (node2) == RECORD_TYPE);
10599 node1 = ffecom_stabilize_aggregate_ (node1);
10600 node2 = ffecom_stabilize_aggregate_ (node2);
10601 realtype = TREE_TYPE (TYPE_FIELDS (type));
10602 item =
10603 ffecom_2 (TRUTH_ANDIF_EXPR, type,
10604 ffecom_2 (code, type,
10605 ffecom_1 (REALPART_EXPR, realtype,
10606 node1),
10607 ffecom_1 (REALPART_EXPR, realtype,
10608 node2)),
10609 ffecom_2 (code, type,
10610 ffecom_1 (IMAGPART_EXPR, realtype,
10611 node1),
10612 ffecom_1 (IMAGPART_EXPR, realtype,
10613 node2)));
10614 break;
10615
10616 case NE_EXPR:
10617 if ((TREE_CODE (node1) != RECORD_TYPE)
10618 && (TREE_CODE (node2) != RECORD_TYPE))
10619 {
10620 item = build (code, type, node1, node2);
10621 break;
10622 }
10623 assert (TREE_CODE (node1) == RECORD_TYPE);
10624 assert (TREE_CODE (node2) == RECORD_TYPE);
10625 node1 = ffecom_stabilize_aggregate_ (node1);
10626 node2 = ffecom_stabilize_aggregate_ (node2);
10627 realtype = TREE_TYPE (TYPE_FIELDS (type));
10628 item =
10629 ffecom_2 (TRUTH_ORIF_EXPR, type,
10630 ffecom_2 (code, type,
10631 ffecom_1 (REALPART_EXPR, realtype,
10632 node1),
10633 ffecom_1 (REALPART_EXPR, realtype,
10634 node2)),
10635 ffecom_2 (code, type,
10636 ffecom_1 (IMAGPART_EXPR, realtype,
10637 node1),
10638 ffecom_1 (IMAGPART_EXPR, realtype,
10639 node2)));
10640 break;
10641
10642 default:
10643 item = build (code, type, node1, node2);
10644 break;
10645 }
10646
10647 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2))
10648 TREE_SIDE_EFFECTS (item) = 1;
10649 return fold (item);
10650}
10651
10652#endif
10653/* ffecom_2pass_advise_entrypoint -- Advise that there's this entrypoint
10654
10655 ffesymbol s; // the ENTRY point itself
10656 if (ffecom_2pass_advise_entrypoint(s))
10657 // the ENTRY point has been accepted
10658
10659 Does whatever compiler needs to do when it learns about the entrypoint,
10660 like determine the return type of the master function, count the
10661 number of entrypoints, etc. Returns FALSE if the return type is
10662 not compatible with the return type(s) of other entrypoint(s).
10663
10664 NOTE: for every call to this fn that returns TRUE, _do_entrypoint must
10665 later (after _finish_progunit) be called with the same entrypoint(s)
10666 as passed to this fn for which TRUE was returned.
10667
10668 03-Jan-92 JCB 2.0
10669 Return FALSE if the return type conflicts with previous entrypoints. */
10670
10671#if FFECOM_targetCURRENT == FFECOM_targetGCC
10672bool
10673ffecom_2pass_advise_entrypoint (ffesymbol entry)
10674{
10675 ffebld list; /* opITEM. */
10676 ffebld mlist; /* opITEM. */
10677 ffebld plist; /* opITEM. */
10678 ffebld arg; /* ffebld_head(opITEM). */
10679 ffebld item; /* opITEM. */
10680 ffesymbol s; /* ffebld_symter(arg). */
10681 ffeinfoBasictype bt = ffesymbol_basictype (entry);
10682 ffeinfoKindtype kt = ffesymbol_kindtype (entry);
10683 ffetargetCharacterSize size = ffesymbol_size (entry);
10684 bool ok;
10685
10686 if (ffecom_num_entrypoints_ == 0)
10687 { /* First entrypoint, make list of main
10688 arglist's dummies. */
10689 assert (ffecom_primary_entry_ != NULL);
10690
10691 ffecom_master_bt_ = ffesymbol_basictype (ffecom_primary_entry_);
10692 ffecom_master_kt_ = ffesymbol_kindtype (ffecom_primary_entry_);
10693 ffecom_master_size_ = ffesymbol_size (ffecom_primary_entry_);
10694
10695 for (plist = NULL, list = ffesymbol_dummyargs (ffecom_primary_entry_);
10696 list != NULL;
10697 list = ffebld_trail (list))
10698 {
10699 arg = ffebld_head (list);
10700 if (ffebld_op (arg) != FFEBLD_opSYMTER)
10701 continue; /* Alternate return or some such thing. */
10702 item = ffebld_new_item (arg, NULL);
10703 if (plist == NULL)
10704 ffecom_master_arglist_ = item;
10705 else
10706 ffebld_set_trail (plist, item);
10707 plist = item;
10708 }
10709 }
10710
10711 /* If necessary, scan entry arglist for alternate returns. Do this scan
10712 apparently redundantly (it's done below to UNIONize the arglists) so
10713 that we don't complain about RETURN 1 if an offending ENTRY is the only
10714 one with an alternate return. */
10715
10716 if (!ffecom_is_altreturning_)
10717 {
10718 for (list = ffesymbol_dummyargs (entry);
10719 list != NULL;
10720 list = ffebld_trail (list))
10721 {
10722 arg = ffebld_head (list);
10723 if (ffebld_op (arg) == FFEBLD_opSTAR)
10724 {
10725 ffecom_is_altreturning_ = TRUE;
10726 break;
10727 }
10728 }
10729 }
10730
10731 /* Now check type compatibility. */
10732
10733 switch (ffecom_master_bt_)
10734 {
10735 case FFEINFO_basictypeNONE:
10736 ok = (bt != FFEINFO_basictypeCHARACTER);
10737 break;
10738
10739 case FFEINFO_basictypeCHARACTER:
10740 ok
10741 = (bt == FFEINFO_basictypeCHARACTER)
10742 && (kt == ffecom_master_kt_)
10743 && (size == ffecom_master_size_);
10744 break;
10745
10746 case FFEINFO_basictypeANY:
10747 return FALSE; /* Just don't bother. */
10748
10749 default:
10750 if (bt == FFEINFO_basictypeCHARACTER)
10751 {
10752 ok = FALSE;
10753 break;
10754 }
10755 ok = TRUE;
10756 if ((bt != ffecom_master_bt_) || (kt != ffecom_master_kt_))
10757 {
10758 ffecom_master_bt_ = FFEINFO_basictypeNONE;
10759 ffecom_master_kt_ = FFEINFO_kindtypeNONE;
10760 }
10761 break;
10762 }
10763
10764 if (!ok)
10765 {
10766 ffebad_start (FFEBAD_ENTRY_CONFLICTS);
10767 ffest_ffebad_here_current_stmt (0);
10768 ffebad_finish ();
10769 return FALSE; /* Can't handle entrypoint. */
10770 }
10771
10772 /* Entrypoint type compatible with previous types. */
10773
10774 ++ffecom_num_entrypoints_;
10775
10776 /* Master-arg-list = UNION(Master-arg-list,entry-arg-list). */
10777
10778 for (list = ffesymbol_dummyargs (entry);
10779 list != NULL;
10780 list = ffebld_trail (list))
10781 {
10782 arg = ffebld_head (list);
10783 if (ffebld_op (arg) != FFEBLD_opSYMTER)
10784 continue; /* Alternate return or some such thing. */
10785 s = ffebld_symter (arg);
10786 for (plist = NULL, mlist = ffecom_master_arglist_;
10787 mlist != NULL;
10788 plist = mlist, mlist = ffebld_trail (mlist))
10789 { /* plist points to previous item for easy
10790 appending of arg. */
10791 if (ffebld_symter (ffebld_head (mlist)) == s)
10792 break; /* Already have this arg in the master list. */
10793 }
10794 if (mlist != NULL)
10795 continue; /* Already have this arg in the master list. */
10796
10797 /* Append this arg to the master list. */
10798
10799 item = ffebld_new_item (arg, NULL);
10800 if (plist == NULL)
10801 ffecom_master_arglist_ = item;
10802 else
10803 ffebld_set_trail (plist, item);
10804 }
10805
10806 return TRUE;
10807}
10808
10809#endif
10810/* ffecom_2pass_do_entrypoint -- Do compilation of entrypoint
10811
10812 ffesymbol s; // the ENTRY point itself
10813 ffecom_2pass_do_entrypoint(s);
10814
10815 Does whatever compiler needs to do to make the entrypoint actually
10816 happen. Must be called for each entrypoint after
10817 ffecom_finish_progunit is called. */
10818
10819#if FFECOM_targetCURRENT == FFECOM_targetGCC
10820void
10821ffecom_2pass_do_entrypoint (ffesymbol entry)
10822{
10823 static int mfn_num = 0;
10824 static int ent_num;
10825
10826 if (mfn_num != ffecom_num_fns_)
10827 { /* First entrypoint for this program unit. */
10828 ent_num = 1;
10829 mfn_num = ffecom_num_fns_;
10830 ffecom_do_entry_ (ffecom_primary_entry_, 0);
10831 }
10832 else
10833 ++ent_num;
10834
10835 --ffecom_num_entrypoints_;
10836
10837 ffecom_do_entry_ (entry, ent_num);
10838}
10839
10840#endif
10841
10842/* Essentially does a "fold (build (code, type, node1, node2))" while
10843 checking for certain housekeeping things. Always sets
10844 TREE_SIDE_EFFECTS. */
10845
10846#if FFECOM_targetCURRENT == FFECOM_targetGCC
10847tree
10848ffecom_2s (enum tree_code code, tree type, tree node1,
10849 tree node2)
10850{
10851 tree item;
10852
10853 if ((node1 == error_mark_node)
10854 || (node2 == error_mark_node)
10855 || (type == error_mark_node))
10856 return error_mark_node;
10857
10858 item = build (code, type, node1, node2);
10859 TREE_SIDE_EFFECTS (item) = 1;
10860 return fold (item);
10861}
10862
10863#endif
10864/* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10865 checking for certain housekeeping things. */
10866
10867#if FFECOM_targetCURRENT == FFECOM_targetGCC
10868tree
10869ffecom_3 (enum tree_code code, tree type, tree node1,
10870 tree node2, tree node3)
10871{
10872 tree item;
10873
10874 if ((node1 == error_mark_node)
10875 || (node2 == error_mark_node)
10876 || (node3 == error_mark_node)
10877 || (type == error_mark_node))
10878 return error_mark_node;
10879
10880 item = build (code, type, node1, node2, node3);
10881 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2)
10882 || (node3 != NULL_TREE && TREE_SIDE_EFFECTS (node3)))
10883 TREE_SIDE_EFFECTS (item) = 1;
10884 return fold (item);
10885}
10886
10887#endif
10888/* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10889 checking for certain housekeeping things. Always sets
10890 TREE_SIDE_EFFECTS. */
10891
10892#if FFECOM_targetCURRENT == FFECOM_targetGCC
10893tree
10894ffecom_3s (enum tree_code code, tree type, tree node1,
10895 tree node2, tree node3)
10896{
10897 tree item;
10898
10899 if ((node1 == error_mark_node)
10900 || (node2 == error_mark_node)
10901 || (node3 == error_mark_node)
10902 || (type == error_mark_node))
10903 return error_mark_node;
10904
10905 item = build (code, type, node1, node2, node3);
10906 TREE_SIDE_EFFECTS (item) = 1;
10907 return fold (item);
10908}
10909
10910#endif
10911/* ffecom_arg_expr -- Transform argument expr into gcc tree
10912
10913 See use by ffecom_list_expr.
10914
10915 If expression is NULL, returns an integer zero tree. If it is not
10916 a CHARACTER expression, returns whatever ffecom_expr
10917 returns and sets the length return value to NULL_TREE. Otherwise
10918 generates code to evaluate the character expression, returns the proper
10919 pointer to the result, but does NOT set the length return value to a tree
10920 that specifies the length of the result. (In other words, the length
10921 variable is always set to NULL_TREE, because a length is never passed.)
10922
10923 21-Dec-91 JCB 1.1
10924 Don't set returned length, since nobody needs it (yet; someday if
10925 we allow CHARACTER*(*) dummies to statement functions, we'll need
10926 it). */
10927
10928#if FFECOM_targetCURRENT == FFECOM_targetGCC
10929tree
10930ffecom_arg_expr (ffebld expr, tree *length)
10931{
10932 tree ign;
10933
10934 *length = NULL_TREE;
10935
10936 if (expr == NULL)
10937 return integer_zero_node;
10938
10939 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10940 return ffecom_expr (expr);
10941
10942 return ffecom_arg_ptr_to_expr (expr, &ign);
10943}
10944
10945#endif
10946/* ffecom_arg_ptr_to_expr -- Transform argument expr into gcc tree
10947
10948 See use by ffecom_list_ptr_to_expr.
10949
10950 If expression is NULL, returns an integer zero tree. If it is not
10951 a CHARACTER expression, returns whatever ffecom_ptr_to_expr
10952 returns and sets the length return value to NULL_TREE. Otherwise
10953 generates code to evaluate the character expression, returns the proper
10954 pointer to the result, AND sets the length return value to a tree that
86fc7a6c
CB
10955 specifies the length of the result.
10956
10957 If the length argument is NULL, this is a slightly special
10958 case of building a FORMAT expression, that is, an expression that
10959 will be used at run time without regard to length. For the current
10960 implementation, which uses the libf2c library, this means it is nice
10961 to append a null byte to the end of the expression, where feasible,
10962 to make sure any diagnostic about the FORMAT string terminates at
10963 some useful point.
10964
10965 For now, treat %REF(char-expr) as the same as char-expr with a NULL
10966 length argument. This might even be seen as a feature, if a null
10967 byte can always be appended. */
5ff904cd
JL
10968
10969#if FFECOM_targetCURRENT == FFECOM_targetGCC
10970tree
10971ffecom_arg_ptr_to_expr (ffebld expr, tree *length)
10972{
10973 tree item;
10974 tree ign_length;
10975 ffecomConcatList_ catlist;
10976
86fc7a6c
CB
10977 if (length != NULL)
10978 *length = NULL_TREE;
5ff904cd
JL
10979
10980 if (expr == NULL)
10981 return integer_zero_node;
10982
10983 switch (ffebld_op (expr))
10984 {
10985 case FFEBLD_opPERCENT_VAL:
10986 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10987 return ffecom_expr (ffebld_left (expr));
10988 {
10989 tree temp_exp;
10990 tree temp_length;
10991
10992 temp_exp = ffecom_arg_ptr_to_expr (ffebld_left (expr), &temp_length);
10993 return ffecom_1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (temp_exp)),
10994 temp_exp);
10995 }
10996
10997 case FFEBLD_opPERCENT_REF:
10998 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10999 return ffecom_ptr_to_expr (ffebld_left (expr));
86fc7a6c
CB
11000 if (length != NULL)
11001 {
11002 ign_length = NULL_TREE;
11003 length = &ign_length;
11004 }
5ff904cd
JL
11005 expr = ffebld_left (expr);
11006 break;
11007
11008 case FFEBLD_opPERCENT_DESCR:
11009 switch (ffeinfo_basictype (ffebld_info (expr)))
11010 {
11011#ifdef PASS_HOLLERITH_BY_DESCRIPTOR
11012 case FFEINFO_basictypeHOLLERITH:
11013#endif
11014 case FFEINFO_basictypeCHARACTER:
11015 break; /* Passed by descriptor anyway. */
11016
11017 default:
11018 item = ffecom_ptr_to_expr (expr);
11019 if (item != error_mark_node)
11020 *length = TYPE_SIZE (TREE_TYPE (TREE_TYPE (item)));
11021 break;
11022 }
11023 break;
11024
11025 default:
11026 break;
11027 }
11028
11029#ifdef PASS_HOLLERITH_BY_DESCRIPTOR
86fc7a6c
CB
11030 if ((ffeinfo_basictype (ffebld_info (expr)) == FFEINFO_basictypeHOLLERITH)
11031 && (length != NULL))
5ff904cd
JL
11032 { /* Pass Hollerith by descriptor. */
11033 ffetargetHollerith h;
11034
11035 assert (ffebld_op (expr) == FFEBLD_opCONTER);
11036 h = ffebld_cu_val_hollerith (ffebld_constant_union
11037 (ffebld_conter (expr)));
11038 *length
11039 = build_int_2 (h.length, 0);
11040 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
11041 }
11042#endif
11043
11044 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
11045 return ffecom_ptr_to_expr (expr);
11046
11047 assert (ffeinfo_kindtype (ffebld_info (expr))
11048 == FFEINFO_kindtypeCHARACTER1);
11049
11050 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
11051 switch (ffecom_concat_list_count_ (catlist))
11052 {
11053 case 0: /* Shouldn't happen, but in case it does... */
86fc7a6c
CB
11054 if (length != NULL)
11055 {
11056 *length = ffecom_f2c_ftnlen_zero_node;
11057 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
11058 }
5ff904cd
JL
11059 ffecom_concat_list_kill_ (catlist);
11060 return null_pointer_node;
11061
11062 case 1: /* The (fairly) easy case. */
86fc7a6c
CB
11063 if (length == NULL)
11064 ffecom_char_args_with_null_ (&item, &ign_length,
11065 ffecom_concat_list_expr_ (catlist, 0));
11066 else
11067 ffecom_char_args_ (&item, length,
11068 ffecom_concat_list_expr_ (catlist, 0));
5ff904cd
JL
11069 ffecom_concat_list_kill_ (catlist);
11070 assert (item != NULL_TREE);
11071 return item;
11072
11073 default: /* Must actually concatenate things. */
11074 break;
11075 }
11076
11077 {
11078 int count = ffecom_concat_list_count_ (catlist);
11079 int i;
11080 tree lengths;
11081 tree items;
11082 tree length_array;
11083 tree item_array;
11084 tree citem;
11085 tree clength;
11086 tree temporary;
11087 tree num;
11088 tree known_length;
11089 ffetargetCharacterSize sz;
11090
11091 length_array
11092 = lengths
11093 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
11094 FFETARGET_charactersizeNONE, count, TRUE);
11095 item_array
11096 = items
11097 = ffecom_push_tempvar (ffecom_f2c_address_type_node,
11098 FFETARGET_charactersizeNONE, count, TRUE);
11099
11100 known_length = ffecom_f2c_ftnlen_zero_node;
11101
11102 for (i = 0; i < count; ++i)
11103 {
86fc7a6c
CB
11104 if ((i == count)
11105 && (length == NULL))
11106 ffecom_char_args_with_null_ (&citem, &clength,
11107 ffecom_concat_list_expr_ (catlist, i));
11108 else
11109 ffecom_char_args_ (&citem, &clength,
11110 ffecom_concat_list_expr_ (catlist, i));
5ff904cd
JL
11111 if ((citem == error_mark_node)
11112 || (clength == error_mark_node))
11113 {
11114 ffecom_concat_list_kill_ (catlist);
11115 *length = error_mark_node;
11116 return error_mark_node;
11117 }
11118
11119 items
11120 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
11121 ffecom_modify (void_type_node,
11122 ffecom_2 (ARRAY_REF,
11123 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
11124 item_array,
11125 build_int_2 (i, 0)),
11126 citem),
11127 items);
11128 clength = ffecom_save_tree (clength);
86fc7a6c
CB
11129 if (length != NULL)
11130 known_length
11131 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
11132 known_length,
11133 clength);
5ff904cd
JL
11134 lengths
11135 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
11136 ffecom_modify (void_type_node,
11137 ffecom_2 (ARRAY_REF,
11138 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
11139 length_array,
11140 build_int_2 (i, 0)),
11141 clength),
11142 lengths);
11143 }
11144
11145 sz = ffecom_concat_list_maxlen_ (catlist);
11146 assert (sz != FFETARGET_charactersizeNONE);
11147
11148 temporary = ffecom_push_tempvar (char_type_node,
11149 sz, -1, TRUE);
11150 temporary = ffecom_1 (ADDR_EXPR,
11151 build_pointer_type (TREE_TYPE (temporary)),
11152 temporary);
11153
11154 item = build_tree_list (NULL_TREE, temporary);
11155 TREE_CHAIN (item)
11156 = build_tree_list (NULL_TREE,
11157 ffecom_1 (ADDR_EXPR,
11158 build_pointer_type (TREE_TYPE (items)),
11159 items));
11160 TREE_CHAIN (TREE_CHAIN (item))
11161 = build_tree_list (NULL_TREE,
11162 ffecom_1 (ADDR_EXPR,
11163 build_pointer_type (TREE_TYPE (lengths)),
11164 lengths));
11165 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
11166 = build_tree_list
11167 (NULL_TREE,
11168 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
11169 convert (ffecom_f2c_ftnlen_type_node,
11170 build_int_2 (count, 0))));
11171 num = build_int_2 (sz, 0);
11172 TREE_TYPE (num) = ffecom_f2c_ftnlen_type_node;
11173 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item))))
11174 = build_tree_list (NULL_TREE, num);
11175
11176 item = ffecom_call_gfrt (FFECOM_gfrtCAT, item);
11177 TREE_SIDE_EFFECTS (item) = 1;
11178 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (temporary),
11179 item,
11180 temporary);
11181
86fc7a6c
CB
11182 if (length != NULL)
11183 *length = known_length;
5ff904cd
JL
11184 }
11185
11186 ffecom_concat_list_kill_ (catlist);
11187 assert (item != NULL_TREE);
11188 return item;
11189}
11190
11191#endif
11192/* ffecom_call_gfrt -- Generate call to run-time function
11193
11194 tree expr;
11195 expr = ffecom_call_gfrt(FFECOM_gfrtSTOPNIL,NULL_TREE);
11196
11197 The first arg is the GNU Fortran Run-Time function index, the second
11198 arg is the list of arguments to pass to it. Returned is the expression
11199 (WITHOUT TREE_SIDE_EFFECTS set!) that makes the call and returns the
11200 result (which may be void). */
11201
11202#if FFECOM_targetCURRENT == FFECOM_targetGCC
11203tree
11204ffecom_call_gfrt (ffecomGfrt ix, tree args)
11205{
11206 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
11207 ffecom_gfrt_kindtype (ix),
11208 ffe_is_f2c_library () && ffecom_gfrt_complex_[ix],
11209 NULL_TREE, args, NULL_TREE, NULL,
11210 NULL, NULL_TREE, TRUE);
11211}
11212#endif
11213
11214/* ffecom_constantunion -- Transform constant-union to tree
11215
11216 ffebldConstantUnion cu; // the constant to transform
11217 ffeinfoBasictype bt; // its basic type
11218 ffeinfoKindtype kt; // its kind type
11219 tree tree_type; // ffecom_tree_type[bt][kt]
11220 ffecom_constantunion(&cu,bt,kt,tree_type); */
11221
11222#if FFECOM_targetCURRENT == FFECOM_targetGCC
11223tree
11224ffecom_constantunion (ffebldConstantUnion *cu, ffeinfoBasictype bt,
11225 ffeinfoKindtype kt, tree tree_type)
11226{
11227 tree item;
11228
11229 switch (bt)
11230 {
11231 case FFEINFO_basictypeINTEGER:
11232 {
11233 int val;
11234
11235 switch (kt)
11236 {
11237#if FFETARGET_okINTEGER1
11238 case FFEINFO_kindtypeINTEGER1:
11239 val = ffebld_cu_val_integer1 (*cu);
11240 break;
11241#endif
11242
11243#if FFETARGET_okINTEGER2
11244 case FFEINFO_kindtypeINTEGER2:
11245 val = ffebld_cu_val_integer2 (*cu);
11246 break;
11247#endif
11248
11249#if FFETARGET_okINTEGER3
11250 case FFEINFO_kindtypeINTEGER3:
11251 val = ffebld_cu_val_integer3 (*cu);
11252 break;
11253#endif
11254
11255#if FFETARGET_okINTEGER4
11256 case FFEINFO_kindtypeINTEGER4:
11257 val = ffebld_cu_val_integer4 (*cu);
11258 break;
11259#endif
11260
11261 default:
11262 assert ("bad INTEGER constant kind type" == NULL);
11263 /* Fall through. */
11264 case FFEINFO_kindtypeANY:
11265 return error_mark_node;
11266 }
11267 item = build_int_2 (val, (val < 0) ? -1 : 0);
11268 TREE_TYPE (item) = tree_type;
11269 }
11270 break;
11271
11272 case FFEINFO_basictypeLOGICAL:
11273 {
11274 int val;
11275
11276 switch (kt)
11277 {
11278#if FFETARGET_okLOGICAL1
11279 case FFEINFO_kindtypeLOGICAL1:
11280 val = ffebld_cu_val_logical1 (*cu);
11281 break;
11282#endif
11283
11284#if FFETARGET_okLOGICAL2
11285 case FFEINFO_kindtypeLOGICAL2:
11286 val = ffebld_cu_val_logical2 (*cu);
11287 break;
11288#endif
11289
11290#if FFETARGET_okLOGICAL3
11291 case FFEINFO_kindtypeLOGICAL3:
11292 val = ffebld_cu_val_logical3 (*cu);
11293 break;
11294#endif
11295
11296#if FFETARGET_okLOGICAL4
11297 case FFEINFO_kindtypeLOGICAL4:
11298 val = ffebld_cu_val_logical4 (*cu);
11299 break;
11300#endif
11301
11302 default:
11303 assert ("bad LOGICAL constant kind type" == NULL);
11304 /* Fall through. */
11305 case FFEINFO_kindtypeANY:
11306 return error_mark_node;
11307 }
11308 item = build_int_2 (val, (val < 0) ? -1 : 0);
11309 TREE_TYPE (item) = tree_type;
11310 }
11311 break;
11312
11313 case FFEINFO_basictypeREAL:
11314 {
11315 REAL_VALUE_TYPE val;
11316
11317 switch (kt)
11318 {
11319#if FFETARGET_okREAL1
11320 case FFEINFO_kindtypeREAL1:
11321 val = ffetarget_value_real1 (ffebld_cu_val_real1 (*cu));
11322 break;
11323#endif
11324
11325#if FFETARGET_okREAL2
11326 case FFEINFO_kindtypeREAL2:
11327 val = ffetarget_value_real2 (ffebld_cu_val_real2 (*cu));
11328 break;
11329#endif
11330
11331#if FFETARGET_okREAL3
11332 case FFEINFO_kindtypeREAL3:
11333 val = ffetarget_value_real3 (ffebld_cu_val_real3 (*cu));
11334 break;
11335#endif
11336
11337#if FFETARGET_okREAL4
11338 case FFEINFO_kindtypeREAL4:
11339 val = ffetarget_value_real4 (ffebld_cu_val_real4 (*cu));
11340 break;
11341#endif
11342
11343 default:
11344 assert ("bad REAL constant kind type" == NULL);
11345 /* Fall through. */
11346 case FFEINFO_kindtypeANY:
11347 return error_mark_node;
11348 }
11349 item = build_real (tree_type, val);
11350 }
11351 break;
11352
11353 case FFEINFO_basictypeCOMPLEX:
11354 {
11355 REAL_VALUE_TYPE real;
11356 REAL_VALUE_TYPE imag;
11357 tree el_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
11358
11359 switch (kt)
11360 {
11361#if FFETARGET_okCOMPLEX1
11362 case FFEINFO_kindtypeREAL1:
11363 real = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).real);
11364 imag = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).imaginary);
11365 break;
11366#endif
11367
11368#if FFETARGET_okCOMPLEX2
11369 case FFEINFO_kindtypeREAL2:
11370 real = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).real);
11371 imag = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).imaginary);
11372 break;
11373#endif
11374
11375#if FFETARGET_okCOMPLEX3
11376 case FFEINFO_kindtypeREAL3:
11377 real = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).real);
11378 imag = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).imaginary);
11379 break;
11380#endif
11381
11382#if FFETARGET_okCOMPLEX4
11383 case FFEINFO_kindtypeREAL4:
11384 real = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).real);
11385 imag = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).imaginary);
11386 break;
11387#endif
11388
11389 default:
11390 assert ("bad REAL constant kind type" == NULL);
11391 /* Fall through. */
11392 case FFEINFO_kindtypeANY:
11393 return error_mark_node;
11394 }
11395 item = ffecom_build_complex_constant_ (tree_type,
11396 build_real (el_type, real),
11397 build_real (el_type, imag));
11398 }
11399 break;
11400
11401 case FFEINFO_basictypeCHARACTER:
11402 { /* Happens only in DATA and similar contexts. */
11403 ffetargetCharacter1 val;
11404
11405 switch (kt)
11406 {
11407#if FFETARGET_okCHARACTER1
11408 case FFEINFO_kindtypeLOGICAL1:
11409 val = ffebld_cu_val_character1 (*cu);
11410 break;
11411#endif
11412
11413 default:
11414 assert ("bad CHARACTER constant kind type" == NULL);
11415 /* Fall through. */
11416 case FFEINFO_kindtypeANY:
11417 return error_mark_node;
11418 }
11419 item = build_string (ffetarget_length_character1 (val),
11420 ffetarget_text_character1 (val));
11421 TREE_TYPE (item)
11422 = build_type_variant (build_array_type (char_type_node,
11423 build_range_type
11424 (integer_type_node,
11425 integer_one_node,
11426 build_int_2
11427 (ffetarget_length_character1
11428 (val), 0))),
11429 1, 0);
11430 }
11431 break;
11432
11433 case FFEINFO_basictypeHOLLERITH:
11434 {
11435 ffetargetHollerith h;
11436
11437 h = ffebld_cu_val_hollerith (*cu);
11438
11439 /* If not at least as wide as default INTEGER, widen it. */
11440 if (h.length >= FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE)
11441 item = build_string (h.length, h.text);
11442 else
11443 {
11444 char str[FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE];
11445
11446 memcpy (str, h.text, h.length);
11447 memset (&str[h.length], ' ',
11448 FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE
11449 - h.length);
11450 item = build_string (FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE,
11451 str);
11452 }
11453 TREE_TYPE (item)
11454 = build_type_variant (build_array_type (char_type_node,
11455 build_range_type
11456 (integer_type_node,
11457 integer_one_node,
11458 build_int_2
11459 (h.length, 0))),
11460 1, 0);
11461 }
11462 break;
11463
11464 case FFEINFO_basictypeTYPELESS:
11465 {
11466 ffetargetInteger1 ival;
11467 ffetargetTypeless tless;
11468 ffebad error;
11469
11470 tless = ffebld_cu_val_typeless (*cu);
11471 error = ffetarget_convert_integer1_typeless (&ival, tless);
11472 assert (error == FFEBAD);
11473
11474 item = build_int_2 ((int) ival, 0);
11475 }
11476 break;
11477
11478 default:
11479 assert ("not yet on constant type" == NULL);
11480 /* Fall through. */
11481 case FFEINFO_basictypeANY:
11482 return error_mark_node;
11483 }
11484
11485 TREE_CONSTANT (item) = 1;
11486
11487 return item;
11488}
11489
11490#endif
11491
11492/* Handy way to make a field in a struct/union. */
11493
11494#if FFECOM_targetCURRENT == FFECOM_targetGCC
11495tree
11496ffecom_decl_field (tree context, tree prevfield,
11497 char *name, tree type)
11498{
11499 tree field;
11500
11501 field = build_decl (FIELD_DECL, get_identifier (name), type);
11502 DECL_CONTEXT (field) = context;
11503 DECL_FRAME_SIZE (field) = 0;
11504 if (prevfield != NULL_TREE)
11505 TREE_CHAIN (prevfield) = field;
11506
11507 return field;
11508}
11509
11510#endif
11511
11512void
11513ffecom_close_include (FILE *f)
11514{
11515#if FFECOM_GCC_INCLUDE
11516 ffecom_close_include_ (f);
11517#endif
11518}
11519
11520int
11521ffecom_decode_include_option (char *spec)
11522{
11523#if FFECOM_GCC_INCLUDE
11524 return ffecom_decode_include_option_ (spec);
11525#else
11526 return 1;
11527#endif
11528}
11529
11530/* ffecom_end_transition -- Perform end transition on all symbols
11531
11532 ffecom_end_transition();
11533
11534 Calls ffecom_sym_end_transition for each global and local symbol. */
11535
11536void
11537ffecom_end_transition ()
11538{
11539#if FFECOM_targetCURRENT == FFECOM_targetGCC
11540 ffebld item;
11541#endif
11542
11543 if (ffe_is_ffedebug ())
11544 fprintf (dmpout, "; end_stmt_transition\n");
11545
11546#if FFECOM_targetCURRENT == FFECOM_targetGCC
11547 ffecom_list_blockdata_ = NULL;
11548 ffecom_list_common_ = NULL;
11549#endif
11550
11551 ffesymbol_drive (ffecom_sym_end_transition);
11552 if (ffe_is_ffedebug ())
11553 {
11554 ffestorag_report ();
8b45da67 11555#if FFECOM_targetCURRENT == FFECOM_targetFFE
5ff904cd 11556 ffesymbol_report_all ();
8b45da67 11557#endif
5ff904cd
JL
11558 }
11559
11560#if FFECOM_targetCURRENT == FFECOM_targetGCC
11561 ffecom_start_progunit_ ();
11562
11563 for (item = ffecom_list_blockdata_;
11564 item != NULL;
11565 item = ffebld_trail (item))
11566 {
11567 ffebld callee;
11568 ffesymbol s;
11569 tree dt;
11570 tree t;
11571 tree var;
11572 int yes;
11573 static int number = 0;
11574
11575 callee = ffebld_head (item);
11576 s = ffebld_symter (callee);
11577 t = ffesymbol_hook (s).decl_tree;
11578 if (t == NULL_TREE)
11579 {
11580 s = ffecom_sym_transform_ (s);
11581 t = ffesymbol_hook (s).decl_tree;
11582 }
11583
11584 yes = suspend_momentary ();
11585
11586 dt = build_pointer_type (TREE_TYPE (t));
11587
11588 var = build_decl (VAR_DECL,
11589 ffecom_get_invented_identifier ("__g77_forceload_%d",
11590 NULL, number++),
11591 dt);
11592 DECL_EXTERNAL (var) = 0;
11593 TREE_STATIC (var) = 1;
11594 TREE_PUBLIC (var) = 0;
11595 DECL_INITIAL (var) = error_mark_node;
11596 TREE_USED (var) = 1;
11597
11598 var = start_decl (var, FALSE);
11599
11600 t = ffecom_1 (ADDR_EXPR, dt, t);
11601
11602 finish_decl (var, t, FALSE);
11603
11604 resume_momentary (yes);
11605 }
11606
11607 /* This handles any COMMON areas that weren't referenced but have, for
11608 example, important initial data. */
11609
11610 for (item = ffecom_list_common_;
11611 item != NULL;
11612 item = ffebld_trail (item))
11613 ffecom_transform_common_ (ffebld_symter (ffebld_head (item)));
11614
11615 ffecom_list_common_ = NULL;
11616#endif
11617}
11618
11619/* ffecom_exec_transition -- Perform exec transition on all symbols
11620
11621 ffecom_exec_transition();
11622
11623 Calls ffecom_sym_exec_transition for each global and local symbol.
11624 Make sure error updating not inhibited. */
11625
11626void
11627ffecom_exec_transition ()
11628{
11629 bool inhibited;
11630
11631 if (ffe_is_ffedebug ())
11632 fprintf (dmpout, "; exec_stmt_transition\n");
11633
11634 inhibited = ffebad_inhibit ();
11635 ffebad_set_inhibit (FALSE);
11636
11637 ffesymbol_drive (ffecom_sym_exec_transition); /* Don't retract! */
11638 ffeequiv_exec_transition (); /* Handle all pending EQUIVALENCEs. */
11639 if (ffe_is_ffedebug ())
11640 {
11641 ffestorag_report ();
8b45da67 11642#if FFECOM_targetCURRENT == FFECOM_targetFFE
5ff904cd 11643 ffesymbol_report_all ();
8b45da67 11644#endif
5ff904cd
JL
11645 }
11646
11647 if (inhibited)
11648 ffebad_set_inhibit (TRUE);
11649}
11650
11651/* ffecom_expand_let_stmt -- Compile let (assignment) statement
11652
11653 ffebld dest;
11654 ffebld source;
11655 ffecom_expand_let_stmt(dest,source);
11656
11657 Convert dest and source using ffecom_expr, then join them
11658 with an ASSIGN op and pass the whole thing to expand_expr_stmt. */
11659
11660#if FFECOM_targetCURRENT == FFECOM_targetGCC
11661void
11662ffecom_expand_let_stmt (ffebld dest, ffebld source)
11663{
11664 tree dest_tree;
11665 tree dest_length;
11666 tree source_tree;
11667 tree expr_tree;
11668
11669 if (ffeinfo_basictype (ffebld_info (dest)) != FFEINFO_basictypeCHARACTER)
11670 {
11671 bool dest_used;
11672
11673 dest_tree = ffecom_expr_rw (dest);
11674 if (dest_tree == error_mark_node)
11675 return;
11676
11677 if ((TREE_CODE (dest_tree) != VAR_DECL)
11678 || TREE_ADDRESSABLE (dest_tree))
092a4ef8
RH
11679 source_tree = ffecom_expr_ (source, dest_tree, dest, &dest_used,
11680 FALSE, FALSE);
5ff904cd
JL
11681 else
11682 {
11683 source_tree = ffecom_expr (source);
11684 dest_used = FALSE;
11685 }
11686 if (source_tree == error_mark_node)
11687 return;
11688
11689 if (dest_used)
11690 expr_tree = source_tree;
11691 else
11692 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11693 dest_tree,
11694 source_tree);
11695
11696 expand_expr_stmt (expr_tree);
11697 return;
11698 }
11699
11700 ffecom_push_calltemps ();
11701 ffecom_char_args_ (&dest_tree, &dest_length, dest);
11702 ffecom_let_char_ (dest_tree, dest_length, ffebld_size_known (dest),
11703 source);
11704 ffecom_pop_calltemps ();
11705}
11706
11707#endif
11708/* ffecom_expr -- Transform expr into gcc tree
11709
11710 tree t;
11711 ffebld expr; // FFE expression.
11712 tree = ffecom_expr(expr);
11713
11714 Recursive descent on expr while making corresponding tree nodes and
11715 attaching type info and such. */
11716
11717#if FFECOM_targetCURRENT == FFECOM_targetGCC
11718tree
11719ffecom_expr (ffebld expr)
11720{
092a4ef8 11721 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, FALSE, FALSE);
5ff904cd
JL
11722}
11723
11724#endif
11725/* Like ffecom_expr, but return tree usable for assigned GOTO or FORMAT. */
11726
11727#if FFECOM_targetCURRENT == FFECOM_targetGCC
11728tree
11729ffecom_expr_assign (ffebld expr)
11730{
092a4ef8 11731 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
5ff904cd
JL
11732}
11733
11734#endif
11735/* Like ffecom_expr_rw, but return tree usable for ASSIGN. */
11736
11737#if FFECOM_targetCURRENT == FFECOM_targetGCC
11738tree
11739ffecom_expr_assign_w (ffebld expr)
11740{
092a4ef8 11741 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
5ff904cd
JL
11742}
11743
11744#endif
11745/* Transform expr for use as into read/write tree and stabilize the
11746 reference. Not for use on CHARACTER expressions.
11747
11748 Recursive descent on expr while making corresponding tree nodes and
11749 attaching type info and such. */
11750
11751#if FFECOM_targetCURRENT == FFECOM_targetGCC
11752tree
11753ffecom_expr_rw (ffebld expr)
11754{
11755 assert (expr != NULL);
11756
11757 return stabilize_reference (ffecom_expr (expr));
11758}
11759
11760#endif
11761/* Do global stuff. */
11762
11763#if FFECOM_targetCURRENT == FFECOM_targetGCC
11764void
11765ffecom_finish_compile ()
11766{
11767 assert (ffecom_outer_function_decl_ == NULL_TREE);
11768 assert (current_function_decl == NULL_TREE);
11769
11770 ffeglobal_drive (ffecom_finish_global_);
11771}
11772
11773#endif
11774/* Public entry point for front end to access finish_decl. */
11775
11776#if FFECOM_targetCURRENT == FFECOM_targetGCC
11777void
11778ffecom_finish_decl (tree decl, tree init, bool is_top_level)
11779{
11780 assert (!is_top_level);
11781 finish_decl (decl, init, FALSE);
11782}
11783
11784#endif
11785/* Finish a program unit. */
11786
11787#if FFECOM_targetCURRENT == FFECOM_targetGCC
11788void
11789ffecom_finish_progunit ()
11790{
11791 ffecom_end_compstmt_ ();
11792
11793 ffecom_previous_function_decl_ = current_function_decl;
11794 ffecom_which_entrypoint_decl_ = NULL_TREE;
11795
11796 finish_function (0);
11797}
11798
11799#endif
11800/* Wrapper for get_identifier. pattern is like "...%s...", text is
11801 inserted into final name in place of "%s", or if text is NULL,
11802 pattern is like "...%d..." and text form of number is inserted
11803 in place of "%d". */
11804
11805#if FFECOM_targetCURRENT == FFECOM_targetGCC
11806tree
11807ffecom_get_invented_identifier (char *pattern, char *text, int number)
11808{
11809 tree decl;
11810 char *nam;
11811 mallocSize lenlen;
11812 char space[66];
11813
11814 if (text == NULL)
11815 lenlen = strlen (pattern) + 20;
11816 else
11817 lenlen = strlen (pattern) + strlen (text) - 1;
11818 if (lenlen > ARRAY_SIZE (space))
11819 nam = malloc_new_ks (malloc_pool_image (), pattern, lenlen);
11820 else
11821 nam = &space[0];
11822 if (text == NULL)
11823 sprintf (&nam[0], pattern, number);
11824 else
11825 sprintf (&nam[0], pattern, text);
11826 decl = get_identifier (nam);
11827 if (lenlen > ARRAY_SIZE (space))
11828 malloc_kill_ks (malloc_pool_image (), nam, lenlen);
11829
11830 IDENTIFIER_INVENTED (decl) = 1;
11831
11832 return decl;
11833}
11834
11835ffeinfoBasictype
11836ffecom_gfrt_basictype (ffecomGfrt gfrt)
11837{
11838 assert (gfrt < FFECOM_gfrt);
11839
11840 switch (ffecom_gfrt_type_[gfrt])
11841 {
11842 case FFECOM_rttypeVOID_:
6d433196 11843 case FFECOM_rttypeVOIDSTAR_:
5ff904cd
JL
11844 return FFEINFO_basictypeNONE;
11845
795232f7 11846 case FFECOM_rttypeFTNINT_:
5ff904cd
JL
11847 return FFEINFO_basictypeINTEGER;
11848
11849 case FFECOM_rttypeINTEGER_:
11850 return FFEINFO_basictypeINTEGER;
11851
11852 case FFECOM_rttypeLONGINT_:
11853 return FFEINFO_basictypeINTEGER;
11854
11855 case FFECOM_rttypeLOGICAL_:
11856 return FFEINFO_basictypeLOGICAL;
11857
11858 case FFECOM_rttypeREAL_F2C_:
11859 case FFECOM_rttypeREAL_GNU_:
11860 return FFEINFO_basictypeREAL;
11861
11862 case FFECOM_rttypeCOMPLEX_F2C_:
11863 case FFECOM_rttypeCOMPLEX_GNU_:
11864 return FFEINFO_basictypeCOMPLEX;
11865
11866 case FFECOM_rttypeDOUBLE_:
795232f7 11867 case FFECOM_rttypeDOUBLEREAL_:
5ff904cd
JL
11868 return FFEINFO_basictypeREAL;
11869
11870 case FFECOM_rttypeDBLCMPLX_F2C_:
11871 case FFECOM_rttypeDBLCMPLX_GNU_:
11872 return FFEINFO_basictypeCOMPLEX;
11873
11874 case FFECOM_rttypeCHARACTER_:
11875 return FFEINFO_basictypeCHARACTER;
11876
11877 default:
11878 return FFEINFO_basictypeANY;
11879 }
11880}
11881
11882ffeinfoKindtype
11883ffecom_gfrt_kindtype (ffecomGfrt gfrt)
11884{
11885 assert (gfrt < FFECOM_gfrt);
11886
11887 switch (ffecom_gfrt_type_[gfrt])
11888 {
11889 case FFECOM_rttypeVOID_:
6d433196 11890 case FFECOM_rttypeVOIDSTAR_:
5ff904cd
JL
11891 return FFEINFO_kindtypeNONE;
11892
795232f7 11893 case FFECOM_rttypeFTNINT_:
5ff904cd
JL
11894 return FFEINFO_kindtypeINTEGER1;
11895
11896 case FFECOM_rttypeINTEGER_:
11897 return FFEINFO_kindtypeINTEGER1;
11898
11899 case FFECOM_rttypeLONGINT_:
11900 return FFEINFO_kindtypeINTEGER4;
11901
11902 case FFECOM_rttypeLOGICAL_:
11903 return FFEINFO_kindtypeLOGICAL1;
11904
11905 case FFECOM_rttypeREAL_F2C_:
11906 case FFECOM_rttypeREAL_GNU_:
11907 return FFEINFO_kindtypeREAL1;
11908
11909 case FFECOM_rttypeCOMPLEX_F2C_:
11910 case FFECOM_rttypeCOMPLEX_GNU_:
11911 return FFEINFO_kindtypeREAL1;
11912
11913 case FFECOM_rttypeDOUBLE_:
795232f7 11914 case FFECOM_rttypeDOUBLEREAL_:
5ff904cd
JL
11915 return FFEINFO_kindtypeREAL2;
11916
11917 case FFECOM_rttypeDBLCMPLX_F2C_:
11918 case FFECOM_rttypeDBLCMPLX_GNU_:
11919 return FFEINFO_kindtypeREAL2;
11920
11921 case FFECOM_rttypeCHARACTER_:
11922 return FFEINFO_kindtypeCHARACTER1;
11923
11924 default:
11925 return FFEINFO_kindtypeANY;
11926 }
11927}
11928
11929void
11930ffecom_init_0 ()
11931{
11932 tree endlink;
11933 int i;
11934 int j;
11935 tree t;
11936 tree field;
11937 ffetype type;
11938 ffetype base_type;
11939
11940 /* This block of code comes from the now-obsolete cktyps.c. It checks
11941 whether the compiler environment is buggy in known ways, some of which
11942 would, if not explicitly checked here, result in subtle bugs in g77. */
11943
11944 if (ffe_is_do_internal_checks ())
11945 {
11946 static char names[][12]
11947 =
11948 {"bar", "bletch", "foo", "foobar"};
11949 char *name;
11950 unsigned long ul;
11951 double fl;
11952
11953 name = bsearch ("foo", &names[0], ARRAY_SIZE (names), sizeof (names[0]),
11954 (int (*)()) strcmp);
11955 if (name != (char *) &names[2])
11956 {
11957 assert ("bsearch doesn't work, #define FFEPROJ_BSEARCH 0 in proj.h"
11958 == NULL);
11959 abort ();
11960 }
11961
11962 ul = strtoul ("123456789", NULL, 10);
11963 if (ul != 123456789L)
11964 {
11965 assert ("strtoul doesn't have enough range, #define FFEPROJ_STRTOUL 0\
11966 in proj.h" == NULL);
11967 abort ();
11968 }
11969
11970 fl = atof ("56.789");
11971 if ((fl < 56.788) || (fl > 56.79))
11972 {
11973 assert ("atof not type double, fix your #include <stdio.h>"
11974 == NULL);
11975 abort ();
11976 }
11977 }
11978
092a4ef8
RH
11979 /* Set the sizetype before we do anything else. This _should_ be the
11980 first type we create. */
11981
11982 t = make_unsigned_type (POINTER_SIZE);
11983 assert (t == sizetype);
11984
5ff904cd
JL
11985#if FFECOM_GCC_INCLUDE
11986 ffecom_initialize_char_syntax_ ();
11987#endif
11988
11989 ffecom_outer_function_decl_ = NULL_TREE;
11990 current_function_decl = NULL_TREE;
11991 named_labels = NULL_TREE;
11992 current_binding_level = NULL_BINDING_LEVEL;
11993 free_binding_level = NULL_BINDING_LEVEL;
11994 pushlevel (0); /* make the binding_level structure for
11995 global names */
11996 global_binding_level = current_binding_level;
11997
11998 /* Define `int' and `char' first so that dbx will output them first. */
11999
12000 integer_type_node = make_signed_type (INT_TYPE_SIZE);
12001 pushdecl (build_decl (TYPE_DECL, get_identifier ("int"),
12002 integer_type_node));
12003
12004 char_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
12005 pushdecl (build_decl (TYPE_DECL, get_identifier ("char"),
12006 char_type_node));
12007
12008 long_integer_type_node = make_signed_type (LONG_TYPE_SIZE);
12009 pushdecl (build_decl (TYPE_DECL, get_identifier ("long int"),
12010 long_integer_type_node));
12011
12012 unsigned_type_node = make_unsigned_type (INT_TYPE_SIZE);
12013 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned int"),
12014 unsigned_type_node));
12015
12016 long_unsigned_type_node = make_unsigned_type (LONG_TYPE_SIZE);
12017 pushdecl (build_decl (TYPE_DECL, get_identifier ("long unsigned int"),
12018 long_unsigned_type_node));
12019
12020 long_long_integer_type_node = make_signed_type (LONG_LONG_TYPE_SIZE);
12021 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long int"),
12022 long_long_integer_type_node));
12023
12024 long_long_unsigned_type_node = make_unsigned_type (LONG_LONG_TYPE_SIZE);
12025 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"),
12026 long_long_unsigned_type_node));
12027
5ff904cd
JL
12028 error_mark_node = make_node (ERROR_MARK);
12029 TREE_TYPE (error_mark_node) = error_mark_node;
12030
12031 short_integer_type_node = make_signed_type (SHORT_TYPE_SIZE);
12032 pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"),
12033 short_integer_type_node));
12034
12035 short_unsigned_type_node = make_unsigned_type (SHORT_TYPE_SIZE);
12036 pushdecl (build_decl (TYPE_DECL, get_identifier ("short unsigned int"),
12037 short_unsigned_type_node));
12038
12039 /* Define both `signed char' and `unsigned char'. */
12040 signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE);
12041 pushdecl (build_decl (TYPE_DECL, get_identifier ("signed char"),
12042 signed_char_type_node));
12043
12044 unsigned_char_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
12045 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned char"),
12046 unsigned_char_type_node));
12047
12048 float_type_node = make_node (REAL_TYPE);
12049 TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE;
12050 layout_type (float_type_node);
12051 pushdecl (build_decl (TYPE_DECL, get_identifier ("float"),
12052 float_type_node));
12053
12054 double_type_node = make_node (REAL_TYPE);
12055 TYPE_PRECISION (double_type_node) = DOUBLE_TYPE_SIZE;
12056 layout_type (double_type_node);
12057 pushdecl (build_decl (TYPE_DECL, get_identifier ("double"),
12058 double_type_node));
12059
12060 long_double_type_node = make_node (REAL_TYPE);
12061 TYPE_PRECISION (long_double_type_node) = LONG_DOUBLE_TYPE_SIZE;
12062 layout_type (long_double_type_node);
12063 pushdecl (build_decl (TYPE_DECL, get_identifier ("long double"),
12064 long_double_type_node));
12065
12066 complex_integer_type_node = ffecom_make_complex_type_ (integer_type_node);
12067 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"),
12068 complex_integer_type_node));
12069
12070 complex_float_type_node = ffecom_make_complex_type_ (float_type_node);
12071 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"),
12072 complex_float_type_node));
12073
12074 complex_double_type_node = ffecom_make_complex_type_ (double_type_node);
12075 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"),
12076 complex_double_type_node));
12077
12078 complex_long_double_type_node = ffecom_make_complex_type_ (long_double_type_node);
12079 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"),
12080 complex_long_double_type_node));
12081
12082 integer_zero_node = build_int_2 (0, 0);
12083 TREE_TYPE (integer_zero_node) = integer_type_node;
12084 integer_one_node = build_int_2 (1, 0);
12085 TREE_TYPE (integer_one_node) = integer_type_node;
12086
12087 size_zero_node = build_int_2 (0, 0);
12088 TREE_TYPE (size_zero_node) = sizetype;
12089 size_one_node = build_int_2 (1, 0);
12090 TREE_TYPE (size_one_node) = sizetype;
12091
12092 void_type_node = make_node (VOID_TYPE);
12093 pushdecl (build_decl (TYPE_DECL, get_identifier ("void"),
12094 void_type_node));
12095 layout_type (void_type_node); /* Uses integer_zero_node */
12096 /* We are not going to have real types in C with less than byte alignment,
12097 so we might as well not have any types that claim to have it. */
12098 TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
12099
12100 null_pointer_node = build_int_2 (0, 0);
12101 TREE_TYPE (null_pointer_node) = build_pointer_type (void_type_node);
12102 layout_type (TREE_TYPE (null_pointer_node));
12103
12104 string_type_node = build_pointer_type (char_type_node);
12105
12106 ffecom_tree_fun_type_void
12107 = build_function_type (void_type_node, NULL_TREE);
12108
12109 ffecom_tree_ptr_to_fun_type_void
12110 = build_pointer_type (ffecom_tree_fun_type_void);
12111
12112 endlink = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
12113
12114 float_ftype_float
12115 = build_function_type (float_type_node,
12116 tree_cons (NULL_TREE, float_type_node, endlink));
12117
12118 double_ftype_double
12119 = build_function_type (double_type_node,
12120 tree_cons (NULL_TREE, double_type_node, endlink));
12121
12122 ldouble_ftype_ldouble
12123 = build_function_type (long_double_type_node,
12124 tree_cons (NULL_TREE, long_double_type_node,
12125 endlink));
12126
12127 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
12128 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
12129 {
12130 ffecom_tree_type[i][j] = NULL_TREE;
12131 ffecom_tree_fun_type[i][j] = NULL_TREE;
12132 ffecom_tree_ptr_to_fun_type[i][j] = NULL_TREE;
12133 ffecom_f2c_typecode_[i][j] = -1;
12134 }
12135
12136 /* Set up standard g77 types. Note that INTEGER and LOGICAL are set
12137 to size FLOAT_TYPE_SIZE because they have to be the same size as
12138 REAL, which also is FLOAT_TYPE_SIZE, according to the standard.
12139 Compiler options and other such stuff that change the ways these
12140 types are set should not affect this particular setup. */
12141
12142 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1]
12143 = t = make_signed_type (FLOAT_TYPE_SIZE);
12144 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer"),
12145 t));
12146 type = ffetype_new ();
12147 base_type = type;
12148 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER1,
12149 type);
12150 ffetype_set_ams (type,
12151 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12152 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12153 ffetype_set_star (base_type,
12154 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12155 type);
12156 ffetype_set_kind (base_type, 1, type);
12157 assert (ffetype_size (type) == sizeof (ffetargetInteger1));
12158
12159 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER1]
12160 = t = make_unsigned_type (FLOAT_TYPE_SIZE); /* HOLLERITH means unsigned. */
12161 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned"),
12162 t));
12163
12164 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER2]
12165 = t = make_signed_type (CHAR_TYPE_SIZE);
12166 pushdecl (build_decl (TYPE_DECL, get_identifier ("byte"),
12167 t));
12168 type = ffetype_new ();
12169 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER2,
12170 type);
12171 ffetype_set_ams (type,
12172 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12173 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12174 ffetype_set_star (base_type,
12175 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12176 type);
12177 ffetype_set_kind (base_type, 3, type);
12178 assert (ffetype_size (type) == sizeof (ffetargetInteger2));
12179
12180 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER2]
12181 = t = make_unsigned_type (CHAR_TYPE_SIZE);
12182 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned byte"),
12183 t));
12184
12185 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER3]
12186 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
12187 pushdecl (build_decl (TYPE_DECL, get_identifier ("word"),
12188 t));
12189 type = ffetype_new ();
12190 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER3,
12191 type);
12192 ffetype_set_ams (type,
12193 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12194 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12195 ffetype_set_star (base_type,
12196 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12197 type);
12198 ffetype_set_kind (base_type, 6, type);
12199 assert (ffetype_size (type) == sizeof (ffetargetInteger3));
12200
12201 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER3]
12202 = t = make_unsigned_type (CHAR_TYPE_SIZE * 2);
12203 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned word"),
12204 t));
12205
12206 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER4]
12207 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
12208 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer4"),
12209 t));
12210 type = ffetype_new ();
12211 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER4,
12212 type);
12213 ffetype_set_ams (type,
12214 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12215 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12216 ffetype_set_star (base_type,
12217 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12218 type);
12219 ffetype_set_kind (base_type, 2, type);
12220 assert (ffetype_size (type) == sizeof (ffetargetInteger4));
12221
12222 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER4]
12223 = t = make_unsigned_type (FLOAT_TYPE_SIZE * 2);
12224 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned4"),
12225 t));
12226
12227#if 0
12228 if (ffe_is_do_internal_checks ()
12229 && LONG_TYPE_SIZE != FLOAT_TYPE_SIZE
12230 && LONG_TYPE_SIZE != CHAR_TYPE_SIZE
12231 && LONG_TYPE_SIZE != SHORT_TYPE_SIZE
12232 && LONG_TYPE_SIZE != LONG_LONG_TYPE_SIZE)
12233 {
12234 fprintf (stderr, "Sorry, no g77 support for LONG_TYPE_SIZE (%d bits) yet.\n",
12235 LONG_TYPE_SIZE);
12236 }
12237#endif
12238
12239 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL1]
12240 = t = make_signed_type (FLOAT_TYPE_SIZE);
12241 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical"),
12242 t));
12243 type = ffetype_new ();
12244 base_type = type;
12245 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL1,
12246 type);
12247 ffetype_set_ams (type,
12248 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12249 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12250 ffetype_set_star (base_type,
12251 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12252 type);
12253 ffetype_set_kind (base_type, 1, type);
12254 assert (ffetype_size (type) == sizeof (ffetargetLogical1));
12255
12256 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL2]
12257 = t = make_signed_type (CHAR_TYPE_SIZE);
12258 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical2"),
12259 t));
12260 type = ffetype_new ();
12261 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL2,
12262 type);
12263 ffetype_set_ams (type,
12264 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12265 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12266 ffetype_set_star (base_type,
12267 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12268 type);
12269 ffetype_set_kind (base_type, 3, type);
12270 assert (ffetype_size (type) == sizeof (ffetargetLogical2));
12271
12272 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL3]
12273 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
12274 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical3"),
12275 t));
12276 type = ffetype_new ();
12277 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL3,
12278 type);
12279 ffetype_set_ams (type,
12280 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12281 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12282 ffetype_set_star (base_type,
12283 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12284 type);
12285 ffetype_set_kind (base_type, 6, type);
12286 assert (ffetype_size (type) == sizeof (ffetargetLogical3));
12287
12288 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL4]
12289 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
12290 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical4"),
12291 t));
12292 type = ffetype_new ();
12293 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL4,
12294 type);
12295 ffetype_set_ams (type,
12296 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12297 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12298 ffetype_set_star (base_type,
12299 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12300 type);
12301 ffetype_set_kind (base_type, 2, type);
12302 assert (ffetype_size (type) == sizeof (ffetargetLogical4));
12303
12304 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
12305 = t = make_node (REAL_TYPE);
12306 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE;
12307 pushdecl (build_decl (TYPE_DECL, get_identifier ("real"),
12308 t));
12309 layout_type (t);
12310 type = ffetype_new ();
12311 base_type = type;
12312 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREAL1,
12313 type);
12314 ffetype_set_ams (type,
12315 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12316 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12317 ffetype_set_star (base_type,
12318 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12319 type);
12320 ffetype_set_kind (base_type, 1, type);
12321 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
12322 = FFETARGET_f2cTYREAL;
12323 assert (ffetype_size (type) == sizeof (ffetargetReal1));
12324
12325 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREALDOUBLE]
12326 = t = make_node (REAL_TYPE);
12327 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE * 2; /* Always twice REAL. */
12328 pushdecl (build_decl (TYPE_DECL, get_identifier ("double precision"),
12329 t));
12330 layout_type (t);
12331 type = ffetype_new ();
12332 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREALDOUBLE,
12333 type);
12334 ffetype_set_ams (type,
12335 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12336 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12337 ffetype_set_star (base_type,
12338 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12339 type);
12340 ffetype_set_kind (base_type, 2, type);
12341 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]
12342 = FFETARGET_f2cTYDREAL;
12343 assert (ffetype_size (type) == sizeof (ffetargetReal2));
12344
12345 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
12346 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]);
12347 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex"),
12348 t));
12349 type = ffetype_new ();
12350 base_type = type;
12351 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREAL1,
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, 1, type);
12360 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
12361 = FFETARGET_f2cTYCOMPLEX;
12362 assert (ffetype_size (type) == sizeof (ffetargetComplex1));
12363
12364 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREALDOUBLE]
12365 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]);
12366 pushdecl (build_decl (TYPE_DECL, get_identifier ("double complex"),
12367 t));
12368 type = ffetype_new ();
12369 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREALDOUBLE,
12370 type);
12371 ffetype_set_ams (type,
12372 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12373 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12374 ffetype_set_star (base_type,
12375 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12376 type);
12377 ffetype_set_kind (base_type, 2,
12378 type);
12379 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL2]
12380 = FFETARGET_f2cTYDCOMPLEX;
12381 assert (ffetype_size (type) == sizeof (ffetargetComplex2));
12382
12383 /* Make function and ptr-to-function types for non-CHARACTER types. */
12384
12385 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
12386 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
12387 {
12388 if ((t = ffecom_tree_type[i][j]) != NULL_TREE)
12389 {
12390 if (i == FFEINFO_basictypeINTEGER)
12391 {
12392 /* Figure out the smallest INTEGER type that can hold
12393 a pointer on this machine. */
12394 if (GET_MODE_SIZE (TYPE_MODE (t))
12395 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
12396 {
12397 if ((ffecom_pointer_kind_ == FFEINFO_kindtypeNONE)
12398 || (GET_MODE_SIZE (TYPE_MODE (ffecom_tree_type[i][ffecom_pointer_kind_]))
12399 > GET_MODE_SIZE (TYPE_MODE (t))))
12400 ffecom_pointer_kind_ = j;
12401 }
12402 }
12403 else if (i == FFEINFO_basictypeCOMPLEX)
12404 t = void_type_node;
12405 /* For f2c compatibility, REAL functions are really
12406 implemented as DOUBLE PRECISION. */
12407 else if ((i == FFEINFO_basictypeREAL)
12408 && (j == FFEINFO_kindtypeREAL1))
12409 t = ffecom_tree_type
12410 [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2];
12411
12412 t = ffecom_tree_fun_type[i][j] = build_function_type (t,
12413 NULL_TREE);
12414 ffecom_tree_ptr_to_fun_type[i][j] = build_pointer_type (t);
12415 }
12416 }
12417
12418 /* Set up pointer types. */
12419
12420 if (ffecom_pointer_kind_ == FFEINFO_basictypeNONE)
12421 fatal ("no INTEGER type can hold a pointer on this configuration");
12422 else if (0 && ffe_is_do_internal_checks ())
12423 fprintf (stderr, "Pointer type kt=%d\n", ffecom_pointer_kind_);
5ff904cd
JL
12424 ffetype_set_kind (ffeinfo_type (FFEINFO_basictypeINTEGER,
12425 FFEINFO_kindtypeINTEGERDEFAULT),
a835e351
CB
12426 7,
12427 ffeinfo_type (FFEINFO_basictypeINTEGER,
12428 ffecom_pointer_kind_));
5ff904cd
JL
12429
12430 if (ffe_is_ugly_assign ())
12431 ffecom_label_kind_ = ffecom_pointer_kind_; /* Require ASSIGN etc to this. */
12432 else
12433 ffecom_label_kind_ = FFEINFO_kindtypeINTEGERDEFAULT;
12434 if (0 && ffe_is_do_internal_checks ())
12435 fprintf (stderr, "Label type kt=%d\n", ffecom_label_kind_);
12436
12437 ffecom_integer_type_node
12438 = ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1];
12439 ffecom_integer_zero_node = convert (ffecom_integer_type_node,
12440 integer_zero_node);
12441 ffecom_integer_one_node = convert (ffecom_integer_type_node,
12442 integer_one_node);
12443
12444 /* Yes, the "FLOAT_TYPE_SIZE" references below are intentional.
12445 Turns out that by TYLONG, runtime/libI77/lio.h really means
12446 "whatever size an ftnint is". For consistency and sanity,
12447 com.h and runtime/f2c.h.in agree that flag, ftnint, and ftlen
12448 all are INTEGER, which we also make out of whatever back-end
12449 integer type is FLOAT_TYPE_SIZE bits wide. This change, from
12450 LONG_TYPE_SIZE, for TYLONG and TYLOGICAL, was necessary to
12451 accommodate machines like the Alpha. Note that this suggests
12452 f2c and libf2c are missing a distinction perhaps needed on
12453 some machines between "int" and "long int". -- burley 0.5.5 950215 */
12454
12455 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, FLOAT_TYPE_SIZE,
12456 FFETARGET_f2cTYLONG);
12457 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, SHORT_TYPE_SIZE,
12458 FFETARGET_f2cTYSHORT);
12459 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, CHAR_TYPE_SIZE,
12460 FFETARGET_f2cTYINT1);
12461 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, LONG_LONG_TYPE_SIZE,
12462 FFETARGET_f2cTYQUAD);
12463 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, FLOAT_TYPE_SIZE,
12464 FFETARGET_f2cTYLOGICAL);
12465 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, SHORT_TYPE_SIZE,
12466 FFETARGET_f2cTYLOGICAL2);
12467 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, CHAR_TYPE_SIZE,
12468 FFETARGET_f2cTYLOGICAL1);
12469 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, LONG_LONG_TYPE_SIZE,
12470 FFETARGET_f2cTYQUAD /* ~~~ */);
12471
12472 /* CHARACTER stuff is all special-cased, so it is not handled in the above
12473 loop. CHARACTER items are built as arrays of unsigned char. */
12474
12475 ffecom_tree_type[FFEINFO_basictypeCHARACTER]
12476 [FFEINFO_kindtypeCHARACTER1] = t = char_type_node;
12477 type = ffetype_new ();
12478 base_type = type;
12479 ffeinfo_set_type (FFEINFO_basictypeCHARACTER,
12480 FFEINFO_kindtypeCHARACTER1,
12481 type);
12482 ffetype_set_ams (type,
12483 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12484 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12485 ffetype_set_kind (base_type, 1, type);
12486 assert (ffetype_size (type)
12487 == sizeof (((ffetargetCharacter1) { 0, NULL }).text[0]));
12488
12489 ffecom_tree_fun_type[FFEINFO_basictypeCHARACTER]
12490 [FFEINFO_kindtypeCHARACTER1] = ffecom_tree_fun_type_void;
12491 ffecom_tree_ptr_to_fun_type[FFEINFO_basictypeCHARACTER]
12492 [FFEINFO_kindtypeCHARACTER1]
12493 = ffecom_tree_ptr_to_fun_type_void;
12494 ffecom_f2c_typecode_[FFEINFO_basictypeCHARACTER][FFEINFO_kindtypeCHARACTER1]
12495 = FFETARGET_f2cTYCHAR;
12496
12497 ffecom_f2c_typecode_[FFEINFO_basictypeANY][FFEINFO_kindtypeANY]
12498 = 0;
12499
12500 /* Make multi-return-value type and fields. */
12501
12502 ffecom_multi_type_node_ = make_node (UNION_TYPE);
12503
12504 field = NULL_TREE;
12505
12506 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
12507 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
12508 {
12509 char name[30];
12510
12511 if (ffecom_tree_type[i][j] == NULL_TREE)
12512 continue; /* Not supported. */
12513 sprintf (&name[0], "bt_%s_kt_%s",
12514 ffeinfo_basictype_string ((ffeinfoBasictype) i),
12515 ffeinfo_kindtype_string ((ffeinfoKindtype) j));
12516 ffecom_multi_fields_[i][j] = build_decl (FIELD_DECL,
12517 get_identifier (name),
12518 ffecom_tree_type[i][j]);
12519 DECL_CONTEXT (ffecom_multi_fields_[i][j])
12520 = ffecom_multi_type_node_;
12521 DECL_FRAME_SIZE (ffecom_multi_fields_[i][j]) = 0;
12522 TREE_CHAIN (ffecom_multi_fields_[i][j]) = field;
12523 field = ffecom_multi_fields_[i][j];
12524 }
12525
12526 TYPE_FIELDS (ffecom_multi_type_node_) = field;
12527 layout_type (ffecom_multi_type_node_);
12528
12529 /* Subroutines usually return integer because they might have alternate
12530 returns. */
12531
12532 ffecom_tree_subr_type
12533 = build_function_type (integer_type_node, NULL_TREE);
12534 ffecom_tree_ptr_to_subr_type
12535 = build_pointer_type (ffecom_tree_subr_type);
12536 ffecom_tree_blockdata_type
12537 = build_function_type (void_type_node, NULL_TREE);
12538
12539 builtin_function ("__builtin_sqrtf", float_ftype_float,
12540 BUILT_IN_FSQRT, "sqrtf");
12541 builtin_function ("__builtin_fsqrt", double_ftype_double,
12542 BUILT_IN_FSQRT, "sqrt");
12543 builtin_function ("__builtin_sqrtl", ldouble_ftype_ldouble,
12544 BUILT_IN_FSQRT, "sqrtl");
12545 builtin_function ("__builtin_sinf", float_ftype_float,
12546 BUILT_IN_SIN, "sinf");
12547 builtin_function ("__builtin_sin", double_ftype_double,
12548 BUILT_IN_SIN, "sin");
12549 builtin_function ("__builtin_sinl", ldouble_ftype_ldouble,
12550 BUILT_IN_SIN, "sinl");
12551 builtin_function ("__builtin_cosf", float_ftype_float,
12552 BUILT_IN_COS, "cosf");
12553 builtin_function ("__builtin_cos", double_ftype_double,
12554 BUILT_IN_COS, "cos");
12555 builtin_function ("__builtin_cosl", ldouble_ftype_ldouble,
12556 BUILT_IN_COS, "cosl");
12557
12558#if BUILT_FOR_270
12559 pedantic_lvalues = FALSE;
12560#endif
12561
12562 ffecom_f2c_make_type_ (&ffecom_f2c_integer_type_node,
12563 FFECOM_f2cINTEGER,
12564 "integer");
12565 ffecom_f2c_make_type_ (&ffecom_f2c_address_type_node,
12566 FFECOM_f2cADDRESS,
12567 "address");
12568 ffecom_f2c_make_type_ (&ffecom_f2c_real_type_node,
12569 FFECOM_f2cREAL,
12570 "real");
12571 ffecom_f2c_make_type_ (&ffecom_f2c_doublereal_type_node,
12572 FFECOM_f2cDOUBLEREAL,
12573 "doublereal");
12574 ffecom_f2c_make_type_ (&ffecom_f2c_complex_type_node,
12575 FFECOM_f2cCOMPLEX,
12576 "complex");
12577 ffecom_f2c_make_type_ (&ffecom_f2c_doublecomplex_type_node,
12578 FFECOM_f2cDOUBLECOMPLEX,
12579 "doublecomplex");
12580 ffecom_f2c_make_type_ (&ffecom_f2c_longint_type_node,
12581 FFECOM_f2cLONGINT,
12582 "longint");
12583 ffecom_f2c_make_type_ (&ffecom_f2c_logical_type_node,
12584 FFECOM_f2cLOGICAL,
12585 "logical");
12586 ffecom_f2c_make_type_ (&ffecom_f2c_flag_type_node,
12587 FFECOM_f2cFLAG,
12588 "flag");
12589 ffecom_f2c_make_type_ (&ffecom_f2c_ftnlen_type_node,
12590 FFECOM_f2cFTNLEN,
12591 "ftnlen");
12592 ffecom_f2c_make_type_ (&ffecom_f2c_ftnint_type_node,
12593 FFECOM_f2cFTNINT,
12594 "ftnint");
12595
12596 ffecom_f2c_ftnlen_zero_node
12597 = convert (ffecom_f2c_ftnlen_type_node, integer_zero_node);
12598
12599 ffecom_f2c_ftnlen_one_node
12600 = convert (ffecom_f2c_ftnlen_type_node, integer_one_node);
12601
12602 ffecom_f2c_ftnlen_two_node = build_int_2 (2, 0);
12603 TREE_TYPE (ffecom_f2c_ftnlen_two_node) = ffecom_integer_type_node;
12604
12605 ffecom_f2c_ptr_to_ftnlen_type_node
12606 = build_pointer_type (ffecom_f2c_ftnlen_type_node);
12607
12608 ffecom_f2c_ptr_to_ftnint_type_node
12609 = build_pointer_type (ffecom_f2c_ftnint_type_node);
12610
12611 ffecom_f2c_ptr_to_integer_type_node
12612 = build_pointer_type (ffecom_f2c_integer_type_node);
12613
12614 ffecom_f2c_ptr_to_real_type_node
12615 = build_pointer_type (ffecom_f2c_real_type_node);
12616
12617 ffecom_float_zero_ = build_real (float_type_node, dconst0);
12618 ffecom_double_zero_ = build_real (double_type_node, dconst0);
12619 {
12620 REAL_VALUE_TYPE point_5;
12621
12622#ifdef REAL_ARITHMETIC
12623 REAL_ARITHMETIC (point_5, RDIV_EXPR, dconst1, dconst2);
12624#else
12625 point_5 = .5;
12626#endif
12627 ffecom_float_half_ = build_real (float_type_node, point_5);
12628 ffecom_double_half_ = build_real (double_type_node, point_5);
12629 }
12630
12631 /* Do "extern int xargc;". */
12632
12633 ffecom_tree_xargc_ = build_decl (VAR_DECL,
1ed565d7 12634 get_identifier ("f__xargc"),
5ff904cd
JL
12635 integer_type_node);
12636 DECL_EXTERNAL (ffecom_tree_xargc_) = 1;
12637 TREE_STATIC (ffecom_tree_xargc_) = 1;
12638 TREE_PUBLIC (ffecom_tree_xargc_) = 1;
12639 ffecom_tree_xargc_ = start_decl (ffecom_tree_xargc_, FALSE);
12640 finish_decl (ffecom_tree_xargc_, NULL_TREE, FALSE);
12641
12642#if 0 /* This is being fixed, and seems to be working now. */
12643 if ((FLOAT_TYPE_SIZE != 32)
12644 || (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))) != 32))
12645 {
12646 warning ("configuration: REAL, INTEGER, and LOGICAL are %d bits wide,",
12647 (int) FLOAT_TYPE_SIZE);
12648 warning ("and pointers are %d bits wide, but g77 doesn't yet work",
12649 (int) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))));
12650 warning ("properly unless they all are 32 bits wide.");
12651 warning ("Please keep this in mind before you report bugs. g77 should");
12652 warning ("support non-32-bit machines better as of version 0.6.");
12653 }
12654#endif
12655
12656#if 0 /* Code in ste.c that would crash has been commented out. */
12657 if (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
12658 < TYPE_PRECISION (string_type_node))
12659 /* I/O will probably crash. */
12660 warning ("configuration: char * holds %d bits, but ftnlen only %d",
12661 TYPE_PRECISION (string_type_node),
12662 TYPE_PRECISION (ffecom_f2c_ftnlen_type_node));
12663#endif
12664
12665#if 0 /* ASSIGN-related stuff has been changed to accommodate this. */
12666 if (TYPE_PRECISION (ffecom_integer_type_node)
12667 < TYPE_PRECISION (string_type_node))
12668 /* ASSIGN 10 TO I will crash. */
12669 warning ("configuration: char * holds %d bits, but INTEGER only %d --\n\
12670 ASSIGN statement might fail",
12671 TYPE_PRECISION (string_type_node),
12672 TYPE_PRECISION (ffecom_integer_type_node));
12673#endif
12674}
12675
12676#endif
12677/* ffecom_init_2 -- Initialize
12678
12679 ffecom_init_2(); */
12680
12681#if FFECOM_targetCURRENT == FFECOM_targetGCC
12682void
12683ffecom_init_2 ()
12684{
12685 assert (ffecom_outer_function_decl_ == NULL_TREE);
12686 assert (current_function_decl == NULL_TREE);
12687 assert (ffecom_which_entrypoint_decl_ == NULL_TREE);
12688
12689 ffecom_master_arglist_ = NULL;
12690 ++ffecom_num_fns_;
12691 ffecom_latest_temp_ = NULL;
12692 ffecom_primary_entry_ = NULL;
12693 ffecom_is_altreturning_ = FALSE;
12694 ffecom_func_result_ = NULL_TREE;
12695 ffecom_multi_retval_ = NULL_TREE;
12696}
12697
12698#endif
12699/* ffecom_list_expr -- Transform list of exprs into gcc tree
12700
12701 tree t;
12702 ffebld expr; // FFE opITEM list.
12703 tree = ffecom_list_expr(expr);
12704
12705 List of actual args is transformed into corresponding gcc backend list. */
12706
12707#if FFECOM_targetCURRENT == FFECOM_targetGCC
12708tree
12709ffecom_list_expr (ffebld expr)
12710{
12711 tree list;
12712 tree *plist = &list;
12713 tree trail = NULL_TREE; /* Append char length args here. */
12714 tree *ptrail = &trail;
12715 tree length;
12716
12717 while (expr != NULL)
12718 {
12719 *plist
12720 = build_tree_list (NULL_TREE, ffecom_arg_expr (ffebld_head (expr),
12721 &length));
12722 plist = &TREE_CHAIN (*plist);
12723 expr = ffebld_trail (expr);
12724 if (length != NULL_TREE)
12725 {
12726 *ptrail = build_tree_list (NULL_TREE, length);
12727 ptrail = &TREE_CHAIN (*ptrail);
12728 }
12729 }
12730
12731 *plist = trail;
12732
12733 return list;
12734}
12735
12736#endif
12737/* ffecom_list_ptr_to_expr -- Transform list of exprs into gcc tree
12738
12739 tree t;
12740 ffebld expr; // FFE opITEM list.
12741 tree = ffecom_list_ptr_to_expr(expr);
12742
12743 List of actual args is transformed into corresponding gcc backend list for
12744 use in calling an external procedure (vs. a statement function). */
12745
12746#if FFECOM_targetCURRENT == FFECOM_targetGCC
12747tree
12748ffecom_list_ptr_to_expr (ffebld expr)
12749{
12750 tree list;
12751 tree *plist = &list;
12752 tree trail = NULL_TREE; /* Append char length args here. */
12753 tree *ptrail = &trail;
12754 tree length;
12755
12756 while (expr != NULL)
12757 {
12758 *plist
12759 = build_tree_list (NULL_TREE,
12760 ffecom_arg_ptr_to_expr (ffebld_head (expr),
12761 &length));
12762 plist = &TREE_CHAIN (*plist);
12763 expr = ffebld_trail (expr);
12764 if (length != NULL_TREE)
12765 {
12766 *ptrail = build_tree_list (NULL_TREE, length);
12767 ptrail = &TREE_CHAIN (*ptrail);
12768 }
12769 }
12770
12771 *plist = trail;
12772
12773 return list;
12774}
12775
12776#endif
12777/* Obtain gcc's LABEL_DECL tree for label. */
12778
12779#if FFECOM_targetCURRENT == FFECOM_targetGCC
12780tree
12781ffecom_lookup_label (ffelab label)
12782{
12783 tree glabel;
12784
12785 if (ffelab_hook (label) == NULL_TREE)
12786 {
12787 char labelname[16];
12788
12789 switch (ffelab_type (label))
12790 {
12791 case FFELAB_typeLOOPEND:
12792 case FFELAB_typeNOTLOOP:
12793 case FFELAB_typeENDIF:
12794 sprintf (labelname, "%" ffelabValue_f "u", ffelab_value (label));
12795 glabel = build_decl (LABEL_DECL, get_identifier (labelname),
12796 void_type_node);
12797 DECL_CONTEXT (glabel) = current_function_decl;
12798 DECL_MODE (glabel) = VOIDmode;
12799 break;
12800
12801 case FFELAB_typeFORMAT:
12802 push_obstacks_nochange ();
12803 end_temporary_allocation ();
12804
12805 glabel = build_decl (VAR_DECL,
12806 ffecom_get_invented_identifier
12807 ("__g77_format_%d", NULL,
12808 (int) ffelab_value (label)),
12809 build_type_variant (build_array_type
12810 (char_type_node,
12811 NULL_TREE),
12812 1, 0));
12813 TREE_CONSTANT (glabel) = 1;
12814 TREE_STATIC (glabel) = 1;
12815 DECL_CONTEXT (glabel) = 0;
12816 DECL_INITIAL (glabel) = NULL;
12817 make_decl_rtl (glabel, NULL, 0);
12818 expand_decl (glabel);
12819
12820 resume_temporary_allocation ();
12821 pop_obstacks ();
12822
12823 break;
12824
12825 case FFELAB_typeANY:
12826 glabel = error_mark_node;
12827 break;
12828
12829 default:
12830 assert ("bad label type" == NULL);
12831 glabel = NULL;
12832 break;
12833 }
12834 ffelab_set_hook (label, glabel);
12835 }
12836 else
12837 {
12838 glabel = ffelab_hook (label);
12839 }
12840
12841 return glabel;
12842}
12843
12844#endif
12845/* Stabilizes the arguments. Don't use this if the lhs and rhs come from
12846 a single source specification (as in the fourth argument of MVBITS).
12847 If the type is NULL_TREE, the type of lhs is used to make the type of
12848 the MODIFY_EXPR. */
12849
12850#if FFECOM_targetCURRENT == FFECOM_targetGCC
12851tree
12852ffecom_modify (tree newtype, tree lhs,
12853 tree rhs)
12854{
12855 if (lhs == error_mark_node || rhs == error_mark_node)
12856 return error_mark_node;
12857
12858 if (newtype == NULL_TREE)
12859 newtype = TREE_TYPE (lhs);
12860
12861 if (TREE_SIDE_EFFECTS (lhs))
12862 lhs = stabilize_reference (lhs);
12863
12864 return ffecom_2s (MODIFY_EXPR, newtype, lhs, rhs);
12865}
12866
12867#endif
12868
12869/* Register source file name. */
12870
12871void
12872ffecom_file (char *name)
12873{
12874#if FFECOM_GCC_INCLUDE
12875 ffecom_file_ (name);
12876#endif
12877}
12878
12879/* ffecom_notify_init_storage -- An aggregate storage is now fully init'ed
12880
12881 ffestorag st;
12882 ffecom_notify_init_storage(st);
12883
12884 Gets called when all possible units in an aggregate storage area (a LOCAL
12885 with equivalences or a COMMON) have been initialized. The initialization
12886 info either is in ffestorag_init or, if that is NULL,
12887 ffestorag_accretion:
12888
12889 ffestorag_init may contain an opCONTER or opARRTER. opCONTER may occur
12890 even for an array if the array is one element in length!
12891
12892 ffestorag_accretion will contain an opACCTER. It is much like an
12893 opARRTER except it has an ffebit object in it instead of just a size.
12894 The back end can use the info in the ffebit object, if it wants, to
12895 reduce the amount of actual initialization, but in any case it should
12896 kill the ffebit object when done. Also, set accretion to NULL but
12897 init to a non-NULL value.
12898
12899 After performing initialization, DO NOT set init to NULL, because that'll
12900 tell the front end it is ok for more initialization to happen. Instead,
12901 set init to an opANY expression or some such thing that you can use to
12902 tell that you've already initialized the object.
12903
12904 27-Oct-91 JCB 1.1
12905 Support two-pass FFE. */
12906
12907void
12908ffecom_notify_init_storage (ffestorag st)
12909{
12910 ffebld init; /* The initialization expression. */
12911#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12912 ffetargetOffset size; /* The size of the entity. */
a6fa6420 12913 ffetargetAlign pad; /* Its initial padding. */
5ff904cd
JL
12914#endif
12915
12916 if (ffestorag_init (st) == NULL)
12917 {
12918 init = ffestorag_accretion (st);
12919 assert (init != NULL);
12920 ffestorag_set_accretion (st, NULL);
12921 ffestorag_set_accretes (st, 0);
12922
12923#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12924 /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12925 size = ffebld_accter_size (init);
a6fa6420 12926 pad = ffebld_accter_pad (init);
5ff904cd
JL
12927 ffebit_kill (ffebld_accter_bits (init));
12928 ffebld_set_op (init, FFEBLD_opARRTER);
12929 ffebld_set_arrter (init, ffebld_accter (init));
12930 ffebld_arrter_set_size (init, size);
a6fa6420 12931 ffebld_arrter_set_pad (init, size);
5ff904cd
JL
12932#endif
12933
12934#if FFECOM_TWOPASS
12935 ffestorag_set_init (st, init);
12936#endif
12937 }
12938#if FFECOM_ONEPASS
12939 else
12940 init = ffestorag_init (st);
12941#endif
12942
12943#if FFECOM_ONEPASS /* Process the inits, wipe 'em out. */
12944 ffestorag_set_init (st, ffebld_new_any ());
12945
12946 if (ffebld_op (init) == FFEBLD_opANY)
12947 return; /* Oh, we already did this! */
12948
12949#if FFECOM_targetCURRENT == FFECOM_targetFFE
12950 {
12951 ffesymbol s;
12952
12953 if (ffestorag_symbol (st) != NULL)
12954 s = ffestorag_symbol (st);
12955 else
12956 s = ffestorag_typesymbol (st);
12957
12958 fprintf (dmpout, "= initialize_storage \"%s\" ",
12959 (s != NULL) ? ffesymbol_text (s) : "(unnamed)");
12960 ffebld_dump (init);
12961 fputc ('\n', dmpout);
12962 }
12963#endif
12964
12965#endif /* if FFECOM_ONEPASS */
12966}
12967
12968/* ffecom_notify_init_symbol -- A symbol is now fully init'ed
12969
12970 ffesymbol s;
12971 ffecom_notify_init_symbol(s);
12972
12973 Gets called when all possible units in a symbol (not placed in COMMON
12974 or involved in EQUIVALENCE, unless it as yet has no ffestorag object)
12975 have been initialized. The initialization info either is in
12976 ffesymbol_init or, if that is NULL, ffesymbol_accretion:
12977
12978 ffesymbol_init may contain an opCONTER or opARRTER. opCONTER may occur
12979 even for an array if the array is one element in length!
12980
12981 ffesymbol_accretion will contain an opACCTER. It is much like an
12982 opARRTER except it has an ffebit object in it instead of just a size.
12983 The back end can use the info in the ffebit object, if it wants, to
12984 reduce the amount of actual initialization, but in any case it should
12985 kill the ffebit object when done. Also, set accretion to NULL but
12986 init to a non-NULL value.
12987
12988 After performing initialization, DO NOT set init to NULL, because that'll
12989 tell the front end it is ok for more initialization to happen. Instead,
12990 set init to an opANY expression or some such thing that you can use to
12991 tell that you've already initialized the object.
12992
12993 27-Oct-91 JCB 1.1
12994 Support two-pass FFE. */
12995
12996void
12997ffecom_notify_init_symbol (ffesymbol s)
12998{
12999 ffebld init; /* The initialization expression. */
13000#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
13001 ffetargetOffset size; /* The size of the entity. */
a6fa6420 13002 ffetargetAlign pad; /* Its initial padding. */
5ff904cd
JL
13003#endif
13004
13005 if (ffesymbol_storage (s) == NULL)
13006 return; /* Do nothing until COMMON/EQUIVALENCE
13007 possibilities checked. */
13008
13009 if ((ffesymbol_init (s) == NULL)
13010 && ((init = ffesymbol_accretion (s)) != NULL))
13011 {
13012 ffesymbol_set_accretion (s, NULL);
13013 ffesymbol_set_accretes (s, 0);
13014
13015#if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
13016 /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
13017 size = ffebld_accter_size (init);
a6fa6420 13018 pad = ffebld_accter_pad (init);
5ff904cd
JL
13019 ffebit_kill (ffebld_accter_bits (init));
13020 ffebld_set_op (init, FFEBLD_opARRTER);
13021 ffebld_set_arrter (init, ffebld_accter (init));
13022 ffebld_arrter_set_size (init, size);
a6fa6420 13023 ffebld_arrter_set_pad (init, size);
5ff904cd
JL
13024#endif
13025
13026#if FFECOM_TWOPASS
13027 ffesymbol_set_init (s, init);
13028#endif
13029 }
13030#if FFECOM_ONEPASS
13031 else
13032 init = ffesymbol_init (s);
13033#endif
13034
13035#if FFECOM_ONEPASS
13036 ffesymbol_set_init (s, ffebld_new_any ());
13037
13038 if (ffebld_op (init) == FFEBLD_opANY)
13039 return; /* Oh, we already did this! */
13040
13041#if FFECOM_targetCURRENT == FFECOM_targetFFE
13042 fprintf (dmpout, "= initialize_symbol \"%s\" ", ffesymbol_text (s));
13043 ffebld_dump (init);
13044 fputc ('\n', dmpout);
13045#endif
13046
13047#endif /* if FFECOM_ONEPASS */
13048}
13049
13050/* ffecom_notify_primary_entry -- Learn which is the primary entry point
13051
13052 ffesymbol s;
13053 ffecom_notify_primary_entry(s);
13054
13055 Gets called when implicit or explicit PROGRAM statement seen or when
13056 FUNCTION, SUBROUTINE, or BLOCK DATA statement seen, with the primary
13057 global symbol that serves as the entry point. */
13058
13059void
13060ffecom_notify_primary_entry (ffesymbol s)
13061{
13062 ffecom_primary_entry_ = s;
13063 ffecom_primary_entry_kind_ = ffesymbol_kind (s);
13064
13065 if ((ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
13066 || (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE))
13067 ffecom_primary_entry_is_proc_ = TRUE;
13068 else
13069 ffecom_primary_entry_is_proc_ = FALSE;
13070
13071 if (!ffe_is_silent ())
13072 {
13073 if (ffecom_primary_entry_kind_ == FFEINFO_kindPROGRAM)
13074 fprintf (stderr, "%s:\n", ffesymbol_text (s));
13075 else
13076 fprintf (stderr, " %s:\n", ffesymbol_text (s));
13077 }
13078
13079#if FFECOM_targetCURRENT == FFECOM_targetGCC
13080 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
13081 {
13082 ffebld list;
13083 ffebld arg;
13084
13085 for (list = ffesymbol_dummyargs (s);
13086 list != NULL;
13087 list = ffebld_trail (list))
13088 {
13089 arg = ffebld_head (list);
13090 if (ffebld_op (arg) == FFEBLD_opSTAR)
13091 {
13092 ffecom_is_altreturning_ = TRUE;
13093 break;
13094 }
13095 }
13096 }
13097#endif
13098}
13099
13100FILE *
13101ffecom_open_include (char *name, ffewhereLine l, ffewhereColumn c)
13102{
13103#if FFECOM_GCC_INCLUDE
13104 return ffecom_open_include_ (name, l, c);
13105#else
13106 return fopen (name, "r");
13107#endif
13108}
13109
13110/* Clean up after making automatically popped call-arg temps.
13111
13112 Call this in pairs with push_calltemps around calls to
13113 ffecom_arg_ptr_to_expr if the latter might use temporaries.
13114 Any temporaries made within the outermost sequence of
13115 push_calltemps and pop_calltemps, that are marked as "auto-pop"
13116 meaning they won't be explicitly popped (freed), are popped
13117 at this point so they can be reused later.
13118
13119 NOTE: when called by ffecom_gen_sfuncdef_, ffecom_pending_calls_
13120 should come in == 1, and all of the in-use auto-pop temps
13121 should have DECL_CONTEXT (temp->t) == current_function_decl.
13122 Moreover, these temps should _never_ be re-used in future
13123 calls to ffecom_push_tempvar -- since current_function_decl will
13124 never be the same again.
13125
13126 SO, it could be a minor win in terms of compile time to just
13127 strip these temps off the list. That is, if the above assumptions
13128 are correct, just remove from the list of temps any temp
13129 that is both in-use and has DECL_CONTEXT (temp->t)
13130 == current_function_decl, when called from ffecom_gen_sfuncdef_. */
13131
13132#if FFECOM_targetCURRENT == FFECOM_targetGCC
13133void
13134ffecom_pop_calltemps ()
13135{
13136 ffecomTemp_ temp;
13137
13138 assert (ffecom_pending_calls_ > 0);
13139
13140 if (--ffecom_pending_calls_ == 0)
13141 for (temp = ffecom_latest_temp_; temp != NULL; temp = temp->next)
13142 if (temp->auto_pop)
13143 temp->in_use = FALSE;
13144}
13145
13146#endif
13147/* Mark latest temp with given tree as no longer in use. */
13148
13149#if FFECOM_targetCURRENT == FFECOM_targetGCC
13150void
13151ffecom_pop_tempvar (tree t)
13152{
13153 ffecomTemp_ temp;
13154
13155 for (temp = ffecom_latest_temp_; temp != NULL; temp = temp->next)
13156 if (temp->in_use && (temp->t == t))
13157 {
13158 assert (!temp->auto_pop);
13159 temp->in_use = FALSE;
13160 return;
13161 }
13162 else
13163 assert (temp->t != t);
13164
13165 assert ("couldn't ffecom_pop_tempvar!" != NULL);
13166}
13167
13168#endif
13169/* ffecom_ptr_to_expr -- Transform expr into gcc tree with & in front
13170
13171 tree t;
13172 ffebld expr; // FFE expression.
13173 tree = ffecom_ptr_to_expr(expr);
13174
13175 Like ffecom_expr, but sticks address-of in front of most things. */
13176
13177#if FFECOM_targetCURRENT == FFECOM_targetGCC
13178tree
13179ffecom_ptr_to_expr (ffebld expr)
13180{
13181 tree item;
13182 ffeinfoBasictype bt;
13183 ffeinfoKindtype kt;
13184 ffesymbol s;
13185
13186 assert (expr != NULL);
13187
13188 switch (ffebld_op (expr))
13189 {
13190 case FFEBLD_opSYMTER:
13191 s = ffebld_symter (expr);
13192 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
13193 {
13194 ffecomGfrt ix;
13195
13196 ix = ffeintrin_gfrt_indirect (ffebld_symter_implementation (expr));
13197 assert (ix != FFECOM_gfrt);
13198 if ((item = ffecom_gfrt_[ix]) == NULL_TREE)
13199 {
13200 ffecom_make_gfrt_ (ix);
13201 item = ffecom_gfrt_[ix];
13202 }
13203 }
13204 else
13205 {
13206 item = ffesymbol_hook (s).decl_tree;
13207 if (item == NULL_TREE)
13208 {
13209 s = ffecom_sym_transform_ (s);
13210 item = ffesymbol_hook (s).decl_tree;
13211 }
13212 }
13213 assert (item != NULL);
13214 if (item == error_mark_node)
13215 return item;
13216 if (!ffesymbol_hook (s).addr)
13217 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
13218 item);
13219 return item;
13220
13221 case FFEBLD_opARRAYREF:
13222 {
13223 ffebld dims[FFECOM_dimensionsMAX];
13224 tree array;
13225 int i;
13226
13227 item = ffecom_ptr_to_expr (ffebld_left (expr));
13228
13229 if (item == error_mark_node)
13230 return item;
13231
13232 if ((ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereFLEETING)
13233 && !mark_addressable (item))
13234 return error_mark_node; /* Make sure non-const ref is to
13235 non-reg. */
13236
13237 /* Build up ARRAY_REFs in reverse order (since we're column major
13238 here in Fortran land). */
13239
13240 for (i = 0, expr = ffebld_right (expr);
13241 expr != NULL;
13242 expr = ffebld_trail (expr))
13243 dims[i++] = ffebld_head (expr);
13244
13245 for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
13246 i >= 0;
13247 --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
13248 {
8cd61d76
RH
13249 /* The initial subtraction should happen in the original type so
13250 that (possible) negative values are handled appropriately. */
5ff904cd
JL
13251 item
13252 = ffecom_2 (PLUS_EXPR,
13253 build_pointer_type (TREE_TYPE (array)),
13254 item,
13255 size_binop (MULT_EXPR,
13256 size_in_bytes (TREE_TYPE (array)),
e203760c
RH
13257 convert (sizetype,
13258 fold (build (MINUS_EXPR,
13259 TREE_TYPE (TYPE_MIN_VALUE (TYPE_DOMAIN (array))),
13260 ffecom_expr (dims[i]),
13261 TYPE_MIN_VALUE (TYPE_DOMAIN (array)))))));
5ff904cd
JL
13262 }
13263 }
13264 return item;
13265
13266 case FFEBLD_opCONTER:
13267
13268 bt = ffeinfo_basictype (ffebld_info (expr));
13269 kt = ffeinfo_kindtype (ffebld_info (expr));
13270
13271 item = ffecom_constantunion (&ffebld_constant_union
13272 (ffebld_conter (expr)), bt, kt,
13273 ffecom_tree_type[bt][kt]);
13274 if (item == error_mark_node)
13275 return error_mark_node;
13276 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
13277 item);
13278 return item;
13279
13280 case FFEBLD_opANY:
13281 return error_mark_node;
13282
13283 default:
13284 assert (ffecom_pending_calls_ > 0);
13285
13286 bt = ffeinfo_basictype (ffebld_info (expr));
13287 kt = ffeinfo_kindtype (ffebld_info (expr));
13288
13289 item = ffecom_expr (expr);
13290 if (item == error_mark_node)
13291 return error_mark_node;
13292
13293 /* The back end currently optimizes a bit too zealously for us, in that
13294 we fail JCB001 if the following block of code is omitted. It checks
13295 to see if the transformed expression is a symbol or array reference,
13296 and encloses it in a SAVE_EXPR if that is the case. */
13297
13298 STRIP_NOPS (item);
13299 if ((TREE_CODE (item) == VAR_DECL)
13300 || (TREE_CODE (item) == PARM_DECL)
13301 || (TREE_CODE (item) == RESULT_DECL)
13302 || (TREE_CODE (item) == INDIRECT_REF)
13303 || (TREE_CODE (item) == ARRAY_REF)
13304 || (TREE_CODE (item) == COMPONENT_REF)
13305#ifdef OFFSET_REF
13306 || (TREE_CODE (item) == OFFSET_REF)
13307#endif
13308 || (TREE_CODE (item) == BUFFER_REF)
13309 || (TREE_CODE (item) == REALPART_EXPR)
13310 || (TREE_CODE (item) == IMAGPART_EXPR))
13311 {
13312 item = ffecom_save_tree (item);
13313 }
13314
13315 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
13316 item);
13317 return item;
13318 }
13319
13320 assert ("fall-through error" == NULL);
13321 return error_mark_node;
13322}
13323
13324#endif
13325/* Prepare to make call-arg temps.
13326
13327 Call this in pairs with pop_calltemps around calls to
13328 ffecom_arg_ptr_to_expr if the latter might use temporaries. */
13329
13330#if FFECOM_targetCURRENT == FFECOM_targetGCC
13331void
13332ffecom_push_calltemps ()
13333{
13334 ffecom_pending_calls_++;
13335}
13336
13337#endif
13338/* Obtain a temp var with given data type.
13339
13340 Returns a VAR_DECL tree of a currently (that is, at the current
13341 statement being compiled) not in use and having the given data type,
13342 making a new one if necessary. size is FFETARGET_charactersizeNONE
13343 for a non-CHARACTER type or >= 0 for a CHARACTER type. elements is
13344 -1 for a scalar or > 0 for an array of type. auto_pop is TRUE if
13345 ffecom_pop_tempvar won't be called, meaning temp will be freed
13346 when #pending calls goes to zero. */
13347
13348#if FFECOM_targetCURRENT == FFECOM_targetGCC
13349tree
13350ffecom_push_tempvar (tree type, ffetargetCharacterSize size, int elements,
13351 bool auto_pop)
13352{
13353 ffecomTemp_ temp;
13354 int yes;
13355 tree t;
13356 static int mynumber;
13357
13358 assert (!auto_pop || (ffecom_pending_calls_ > 0));
13359
13360 if (type == error_mark_node)
13361 return error_mark_node;
13362
13363 for (temp = ffecom_latest_temp_; temp != NULL; temp = temp->next)
13364 {
13365 if (temp->in_use
13366 || (temp->type != type)
13367 || (temp->size != size)
13368 || (temp->elements != elements)
13369 || (DECL_CONTEXT (temp->t) != current_function_decl))
13370 continue;
13371
13372 temp->in_use = TRUE;
13373 temp->auto_pop = auto_pop;
13374 return temp->t;
13375 }
13376
13377 /* Create a new temp. */
13378
13379 yes = suspend_momentary ();
13380
13381 if (size != FFETARGET_charactersizeNONE)
13382 type = build_array_type (type,
13383 build_range_type (ffecom_f2c_ftnlen_type_node,
13384 ffecom_f2c_ftnlen_one_node,
13385 build_int_2 (size, 0)));
13386 if (elements != -1)
13387 type = build_array_type (type,
13388 build_range_type (integer_type_node,
13389 integer_zero_node,
13390 build_int_2 (elements - 1,
13391 0)));
13392 t = build_decl (VAR_DECL,
13393 ffecom_get_invented_identifier ("__g77_expr_%d", NULL,
13394 mynumber++),
13395 type);
13396 { /* ~~~~ kludge alert here!!! else temp gets reused outside
13397 a compound-statement sequence.... */
13398 extern tree sequence_rtl_expr;
13399 tree back_end_bug = sequence_rtl_expr;
13400
13401 sequence_rtl_expr = NULL_TREE;
13402
13403 t = start_decl (t, FALSE);
13404 finish_decl (t, NULL_TREE, FALSE);
13405
13406 sequence_rtl_expr = back_end_bug;
13407 }
13408
13409 resume_momentary (yes);
13410
13411 temp = malloc_new_kp (ffe_pool_program_unit (), "ffecomTemp_",
13412 sizeof (*temp));
13413
13414 temp->next = ffecom_latest_temp_;
13415 temp->type = type;
13416 temp->t = t;
13417 temp->size = size;
13418 temp->elements = elements;
13419 temp->in_use = TRUE;
13420 temp->auto_pop = auto_pop;
13421
13422 ffecom_latest_temp_ = temp;
13423
13424 return t;
13425}
13426
13427#endif
13428/* ffecom_return_expr -- Returns return-value expr given alt return expr
13429
13430 tree rtn; // NULL_TREE means use expand_null_return()
13431 ffebld expr; // NULL if no alt return expr to RETURN stmt
13432 rtn = ffecom_return_expr(expr);
13433
13434 Based on the program unit type and other info (like return function
13435 type, return master function type when alternate ENTRY points,
13436 whether subroutine has any alternate RETURN points, etc), returns the
13437 appropriate expression to be returned to the caller, or NULL_TREE
13438 meaning no return value or the caller expects it to be returned somewhere
13439 else (which is handled by other parts of this module). */
13440
13441#if FFECOM_targetCURRENT == FFECOM_targetGCC
13442tree
13443ffecom_return_expr (ffebld expr)
13444{
13445 tree rtn;
13446
13447 switch (ffecom_primary_entry_kind_)
13448 {
13449 case FFEINFO_kindPROGRAM:
13450 case FFEINFO_kindBLOCKDATA:
13451 rtn = NULL_TREE;
13452 break;
13453
13454 case FFEINFO_kindSUBROUTINE:
13455 if (!ffecom_is_altreturning_)
13456 rtn = NULL_TREE; /* No alt returns, never an expr. */
13457 else if (expr == NULL)
13458 rtn = integer_zero_node;
13459 else
13460 rtn = ffecom_expr (expr);
13461 break;
13462
13463 case FFEINFO_kindFUNCTION:
13464 if ((ffecom_multi_retval_ != NULL_TREE)
13465 || (ffesymbol_basictype (ffecom_primary_entry_)
13466 == FFEINFO_basictypeCHARACTER)
13467 || ((ffesymbol_basictype (ffecom_primary_entry_)
13468 == FFEINFO_basictypeCOMPLEX)
13469 && (ffecom_num_entrypoints_ == 0)
13470 && ffesymbol_is_f2c (ffecom_primary_entry_)))
13471 { /* Value is returned by direct assignment
13472 into (implicit) dummy. */
13473 rtn = NULL_TREE;
13474 break;
13475 }
13476 rtn = ffecom_func_result_;
13477#if 0
13478 /* Spurious error if RETURN happens before first reference! So elide
13479 this code. In particular, for debugging registry, rtn should always
13480 be non-null after all, but TREE_USED won't be set until we encounter
13481 a reference in the code. Perfectly okay (but weird) code that,
13482 e.g., has "GOTO 20;10 RETURN;20 RTN=0;GOTO 10", would result in
13483 this diagnostic for no reason. Have people use -O -Wuninitialized
13484 and leave it to the back end to find obviously weird cases. */
13485
13486 /* Used to "assert(rtn != NULL_TREE);" here, but it's kind of a valid
13487 situation; if the return value has never been referenced, it won't
13488 have a tree under 2pass mode. */
13489 if ((rtn == NULL_TREE)
13490 || !TREE_USED (rtn))
13491 {
13492 ffebad_start (FFEBAD_RETURN_VALUE_UNSET);
13493 ffebad_here (0, ffesymbol_where_line (ffecom_primary_entry_),
13494 ffesymbol_where_column (ffecom_primary_entry_));
13495 ffebad_string (ffesymbol_text (ffesymbol_funcresult
13496 (ffecom_primary_entry_)));
13497 ffebad_finish ();
13498 }
13499#endif
13500 break;
13501
13502 default:
13503 assert ("bad unit kind" == NULL);
13504 case FFEINFO_kindANY:
13505 rtn = error_mark_node;
13506 break;
13507 }
13508
13509 return rtn;
13510}
13511
13512#endif
13513/* Do save_expr only if tree is not error_mark_node. */
13514
13515#if FFECOM_targetCURRENT == FFECOM_targetGCC
a2977d2d
CB
13516tree
13517ffecom_save_tree (tree t)
5ff904cd
JL
13518{
13519 return save_expr (t);
13520}
13521#endif
13522
13523/* Public entry point for front end to access start_decl. */
13524
13525#if FFECOM_targetCURRENT == FFECOM_targetGCC
13526tree
13527ffecom_start_decl (tree decl, bool is_initialized)
13528{
13529 DECL_INITIAL (decl) = is_initialized ? error_mark_node : NULL_TREE;
13530 return start_decl (decl, FALSE);
13531}
13532
13533#endif
13534/* ffecom_sym_commit -- Symbol's state being committed to reality
13535
13536 ffesymbol s;
13537 ffecom_sym_commit(s);
13538
13539 Does whatever the backend needs when a symbol is committed after having
13540 been backtrackable for a period of time. */
13541
13542#if FFECOM_targetCURRENT == FFECOM_targetGCC
13543void
13544ffecom_sym_commit (ffesymbol s UNUSED)
13545{
13546 assert (!ffesymbol_retractable ());
13547}
13548
13549#endif
13550/* ffecom_sym_end_transition -- Perform end transition on all symbols
13551
13552 ffecom_sym_end_transition();
13553
13554 Does backend-specific stuff and also calls ffest_sym_end_transition
13555 to do the necessary FFE stuff.
13556
13557 Backtracking is never enabled when this fn is called, so don't worry
13558 about it. */
13559
13560ffesymbol
13561ffecom_sym_end_transition (ffesymbol s)
13562{
13563 ffestorag st;
13564
13565 assert (!ffesymbol_retractable ());
13566
13567 s = ffest_sym_end_transition (s);
13568
13569#if FFECOM_targetCURRENT == FFECOM_targetGCC
13570 if ((ffesymbol_kind (s) == FFEINFO_kindBLOCKDATA)
13571 && (ffesymbol_where (s) == FFEINFO_whereGLOBAL))
13572 {
13573 ffecom_list_blockdata_
13574 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13575 FFEINTRIN_specNONE,
13576 FFEINTRIN_impNONE),
13577 ffecom_list_blockdata_);
13578 }
13579#endif
13580
13581 /* This is where we finally notice that a symbol has partial initialization
13582 and finalize it. */
13583
13584 if (ffesymbol_accretion (s) != NULL)
13585 {
13586 assert (ffesymbol_init (s) == NULL);
13587 ffecom_notify_init_symbol (s);
13588 }
13589 else if (((st = ffesymbol_storage (s)) != NULL)
13590 && ((st = ffestorag_parent (st)) != NULL)
13591 && (ffestorag_accretion (st) != NULL))
13592 {
13593 assert (ffestorag_init (st) == NULL);
13594 ffecom_notify_init_storage (st);
13595 }
13596
13597#if FFECOM_targetCURRENT == FFECOM_targetGCC
13598 if ((ffesymbol_kind (s) == FFEINFO_kindCOMMON)
13599 && (ffesymbol_where (s) == FFEINFO_whereLOCAL)
13600 && (ffesymbol_storage (s) != NULL))
13601 {
13602 ffecom_list_common_
13603 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13604 FFEINTRIN_specNONE,
13605 FFEINTRIN_impNONE),
13606 ffecom_list_common_);
13607 }
13608#endif
13609
13610 return s;
13611}
13612
13613/* ffecom_sym_exec_transition -- Perform exec transition on all symbols
13614
13615 ffecom_sym_exec_transition();
13616
13617 Does backend-specific stuff and also calls ffest_sym_exec_transition
13618 to do the necessary FFE stuff.
13619
13620 See the long-winded description in ffecom_sym_learned for info
13621 on handling the situation where backtracking is inhibited. */
13622
13623ffesymbol
13624ffecom_sym_exec_transition (ffesymbol s)
13625{
13626 s = ffest_sym_exec_transition (s);
13627
13628 return s;
13629}
13630
13631/* ffecom_sym_learned -- Initial or more info gained on symbol after exec
13632
13633 ffesymbol s;
13634 s = ffecom_sym_learned(s);
13635
13636 Called when a new symbol is seen after the exec transition or when more
13637 info (perhaps) is gained for an UNCERTAIN symbol. The symbol state when
13638 it arrives here is that all its latest info is updated already, so its
13639 state may be UNCERTAIN or UNDERSTOOD, it might already have the hook
13640 field filled in if its gone through here or exec_transition first, and
13641 so on.
13642
13643 The backend probably wants to check ffesymbol_retractable() to see if
13644 backtracking is in effect. If so, the FFE's changes to the symbol may
13645 be retracted (undone) or committed (ratified), at which time the
13646 appropriate ffecom_sym_retract or _commit function will be called
13647 for that function.
13648
13649 If the backend has its own backtracking mechanism, great, use it so that
13650 committal is a simple operation. Though it doesn't make much difference,
13651 I suppose: the reason for tentative symbol evolution in the FFE is to
13652 enable error detection in weird incorrect statements early and to disable
13653 incorrect error detection on a correct statement. The backend is not
13654 likely to introduce any information that'll get involved in these
13655 considerations, so it is probably just fine that the implementation
13656 model for this fn and for _exec_transition is to not do anything
13657 (besides the required FFE stuff) if ffesymbol_retractable() returns TRUE
13658 and instead wait until ffecom_sym_commit is called (which it never
13659 will be as long as we're using ambiguity-detecting statement analysis in
13660 the FFE, which we are initially to shake out the code, but don't depend
13661 on this), otherwise go ahead and do whatever is needed.
13662
13663 In essence, then, when this fn and _exec_transition get called while
13664 backtracking is enabled, a general mechanism would be to flag which (or
13665 both) of these were called (and in what order? neat question as to what
13666 might happen that I'm too lame to think through right now) and then when
13667 _commit is called reproduce the original calling sequence, if any, for
13668 the two fns (at which point backtracking will, of course, be disabled). */
13669
13670ffesymbol
13671ffecom_sym_learned (ffesymbol s)
13672{
13673 ffestorag_exec_layout (s);
13674
13675 return s;
13676}
13677
13678/* ffecom_sym_retract -- Symbol's state being retracted from reality
13679
13680 ffesymbol s;
13681 ffecom_sym_retract(s);
13682
13683 Does whatever the backend needs when a symbol is retracted after having
13684 been backtrackable for a period of time. */
13685
13686#if FFECOM_targetCURRENT == FFECOM_targetGCC
13687void
13688ffecom_sym_retract (ffesymbol s UNUSED)
13689{
13690 assert (!ffesymbol_retractable ());
13691
13692#if 0 /* GCC doesn't commit any backtrackable sins,
13693 so nothing needed here. */
13694 switch (ffesymbol_hook (s).state)
13695 {
13696 case 0: /* nothing happened yet. */
13697 break;
13698
13699 case 1: /* exec transition happened. */
13700 break;
13701
13702 case 2: /* learned happened. */
13703 break;
13704
13705 case 3: /* learned then exec. */
13706 break;
13707
13708 case 4: /* exec then learned. */
13709 break;
13710
13711 default:
13712 assert ("bad hook state" == NULL);
13713 break;
13714 }
13715#endif
13716}
13717
13718#endif
13719/* Create temporary gcc label. */
13720
13721#if FFECOM_targetCURRENT == FFECOM_targetGCC
13722tree
13723ffecom_temp_label ()
13724{
13725 tree glabel;
13726 static int mynumber = 0;
13727
13728 glabel = build_decl (LABEL_DECL,
13729 ffecom_get_invented_identifier ("__g77_label_%d",
13730 NULL,
13731 mynumber++),
13732 void_type_node);
13733 DECL_CONTEXT (glabel) = current_function_decl;
13734 DECL_MODE (glabel) = VOIDmode;
13735
13736 return glabel;
13737}
13738
13739#endif
13740/* Return an expression that is usable as an arg in a conditional context
13741 (IF, DO WHILE, .NOT., and so on).
13742
13743 Use the one provided for the back end as of >2.6.0. */
13744
13745#if FFECOM_targetCURRENT == FFECOM_targetGCC
13746tree
13747ffecom_truth_value (tree expr)
13748{
13749 return truthvalue_conversion (expr);
13750}
13751
13752#endif
13753/* Return the inversion of a truth value (the inversion of what
13754 ffecom_truth_value builds).
13755
13756 Apparently invert_truthvalue, which is properly in the back end, is
13757 enough for now, so just use it. */
13758
13759#if FFECOM_targetCURRENT == FFECOM_targetGCC
13760tree
13761ffecom_truth_value_invert (tree expr)
13762{
13763 return invert_truthvalue (ffecom_truth_value (expr));
13764}
13765
13766#endif
13767/* Return PARM_DECL for arg#1 of master fn containing alternate ENTRY points
13768
13769 If the PARM_DECL already exists, return it, else create it. It's an
13770 integer_type_node argument for the master function that implements a
13771 subroutine or function with more than one entrypoint and is bound at
13772 run time with the entrypoint number (0 for SUBROUTINE/FUNCTION, 1 for
13773 first ENTRY statement, and so on). */
13774
13775#if FFECOM_targetCURRENT == FFECOM_targetGCC
13776tree
13777ffecom_which_entrypoint_decl ()
13778{
13779 assert (ffecom_which_entrypoint_decl_ != NULL_TREE);
13780
13781 return ffecom_which_entrypoint_decl_;
13782}
13783
13784#endif
13785\f
13786/* The following sections consists of private and public functions
13787 that have the same names and perform roughly the same functions
13788 as counterparts in the C front end. Changes in the C front end
13789 might affect how things should be done here. Only functions
13790 needed by the back end should be public here; the rest should
13791 be private (static in the C sense). Functions needed by other
13792 g77 front-end modules should be accessed by them via public
13793 ffecom_* names, which should themselves call private versions
13794 in this section so the private versions are easy to recognize
13795 when upgrading to a new gcc and finding interesting changes
13796 in the front end.
13797
13798 Functions named after rule "foo:" in c-parse.y are named
13799 "bison_rule_foo_" so they are easy to find. */
13800
13801#if FFECOM_targetCURRENT == FFECOM_targetGCC
13802
13803static void
13804bison_rule_compstmt_ ()
13805{
13806 emit_line_note (input_filename, lineno);
13807 expand_end_bindings (getdecls (), 1, 1);
13808 poplevel (1, 1, 0);
13809 pop_momentary ();
13810}
13811
13812static void
13813bison_rule_pushlevel_ ()
13814{
13815 emit_line_note (input_filename, lineno);
13816 pushlevel (0);
13817 clear_last_expr ();
13818 push_momentary ();
13819 expand_start_bindings (0);
13820}
13821
13822/* Return a definition for a builtin function named NAME and whose data type
13823 is TYPE. TYPE should be a function type with argument types.
13824 FUNCTION_CODE tells later passes how to compile calls to this function.
13825 See tree.h for its possible values.
13826
13827 If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
13828 the name to be called if we can't opencode the function. */
13829
13830static tree
13831builtin_function (char *name, tree type,
13832 enum built_in_function function_code, char *library_name)
13833{
13834 tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
13835 DECL_EXTERNAL (decl) = 1;
13836 TREE_PUBLIC (decl) = 1;
13837 if (library_name)
13838 DECL_ASSEMBLER_NAME (decl) = get_identifier (library_name);
13839 make_decl_rtl (decl, NULL_PTR, 1);
13840 pushdecl (decl);
13841 if (function_code != NOT_BUILT_IN)
13842 {
13843 DECL_BUILT_IN (decl) = 1;
13844 DECL_FUNCTION_CODE (decl) = function_code;
13845 }
13846
13847 return decl;
13848}
13849
13850/* Handle when a new declaration NEWDECL
13851 has the same name as an old one OLDDECL
13852 in the same binding contour.
13853 Prints an error message if appropriate.
13854
13855 If safely possible, alter OLDDECL to look like NEWDECL, and return 1.
13856 Otherwise, return 0. */
13857
13858static int
13859duplicate_decls (tree newdecl, tree olddecl)
13860{
13861 int types_match = 1;
13862 int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
13863 && DECL_INITIAL (newdecl) != 0);
13864 tree oldtype = TREE_TYPE (olddecl);
13865 tree newtype = TREE_TYPE (newdecl);
13866
13867 if (olddecl == newdecl)
13868 return 1;
13869
13870 if (TREE_CODE (newtype) == ERROR_MARK
13871 || TREE_CODE (oldtype) == ERROR_MARK)
13872 types_match = 0;
13873
13874 /* New decl is completely inconsistent with the old one =>
13875 tell caller to replace the old one.
13876 This is always an error except in the case of shadowing a builtin. */
13877 if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
13878 return 0;
13879
13880 /* For real parm decl following a forward decl,
13881 return 1 so old decl will be reused. */
13882 if (types_match && TREE_CODE (newdecl) == PARM_DECL
13883 && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
13884 return 1;
13885
13886 /* The new declaration is the same kind of object as the old one.
13887 The declarations may partially match. Print warnings if they don't
13888 match enough. Ultimately, copy most of the information from the new
13889 decl to the old one, and keep using the old one. */
13890
13891 if (TREE_CODE (olddecl) == FUNCTION_DECL
13892 && DECL_BUILT_IN (olddecl))
13893 {
13894 /* A function declaration for a built-in function. */
13895 if (!TREE_PUBLIC (newdecl))
13896 return 0;
13897 else if (!types_match)
13898 {
13899 /* Accept the return type of the new declaration if same modes. */
13900 tree oldreturntype = TREE_TYPE (TREE_TYPE (olddecl));
13901 tree newreturntype = TREE_TYPE (TREE_TYPE (newdecl));
13902
13903 /* Make sure we put the new type in the same obstack as the old ones.
13904 If the old types are not both in the same obstack, use the
13905 permanent one. */
13906 if (TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (newtype))
13907 push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
13908 else
13909 {
13910 push_obstacks_nochange ();
13911 end_temporary_allocation ();
13912 }
13913
13914 if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
13915 {
13916 /* Function types may be shared, so we can't just modify
13917 the return type of olddecl's function type. */
13918 tree newtype
13919 = build_function_type (newreturntype,
13920 TYPE_ARG_TYPES (TREE_TYPE (olddecl)));
13921
13922 types_match = 1;
13923 if (types_match)
13924 TREE_TYPE (olddecl) = newtype;
13925 }
13926
13927 pop_obstacks ();
13928 }
13929 if (!types_match)
13930 return 0;
13931 }
13932 else if (TREE_CODE (olddecl) == FUNCTION_DECL
13933 && DECL_SOURCE_LINE (olddecl) == 0)
13934 {
13935 /* A function declaration for a predeclared function
13936 that isn't actually built in. */
13937 if (!TREE_PUBLIC (newdecl))
13938 return 0;
13939 else if (!types_match)
13940 {
13941 /* If the types don't match, preserve volatility indication.
13942 Later on, we will discard everything else about the
13943 default declaration. */
13944 TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
13945 }
13946 }
13947
13948 /* Copy all the DECL_... slots specified in the new decl
13949 except for any that we copy here from the old type.
13950
13951 Past this point, we don't change OLDTYPE and NEWTYPE
13952 even if we change the types of NEWDECL and OLDDECL. */
13953
13954 if (types_match)
13955 {
13956 /* Make sure we put the new type in the same obstack as the old ones.
13957 If the old types are not both in the same obstack, use the permanent
13958 one. */
13959 if (TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (newtype))
13960 push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
13961 else
13962 {
13963 push_obstacks_nochange ();
13964 end_temporary_allocation ();
13965 }
13966
13967 /* Merge the data types specified in the two decls. */
13968 if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
13969 TREE_TYPE (newdecl)
13970 = TREE_TYPE (olddecl)
13971 = TREE_TYPE (newdecl);
13972
13973 /* Lay the type out, unless already done. */
13974 if (oldtype != TREE_TYPE (newdecl))
13975 {
13976 if (TREE_TYPE (newdecl) != error_mark_node)
13977 layout_type (TREE_TYPE (newdecl));
13978 if (TREE_CODE (newdecl) != FUNCTION_DECL
13979 && TREE_CODE (newdecl) != TYPE_DECL
13980 && TREE_CODE (newdecl) != CONST_DECL)
13981 layout_decl (newdecl, 0);
13982 }
13983 else
13984 {
13985 /* Since the type is OLDDECL's, make OLDDECL's size go with. */
13986 DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
13987 if (TREE_CODE (olddecl) != FUNCTION_DECL)
13988 if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
13989 DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
13990 }
13991
13992 /* Keep the old rtl since we can safely use it. */
13993 DECL_RTL (newdecl) = DECL_RTL (olddecl);
13994
13995 /* Merge the type qualifiers. */
13996 if (DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl)
13997 && !TREE_THIS_VOLATILE (newdecl))
13998 TREE_THIS_VOLATILE (olddecl) = 0;
13999 if (TREE_READONLY (newdecl))
14000 TREE_READONLY (olddecl) = 1;
14001 if (TREE_THIS_VOLATILE (newdecl))
14002 {
14003 TREE_THIS_VOLATILE (olddecl) = 1;
14004 if (TREE_CODE (newdecl) == VAR_DECL)
14005 make_var_volatile (newdecl);
14006 }
14007
14008 /* Keep source location of definition rather than declaration.
14009 Likewise, keep decl at outer scope. */
14010 if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
14011 || (DECL_CONTEXT (newdecl) != 0 && DECL_CONTEXT (olddecl) == 0))
14012 {
14013 DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
14014 DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl);
14015
14016 if (DECL_CONTEXT (olddecl) == 0
14017 && TREE_CODE (newdecl) != FUNCTION_DECL)
14018 DECL_CONTEXT (newdecl) = 0;
14019 }
14020
14021 /* Merge the unused-warning information. */
14022 if (DECL_IN_SYSTEM_HEADER (olddecl))
14023 DECL_IN_SYSTEM_HEADER (newdecl) = 1;
14024 else if (DECL_IN_SYSTEM_HEADER (newdecl))
14025 DECL_IN_SYSTEM_HEADER (olddecl) = 1;
14026
14027 /* Merge the initialization information. */
14028 if (DECL_INITIAL (newdecl) == 0)
14029 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
14030
14031 /* Merge the section attribute.
14032 We want to issue an error if the sections conflict but that must be
14033 done later in decl_attributes since we are called before attributes
14034 are assigned. */
14035 if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
14036 DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
14037
14038#if BUILT_FOR_270
14039 if (TREE_CODE (newdecl) == FUNCTION_DECL)
14040 {
14041 DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
14042 DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
14043 }
14044#endif
14045
14046 pop_obstacks ();
14047 }
14048 /* If cannot merge, then use the new type and qualifiers,
14049 and don't preserve the old rtl. */
14050 else
14051 {
14052 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
14053 TREE_READONLY (olddecl) = TREE_READONLY (newdecl);
14054 TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl);
14055 TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl);
14056 }
14057
14058 /* Merge the storage class information. */
14059 /* For functions, static overrides non-static. */
14060 if (TREE_CODE (newdecl) == FUNCTION_DECL)
14061 {
14062 TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
14063 /* This is since we don't automatically
14064 copy the attributes of NEWDECL into OLDDECL. */
14065 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
14066 /* If this clears `static', clear it in the identifier too. */
14067 if (! TREE_PUBLIC (olddecl))
14068 TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
14069 }
14070 if (DECL_EXTERNAL (newdecl))
14071 {
14072 TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
14073 DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
14074 /* An extern decl does not override previous storage class. */
14075 TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
14076 }
14077 else
14078 {
14079 TREE_STATIC (olddecl) = TREE_STATIC (newdecl);
14080 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
14081 }
14082
14083 /* If either decl says `inline', this fn is inline,
14084 unless its definition was passed already. */
14085 if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
14086 DECL_INLINE (olddecl) = 1;
14087 DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
14088
14089 /* Get rid of any built-in function if new arg types don't match it
14090 or if we have a function definition. */
14091 if (TREE_CODE (newdecl) == FUNCTION_DECL
14092 && DECL_BUILT_IN (olddecl)
14093 && (!types_match || new_is_definition))
14094 {
14095 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
14096 DECL_BUILT_IN (olddecl) = 0;
14097 }
14098
14099 /* If redeclaring a builtin function, and not a definition,
14100 it stays built in.
14101 Also preserve various other info from the definition. */
14102 if (TREE_CODE (newdecl) == FUNCTION_DECL && !new_is_definition)
14103 {
14104 if (DECL_BUILT_IN (olddecl))
14105 {
14106 DECL_BUILT_IN (newdecl) = 1;
14107 DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
14108 }
14109 else
14110 DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl);
14111
14112 DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
14113 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
14114 DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
14115 DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
14116 }
14117
14118 /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
14119 But preserve olddecl's DECL_UID. */
14120 {
14121 register unsigned olddecl_uid = DECL_UID (olddecl);
14122
34b8e428
JL
14123 memcpy ((char *) olddecl + sizeof (struct tree_common),
14124 (char *) newdecl + sizeof (struct tree_common),
14125 sizeof (struct tree_decl) - sizeof (struct tree_common));
5ff904cd
JL
14126 DECL_UID (olddecl) = olddecl_uid;
14127 }
14128
14129 return 1;
14130}
14131
14132/* Finish processing of a declaration;
14133 install its initial value.
14134 If the length of an array type is not known before,
14135 it must be determined now, from the initial value, or it is an error. */
14136
14137static void
14138finish_decl (tree decl, tree init, bool is_top_level)
14139{
14140 register tree type = TREE_TYPE (decl);
14141 int was_incomplete = (DECL_SIZE (decl) == 0);
14142 int temporary = allocation_temporary_p ();
14143 bool at_top_level = (current_binding_level == global_binding_level);
14144 bool top_level = is_top_level || at_top_level;
14145
14146 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
14147 level anyway. */
14148 assert (!is_top_level || !at_top_level);
14149
14150 if (TREE_CODE (decl) == PARM_DECL)
14151 assert (init == NULL_TREE);
14152 /* Remember that PARM_DECL doesn't have a DECL_INITIAL field per se -- it
14153 overlaps DECL_ARG_TYPE. */
14154 else if (init == NULL_TREE)
14155 assert (DECL_INITIAL (decl) == NULL_TREE);
14156 else
14157 assert (DECL_INITIAL (decl) == error_mark_node);
14158
14159 if (init != NULL_TREE)
14160 {
14161 if (TREE_CODE (decl) != TYPE_DECL)
14162 DECL_INITIAL (decl) = init;
14163 else
14164 {
14165 /* typedef foo = bar; store the type of bar as the type of foo. */
14166 TREE_TYPE (decl) = TREE_TYPE (init);
14167 DECL_INITIAL (decl) = init = 0;
14168 }
14169 }
14170
14171 /* Pop back to the obstack that is current for this binding level. This is
14172 because MAXINDEX, rtl, etc. to be made below must go in the permanent
14173 obstack. But don't discard the temporary data yet. */
14174 pop_obstacks ();
14175
14176 /* Deduce size of array from initialization, if not already known */
14177
14178 if (TREE_CODE (type) == ARRAY_TYPE
14179 && TYPE_DOMAIN (type) == 0
14180 && TREE_CODE (decl) != TYPE_DECL)
14181 {
14182 assert (top_level);
14183 assert (was_incomplete);
14184
14185 layout_decl (decl, 0);
14186 }
14187
14188 if (TREE_CODE (decl) == VAR_DECL)
14189 {
14190 if (DECL_SIZE (decl) == NULL_TREE
14191 && TYPE_SIZE (TREE_TYPE (decl)) != NULL_TREE)
14192 layout_decl (decl, 0);
14193
14194 if (DECL_SIZE (decl) == NULL_TREE
14195 && (TREE_STATIC (decl)
14196 ?
14197 /* A static variable with an incomplete type is an error if it is
14198 initialized. Also if it is not file scope. Otherwise, let it
14199 through, but if it is not `extern' then it may cause an error
14200 message later. */
14201 (DECL_INITIAL (decl) != 0 || DECL_CONTEXT (decl) != 0)
14202 :
14203 /* An automatic variable with an incomplete type is an error. */
14204 !DECL_EXTERNAL (decl)))
14205 {
14206 assert ("storage size not known" == NULL);
14207 abort ();
14208 }
14209
14210 if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
14211 && (DECL_SIZE (decl) != 0)
14212 && (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST))
14213 {
14214 assert ("storage size not constant" == NULL);
14215 abort ();
14216 }
14217 }
14218
14219 /* Output the assembler code and/or RTL code for variables and functions,
14220 unless the type is an undefined structure or union. If not, it will get
14221 done when the type is completed. */
14222
14223 if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
14224 {
14225 rest_of_decl_compilation (decl, NULL,
14226 DECL_CONTEXT (decl) == 0,
14227 0);
14228
14229 if (DECL_CONTEXT (decl) != 0)
14230 {
14231 /* Recompute the RTL of a local array now if it used to be an
14232 incomplete type. */
14233 if (was_incomplete
14234 && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
14235 {
14236 /* If we used it already as memory, it must stay in memory. */
14237 TREE_ADDRESSABLE (decl) = TREE_USED (decl);
14238 /* If it's still incomplete now, no init will save it. */
14239 if (DECL_SIZE (decl) == 0)
14240 DECL_INITIAL (decl) = 0;
14241 expand_decl (decl);
14242 }
14243 /* Compute and store the initial value. */
14244 if (TREE_CODE (decl) != FUNCTION_DECL)
14245 expand_decl_init (decl);
14246 }
14247 }
14248 else if (TREE_CODE (decl) == TYPE_DECL)
14249 {
14250 rest_of_decl_compilation (decl, NULL_PTR,
14251 DECL_CONTEXT (decl) == 0,
14252 0);
14253 }
14254
14255 /* This test used to include TREE_PERMANENT, however, we have the same
14256 problem with initializers at the function level. Such initializers get
14257 saved until the end of the function on the momentary_obstack. */
14258 if (!(TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))
14259 && temporary
14260 /* DECL_INITIAL is not defined in PARM_DECLs, since it shares space with
14261 DECL_ARG_TYPE. */
14262 && TREE_CODE (decl) != PARM_DECL)
14263 {
14264 /* We need to remember that this array HAD an initialization, but
14265 discard the actual temporary nodes, since we can't have a permanent
14266 node keep pointing to them. */
14267 /* We make an exception for inline functions, since it's normal for a
14268 local extern redeclaration of an inline function to have a copy of
14269 the top-level decl's DECL_INLINE. */
14270 if ((DECL_INITIAL (decl) != 0)
14271 && (DECL_INITIAL (decl) != error_mark_node))
14272 {
14273 /* If this is a const variable, then preserve the
14274 initializer instead of discarding it so that we can optimize
14275 references to it. */
14276 /* This test used to include TREE_STATIC, but this won't be set
14277 for function level initializers. */
14278 if (TREE_READONLY (decl))
14279 {
14280 preserve_initializer ();
14281 /* Hack? Set the permanent bit for something that is
14282 permanent, but not on the permenent obstack, so as to
14283 convince output_constant_def to make its rtl on the
14284 permanent obstack. */
14285 TREE_PERMANENT (DECL_INITIAL (decl)) = 1;
14286
14287 /* The initializer and DECL must have the same (or equivalent
14288 types), but if the initializer is a STRING_CST, its type
14289 might not be on the right obstack, so copy the type
14290 of DECL. */
14291 TREE_TYPE (DECL_INITIAL (decl)) = type;
14292 }
14293 else
14294 DECL_INITIAL (decl) = error_mark_node;
14295 }
14296 }
14297
14298 /* If requested, warn about definitions of large data objects. */
14299
14300 if (warn_larger_than
14301 && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
14302 && !DECL_EXTERNAL (decl))
14303 {
14304 register tree decl_size = DECL_SIZE (decl);
14305
14306 if (decl_size && TREE_CODE (decl_size) == INTEGER_CST)
14307 {
14308 unsigned units = TREE_INT_CST_LOW (decl_size) / BITS_PER_UNIT;
14309
14310 if (units > larger_than_size)
14311 warning_with_decl (decl, "size of `%s' is %u bytes", units);
14312 }
14313 }
14314
14315 /* If we have gone back from temporary to permanent allocation, actually
14316 free the temporary space that we no longer need. */
14317 if (temporary && !allocation_temporary_p ())
14318 permanent_allocation (0);
14319
14320 /* At the end of a declaration, throw away any variable type sizes of types
14321 defined inside that declaration. There is no use computing them in the
14322 following function definition. */
14323 if (current_binding_level == global_binding_level)
14324 get_pending_sizes ();
14325}
14326
14327/* Finish up a function declaration and compile that function
14328 all the way to assembler language output. The free the storage
14329 for the function definition.
14330
14331 This is called after parsing the body of the function definition.
14332
14333 NESTED is nonzero if the function being finished is nested in another. */
14334
14335static void
14336finish_function (int nested)
14337{
14338 register tree fndecl = current_function_decl;
14339
14340 assert (fndecl != NULL_TREE);
56a0044b
JL
14341 if (TREE_CODE (fndecl) != ERROR_MARK)
14342 {
14343 if (nested)
14344 assert (DECL_CONTEXT (fndecl) != NULL_TREE);
14345 else
14346 assert (DECL_CONTEXT (fndecl) == NULL_TREE);
14347 }
5ff904cd
JL
14348
14349/* TREE_READONLY (fndecl) = 1;
14350 This caused &foo to be of type ptr-to-const-function
14351 which then got a warning when stored in a ptr-to-function variable. */
14352
14353 poplevel (1, 0, 1);
5ff904cd 14354
56a0044b
JL
14355 if (TREE_CODE (fndecl) != ERROR_MARK)
14356 {
14357 BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
14358
14359 /* Must mark the RESULT_DECL as being in this function. */
5ff904cd 14360
56a0044b 14361 DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
5ff904cd 14362
56a0044b
JL
14363 /* Obey `register' declarations if `setjmp' is called in this fn. */
14364 /* Generate rtl for function exit. */
14365 expand_function_end (input_filename, lineno, 0);
5ff904cd 14366
56a0044b
JL
14367 /* So we can tell if jump_optimize sets it to 1. */
14368 can_reach_end = 0;
5ff904cd 14369
56a0044b
JL
14370 /* Run the optimizers and output the assembler code for this function. */
14371 rest_of_compilation (fndecl);
14372 }
5ff904cd
JL
14373
14374 /* Free all the tree nodes making up this function. */
14375 /* Switch back to allocating nodes permanently until we start another
14376 function. */
14377 if (!nested)
14378 permanent_allocation (1);
14379
56a0044b 14380 if (DECL_SAVED_INSNS (fndecl) == 0 && !nested && (TREE_CODE (fndecl) != ERROR_MARK))
5ff904cd
JL
14381 {
14382 /* Stop pointing to the local nodes about to be freed. */
14383 /* But DECL_INITIAL must remain nonzero so we know this was an actual
14384 function definition. */
14385 /* For a nested function, this is done in pop_f_function_context. */
14386 /* If rest_of_compilation set this to 0, leave it 0. */
14387 if (DECL_INITIAL (fndecl) != 0)
14388 DECL_INITIAL (fndecl) = error_mark_node;
14389 DECL_ARGUMENTS (fndecl) = 0;
14390 }
14391
14392 if (!nested)
14393 {
14394 /* Let the error reporting routines know that we're outside a function.
14395 For a nested function, this value is used in pop_c_function_context
14396 and then reset via pop_function_context. */
14397 ffecom_outer_function_decl_ = current_function_decl = NULL;
14398 }
14399}
14400
14401/* Plug-in replacement for identifying the name of a decl and, for a
14402 function, what we call it in diagnostics. For now, "program unit"
14403 should suffice, since it's a bit of a hassle to figure out which
14404 of several kinds of things it is. Note that it could conceivably
14405 be a statement function, which probably isn't really a program unit
14406 per se, but if that comes up, it should be easy to check (being a
14407 nested function and all). */
14408
14409static char *
8f87a563 14410lang_printable_name (tree decl, int v)
5ff904cd 14411{
b92f5cc0
JL
14412 /* Just to keep GCC quiet about the unused variable.
14413 In theory, differing values of V should produce different
14414 output. */
14415 switch (v)
14416 {
14417 default:
56a0044b
JL
14418 if (TREE_CODE (decl) == ERROR_MARK)
14419 return "erroneous code";
b92f5cc0
JL
14420 return IDENTIFIER_POINTER (DECL_NAME (decl));
14421 }
5ff904cd
JL
14422}
14423
14424/* g77's function to print out name of current function that caused
14425 an error. */
14426
14427#if BUILT_FOR_270
14428void
14429lang_print_error_function (file)
14430 char *file;
14431{
56a0044b 14432 static ffeglobal last_g = NULL;
5ff904cd 14433 static ffesymbol last_s = NULL;
56a0044b 14434 ffeglobal g;
5ff904cd
JL
14435 ffesymbol s;
14436 char *kind;
14437
56a0044b
JL
14438 if ((ffecom_primary_entry_ == NULL)
14439 || (ffesymbol_global (ffecom_primary_entry_) == NULL))
5ff904cd 14440 {
56a0044b 14441 g = NULL;
5ff904cd
JL
14442 s = NULL;
14443 kind = NULL;
14444 }
56a0044b 14445 else
5ff904cd 14446 {
56a0044b
JL
14447 g = ffesymbol_global (ffecom_primary_entry_);
14448 if (ffecom_nested_entry_ == NULL)
5ff904cd 14449 {
56a0044b
JL
14450 s = ffecom_primary_entry_;
14451 switch (ffesymbol_kind (s))
14452 {
14453 case FFEINFO_kindFUNCTION:
14454 kind = "function";
14455 break;
5ff904cd 14456
56a0044b
JL
14457 case FFEINFO_kindSUBROUTINE:
14458 kind = "subroutine";
14459 break;
5ff904cd 14460
56a0044b
JL
14461 case FFEINFO_kindPROGRAM:
14462 kind = "program";
14463 break;
5ff904cd 14464
56a0044b
JL
14465 case FFEINFO_kindBLOCKDATA:
14466 kind = "block-data";
14467 break;
5ff904cd 14468
56a0044b
JL
14469 default:
14470 kind = ffeinfo_kind_message (ffesymbol_kind (s));
14471 break;
14472 }
14473 }
14474 else
14475 {
14476 s = ffecom_nested_entry_;
14477 kind = "statement function";
5ff904cd 14478 }
5ff904cd
JL
14479 }
14480
56a0044b 14481 if ((last_g != g) || (last_s != s))
5ff904cd
JL
14482 {
14483 if (file)
14484 fprintf (stderr, "%s: ", file);
14485
14486 if (s == NULL)
14487 fprintf (stderr, "Outside of any program unit:\n");
14488 else
14489 {
14490 char *name = ffesymbol_text (s);
14491
14492 fprintf (stderr, "In %s `%s':\n", kind, name);
14493 }
14494
56a0044b 14495 last_g = g;
5ff904cd
JL
14496 last_s = s;
14497 }
14498}
14499#endif
14500
14501/* Similar to `lookup_name' but look only at current binding level. */
14502
14503static tree
14504lookup_name_current_level (tree name)
14505{
14506 register tree t;
14507
14508 if (current_binding_level == global_binding_level)
14509 return IDENTIFIER_GLOBAL_VALUE (name);
14510
14511 if (IDENTIFIER_LOCAL_VALUE (name) == 0)
14512 return 0;
14513
14514 for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
14515 if (DECL_NAME (t) == name)
14516 break;
14517
14518 return t;
14519}
14520
14521/* Create a new `struct binding_level'. */
14522
14523static struct binding_level *
14524make_binding_level ()
14525{
14526 /* NOSTRICT */
14527 return (struct binding_level *) xmalloc (sizeof (struct binding_level));
14528}
14529
14530/* Save and restore the variables in this file and elsewhere
14531 that keep track of the progress of compilation of the current function.
14532 Used for nested functions. */
14533
14534struct f_function
14535{
14536 struct f_function *next;
14537 tree named_labels;
14538 tree shadowed_labels;
14539 struct binding_level *binding_level;
14540};
14541
14542struct f_function *f_function_chain;
14543
14544/* Restore the variables used during compilation of a C function. */
14545
14546static void
14547pop_f_function_context ()
14548{
14549 struct f_function *p = f_function_chain;
14550 tree link;
14551
14552 /* Bring back all the labels that were shadowed. */
14553 for (link = shadowed_labels; link; link = TREE_CHAIN (link))
14554 if (DECL_NAME (TREE_VALUE (link)) != 0)
14555 IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)))
14556 = TREE_VALUE (link);
14557
14558 if (DECL_SAVED_INSNS (current_function_decl) == 0)
14559 {
14560 /* Stop pointing to the local nodes about to be freed. */
14561 /* But DECL_INITIAL must remain nonzero so we know this was an actual
14562 function definition. */
14563 DECL_INITIAL (current_function_decl) = error_mark_node;
14564 DECL_ARGUMENTS (current_function_decl) = 0;
14565 }
14566
14567 pop_function_context ();
14568
14569 f_function_chain = p->next;
14570
14571 named_labels = p->named_labels;
14572 shadowed_labels = p->shadowed_labels;
14573 current_binding_level = p->binding_level;
14574
14575 free (p);
14576}
14577
14578/* Save and reinitialize the variables
14579 used during compilation of a C function. */
14580
14581static void
14582push_f_function_context ()
14583{
14584 struct f_function *p
14585 = (struct f_function *) xmalloc (sizeof (struct f_function));
14586
14587 push_function_context ();
14588
14589 p->next = f_function_chain;
14590 f_function_chain = p;
14591
14592 p->named_labels = named_labels;
14593 p->shadowed_labels = shadowed_labels;
14594 p->binding_level = current_binding_level;
14595}
14596
14597static void
14598push_parm_decl (tree parm)
14599{
14600 int old_immediate_size_expand = immediate_size_expand;
14601
14602 /* Don't try computing parm sizes now -- wait till fn is called. */
14603
14604 immediate_size_expand = 0;
14605
14606 push_obstacks_nochange ();
14607
14608 /* Fill in arg stuff. */
14609
14610 DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
14611 DECL_ARG_TYPE_AS_WRITTEN (parm) = TREE_TYPE (parm);
14612 TREE_READONLY (parm) = 1; /* All implementation args are read-only. */
14613
14614 parm = pushdecl (parm);
14615
14616 immediate_size_expand = old_immediate_size_expand;
14617
14618 finish_decl (parm, NULL_TREE, FALSE);
14619}
14620
14621/* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, if appropriate. */
14622
14623static tree
14624pushdecl_top_level (x)
14625 tree x;
14626{
14627 register tree t;
14628 register struct binding_level *b = current_binding_level;
14629 register tree f = current_function_decl;
14630
14631 current_binding_level = global_binding_level;
14632 current_function_decl = NULL_TREE;
14633 t = pushdecl (x);
14634 current_binding_level = b;
14635 current_function_decl = f;
14636 return t;
14637}
14638
14639/* Store the list of declarations of the current level.
14640 This is done for the parameter declarations of a function being defined,
14641 after they are modified in the light of any missing parameters. */
14642
14643static tree
14644storedecls (decls)
14645 tree decls;
14646{
14647 return current_binding_level->names = decls;
14648}
14649
14650/* Store the parameter declarations into the current function declaration.
14651 This is called after parsing the parameter declarations, before
14652 digesting the body of the function.
14653
14654 For an old-style definition, modify the function's type
14655 to specify at least the number of arguments. */
14656
14657static void
14658store_parm_decls (int is_main_program UNUSED)
14659{
14660 register tree fndecl = current_function_decl;
14661
14662 /* This is a chain of PARM_DECLs from old-style parm declarations. */
14663 DECL_ARGUMENTS (fndecl) = storedecls (nreverse (getdecls ()));
14664
14665 /* Initialize the RTL code for the function. */
14666
14667 init_function_start (fndecl, input_filename, lineno);
14668
14669 /* Set up parameters and prepare for return, for the function. */
14670
14671 expand_function_start (fndecl, 0);
14672}
14673
14674static tree
14675start_decl (tree decl, bool is_top_level)
14676{
14677 register tree tem;
14678 bool at_top_level = (current_binding_level == global_binding_level);
14679 bool top_level = is_top_level || at_top_level;
14680
14681 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
14682 level anyway. */
14683 assert (!is_top_level || !at_top_level);
14684
14685 /* The corresponding pop_obstacks is in finish_decl. */
14686 push_obstacks_nochange ();
14687
14688 if (DECL_INITIAL (decl) != NULL_TREE)
14689 {
14690 assert (DECL_INITIAL (decl) == error_mark_node);
14691 assert (!DECL_EXTERNAL (decl));
14692 }
14693 else if (top_level)
14694 assert ((TREE_STATIC (decl) == 1) || DECL_EXTERNAL (decl) == 1);
14695
14696 /* For Fortran, we by default put things in .common when possible. */
14697 DECL_COMMON (decl) = 1;
14698
14699 /* Add this decl to the current binding level. TEM may equal DECL or it may
14700 be a previous decl of the same name. */
14701 if (is_top_level)
14702 tem = pushdecl_top_level (decl);
14703 else
14704 tem = pushdecl (decl);
14705
14706 /* For a local variable, define the RTL now. */
14707 if (!top_level
14708 /* But not if this is a duplicate decl and we preserved the rtl from the
14709 previous one (which may or may not happen). */
14710 && DECL_RTL (tem) == 0)
14711 {
14712 if (TYPE_SIZE (TREE_TYPE (tem)) != 0)
14713 expand_decl (tem);
14714 else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
14715 && DECL_INITIAL (tem) != 0)
14716 expand_decl (tem);
14717 }
14718
14719 if (DECL_INITIAL (tem) != NULL_TREE)
14720 {
14721 /* When parsing and digesting the initializer, use temporary storage.
14722 Do this even if we will ignore the value. */
14723 if (at_top_level)
14724 temporary_allocation ();
14725 }
14726
14727 return tem;
14728}
14729
14730/* Create the FUNCTION_DECL for a function definition.
14731 DECLSPECS and DECLARATOR are the parts of the declaration;
14732 they describe the function's name and the type it returns,
14733 but twisted together in a fashion that parallels the syntax of C.
14734
14735 This function creates a binding context for the function body
14736 as well as setting up the FUNCTION_DECL in current_function_decl.
14737
14738 Returns 1 on success. If the DECLARATOR is not suitable for a function
14739 (it defines a datum instead), we return 0, which tells
14740 yyparse to report a parse error.
14741
14742 NESTED is nonzero for a function nested within another function. */
14743
14744static void
14745start_function (tree name, tree type, int nested, int public)
14746{
14747 tree decl1;
14748 tree restype;
14749 int old_immediate_size_expand = immediate_size_expand;
14750
14751 named_labels = 0;
14752 shadowed_labels = 0;
14753
14754 /* Don't expand any sizes in the return type of the function. */
14755 immediate_size_expand = 0;
14756
14757 if (nested)
14758 {
14759 assert (!public);
14760 assert (current_function_decl != NULL_TREE);
14761 assert (DECL_CONTEXT (current_function_decl) == NULL_TREE);
14762 }
14763 else
14764 {
14765 assert (current_function_decl == NULL_TREE);
14766 }
14767
56a0044b
JL
14768 if (TREE_CODE (type) == ERROR_MARK)
14769 decl1 = current_function_decl = error_mark_node;
14770 else
14771 {
14772 decl1 = build_decl (FUNCTION_DECL,
14773 name,
14774 type);
14775 TREE_PUBLIC (decl1) = public ? 1 : 0;
14776 if (nested)
14777 DECL_INLINE (decl1) = 1;
14778 TREE_STATIC (decl1) = 1;
14779 DECL_EXTERNAL (decl1) = 0;
5ff904cd 14780
56a0044b 14781 announce_function (decl1);
5ff904cd 14782
56a0044b
JL
14783 /* Make the init_value nonzero so pushdecl knows this is not tentative.
14784 error_mark_node is replaced below (in poplevel) with the BLOCK. */
14785 DECL_INITIAL (decl1) = error_mark_node;
5ff904cd 14786
56a0044b
JL
14787 /* Record the decl so that the function name is defined. If we already have
14788 a decl for this name, and it is a FUNCTION_DECL, use the old decl. */
14789
14790 current_function_decl = pushdecl (decl1);
14791 }
5ff904cd 14792
5ff904cd
JL
14793 if (!nested)
14794 ffecom_outer_function_decl_ = current_function_decl;
14795
14796 pushlevel (0);
14797
56a0044b
JL
14798 if (TREE_CODE (current_function_decl) != ERROR_MARK)
14799 {
14800 make_function_rtl (current_function_decl);
5ff904cd 14801
56a0044b
JL
14802 restype = TREE_TYPE (TREE_TYPE (current_function_decl));
14803 DECL_RESULT (current_function_decl)
14804 = build_decl (RESULT_DECL, NULL_TREE, restype);
14805 }
5ff904cd
JL
14806
14807 if (!nested)
14808 /* Allocate further tree nodes temporarily during compilation of this
14809 function only. */
14810 temporary_allocation ();
14811
56a0044b 14812 if (!nested && (TREE_CODE (current_function_decl) != ERROR_MARK))
5ff904cd
JL
14813 TREE_ADDRESSABLE (current_function_decl) = 1;
14814
14815 immediate_size_expand = old_immediate_size_expand;
14816}
14817\f
14818/* Here are the public functions the GNU back end needs. */
14819
14820/* This is used by the `assert' macro. It is provided in libgcc.a,
14821 which `cc' doesn't know how to link. Note that the C++ front-end
14822 no longer actually uses the `assert' macro (instead, it calls
14823 my_friendly_assert). But all of the back-end files still need this. */
14824void
14825__eprintf (string, expression, line, filename)
14826#ifdef __STDC__
14827 const char *string;
14828 const char *expression;
14829 unsigned line;
14830 const char *filename;
14831#else
14832 char *string;
14833 char *expression;
14834 unsigned line;
14835 char *filename;
14836#endif
14837{
14838 fprintf (stderr, string, expression, line, filename);
14839 fflush (stderr);
14840 abort ();
14841}
14842
14843tree
14844convert (type, expr)
14845 tree type, expr;
14846{
14847 register tree e = expr;
14848 register enum tree_code code = TREE_CODE (type);
14849
14850 if (type == TREE_TYPE (e)
14851 || TREE_CODE (e) == ERROR_MARK)
14852 return e;
14853 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
14854 return fold (build1 (NOP_EXPR, type, e));
14855 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
14856 || code == ERROR_MARK)
14857 return error_mark_node;
14858 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
14859 {
14860 assert ("void value not ignored as it ought to be" == NULL);
14861 return error_mark_node;
14862 }
14863 if (code == VOID_TYPE)
14864 return build1 (CONVERT_EXPR, type, e);
14865 if ((code != RECORD_TYPE)
14866 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
14867 e = ffecom_1 (REALPART_EXPR, TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e))),
14868 e);
14869 if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
14870 return fold (convert_to_integer (type, e));
14871 if (code == POINTER_TYPE)
14872 return fold (convert_to_pointer (type, e));
14873 if (code == REAL_TYPE)
14874 return fold (convert_to_real (type, e));
14875 if (code == COMPLEX_TYPE)
14876 return fold (convert_to_complex (type, e));
14877 if (code == RECORD_TYPE)
14878 return fold (ffecom_convert_to_complex_ (type, e));
14879
14880 assert ("conversion to non-scalar type requested" == NULL);
14881 return error_mark_node;
14882}
14883
14884/* integrate_decl_tree calls this function, but since we don't use the
14885 DECL_LANG_SPECIFIC field, this is a no-op. */
14886
14887void
14888copy_lang_decl (node)
14889 tree node UNUSED;
14890{
14891}
14892
14893/* Return the list of declarations of the current level.
14894 Note that this list is in reverse order unless/until
14895 you nreverse it; and when you do nreverse it, you must
14896 store the result back using `storedecls' or you will lose. */
14897
14898tree
14899getdecls ()
14900{
14901 return current_binding_level->names;
14902}
14903
14904/* Nonzero if we are currently in the global binding level. */
14905
14906int
14907global_bindings_p ()
14908{
14909 return current_binding_level == global_binding_level;
14910}
14911
14912/* Insert BLOCK at the end of the list of subblocks of the
14913 current binding level. This is used when a BIND_EXPR is expanded,
14914 to handle the BLOCK node inside the BIND_EXPR. */
14915
14916void
14917incomplete_type_error (value, type)
14918 tree value UNUSED;
14919 tree type;
14920{
14921 if (TREE_CODE (type) == ERROR_MARK)
14922 return;
14923
14924 assert ("incomplete type?!?" == NULL);
14925}
14926
14927void
14928init_decl_processing ()
14929{
14930 malloc_init ();
14931 ffe_init_0 ();
14932}
14933
71b5e532 14934char *
77f77701
DB
14935init_parse (filename)
14936 char *filename;
5ff904cd
JL
14937{
14938#if BUILT_FOR_270
14939 extern void (*print_error_function) (char *);
14940#endif
14941
77f77701
DB
14942 /* Open input file. */
14943 if (filename == 0 || !strcmp (filename, "-"))
14944 {
14945 finput = stdin;
14946 filename = "stdin";
14947 }
14948 else
14949 finput = fopen (filename, "r");
14950 if (finput == 0)
14951 pfatal_with_name (filename);
14952
14953#ifdef IO_BUFFER_SIZE
14954 setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);
14955#endif
14956
5ff904cd
JL
14957 /* Make identifier nodes long enough for the language-specific slots. */
14958 set_identifier_size (sizeof (struct lang_identifier));
14959 decl_printable_name = lang_printable_name;
14960#if BUILT_FOR_270
14961 print_error_function = lang_print_error_function;
14962#endif
71b5e532
DB
14963
14964 return filename;
5ff904cd
JL
14965}
14966
77f77701
DB
14967void
14968finish_parse ()
14969{
14970 fclose (finput);
14971}
14972
5ff904cd
JL
14973void
14974insert_block (block)
14975 tree block;
14976{
14977 TREE_USED (block) = 1;
14978 current_binding_level->blocks
14979 = chainon (current_binding_level->blocks, block);
14980}
14981
14982int
ab9e0ff9
DB
14983lang_decode_option (argc, argv)
14984 int argc;
14985 char **argv;
5ff904cd 14986{
ab9e0ff9 14987 return ffe_decode_option (argc, argv);
5ff904cd
JL
14988}
14989
bc289659
ML
14990/* used by print-tree.c */
14991
14992void
14993lang_print_xnode (file, node, indent)
14994 FILE *file UNUSED;
14995 tree node UNUSED;
14996 int indent UNUSED;
14997{
14998}
14999
5ff904cd
JL
15000void
15001lang_finish ()
15002{
15003 ffe_terminate_0 ();
15004
15005 if (ffe_is_ffedebug ())
15006 malloc_pool_display (malloc_pool_image ());
15007}
15008
15009char *
15010lang_identify ()
15011{
15012 return "f77";
15013}
15014
f84639ba
RH
15015void
15016lang_init_options ()
15017{
15018 /* Set default options for Fortran. */
15019 flag_move_all_movables = 1;
15020 flag_reduce_all_givs = 1;
15021 flag_argument_noalias = 2;
15022}
15023
5ff904cd
JL
15024void
15025lang_init ()
15026{
5ff904cd
JL
15027 /* If the file is output from cpp, it should contain a first line
15028 `# 1 "real-filename"', and the current design of gcc (toplev.c
15029 in particular and the way it sets up information relied on by
15030 INCLUDE) requires that we read this now, and store the
15031 "real-filename" info in master_input_filename. Ask the lexer
15032 to try doing this. */
15033 ffelex_hash_kludge (finput);
15034}
15035
15036int
15037mark_addressable (exp)
15038 tree exp;
15039{
15040 register tree x = exp;
15041 while (1)
15042 switch (TREE_CODE (x))
15043 {
15044 case ADDR_EXPR:
15045 case COMPONENT_REF:
15046 case ARRAY_REF:
15047 x = TREE_OPERAND (x, 0);
15048 break;
15049
15050 case CONSTRUCTOR:
15051 TREE_ADDRESSABLE (x) = 1;
15052 return 1;
15053
15054 case VAR_DECL:
15055 case CONST_DECL:
15056 case PARM_DECL:
15057 case RESULT_DECL:
15058 if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)
15059 && DECL_NONLOCAL (x))
15060 {
15061 if (TREE_PUBLIC (x))
15062 {
15063 assert ("address of global register var requested" == NULL);
15064 return 0;
15065 }
15066 assert ("address of register variable requested" == NULL);
15067 }
15068 else if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x))
15069 {
15070 if (TREE_PUBLIC (x))
15071 {
15072 assert ("address of global register var requested" == NULL);
15073 return 0;
15074 }
15075 assert ("address of register var requested" == NULL);
15076 }
15077 put_var_into_stack (x);
15078
15079 /* drops in */
15080 case FUNCTION_DECL:
15081 TREE_ADDRESSABLE (x) = 1;
15082#if 0 /* poplevel deals with this now. */
15083 if (DECL_CONTEXT (x) == 0)
15084 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
15085#endif
15086
15087 default:
15088 return 1;
15089 }
15090}
15091
15092/* If DECL has a cleanup, build and return that cleanup here.
15093 This is a callback called by expand_expr. */
15094
15095tree
15096maybe_build_cleanup (decl)
15097 tree decl UNUSED;
15098{
15099 /* There are no cleanups in Fortran. */
15100 return NULL_TREE;
15101}
15102
15103/* Exit a binding level.
15104 Pop the level off, and restore the state of the identifier-decl mappings
15105 that were in effect when this level was entered.
15106
15107 If KEEP is nonzero, this level had explicit declarations, so
15108 and create a "block" (a BLOCK node) for the level
15109 to record its declarations and subblocks for symbol table output.
15110
15111 If FUNCTIONBODY is nonzero, this level is the body of a function,
15112 so create a block as if KEEP were set and also clear out all
15113 label names.
15114
15115 If REVERSE is nonzero, reverse the order of decls before putting
15116 them into the BLOCK. */
15117
15118tree
15119poplevel (keep, reverse, functionbody)
15120 int keep;
15121 int reverse;
15122 int functionbody;
15123{
15124 register tree link;
15125 /* The chain of decls was accumulated in reverse order. Put it into forward
15126 order, just for cleanliness. */
15127 tree decls;
15128 tree subblocks = current_binding_level->blocks;
15129 tree block = 0;
15130 tree decl;
15131 int block_previously_created;
15132
15133 /* Get the decls in the order they were written. Usually
15134 current_binding_level->names is in reverse order. But parameter decls
15135 were previously put in forward order. */
15136
15137 if (reverse)
15138 current_binding_level->names
15139 = decls = nreverse (current_binding_level->names);
15140 else
15141 decls = current_binding_level->names;
15142
15143 /* Output any nested inline functions within this block if they weren't
15144 already output. */
15145
15146 for (decl = decls; decl; decl = TREE_CHAIN (decl))
15147 if (TREE_CODE (decl) == FUNCTION_DECL
15148 && !TREE_ASM_WRITTEN (decl)
15149 && DECL_INITIAL (decl) != 0
15150 && TREE_ADDRESSABLE (decl))
15151 {
15152 /* If this decl was copied from a file-scope decl on account of a
15153 block-scope extern decl, propagate TREE_ADDRESSABLE to the
15154 file-scope decl. */
15155 if (DECL_ABSTRACT_ORIGIN (decl) != 0)
15156 TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
15157 else
15158 {
15159 push_function_context ();
15160 output_inline_function (decl);
15161 pop_function_context ();
15162 }
15163 }
15164
15165 /* If there were any declarations or structure tags in that level, or if
15166 this level is a function body, create a BLOCK to record them for the
15167 life of this function. */
15168
15169 block = 0;
15170 block_previously_created = (current_binding_level->this_block != 0);
15171 if (block_previously_created)
15172 block = current_binding_level->this_block;
15173 else if (keep || functionbody)
15174 block = make_node (BLOCK);
15175 if (block != 0)
15176 {
15177 BLOCK_VARS (block) = decls;
15178 BLOCK_SUBBLOCKS (block) = subblocks;
15179 remember_end_note (block);
15180 }
15181
15182 /* In each subblock, record that this is its superior. */
15183
15184 for (link = subblocks; link; link = TREE_CHAIN (link))
15185 BLOCK_SUPERCONTEXT (link) = block;
15186
15187 /* Clear out the meanings of the local variables of this level. */
15188
15189 for (link = decls; link; link = TREE_CHAIN (link))
15190 {
15191 if (DECL_NAME (link) != 0)
15192 {
15193 /* If the ident. was used or addressed via a local extern decl,
15194 don't forget that fact. */
15195 if (DECL_EXTERNAL (link))
15196 {
15197 if (TREE_USED (link))
15198 TREE_USED (DECL_NAME (link)) = 1;
15199 if (TREE_ADDRESSABLE (link))
15200 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
15201 }
15202 IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0;
15203 }
15204 }
15205
15206 /* If the level being exited is the top level of a function, check over all
15207 the labels, and clear out the current (function local) meanings of their
15208 names. */
15209
15210 if (functionbody)
15211 {
15212 /* If this is the top level block of a function, the vars are the
15213 function's parameters. Don't leave them in the BLOCK because they
15214 are found in the FUNCTION_DECL instead. */
15215
15216 BLOCK_VARS (block) = 0;
15217 }
15218
15219 /* Pop the current level, and free the structure for reuse. */
15220
15221 {
15222 register struct binding_level *level = current_binding_level;
15223 current_binding_level = current_binding_level->level_chain;
15224
15225 level->level_chain = free_binding_level;
15226 free_binding_level = level;
15227 }
15228
15229 /* Dispose of the block that we just made inside some higher level. */
15230 if (functionbody)
15231 DECL_INITIAL (current_function_decl) = block;
15232 else if (block)
15233 {
15234 if (!block_previously_created)
15235 current_binding_level->blocks
15236 = chainon (current_binding_level->blocks, block);
15237 }
15238 /* If we did not make a block for the level just exited, any blocks made
15239 for inner levels (since they cannot be recorded as subblocks in that
15240 level) must be carried forward so they will later become subblocks of
15241 something else. */
15242 else if (subblocks)
15243 current_binding_level->blocks
15244 = chainon (current_binding_level->blocks, subblocks);
15245
15246 /* Set the TYPE_CONTEXTs for all of the tagged types belonging to this
15247 binding contour so that they point to the appropriate construct, i.e.
15248 either to the current FUNCTION_DECL node, or else to the BLOCK node we
15249 just constructed.
15250
15251 Note that for tagged types whose scope is just the formal parameter list
15252 for some function type specification, we can't properly set their
15253 TYPE_CONTEXTs here, because we don't have a pointer to the appropriate
15254 FUNCTION_TYPE node readily available to us. For those cases, the
15255 TYPE_CONTEXTs of the relevant tagged type nodes get set in
15256 `grokdeclarator' as soon as we have created the FUNCTION_TYPE node which
15257 will represent the "scope" for these "parameter list local" tagged
15258 types. */
15259
15260 if (block)
15261 TREE_USED (block) = 1;
15262 return block;
15263}
15264
15265void
15266print_lang_decl (file, node, indent)
15267 FILE *file UNUSED;
15268 tree node UNUSED;
15269 int indent UNUSED;
15270{
15271}
15272
15273void
15274print_lang_identifier (file, node, indent)
15275 FILE *file;
15276 tree node;
15277 int indent;
15278{
15279 print_node (file, "global", IDENTIFIER_GLOBAL_VALUE (node), indent + 4);
15280 print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4);
15281}
15282
15283void
15284print_lang_statistics ()
15285{
15286}
15287
15288void
15289print_lang_type (file, node, indent)
15290 FILE *file UNUSED;
15291 tree node UNUSED;
15292 int indent UNUSED;
15293{
15294}
15295
15296/* Record a decl-node X as belonging to the current lexical scope.
15297 Check for errors (such as an incompatible declaration for the same
15298 name already seen in the same scope).
15299
15300 Returns either X or an old decl for the same name.
15301 If an old decl is returned, it may have been smashed
15302 to agree with what X says. */
15303
15304tree
15305pushdecl (x)
15306 tree x;
15307{
15308 register tree t;
15309 register tree name = DECL_NAME (x);
15310 register struct binding_level *b = current_binding_level;
15311
15312 if ((TREE_CODE (x) == FUNCTION_DECL)
15313 && (DECL_INITIAL (x) == 0)
15314 && DECL_EXTERNAL (x))
15315 DECL_CONTEXT (x) = NULL_TREE;
15316 else
15317 DECL_CONTEXT (x) = current_function_decl;
15318
15319 if (name)
15320 {
15321 if (IDENTIFIER_INVENTED (name))
15322 {
15323#if BUILT_FOR_270
15324 DECL_ARTIFICIAL (x) = 1;
15325#endif
15326 DECL_IN_SYSTEM_HEADER (x) = 1;
5ff904cd
JL
15327 }
15328
15329 t = lookup_name_current_level (name);
15330
15331 assert ((t == NULL_TREE) || (DECL_CONTEXT (x) == NULL_TREE));
15332
15333 /* Don't push non-parms onto list for parms until we understand
15334 why we're doing this and whether it works. */
15335
15336 assert ((b == global_binding_level)
15337 || !ffecom_transform_only_dummies_
15338 || TREE_CODE (x) == PARM_DECL);
15339
15340 if ((t != NULL_TREE) && duplicate_decls (x, t))
15341 return t;
15342
15343 /* If we are processing a typedef statement, generate a whole new
15344 ..._TYPE node (which will be just an variant of the existing
15345 ..._TYPE node with identical properties) and then install the
15346 TYPE_DECL node generated to represent the typedef name as the
15347 TYPE_NAME of this brand new (duplicate) ..._TYPE node.
15348
15349 The whole point here is to end up with a situation where each and every
15350 ..._TYPE node the compiler creates will be uniquely associated with
15351 AT MOST one node representing a typedef name. This way, even though
15352 the compiler substitutes corresponding ..._TYPE nodes for TYPE_DECL
15353 (i.e. "typedef name") nodes very early on, later parts of the
15354 compiler can always do the reverse translation and get back the
15355 corresponding typedef name. For example, given:
15356
15357 typedef struct S MY_TYPE; MY_TYPE object;
15358
15359 Later parts of the compiler might only know that `object' was of type
38e01259 15360 `struct S' if it were not for code just below. With this code
5ff904cd
JL
15361 however, later parts of the compiler see something like:
15362
15363 struct S' == struct S typedef struct S' MY_TYPE; struct S' object;
15364
15365 And they can then deduce (from the node for type struct S') that the
15366 original object declaration was:
15367
15368 MY_TYPE object;
15369
15370 Being able to do this is important for proper support of protoize, and
15371 also for generating precise symbolic debugging information which
15372 takes full account of the programmer's (typedef) vocabulary.
15373
15374 Obviously, we don't want to generate a duplicate ..._TYPE node if the
15375 TYPE_DECL node that we are now processing really represents a
15376 standard built-in type.
15377
15378 Since all standard types are effectively declared at line zero in the
15379 source file, we can easily check to see if we are working on a
15380 standard type by checking the current value of lineno. */
15381
15382 if (TREE_CODE (x) == TYPE_DECL)
15383 {
15384 if (DECL_SOURCE_LINE (x) == 0)
15385 {
15386 if (TYPE_NAME (TREE_TYPE (x)) == 0)
15387 TYPE_NAME (TREE_TYPE (x)) = x;
15388 }
15389 else if (TREE_TYPE (x) != error_mark_node)
15390 {
15391 tree tt = TREE_TYPE (x);
15392
15393 tt = build_type_copy (tt);
15394 TYPE_NAME (tt) = x;
15395 TREE_TYPE (x) = tt;
15396 }
15397 }
15398
15399 /* This name is new in its binding level. Install the new declaration
15400 and return it. */
15401 if (b == global_binding_level)
15402 IDENTIFIER_GLOBAL_VALUE (name) = x;
15403 else
15404 IDENTIFIER_LOCAL_VALUE (name) = x;
15405 }
15406
15407 /* Put decls on list in reverse order. We will reverse them later if
15408 necessary. */
15409 TREE_CHAIN (x) = b->names;
15410 b->names = x;
15411
15412 return x;
15413}
15414
15415/* Enter a new binding level.
15416 If TAG_TRANSPARENT is nonzero, do so only for the name space of variables,
15417 not for that of tags. */
15418
15419void
15420pushlevel (tag_transparent)
15421 int tag_transparent;
15422{
15423 register struct binding_level *newlevel = NULL_BINDING_LEVEL;
15424
15425 assert (!tag_transparent);
15426
15427 /* Reuse or create a struct for this binding level. */
15428
15429 if (free_binding_level)
15430 {
15431 newlevel = free_binding_level;
15432 free_binding_level = free_binding_level->level_chain;
15433 }
15434 else
15435 {
15436 newlevel = make_binding_level ();
15437 }
15438
15439 /* Add this level to the front of the chain (stack) of levels that are
15440 active. */
15441
15442 *newlevel = clear_binding_level;
15443 newlevel->level_chain = current_binding_level;
15444 current_binding_level = newlevel;
15445}
15446
15447/* Set the BLOCK node for the innermost scope
15448 (the one we are currently in). */
15449
15450void
15451set_block (block)
15452 register tree block;
15453{
15454 current_binding_level->this_block = block;
15455}
15456
15457/* ~~tree.h SHOULD declare this, because toplev.c references it. */
15458
15459/* Can't 'yydebug' a front end not generated by yacc/bison! */
15460
15461void
15462set_yydebug (value)
15463 int value;
15464{
15465 if (value)
15466 fprintf (stderr, "warning: no yacc/bison-generated output to debug!\n");
15467}
15468
15469tree
15470signed_or_unsigned_type (unsignedp, type)
15471 int unsignedp;
15472 tree type;
15473{
15474 tree type2;
15475
15476 if (! INTEGRAL_TYPE_P (type))
15477 return type;
15478 if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
15479 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15480 if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
15481 return unsignedp ? unsigned_type_node : integer_type_node;
15482 if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node))
15483 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15484 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node))
15485 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15486 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node))
15487 return (unsignedp ? long_long_unsigned_type_node
15488 : long_long_integer_type_node);
15489
15490 type2 = type_for_size (TYPE_PRECISION (type), unsignedp);
15491 if (type2 == NULL_TREE)
15492 return type;
15493
15494 return type2;
15495}
15496
15497tree
15498signed_type (type)
15499 tree type;
15500{
15501 tree type1 = TYPE_MAIN_VARIANT (type);
15502 ffeinfoKindtype kt;
15503 tree type2;
15504
15505 if (type1 == unsigned_char_type_node || type1 == char_type_node)
15506 return signed_char_type_node;
15507 if (type1 == unsigned_type_node)
15508 return integer_type_node;
15509 if (type1 == short_unsigned_type_node)
15510 return short_integer_type_node;
15511 if (type1 == long_unsigned_type_node)
15512 return long_integer_type_node;
15513 if (type1 == long_long_unsigned_type_node)
15514 return long_long_integer_type_node;
15515#if 0 /* gcc/c-* files only */
15516 if (type1 == unsigned_intDI_type_node)
15517 return intDI_type_node;
15518 if (type1 == unsigned_intSI_type_node)
15519 return intSI_type_node;
15520 if (type1 == unsigned_intHI_type_node)
15521 return intHI_type_node;
15522 if (type1 == unsigned_intQI_type_node)
15523 return intQI_type_node;
15524#endif
15525
15526 type2 = type_for_size (TYPE_PRECISION (type1), 0);
15527 if (type2 != NULL_TREE)
15528 return type2;
15529
15530 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15531 {
15532 type2 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
15533
15534 if (type1 == type2)
15535 return ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15536 }
15537
15538 return type;
15539}
15540
15541/* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
15542 or validate its data type for an `if' or `while' statement or ?..: exp.
15543
15544 This preparation consists of taking the ordinary
15545 representation of an expression expr and producing a valid tree
15546 boolean expression describing whether expr is nonzero. We could
15547 simply always do build_binary_op (NE_EXPR, expr, integer_zero_node, 1),
15548 but we optimize comparisons, &&, ||, and !.
15549
15550 The resulting type should always be `integer_type_node'. */
15551
15552tree
15553truthvalue_conversion (expr)
15554 tree expr;
15555{
15556 if (TREE_CODE (expr) == ERROR_MARK)
15557 return expr;
15558
15559#if 0 /* This appears to be wrong for C++. */
15560 /* These really should return error_mark_node after 2.4 is stable.
15561 But not all callers handle ERROR_MARK properly. */
15562 switch (TREE_CODE (TREE_TYPE (expr)))
15563 {
15564 case RECORD_TYPE:
15565 error ("struct type value used where scalar is required");
15566 return integer_zero_node;
15567
15568 case UNION_TYPE:
15569 error ("union type value used where scalar is required");
15570 return integer_zero_node;
15571
15572 case ARRAY_TYPE:
15573 error ("array type value used where scalar is required");
15574 return integer_zero_node;
15575
15576 default:
15577 break;
15578 }
15579#endif /* 0 */
15580
15581 switch (TREE_CODE (expr))
15582 {
15583 /* It is simpler and generates better code to have only TRUTH_*_EXPR
15584 or comparison expressions as truth values at this level. */
15585#if 0
15586 case COMPONENT_REF:
15587 /* A one-bit unsigned bit-field is already acceptable. */
15588 if (1 == TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (expr, 1)))
15589 && TREE_UNSIGNED (TREE_OPERAND (expr, 1)))
15590 return expr;
15591 break;
15592#endif
15593
15594 case EQ_EXPR:
15595 /* It is simpler and generates better code to have only TRUTH_*_EXPR
15596 or comparison expressions as truth values at this level. */
15597#if 0
15598 if (integer_zerop (TREE_OPERAND (expr, 1)))
15599 return build_unary_op (TRUTH_NOT_EXPR, TREE_OPERAND (expr, 0), 0);
15600#endif
15601 case NE_EXPR: case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
15602 case TRUTH_ANDIF_EXPR:
15603 case TRUTH_ORIF_EXPR:
15604 case TRUTH_AND_EXPR:
15605 case TRUTH_OR_EXPR:
15606 case TRUTH_XOR_EXPR:
15607 TREE_TYPE (expr) = integer_type_node;
15608 return expr;
15609
15610 case ERROR_MARK:
15611 return expr;
15612
15613 case INTEGER_CST:
15614 return integer_zerop (expr) ? integer_zero_node : integer_one_node;
15615
15616 case REAL_CST:
15617 return real_zerop (expr) ? integer_zero_node : integer_one_node;
15618
15619 case ADDR_EXPR:
15620 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0)))
15621 return build (COMPOUND_EXPR, integer_type_node,
15622 TREE_OPERAND (expr, 0), integer_one_node);
15623 else
15624 return integer_one_node;
15625
15626 case COMPLEX_EXPR:
15627 return ffecom_2 ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
15628 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15629 integer_type_node,
15630 truthvalue_conversion (TREE_OPERAND (expr, 0)),
15631 truthvalue_conversion (TREE_OPERAND (expr, 1)));
15632
15633 case NEGATE_EXPR:
15634 case ABS_EXPR:
15635 case FLOAT_EXPR:
15636 case FFS_EXPR:
15637 /* These don't change whether an object is non-zero or zero. */
15638 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15639
15640 case LROTATE_EXPR:
15641 case RROTATE_EXPR:
15642 /* These don't change whether an object is zero or non-zero, but
15643 we can't ignore them if their second arg has side-effects. */
15644 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
15645 return build (COMPOUND_EXPR, integer_type_node, TREE_OPERAND (expr, 1),
15646 truthvalue_conversion (TREE_OPERAND (expr, 0)));
15647 else
15648 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15649
15650 case COND_EXPR:
15651 /* Distribute the conversion into the arms of a COND_EXPR. */
15652 return fold (build (COND_EXPR, integer_type_node, TREE_OPERAND (expr, 0),
15653 truthvalue_conversion (TREE_OPERAND (expr, 1)),
15654 truthvalue_conversion (TREE_OPERAND (expr, 2))));
15655
15656 case CONVERT_EXPR:
15657 /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
15658 since that affects how `default_conversion' will behave. */
15659 if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE
15660 || TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
15661 break;
15662 /* fall through... */
15663 case NOP_EXPR:
15664 /* If this is widening the argument, we can ignore it. */
15665 if (TYPE_PRECISION (TREE_TYPE (expr))
15666 >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
15667 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15668 break;
15669
15670 case MINUS_EXPR:
15671 /* With IEEE arithmetic, x - x may not equal 0, so we can't optimize
15672 this case. */
15673 if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
15674 && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE)
15675 break;
15676 /* fall through... */
15677 case BIT_XOR_EXPR:
15678 /* This and MINUS_EXPR can be changed into a comparison of the
15679 two objects. */
15680 if (TREE_TYPE (TREE_OPERAND (expr, 0))
15681 == TREE_TYPE (TREE_OPERAND (expr, 1)))
15682 return ffecom_2 (NE_EXPR, integer_type_node,
15683 TREE_OPERAND (expr, 0),
15684 TREE_OPERAND (expr, 1));
15685 return ffecom_2 (NE_EXPR, integer_type_node,
15686 TREE_OPERAND (expr, 0),
15687 fold (build1 (NOP_EXPR,
15688 TREE_TYPE (TREE_OPERAND (expr, 0)),
15689 TREE_OPERAND (expr, 1))));
15690
15691 case BIT_AND_EXPR:
15692 if (integer_onep (TREE_OPERAND (expr, 1)))
15693 return expr;
15694 break;
15695
15696 case MODIFY_EXPR:
15697#if 0 /* No such thing in Fortran. */
15698 if (warn_parentheses && C_EXP_ORIGINAL_CODE (expr) == MODIFY_EXPR)
15699 warning ("suggest parentheses around assignment used as truth value");
15700#endif
15701 break;
15702
15703 default:
15704 break;
15705 }
15706
15707 if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
15708 return (ffecom_2
15709 ((TREE_SIDE_EFFECTS (expr)
15710 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15711 integer_type_node,
15712 truthvalue_conversion (ffecom_1 (REALPART_EXPR,
15713 TREE_TYPE (TREE_TYPE (expr)),
15714 expr)),
15715 truthvalue_conversion (ffecom_1 (IMAGPART_EXPR,
15716 TREE_TYPE (TREE_TYPE (expr)),
15717 expr))));
15718
15719 return ffecom_2 (NE_EXPR, integer_type_node,
15720 expr,
15721 convert (TREE_TYPE (expr), integer_zero_node));
15722}
15723
15724tree
15725type_for_mode (mode, unsignedp)
15726 enum machine_mode mode;
15727 int unsignedp;
15728{
15729 int i;
15730 int j;
15731 tree t;
15732
15733 if (mode == TYPE_MODE (integer_type_node))
15734 return unsignedp ? unsigned_type_node : integer_type_node;
15735
15736 if (mode == TYPE_MODE (signed_char_type_node))
15737 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15738
15739 if (mode == TYPE_MODE (short_integer_type_node))
15740 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15741
15742 if (mode == TYPE_MODE (long_integer_type_node))
15743 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15744
15745 if (mode == TYPE_MODE (long_long_integer_type_node))
15746 return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
15747
15748 if (mode == TYPE_MODE (float_type_node))
15749 return float_type_node;
15750
15751 if (mode == TYPE_MODE (double_type_node))
15752 return double_type_node;
15753
15754 if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
15755 return build_pointer_type (char_type_node);
15756
15757 if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
15758 return build_pointer_type (integer_type_node);
15759
15760 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
15761 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
15762 {
15763 if (((t = ffecom_tree_type[i][j]) != NULL_TREE)
15764 && (mode == TYPE_MODE (t)))
567f3d36
KG
15765 {
15766 if ((i == FFEINFO_basictypeINTEGER) && unsignedp)
15767 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][j];
15768 else
15769 return t;
15770 }
5ff904cd
JL
15771 }
15772
15773 return 0;
15774}
15775
15776tree
15777type_for_size (bits, unsignedp)
15778 unsigned bits;
15779 int unsignedp;
15780{
15781 ffeinfoKindtype kt;
15782 tree type_node;
15783
15784 if (bits == TYPE_PRECISION (integer_type_node))
15785 return unsignedp ? unsigned_type_node : integer_type_node;
15786
15787 if (bits == TYPE_PRECISION (signed_char_type_node))
15788 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15789
15790 if (bits == TYPE_PRECISION (short_integer_type_node))
15791 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15792
15793 if (bits == TYPE_PRECISION (long_integer_type_node))
15794 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15795
15796 if (bits == TYPE_PRECISION (long_long_integer_type_node))
15797 return (unsignedp ? long_long_unsigned_type_node
15798 : long_long_integer_type_node);
15799
15800 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15801 {
15802 type_node = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15803
15804 if ((type_node != NULL_TREE) && (bits == TYPE_PRECISION (type_node)))
15805 return unsignedp ? ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt]
15806 : type_node;
15807 }
15808
15809 return 0;
15810}
15811
15812tree
15813unsigned_type (type)
15814 tree type;
15815{
15816 tree type1 = TYPE_MAIN_VARIANT (type);
15817 ffeinfoKindtype kt;
15818 tree type2;
15819
15820 if (type1 == signed_char_type_node || type1 == char_type_node)
15821 return unsigned_char_type_node;
15822 if (type1 == integer_type_node)
15823 return unsigned_type_node;
15824 if (type1 == short_integer_type_node)
15825 return short_unsigned_type_node;
15826 if (type1 == long_integer_type_node)
15827 return long_unsigned_type_node;
15828 if (type1 == long_long_integer_type_node)
15829 return long_long_unsigned_type_node;
15830#if 0 /* gcc/c-* files only */
15831 if (type1 == intDI_type_node)
15832 return unsigned_intDI_type_node;
15833 if (type1 == intSI_type_node)
15834 return unsigned_intSI_type_node;
15835 if (type1 == intHI_type_node)
15836 return unsigned_intHI_type_node;
15837 if (type1 == intQI_type_node)
15838 return unsigned_intQI_type_node;
15839#endif
15840
15841 type2 = type_for_size (TYPE_PRECISION (type1), 1);
15842 if (type2 != NULL_TREE)
15843 return type2;
15844
15845 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15846 {
15847 type2 = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15848
15849 if (type1 == type2)
15850 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
15851 }
15852
15853 return type;
15854}
15855
15856#endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
15857\f
15858#if FFECOM_GCC_INCLUDE
15859
15860/* From gcc/cccp.c, the code to handle -I. */
15861
15862/* Skip leading "./" from a directory name.
15863 This may yield the empty string, which represents the current directory. */
15864
15865static char *
15866skip_redundant_dir_prefix (char *dir)
15867{
15868 while (dir[0] == '.' && dir[1] == '/')
15869 for (dir += 2; *dir == '/'; dir++)
15870 continue;
15871 if (dir[0] == '.' && !dir[1])
15872 dir++;
15873 return dir;
15874}
15875
15876/* The file_name_map structure holds a mapping of file names for a
15877 particular directory. This mapping is read from the file named
15878 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
15879 map filenames on a file system with severe filename restrictions,
15880 such as DOS. The format of the file name map file is just a series
15881 of lines with two tokens on each line. The first token is the name
15882 to map, and the second token is the actual name to use. */
15883
15884struct file_name_map
15885{
15886 struct file_name_map *map_next;
15887 char *map_from;
15888 char *map_to;
15889};
15890
15891#define FILE_NAME_MAP_FILE "header.gcc"
15892
15893/* Current maximum length of directory names in the search path
15894 for include files. (Altered as we get more of them.) */
15895
15896static int max_include_len = 0;
15897
15898struct file_name_list
15899 {
15900 struct file_name_list *next;
15901 char *fname;
15902 /* Mapping of file names for this directory. */
15903 struct file_name_map *name_map;
15904 /* Non-zero if name_map is valid. */
15905 int got_name_map;
15906 };
15907
15908static struct file_name_list *include = NULL; /* First dir to search */
15909static struct file_name_list *last_include = NULL; /* Last in chain */
15910
15911/* I/O buffer structure.
15912 The `fname' field is nonzero for source files and #include files
15913 and for the dummy text used for -D and -U.
15914 It is zero for rescanning results of macro expansion
15915 and for expanding macro arguments. */
15916#define INPUT_STACK_MAX 400
15917static struct file_buf {
15918 char *fname;
15919 /* Filename specified with #line command. */
15920 char *nominal_fname;
15921 /* Record where in the search path this file was found.
15922 For #include_next. */
15923 struct file_name_list *dir;
15924 ffewhereLine line;
15925 ffewhereColumn column;
15926} instack[INPUT_STACK_MAX];
15927
15928static int last_error_tick = 0; /* Incremented each time we print it. */
15929static int input_file_stack_tick = 0; /* Incremented when status changes. */
15930
15931/* Current nesting level of input sources.
15932 `instack[indepth]' is the level currently being read. */
15933static int indepth = -1;
15934
15935typedef struct file_buf FILE_BUF;
15936
15937typedef unsigned char U_CHAR;
15938
15939/* table to tell if char can be part of a C identifier. */
15940U_CHAR is_idchar[256];
15941/* table to tell if char can be first char of a c identifier. */
15942U_CHAR is_idstart[256];
15943/* table to tell if c is horizontal space. */
15944U_CHAR is_hor_space[256];
15945/* table to tell if c is horizontal or vertical space. */
15946static U_CHAR is_space[256];
15947
15948#define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
15949#define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*p]) p++; } while (0)
15950
15951/* Nonzero means -I- has been seen,
15952 so don't look for #include "foo" the source-file directory. */
15953static int ignore_srcdir;
15954
15955#ifndef INCLUDE_LEN_FUDGE
15956#define INCLUDE_LEN_FUDGE 0
15957#endif
15958
15959static void append_include_chain (struct file_name_list *first,
15960 struct file_name_list *last);
15961static FILE *open_include_file (char *filename,
15962 struct file_name_list *searchptr);
15963static void print_containing_files (ffebadSeverity sev);
15964static char *skip_redundant_dir_prefix (char *);
15965static char *read_filename_string (int ch, FILE *f);
15966static struct file_name_map *read_name_map (char *dirname);
15967static char *savestring (char *input);
15968
15969/* Append a chain of `struct file_name_list's
15970 to the end of the main include chain.
15971 FIRST is the beginning of the chain to append, and LAST is the end. */
15972
15973static void
15974append_include_chain (first, last)
15975 struct file_name_list *first, *last;
15976{
15977 struct file_name_list *dir;
15978
15979 if (!first || !last)
15980 return;
15981
15982 if (include == 0)
15983 include = first;
15984 else
15985 last_include->next = first;
15986
15987 for (dir = first; ; dir = dir->next) {
15988 int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE;
15989 if (len > max_include_len)
15990 max_include_len = len;
15991 if (dir == last)
15992 break;
15993 }
15994
15995 last->next = NULL;
15996 last_include = last;
15997}
15998
15999/* Try to open include file FILENAME. SEARCHPTR is the directory
16000 being tried from the include file search path. This function maps
16001 filenames on file systems based on information read by
16002 read_name_map. */
16003
16004static FILE *
16005open_include_file (filename, searchptr)
16006 char *filename;
16007 struct file_name_list *searchptr;
16008{
16009 register struct file_name_map *map;
16010 register char *from;
16011 char *p, *dir;
16012
16013 if (searchptr && ! searchptr->got_name_map)
16014 {
16015 searchptr->name_map = read_name_map (searchptr->fname
16016 ? searchptr->fname : ".");
16017 searchptr->got_name_map = 1;
16018 }
16019
16020 /* First check the mapping for the directory we are using. */
16021 if (searchptr && searchptr->name_map)
16022 {
16023 from = filename;
16024 if (searchptr->fname)
16025 from += strlen (searchptr->fname) + 1;
16026 for (map = searchptr->name_map; map; map = map->map_next)
16027 {
16028 if (! strcmp (map->map_from, from))
16029 {
16030 /* Found a match. */
16031 return fopen (map->map_to, "r");
16032 }
16033 }
16034 }
16035
16036 /* Try to find a mapping file for the particular directory we are
16037 looking in. Thus #include <sys/types.h> will look up sys/types.h
16038 in /usr/include/header.gcc and look up types.h in
16039 /usr/include/sys/header.gcc. */
16040 p = rindex (filename, '/');
16041#ifdef DIR_SEPARATOR
16042 if (! p) p = rindex (filename, DIR_SEPARATOR);
16043 else {
16044 char *tmp = rindex (filename, DIR_SEPARATOR);
16045 if (tmp != NULL && tmp > p) p = tmp;
16046 }
16047#endif
16048 if (! p)
16049 p = filename;
16050 if (searchptr
16051 && searchptr->fname
16052 && strlen (searchptr->fname) == (size_t) (p - filename)
16053 && ! strncmp (searchptr->fname, filename, (int) (p - filename)))
16054 {
16055 /* FILENAME is in SEARCHPTR, which we've already checked. */
16056 return fopen (filename, "r");
16057 }
16058
16059 if (p == filename)
16060 {
16061 from = filename;
16062 map = read_name_map (".");
16063 }
16064 else
16065 {
16066 dir = (char *) xmalloc (p - filename + 1);
34b8e428 16067 memcpy (dir, filename, p - filename);
5ff904cd
JL
16068 dir[p - filename] = '\0';
16069 from = p + 1;
16070 map = read_name_map (dir);
16071 free (dir);
16072 }
16073 for (; map; map = map->map_next)
16074 if (! strcmp (map->map_from, from))
16075 return fopen (map->map_to, "r");
16076
16077 return fopen (filename, "r");
16078}
16079
16080/* Print the file names and line numbers of the #include
16081 commands which led to the current file. */
16082
16083static void
16084print_containing_files (ffebadSeverity sev)
16085{
16086 FILE_BUF *ip = NULL;
16087 int i;
16088 int first = 1;
16089 char *str1;
16090 char *str2;
16091
16092 /* If stack of files hasn't changed since we last printed
16093 this info, don't repeat it. */
16094 if (last_error_tick == input_file_stack_tick)
16095 return;
16096
16097 for (i = indepth; i >= 0; i--)
16098 if (instack[i].fname != NULL) {
16099 ip = &instack[i];
16100 break;
16101 }
16102
16103 /* Give up if we don't find a source file. */
16104 if (ip == NULL)
16105 return;
16106
16107 /* Find the other, outer source files. */
16108 for (i--; i >= 0; i--)
16109 if (instack[i].fname != NULL)
16110 {
16111 ip = &instack[i];
16112 if (first)
16113 {
16114 first = 0;
16115 str1 = "In file included";
16116 }
16117 else
16118 {
16119 str1 = "... ...";
16120 }
16121
16122 if (i == 1)
16123 str2 = ":";
16124 else
16125 str2 = "";
16126
16127 ffebad_start_msg ("%A from %B at %0%C", sev);
16128 ffebad_here (0, ip->line, ip->column);
16129 ffebad_string (str1);
16130 ffebad_string (ip->nominal_fname);
16131 ffebad_string (str2);
16132 ffebad_finish ();
16133 }
16134
16135 /* Record we have printed the status as of this time. */
16136 last_error_tick = input_file_stack_tick;
16137}
16138
16139/* Read a space delimited string of unlimited length from a stdio
16140 file. */
16141
16142static char *
16143read_filename_string (ch, f)
16144 int ch;
16145 FILE *f;
16146{
16147 char *alloc, *set;
16148 int len;
16149
16150 len = 20;
16151 set = alloc = xmalloc (len + 1);
16152 if (! is_space[ch])
16153 {
16154 *set++ = ch;
16155 while ((ch = getc (f)) != EOF && ! is_space[ch])
16156 {
16157 if (set - alloc == len)
16158 {
16159 len *= 2;
16160 alloc = xrealloc (alloc, len + 1);
16161 set = alloc + len / 2;
16162 }
16163 *set++ = ch;
16164 }
16165 }
16166 *set = '\0';
16167 ungetc (ch, f);
16168 return alloc;
16169}
16170
16171/* Read the file name map file for DIRNAME. */
16172
16173static struct file_name_map *
16174read_name_map (dirname)
16175 char *dirname;
16176{
16177 /* This structure holds a linked list of file name maps, one per
16178 directory. */
16179 struct file_name_map_list
16180 {
16181 struct file_name_map_list *map_list_next;
16182 char *map_list_name;
16183 struct file_name_map *map_list_map;
16184 };
16185 static struct file_name_map_list *map_list;
16186 register struct file_name_map_list *map_list_ptr;
16187 char *name;
16188 FILE *f;
16189 size_t dirlen;
16190 int separator_needed;
16191
16192 dirname = skip_redundant_dir_prefix (dirname);
16193
16194 for (map_list_ptr = map_list; map_list_ptr;
16195 map_list_ptr = map_list_ptr->map_list_next)
16196 if (! strcmp (map_list_ptr->map_list_name, dirname))
16197 return map_list_ptr->map_list_map;
16198
16199 map_list_ptr = ((struct file_name_map_list *)
16200 xmalloc (sizeof (struct file_name_map_list)));
16201 map_list_ptr->map_list_name = savestring (dirname);
16202 map_list_ptr->map_list_map = NULL;
16203
16204 dirlen = strlen (dirname);
16205 separator_needed = dirlen != 0 && dirname[dirlen - 1] != '/';
16206 name = (char *) xmalloc (dirlen + strlen (FILE_NAME_MAP_FILE) + 2);
16207 strcpy (name, dirname);
16208 name[dirlen] = '/';
16209 strcpy (name + dirlen + separator_needed, FILE_NAME_MAP_FILE);
16210 f = fopen (name, "r");
16211 free (name);
16212 if (!f)
16213 map_list_ptr->map_list_map = NULL;
16214 else
16215 {
16216 int ch;
16217
16218 while ((ch = getc (f)) != EOF)
16219 {
16220 char *from, *to;
16221 struct file_name_map *ptr;
16222
16223 if (is_space[ch])
16224 continue;
16225 from = read_filename_string (ch, f);
16226 while ((ch = getc (f)) != EOF && is_hor_space[ch])
16227 ;
16228 to = read_filename_string (ch, f);
16229
16230 ptr = ((struct file_name_map *)
16231 xmalloc (sizeof (struct file_name_map)));
16232 ptr->map_from = from;
16233
16234 /* Make the real filename absolute. */
16235 if (*to == '/')
16236 ptr->map_to = to;
16237 else
16238 {
16239 ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
16240 strcpy (ptr->map_to, dirname);
16241 ptr->map_to[dirlen] = '/';
16242 strcpy (ptr->map_to + dirlen + separator_needed, to);
16243 free (to);
16244 }
16245
16246 ptr->map_next = map_list_ptr->map_list_map;
16247 map_list_ptr->map_list_map = ptr;
16248
16249 while ((ch = getc (f)) != '\n')
16250 if (ch == EOF)
16251 break;
16252 }
16253 fclose (f);
16254 }
16255
16256 map_list_ptr->map_list_next = map_list;
16257 map_list = map_list_ptr;
16258
16259 return map_list_ptr->map_list_map;
16260}
16261
16262static char *
16263savestring (input)
16264 char *input;
16265{
16266 unsigned size = strlen (input);
16267 char *output = xmalloc (size + 1);
16268 strcpy (output, input);
16269 return output;
16270}
16271
16272static void
16273ffecom_file_ (char *name)
16274{
16275 FILE_BUF *fp;
16276
16277 /* Do partial setup of input buffer for the sake of generating
16278 early #line directives (when -g is in effect). */
16279
16280 fp = &instack[++indepth];
34b8e428 16281 memset ((char *) fp, 0, sizeof (FILE_BUF));
5ff904cd
JL
16282 if (name == NULL)
16283 name = "";
16284 fp->nominal_fname = fp->fname = name;
16285}
16286
16287/* Initialize syntactic classifications of characters. */
16288
16289static void
16290ffecom_initialize_char_syntax_ ()
16291{
16292 register int i;
16293
16294 /*
16295 * Set up is_idchar and is_idstart tables. These should be
16296 * faster than saying (is_alpha (c) || c == '_'), etc.
16297 * Set up these things before calling any routines tthat
16298 * refer to them.
16299 */
16300 for (i = 'a'; i <= 'z'; i++) {
16301 is_idchar[i - 'a' + 'A'] = 1;
16302 is_idchar[i] = 1;
16303 is_idstart[i - 'a' + 'A'] = 1;
16304 is_idstart[i] = 1;
16305 }
16306 for (i = '0'; i <= '9'; i++)
16307 is_idchar[i] = 1;
16308 is_idchar['_'] = 1;
16309 is_idstart['_'] = 1;
16310
16311 /* horizontal space table */
16312 is_hor_space[' '] = 1;
16313 is_hor_space['\t'] = 1;
16314 is_hor_space['\v'] = 1;
16315 is_hor_space['\f'] = 1;
16316 is_hor_space['\r'] = 1;
16317
16318 is_space[' '] = 1;
16319 is_space['\t'] = 1;
16320 is_space['\v'] = 1;
16321 is_space['\f'] = 1;
16322 is_space['\n'] = 1;
16323 is_space['\r'] = 1;
16324}
16325
16326static void
16327ffecom_close_include_ (FILE *f)
16328{
16329 fclose (f);
16330
16331 indepth--;
16332 input_file_stack_tick++;
16333
16334 ffewhere_line_kill (instack[indepth].line);
16335 ffewhere_column_kill (instack[indepth].column);
16336}
16337
16338static int
16339ffecom_decode_include_option_ (char *spec)
16340{
16341 struct file_name_list *dirtmp;
16342
16343 if (! ignore_srcdir && !strcmp (spec, "-"))
16344 ignore_srcdir = 1;
16345 else
16346 {
16347 dirtmp = (struct file_name_list *)
16348 xmalloc (sizeof (struct file_name_list));
16349 dirtmp->next = 0; /* New one goes on the end */
16350 if (spec[0] != 0)
16351 dirtmp->fname = spec;
16352 else
16353 fatal ("Directory name must immediately follow -I option with no intervening spaces, as in `-Idir', not `-I dir'");
16354 dirtmp->got_name_map = 0;
16355 append_include_chain (dirtmp, dirtmp);
16356 }
16357 return 1;
16358}
16359
16360/* Open INCLUDEd file. */
16361
16362static FILE *
16363ffecom_open_include_ (char *name, ffewhereLine l, ffewhereColumn c)
16364{
16365 char *fbeg = name;
16366 size_t flen = strlen (fbeg);
16367 struct file_name_list *search_start = include; /* Chain of dirs to search */
16368 struct file_name_list dsp[1]; /* First in chain, if #include "..." */
16369 struct file_name_list *searchptr = 0;
16370 char *fname; /* Dynamically allocated fname buffer */
16371 FILE *f;
16372 FILE_BUF *fp;
16373
16374 if (flen == 0)
16375 return NULL;
16376
16377 dsp[0].fname = NULL;
16378
16379 /* If -I- was specified, don't search current dir, only spec'd ones. */
16380 if (!ignore_srcdir)
16381 {
16382 for (fp = &instack[indepth]; fp >= instack; fp--)
16383 {
16384 int n;
16385 char *ep;
16386 char *nam;
16387
16388 if ((nam = fp->nominal_fname) != NULL)
16389 {
16390 /* Found a named file. Figure out dir of the file,
16391 and put it in front of the search list. */
16392 dsp[0].next = search_start;
16393 search_start = dsp;
16394#ifndef VMS
16395 ep = rindex (nam, '/');
16396#ifdef DIR_SEPARATOR
16397 if (ep == NULL) ep = rindex (nam, DIR_SEPARATOR);
16398 else {
16399 char *tmp = rindex (nam, DIR_SEPARATOR);
16400 if (tmp != NULL && tmp > ep) ep = tmp;
16401 }
16402#endif
16403#else /* VMS */
16404 ep = rindex (nam, ']');
16405 if (ep == NULL) ep = rindex (nam, '>');
16406 if (ep == NULL) ep = rindex (nam, ':');
16407 if (ep != NULL) ep++;
16408#endif /* VMS */
16409 if (ep != NULL)
16410 {
16411 n = ep - nam;
16412 dsp[0].fname = (char *) xmalloc (n + 1);
16413 strncpy (dsp[0].fname, nam, n);
16414 dsp[0].fname[n] = '\0';
16415 if (n + INCLUDE_LEN_FUDGE > max_include_len)
16416 max_include_len = n + INCLUDE_LEN_FUDGE;
16417 }
16418 else
16419 dsp[0].fname = NULL; /* Current directory */
16420 dsp[0].got_name_map = 0;
16421 break;
16422 }
16423 }
16424 }
16425
16426 /* Allocate this permanently, because it gets stored in the definitions
16427 of macros. */
16428 fname = xmalloc (max_include_len + flen + 4);
16429 /* + 2 above for slash and terminating null. */
16430 /* + 2 added for '.h' on VMS (to support '#include filename') (NOT USED
16431 for g77 yet). */
16432
16433 /* If specified file name is absolute, just open it. */
16434
16435 if (*fbeg == '/'
16436#ifdef DIR_SEPARATOR
16437 || *fbeg == DIR_SEPARATOR
16438#endif
16439 )
16440 {
16441 strncpy (fname, (char *) fbeg, flen);
16442 fname[flen] = 0;
16443 f = open_include_file (fname, NULL_PTR);
16444 }
16445 else
16446 {
16447 f = NULL;
16448
16449 /* Search directory path, trying to open the file.
16450 Copy each filename tried into FNAME. */
16451
16452 for (searchptr = search_start; searchptr; searchptr = searchptr->next)
16453 {
16454 if (searchptr->fname)
16455 {
16456 /* The empty string in a search path is ignored.
16457 This makes it possible to turn off entirely
16458 a standard piece of the list. */
16459 if (searchptr->fname[0] == 0)
16460 continue;
16461 strcpy (fname, skip_redundant_dir_prefix (searchptr->fname));
16462 if (fname[0] && fname[strlen (fname) - 1] != '/')
16463 strcat (fname, "/");
16464 fname[strlen (fname) + flen] = 0;
16465 }
16466 else
16467 fname[0] = 0;
16468
16469 strncat (fname, fbeg, flen);
16470#ifdef VMS
16471 /* Change this 1/2 Unix 1/2 VMS file specification into a
16472 full VMS file specification */
16473 if (searchptr->fname && (searchptr->fname[0] != 0))
16474 {
16475 /* Fix up the filename */
16476 hack_vms_include_specification (fname);
16477 }
16478 else
16479 {
16480 /* This is a normal VMS filespec, so use it unchanged. */
16481 strncpy (fname, (char *) fbeg, flen);
16482 fname[flen] = 0;
16483#if 0 /* Not for g77. */
16484 /* if it's '#include filename', add the missing .h */
16485 if (index (fname, '.') == NULL)
16486 strcat (fname, ".h");
16487#endif
16488 }
16489#endif /* VMS */
16490 f = open_include_file (fname, searchptr);
16491#ifdef EACCES
16492 if (f == NULL && errno == EACCES)
16493 {
16494 print_containing_files (FFEBAD_severityWARNING);
16495 ffebad_start_msg ("At %0, INCLUDE file %A exists, but is not readable",
16496 FFEBAD_severityWARNING);
16497 ffebad_string (fname);
16498 ffebad_here (0, l, c);
16499 ffebad_finish ();
16500 }
16501#endif
16502 if (f != NULL)
16503 break;
16504 }
16505 }
16506
16507 if (f == NULL)
16508 {
16509 /* A file that was not found. */
16510
16511 strncpy (fname, (char *) fbeg, flen);
16512 fname[flen] = 0;
16513 print_containing_files (ffebad_severity (FFEBAD_OPEN_INCLUDE));
16514 ffebad_start (FFEBAD_OPEN_INCLUDE);
16515 ffebad_here (0, l, c);
16516 ffebad_string (fname);
16517 ffebad_finish ();
16518 }
16519
16520 if (dsp[0].fname != NULL)
16521 free (dsp[0].fname);
16522
16523 if (f == NULL)
16524 return NULL;
16525
16526 if (indepth >= (INPUT_STACK_MAX - 1))
16527 {
16528 print_containing_files (FFEBAD_severityFATAL);
16529 ffebad_start_msg ("At %0, INCLUDE nesting too deep",
16530 FFEBAD_severityFATAL);
16531 ffebad_string (fname);
16532 ffebad_here (0, l, c);
16533 ffebad_finish ();
16534 return NULL;
16535 }
16536
16537 instack[indepth].line = ffewhere_line_use (l);
16538 instack[indepth].column = ffewhere_column_use (c);
16539
16540 fp = &instack[indepth + 1];
34b8e428 16541 memset ((char *) fp, 0, sizeof (FILE_BUF));
5ff904cd
JL
16542 fp->nominal_fname = fp->fname = fname;
16543 fp->dir = searchptr;
16544
16545 indepth++;
16546 input_file_stack_tick++;
16547
16548 return f;
16549}
16550#endif /* FFECOM_GCC_INCLUDE */
This page took 1.767175 seconds and 5 git commands to generate.