com.c (ffecom_transform_equiv_): Make EQUIVALENCEs addressable so that debug info...
[gcc.git] / gcc / f / com.c
1 /* com.c -- Implementation File (module.c template V1.0)
2 Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000
3 Free Software Foundation, Inc.
4 Contributed by James Craig Burley.
5
6 This file is part of GNU Fortran.
7
8 GNU Fortran is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 GNU Fortran is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GNU Fortran; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
21 02111-1307, USA.
22
23 Related Modules:
24 None
25
26 Description:
27 Contains compiler-specific functions.
28
29 Modifications:
30 */
31
32 /* Understanding this module means understanding the interface between
33 the g77 front end and the gcc back end (or, perhaps, some other
34 back end). In here are the functions called by the front end proper
35 to notify whatever back end is in place about certain things, and
36 also the back-end-specific functions. It's a bear to deal with, so
37 lately I've been trying to simplify things, especially with regard
38 to the gcc-back-end-specific stuff.
39
40 Building expressions generally seems quite easy, but building decls
41 has been challenging and is undergoing revision. gcc has several
42 kinds of decls:
43
44 TYPE_DECL -- a type (int, float, struct, function, etc.)
45 CONST_DECL -- a constant of some type other than function
46 LABEL_DECL -- a variable or a constant?
47 PARM_DECL -- an argument to a function (a variable that is a dummy)
48 RESULT_DECL -- the return value of a function (a variable)
49 VAR_DECL -- other variable (can hold a ptr-to-function, struct, int, etc.)
50 FUNCTION_DECL -- a function (either the actual function or an extern ref)
51 FIELD_DECL -- a field in a struct or union (goes into types)
52
53 g77 has a set of functions that somewhat parallels the gcc front end
54 when it comes to building decls:
55
56 Internal Function (one we define, not just declare as extern):
57 int yes;
58 yes = suspend_momentary ();
59 if (is_nested) push_f_function_context ();
60 start_function (get_identifier ("function_name"), function_type,
61 is_nested, is_public);
62 // for each arg, build PARM_DECL and call push_parm_decl (decl) with it;
63 store_parm_decls (is_main_program);
64 ffecom_start_compstmt ();
65 // for stmts and decls inside function, do appropriate things;
66 ffecom_end_compstmt ();
67 finish_function (is_nested);
68 if (is_nested) pop_f_function_context ();
69 if (is_nested) resume_momentary (yes);
70
71 Everything Else:
72 int yes;
73 tree d;
74 tree init;
75 yes = suspend_momentary ();
76 // fill in external, public, static, &c for decl, and
77 // set DECL_INITIAL to error_mark_node if going to initialize
78 // set is_top_level TRUE only if not at top level and decl
79 // must go in top level (i.e. not within current function decl context)
80 d = start_decl (decl, is_top_level);
81 init = ...; // if have initializer
82 finish_decl (d, init, is_top_level);
83 resume_momentary (yes);
84
85 */
86
87 /* Include files. */
88
89 #include "proj.h"
90 #if FFECOM_targetCURRENT == FFECOM_targetGCC
91 #include "flags.h"
92 #include "rtl.h"
93 #include "toplev.h"
94 #include "tree.h"
95 #include "output.h" /* Must follow tree.h so TREE_CODE is defined! */
96 #include "convert.h"
97 #include "ggc.h"
98 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
99
100 #define FFECOM_GCC_INCLUDE 1 /* Enable -I. */
101
102 /* BEGIN stuff from gcc/cccp.c. */
103
104 /* The following symbols should be autoconfigured:
105 HAVE_FCNTL_H
106 HAVE_STDLIB_H
107 HAVE_SYS_TIME_H
108 HAVE_UNISTD_H
109 STDC_HEADERS
110 TIME_WITH_SYS_TIME
111 In the mean time, we'll get by with approximations based
112 on existing GCC configuration symbols. */
113
114 #ifdef POSIX
115 # ifndef HAVE_STDLIB_H
116 # define HAVE_STDLIB_H 1
117 # endif
118 # ifndef HAVE_UNISTD_H
119 # define HAVE_UNISTD_H 1
120 # endif
121 # ifndef STDC_HEADERS
122 # define STDC_HEADERS 1
123 # endif
124 #endif /* defined (POSIX) */
125
126 #if defined (POSIX) || (defined (USG) && !defined (VMS))
127 # ifndef HAVE_FCNTL_H
128 # define HAVE_FCNTL_H 1
129 # endif
130 #endif
131
132 #ifndef RLIMIT_STACK
133 # include <time.h>
134 #else
135 # if TIME_WITH_SYS_TIME
136 # include <sys/time.h>
137 # include <time.h>
138 # else
139 # if HAVE_SYS_TIME_H
140 # include <sys/time.h>
141 # else
142 # include <time.h>
143 # endif
144 # endif
145 # include <sys/resource.h>
146 #endif
147
148 #if HAVE_FCNTL_H
149 # include <fcntl.h>
150 #endif
151
152 /* This defines "errno" properly for VMS, and gives us EACCES. */
153 #include <errno.h>
154
155 #if HAVE_STDLIB_H
156 # include <stdlib.h>
157 #else
158 char *getenv ();
159 #endif
160
161 #if HAVE_UNISTD_H
162 # include <unistd.h>
163 #endif
164
165 /* VMS-specific definitions */
166 #ifdef VMS
167 #include <descrip.h>
168 #define O_RDONLY 0 /* Open arg for Read/Only */
169 #define O_WRONLY 1 /* Open arg for Write/Only */
170 #define read(fd,buf,size) VMS_read (fd,buf,size)
171 #define write(fd,buf,size) VMS_write (fd,buf,size)
172 #define open(fname,mode,prot) VMS_open (fname,mode,prot)
173 #define fopen(fname,mode) VMS_fopen (fname,mode)
174 #define freopen(fname,mode,ofile) VMS_freopen (fname,mode,ofile)
175 #define strncat(dst,src,cnt) VMS_strncat (dst,src,cnt)
176 #define fstat(fd,stbuf) VMS_fstat (fd,stbuf)
177 static int VMS_fstat (), VMS_stat ();
178 static char * VMS_strncat ();
179 static int VMS_read ();
180 static int VMS_write ();
181 static int VMS_open ();
182 static FILE * VMS_fopen ();
183 static FILE * VMS_freopen ();
184 static void hack_vms_include_specification ();
185 typedef struct { unsigned :16, :16, :16; } vms_ino_t;
186 #define ino_t vms_ino_t
187 #define INCLUDE_LEN_FUDGE 10 /* leave room for VMS syntax conversion */
188 #ifdef __GNUC__
189 #define BSTRING /* VMS/GCC supplies the bstring routines */
190 #endif /* __GNUC__ */
191 #endif /* VMS */
192
193 #ifndef O_RDONLY
194 #define O_RDONLY 0
195 #endif
196
197 /* END stuff from gcc/cccp.c. */
198
199 #define FFECOM_DETERMINE_TYPES 1 /* for com.h */
200 #include "com.h"
201 #include "bad.h"
202 #include "bld.h"
203 #include "equiv.h"
204 #include "expr.h"
205 #include "implic.h"
206 #include "info.h"
207 #include "malloc.h"
208 #include "src.h"
209 #include "st.h"
210 #include "storag.h"
211 #include "symbol.h"
212 #include "target.h"
213 #include "top.h"
214 #include "type.h"
215
216 /* Externals defined here. */
217
218 #if FFECOM_targetCURRENT == FFECOM_targetGCC
219
220 /* ~~gcc/tree.h *should* declare this, because toplev.c and dwarfout.c
221 reference it. */
222
223 const char * const language_string = "GNU F77";
224
225 /* Stream for reading from the input file. */
226 FILE *finput;
227
228 /* These definitions parallel those in c-decl.c so that code from that
229 module can be used pretty much as is. Much of these defs aren't
230 otherwise used, i.e. by g77 code per se, except some of them are used
231 to build some of them that are. The ones that are global (i.e. not
232 "static") are those that ste.c and such might use (directly
233 or by using com macros that reference them in their definitions). */
234
235 tree string_type_node;
236
237 /* The rest of these are inventions for g77, though there might be
238 similar things in the C front end. As they are found, these
239 inventions should be renamed to be canonical. Note that only
240 the ones currently required to be global are so. */
241
242 static tree ffecom_tree_fun_type_void;
243
244 tree ffecom_integer_type_node; /* Abbrev for _tree_type[blah][blah]. */
245 tree ffecom_integer_zero_node; /* Like *_*_* with g77's integer type. */
246 tree ffecom_integer_one_node; /* " */
247 tree ffecom_tree_type[FFEINFO_basictype][FFEINFO_kindtype];
248
249 /* _fun_type things are the f2c-specific versions. For -fno-f2c,
250 just use build_function_type and build_pointer_type on the
251 appropriate _tree_type array element. */
252
253 static tree ffecom_tree_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
254 static tree ffecom_tree_ptr_to_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
255 static tree ffecom_tree_subr_type;
256 static tree ffecom_tree_ptr_to_subr_type;
257 static tree ffecom_tree_blockdata_type;
258
259 static tree ffecom_tree_xargc_;
260
261 ffecomSymbol ffecom_symbol_null_
262 =
263 {
264 NULL_TREE,
265 NULL_TREE,
266 NULL_TREE,
267 NULL_TREE,
268 false
269 };
270 ffeinfoKindtype ffecom_pointer_kind_ = FFEINFO_basictypeNONE;
271 ffeinfoKindtype ffecom_label_kind_ = FFEINFO_basictypeNONE;
272
273 int ffecom_f2c_typecode_[FFEINFO_basictype][FFEINFO_kindtype];
274 tree ffecom_f2c_integer_type_node;
275 tree ffecom_f2c_ptr_to_integer_type_node;
276 tree ffecom_f2c_address_type_node;
277 tree ffecom_f2c_real_type_node;
278 tree ffecom_f2c_ptr_to_real_type_node;
279 tree ffecom_f2c_doublereal_type_node;
280 tree ffecom_f2c_complex_type_node;
281 tree ffecom_f2c_doublecomplex_type_node;
282 tree ffecom_f2c_longint_type_node;
283 tree ffecom_f2c_logical_type_node;
284 tree ffecom_f2c_flag_type_node;
285 tree ffecom_f2c_ftnlen_type_node;
286 tree ffecom_f2c_ftnlen_zero_node;
287 tree ffecom_f2c_ftnlen_one_node;
288 tree ffecom_f2c_ftnlen_two_node;
289 tree ffecom_f2c_ptr_to_ftnlen_type_node;
290 tree ffecom_f2c_ftnint_type_node;
291 tree ffecom_f2c_ptr_to_ftnint_type_node;
292 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
293
294 /* Simple definitions and enumerations. */
295
296 #ifndef FFECOM_sizeMAXSTACKITEM
297 #define FFECOM_sizeMAXSTACKITEM 32*1024 /* Keep user-declared things
298 larger than this # bytes
299 off stack if possible. */
300 #endif
301
302 /* For systems that have large enough stacks, they should define
303 this to 0, and here, for ease of use later on, we just undefine
304 it if it is 0. */
305
306 #if FFECOM_sizeMAXSTACKITEM == 0
307 #undef FFECOM_sizeMAXSTACKITEM
308 #endif
309
310 typedef enum
311 {
312 FFECOM_rttypeVOID_,
313 FFECOM_rttypeVOIDSTAR_, /* C's `void *' type. */
314 FFECOM_rttypeFTNINT_, /* f2c's `ftnint' type. */
315 FFECOM_rttypeINTEGER_, /* f2c's `integer' type. */
316 FFECOM_rttypeLONGINT_, /* f2c's `longint' type. */
317 FFECOM_rttypeLOGICAL_, /* f2c's `logical' type. */
318 FFECOM_rttypeREAL_F2C_, /* f2c's `real' returned as `double'. */
319 FFECOM_rttypeREAL_GNU_, /* `real' returned as such. */
320 FFECOM_rttypeCOMPLEX_F2C_, /* f2c's `complex' returned via 1st arg. */
321 FFECOM_rttypeCOMPLEX_GNU_, /* f2c's `complex' returned directly. */
322 FFECOM_rttypeDOUBLE_, /* C's `double' type. */
323 FFECOM_rttypeDOUBLEREAL_, /* f2c's `doublereal' type. */
324 FFECOM_rttypeDBLCMPLX_F2C_, /* f2c's `doublecomplex' returned via 1st arg. */
325 FFECOM_rttypeDBLCMPLX_GNU_, /* f2c's `doublecomplex' returned directly. */
326 FFECOM_rttypeCHARACTER_, /* f2c `char *'/`ftnlen' pair. */
327 FFECOM_rttype_
328 } ffecomRttype_;
329
330 /* Internal typedefs. */
331
332 #if FFECOM_targetCURRENT == FFECOM_targetGCC
333 typedef struct _ffecom_concat_list_ ffecomConcatList_;
334 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
335
336 /* Private include files. */
337
338
339 /* Internal structure definitions. */
340
341 #if FFECOM_targetCURRENT == FFECOM_targetGCC
342 struct _ffecom_concat_list_
343 {
344 ffebld *exprs;
345 int count;
346 int max;
347 ffetargetCharacterSize minlen;
348 ffetargetCharacterSize maxlen;
349 };
350 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
351
352 /* Static functions (internal). */
353
354 #if FFECOM_targetCURRENT == FFECOM_targetGCC
355 static tree ffecom_arglist_expr_ (const char *argstring, ffebld args);
356 static tree ffecom_widest_expr_type_ (ffebld list);
357 static bool ffecom_overlap_ (tree dest_decl, tree dest_offset,
358 tree dest_size, tree source_tree,
359 ffebld source, bool scalar_arg);
360 static bool ffecom_args_overlapping_ (tree dest_tree, ffebld dest,
361 tree args, tree callee_commons,
362 bool scalar_args);
363 static tree ffecom_build_f2c_string_ (int i, const char *s);
364 static tree ffecom_call_ (tree fn, ffeinfoKindtype kt,
365 bool is_f2c_complex, tree type,
366 tree args, tree dest_tree,
367 ffebld dest, bool *dest_used,
368 tree callee_commons, bool scalar_args, tree hook);
369 static tree ffecom_call_binop_ (tree fn, ffeinfoKindtype kt,
370 bool is_f2c_complex, tree type,
371 ffebld left, ffebld right,
372 tree dest_tree, ffebld dest,
373 bool *dest_used, tree callee_commons,
374 bool scalar_args, tree hook);
375 static void ffecom_char_args_x_ (tree *xitem, tree *length,
376 ffebld expr, bool with_null);
377 static tree ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy);
378 static tree ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s);
379 static ffecomConcatList_
380 ffecom_concat_list_gather_ (ffecomConcatList_ catlist,
381 ffebld expr,
382 ffetargetCharacterSize max);
383 static void ffecom_concat_list_kill_ (ffecomConcatList_ catlist);
384 static ffecomConcatList_ ffecom_concat_list_new_ (ffebld expr,
385 ffetargetCharacterSize max);
386 static void ffecom_debug_kludge_ (tree aggr, const char *aggr_type,
387 ffesymbol member, tree member_type,
388 ffetargetOffset offset);
389 static void ffecom_do_entry_ (ffesymbol fn, int entrynum);
390 static tree ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
391 bool *dest_used, bool assignp, bool widenp);
392 static tree ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
393 ffebld dest, bool *dest_used);
394 static tree ffecom_expr_power_integer_ (ffebld expr);
395 static void ffecom_expr_transform_ (ffebld expr);
396 static void ffecom_f2c_make_type_ (tree *type, int tcode, const char *name);
397 static void ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
398 int code);
399 static ffeglobal ffecom_finish_global_ (ffeglobal global);
400 static ffesymbol ffecom_finish_symbol_transform_ (ffesymbol s);
401 static tree ffecom_get_appended_identifier_ (char us, const char *text);
402 static tree ffecom_get_external_identifier_ (ffesymbol s);
403 static tree ffecom_get_identifier_ (const char *text);
404 static tree ffecom_gen_sfuncdef_ (ffesymbol s,
405 ffeinfoBasictype bt,
406 ffeinfoKindtype kt);
407 static const char *ffecom_gfrt_args_ (ffecomGfrt ix);
408 static tree ffecom_gfrt_tree_ (ffecomGfrt ix);
409 static tree ffecom_init_zero_ (tree decl);
410 static tree ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
411 tree *maybe_tree);
412 static tree ffecom_intrinsic_len_ (ffebld expr);
413 static void ffecom_let_char_ (tree dest_tree,
414 tree dest_length,
415 ffetargetCharacterSize dest_size,
416 ffebld source);
417 static void ffecom_make_gfrt_ (ffecomGfrt ix);
418 static void ffecom_member_phase1_ (ffestorag mst, ffestorag st);
419 static void ffecom_member_phase2_ (ffestorag mst, ffestorag st);
420 static void ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size,
421 ffebld source);
422 static void ffecom_push_dummy_decls_ (ffebld dumlist,
423 bool stmtfunc);
424 static void ffecom_start_progunit_ (void);
425 static ffesymbol ffecom_sym_transform_ (ffesymbol s);
426 static ffesymbol ffecom_sym_transform_assign_ (ffesymbol s);
427 static void ffecom_transform_common_ (ffesymbol s);
428 static void ffecom_transform_equiv_ (ffestorag st);
429 static tree ffecom_transform_namelist_ (ffesymbol s);
430 static void ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
431 tree t);
432 static void ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
433 tree *size, tree tree);
434 static tree ffecom_tree_divide_ (tree tree_type, tree left, tree right,
435 tree dest_tree, ffebld dest,
436 bool *dest_used, tree hook);
437 static tree ffecom_type_localvar_ (ffesymbol s,
438 ffeinfoBasictype bt,
439 ffeinfoKindtype kt);
440 static tree ffecom_type_namelist_ (void);
441 static tree ffecom_type_vardesc_ (void);
442 static tree ffecom_vardesc_ (ffebld expr);
443 static tree ffecom_vardesc_array_ (ffesymbol s);
444 static tree ffecom_vardesc_dims_ (ffesymbol s);
445 static tree ffecom_convert_narrow_ (tree type, tree expr);
446 static tree ffecom_convert_widen_ (tree type, tree expr);
447 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
448
449 /* These are static functions that parallel those found in the C front
450 end and thus have the same names. */
451
452 #if FFECOM_targetCURRENT == FFECOM_targetGCC
453 static tree bison_rule_compstmt_ (void);
454 static void bison_rule_pushlevel_ (void);
455 static void delete_block (tree block);
456 static int duplicate_decls (tree newdecl, tree olddecl);
457 static void finish_decl (tree decl, tree init, bool is_top_level);
458 static void finish_function (int nested);
459 static const char *lang_printable_name (tree decl, int v);
460 static tree lookup_name_current_level (tree name);
461 static struct binding_level *make_binding_level (void);
462 static void pop_f_function_context (void);
463 static void push_f_function_context (void);
464 static void push_parm_decl (tree parm);
465 static tree pushdecl_top_level (tree decl);
466 static int kept_level_p (void);
467 static tree storedecls (tree decls);
468 static void store_parm_decls (int is_main_program);
469 static tree start_decl (tree decl, bool is_top_level);
470 static void start_function (tree name, tree type, int nested, int public);
471 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
472 #if FFECOM_GCC_INCLUDE
473 static void ffecom_file_ (const char *name);
474 static void ffecom_initialize_char_syntax_ (void);
475 static void ffecom_close_include_ (FILE *f);
476 static int ffecom_decode_include_option_ (char *spec);
477 static FILE *ffecom_open_include_ (char *name, ffewhereLine l,
478 ffewhereColumn c);
479 #endif /* FFECOM_GCC_INCLUDE */
480
481 /* Static objects accessed by functions in this module. */
482
483 static ffesymbol ffecom_primary_entry_ = NULL;
484 static ffesymbol ffecom_nested_entry_ = NULL;
485 static ffeinfoKind ffecom_primary_entry_kind_;
486 static bool ffecom_primary_entry_is_proc_;
487 #if FFECOM_targetCURRENT == FFECOM_targetGCC
488 static tree ffecom_outer_function_decl_;
489 static tree ffecom_previous_function_decl_;
490 static tree ffecom_which_entrypoint_decl_;
491 static tree ffecom_float_zero_ = NULL_TREE;
492 static tree ffecom_float_half_ = NULL_TREE;
493 static tree ffecom_double_zero_ = NULL_TREE;
494 static tree ffecom_double_half_ = NULL_TREE;
495 static tree ffecom_func_result_;/* For functions. */
496 static tree ffecom_func_length_;/* For CHARACTER fns. */
497 static ffebld ffecom_list_blockdata_;
498 static ffebld ffecom_list_common_;
499 static ffebld ffecom_master_arglist_;
500 static ffeinfoBasictype ffecom_master_bt_;
501 static ffeinfoKindtype ffecom_master_kt_;
502 static ffetargetCharacterSize ffecom_master_size_;
503 static int ffecom_num_fns_ = 0;
504 static int ffecom_num_entrypoints_ = 0;
505 static bool ffecom_is_altreturning_ = FALSE;
506 static tree ffecom_multi_type_node_;
507 static tree ffecom_multi_retval_;
508 static tree
509 ffecom_multi_fields_[FFEINFO_basictype][FFEINFO_kindtype];
510 static bool ffecom_member_namelisted_; /* _member_phase1_ namelisted? */
511 static bool ffecom_doing_entry_ = FALSE;
512 static bool ffecom_transform_only_dummies_ = FALSE;
513 static int ffecom_typesize_pointer_;
514 static int ffecom_typesize_integer1_;
515
516 /* Holds pointer-to-function expressions. */
517
518 static tree ffecom_gfrt_[FFECOM_gfrt]
519 =
520 {
521 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) NULL_TREE,
522 #include "com-rt.def"
523 #undef DEFGFRT
524 };
525
526 /* Holds the external names of the functions. */
527
528 static const char *ffecom_gfrt_name_[FFECOM_gfrt]
529 =
530 {
531 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) NAME,
532 #include "com-rt.def"
533 #undef DEFGFRT
534 };
535
536 /* Whether the function returns. */
537
538 static bool ffecom_gfrt_volatile_[FFECOM_gfrt]
539 =
540 {
541 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) VOLATILE,
542 #include "com-rt.def"
543 #undef DEFGFRT
544 };
545
546 /* Whether the function returns type complex. */
547
548 static bool ffecom_gfrt_complex_[FFECOM_gfrt]
549 =
550 {
551 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) COMPLEX,
552 #include "com-rt.def"
553 #undef DEFGFRT
554 };
555
556 /* Type code for the function return value. */
557
558 static ffecomRttype_ ffecom_gfrt_type_[FFECOM_gfrt]
559 =
560 {
561 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) TYPE,
562 #include "com-rt.def"
563 #undef DEFGFRT
564 };
565
566 /* String of codes for the function's arguments. */
567
568 static const char *ffecom_gfrt_argstring_[FFECOM_gfrt]
569 =
570 {
571 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) ARGS,
572 #include "com-rt.def"
573 #undef DEFGFRT
574 };
575 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
576
577 /* Internal macros. */
578
579 #if FFECOM_targetCURRENT == FFECOM_targetGCC
580
581 /* We let tm.h override the types used here, to handle trivial differences
582 such as the choice of unsigned int or long unsigned int for size_t.
583 When machines start needing nontrivial differences in the size type,
584 it would be best to do something here to figure out automatically
585 from other information what type to use. */
586
587 #ifndef SIZE_TYPE
588 #define SIZE_TYPE "long unsigned int"
589 #endif
590
591 #define ffecom_concat_list_count_(catlist) ((catlist).count)
592 #define ffecom_concat_list_expr_(catlist,i) ((catlist).exprs[(i)])
593 #define ffecom_concat_list_maxlen_(catlist) ((catlist).maxlen)
594 #define ffecom_concat_list_minlen_(catlist) ((catlist).minlen)
595
596 #define ffecom_char_args_(i,l,e) ffecom_char_args_x_((i),(l),(e),FALSE)
597 #define ffecom_char_args_with_null_(i,l,e) ffecom_char_args_x_((i),(l),(e),TRUE)
598
599 /* For each binding contour we allocate a binding_level structure
600 * which records the names defined in that contour.
601 * Contours include:
602 * 0) the global one
603 * 1) one for each function definition,
604 * where internal declarations of the parameters appear.
605 *
606 * The current meaning of a name can be found by searching the levels from
607 * the current one out to the global one.
608 */
609
610 /* Note that the information in the `names' component of the global contour
611 is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
612
613 struct binding_level
614 {
615 /* A chain of _DECL nodes for all variables, constants, functions,
616 and typedef types. These are in the reverse of the order supplied.
617 */
618 tree names;
619
620 /* For each level (except not the global one),
621 a chain of BLOCK nodes for all the levels
622 that were entered and exited one level down. */
623 tree blocks;
624
625 /* The BLOCK node for this level, if one has been preallocated.
626 If 0, the BLOCK is allocated (if needed) when the level is popped. */
627 tree this_block;
628
629 /* The binding level which this one is contained in (inherits from). */
630 struct binding_level *level_chain;
631
632 /* 0: no ffecom_prepare_* functions called at this level yet;
633 1: ffecom_prepare* functions called, except not ffecom_prepare_end;
634 2: ffecom_prepare_end called. */
635 int prep_state;
636 };
637
638 #define NULL_BINDING_LEVEL (struct binding_level *) NULL
639
640 /* The binding level currently in effect. */
641
642 static struct binding_level *current_binding_level;
643
644 /* A chain of binding_level structures awaiting reuse. */
645
646 static struct binding_level *free_binding_level;
647
648 /* The outermost binding level, for names of file scope.
649 This is created when the compiler is started and exists
650 through the entire run. */
651
652 static struct binding_level *global_binding_level;
653
654 /* Binding level structures are initialized by copying this one. */
655
656 static struct binding_level clear_binding_level
657 =
658 {NULL, NULL, NULL, NULL_BINDING_LEVEL, 0};
659
660 /* Language-dependent contents of an identifier. */
661
662 struct lang_identifier
663 {
664 struct tree_identifier ignore;
665 tree global_value, local_value, label_value;
666 bool invented;
667 };
668
669 /* Macros for access to language-specific slots in an identifier. */
670 /* Each of these slots contains a DECL node or null. */
671
672 /* This represents the value which the identifier has in the
673 file-scope namespace. */
674 #define IDENTIFIER_GLOBAL_VALUE(NODE) \
675 (((struct lang_identifier *)(NODE))->global_value)
676 /* This represents the value which the identifier has in the current
677 scope. */
678 #define IDENTIFIER_LOCAL_VALUE(NODE) \
679 (((struct lang_identifier *)(NODE))->local_value)
680 /* This represents the value which the identifier has as a label in
681 the current label scope. */
682 #define IDENTIFIER_LABEL_VALUE(NODE) \
683 (((struct lang_identifier *)(NODE))->label_value)
684 /* This is nonzero if the identifier was "made up" by g77 code. */
685 #define IDENTIFIER_INVENTED(NODE) \
686 (((struct lang_identifier *)(NODE))->invented)
687
688 /* In identifiers, C uses the following fields in a special way:
689 TREE_PUBLIC to record that there was a previous local extern decl.
690 TREE_USED to record that such a decl was used.
691 TREE_ADDRESSABLE to record that the address of such a decl was used. */
692
693 /* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
694 that have names. Here so we can clear out their names' definitions
695 at the end of the function. */
696
697 static tree named_labels;
698
699 /* A list of LABEL_DECLs from outer contexts that are currently shadowed. */
700
701 static tree shadowed_labels;
702
703 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
704 \f
705 /* Return the subscript expression, modified to do range-checking.
706
707 `array' is the array to be checked against.
708 `element' is the subscript expression to check.
709 `dim' is the dimension number (starting at 0).
710 `total_dims' is the total number of dimensions (0 for CHARACTER substring).
711 */
712
713 static tree
714 ffecom_subscript_check_ (tree array, tree element, int dim, int total_dims,
715 const char *array_name)
716 {
717 tree low = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
718 tree high = TYPE_MAX_VALUE (TYPE_DOMAIN (array));
719 tree cond;
720 tree die;
721 tree args;
722
723 if (element == error_mark_node)
724 return element;
725
726 if (TREE_TYPE (low) != TREE_TYPE (element))
727 {
728 if (TYPE_PRECISION (TREE_TYPE (low))
729 > TYPE_PRECISION (TREE_TYPE (element)))
730 element = convert (TREE_TYPE (low), element);
731 else
732 {
733 low = convert (TREE_TYPE (element), low);
734 if (high)
735 high = convert (TREE_TYPE (element), high);
736 }
737 }
738
739 element = ffecom_save_tree (element);
740 cond = ffecom_2 (LE_EXPR, integer_type_node,
741 low,
742 element);
743 if (high)
744 {
745 cond = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
746 cond,
747 ffecom_2 (LE_EXPR, integer_type_node,
748 element,
749 high));
750 }
751
752 {
753 int len;
754 char *proc;
755 char *var;
756 tree arg3;
757 tree arg2;
758 tree arg1;
759 tree arg4;
760
761 switch (total_dims)
762 {
763 case 0:
764 var = xmalloc (strlen (array_name) + 20);
765 sprintf (var, "%s[%s-substring]",
766 array_name,
767 dim ? "end" : "start");
768 len = strlen (var) + 1;
769 arg1 = build_string (len, var);
770 free (var);
771 break;
772
773 case 1:
774 len = strlen (array_name) + 1;
775 arg1 = build_string (len, array_name);
776 break;
777
778 default:
779 var = xmalloc (strlen (array_name) + 40);
780 sprintf (var, "%s[subscript-%d-of-%d]",
781 array_name,
782 dim + 1, total_dims);
783 len = strlen (var) + 1;
784 arg1 = build_string (len, var);
785 free (var);
786 break;
787 }
788
789 TREE_TYPE (arg1)
790 = build_type_variant (build_array_type (char_type_node,
791 build_range_type
792 (integer_type_node,
793 integer_one_node,
794 build_int_2 (len, 0))),
795 1, 0);
796 TREE_CONSTANT (arg1) = 1;
797 TREE_STATIC (arg1) = 1;
798 arg1 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg1)),
799 arg1);
800
801 /* s_rnge adds one to the element to print it, so bias against
802 that -- want to print a faithful *subscript* value. */
803 arg2 = convert (ffecom_f2c_ftnint_type_node,
804 ffecom_2 (MINUS_EXPR,
805 TREE_TYPE (element),
806 element,
807 convert (TREE_TYPE (element),
808 integer_one_node)));
809
810 proc = xmalloc ((len = strlen (input_filename)
811 + IDENTIFIER_LENGTH (DECL_NAME (current_function_decl))
812 + 2));
813
814 sprintf (&proc[0], "%s/%s",
815 input_filename,
816 IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
817 arg3 = build_string (len, proc);
818
819 free (proc);
820
821 TREE_TYPE (arg3)
822 = build_type_variant (build_array_type (char_type_node,
823 build_range_type
824 (integer_type_node,
825 integer_one_node,
826 build_int_2 (len, 0))),
827 1, 0);
828 TREE_CONSTANT (arg3) = 1;
829 TREE_STATIC (arg3) = 1;
830 arg3 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg3)),
831 arg3);
832
833 arg4 = convert (ffecom_f2c_ftnint_type_node,
834 build_int_2 (lineno, 0));
835
836 arg1 = build_tree_list (NULL_TREE, arg1);
837 arg2 = build_tree_list (NULL_TREE, arg2);
838 arg3 = build_tree_list (NULL_TREE, arg3);
839 arg4 = build_tree_list (NULL_TREE, arg4);
840 TREE_CHAIN (arg3) = arg4;
841 TREE_CHAIN (arg2) = arg3;
842 TREE_CHAIN (arg1) = arg2;
843
844 args = arg1;
845 }
846 die = ffecom_call_gfrt (FFECOM_gfrtRANGE,
847 args, NULL_TREE);
848 TREE_SIDE_EFFECTS (die) = 1;
849
850 element = ffecom_3 (COND_EXPR,
851 TREE_TYPE (element),
852 cond,
853 element,
854 die);
855
856 return element;
857 }
858
859 /* Return the computed element of an array reference.
860
861 `item' is NULL_TREE, or the transformed pointer to the array.
862 `expr' is the original opARRAYREF expression, which is transformed
863 if `item' is NULL_TREE.
864 `want_ptr' is non-zero if a pointer to the element, instead of
865 the element itself, is to be returned. */
866
867 static tree
868 ffecom_arrayref_ (tree item, ffebld expr, int want_ptr)
869 {
870 ffebld dims[FFECOM_dimensionsMAX];
871 int i;
872 int total_dims;
873 int flatten = ffe_is_flatten_arrays ();
874 int need_ptr;
875 tree array;
876 tree element;
877 tree tree_type;
878 tree tree_type_x;
879 const char *array_name;
880 ffetype type;
881 ffebld list;
882
883 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER)
884 array_name = ffesymbol_text (ffebld_symter (ffebld_left (expr)));
885 else
886 array_name = "[expr?]";
887
888 /* Build up ARRAY_REFs in reverse order (since we're column major
889 here in Fortran land). */
890
891 for (i = 0, list = ffebld_right (expr);
892 list != NULL;
893 ++i, list = ffebld_trail (list))
894 {
895 dims[i] = ffebld_head (list);
896 type = ffeinfo_type (ffebld_basictype (dims[i]),
897 ffebld_kindtype (dims[i]));
898 if (! flatten
899 && ffecom_typesize_pointer_ > ffecom_typesize_integer1_
900 && ffetype_size (type) > ffecom_typesize_integer1_)
901 /* E.g. ARRAY(INDEX), given INTEGER*8 INDEX, on a system with 64-bit
902 pointers and 32-bit integers. Do the full 64-bit pointer
903 arithmetic, for codes using arrays for nonstandard heap-like
904 work. */
905 flatten = 1;
906 }
907
908 total_dims = i;
909
910 need_ptr = want_ptr || flatten;
911
912 if (! item)
913 {
914 if (need_ptr)
915 item = ffecom_ptr_to_expr (ffebld_left (expr));
916 else
917 item = ffecom_expr (ffebld_left (expr));
918
919 if (item == error_mark_node)
920 return item;
921
922 if (ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereFLEETING
923 && ! mark_addressable (item))
924 return error_mark_node;
925 }
926
927 if (item == error_mark_node)
928 return item;
929
930 if (need_ptr)
931 {
932 tree min;
933
934 for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
935 i >= 0;
936 --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
937 {
938 min = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
939 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
940 if (flag_bounds_check)
941 element = ffecom_subscript_check_ (array, element, i, total_dims,
942 array_name);
943 if (element == error_mark_node)
944 return element;
945
946 /* Widen integral arithmetic as desired while preserving
947 signedness. */
948 tree_type = TREE_TYPE (element);
949 tree_type_x = tree_type;
950 if (tree_type
951 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
952 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
953 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
954
955 if (TREE_TYPE (min) != tree_type_x)
956 min = convert (tree_type_x, min);
957 if (TREE_TYPE (element) != tree_type_x)
958 element = convert (tree_type_x, element);
959
960 item = ffecom_2 (PLUS_EXPR,
961 build_pointer_type (TREE_TYPE (array)),
962 item,
963 size_binop (MULT_EXPR,
964 size_in_bytes (TREE_TYPE (array)),
965 convert (sizetype,
966 fold (build (MINUS_EXPR,
967 tree_type_x,
968 element, min)))));
969 }
970 if (! want_ptr)
971 {
972 item = ffecom_1 (INDIRECT_REF,
973 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
974 item);
975 }
976 }
977 else
978 {
979 for (--i;
980 i >= 0;
981 --i)
982 {
983 array = TYPE_MAIN_VARIANT (TREE_TYPE (item));
984
985 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
986 if (flag_bounds_check)
987 element = ffecom_subscript_check_ (array, element, i, total_dims,
988 array_name);
989 if (element == error_mark_node)
990 return element;
991
992 /* Widen integral arithmetic as desired while preserving
993 signedness. */
994 tree_type = TREE_TYPE (element);
995 tree_type_x = tree_type;
996 if (tree_type
997 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
998 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
999 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
1000
1001 element = convert (tree_type_x, element);
1002
1003 item = ffecom_2 (ARRAY_REF,
1004 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
1005 item,
1006 element);
1007 }
1008 }
1009
1010 return item;
1011 }
1012
1013 /* This is like gcc's stabilize_reference -- in fact, most of the code
1014 comes from that -- but it handles the situation where the reference
1015 is going to have its subparts picked at, and it shouldn't change
1016 (or trigger extra invocations of functions in the subtrees) due to
1017 this. save_expr is a bit overzealous, because we don't need the
1018 entire thing calculated and saved like a temp. So, for DECLs, no
1019 change is needed, because these are stable aggregates, and ARRAY_REF
1020 and such might well be stable too, but for things like calculations,
1021 we do need to calculate a snapshot of a value before picking at it. */
1022
1023 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1024 static tree
1025 ffecom_stabilize_aggregate_ (tree ref)
1026 {
1027 tree result;
1028 enum tree_code code = TREE_CODE (ref);
1029
1030 switch (code)
1031 {
1032 case VAR_DECL:
1033 case PARM_DECL:
1034 case RESULT_DECL:
1035 /* No action is needed in this case. */
1036 return ref;
1037
1038 case NOP_EXPR:
1039 case CONVERT_EXPR:
1040 case FLOAT_EXPR:
1041 case FIX_TRUNC_EXPR:
1042 case FIX_FLOOR_EXPR:
1043 case FIX_ROUND_EXPR:
1044 case FIX_CEIL_EXPR:
1045 result = build_nt (code, stabilize_reference (TREE_OPERAND (ref, 0)));
1046 break;
1047
1048 case INDIRECT_REF:
1049 result = build_nt (INDIRECT_REF,
1050 stabilize_reference_1 (TREE_OPERAND (ref, 0)));
1051 break;
1052
1053 case COMPONENT_REF:
1054 result = build_nt (COMPONENT_REF,
1055 stabilize_reference (TREE_OPERAND (ref, 0)),
1056 TREE_OPERAND (ref, 1));
1057 break;
1058
1059 case BIT_FIELD_REF:
1060 result = build_nt (BIT_FIELD_REF,
1061 stabilize_reference (TREE_OPERAND (ref, 0)),
1062 stabilize_reference_1 (TREE_OPERAND (ref, 1)),
1063 stabilize_reference_1 (TREE_OPERAND (ref, 2)));
1064 break;
1065
1066 case ARRAY_REF:
1067 result = build_nt (ARRAY_REF,
1068 stabilize_reference (TREE_OPERAND (ref, 0)),
1069 stabilize_reference_1 (TREE_OPERAND (ref, 1)));
1070 break;
1071
1072 case COMPOUND_EXPR:
1073 result = build_nt (COMPOUND_EXPR,
1074 stabilize_reference_1 (TREE_OPERAND (ref, 0)),
1075 stabilize_reference (TREE_OPERAND (ref, 1)));
1076 break;
1077
1078 case RTL_EXPR:
1079 result = build1 (INDIRECT_REF, TREE_TYPE (ref),
1080 save_expr (build1 (ADDR_EXPR,
1081 build_pointer_type (TREE_TYPE (ref)),
1082 ref)));
1083 break;
1084
1085
1086 default:
1087 return save_expr (ref);
1088
1089 case ERROR_MARK:
1090 return error_mark_node;
1091 }
1092
1093 TREE_TYPE (result) = TREE_TYPE (ref);
1094 TREE_READONLY (result) = TREE_READONLY (ref);
1095 TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (ref);
1096 TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (ref);
1097
1098 return result;
1099 }
1100 #endif
1101
1102 /* A rip-off of gcc's convert.c convert_to_complex function,
1103 reworked to handle complex implemented as C structures
1104 (RECORD_TYPE with two fields, real and imaginary `r' and `i'). */
1105
1106 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1107 static tree
1108 ffecom_convert_to_complex_ (tree type, tree expr)
1109 {
1110 register enum tree_code form = TREE_CODE (TREE_TYPE (expr));
1111 tree subtype;
1112
1113 assert (TREE_CODE (type) == RECORD_TYPE);
1114
1115 subtype = TREE_TYPE (TYPE_FIELDS (type));
1116
1117 if (form == REAL_TYPE || form == INTEGER_TYPE || form == ENUMERAL_TYPE)
1118 {
1119 expr = convert (subtype, expr);
1120 return ffecom_2 (COMPLEX_EXPR, type, expr,
1121 convert (subtype, integer_zero_node));
1122 }
1123
1124 if (form == RECORD_TYPE)
1125 {
1126 tree elt_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr)));
1127 if (TYPE_MAIN_VARIANT (elt_type) == TYPE_MAIN_VARIANT (subtype))
1128 return expr;
1129 else
1130 {
1131 expr = save_expr (expr);
1132 return ffecom_2 (COMPLEX_EXPR,
1133 type,
1134 convert (subtype,
1135 ffecom_1 (REALPART_EXPR,
1136 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1137 expr)),
1138 convert (subtype,
1139 ffecom_1 (IMAGPART_EXPR,
1140 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1141 expr)));
1142 }
1143 }
1144
1145 if (form == POINTER_TYPE || form == REFERENCE_TYPE)
1146 error ("pointer value used where a complex was expected");
1147 else
1148 error ("aggregate value used where a complex was expected");
1149
1150 return ffecom_2 (COMPLEX_EXPR, type,
1151 convert (subtype, integer_zero_node),
1152 convert (subtype, integer_zero_node));
1153 }
1154 #endif
1155
1156 /* Like gcc's convert(), but crashes if widening might happen. */
1157
1158 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1159 static tree
1160 ffecom_convert_narrow_ (type, expr)
1161 tree type, expr;
1162 {
1163 register tree e = expr;
1164 register enum tree_code code = TREE_CODE (type);
1165
1166 if (type == TREE_TYPE (e)
1167 || TREE_CODE (e) == ERROR_MARK)
1168 return e;
1169 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1170 return fold (build1 (NOP_EXPR, type, e));
1171 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1172 || code == ERROR_MARK)
1173 return error_mark_node;
1174 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1175 {
1176 assert ("void value not ignored as it ought to be" == NULL);
1177 return error_mark_node;
1178 }
1179 assert (code != VOID_TYPE);
1180 if ((code != RECORD_TYPE)
1181 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1182 assert ("converting COMPLEX to REAL" == NULL);
1183 assert (code != ENUMERAL_TYPE);
1184 if (code == INTEGER_TYPE)
1185 {
1186 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1187 && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)))
1188 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1189 && (TYPE_PRECISION (type)
1190 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
1191 return fold (convert_to_integer (type, e));
1192 }
1193 if (code == POINTER_TYPE)
1194 {
1195 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1196 return fold (convert_to_pointer (type, e));
1197 }
1198 if (code == REAL_TYPE)
1199 {
1200 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1201 assert (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)));
1202 return fold (convert_to_real (type, e));
1203 }
1204 if (code == COMPLEX_TYPE)
1205 {
1206 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1207 assert (TYPE_PRECISION (TREE_TYPE (type)) <= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1208 return fold (convert_to_complex (type, e));
1209 }
1210 if (code == RECORD_TYPE)
1211 {
1212 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
1213 /* Check that at least the first field name agrees. */
1214 assert (DECL_NAME (TYPE_FIELDS (type))
1215 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
1216 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1217 <= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
1218 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1219 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1220 return e;
1221 return fold (ffecom_convert_to_complex_ (type, e));
1222 }
1223
1224 assert ("conversion to non-scalar type requested" == NULL);
1225 return error_mark_node;
1226 }
1227 #endif
1228
1229 /* Like gcc's convert(), but crashes if narrowing might happen. */
1230
1231 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1232 static tree
1233 ffecom_convert_widen_ (type, expr)
1234 tree type, expr;
1235 {
1236 register tree e = expr;
1237 register enum tree_code code = TREE_CODE (type);
1238
1239 if (type == TREE_TYPE (e)
1240 || TREE_CODE (e) == ERROR_MARK)
1241 return e;
1242 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1243 return fold (build1 (NOP_EXPR, type, e));
1244 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1245 || code == ERROR_MARK)
1246 return error_mark_node;
1247 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1248 {
1249 assert ("void value not ignored as it ought to be" == NULL);
1250 return error_mark_node;
1251 }
1252 assert (code != VOID_TYPE);
1253 if ((code != RECORD_TYPE)
1254 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1255 assert ("narrowing COMPLEX to REAL" == NULL);
1256 assert (code != ENUMERAL_TYPE);
1257 if (code == INTEGER_TYPE)
1258 {
1259 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1260 && TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)))
1261 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1262 && (TYPE_PRECISION (type)
1263 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
1264 return fold (convert_to_integer (type, e));
1265 }
1266 if (code == POINTER_TYPE)
1267 {
1268 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1269 return fold (convert_to_pointer (type, e));
1270 }
1271 if (code == REAL_TYPE)
1272 {
1273 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1274 assert (TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)));
1275 return fold (convert_to_real (type, e));
1276 }
1277 if (code == COMPLEX_TYPE)
1278 {
1279 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1280 assert (TYPE_PRECISION (TREE_TYPE (type)) >= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1281 return fold (convert_to_complex (type, e));
1282 }
1283 if (code == RECORD_TYPE)
1284 {
1285 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
1286 /* Check that at least the first field name agrees. */
1287 assert (DECL_NAME (TYPE_FIELDS (type))
1288 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
1289 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1290 >= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
1291 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1292 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1293 return e;
1294 return fold (ffecom_convert_to_complex_ (type, e));
1295 }
1296
1297 assert ("conversion to non-scalar type requested" == NULL);
1298 return error_mark_node;
1299 }
1300 #endif
1301
1302 /* Handles making a COMPLEX type, either the standard
1303 (but buggy?) gbe way, or the safer (but less elegant?)
1304 f2c way. */
1305
1306 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1307 static tree
1308 ffecom_make_complex_type_ (tree subtype)
1309 {
1310 tree type;
1311 tree realfield;
1312 tree imagfield;
1313
1314 if (ffe_is_emulate_complex ())
1315 {
1316 type = make_node (RECORD_TYPE);
1317 realfield = ffecom_decl_field (type, NULL_TREE, "r", subtype);
1318 imagfield = ffecom_decl_field (type, realfield, "i", subtype);
1319 TYPE_FIELDS (type) = realfield;
1320 layout_type (type);
1321 }
1322 else
1323 {
1324 type = make_node (COMPLEX_TYPE);
1325 TREE_TYPE (type) = subtype;
1326 layout_type (type);
1327 }
1328
1329 return type;
1330 }
1331 #endif
1332
1333 /* Chooses either the gbe or the f2c way to build a
1334 complex constant. */
1335
1336 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1337 static tree
1338 ffecom_build_complex_constant_ (tree type, tree realpart, tree imagpart)
1339 {
1340 tree bothparts;
1341
1342 if (ffe_is_emulate_complex ())
1343 {
1344 bothparts = build_tree_list (TYPE_FIELDS (type), realpart);
1345 TREE_CHAIN (bothparts) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), imagpart);
1346 bothparts = build (CONSTRUCTOR, type, NULL_TREE, bothparts);
1347 }
1348 else
1349 {
1350 bothparts = build_complex (type, realpart, imagpart);
1351 }
1352
1353 return bothparts;
1354 }
1355 #endif
1356
1357 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1358 static tree
1359 ffecom_arglist_expr_ (const char *c, ffebld expr)
1360 {
1361 tree list;
1362 tree *plist = &list;
1363 tree trail = NULL_TREE; /* Append char length args here. */
1364 tree *ptrail = &trail;
1365 tree length;
1366 ffebld exprh;
1367 tree item;
1368 bool ptr = FALSE;
1369 tree wanted = NULL_TREE;
1370 static char zed[] = "0";
1371
1372 if (c == NULL)
1373 c = &zed[0];
1374
1375 while (expr != NULL)
1376 {
1377 if (*c != '\0')
1378 {
1379 ptr = FALSE;
1380 if (*c == '&')
1381 {
1382 ptr = TRUE;
1383 ++c;
1384 }
1385 switch (*(c++))
1386 {
1387 case '\0':
1388 ptr = TRUE;
1389 wanted = NULL_TREE;
1390 break;
1391
1392 case 'a':
1393 assert (ptr);
1394 wanted = NULL_TREE;
1395 break;
1396
1397 case 'c':
1398 wanted = ffecom_f2c_complex_type_node;
1399 break;
1400
1401 case 'd':
1402 wanted = ffecom_f2c_doublereal_type_node;
1403 break;
1404
1405 case 'e':
1406 wanted = ffecom_f2c_doublecomplex_type_node;
1407 break;
1408
1409 case 'f':
1410 wanted = ffecom_f2c_real_type_node;
1411 break;
1412
1413 case 'i':
1414 wanted = ffecom_f2c_integer_type_node;
1415 break;
1416
1417 case 'j':
1418 wanted = ffecom_f2c_longint_type_node;
1419 break;
1420
1421 default:
1422 assert ("bad argstring code" == NULL);
1423 wanted = NULL_TREE;
1424 break;
1425 }
1426 }
1427
1428 exprh = ffebld_head (expr);
1429 if (exprh == NULL)
1430 wanted = NULL_TREE;
1431
1432 if ((wanted == NULL_TREE)
1433 || (ptr
1434 && (TYPE_MODE
1435 (ffecom_tree_type[ffeinfo_basictype (ffebld_info (exprh))]
1436 [ffeinfo_kindtype (ffebld_info (exprh))])
1437 == TYPE_MODE (wanted))))
1438 *plist
1439 = build_tree_list (NULL_TREE,
1440 ffecom_arg_ptr_to_expr (exprh,
1441 &length));
1442 else
1443 {
1444 item = ffecom_arg_expr (exprh, &length);
1445 item = ffecom_convert_widen_ (wanted, item);
1446 if (ptr)
1447 {
1448 item = ffecom_1 (ADDR_EXPR,
1449 build_pointer_type (TREE_TYPE (item)),
1450 item);
1451 }
1452 *plist
1453 = build_tree_list (NULL_TREE,
1454 item);
1455 }
1456
1457 plist = &TREE_CHAIN (*plist);
1458 expr = ffebld_trail (expr);
1459 if (length != NULL_TREE)
1460 {
1461 *ptrail = build_tree_list (NULL_TREE, length);
1462 ptrail = &TREE_CHAIN (*ptrail);
1463 }
1464 }
1465
1466 /* We've run out of args in the call; if the implementation expects
1467 more, supply null pointers for them, which the implementation can
1468 check to see if an arg was omitted. */
1469
1470 while (*c != '\0' && *c != '0')
1471 {
1472 if (*c == '&')
1473 ++c;
1474 else
1475 assert ("missing arg to run-time routine!" == NULL);
1476
1477 switch (*(c++))
1478 {
1479 case '\0':
1480 case 'a':
1481 case 'c':
1482 case 'd':
1483 case 'e':
1484 case 'f':
1485 case 'i':
1486 case 'j':
1487 break;
1488
1489 default:
1490 assert ("bad arg string code" == NULL);
1491 break;
1492 }
1493 *plist
1494 = build_tree_list (NULL_TREE,
1495 null_pointer_node);
1496 plist = &TREE_CHAIN (*plist);
1497 }
1498
1499 *plist = trail;
1500
1501 return list;
1502 }
1503 #endif
1504
1505 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1506 static tree
1507 ffecom_widest_expr_type_ (ffebld list)
1508 {
1509 ffebld item;
1510 ffebld widest = NULL;
1511 ffetype type;
1512 ffetype widest_type = NULL;
1513 tree t;
1514
1515 for (; list != NULL; list = ffebld_trail (list))
1516 {
1517 item = ffebld_head (list);
1518 if (item == NULL)
1519 continue;
1520 if ((widest != NULL)
1521 && (ffeinfo_basictype (ffebld_info (item))
1522 != ffeinfo_basictype (ffebld_info (widest))))
1523 continue;
1524 type = ffeinfo_type (ffeinfo_basictype (ffebld_info (item)),
1525 ffeinfo_kindtype (ffebld_info (item)));
1526 if ((widest == FFEINFO_kindtypeNONE)
1527 || (ffetype_size (type)
1528 > ffetype_size (widest_type)))
1529 {
1530 widest = item;
1531 widest_type = type;
1532 }
1533 }
1534
1535 assert (widest != NULL);
1536 t = ffecom_tree_type[ffeinfo_basictype (ffebld_info (widest))]
1537 [ffeinfo_kindtype (ffebld_info (widest))];
1538 assert (t != NULL_TREE);
1539 return t;
1540 }
1541 #endif
1542
1543 /* Check whether a partial overlap between two expressions is possible.
1544
1545 Can *starting* to write a portion of expr1 change the value
1546 computed (perhaps already, *partially*) by expr2?
1547
1548 Currently, this is a concern only for a COMPLEX expr1. But if it
1549 isn't in COMMON or local EQUIVALENCE, since we don't support
1550 aliasing of arguments, it isn't a concern. */
1551
1552 static bool
1553 ffecom_possible_partial_overlap_ (ffebld expr1, ffebld expr2 ATTRIBUTE_UNUSED)
1554 {
1555 ffesymbol sym;
1556 ffestorag st;
1557
1558 switch (ffebld_op (expr1))
1559 {
1560 case FFEBLD_opSYMTER:
1561 sym = ffebld_symter (expr1);
1562 break;
1563
1564 case FFEBLD_opARRAYREF:
1565 if (ffebld_op (ffebld_left (expr1)) != FFEBLD_opSYMTER)
1566 return FALSE;
1567 sym = ffebld_symter (ffebld_left (expr1));
1568 break;
1569
1570 default:
1571 return FALSE;
1572 }
1573
1574 if (ffesymbol_where (sym) != FFEINFO_whereCOMMON
1575 && (ffesymbol_where (sym) != FFEINFO_whereLOCAL
1576 || ! (st = ffesymbol_storage (sym))
1577 || ! ffestorag_parent (st)))
1578 return FALSE;
1579
1580 /* It's in COMMON or local EQUIVALENCE. */
1581
1582 return TRUE;
1583 }
1584
1585 /* Check whether dest and source might overlap. ffebld versions of these
1586 might or might not be passed, will be NULL if not.
1587
1588 The test is really whether source_tree is modifiable and, if modified,
1589 might overlap destination such that the value(s) in the destination might
1590 change before it is finally modified. dest_* are the canonized
1591 destination itself. */
1592
1593 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1594 static bool
1595 ffecom_overlap_ (tree dest_decl, tree dest_offset, tree dest_size,
1596 tree source_tree, ffebld source UNUSED,
1597 bool scalar_arg)
1598 {
1599 tree source_decl;
1600 tree source_offset;
1601 tree source_size;
1602 tree t;
1603
1604 if (source_tree == NULL_TREE)
1605 return FALSE;
1606
1607 switch (TREE_CODE (source_tree))
1608 {
1609 case ERROR_MARK:
1610 case IDENTIFIER_NODE:
1611 case INTEGER_CST:
1612 case REAL_CST:
1613 case COMPLEX_CST:
1614 case STRING_CST:
1615 case CONST_DECL:
1616 case VAR_DECL:
1617 case RESULT_DECL:
1618 case FIELD_DECL:
1619 case MINUS_EXPR:
1620 case MULT_EXPR:
1621 case TRUNC_DIV_EXPR:
1622 case CEIL_DIV_EXPR:
1623 case FLOOR_DIV_EXPR:
1624 case ROUND_DIV_EXPR:
1625 case TRUNC_MOD_EXPR:
1626 case CEIL_MOD_EXPR:
1627 case FLOOR_MOD_EXPR:
1628 case ROUND_MOD_EXPR:
1629 case RDIV_EXPR:
1630 case EXACT_DIV_EXPR:
1631 case FIX_TRUNC_EXPR:
1632 case FIX_CEIL_EXPR:
1633 case FIX_FLOOR_EXPR:
1634 case FIX_ROUND_EXPR:
1635 case FLOAT_EXPR:
1636 case EXPON_EXPR:
1637 case NEGATE_EXPR:
1638 case MIN_EXPR:
1639 case MAX_EXPR:
1640 case ABS_EXPR:
1641 case FFS_EXPR:
1642 case LSHIFT_EXPR:
1643 case RSHIFT_EXPR:
1644 case LROTATE_EXPR:
1645 case RROTATE_EXPR:
1646 case BIT_IOR_EXPR:
1647 case BIT_XOR_EXPR:
1648 case BIT_AND_EXPR:
1649 case BIT_ANDTC_EXPR:
1650 case BIT_NOT_EXPR:
1651 case TRUTH_ANDIF_EXPR:
1652 case TRUTH_ORIF_EXPR:
1653 case TRUTH_AND_EXPR:
1654 case TRUTH_OR_EXPR:
1655 case TRUTH_XOR_EXPR:
1656 case TRUTH_NOT_EXPR:
1657 case LT_EXPR:
1658 case LE_EXPR:
1659 case GT_EXPR:
1660 case GE_EXPR:
1661 case EQ_EXPR:
1662 case NE_EXPR:
1663 case COMPLEX_EXPR:
1664 case CONJ_EXPR:
1665 case REALPART_EXPR:
1666 case IMAGPART_EXPR:
1667 case LABEL_EXPR:
1668 case COMPONENT_REF:
1669 return FALSE;
1670
1671 case COMPOUND_EXPR:
1672 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1673 TREE_OPERAND (source_tree, 1), NULL,
1674 scalar_arg);
1675
1676 case MODIFY_EXPR:
1677 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1678 TREE_OPERAND (source_tree, 0), NULL,
1679 scalar_arg);
1680
1681 case CONVERT_EXPR:
1682 case NOP_EXPR:
1683 case NON_LVALUE_EXPR:
1684 case PLUS_EXPR:
1685 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1686 return TRUE;
1687
1688 ffecom_tree_canonize_ptr_ (&source_decl, &source_offset,
1689 source_tree);
1690 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1691 break;
1692
1693 case COND_EXPR:
1694 return
1695 ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1696 TREE_OPERAND (source_tree, 1), NULL,
1697 scalar_arg)
1698 || ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1699 TREE_OPERAND (source_tree, 2), NULL,
1700 scalar_arg);
1701
1702
1703 case ADDR_EXPR:
1704 ffecom_tree_canonize_ref_ (&source_decl, &source_offset,
1705 &source_size,
1706 TREE_OPERAND (source_tree, 0));
1707 break;
1708
1709 case PARM_DECL:
1710 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1711 return TRUE;
1712
1713 source_decl = source_tree;
1714 source_offset = bitsize_zero_node;
1715 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1716 break;
1717
1718 case SAVE_EXPR:
1719 case REFERENCE_EXPR:
1720 case PREDECREMENT_EXPR:
1721 case PREINCREMENT_EXPR:
1722 case POSTDECREMENT_EXPR:
1723 case POSTINCREMENT_EXPR:
1724 case INDIRECT_REF:
1725 case ARRAY_REF:
1726 case CALL_EXPR:
1727 default:
1728 return TRUE;
1729 }
1730
1731 /* Come here when source_decl, source_offset, and source_size filled
1732 in appropriately. */
1733
1734 if (source_decl == NULL_TREE)
1735 return FALSE; /* No decl involved, so no overlap. */
1736
1737 if (source_decl != dest_decl)
1738 return FALSE; /* Different decl, no overlap. */
1739
1740 if (TREE_CODE (dest_size) == ERROR_MARK)
1741 return TRUE; /* Assignment into entire assumed-size
1742 array? Shouldn't happen.... */
1743
1744 t = ffecom_2 (LE_EXPR, integer_type_node,
1745 ffecom_2 (PLUS_EXPR, TREE_TYPE (dest_offset),
1746 dest_offset,
1747 convert (TREE_TYPE (dest_offset),
1748 dest_size)),
1749 convert (TREE_TYPE (dest_offset),
1750 source_offset));
1751
1752 if (integer_onep (t))
1753 return FALSE; /* Destination precedes source. */
1754
1755 if (!scalar_arg
1756 || (source_size == NULL_TREE)
1757 || (TREE_CODE (source_size) == ERROR_MARK)
1758 || integer_zerop (source_size))
1759 return TRUE; /* No way to tell if dest follows source. */
1760
1761 t = ffecom_2 (LE_EXPR, integer_type_node,
1762 ffecom_2 (PLUS_EXPR, TREE_TYPE (source_offset),
1763 source_offset,
1764 convert (TREE_TYPE (source_offset),
1765 source_size)),
1766 convert (TREE_TYPE (source_offset),
1767 dest_offset));
1768
1769 if (integer_onep (t))
1770 return FALSE; /* Destination follows source. */
1771
1772 return TRUE; /* Destination and source overlap. */
1773 }
1774 #endif
1775
1776 /* Check whether dest might overlap any of a list of arguments or is
1777 in a COMMON area the callee might know about (and thus modify). */
1778
1779 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1780 static bool
1781 ffecom_args_overlapping_ (tree dest_tree, ffebld dest UNUSED,
1782 tree args, tree callee_commons,
1783 bool scalar_args)
1784 {
1785 tree arg;
1786 tree dest_decl;
1787 tree dest_offset;
1788 tree dest_size;
1789
1790 ffecom_tree_canonize_ref_ (&dest_decl, &dest_offset, &dest_size,
1791 dest_tree);
1792
1793 if (dest_decl == NULL_TREE)
1794 return FALSE; /* Seems unlikely! */
1795
1796 /* If the decl cannot be determined reliably, or if its in COMMON
1797 and the callee isn't known to not futz with COMMON via other
1798 means, overlap might happen. */
1799
1800 if ((TREE_CODE (dest_decl) == ERROR_MARK)
1801 || ((callee_commons != NULL_TREE)
1802 && TREE_PUBLIC (dest_decl)))
1803 return TRUE;
1804
1805 for (; args != NULL_TREE; args = TREE_CHAIN (args))
1806 {
1807 if (((arg = TREE_VALUE (args)) != NULL_TREE)
1808 && ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1809 arg, NULL, scalar_args))
1810 return TRUE;
1811 }
1812
1813 return FALSE;
1814 }
1815 #endif
1816
1817 /* Build a string for a variable name as used by NAMELIST. This means that
1818 if we're using the f2c library, we build an uppercase string, since
1819 f2c does this. */
1820
1821 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1822 static tree
1823 ffecom_build_f2c_string_ (int i, const char *s)
1824 {
1825 if (!ffe_is_f2c_library ())
1826 return build_string (i, s);
1827
1828 {
1829 char *tmp;
1830 const char *p;
1831 char *q;
1832 char space[34];
1833 tree t;
1834
1835 if (((size_t) i) > ARRAY_SIZE (space))
1836 tmp = malloc_new_ks (malloc_pool_image (), "f2c_string", i);
1837 else
1838 tmp = &space[0];
1839
1840 for (p = s, q = tmp; *p != '\0'; ++p, ++q)
1841 *q = ffesrc_toupper (*p);
1842 *q = '\0';
1843
1844 t = build_string (i, tmp);
1845
1846 if (((size_t) i) > ARRAY_SIZE (space))
1847 malloc_kill_ks (malloc_pool_image (), tmp, i);
1848
1849 return t;
1850 }
1851 }
1852
1853 #endif
1854 /* Returns CALL_EXPR or equivalent with given type (pass NULL_TREE for
1855 type to just get whatever the function returns), handling the
1856 f2c value-returning convention, if required, by prepending
1857 to the arglist a pointer to a temporary to receive the return value. */
1858
1859 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1860 static tree
1861 ffecom_call_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1862 tree type, tree args, tree dest_tree,
1863 ffebld dest, bool *dest_used, tree callee_commons,
1864 bool scalar_args, tree hook)
1865 {
1866 tree item;
1867 tree tempvar;
1868
1869 if (dest_used != NULL)
1870 *dest_used = FALSE;
1871
1872 if (is_f2c_complex)
1873 {
1874 if ((dest_used == NULL)
1875 || (dest == NULL)
1876 || (ffeinfo_basictype (ffebld_info (dest))
1877 != FFEINFO_basictypeCOMPLEX)
1878 || (ffeinfo_kindtype (ffebld_info (dest)) != kt)
1879 || ((type != NULL_TREE) && (TREE_TYPE (dest_tree) != type))
1880 || ffecom_args_overlapping_ (dest_tree, dest, args,
1881 callee_commons,
1882 scalar_args))
1883 {
1884 #ifdef HOHO
1885 tempvar = ffecom_make_tempvar (ffecom_tree_type
1886 [FFEINFO_basictypeCOMPLEX][kt],
1887 FFETARGET_charactersizeNONE,
1888 -1);
1889 #else
1890 tempvar = hook;
1891 assert (tempvar);
1892 #endif
1893 }
1894 else
1895 {
1896 *dest_used = TRUE;
1897 tempvar = dest_tree;
1898 type = NULL_TREE;
1899 }
1900
1901 item
1902 = build_tree_list (NULL_TREE,
1903 ffecom_1 (ADDR_EXPR,
1904 build_pointer_type (TREE_TYPE (tempvar)),
1905 tempvar));
1906 TREE_CHAIN (item) = args;
1907
1908 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1909 item, NULL_TREE);
1910
1911 if (tempvar != dest_tree)
1912 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item, tempvar);
1913 }
1914 else
1915 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1916 args, NULL_TREE);
1917
1918 if ((type != NULL_TREE) && (TREE_TYPE (item) != type))
1919 item = ffecom_convert_narrow_ (type, item);
1920
1921 return item;
1922 }
1923 #endif
1924
1925 /* Given two arguments, transform them and make a call to the given
1926 function via ffecom_call_. */
1927
1928 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1929 static tree
1930 ffecom_call_binop_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1931 tree type, ffebld left, ffebld right,
1932 tree dest_tree, ffebld dest, bool *dest_used,
1933 tree callee_commons, bool scalar_args, tree hook)
1934 {
1935 tree left_tree;
1936 tree right_tree;
1937 tree left_length;
1938 tree right_length;
1939
1940 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
1941 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
1942
1943 left_tree = build_tree_list (NULL_TREE, left_tree);
1944 right_tree = build_tree_list (NULL_TREE, right_tree);
1945 TREE_CHAIN (left_tree) = right_tree;
1946
1947 if (left_length != NULL_TREE)
1948 {
1949 left_length = build_tree_list (NULL_TREE, left_length);
1950 TREE_CHAIN (right_tree) = left_length;
1951 }
1952
1953 if (right_length != NULL_TREE)
1954 {
1955 right_length = build_tree_list (NULL_TREE, right_length);
1956 if (left_length != NULL_TREE)
1957 TREE_CHAIN (left_length) = right_length;
1958 else
1959 TREE_CHAIN (right_tree) = right_length;
1960 }
1961
1962 return ffecom_call_ (fn, kt, is_f2c_complex, type, left_tree,
1963 dest_tree, dest, dest_used, callee_commons,
1964 scalar_args, hook);
1965 }
1966 #endif
1967
1968 /* Return ptr/length args for char subexpression
1969
1970 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
1971 subexpressions by constructing the appropriate trees for the ptr-to-
1972 character-text and length-of-character-text arguments in a calling
1973 sequence.
1974
1975 Note that if with_null is TRUE, and the expression is an opCONTER,
1976 a null byte is appended to the string. */
1977
1978 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1979 static void
1980 ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
1981 {
1982 tree item;
1983 tree high;
1984 ffetargetCharacter1 val;
1985 ffetargetCharacterSize newlen;
1986
1987 switch (ffebld_op (expr))
1988 {
1989 case FFEBLD_opCONTER:
1990 val = ffebld_constant_character1 (ffebld_conter (expr));
1991 newlen = ffetarget_length_character1 (val);
1992 if (with_null)
1993 {
1994 /* Begin FFETARGET-NULL-KLUDGE. */
1995 if (newlen != 0)
1996 ++newlen;
1997 }
1998 *length = build_int_2 (newlen, 0);
1999 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2000 high = build_int_2 (newlen, 0);
2001 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
2002 item = build_string (newlen,
2003 ffetarget_text_character1 (val));
2004 /* End FFETARGET-NULL-KLUDGE. */
2005 TREE_TYPE (item)
2006 = build_type_variant
2007 (build_array_type
2008 (char_type_node,
2009 build_range_type
2010 (ffecom_f2c_ftnlen_type_node,
2011 ffecom_f2c_ftnlen_one_node,
2012 high)),
2013 1, 0);
2014 TREE_CONSTANT (item) = 1;
2015 TREE_STATIC (item) = 1;
2016 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
2017 item);
2018 break;
2019
2020 case FFEBLD_opSYMTER:
2021 {
2022 ffesymbol s = ffebld_symter (expr);
2023
2024 item = ffesymbol_hook (s).decl_tree;
2025 if (item == NULL_TREE)
2026 {
2027 s = ffecom_sym_transform_ (s);
2028 item = ffesymbol_hook (s).decl_tree;
2029 }
2030 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
2031 {
2032 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
2033 *length = ffesymbol_hook (s).length_tree;
2034 else
2035 {
2036 *length = build_int_2 (ffesymbol_size (s), 0);
2037 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2038 }
2039 }
2040 else if (item == error_mark_node)
2041 *length = error_mark_node;
2042 else
2043 /* FFEINFO_kindFUNCTION. */
2044 *length = NULL_TREE;
2045 if (!ffesymbol_hook (s).addr
2046 && (item != error_mark_node))
2047 item = ffecom_1 (ADDR_EXPR,
2048 build_pointer_type (TREE_TYPE (item)),
2049 item);
2050 }
2051 break;
2052
2053 case FFEBLD_opARRAYREF:
2054 {
2055 ffecom_char_args_ (&item, length, ffebld_left (expr));
2056
2057 if (item == error_mark_node || *length == error_mark_node)
2058 {
2059 item = *length = error_mark_node;
2060 break;
2061 }
2062
2063 item = ffecom_arrayref_ (item, expr, 1);
2064 }
2065 break;
2066
2067 case FFEBLD_opSUBSTR:
2068 {
2069 ffebld start;
2070 ffebld end;
2071 ffebld thing = ffebld_right (expr);
2072 tree start_tree;
2073 tree end_tree;
2074 const char *char_name;
2075 ffebld left_symter;
2076 tree array;
2077
2078 assert (ffebld_op (thing) == FFEBLD_opITEM);
2079 start = ffebld_head (thing);
2080 thing = ffebld_trail (thing);
2081 assert (ffebld_trail (thing) == NULL);
2082 end = ffebld_head (thing);
2083
2084 /* Determine name for pretty-printing range-check errors. */
2085 for (left_symter = ffebld_left (expr);
2086 left_symter && ffebld_op (left_symter) == FFEBLD_opARRAYREF;
2087 left_symter = ffebld_left (left_symter))
2088 ;
2089 if (ffebld_op (left_symter) == FFEBLD_opSYMTER)
2090 char_name = ffesymbol_text (ffebld_symter (left_symter));
2091 else
2092 char_name = "[expr?]";
2093
2094 ffecom_char_args_ (&item, length, ffebld_left (expr));
2095
2096 if (item == error_mark_node || *length == error_mark_node)
2097 {
2098 item = *length = error_mark_node;
2099 break;
2100 }
2101
2102 array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
2103
2104 /* ~~~~Handle INTEGER*8 start/end, a la FFEBLD_opARRAYREF. */
2105
2106 if (start == NULL)
2107 {
2108 if (end == NULL)
2109 ;
2110 else
2111 {
2112 end_tree = ffecom_expr (end);
2113 if (flag_bounds_check)
2114 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2115 char_name);
2116 end_tree = convert (ffecom_f2c_ftnlen_type_node,
2117 end_tree);
2118
2119 if (end_tree == error_mark_node)
2120 {
2121 item = *length = error_mark_node;
2122 break;
2123 }
2124
2125 *length = end_tree;
2126 }
2127 }
2128 else
2129 {
2130 start_tree = ffecom_expr (start);
2131 if (flag_bounds_check)
2132 start_tree = ffecom_subscript_check_ (array, start_tree, 0, 0,
2133 char_name);
2134 start_tree = convert (ffecom_f2c_ftnlen_type_node,
2135 start_tree);
2136
2137 if (start_tree == error_mark_node)
2138 {
2139 item = *length = error_mark_node;
2140 break;
2141 }
2142
2143 start_tree = ffecom_save_tree (start_tree);
2144
2145 item = ffecom_2 (PLUS_EXPR, TREE_TYPE (item),
2146 item,
2147 ffecom_2 (MINUS_EXPR,
2148 TREE_TYPE (start_tree),
2149 start_tree,
2150 ffecom_f2c_ftnlen_one_node));
2151
2152 if (end == NULL)
2153 {
2154 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2155 ffecom_f2c_ftnlen_one_node,
2156 ffecom_2 (MINUS_EXPR,
2157 ffecom_f2c_ftnlen_type_node,
2158 *length,
2159 start_tree));
2160 }
2161 else
2162 {
2163 end_tree = ffecom_expr (end);
2164 if (flag_bounds_check)
2165 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2166 char_name);
2167 end_tree = convert (ffecom_f2c_ftnlen_type_node,
2168 end_tree);
2169
2170 if (end_tree == error_mark_node)
2171 {
2172 item = *length = error_mark_node;
2173 break;
2174 }
2175
2176 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2177 ffecom_f2c_ftnlen_one_node,
2178 ffecom_2 (MINUS_EXPR,
2179 ffecom_f2c_ftnlen_type_node,
2180 end_tree, start_tree));
2181 }
2182 }
2183 }
2184 break;
2185
2186 case FFEBLD_opFUNCREF:
2187 {
2188 ffesymbol s = ffebld_symter (ffebld_left (expr));
2189 tree tempvar;
2190 tree args;
2191 ffetargetCharacterSize size = ffeinfo_size (ffebld_info (expr));
2192 ffecomGfrt ix;
2193
2194 if (size == FFETARGET_charactersizeNONE)
2195 /* ~~Kludge alert! This should someday be fixed. */
2196 size = 24;
2197
2198 *length = build_int_2 (size, 0);
2199 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2200
2201 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
2202 == FFEINFO_whereINTRINSIC)
2203 {
2204 if (size == 1)
2205 {
2206 /* Invocation of an intrinsic returning CHARACTER*1. */
2207 item = ffecom_expr_intrinsic_ (expr, NULL_TREE,
2208 NULL, NULL);
2209 break;
2210 }
2211 ix = ffeintrin_gfrt_direct (ffebld_symter_implementation (ffebld_left (expr)));
2212 assert (ix != FFECOM_gfrt);
2213 item = ffecom_gfrt_tree_ (ix);
2214 }
2215 else
2216 {
2217 ix = FFECOM_gfrt;
2218 item = ffesymbol_hook (s).decl_tree;
2219 if (item == NULL_TREE)
2220 {
2221 s = ffecom_sym_transform_ (s);
2222 item = ffesymbol_hook (s).decl_tree;
2223 }
2224 if (item == error_mark_node)
2225 {
2226 item = *length = error_mark_node;
2227 break;
2228 }
2229
2230 if (!ffesymbol_hook (s).addr)
2231 item = ffecom_1_fn (item);
2232 }
2233
2234 #ifdef HOHO
2235 tempvar = ffecom_push_tempvar (char_type_node, size, -1, TRUE);
2236 #else
2237 tempvar = ffebld_nonter_hook (expr);
2238 assert (tempvar);
2239 #endif
2240 tempvar = ffecom_1 (ADDR_EXPR,
2241 build_pointer_type (TREE_TYPE (tempvar)),
2242 tempvar);
2243
2244 args = build_tree_list (NULL_TREE, tempvar);
2245
2246 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT) /* Sfunc args by value. */
2247 TREE_CHAIN (args) = ffecom_list_expr (ffebld_right (expr));
2248 else
2249 {
2250 TREE_CHAIN (args) = build_tree_list (NULL_TREE, *length);
2251 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
2252 {
2253 TREE_CHAIN (TREE_CHAIN (args))
2254 = ffecom_arglist_expr_ (ffecom_gfrt_args_ (ix),
2255 ffebld_right (expr));
2256 }
2257 else
2258 {
2259 TREE_CHAIN (TREE_CHAIN (args))
2260 = ffecom_list_ptr_to_expr (ffebld_right (expr));
2261 }
2262 }
2263
2264 item = ffecom_3s (CALL_EXPR,
2265 TREE_TYPE (TREE_TYPE (TREE_TYPE (item))),
2266 item, args, NULL_TREE);
2267 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item,
2268 tempvar);
2269 }
2270 break;
2271
2272 case FFEBLD_opCONVERT:
2273
2274 ffecom_char_args_ (&item, length, ffebld_left (expr));
2275
2276 if (item == error_mark_node || *length == error_mark_node)
2277 {
2278 item = *length = error_mark_node;
2279 break;
2280 }
2281
2282 if ((ffebld_size_known (ffebld_left (expr))
2283 == FFETARGET_charactersizeNONE)
2284 || (ffebld_size_known (ffebld_left (expr)) < (ffebld_size (expr))))
2285 { /* Possible blank-padding needed, copy into
2286 temporary. */
2287 tree tempvar;
2288 tree args;
2289 tree newlen;
2290
2291 #ifdef HOHO
2292 tempvar = ffecom_make_tempvar (char_type_node,
2293 ffebld_size (expr), -1);
2294 #else
2295 tempvar = ffebld_nonter_hook (expr);
2296 assert (tempvar);
2297 #endif
2298 tempvar = ffecom_1 (ADDR_EXPR,
2299 build_pointer_type (TREE_TYPE (tempvar)),
2300 tempvar);
2301
2302 newlen = build_int_2 (ffebld_size (expr), 0);
2303 TREE_TYPE (newlen) = ffecom_f2c_ftnlen_type_node;
2304
2305 args = build_tree_list (NULL_TREE, tempvar);
2306 TREE_CHAIN (args) = build_tree_list (NULL_TREE, item);
2307 TREE_CHAIN (TREE_CHAIN (args)) = build_tree_list (NULL_TREE, newlen);
2308 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (args)))
2309 = build_tree_list (NULL_TREE, *length);
2310
2311 item = ffecom_call_gfrt (FFECOM_gfrtCOPY, args, NULL_TREE);
2312 TREE_SIDE_EFFECTS (item) = 1;
2313 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), fold (item),
2314 tempvar);
2315 *length = newlen;
2316 }
2317 else
2318 { /* Just truncate the length. */
2319 *length = build_int_2 (ffebld_size (expr), 0);
2320 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2321 }
2322 break;
2323
2324 default:
2325 assert ("bad op for single char arg expr" == NULL);
2326 item = NULL_TREE;
2327 break;
2328 }
2329
2330 *xitem = item;
2331 }
2332 #endif
2333
2334 /* Check the size of the type to be sure it doesn't overflow the
2335 "portable" capacities of the compiler back end. `dummy' types
2336 can generally overflow the normal sizes as long as the computations
2337 themselves don't overflow. A particular target of the back end
2338 must still enforce its size requirements, though, and the back
2339 end takes care of this in stor-layout.c. */
2340
2341 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2342 static tree
2343 ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy)
2344 {
2345 if (TREE_CODE (type) == ERROR_MARK)
2346 return type;
2347
2348 if (TYPE_SIZE (type) == NULL_TREE)
2349 return type;
2350
2351 if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
2352 return type;
2353
2354 if ((tree_int_cst_sgn (TYPE_SIZE (type)) < 0)
2355 || (!dummy && (((TREE_INT_CST_HIGH (TYPE_SIZE (type)) != 0))
2356 || TREE_OVERFLOW (TYPE_SIZE (type)))))
2357 {
2358 ffebad_start (FFEBAD_ARRAY_LARGE);
2359 ffebad_string (ffesymbol_text (s));
2360 ffebad_here (0, ffesymbol_where_line (s), ffesymbol_where_column (s));
2361 ffebad_finish ();
2362
2363 return error_mark_node;
2364 }
2365
2366 return type;
2367 }
2368 #endif
2369
2370 /* Builds a length argument (PARM_DECL). Also wraps type in an array type
2371 where the dimension info is (1:size) where <size> is ffesymbol_size(s) if
2372 known, length_arg if not known (FFETARGET_charactersizeNONE). */
2373
2374 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2375 static tree
2376 ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s)
2377 {
2378 ffetargetCharacterSize sz = ffesymbol_size (s);
2379 tree highval;
2380 tree tlen;
2381 tree type = *xtype;
2382
2383 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
2384 tlen = NULL_TREE; /* A statement function, no length passed. */
2385 else
2386 {
2387 if (ffesymbol_where (s) == FFEINFO_whereDUMMY)
2388 tlen = ffecom_get_invented_identifier ("__g77_length_%s",
2389 ffesymbol_text (s));
2390 else
2391 tlen = ffecom_get_invented_identifier ("__g77_%s", "length");
2392 tlen = build_decl (PARM_DECL, tlen, ffecom_f2c_ftnlen_type_node);
2393 #if BUILT_FOR_270
2394 DECL_ARTIFICIAL (tlen) = 1;
2395 #endif
2396 }
2397
2398 if (sz == FFETARGET_charactersizeNONE)
2399 {
2400 assert (tlen != NULL_TREE);
2401 highval = variable_size (tlen);
2402 }
2403 else
2404 {
2405 highval = build_int_2 (sz, 0);
2406 TREE_TYPE (highval) = ffecom_f2c_ftnlen_type_node;
2407 }
2408
2409 type = build_array_type (type,
2410 build_range_type (ffecom_f2c_ftnlen_type_node,
2411 ffecom_f2c_ftnlen_one_node,
2412 highval));
2413
2414 *xtype = type;
2415 return tlen;
2416 }
2417
2418 #endif
2419 /* ffecom_concat_list_gather_ -- Gather list of concatenated string exprs
2420
2421 ffecomConcatList_ catlist;
2422 ffebld expr; // expr of CHARACTER basictype.
2423 ffetargetCharacterSize max; // max chars to gather or _...NONE if no max
2424 catlist = ffecom_concat_list_gather_(catlist,expr,max);
2425
2426 Scans expr for character subexpressions, updates and returns catlist
2427 accordingly. */
2428
2429 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2430 static ffecomConcatList_
2431 ffecom_concat_list_gather_ (ffecomConcatList_ catlist, ffebld expr,
2432 ffetargetCharacterSize max)
2433 {
2434 ffetargetCharacterSize sz;
2435
2436 recurse: /* :::::::::::::::::::: */
2437
2438 if (expr == NULL)
2439 return catlist;
2440
2441 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen >= max))
2442 return catlist; /* Don't append any more items. */
2443
2444 switch (ffebld_op (expr))
2445 {
2446 case FFEBLD_opCONTER:
2447 case FFEBLD_opSYMTER:
2448 case FFEBLD_opARRAYREF:
2449 case FFEBLD_opFUNCREF:
2450 case FFEBLD_opSUBSTR:
2451 case FFEBLD_opCONVERT: /* Callers should strip this off beforehand
2452 if they don't need to preserve it. */
2453 if (catlist.count == catlist.max)
2454 { /* Make a (larger) list. */
2455 ffebld *newx;
2456 int newmax;
2457
2458 newmax = (catlist.max == 0) ? 8 : catlist.max * 2;
2459 newx = malloc_new_ks (malloc_pool_image (), "catlist",
2460 newmax * sizeof (newx[0]));
2461 if (catlist.max != 0)
2462 {
2463 memcpy (newx, catlist.exprs, catlist.max * sizeof (newx[0]));
2464 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2465 catlist.max * sizeof (newx[0]));
2466 }
2467 catlist.max = newmax;
2468 catlist.exprs = newx;
2469 }
2470 if ((sz = ffebld_size_known (expr)) != FFETARGET_charactersizeNONE)
2471 catlist.minlen += sz;
2472 else
2473 ++catlist.minlen; /* Not true for F90; can be 0 length. */
2474 if ((sz = ffebld_size_max (expr)) == FFETARGET_charactersizeNONE)
2475 catlist.maxlen = sz;
2476 else
2477 catlist.maxlen += sz;
2478 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen > max))
2479 { /* This item overlaps (or is beyond) the end
2480 of the destination. */
2481 switch (ffebld_op (expr))
2482 {
2483 case FFEBLD_opCONTER:
2484 case FFEBLD_opSYMTER:
2485 case FFEBLD_opARRAYREF:
2486 case FFEBLD_opFUNCREF:
2487 case FFEBLD_opSUBSTR:
2488 /* ~~Do useful truncations here. */
2489 break;
2490
2491 default:
2492 assert ("op changed or inconsistent switches!" == NULL);
2493 break;
2494 }
2495 }
2496 catlist.exprs[catlist.count++] = expr;
2497 return catlist;
2498
2499 case FFEBLD_opPAREN:
2500 expr = ffebld_left (expr);
2501 goto recurse; /* :::::::::::::::::::: */
2502
2503 case FFEBLD_opCONCATENATE:
2504 catlist = ffecom_concat_list_gather_ (catlist, ffebld_left (expr), max);
2505 expr = ffebld_right (expr);
2506 goto recurse; /* :::::::::::::::::::: */
2507
2508 #if 0 /* Breaks passing small actual arg to larger
2509 dummy arg of sfunc */
2510 case FFEBLD_opCONVERT:
2511 expr = ffebld_left (expr);
2512 {
2513 ffetargetCharacterSize cmax;
2514
2515 cmax = catlist.len + ffebld_size_known (expr);
2516
2517 if ((max == FFETARGET_charactersizeNONE) || (max > cmax))
2518 max = cmax;
2519 }
2520 goto recurse; /* :::::::::::::::::::: */
2521 #endif
2522
2523 case FFEBLD_opANY:
2524 return catlist;
2525
2526 default:
2527 assert ("bad op in _gather_" == NULL);
2528 return catlist;
2529 }
2530 }
2531
2532 #endif
2533 /* ffecom_concat_list_kill_ -- Kill list of concatenated string exprs
2534
2535 ffecomConcatList_ catlist;
2536 ffecom_concat_list_kill_(catlist);
2537
2538 Anything allocated within the list info is deallocated. */
2539
2540 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2541 static void
2542 ffecom_concat_list_kill_ (ffecomConcatList_ catlist)
2543 {
2544 if (catlist.max != 0)
2545 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2546 catlist.max * sizeof (catlist.exprs[0]));
2547 }
2548
2549 #endif
2550 /* Make list of concatenated string exprs.
2551
2552 Returns a flattened list of concatenated subexpressions given a
2553 tree of such expressions. */
2554
2555 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2556 static ffecomConcatList_
2557 ffecom_concat_list_new_ (ffebld expr, ffetargetCharacterSize max)
2558 {
2559 ffecomConcatList_ catlist;
2560
2561 catlist.maxlen = catlist.minlen = catlist.max = catlist.count = 0;
2562 return ffecom_concat_list_gather_ (catlist, expr, max);
2563 }
2564
2565 #endif
2566
2567 /* Provide some kind of useful info on member of aggregate area,
2568 since current g77/gcc technology does not provide debug info
2569 on these members. */
2570
2571 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2572 static void
2573 ffecom_debug_kludge_ (tree aggr, const char *aggr_type, ffesymbol member,
2574 tree member_type UNUSED, ffetargetOffset offset)
2575 {
2576 tree value;
2577 tree decl;
2578 int len;
2579 char *buff;
2580 char space[120];
2581 #if 0
2582 tree type_id;
2583
2584 for (type_id = member_type;
2585 TREE_CODE (type_id) != IDENTIFIER_NODE;
2586 )
2587 {
2588 switch (TREE_CODE (type_id))
2589 {
2590 case INTEGER_TYPE:
2591 case REAL_TYPE:
2592 type_id = TYPE_NAME (type_id);
2593 break;
2594
2595 case ARRAY_TYPE:
2596 case COMPLEX_TYPE:
2597 type_id = TREE_TYPE (type_id);
2598 break;
2599
2600 default:
2601 assert ("no IDENTIFIER_NODE for type!" == NULL);
2602 type_id = error_mark_node;
2603 break;
2604 }
2605 }
2606 #endif
2607
2608 if (ffecom_transform_only_dummies_
2609 || !ffe_is_debug_kludge ())
2610 return; /* Can't do this yet, maybe later. */
2611
2612 len = 60
2613 + strlen (aggr_type)
2614 + IDENTIFIER_LENGTH (DECL_NAME (aggr));
2615 #if 0
2616 + IDENTIFIER_LENGTH (type_id);
2617 #endif
2618
2619 if (((size_t) len) >= ARRAY_SIZE (space))
2620 buff = malloc_new_ks (malloc_pool_image (), "debug_kludge", len + 1);
2621 else
2622 buff = &space[0];
2623
2624 sprintf (&buff[0], "At (%s) `%s' plus %ld bytes",
2625 aggr_type,
2626 IDENTIFIER_POINTER (DECL_NAME (aggr)),
2627 (long int) offset);
2628
2629 value = build_string (len, buff);
2630 TREE_TYPE (value)
2631 = build_type_variant (build_array_type (char_type_node,
2632 build_range_type
2633 (integer_type_node,
2634 integer_one_node,
2635 build_int_2 (strlen (buff), 0))),
2636 1, 0);
2637 decl = build_decl (VAR_DECL,
2638 ffecom_get_identifier_ (ffesymbol_text (member)),
2639 TREE_TYPE (value));
2640 TREE_CONSTANT (decl) = 1;
2641 TREE_STATIC (decl) = 1;
2642 DECL_INITIAL (decl) = error_mark_node;
2643 DECL_IN_SYSTEM_HEADER (decl) = 1; /* Don't let -Wunused complain. */
2644 decl = start_decl (decl, FALSE);
2645 finish_decl (decl, value, FALSE);
2646
2647 if (buff != &space[0])
2648 malloc_kill_ks (malloc_pool_image (), buff, len + 1);
2649 }
2650 #endif
2651
2652 /* ffecom_do_entry_ -- Do compilation of a particular entrypoint
2653
2654 ffesymbol fn; // the SUBROUTINE, FUNCTION, or ENTRY symbol itself
2655 int i; // entry# for this entrypoint (used by master fn)
2656 ffecom_do_entrypoint_(s,i);
2657
2658 Makes a public entry point that calls our private master fn (already
2659 compiled). */
2660
2661 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2662 static void
2663 ffecom_do_entry_ (ffesymbol fn, int entrynum)
2664 {
2665 ffebld item;
2666 tree type; /* Type of function. */
2667 tree multi_retval; /* Var holding return value (union). */
2668 tree result; /* Var holding result. */
2669 ffeinfoBasictype bt;
2670 ffeinfoKindtype kt;
2671 ffeglobal g;
2672 ffeglobalType gt;
2673 bool charfunc; /* All entry points return same type
2674 CHARACTER. */
2675 bool cmplxfunc; /* Use f2c way of returning COMPLEX. */
2676 bool multi; /* Master fn has multiple return types. */
2677 bool altreturning = FALSE; /* This entry point has alternate returns. */
2678 int yes;
2679 int old_lineno = lineno;
2680 const char *old_input_filename = input_filename;
2681
2682 input_filename = ffesymbol_where_filename (fn);
2683 lineno = ffesymbol_where_filelinenum (fn);
2684
2685 /* c-parse.y indeed does call suspend_momentary and not only ignores the
2686 return value, but also never calls resume_momentary, when starting an
2687 outer function (see "fndef:", "setspecs:", and so on). So g77 does the
2688 same thing. It shouldn't be a problem since start_function calls
2689 temporary_allocation, but it might be necessary. If it causes a problem
2690 here, then maybe there's a bug lurking in gcc. NOTE: This identical
2691 comment appears twice in thist file. */
2692
2693 suspend_momentary ();
2694
2695 ffecom_doing_entry_ = TRUE; /* Don't bother with array dimensions. */
2696
2697 switch (ffecom_primary_entry_kind_)
2698 {
2699 case FFEINFO_kindFUNCTION:
2700
2701 /* Determine actual return type for function. */
2702
2703 gt = FFEGLOBAL_typeFUNC;
2704 bt = ffesymbol_basictype (fn);
2705 kt = ffesymbol_kindtype (fn);
2706 if (bt == FFEINFO_basictypeNONE)
2707 {
2708 ffeimplic_establish_symbol (fn);
2709 if (ffesymbol_funcresult (fn) != NULL)
2710 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
2711 bt = ffesymbol_basictype (fn);
2712 kt = ffesymbol_kindtype (fn);
2713 }
2714
2715 if (bt == FFEINFO_basictypeCHARACTER)
2716 charfunc = TRUE, cmplxfunc = FALSE;
2717 else if ((bt == FFEINFO_basictypeCOMPLEX)
2718 && ffesymbol_is_f2c (fn))
2719 charfunc = FALSE, cmplxfunc = TRUE;
2720 else
2721 charfunc = cmplxfunc = FALSE;
2722
2723 if (charfunc)
2724 type = ffecom_tree_fun_type_void;
2725 else if (ffesymbol_is_f2c (fn))
2726 type = ffecom_tree_fun_type[bt][kt];
2727 else
2728 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
2729
2730 if ((type == NULL_TREE)
2731 || (TREE_TYPE (type) == NULL_TREE))
2732 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
2733
2734 multi = (ffecom_master_bt_ == FFEINFO_basictypeNONE);
2735 break;
2736
2737 case FFEINFO_kindSUBROUTINE:
2738 gt = FFEGLOBAL_typeSUBR;
2739 bt = FFEINFO_basictypeNONE;
2740 kt = FFEINFO_kindtypeNONE;
2741 if (ffecom_is_altreturning_)
2742 { /* Am _I_ altreturning? */
2743 for (item = ffesymbol_dummyargs (fn);
2744 item != NULL;
2745 item = ffebld_trail (item))
2746 {
2747 if (ffebld_op (ffebld_head (item)) == FFEBLD_opSTAR)
2748 {
2749 altreturning = TRUE;
2750 break;
2751 }
2752 }
2753 if (altreturning)
2754 type = ffecom_tree_subr_type;
2755 else
2756 type = ffecom_tree_fun_type_void;
2757 }
2758 else
2759 type = ffecom_tree_fun_type_void;
2760 charfunc = FALSE;
2761 cmplxfunc = FALSE;
2762 multi = FALSE;
2763 break;
2764
2765 default:
2766 assert ("say what??" == NULL);
2767 /* Fall through. */
2768 case FFEINFO_kindANY:
2769 gt = FFEGLOBAL_typeANY;
2770 bt = FFEINFO_basictypeNONE;
2771 kt = FFEINFO_kindtypeNONE;
2772 type = error_mark_node;
2773 charfunc = FALSE;
2774 cmplxfunc = FALSE;
2775 multi = FALSE;
2776 break;
2777 }
2778
2779 /* build_decl uses the current lineno and input_filename to set the decl
2780 source info. So, I've putzed with ffestd and ffeste code to update that
2781 source info to point to the appropriate statement just before calling
2782 ffecom_do_entrypoint (which calls this fn). */
2783
2784 start_function (ffecom_get_external_identifier_ (fn),
2785 type,
2786 0, /* nested/inline */
2787 1); /* TREE_PUBLIC */
2788
2789 if (((g = ffesymbol_global (fn)) != NULL)
2790 && ((ffeglobal_type (g) == gt)
2791 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
2792 {
2793 ffeglobal_set_hook (g, current_function_decl);
2794 }
2795
2796 /* Reset args in master arg list so they get retransitioned. */
2797
2798 for (item = ffecom_master_arglist_;
2799 item != NULL;
2800 item = ffebld_trail (item))
2801 {
2802 ffebld arg;
2803 ffesymbol s;
2804
2805 arg = ffebld_head (item);
2806 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2807 continue; /* Alternate return or some such thing. */
2808 s = ffebld_symter (arg);
2809 ffesymbol_hook (s).decl_tree = NULL_TREE;
2810 ffesymbol_hook (s).length_tree = NULL_TREE;
2811 }
2812
2813 /* Build dummy arg list for this entry point. */
2814
2815 yes = suspend_momentary ();
2816
2817 if (charfunc || cmplxfunc)
2818 { /* Prepend arg for where result goes. */
2819 tree type;
2820 tree length;
2821
2822 if (charfunc)
2823 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
2824 else
2825 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
2826
2827 result = ffecom_get_invented_identifier ("__g77_%s", "result");
2828
2829 /* Make length arg _and_ enhance type info for CHAR arg itself. */
2830
2831 if (charfunc)
2832 length = ffecom_char_enhance_arg_ (&type, fn);
2833 else
2834 length = NULL_TREE; /* Not ref'd if !charfunc. */
2835
2836 type = build_pointer_type (type);
2837 result = build_decl (PARM_DECL, result, type);
2838
2839 push_parm_decl (result);
2840 ffecom_func_result_ = result;
2841
2842 if (charfunc)
2843 {
2844 push_parm_decl (length);
2845 ffecom_func_length_ = length;
2846 }
2847 }
2848 else
2849 result = DECL_RESULT (current_function_decl);
2850
2851 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (fn), FALSE);
2852
2853 resume_momentary (yes);
2854
2855 store_parm_decls (0);
2856
2857 ffecom_start_compstmt ();
2858 /* Disallow temp vars at this level. */
2859 current_binding_level->prep_state = 2;
2860
2861 /* Make local var to hold return type for multi-type master fn. */
2862
2863 if (multi)
2864 {
2865 yes = suspend_momentary ();
2866
2867 multi_retval = ffecom_get_invented_identifier ("__g77_%s",
2868 "multi_retval");
2869 multi_retval = build_decl (VAR_DECL, multi_retval,
2870 ffecom_multi_type_node_);
2871 multi_retval = start_decl (multi_retval, FALSE);
2872 finish_decl (multi_retval, NULL_TREE, FALSE);
2873
2874 resume_momentary (yes);
2875 }
2876 else
2877 multi_retval = NULL_TREE; /* Not actually ref'd if !multi. */
2878
2879 /* Here we emit the actual code for the entry point. */
2880
2881 {
2882 ffebld list;
2883 ffebld arg;
2884 ffesymbol s;
2885 tree arglist = NULL_TREE;
2886 tree *plist = &arglist;
2887 tree prepend;
2888 tree call;
2889 tree actarg;
2890 tree master_fn;
2891
2892 /* Prepare actual arg list based on master arg list. */
2893
2894 for (list = ffecom_master_arglist_;
2895 list != NULL;
2896 list = ffebld_trail (list))
2897 {
2898 arg = ffebld_head (list);
2899 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2900 continue;
2901 s = ffebld_symter (arg);
2902 if (ffesymbol_hook (s).decl_tree == NULL_TREE
2903 || ffesymbol_hook (s).decl_tree == error_mark_node)
2904 actarg = null_pointer_node; /* We don't have this arg. */
2905 else
2906 actarg = ffesymbol_hook (s).decl_tree;
2907 *plist = build_tree_list (NULL_TREE, actarg);
2908 plist = &TREE_CHAIN (*plist);
2909 }
2910
2911 /* This code appends the length arguments for character
2912 variables/arrays. */
2913
2914 for (list = ffecom_master_arglist_;
2915 list != NULL;
2916 list = ffebld_trail (list))
2917 {
2918 arg = ffebld_head (list);
2919 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2920 continue;
2921 s = ffebld_symter (arg);
2922 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
2923 continue; /* Only looking for CHARACTER arguments. */
2924 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
2925 continue; /* Only looking for variables and arrays. */
2926 if (ffesymbol_hook (s).length_tree == NULL_TREE
2927 || ffesymbol_hook (s).length_tree == error_mark_node)
2928 actarg = ffecom_f2c_ftnlen_zero_node; /* We don't have this arg. */
2929 else
2930 actarg = ffesymbol_hook (s).length_tree;
2931 *plist = build_tree_list (NULL_TREE, actarg);
2932 plist = &TREE_CHAIN (*plist);
2933 }
2934
2935 /* Prepend character-value return info to actual arg list. */
2936
2937 if (charfunc)
2938 {
2939 prepend = build_tree_list (NULL_TREE, ffecom_func_result_);
2940 TREE_CHAIN (prepend)
2941 = build_tree_list (NULL_TREE, ffecom_func_length_);
2942 TREE_CHAIN (TREE_CHAIN (prepend)) = arglist;
2943 arglist = prepend;
2944 }
2945
2946 /* Prepend multi-type return value to actual arg list. */
2947
2948 if (multi)
2949 {
2950 prepend
2951 = build_tree_list (NULL_TREE,
2952 ffecom_1 (ADDR_EXPR,
2953 build_pointer_type (TREE_TYPE (multi_retval)),
2954 multi_retval));
2955 TREE_CHAIN (prepend) = arglist;
2956 arglist = prepend;
2957 }
2958
2959 /* Prepend my entry-point number to the actual arg list. */
2960
2961 prepend = build_tree_list (NULL_TREE, build_int_2 (entrynum, 0));
2962 TREE_CHAIN (prepend) = arglist;
2963 arglist = prepend;
2964
2965 /* Build the call to the master function. */
2966
2967 master_fn = ffecom_1_fn (ffecom_previous_function_decl_);
2968 call = ffecom_3s (CALL_EXPR,
2969 TREE_TYPE (TREE_TYPE (TREE_TYPE (master_fn))),
2970 master_fn, arglist, NULL_TREE);
2971
2972 /* Decide whether the master function is a function or subroutine, and
2973 handle the return value for my entry point. */
2974
2975 if (charfunc || ((ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
2976 && !altreturning))
2977 {
2978 expand_expr_stmt (call);
2979 expand_null_return ();
2980 }
2981 else if (multi && cmplxfunc)
2982 {
2983 expand_expr_stmt (call);
2984 result
2985 = ffecom_1 (INDIRECT_REF,
2986 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
2987 result);
2988 result = ffecom_modify (NULL_TREE, result,
2989 ffecom_2 (COMPONENT_REF, TREE_TYPE (result),
2990 multi_retval,
2991 ffecom_multi_fields_[bt][kt]));
2992 expand_expr_stmt (result);
2993 expand_null_return ();
2994 }
2995 else if (multi)
2996 {
2997 expand_expr_stmt (call);
2998 result
2999 = ffecom_modify (NULL_TREE, result,
3000 convert (TREE_TYPE (result),
3001 ffecom_2 (COMPONENT_REF,
3002 ffecom_tree_type[bt][kt],
3003 multi_retval,
3004 ffecom_multi_fields_[bt][kt])));
3005 expand_return (result);
3006 }
3007 else if (cmplxfunc)
3008 {
3009 result
3010 = ffecom_1 (INDIRECT_REF,
3011 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
3012 result);
3013 result = ffecom_modify (NULL_TREE, result, call);
3014 expand_expr_stmt (result);
3015 expand_null_return ();
3016 }
3017 else
3018 {
3019 result = ffecom_modify (NULL_TREE,
3020 result,
3021 convert (TREE_TYPE (result),
3022 call));
3023 expand_return (result);
3024 }
3025
3026 clear_momentary ();
3027 }
3028
3029 ffecom_end_compstmt ();
3030
3031 finish_function (0);
3032
3033 lineno = old_lineno;
3034 input_filename = old_input_filename;
3035
3036 ffecom_doing_entry_ = FALSE;
3037 }
3038
3039 #endif
3040 /* Transform expr into gcc tree with possible destination
3041
3042 Recursive descent on expr while making corresponding tree nodes and
3043 attaching type info and such. If destination supplied and compatible
3044 with temporary that would be made in certain cases, temporary isn't
3045 made, destination used instead, and dest_used flag set TRUE. */
3046
3047 #if FFECOM_targetCURRENT == FFECOM_targetGCC
3048 static tree
3049 ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
3050 bool *dest_used, bool assignp, bool widenp)
3051 {
3052 tree item;
3053 tree list;
3054 tree args;
3055 ffeinfoBasictype bt;
3056 ffeinfoKindtype kt;
3057 tree t;
3058 tree dt; /* decl_tree for an ffesymbol. */
3059 tree tree_type, tree_type_x;
3060 tree left, right;
3061 ffesymbol s;
3062 enum tree_code code;
3063
3064 assert (expr != NULL);
3065
3066 if (dest_used != NULL)
3067 *dest_used = FALSE;
3068
3069 bt = ffeinfo_basictype (ffebld_info (expr));
3070 kt = ffeinfo_kindtype (ffebld_info (expr));
3071 tree_type = ffecom_tree_type[bt][kt];
3072
3073 /* Widen integral arithmetic as desired while preserving signedness. */
3074 tree_type_x = NULL_TREE;
3075 if (widenp && tree_type
3076 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
3077 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
3078 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
3079
3080 switch (ffebld_op (expr))
3081 {
3082 case FFEBLD_opACCTER:
3083 {
3084 ffebitCount i;
3085 ffebit bits = ffebld_accter_bits (expr);
3086 ffetargetOffset source_offset = 0;
3087 ffetargetOffset dest_offset = ffebld_accter_pad (expr);
3088 tree purpose;
3089
3090 assert (dest_offset == 0
3091 || (bt == FFEINFO_basictypeCHARACTER
3092 && kt == FFEINFO_kindtypeCHARACTER1));
3093
3094 list = item = NULL;
3095 for (;;)
3096 {
3097 ffebldConstantUnion cu;
3098 ffebitCount length;
3099 bool value;
3100 ffebldConstantArray ca = ffebld_accter (expr);
3101
3102 ffebit_test (bits, source_offset, &value, &length);
3103 if (length == 0)
3104 break;
3105
3106 if (value)
3107 {
3108 for (i = 0; i < length; ++i)
3109 {
3110 cu = ffebld_constantarray_get (ca, bt, kt,
3111 source_offset + i);
3112
3113 t = ffecom_constantunion (&cu, bt, kt, tree_type);
3114
3115 if (i == 0
3116 && dest_offset != 0)
3117 purpose = build_int_2 (dest_offset, 0);
3118 else
3119 purpose = NULL_TREE;
3120
3121 if (list == NULL_TREE)
3122 list = item = build_tree_list (purpose, t);
3123 else
3124 {
3125 TREE_CHAIN (item) = build_tree_list (purpose, t);
3126 item = TREE_CHAIN (item);
3127 }
3128 }
3129 }
3130 source_offset += length;
3131 dest_offset += length;
3132 }
3133 }
3134
3135 item = build_int_2 ((ffebld_accter_size (expr)
3136 + ffebld_accter_pad (expr)) - 1, 0);
3137 ffebit_kill (ffebld_accter_bits (expr));
3138 TREE_TYPE (item) = ffecom_integer_type_node;
3139 item
3140 = build_array_type
3141 (tree_type,
3142 build_range_type (ffecom_integer_type_node,
3143 ffecom_integer_zero_node,
3144 item));
3145 list = build (CONSTRUCTOR, item, NULL_TREE, list);
3146 TREE_CONSTANT (list) = 1;
3147 TREE_STATIC (list) = 1;
3148 return list;
3149
3150 case FFEBLD_opARRTER:
3151 {
3152 ffetargetOffset i;
3153
3154 list = NULL_TREE;
3155 if (ffebld_arrter_pad (expr) == 0)
3156 item = NULL_TREE;
3157 else
3158 {
3159 assert (bt == FFEINFO_basictypeCHARACTER
3160 && kt == FFEINFO_kindtypeCHARACTER1);
3161
3162 /* Becomes PURPOSE first time through loop. */
3163 item = build_int_2 (ffebld_arrter_pad (expr), 0);
3164 }
3165
3166 for (i = 0; i < ffebld_arrter_size (expr); ++i)
3167 {
3168 ffebldConstantUnion cu
3169 = ffebld_constantarray_get (ffebld_arrter (expr), bt, kt, i);
3170
3171 t = ffecom_constantunion (&cu, bt, kt, tree_type);
3172
3173 if (list == NULL_TREE)
3174 /* Assume item is PURPOSE first time through loop. */
3175 list = item = build_tree_list (item, t);
3176 else
3177 {
3178 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
3179 item = TREE_CHAIN (item);
3180 }
3181 }
3182 }
3183
3184 item = build_int_2 ((ffebld_arrter_size (expr)
3185 + ffebld_arrter_pad (expr)) - 1, 0);
3186 TREE_TYPE (item) = ffecom_integer_type_node;
3187 item
3188 = build_array_type
3189 (tree_type,
3190 build_range_type (ffecom_integer_type_node,
3191 ffecom_integer_zero_node,
3192 item));
3193 list = build (CONSTRUCTOR, item, NULL_TREE, list);
3194 TREE_CONSTANT (list) = 1;
3195 TREE_STATIC (list) = 1;
3196 return list;
3197
3198 case FFEBLD_opCONTER:
3199 assert (ffebld_conter_pad (expr) == 0);
3200 item
3201 = ffecom_constantunion (&ffebld_constant_union (ffebld_conter (expr)),
3202 bt, kt, tree_type);
3203 return item;
3204
3205 case FFEBLD_opSYMTER:
3206 if ((ffebld_symter_generic (expr) != FFEINTRIN_genNONE)
3207 || (ffebld_symter_specific (expr) != FFEINTRIN_specNONE))
3208 return ffecom_ptr_to_expr (expr); /* Same as %REF(intrinsic). */
3209 s = ffebld_symter (expr);
3210 t = ffesymbol_hook (s).decl_tree;
3211
3212 if (assignp)
3213 { /* ASSIGN'ed-label expr. */
3214 if (ffe_is_ugly_assign ())
3215 {
3216 /* User explicitly wants ASSIGN'ed variables to be at the same
3217 memory address as the variables when used in non-ASSIGN
3218 contexts. That can make old, arcane, non-standard code
3219 work, but don't try to do it when a pointer wouldn't fit
3220 in the normal variable (take other approach, and warn,
3221 instead). */
3222
3223 if (t == NULL_TREE)
3224 {
3225 s = ffecom_sym_transform_ (s);
3226 t = ffesymbol_hook (s).decl_tree;
3227 assert (t != NULL_TREE);
3228 }
3229
3230 if (t == error_mark_node)
3231 return t;
3232
3233 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (t)))
3234 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
3235 {
3236 if (ffesymbol_hook (s).addr)
3237 t = ffecom_1 (INDIRECT_REF,
3238 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3239 return t;
3240 }
3241
3242 if (ffesymbol_hook (s).assign_tree == NULL_TREE)
3243 {
3244 ffebad_start_msg ("ASSIGN'ed label cannot fit into `%A' at %0 -- using wider sibling",
3245 FFEBAD_severityWARNING);
3246 ffebad_string (ffesymbol_text (s));
3247 ffebad_here (0, ffesymbol_where_line (s),
3248 ffesymbol_where_column (s));
3249 ffebad_finish ();
3250 }
3251 }
3252
3253 /* Don't use the normal variable's tree for ASSIGN, though mark
3254 it as in the system header (housekeeping). Use an explicit,
3255 specially created sibling that is known to be wide enough
3256 to hold pointers to labels. */
3257
3258 if (t != NULL_TREE
3259 && TREE_CODE (t) == VAR_DECL)
3260 DECL_IN_SYSTEM_HEADER (t) = 1; /* Don't let -Wunused complain. */
3261
3262 t = ffesymbol_hook (s).assign_tree;
3263 if (t == NULL_TREE)
3264 {
3265 s = ffecom_sym_transform_assign_ (s);
3266 t = ffesymbol_hook (s).assign_tree;
3267 assert (t != NULL_TREE);
3268 }
3269 }
3270 else
3271 {
3272 if (t == NULL_TREE)
3273 {
3274 s = ffecom_sym_transform_ (s);
3275 t = ffesymbol_hook (s).decl_tree;
3276 assert (t != NULL_TREE);
3277 }
3278 if (ffesymbol_hook (s).addr)
3279 t = ffecom_1 (INDIRECT_REF,
3280 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3281 }
3282 return t;
3283
3284 case FFEBLD_opARRAYREF:
3285 return ffecom_arrayref_ (NULL_TREE, expr, 0);
3286
3287 case FFEBLD_opUPLUS:
3288 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3289 return ffecom_1 (NOP_EXPR, tree_type, left);
3290
3291 case FFEBLD_opPAREN:
3292 /* ~~~Make sure Fortran rules respected here */
3293 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3294 return ffecom_1 (NOP_EXPR, tree_type, left);
3295
3296 case FFEBLD_opUMINUS:
3297 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3298 if (tree_type_x)
3299 {
3300 tree_type = tree_type_x;
3301 left = convert (tree_type, left);
3302 }
3303 return ffecom_1 (NEGATE_EXPR, tree_type, left);
3304
3305 case FFEBLD_opADD:
3306 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3307 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3308 if (tree_type_x)
3309 {
3310 tree_type = tree_type_x;
3311 left = convert (tree_type, left);
3312 right = convert (tree_type, right);
3313 }
3314 return ffecom_2 (PLUS_EXPR, tree_type, left, right);
3315
3316 case FFEBLD_opSUBTRACT:
3317 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3318 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3319 if (tree_type_x)
3320 {
3321 tree_type = tree_type_x;
3322 left = convert (tree_type, left);
3323 right = convert (tree_type, right);
3324 }
3325 return ffecom_2 (MINUS_EXPR, tree_type, left, right);
3326
3327 case FFEBLD_opMULTIPLY:
3328 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3329 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3330 if (tree_type_x)
3331 {
3332 tree_type = tree_type_x;
3333 left = convert (tree_type, left);
3334 right = convert (tree_type, right);
3335 }
3336 return ffecom_2 (MULT_EXPR, tree_type, left, right);
3337
3338 case FFEBLD_opDIVIDE:
3339 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3340 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3341 if (tree_type_x)
3342 {
3343 tree_type = tree_type_x;
3344 left = convert (tree_type, left);
3345 right = convert (tree_type, right);
3346 }
3347 return ffecom_tree_divide_ (tree_type, left, right,
3348 dest_tree, dest, dest_used,
3349 ffebld_nonter_hook (expr));
3350
3351 case FFEBLD_opPOWER:
3352 {
3353 ffebld left = ffebld_left (expr);
3354 ffebld right = ffebld_right (expr);
3355 ffecomGfrt code;
3356 ffeinfoKindtype rtkt;
3357 ffeinfoKindtype ltkt;
3358
3359 switch (ffeinfo_basictype (ffebld_info (right)))
3360 {
3361 case FFEINFO_basictypeINTEGER:
3362 if (1 || optimize)
3363 {
3364 item = ffecom_expr_power_integer_ (expr);
3365 if (item != NULL_TREE)
3366 return item;
3367 }
3368
3369 rtkt = FFEINFO_kindtypeINTEGER1;
3370 switch (ffeinfo_basictype (ffebld_info (left)))
3371 {
3372 case FFEINFO_basictypeINTEGER:
3373 if ((ffeinfo_kindtype (ffebld_info (left))
3374 == FFEINFO_kindtypeINTEGER4)
3375 || (ffeinfo_kindtype (ffebld_info (right))
3376 == FFEINFO_kindtypeINTEGER4))
3377 {
3378 code = FFECOM_gfrtPOW_QQ;
3379 ltkt = FFEINFO_kindtypeINTEGER4;
3380 rtkt = FFEINFO_kindtypeINTEGER4;
3381 }
3382 else
3383 {
3384 code = FFECOM_gfrtPOW_II;
3385 ltkt = FFEINFO_kindtypeINTEGER1;
3386 }
3387 break;
3388
3389 case FFEINFO_basictypeREAL:
3390 if (ffeinfo_kindtype (ffebld_info (left))
3391 == FFEINFO_kindtypeREAL1)
3392 {
3393 code = FFECOM_gfrtPOW_RI;
3394 ltkt = FFEINFO_kindtypeREAL1;
3395 }
3396 else
3397 {
3398 code = FFECOM_gfrtPOW_DI;
3399 ltkt = FFEINFO_kindtypeREAL2;
3400 }
3401 break;
3402
3403 case FFEINFO_basictypeCOMPLEX:
3404 if (ffeinfo_kindtype (ffebld_info (left))
3405 == FFEINFO_kindtypeREAL1)
3406 {
3407 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
3408 ltkt = FFEINFO_kindtypeREAL1;
3409 }
3410 else
3411 {
3412 code = FFECOM_gfrtPOW_ZI; /* Overlapping result okay. */
3413 ltkt = FFEINFO_kindtypeREAL2;
3414 }
3415 break;
3416
3417 default:
3418 assert ("bad pow_*i" == NULL);
3419 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
3420 ltkt = FFEINFO_kindtypeREAL1;
3421 break;
3422 }
3423 if (ffeinfo_kindtype (ffebld_info (left)) != ltkt)
3424 left = ffeexpr_convert (left, NULL, NULL,
3425 ffeinfo_basictype (ffebld_info (left)),
3426 ltkt, 0,
3427 FFETARGET_charactersizeNONE,
3428 FFEEXPR_contextLET);
3429 if (ffeinfo_kindtype (ffebld_info (right)) != rtkt)
3430 right = ffeexpr_convert (right, NULL, NULL,
3431 FFEINFO_basictypeINTEGER,
3432 rtkt, 0,
3433 FFETARGET_charactersizeNONE,
3434 FFEEXPR_contextLET);
3435 break;
3436
3437 case FFEINFO_basictypeREAL:
3438 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3439 left = ffeexpr_convert (left, NULL, NULL, FFEINFO_basictypeREAL,
3440 FFEINFO_kindtypeREALDOUBLE, 0,
3441 FFETARGET_charactersizeNONE,
3442 FFEEXPR_contextLET);
3443 if (ffeinfo_kindtype (ffebld_info (right))
3444 == FFEINFO_kindtypeREAL1)
3445 right = ffeexpr_convert (right, NULL, NULL,
3446 FFEINFO_basictypeREAL,
3447 FFEINFO_kindtypeREALDOUBLE, 0,
3448 FFETARGET_charactersizeNONE,
3449 FFEEXPR_contextLET);
3450 code = FFECOM_gfrtPOW_DD;
3451 break;
3452
3453 case FFEINFO_basictypeCOMPLEX:
3454 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3455 left = ffeexpr_convert (left, NULL, NULL,
3456 FFEINFO_basictypeCOMPLEX,
3457 FFEINFO_kindtypeREALDOUBLE, 0,
3458 FFETARGET_charactersizeNONE,
3459 FFEEXPR_contextLET);
3460 if (ffeinfo_kindtype (ffebld_info (right))
3461 == FFEINFO_kindtypeREAL1)
3462 right = ffeexpr_convert (right, NULL, NULL,
3463 FFEINFO_basictypeCOMPLEX,
3464 FFEINFO_kindtypeREALDOUBLE, 0,
3465 FFETARGET_charactersizeNONE,
3466 FFEEXPR_contextLET);
3467 code = FFECOM_gfrtPOW_ZZ; /* Overlapping result okay. */
3468 break;
3469
3470 default:
3471 assert ("bad pow_x*" == NULL);
3472 code = FFECOM_gfrtPOW_II;
3473 break;
3474 }
3475 return ffecom_call_binop_ (ffecom_gfrt_tree_ (code),
3476 ffecom_gfrt_kindtype (code),
3477 (ffe_is_f2c_library ()
3478 && ffecom_gfrt_complex_[code]),
3479 tree_type, left, right,
3480 dest_tree, dest, dest_used,
3481 NULL_TREE, FALSE,
3482 ffebld_nonter_hook (expr));
3483 }
3484
3485 case FFEBLD_opNOT:
3486 switch (bt)
3487 {
3488 case FFEINFO_basictypeLOGICAL:
3489 item = ffecom_truth_value_invert (ffecom_expr (ffebld_left (expr)));
3490 return convert (tree_type, item);
3491
3492 case FFEINFO_basictypeINTEGER:
3493 return ffecom_1 (BIT_NOT_EXPR, tree_type,
3494 ffecom_expr (ffebld_left (expr)));
3495
3496 default:
3497 assert ("NOT bad basictype" == NULL);
3498 /* Fall through. */
3499 case FFEINFO_basictypeANY:
3500 return error_mark_node;
3501 }
3502 break;
3503
3504 case FFEBLD_opFUNCREF:
3505 assert (ffeinfo_basictype (ffebld_info (expr))
3506 != FFEINFO_basictypeCHARACTER);
3507 /* Fall through. */
3508 case FFEBLD_opSUBRREF:
3509 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
3510 == FFEINFO_whereINTRINSIC)
3511 { /* Invocation of an intrinsic. */
3512 item = ffecom_expr_intrinsic_ (expr, dest_tree, dest,
3513 dest_used);
3514 return item;
3515 }
3516 s = ffebld_symter (ffebld_left (expr));
3517 dt = ffesymbol_hook (s).decl_tree;
3518 if (dt == NULL_TREE)
3519 {
3520 s = ffecom_sym_transform_ (s);
3521 dt = ffesymbol_hook (s).decl_tree;
3522 }
3523 if (dt == error_mark_node)
3524 return dt;
3525
3526 if (ffesymbol_hook (s).addr)
3527 item = dt;
3528 else
3529 item = ffecom_1_fn (dt);
3530
3531 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
3532 args = ffecom_list_expr (ffebld_right (expr));
3533 else
3534 args = ffecom_list_ptr_to_expr (ffebld_right (expr));
3535
3536 if (args == error_mark_node)
3537 return error_mark_node;
3538
3539 item = ffecom_call_ (item, kt,
3540 ffesymbol_is_f2c (s)
3541 && (bt == FFEINFO_basictypeCOMPLEX)
3542 && (ffesymbol_where (s)
3543 != FFEINFO_whereCONSTANT),
3544 tree_type,
3545 args,
3546 dest_tree, dest, dest_used,
3547 error_mark_node, FALSE,
3548 ffebld_nonter_hook (expr));
3549 TREE_SIDE_EFFECTS (item) = 1;
3550 return item;
3551
3552 case FFEBLD_opAND:
3553 switch (bt)
3554 {
3555 case FFEINFO_basictypeLOGICAL:
3556 item
3557 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3558 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3559 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3560 return convert (tree_type, item);
3561
3562 case FFEINFO_basictypeINTEGER:
3563 return ffecom_2 (BIT_AND_EXPR, tree_type,
3564 ffecom_expr (ffebld_left (expr)),
3565 ffecom_expr (ffebld_right (expr)));
3566
3567 default:
3568 assert ("AND bad basictype" == NULL);
3569 /* Fall through. */
3570 case FFEINFO_basictypeANY:
3571 return error_mark_node;
3572 }
3573 break;
3574
3575 case FFEBLD_opOR:
3576 switch (bt)
3577 {
3578 case FFEINFO_basictypeLOGICAL:
3579 item
3580 = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
3581 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3582 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3583 return convert (tree_type, item);
3584
3585 case FFEINFO_basictypeINTEGER:
3586 return ffecom_2 (BIT_IOR_EXPR, tree_type,
3587 ffecom_expr (ffebld_left (expr)),
3588 ffecom_expr (ffebld_right (expr)));
3589
3590 default:
3591 assert ("OR bad basictype" == NULL);
3592 /* Fall through. */
3593 case FFEINFO_basictypeANY:
3594 return error_mark_node;
3595 }
3596 break;
3597
3598 case FFEBLD_opXOR:
3599 case FFEBLD_opNEQV:
3600 switch (bt)
3601 {
3602 case FFEINFO_basictypeLOGICAL:
3603 item
3604 = ffecom_2 (NE_EXPR, integer_type_node,
3605 ffecom_expr (ffebld_left (expr)),
3606 ffecom_expr (ffebld_right (expr)));
3607 return convert (tree_type, ffecom_truth_value (item));
3608
3609 case FFEINFO_basictypeINTEGER:
3610 return ffecom_2 (BIT_XOR_EXPR, tree_type,
3611 ffecom_expr (ffebld_left (expr)),
3612 ffecom_expr (ffebld_right (expr)));
3613
3614 default:
3615 assert ("XOR/NEQV bad basictype" == NULL);
3616 /* Fall through. */
3617 case FFEINFO_basictypeANY:
3618 return error_mark_node;
3619 }
3620 break;
3621
3622 case FFEBLD_opEQV:
3623 switch (bt)
3624 {
3625 case FFEINFO_basictypeLOGICAL:
3626 item
3627 = ffecom_2 (EQ_EXPR, integer_type_node,
3628 ffecom_expr (ffebld_left (expr)),
3629 ffecom_expr (ffebld_right (expr)));
3630 return convert (tree_type, ffecom_truth_value (item));
3631
3632 case FFEINFO_basictypeINTEGER:
3633 return
3634 ffecom_1 (BIT_NOT_EXPR, tree_type,
3635 ffecom_2 (BIT_XOR_EXPR, tree_type,
3636 ffecom_expr (ffebld_left (expr)),
3637 ffecom_expr (ffebld_right (expr))));
3638
3639 default:
3640 assert ("EQV bad basictype" == NULL);
3641 /* Fall through. */
3642 case FFEINFO_basictypeANY:
3643 return error_mark_node;
3644 }
3645 break;
3646
3647 case FFEBLD_opCONVERT:
3648 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opANY)
3649 return error_mark_node;
3650
3651 switch (bt)
3652 {
3653 case FFEINFO_basictypeLOGICAL:
3654 case FFEINFO_basictypeINTEGER:
3655 case FFEINFO_basictypeREAL:
3656 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3657
3658 case FFEINFO_basictypeCOMPLEX:
3659 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3660 {
3661 case FFEINFO_basictypeINTEGER:
3662 case FFEINFO_basictypeLOGICAL:
3663 case FFEINFO_basictypeREAL:
3664 item = ffecom_expr (ffebld_left (expr));
3665 if (item == error_mark_node)
3666 return error_mark_node;
3667 /* convert() takes care of converting to the subtype first,
3668 at least in gcc-2.7.2. */
3669 item = convert (tree_type, item);
3670 return item;
3671
3672 case FFEINFO_basictypeCOMPLEX:
3673 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3674
3675 default:
3676 assert ("CONVERT COMPLEX bad basictype" == NULL);
3677 /* Fall through. */
3678 case FFEINFO_basictypeANY:
3679 return error_mark_node;
3680 }
3681 break;
3682
3683 default:
3684 assert ("CONVERT bad basictype" == NULL);
3685 /* Fall through. */
3686 case FFEINFO_basictypeANY:
3687 return error_mark_node;
3688 }
3689 break;
3690
3691 case FFEBLD_opLT:
3692 code = LT_EXPR;
3693 goto relational; /* :::::::::::::::::::: */
3694
3695 case FFEBLD_opLE:
3696 code = LE_EXPR;
3697 goto relational; /* :::::::::::::::::::: */
3698
3699 case FFEBLD_opEQ:
3700 code = EQ_EXPR;
3701 goto relational; /* :::::::::::::::::::: */
3702
3703 case FFEBLD_opNE:
3704 code = NE_EXPR;
3705 goto relational; /* :::::::::::::::::::: */
3706
3707 case FFEBLD_opGT:
3708 code = GT_EXPR;
3709 goto relational; /* :::::::::::::::::::: */
3710
3711 case FFEBLD_opGE:
3712 code = GE_EXPR;
3713
3714 relational: /* :::::::::::::::::::: */
3715 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3716 {
3717 case FFEINFO_basictypeLOGICAL:
3718 case FFEINFO_basictypeINTEGER:
3719 case FFEINFO_basictypeREAL:
3720 item = ffecom_2 (code, integer_type_node,
3721 ffecom_expr (ffebld_left (expr)),
3722 ffecom_expr (ffebld_right (expr)));
3723 return convert (tree_type, item);
3724
3725 case FFEINFO_basictypeCOMPLEX:
3726 assert (code == EQ_EXPR || code == NE_EXPR);
3727 {
3728 tree real_type;
3729 tree arg1 = ffecom_expr (ffebld_left (expr));
3730 tree arg2 = ffecom_expr (ffebld_right (expr));
3731
3732 if (arg1 == error_mark_node || arg2 == error_mark_node)
3733 return error_mark_node;
3734
3735 arg1 = ffecom_save_tree (arg1);
3736 arg2 = ffecom_save_tree (arg2);
3737
3738 if (TREE_CODE (TREE_TYPE (arg1)) == COMPLEX_TYPE)
3739 {
3740 real_type = TREE_TYPE (TREE_TYPE (arg1));
3741 assert (real_type == TREE_TYPE (TREE_TYPE (arg2)));
3742 }
3743 else
3744 {
3745 real_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg1)));
3746 assert (real_type == TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg2))));
3747 }
3748
3749 item
3750 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3751 ffecom_2 (EQ_EXPR, integer_type_node,
3752 ffecom_1 (REALPART_EXPR, real_type, arg1),
3753 ffecom_1 (REALPART_EXPR, real_type, arg2)),
3754 ffecom_2 (EQ_EXPR, integer_type_node,
3755 ffecom_1 (IMAGPART_EXPR, real_type, arg1),
3756 ffecom_1 (IMAGPART_EXPR, real_type,
3757 arg2)));
3758 if (code == EQ_EXPR)
3759 item = ffecom_truth_value (item);
3760 else
3761 item = ffecom_truth_value_invert (item);
3762 return convert (tree_type, item);
3763 }
3764
3765 case FFEINFO_basictypeCHARACTER:
3766 {
3767 ffebld left = ffebld_left (expr);
3768 ffebld right = ffebld_right (expr);
3769 tree left_tree;
3770 tree right_tree;
3771 tree left_length;
3772 tree right_length;
3773
3774 /* f2c run-time functions do the implicit blank-padding for us,
3775 so we don't usually have to implement blank-padding ourselves.
3776 (The exception is when we pass an argument to a separately
3777 compiled statement function -- if we know the arg is not the
3778 same length as the dummy, we must truncate or extend it. If
3779 we "inline" statement functions, that necessity goes away as
3780 well.)
3781
3782 Strip off the CONVERT operators that blank-pad. (Truncation by
3783 CONVERT shouldn't happen here, but it can happen in
3784 assignments.) */
3785
3786 while (ffebld_op (left) == FFEBLD_opCONVERT)
3787 left = ffebld_left (left);
3788 while (ffebld_op (right) == FFEBLD_opCONVERT)
3789 right = ffebld_left (right);
3790
3791 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
3792 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
3793
3794 if (left_tree == error_mark_node || left_length == error_mark_node
3795 || right_tree == error_mark_node
3796 || right_length == error_mark_node)
3797 return error_mark_node;
3798
3799 if ((ffebld_size_known (left) == 1)
3800 && (ffebld_size_known (right) == 1))
3801 {
3802 left_tree
3803 = ffecom_1 (INDIRECT_REF,
3804 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3805 left_tree);
3806 right_tree
3807 = ffecom_1 (INDIRECT_REF,
3808 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3809 right_tree);
3810
3811 item
3812 = ffecom_2 (code, integer_type_node,
3813 ffecom_2 (ARRAY_REF,
3814 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3815 left_tree,
3816 integer_one_node),
3817 ffecom_2 (ARRAY_REF,
3818 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3819 right_tree,
3820 integer_one_node));
3821 }
3822 else
3823 {
3824 item = build_tree_list (NULL_TREE, left_tree);
3825 TREE_CHAIN (item) = build_tree_list (NULL_TREE, right_tree);
3826 TREE_CHAIN (TREE_CHAIN (item)) = build_tree_list (NULL_TREE,
3827 left_length);
3828 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
3829 = build_tree_list (NULL_TREE, right_length);
3830 item = ffecom_call_gfrt (FFECOM_gfrtCMP, item, NULL_TREE);
3831 item = ffecom_2 (code, integer_type_node,
3832 item,
3833 convert (TREE_TYPE (item),
3834 integer_zero_node));
3835 }
3836 item = convert (tree_type, item);
3837 }
3838
3839 return item;
3840
3841 default:
3842 assert ("relational bad basictype" == NULL);
3843 /* Fall through. */
3844 case FFEINFO_basictypeANY:
3845 return error_mark_node;
3846 }
3847 break;
3848
3849 case FFEBLD_opPERCENT_LOC:
3850 item = ffecom_arg_ptr_to_expr (ffebld_left (expr), &list);
3851 return convert (tree_type, item);
3852
3853 case FFEBLD_opITEM:
3854 case FFEBLD_opSTAR:
3855 case FFEBLD_opBOUNDS:
3856 case FFEBLD_opREPEAT:
3857 case FFEBLD_opLABTER:
3858 case FFEBLD_opLABTOK:
3859 case FFEBLD_opIMPDO:
3860 case FFEBLD_opCONCATENATE:
3861 case FFEBLD_opSUBSTR:
3862 default:
3863 assert ("bad op" == NULL);
3864 /* Fall through. */
3865 case FFEBLD_opANY:
3866 return error_mark_node;
3867 }
3868
3869 #if 1
3870 assert ("didn't think anything got here anymore!!" == NULL);
3871 #else
3872 switch (ffebld_arity (expr))
3873 {
3874 case 2:
3875 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3876 TREE_OPERAND (item, 1) = ffecom_expr (ffebld_right (expr));
3877 if (TREE_OPERAND (item, 0) == error_mark_node
3878 || TREE_OPERAND (item, 1) == error_mark_node)
3879 return error_mark_node;
3880 break;
3881
3882 case 1:
3883 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3884 if (TREE_OPERAND (item, 0) == error_mark_node)
3885 return error_mark_node;
3886 break;
3887
3888 default:
3889 break;
3890 }
3891
3892 return fold (item);
3893 #endif
3894 }
3895
3896 #endif
3897 /* Returns the tree that does the intrinsic invocation.
3898
3899 Note: this function applies only to intrinsics returning
3900 CHARACTER*1 or non-CHARACTER results, and to intrinsic
3901 subroutines. */
3902
3903 #if FFECOM_targetCURRENT == FFECOM_targetGCC
3904 static tree
3905 ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
3906 ffebld dest, bool *dest_used)
3907 {
3908 tree expr_tree;
3909 tree saved_expr1; /* For those who need it. */
3910 tree saved_expr2; /* For those who need it. */
3911 ffeinfoBasictype bt;
3912 ffeinfoKindtype kt;
3913 tree tree_type;
3914 tree arg1_type;
3915 tree real_type; /* REAL type corresponding to COMPLEX. */
3916 tree tempvar;
3917 ffebld list = ffebld_right (expr); /* List of (some) args. */
3918 ffebld arg1; /* For handy reference. */
3919 ffebld arg2;
3920 ffebld arg3;
3921 ffeintrinImp codegen_imp;
3922 ffecomGfrt gfrt;
3923
3924 assert (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER);
3925
3926 if (dest_used != NULL)
3927 *dest_used = FALSE;
3928
3929 bt = ffeinfo_basictype (ffebld_info (expr));
3930 kt = ffeinfo_kindtype (ffebld_info (expr));
3931 tree_type = ffecom_tree_type[bt][kt];
3932
3933 if (list != NULL)
3934 {
3935 arg1 = ffebld_head (list);
3936 if (arg1 != NULL && ffebld_op (arg1) == FFEBLD_opANY)
3937 return error_mark_node;
3938 if ((list = ffebld_trail (list)) != NULL)
3939 {
3940 arg2 = ffebld_head (list);
3941 if (arg2 != NULL && ffebld_op (arg2) == FFEBLD_opANY)
3942 return error_mark_node;
3943 if ((list = ffebld_trail (list)) != NULL)
3944 {
3945 arg3 = ffebld_head (list);
3946 if (arg3 != NULL && ffebld_op (arg3) == FFEBLD_opANY)
3947 return error_mark_node;
3948 }
3949 else
3950 arg3 = NULL;
3951 }
3952 else
3953 arg2 = arg3 = NULL;
3954 }
3955 else
3956 arg1 = arg2 = arg3 = NULL;
3957
3958 /* <list> ends up at the opITEM of the 3rd arg, or NULL if there are < 3
3959 args. This is used by the MAX/MIN expansions. */
3960
3961 if (arg1 != NULL)
3962 arg1_type = ffecom_tree_type
3963 [ffeinfo_basictype (ffebld_info (arg1))]
3964 [ffeinfo_kindtype (ffebld_info (arg1))];
3965 else
3966 arg1_type = NULL_TREE; /* Really not needed, but might catch bugs
3967 here. */
3968
3969 /* There are several ways for each of the cases in the following switch
3970 statements to exit (from simplest to use to most complicated):
3971
3972 break; (when expr_tree == NULL)
3973
3974 A standard call is made to the specific intrinsic just as if it had been
3975 passed in as a dummy procedure and called as any old procedure. This
3976 method can produce slower code but in some cases it's the easiest way for
3977 now. However, if a (presumably faster) direct call is available,
3978 that is used, so this is the easiest way in many more cases now.
3979
3980 gfrt = FFECOM_gfrtWHATEVER;
3981 break;
3982
3983 gfrt contains the gfrt index of a library function to call, passing the
3984 argument(s) by value rather than by reference. Used when a more
3985 careful choice of library function is needed than that provided
3986 by the vanilla `break;'.
3987
3988 return expr_tree;
3989
3990 The expr_tree has been completely set up and is ready to be returned
3991 as is. No further actions are taken. Use this when the tree is not
3992 in the simple form for one of the arity_n labels. */
3993
3994 /* For info on how the switch statement cases were written, see the files
3995 enclosed in comments below the switch statement. */
3996
3997 codegen_imp = ffebld_symter_implementation (ffebld_left (expr));
3998 gfrt = ffeintrin_gfrt_direct (codegen_imp);
3999 if (gfrt == FFECOM_gfrt)
4000 gfrt = ffeintrin_gfrt_indirect (codegen_imp);
4001
4002 switch (codegen_imp)
4003 {
4004 case FFEINTRIN_impABS:
4005 case FFEINTRIN_impCABS:
4006 case FFEINTRIN_impCDABS:
4007 case FFEINTRIN_impDABS:
4008 case FFEINTRIN_impIABS:
4009 if (ffeinfo_basictype (ffebld_info (arg1))
4010 == FFEINFO_basictypeCOMPLEX)
4011 {
4012 if (kt == FFEINFO_kindtypeREAL1)
4013 gfrt = FFECOM_gfrtCABS;
4014 else if (kt == FFEINFO_kindtypeREAL2)
4015 gfrt = FFECOM_gfrtCDABS;
4016 break;
4017 }
4018 return ffecom_1 (ABS_EXPR, tree_type,
4019 convert (tree_type, ffecom_expr (arg1)));
4020
4021 case FFEINTRIN_impACOS:
4022 case FFEINTRIN_impDACOS:
4023 break;
4024
4025 case FFEINTRIN_impAIMAG:
4026 case FFEINTRIN_impDIMAG:
4027 case FFEINTRIN_impIMAGPART:
4028 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4029 arg1_type = TREE_TYPE (arg1_type);
4030 else
4031 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4032
4033 return
4034 convert (tree_type,
4035 ffecom_1 (IMAGPART_EXPR, arg1_type,
4036 ffecom_expr (arg1)));
4037
4038 case FFEINTRIN_impAINT:
4039 case FFEINTRIN_impDINT:
4040 #if 0
4041 /* ~~Someday implement FIX_TRUNC_EXPR yielding same type as arg. */
4042 return ffecom_1 (FIX_TRUNC_EXPR, tree_type, ffecom_expr (arg1));
4043 #else /* in the meantime, must use floor to avoid range problems with ints */
4044 /* r__1 = r1 >= 0 ? floor(r1) : -floor(-r1); */
4045 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4046 return
4047 convert (tree_type,
4048 ffecom_3 (COND_EXPR, double_type_node,
4049 ffecom_truth_value
4050 (ffecom_2 (GE_EXPR, integer_type_node,
4051 saved_expr1,
4052 convert (arg1_type,
4053 ffecom_float_zero_))),
4054 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4055 build_tree_list (NULL_TREE,
4056 convert (double_type_node,
4057 saved_expr1)),
4058 NULL_TREE),
4059 ffecom_1 (NEGATE_EXPR, double_type_node,
4060 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4061 build_tree_list (NULL_TREE,
4062 convert (double_type_node,
4063 ffecom_1 (NEGATE_EXPR,
4064 arg1_type,
4065 saved_expr1))),
4066 NULL_TREE)
4067 ))
4068 );
4069 #endif
4070
4071 case FFEINTRIN_impANINT:
4072 case FFEINTRIN_impDNINT:
4073 #if 0 /* This way of doing it won't handle real
4074 numbers of large magnitudes. */
4075 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4076 expr_tree = convert (tree_type,
4077 convert (integer_type_node,
4078 ffecom_3 (COND_EXPR, tree_type,
4079 ffecom_truth_value
4080 (ffecom_2 (GE_EXPR,
4081 integer_type_node,
4082 saved_expr1,
4083 ffecom_float_zero_)),
4084 ffecom_2 (PLUS_EXPR,
4085 tree_type,
4086 saved_expr1,
4087 ffecom_float_half_),
4088 ffecom_2 (MINUS_EXPR,
4089 tree_type,
4090 saved_expr1,
4091 ffecom_float_half_))));
4092 return expr_tree;
4093 #else /* So we instead call floor. */
4094 /* r__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1) */
4095 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4096 return
4097 convert (tree_type,
4098 ffecom_3 (COND_EXPR, double_type_node,
4099 ffecom_truth_value
4100 (ffecom_2 (GE_EXPR, integer_type_node,
4101 saved_expr1,
4102 convert (arg1_type,
4103 ffecom_float_zero_))),
4104 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4105 build_tree_list (NULL_TREE,
4106 convert (double_type_node,
4107 ffecom_2 (PLUS_EXPR,
4108 arg1_type,
4109 saved_expr1,
4110 convert (arg1_type,
4111 ffecom_float_half_)))),
4112 NULL_TREE),
4113 ffecom_1 (NEGATE_EXPR, double_type_node,
4114 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4115 build_tree_list (NULL_TREE,
4116 convert (double_type_node,
4117 ffecom_2 (MINUS_EXPR,
4118 arg1_type,
4119 convert (arg1_type,
4120 ffecom_float_half_),
4121 saved_expr1))),
4122 NULL_TREE))
4123 )
4124 );
4125 #endif
4126
4127 case FFEINTRIN_impASIN:
4128 case FFEINTRIN_impDASIN:
4129 case FFEINTRIN_impATAN:
4130 case FFEINTRIN_impDATAN:
4131 case FFEINTRIN_impATAN2:
4132 case FFEINTRIN_impDATAN2:
4133 break;
4134
4135 case FFEINTRIN_impCHAR:
4136 case FFEINTRIN_impACHAR:
4137 #ifdef HOHO
4138 tempvar = ffecom_make_tempvar (char_type_node, 1, -1);
4139 #else
4140 tempvar = ffebld_nonter_hook (expr);
4141 assert (tempvar);
4142 #endif
4143 {
4144 tree tmv = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (tempvar)));
4145
4146 expr_tree = ffecom_modify (tmv,
4147 ffecom_2 (ARRAY_REF, tmv, tempvar,
4148 integer_one_node),
4149 convert (tmv, ffecom_expr (arg1)));
4150 }
4151 expr_tree = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar),
4152 expr_tree,
4153 tempvar);
4154 expr_tree = ffecom_1 (ADDR_EXPR,
4155 build_pointer_type (TREE_TYPE (expr_tree)),
4156 expr_tree);
4157 return expr_tree;
4158
4159 case FFEINTRIN_impCMPLX:
4160 case FFEINTRIN_impDCMPLX:
4161 if (arg2 == NULL)
4162 return
4163 convert (tree_type, ffecom_expr (arg1));
4164
4165 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4166 return
4167 ffecom_2 (COMPLEX_EXPR, tree_type,
4168 convert (real_type, ffecom_expr (arg1)),
4169 convert (real_type,
4170 ffecom_expr (arg2)));
4171
4172 case FFEINTRIN_impCOMPLEX:
4173 return
4174 ffecom_2 (COMPLEX_EXPR, tree_type,
4175 ffecom_expr (arg1),
4176 ffecom_expr (arg2));
4177
4178 case FFEINTRIN_impCONJG:
4179 case FFEINTRIN_impDCONJG:
4180 {
4181 tree arg1_tree;
4182
4183 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4184 arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4185 return
4186 ffecom_2 (COMPLEX_EXPR, tree_type,
4187 ffecom_1 (REALPART_EXPR, real_type, arg1_tree),
4188 ffecom_1 (NEGATE_EXPR, real_type,
4189 ffecom_1 (IMAGPART_EXPR, real_type, arg1_tree)));
4190 }
4191
4192 case FFEINTRIN_impCOS:
4193 case FFEINTRIN_impCCOS:
4194 case FFEINTRIN_impCDCOS:
4195 case FFEINTRIN_impDCOS:
4196 if (bt == FFEINFO_basictypeCOMPLEX)
4197 {
4198 if (kt == FFEINFO_kindtypeREAL1)
4199 gfrt = FFECOM_gfrtCCOS; /* Overlapping result okay. */
4200 else if (kt == FFEINFO_kindtypeREAL2)
4201 gfrt = FFECOM_gfrtCDCOS; /* Overlapping result okay. */
4202 }
4203 break;
4204
4205 case FFEINTRIN_impCOSH:
4206 case FFEINTRIN_impDCOSH:
4207 break;
4208
4209 case FFEINTRIN_impDBLE:
4210 case FFEINTRIN_impDFLOAT:
4211 case FFEINTRIN_impDREAL:
4212 case FFEINTRIN_impFLOAT:
4213 case FFEINTRIN_impIDINT:
4214 case FFEINTRIN_impIFIX:
4215 case FFEINTRIN_impINT2:
4216 case FFEINTRIN_impINT8:
4217 case FFEINTRIN_impINT:
4218 case FFEINTRIN_impLONG:
4219 case FFEINTRIN_impREAL:
4220 case FFEINTRIN_impSHORT:
4221 case FFEINTRIN_impSNGL:
4222 return convert (tree_type, ffecom_expr (arg1));
4223
4224 case FFEINTRIN_impDIM:
4225 case FFEINTRIN_impDDIM:
4226 case FFEINTRIN_impIDIM:
4227 saved_expr1 = ffecom_save_tree (convert (tree_type,
4228 ffecom_expr (arg1)));
4229 saved_expr2 = ffecom_save_tree (convert (tree_type,
4230 ffecom_expr (arg2)));
4231 return
4232 ffecom_3 (COND_EXPR, tree_type,
4233 ffecom_truth_value
4234 (ffecom_2 (GT_EXPR, integer_type_node,
4235 saved_expr1,
4236 saved_expr2)),
4237 ffecom_2 (MINUS_EXPR, tree_type,
4238 saved_expr1,
4239 saved_expr2),
4240 convert (tree_type, ffecom_float_zero_));
4241
4242 case FFEINTRIN_impDPROD:
4243 return
4244 ffecom_2 (MULT_EXPR, tree_type,
4245 convert (tree_type, ffecom_expr (arg1)),
4246 convert (tree_type, ffecom_expr (arg2)));
4247
4248 case FFEINTRIN_impEXP:
4249 case FFEINTRIN_impCDEXP:
4250 case FFEINTRIN_impCEXP:
4251 case FFEINTRIN_impDEXP:
4252 if (bt == FFEINFO_basictypeCOMPLEX)
4253 {
4254 if (kt == FFEINFO_kindtypeREAL1)
4255 gfrt = FFECOM_gfrtCEXP; /* Overlapping result okay. */
4256 else if (kt == FFEINFO_kindtypeREAL2)
4257 gfrt = FFECOM_gfrtCDEXP; /* Overlapping result okay. */
4258 }
4259 break;
4260
4261 case FFEINTRIN_impICHAR:
4262 case FFEINTRIN_impIACHAR:
4263 #if 0 /* The simple approach. */
4264 ffecom_char_args_ (&expr_tree, &saved_expr1 /* Ignored */ , arg1);
4265 expr_tree
4266 = ffecom_1 (INDIRECT_REF,
4267 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4268 expr_tree);
4269 expr_tree
4270 = ffecom_2 (ARRAY_REF,
4271 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4272 expr_tree,
4273 integer_one_node);
4274 return convert (tree_type, expr_tree);
4275 #else /* The more interesting (and more optimal) approach. */
4276 expr_tree = ffecom_intrinsic_ichar_ (tree_type, arg1, &saved_expr1);
4277 expr_tree = ffecom_3 (COND_EXPR, tree_type,
4278 saved_expr1,
4279 expr_tree,
4280 convert (tree_type, integer_zero_node));
4281 return expr_tree;
4282 #endif
4283
4284 case FFEINTRIN_impINDEX:
4285 break;
4286
4287 case FFEINTRIN_impLEN:
4288 #if 0
4289 break; /* The simple approach. */
4290 #else
4291 return ffecom_intrinsic_len_ (arg1); /* The more optimal approach. */
4292 #endif
4293
4294 case FFEINTRIN_impLGE:
4295 case FFEINTRIN_impLGT:
4296 case FFEINTRIN_impLLE:
4297 case FFEINTRIN_impLLT:
4298 break;
4299
4300 case FFEINTRIN_impLOG:
4301 case FFEINTRIN_impALOG:
4302 case FFEINTRIN_impCDLOG:
4303 case FFEINTRIN_impCLOG:
4304 case FFEINTRIN_impDLOG:
4305 if (bt == FFEINFO_basictypeCOMPLEX)
4306 {
4307 if (kt == FFEINFO_kindtypeREAL1)
4308 gfrt = FFECOM_gfrtCLOG; /* Overlapping result okay. */
4309 else if (kt == FFEINFO_kindtypeREAL2)
4310 gfrt = FFECOM_gfrtCDLOG; /* Overlapping result okay. */
4311 }
4312 break;
4313
4314 case FFEINTRIN_impLOG10:
4315 case FFEINTRIN_impALOG10:
4316 case FFEINTRIN_impDLOG10:
4317 if (gfrt != FFECOM_gfrt)
4318 break; /* Already picked one, stick with it. */
4319
4320 if (kt == FFEINFO_kindtypeREAL1)
4321 gfrt = FFECOM_gfrtALOG10;
4322 else if (kt == FFEINFO_kindtypeREAL2)
4323 gfrt = FFECOM_gfrtDLOG10;
4324 break;
4325
4326 case FFEINTRIN_impMAX:
4327 case FFEINTRIN_impAMAX0:
4328 case FFEINTRIN_impAMAX1:
4329 case FFEINTRIN_impDMAX1:
4330 case FFEINTRIN_impMAX0:
4331 case FFEINTRIN_impMAX1:
4332 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4333 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4334 else
4335 arg1_type = tree_type;
4336 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4337 convert (arg1_type, ffecom_expr (arg1)),
4338 convert (arg1_type, ffecom_expr (arg2)));
4339 for (; list != NULL; list = ffebld_trail (list))
4340 {
4341 if ((ffebld_head (list) == NULL)
4342 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4343 continue;
4344 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4345 expr_tree,
4346 convert (arg1_type,
4347 ffecom_expr (ffebld_head (list))));
4348 }
4349 return convert (tree_type, expr_tree);
4350
4351 case FFEINTRIN_impMIN:
4352 case FFEINTRIN_impAMIN0:
4353 case FFEINTRIN_impAMIN1:
4354 case FFEINTRIN_impDMIN1:
4355 case FFEINTRIN_impMIN0:
4356 case FFEINTRIN_impMIN1:
4357 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4358 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4359 else
4360 arg1_type = tree_type;
4361 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4362 convert (arg1_type, ffecom_expr (arg1)),
4363 convert (arg1_type, ffecom_expr (arg2)));
4364 for (; list != NULL; list = ffebld_trail (list))
4365 {
4366 if ((ffebld_head (list) == NULL)
4367 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4368 continue;
4369 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4370 expr_tree,
4371 convert (arg1_type,
4372 ffecom_expr (ffebld_head (list))));
4373 }
4374 return convert (tree_type, expr_tree);
4375
4376 case FFEINTRIN_impMOD:
4377 case FFEINTRIN_impAMOD:
4378 case FFEINTRIN_impDMOD:
4379 if (bt != FFEINFO_basictypeREAL)
4380 return ffecom_2 (TRUNC_MOD_EXPR, tree_type,
4381 convert (tree_type, ffecom_expr (arg1)),
4382 convert (tree_type, ffecom_expr (arg2)));
4383
4384 if (kt == FFEINFO_kindtypeREAL1)
4385 gfrt = FFECOM_gfrtAMOD;
4386 else if (kt == FFEINFO_kindtypeREAL2)
4387 gfrt = FFECOM_gfrtDMOD;
4388 break;
4389
4390 case FFEINTRIN_impNINT:
4391 case FFEINTRIN_impIDNINT:
4392 #if 0
4393 /* ~~Ideally FIX_ROUND_EXPR would be implemented, but it ain't yet. */
4394 return ffecom_1 (FIX_ROUND_EXPR, tree_type, ffecom_expr (arg1));
4395 #else
4396 /* i__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1); */
4397 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4398 return
4399 convert (ffecom_integer_type_node,
4400 ffecom_3 (COND_EXPR, arg1_type,
4401 ffecom_truth_value
4402 (ffecom_2 (GE_EXPR, integer_type_node,
4403 saved_expr1,
4404 convert (arg1_type,
4405 ffecom_float_zero_))),
4406 ffecom_2 (PLUS_EXPR, arg1_type,
4407 saved_expr1,
4408 convert (arg1_type,
4409 ffecom_float_half_)),
4410 ffecom_2 (MINUS_EXPR, arg1_type,
4411 saved_expr1,
4412 convert (arg1_type,
4413 ffecom_float_half_))));
4414 #endif
4415
4416 case FFEINTRIN_impSIGN:
4417 case FFEINTRIN_impDSIGN:
4418 case FFEINTRIN_impISIGN:
4419 {
4420 tree arg2_tree = ffecom_expr (arg2);
4421
4422 saved_expr1
4423 = ffecom_save_tree
4424 (ffecom_1 (ABS_EXPR, tree_type,
4425 convert (tree_type,
4426 ffecom_expr (arg1))));
4427 expr_tree
4428 = ffecom_3 (COND_EXPR, tree_type,
4429 ffecom_truth_value
4430 (ffecom_2 (GE_EXPR, integer_type_node,
4431 arg2_tree,
4432 convert (TREE_TYPE (arg2_tree),
4433 integer_zero_node))),
4434 saved_expr1,
4435 ffecom_1 (NEGATE_EXPR, tree_type, saved_expr1));
4436 /* Make sure SAVE_EXPRs get referenced early enough. */
4437 expr_tree
4438 = ffecom_2 (COMPOUND_EXPR, tree_type,
4439 convert (void_type_node, saved_expr1),
4440 expr_tree);
4441 }
4442 return expr_tree;
4443
4444 case FFEINTRIN_impSIN:
4445 case FFEINTRIN_impCDSIN:
4446 case FFEINTRIN_impCSIN:
4447 case FFEINTRIN_impDSIN:
4448 if (bt == FFEINFO_basictypeCOMPLEX)
4449 {
4450 if (kt == FFEINFO_kindtypeREAL1)
4451 gfrt = FFECOM_gfrtCSIN; /* Overlapping result okay. */
4452 else if (kt == FFEINFO_kindtypeREAL2)
4453 gfrt = FFECOM_gfrtCDSIN; /* Overlapping result okay. */
4454 }
4455 break;
4456
4457 case FFEINTRIN_impSINH:
4458 case FFEINTRIN_impDSINH:
4459 break;
4460
4461 case FFEINTRIN_impSQRT:
4462 case FFEINTRIN_impCDSQRT:
4463 case FFEINTRIN_impCSQRT:
4464 case FFEINTRIN_impDSQRT:
4465 if (bt == FFEINFO_basictypeCOMPLEX)
4466 {
4467 if (kt == FFEINFO_kindtypeREAL1)
4468 gfrt = FFECOM_gfrtCSQRT; /* Overlapping result okay. */
4469 else if (kt == FFEINFO_kindtypeREAL2)
4470 gfrt = FFECOM_gfrtCDSQRT; /* Overlapping result okay. */
4471 }
4472 break;
4473
4474 case FFEINTRIN_impTAN:
4475 case FFEINTRIN_impDTAN:
4476 case FFEINTRIN_impTANH:
4477 case FFEINTRIN_impDTANH:
4478 break;
4479
4480 case FFEINTRIN_impREALPART:
4481 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4482 arg1_type = TREE_TYPE (arg1_type);
4483 else
4484 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4485
4486 return
4487 convert (tree_type,
4488 ffecom_1 (REALPART_EXPR, arg1_type,
4489 ffecom_expr (arg1)));
4490
4491 case FFEINTRIN_impIAND:
4492 case FFEINTRIN_impAND:
4493 return ffecom_2 (BIT_AND_EXPR, tree_type,
4494 convert (tree_type,
4495 ffecom_expr (arg1)),
4496 convert (tree_type,
4497 ffecom_expr (arg2)));
4498
4499 case FFEINTRIN_impIOR:
4500 case FFEINTRIN_impOR:
4501 return ffecom_2 (BIT_IOR_EXPR, tree_type,
4502 convert (tree_type,
4503 ffecom_expr (arg1)),
4504 convert (tree_type,
4505 ffecom_expr (arg2)));
4506
4507 case FFEINTRIN_impIEOR:
4508 case FFEINTRIN_impXOR:
4509 return ffecom_2 (BIT_XOR_EXPR, tree_type,
4510 convert (tree_type,
4511 ffecom_expr (arg1)),
4512 convert (tree_type,
4513 ffecom_expr (arg2)));
4514
4515 case FFEINTRIN_impLSHIFT:
4516 return ffecom_2 (LSHIFT_EXPR, tree_type,
4517 ffecom_expr (arg1),
4518 convert (integer_type_node,
4519 ffecom_expr (arg2)));
4520
4521 case FFEINTRIN_impRSHIFT:
4522 return ffecom_2 (RSHIFT_EXPR, tree_type,
4523 ffecom_expr (arg1),
4524 convert (integer_type_node,
4525 ffecom_expr (arg2)));
4526
4527 case FFEINTRIN_impNOT:
4528 return ffecom_1 (BIT_NOT_EXPR, tree_type, ffecom_expr (arg1));
4529
4530 case FFEINTRIN_impBIT_SIZE:
4531 return convert (tree_type, TYPE_SIZE (arg1_type));
4532
4533 case FFEINTRIN_impBTEST:
4534 {
4535 ffetargetLogical1 true;
4536 ffetargetLogical1 false;
4537 tree true_tree;
4538 tree false_tree;
4539
4540 ffetarget_logical1 (&true, TRUE);
4541 ffetarget_logical1 (&false, FALSE);
4542 if (true == 1)
4543 true_tree = convert (tree_type, integer_one_node);
4544 else
4545 true_tree = convert (tree_type, build_int_2 (true, 0));
4546 if (false == 0)
4547 false_tree = convert (tree_type, integer_zero_node);
4548 else
4549 false_tree = convert (tree_type, build_int_2 (false, 0));
4550
4551 return
4552 ffecom_3 (COND_EXPR, tree_type,
4553 ffecom_truth_value
4554 (ffecom_2 (EQ_EXPR, integer_type_node,
4555 ffecom_2 (BIT_AND_EXPR, arg1_type,
4556 ffecom_expr (arg1),
4557 ffecom_2 (LSHIFT_EXPR, arg1_type,
4558 convert (arg1_type,
4559 integer_one_node),
4560 convert (integer_type_node,
4561 ffecom_expr (arg2)))),
4562 convert (arg1_type,
4563 integer_zero_node))),
4564 false_tree,
4565 true_tree);
4566 }
4567
4568 case FFEINTRIN_impIBCLR:
4569 return
4570 ffecom_2 (BIT_AND_EXPR, tree_type,
4571 ffecom_expr (arg1),
4572 ffecom_1 (BIT_NOT_EXPR, tree_type,
4573 ffecom_2 (LSHIFT_EXPR, tree_type,
4574 convert (tree_type,
4575 integer_one_node),
4576 convert (integer_type_node,
4577 ffecom_expr (arg2)))));
4578
4579 case FFEINTRIN_impIBITS:
4580 {
4581 tree arg3_tree = ffecom_save_tree (convert (integer_type_node,
4582 ffecom_expr (arg3)));
4583 tree uns_type
4584 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4585
4586 expr_tree
4587 = ffecom_2 (BIT_AND_EXPR, tree_type,
4588 ffecom_2 (RSHIFT_EXPR, tree_type,
4589 ffecom_expr (arg1),
4590 convert (integer_type_node,
4591 ffecom_expr (arg2))),
4592 convert (tree_type,
4593 ffecom_2 (RSHIFT_EXPR, uns_type,
4594 ffecom_1 (BIT_NOT_EXPR,
4595 uns_type,
4596 convert (uns_type,
4597 integer_zero_node)),
4598 ffecom_2 (MINUS_EXPR,
4599 integer_type_node,
4600 TYPE_SIZE (uns_type),
4601 arg3_tree))));
4602 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4603 expr_tree
4604 = ffecom_3 (COND_EXPR, tree_type,
4605 ffecom_truth_value
4606 (ffecom_2 (NE_EXPR, integer_type_node,
4607 arg3_tree,
4608 integer_zero_node)),
4609 expr_tree,
4610 convert (tree_type, integer_zero_node));
4611 #endif
4612 }
4613 return expr_tree;
4614
4615 case FFEINTRIN_impIBSET:
4616 return
4617 ffecom_2 (BIT_IOR_EXPR, tree_type,
4618 ffecom_expr (arg1),
4619 ffecom_2 (LSHIFT_EXPR, tree_type,
4620 convert (tree_type, integer_one_node),
4621 convert (integer_type_node,
4622 ffecom_expr (arg2))));
4623
4624 case FFEINTRIN_impISHFT:
4625 {
4626 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4627 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4628 ffecom_expr (arg2)));
4629 tree uns_type
4630 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4631
4632 expr_tree
4633 = ffecom_3 (COND_EXPR, tree_type,
4634 ffecom_truth_value
4635 (ffecom_2 (GE_EXPR, integer_type_node,
4636 arg2_tree,
4637 integer_zero_node)),
4638 ffecom_2 (LSHIFT_EXPR, tree_type,
4639 arg1_tree,
4640 arg2_tree),
4641 convert (tree_type,
4642 ffecom_2 (RSHIFT_EXPR, uns_type,
4643 convert (uns_type, arg1_tree),
4644 ffecom_1 (NEGATE_EXPR,
4645 integer_type_node,
4646 arg2_tree))));
4647 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4648 expr_tree
4649 = ffecom_3 (COND_EXPR, tree_type,
4650 ffecom_truth_value
4651 (ffecom_2 (NE_EXPR, integer_type_node,
4652 arg2_tree,
4653 TYPE_SIZE (uns_type))),
4654 expr_tree,
4655 convert (tree_type, integer_zero_node));
4656 #endif
4657 /* Make sure SAVE_EXPRs get referenced early enough. */
4658 expr_tree
4659 = ffecom_2 (COMPOUND_EXPR, tree_type,
4660 convert (void_type_node, arg1_tree),
4661 ffecom_2 (COMPOUND_EXPR, tree_type,
4662 convert (void_type_node, arg2_tree),
4663 expr_tree));
4664 }
4665 return expr_tree;
4666
4667 case FFEINTRIN_impISHFTC:
4668 {
4669 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4670 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4671 ffecom_expr (arg2)));
4672 tree arg3_tree = (arg3 == NULL) ? TYPE_SIZE (tree_type)
4673 : ffecom_save_tree (convert (integer_type_node, ffecom_expr (arg3)));
4674 tree shift_neg;
4675 tree shift_pos;
4676 tree mask_arg1;
4677 tree masked_arg1;
4678 tree uns_type
4679 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4680
4681 mask_arg1
4682 = ffecom_2 (LSHIFT_EXPR, tree_type,
4683 ffecom_1 (BIT_NOT_EXPR, tree_type,
4684 convert (tree_type, integer_zero_node)),
4685 arg3_tree);
4686 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4687 mask_arg1
4688 = ffecom_3 (COND_EXPR, tree_type,
4689 ffecom_truth_value
4690 (ffecom_2 (NE_EXPR, integer_type_node,
4691 arg3_tree,
4692 TYPE_SIZE (uns_type))),
4693 mask_arg1,
4694 convert (tree_type, integer_zero_node));
4695 #endif
4696 mask_arg1 = ffecom_save_tree (mask_arg1);
4697 masked_arg1
4698 = ffecom_2 (BIT_AND_EXPR, tree_type,
4699 arg1_tree,
4700 ffecom_1 (BIT_NOT_EXPR, tree_type,
4701 mask_arg1));
4702 masked_arg1 = ffecom_save_tree (masked_arg1);
4703 shift_neg
4704 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4705 convert (tree_type,
4706 ffecom_2 (RSHIFT_EXPR, uns_type,
4707 convert (uns_type, masked_arg1),
4708 ffecom_1 (NEGATE_EXPR,
4709 integer_type_node,
4710 arg2_tree))),
4711 ffecom_2 (LSHIFT_EXPR, tree_type,
4712 arg1_tree,
4713 ffecom_2 (PLUS_EXPR, integer_type_node,
4714 arg2_tree,
4715 arg3_tree)));
4716 shift_pos
4717 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4718 ffecom_2 (LSHIFT_EXPR, tree_type,
4719 arg1_tree,
4720 arg2_tree),
4721 convert (tree_type,
4722 ffecom_2 (RSHIFT_EXPR, uns_type,
4723 convert (uns_type, masked_arg1),
4724 ffecom_2 (MINUS_EXPR,
4725 integer_type_node,
4726 arg3_tree,
4727 arg2_tree))));
4728 expr_tree
4729 = ffecom_3 (COND_EXPR, tree_type,
4730 ffecom_truth_value
4731 (ffecom_2 (LT_EXPR, integer_type_node,
4732 arg2_tree,
4733 integer_zero_node)),
4734 shift_neg,
4735 shift_pos);
4736 expr_tree
4737 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4738 ffecom_2 (BIT_AND_EXPR, tree_type,
4739 mask_arg1,
4740 arg1_tree),
4741 ffecom_2 (BIT_AND_EXPR, tree_type,
4742 ffecom_1 (BIT_NOT_EXPR, tree_type,
4743 mask_arg1),
4744 expr_tree));
4745 expr_tree
4746 = ffecom_3 (COND_EXPR, tree_type,
4747 ffecom_truth_value
4748 (ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
4749 ffecom_2 (EQ_EXPR, integer_type_node,
4750 ffecom_1 (ABS_EXPR,
4751 integer_type_node,
4752 arg2_tree),
4753 arg3_tree),
4754 ffecom_2 (EQ_EXPR, integer_type_node,
4755 arg2_tree,
4756 integer_zero_node))),
4757 arg1_tree,
4758 expr_tree);
4759 /* Make sure SAVE_EXPRs get referenced early enough. */
4760 expr_tree
4761 = ffecom_2 (COMPOUND_EXPR, tree_type,
4762 convert (void_type_node, arg1_tree),
4763 ffecom_2 (COMPOUND_EXPR, tree_type,
4764 convert (void_type_node, arg2_tree),
4765 ffecom_2 (COMPOUND_EXPR, tree_type,
4766 convert (void_type_node,
4767 mask_arg1),
4768 ffecom_2 (COMPOUND_EXPR, tree_type,
4769 convert (void_type_node,
4770 masked_arg1),
4771 expr_tree))));
4772 expr_tree
4773 = ffecom_2 (COMPOUND_EXPR, tree_type,
4774 convert (void_type_node,
4775 arg3_tree),
4776 expr_tree);
4777 }
4778 return expr_tree;
4779
4780 case FFEINTRIN_impLOC:
4781 {
4782 tree arg1_tree = ffecom_expr (arg1);
4783
4784 expr_tree
4785 = convert (tree_type,
4786 ffecom_1 (ADDR_EXPR,
4787 build_pointer_type (TREE_TYPE (arg1_tree)),
4788 arg1_tree));
4789 }
4790 return expr_tree;
4791
4792 case FFEINTRIN_impMVBITS:
4793 {
4794 tree arg1_tree;
4795 tree arg2_tree;
4796 tree arg3_tree;
4797 ffebld arg4 = ffebld_head (ffebld_trail (list));
4798 tree arg4_tree;
4799 tree arg4_type;
4800 ffebld arg5 = ffebld_head (ffebld_trail (ffebld_trail (list)));
4801 tree arg5_tree;
4802 tree prep_arg1;
4803 tree prep_arg4;
4804 tree arg5_plus_arg3;
4805
4806 arg2_tree = convert (integer_type_node,
4807 ffecom_expr (arg2));
4808 arg3_tree = ffecom_save_tree (convert (integer_type_node,
4809 ffecom_expr (arg3)));
4810 arg4_tree = ffecom_expr_rw (NULL_TREE, arg4);
4811 arg4_type = TREE_TYPE (arg4_tree);
4812
4813 arg1_tree = ffecom_save_tree (convert (arg4_type,
4814 ffecom_expr (arg1)));
4815
4816 arg5_tree = ffecom_save_tree (convert (integer_type_node,
4817 ffecom_expr (arg5)));
4818
4819 prep_arg1
4820 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4821 ffecom_2 (BIT_AND_EXPR, arg4_type,
4822 ffecom_2 (RSHIFT_EXPR, arg4_type,
4823 arg1_tree,
4824 arg2_tree),
4825 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4826 ffecom_2 (LSHIFT_EXPR, arg4_type,
4827 ffecom_1 (BIT_NOT_EXPR,
4828 arg4_type,
4829 convert
4830 (arg4_type,
4831 integer_zero_node)),
4832 arg3_tree))),
4833 arg5_tree);
4834 arg5_plus_arg3
4835 = ffecom_save_tree (ffecom_2 (PLUS_EXPR, arg4_type,
4836 arg5_tree,
4837 arg3_tree));
4838 prep_arg4
4839 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4840 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4841 convert (arg4_type,
4842 integer_zero_node)),
4843 arg5_plus_arg3);
4844 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4845 prep_arg4
4846 = ffecom_3 (COND_EXPR, arg4_type,
4847 ffecom_truth_value
4848 (ffecom_2 (NE_EXPR, integer_type_node,
4849 arg5_plus_arg3,
4850 convert (TREE_TYPE (arg5_plus_arg3),
4851 TYPE_SIZE (arg4_type)))),
4852 prep_arg4,
4853 convert (arg4_type, integer_zero_node));
4854 #endif
4855 prep_arg4
4856 = ffecom_2 (BIT_AND_EXPR, arg4_type,
4857 arg4_tree,
4858 ffecom_2 (BIT_IOR_EXPR, arg4_type,
4859 prep_arg4,
4860 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4861 ffecom_2 (LSHIFT_EXPR, arg4_type,
4862 ffecom_1 (BIT_NOT_EXPR,
4863 arg4_type,
4864 convert
4865 (arg4_type,
4866 integer_zero_node)),
4867 arg5_tree))));
4868 prep_arg1
4869 = ffecom_2 (BIT_IOR_EXPR, arg4_type,
4870 prep_arg1,
4871 prep_arg4);
4872 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4873 prep_arg1
4874 = ffecom_3 (COND_EXPR, arg4_type,
4875 ffecom_truth_value
4876 (ffecom_2 (NE_EXPR, integer_type_node,
4877 arg3_tree,
4878 convert (TREE_TYPE (arg3_tree),
4879 integer_zero_node))),
4880 prep_arg1,
4881 arg4_tree);
4882 prep_arg1
4883 = ffecom_3 (COND_EXPR, arg4_type,
4884 ffecom_truth_value
4885 (ffecom_2 (NE_EXPR, integer_type_node,
4886 arg3_tree,
4887 convert (TREE_TYPE (arg3_tree),
4888 TYPE_SIZE (arg4_type)))),
4889 prep_arg1,
4890 arg1_tree);
4891 #endif
4892 expr_tree
4893 = ffecom_2s (MODIFY_EXPR, void_type_node,
4894 arg4_tree,
4895 prep_arg1);
4896 /* Make sure SAVE_EXPRs get referenced early enough. */
4897 expr_tree
4898 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4899 arg1_tree,
4900 ffecom_2 (COMPOUND_EXPR, void_type_node,
4901 arg3_tree,
4902 ffecom_2 (COMPOUND_EXPR, void_type_node,
4903 arg5_tree,
4904 ffecom_2 (COMPOUND_EXPR, void_type_node,
4905 arg5_plus_arg3,
4906 expr_tree))));
4907 expr_tree
4908 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4909 arg4_tree,
4910 expr_tree);
4911
4912 }
4913 return expr_tree;
4914
4915 case FFEINTRIN_impDERF:
4916 case FFEINTRIN_impERF:
4917 case FFEINTRIN_impDERFC:
4918 case FFEINTRIN_impERFC:
4919 break;
4920
4921 case FFEINTRIN_impIARGC:
4922 /* extern int xargc; i__1 = xargc - 1; */
4923 expr_tree = ffecom_2 (MINUS_EXPR, TREE_TYPE (ffecom_tree_xargc_),
4924 ffecom_tree_xargc_,
4925 convert (TREE_TYPE (ffecom_tree_xargc_),
4926 integer_one_node));
4927 return expr_tree;
4928
4929 case FFEINTRIN_impSIGNAL_func:
4930 case FFEINTRIN_impSIGNAL_subr:
4931 {
4932 tree arg1_tree;
4933 tree arg2_tree;
4934 tree arg3_tree;
4935
4936 arg1_tree = convert (ffecom_f2c_integer_type_node,
4937 ffecom_expr (arg1));
4938 arg1_tree = ffecom_1 (ADDR_EXPR,
4939 build_pointer_type (TREE_TYPE (arg1_tree)),
4940 arg1_tree);
4941
4942 /* Pass procedure as a pointer to it, anything else by value. */
4943 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4944 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4945 else
4946 arg2_tree = ffecom_ptr_to_expr (arg2);
4947 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4948 arg2_tree);
4949
4950 if (arg3 != NULL)
4951 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
4952 else
4953 arg3_tree = NULL_TREE;
4954
4955 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4956 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4957 TREE_CHAIN (arg1_tree) = arg2_tree;
4958
4959 expr_tree
4960 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4961 ffecom_gfrt_kindtype (gfrt),
4962 FALSE,
4963 ((codegen_imp == FFEINTRIN_impSIGNAL_subr) ?
4964 NULL_TREE :
4965 tree_type),
4966 arg1_tree,
4967 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4968 ffebld_nonter_hook (expr));
4969
4970 if (arg3_tree != NULL_TREE)
4971 expr_tree
4972 = ffecom_modify (NULL_TREE, arg3_tree,
4973 convert (TREE_TYPE (arg3_tree),
4974 expr_tree));
4975 }
4976 return expr_tree;
4977
4978 case FFEINTRIN_impALARM:
4979 {
4980 tree arg1_tree;
4981 tree arg2_tree;
4982 tree arg3_tree;
4983
4984 arg1_tree = convert (ffecom_f2c_integer_type_node,
4985 ffecom_expr (arg1));
4986 arg1_tree = ffecom_1 (ADDR_EXPR,
4987 build_pointer_type (TREE_TYPE (arg1_tree)),
4988 arg1_tree);
4989
4990 /* Pass procedure as a pointer to it, anything else by value. */
4991 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4992 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4993 else
4994 arg2_tree = ffecom_ptr_to_expr (arg2);
4995 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4996 arg2_tree);
4997
4998 if (arg3 != NULL)
4999 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5000 else
5001 arg3_tree = NULL_TREE;
5002
5003 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5004 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5005 TREE_CHAIN (arg1_tree) = arg2_tree;
5006
5007 expr_tree
5008 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5009 ffecom_gfrt_kindtype (gfrt),
5010 FALSE,
5011 NULL_TREE,
5012 arg1_tree,
5013 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5014 ffebld_nonter_hook (expr));
5015
5016 if (arg3_tree != NULL_TREE)
5017 expr_tree
5018 = ffecom_modify (NULL_TREE, arg3_tree,
5019 convert (TREE_TYPE (arg3_tree),
5020 expr_tree));
5021 }
5022 return expr_tree;
5023
5024 case FFEINTRIN_impCHDIR_subr:
5025 case FFEINTRIN_impFDATE_subr:
5026 case FFEINTRIN_impFGET_subr:
5027 case FFEINTRIN_impFPUT_subr:
5028 case FFEINTRIN_impGETCWD_subr:
5029 case FFEINTRIN_impHOSTNM_subr:
5030 case FFEINTRIN_impSYSTEM_subr:
5031 case FFEINTRIN_impUNLINK_subr:
5032 {
5033 tree arg1_len = integer_zero_node;
5034 tree arg1_tree;
5035 tree arg2_tree;
5036
5037 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5038
5039 if (arg2 != NULL)
5040 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
5041 else
5042 arg2_tree = NULL_TREE;
5043
5044 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5045 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5046 TREE_CHAIN (arg1_tree) = arg1_len;
5047
5048 expr_tree
5049 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5050 ffecom_gfrt_kindtype (gfrt),
5051 FALSE,
5052 NULL_TREE,
5053 arg1_tree,
5054 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5055 ffebld_nonter_hook (expr));
5056
5057 if (arg2_tree != NULL_TREE)
5058 expr_tree
5059 = ffecom_modify (NULL_TREE, arg2_tree,
5060 convert (TREE_TYPE (arg2_tree),
5061 expr_tree));
5062 }
5063 return expr_tree;
5064
5065 case FFEINTRIN_impEXIT:
5066 if (arg1 != NULL)
5067 break;
5068
5069 expr_tree = build_tree_list (NULL_TREE,
5070 ffecom_1 (ADDR_EXPR,
5071 build_pointer_type
5072 (ffecom_integer_type_node),
5073 integer_zero_node));
5074
5075 return
5076 ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5077 ffecom_gfrt_kindtype (gfrt),
5078 FALSE,
5079 void_type_node,
5080 expr_tree,
5081 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5082 ffebld_nonter_hook (expr));
5083
5084 case FFEINTRIN_impFLUSH:
5085 if (arg1 == NULL)
5086 gfrt = FFECOM_gfrtFLUSH;
5087 else
5088 gfrt = FFECOM_gfrtFLUSH1;
5089 break;
5090
5091 case FFEINTRIN_impCHMOD_subr:
5092 case FFEINTRIN_impLINK_subr:
5093 case FFEINTRIN_impRENAME_subr:
5094 case FFEINTRIN_impSYMLNK_subr:
5095 {
5096 tree arg1_len = integer_zero_node;
5097 tree arg1_tree;
5098 tree arg2_len = integer_zero_node;
5099 tree arg2_tree;
5100 tree arg3_tree;
5101
5102 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5103 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
5104 if (arg3 != NULL)
5105 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5106 else
5107 arg3_tree = NULL_TREE;
5108
5109 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5110 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5111 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5112 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5113 TREE_CHAIN (arg1_tree) = arg2_tree;
5114 TREE_CHAIN (arg2_tree) = arg1_len;
5115 TREE_CHAIN (arg1_len) = arg2_len;
5116 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5117 ffecom_gfrt_kindtype (gfrt),
5118 FALSE,
5119 NULL_TREE,
5120 arg1_tree,
5121 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5122 ffebld_nonter_hook (expr));
5123 if (arg3_tree != NULL_TREE)
5124 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5125 convert (TREE_TYPE (arg3_tree),
5126 expr_tree));
5127 }
5128 return expr_tree;
5129
5130 case FFEINTRIN_impLSTAT_subr:
5131 case FFEINTRIN_impSTAT_subr:
5132 {
5133 tree arg1_len = integer_zero_node;
5134 tree arg1_tree;
5135 tree arg2_tree;
5136 tree arg3_tree;
5137
5138 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5139
5140 arg2_tree = ffecom_ptr_to_expr (arg2);
5141
5142 if (arg3 != NULL)
5143 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5144 else
5145 arg3_tree = NULL_TREE;
5146
5147 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5148 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5149 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5150 TREE_CHAIN (arg1_tree) = arg2_tree;
5151 TREE_CHAIN (arg2_tree) = arg1_len;
5152 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5153 ffecom_gfrt_kindtype (gfrt),
5154 FALSE,
5155 NULL_TREE,
5156 arg1_tree,
5157 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5158 ffebld_nonter_hook (expr));
5159 if (arg3_tree != NULL_TREE)
5160 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5161 convert (TREE_TYPE (arg3_tree),
5162 expr_tree));
5163 }
5164 return expr_tree;
5165
5166 case FFEINTRIN_impFGETC_subr:
5167 case FFEINTRIN_impFPUTC_subr:
5168 {
5169 tree arg1_tree;
5170 tree arg2_tree;
5171 tree arg2_len = integer_zero_node;
5172 tree arg3_tree;
5173
5174 arg1_tree = convert (ffecom_f2c_integer_type_node,
5175 ffecom_expr (arg1));
5176 arg1_tree = ffecom_1 (ADDR_EXPR,
5177 build_pointer_type (TREE_TYPE (arg1_tree)),
5178 arg1_tree);
5179
5180 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
5181 if (arg3 != NULL)
5182 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5183 else
5184 arg3_tree = NULL_TREE;
5185
5186 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5187 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5188 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5189 TREE_CHAIN (arg1_tree) = arg2_tree;
5190 TREE_CHAIN (arg2_tree) = arg2_len;
5191
5192 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5193 ffecom_gfrt_kindtype (gfrt),
5194 FALSE,
5195 NULL_TREE,
5196 arg1_tree,
5197 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5198 ffebld_nonter_hook (expr));
5199 if (arg3_tree != NULL_TREE)
5200 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5201 convert (TREE_TYPE (arg3_tree),
5202 expr_tree));
5203 }
5204 return expr_tree;
5205
5206 case FFEINTRIN_impFSTAT_subr:
5207 {
5208 tree arg1_tree;
5209 tree arg2_tree;
5210 tree arg3_tree;
5211
5212 arg1_tree = convert (ffecom_f2c_integer_type_node,
5213 ffecom_expr (arg1));
5214 arg1_tree = ffecom_1 (ADDR_EXPR,
5215 build_pointer_type (TREE_TYPE (arg1_tree)),
5216 arg1_tree);
5217
5218 arg2_tree = convert (ffecom_f2c_ptr_to_integer_type_node,
5219 ffecom_ptr_to_expr (arg2));
5220
5221 if (arg3 == NULL)
5222 arg3_tree = NULL_TREE;
5223 else
5224 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5225
5226 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5227 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5228 TREE_CHAIN (arg1_tree) = arg2_tree;
5229 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5230 ffecom_gfrt_kindtype (gfrt),
5231 FALSE,
5232 NULL_TREE,
5233 arg1_tree,
5234 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5235 ffebld_nonter_hook (expr));
5236 if (arg3_tree != NULL_TREE) {
5237 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5238 convert (TREE_TYPE (arg3_tree),
5239 expr_tree));
5240 }
5241 }
5242 return expr_tree;
5243
5244 case FFEINTRIN_impKILL_subr:
5245 {
5246 tree arg1_tree;
5247 tree arg2_tree;
5248 tree arg3_tree;
5249
5250 arg1_tree = convert (ffecom_f2c_integer_type_node,
5251 ffecom_expr (arg1));
5252 arg1_tree = ffecom_1 (ADDR_EXPR,
5253 build_pointer_type (TREE_TYPE (arg1_tree)),
5254 arg1_tree);
5255
5256 arg2_tree = convert (ffecom_f2c_integer_type_node,
5257 ffecom_expr (arg2));
5258 arg2_tree = ffecom_1 (ADDR_EXPR,
5259 build_pointer_type (TREE_TYPE (arg2_tree)),
5260 arg2_tree);
5261
5262 if (arg3 == NULL)
5263 arg3_tree = NULL_TREE;
5264 else
5265 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5266
5267 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5268 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5269 TREE_CHAIN (arg1_tree) = arg2_tree;
5270 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5271 ffecom_gfrt_kindtype (gfrt),
5272 FALSE,
5273 NULL_TREE,
5274 arg1_tree,
5275 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5276 ffebld_nonter_hook (expr));
5277 if (arg3_tree != NULL_TREE) {
5278 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5279 convert (TREE_TYPE (arg3_tree),
5280 expr_tree));
5281 }
5282 }
5283 return expr_tree;
5284
5285 case FFEINTRIN_impCTIME_subr:
5286 case FFEINTRIN_impTTYNAM_subr:
5287 {
5288 tree arg1_len = integer_zero_node;
5289 tree arg1_tree;
5290 tree arg2_tree;
5291
5292 arg1_tree = ffecom_arg_ptr_to_expr (arg2, &arg1_len);
5293
5294 arg2_tree = convert (((codegen_imp == FFEINTRIN_impCTIME_subr) ?
5295 ffecom_f2c_longint_type_node :
5296 ffecom_f2c_integer_type_node),
5297 ffecom_expr (arg1));
5298 arg2_tree = ffecom_1 (ADDR_EXPR,
5299 build_pointer_type (TREE_TYPE (arg2_tree)),
5300 arg2_tree);
5301
5302 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5303 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5304 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5305 TREE_CHAIN (arg1_len) = arg2_tree;
5306 TREE_CHAIN (arg1_tree) = arg1_len;
5307
5308 expr_tree
5309 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5310 ffecom_gfrt_kindtype (gfrt),
5311 FALSE,
5312 NULL_TREE,
5313 arg1_tree,
5314 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5315 ffebld_nonter_hook (expr));
5316 TREE_SIDE_EFFECTS (expr_tree) = 1;
5317 }
5318 return expr_tree;
5319
5320 case FFEINTRIN_impIRAND:
5321 case FFEINTRIN_impRAND:
5322 /* Arg defaults to 0 (normal random case) */
5323 {
5324 tree arg1_tree;
5325
5326 if (arg1 == NULL)
5327 arg1_tree = ffecom_integer_zero_node;
5328 else
5329 arg1_tree = ffecom_expr (arg1);
5330 arg1_tree = convert (ffecom_f2c_integer_type_node,
5331 arg1_tree);
5332 arg1_tree = ffecom_1 (ADDR_EXPR,
5333 build_pointer_type (TREE_TYPE (arg1_tree)),
5334 arg1_tree);
5335 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5336
5337 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5338 ffecom_gfrt_kindtype (gfrt),
5339 FALSE,
5340 ((codegen_imp == FFEINTRIN_impIRAND) ?
5341 ffecom_f2c_integer_type_node :
5342 ffecom_f2c_real_type_node),
5343 arg1_tree,
5344 dest_tree, dest, dest_used,
5345 NULL_TREE, TRUE,
5346 ffebld_nonter_hook (expr));
5347 }
5348 return expr_tree;
5349
5350 case FFEINTRIN_impFTELL_subr:
5351 case FFEINTRIN_impUMASK_subr:
5352 {
5353 tree arg1_tree;
5354 tree arg2_tree;
5355
5356 arg1_tree = convert (ffecom_f2c_integer_type_node,
5357 ffecom_expr (arg1));
5358 arg1_tree = ffecom_1 (ADDR_EXPR,
5359 build_pointer_type (TREE_TYPE (arg1_tree)),
5360 arg1_tree);
5361
5362 if (arg2 == NULL)
5363 arg2_tree = NULL_TREE;
5364 else
5365 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
5366
5367 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5368 ffecom_gfrt_kindtype (gfrt),
5369 FALSE,
5370 NULL_TREE,
5371 build_tree_list (NULL_TREE, arg1_tree),
5372 NULL_TREE, NULL, NULL, NULL_TREE,
5373 TRUE,
5374 ffebld_nonter_hook (expr));
5375 if (arg2_tree != NULL_TREE) {
5376 expr_tree = ffecom_modify (NULL_TREE, arg2_tree,
5377 convert (TREE_TYPE (arg2_tree),
5378 expr_tree));
5379 }
5380 }
5381 return expr_tree;
5382
5383 case FFEINTRIN_impCPU_TIME:
5384 case FFEINTRIN_impSECOND_subr:
5385 {
5386 tree arg1_tree;
5387
5388 arg1_tree = ffecom_expr_w (NULL_TREE, arg1);
5389
5390 expr_tree
5391 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5392 ffecom_gfrt_kindtype (gfrt),
5393 FALSE,
5394 NULL_TREE,
5395 NULL_TREE,
5396 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5397 ffebld_nonter_hook (expr));
5398
5399 expr_tree
5400 = ffecom_modify (NULL_TREE, arg1_tree,
5401 convert (TREE_TYPE (arg1_tree),
5402 expr_tree));
5403 }
5404 return expr_tree;
5405
5406 case FFEINTRIN_impDTIME_subr:
5407 case FFEINTRIN_impETIME_subr:
5408 {
5409 tree arg1_tree;
5410 tree result_tree;
5411
5412 result_tree = ffecom_expr_w (NULL_TREE, arg2);
5413
5414 arg1_tree = ffecom_ptr_to_expr (arg1);
5415
5416 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5417 ffecom_gfrt_kindtype (gfrt),
5418 FALSE,
5419 NULL_TREE,
5420 build_tree_list (NULL_TREE, arg1_tree),
5421 NULL_TREE, NULL, NULL, NULL_TREE,
5422 TRUE,
5423 ffebld_nonter_hook (expr));
5424 expr_tree = ffecom_modify (NULL_TREE, result_tree,
5425 convert (TREE_TYPE (result_tree),
5426 expr_tree));
5427 }
5428 return expr_tree;
5429
5430 /* Straightforward calls of libf2c routines: */
5431 case FFEINTRIN_impABORT:
5432 case FFEINTRIN_impACCESS:
5433 case FFEINTRIN_impBESJ0:
5434 case FFEINTRIN_impBESJ1:
5435 case FFEINTRIN_impBESJN:
5436 case FFEINTRIN_impBESY0:
5437 case FFEINTRIN_impBESY1:
5438 case FFEINTRIN_impBESYN:
5439 case FFEINTRIN_impCHDIR_func:
5440 case FFEINTRIN_impCHMOD_func:
5441 case FFEINTRIN_impDATE:
5442 case FFEINTRIN_impDATE_AND_TIME:
5443 case FFEINTRIN_impDBESJ0:
5444 case FFEINTRIN_impDBESJ1:
5445 case FFEINTRIN_impDBESJN:
5446 case FFEINTRIN_impDBESY0:
5447 case FFEINTRIN_impDBESY1:
5448 case FFEINTRIN_impDBESYN:
5449 case FFEINTRIN_impDTIME_func:
5450 case FFEINTRIN_impETIME_func:
5451 case FFEINTRIN_impFGETC_func:
5452 case FFEINTRIN_impFGET_func:
5453 case FFEINTRIN_impFNUM:
5454 case FFEINTRIN_impFPUTC_func:
5455 case FFEINTRIN_impFPUT_func:
5456 case FFEINTRIN_impFSEEK:
5457 case FFEINTRIN_impFSTAT_func:
5458 case FFEINTRIN_impFTELL_func:
5459 case FFEINTRIN_impGERROR:
5460 case FFEINTRIN_impGETARG:
5461 case FFEINTRIN_impGETCWD_func:
5462 case FFEINTRIN_impGETENV:
5463 case FFEINTRIN_impGETGID:
5464 case FFEINTRIN_impGETLOG:
5465 case FFEINTRIN_impGETPID:
5466 case FFEINTRIN_impGETUID:
5467 case FFEINTRIN_impGMTIME:
5468 case FFEINTRIN_impHOSTNM_func:
5469 case FFEINTRIN_impIDATE_unix:
5470 case FFEINTRIN_impIDATE_vxt:
5471 case FFEINTRIN_impIERRNO:
5472 case FFEINTRIN_impISATTY:
5473 case FFEINTRIN_impITIME:
5474 case FFEINTRIN_impKILL_func:
5475 case FFEINTRIN_impLINK_func:
5476 case FFEINTRIN_impLNBLNK:
5477 case FFEINTRIN_impLSTAT_func:
5478 case FFEINTRIN_impLTIME:
5479 case FFEINTRIN_impMCLOCK8:
5480 case FFEINTRIN_impMCLOCK:
5481 case FFEINTRIN_impPERROR:
5482 case FFEINTRIN_impRENAME_func:
5483 case FFEINTRIN_impSECNDS:
5484 case FFEINTRIN_impSECOND_func:
5485 case FFEINTRIN_impSLEEP:
5486 case FFEINTRIN_impSRAND:
5487 case FFEINTRIN_impSTAT_func:
5488 case FFEINTRIN_impSYMLNK_func:
5489 case FFEINTRIN_impSYSTEM_CLOCK:
5490 case FFEINTRIN_impSYSTEM_func:
5491 case FFEINTRIN_impTIME8:
5492 case FFEINTRIN_impTIME_unix:
5493 case FFEINTRIN_impTIME_vxt:
5494 case FFEINTRIN_impUMASK_func:
5495 case FFEINTRIN_impUNLINK_func:
5496 break;
5497
5498 case FFEINTRIN_impCTIME_func: /* CHARACTER functions not handled here. */
5499 case FFEINTRIN_impFDATE_func: /* CHARACTER functions not handled here. */
5500 case FFEINTRIN_impTTYNAM_func: /* CHARACTER functions not handled here. */
5501 case FFEINTRIN_impNONE:
5502 case FFEINTRIN_imp: /* Hush up gcc warning. */
5503 fprintf (stderr, "No %s implementation.\n",
5504 ffeintrin_name_implementation (ffebld_symter_implementation (ffebld_left (expr))));
5505 assert ("unimplemented intrinsic" == NULL);
5506 return error_mark_node;
5507 }
5508
5509 assert (gfrt != FFECOM_gfrt); /* Must have an implementation! */
5510
5511 expr_tree = ffecom_arglist_expr_ (ffecom_gfrt_args_ (gfrt),
5512 ffebld_right (expr));
5513
5514 return ffecom_call_ (ffecom_gfrt_tree_ (gfrt), ffecom_gfrt_kindtype (gfrt),
5515 (ffe_is_f2c_library () && ffecom_gfrt_complex_[gfrt]),
5516 tree_type,
5517 expr_tree, dest_tree, dest, dest_used,
5518 NULL_TREE, TRUE,
5519 ffebld_nonter_hook (expr));
5520
5521 /* See bottom of this file for f2c transforms used to determine
5522 many of the above implementations. The info seems to confuse
5523 Emacs's C mode indentation, which is why it's been moved to
5524 the bottom of this source file. */
5525 }
5526
5527 #endif
5528 /* For power (exponentiation) where right-hand operand is type INTEGER,
5529 generate in-line code to do it the fast way (which, if the operand
5530 is a constant, might just mean a series of multiplies). */
5531
5532 #if FFECOM_targetCURRENT == FFECOM_targetGCC
5533 static tree
5534 ffecom_expr_power_integer_ (ffebld expr)
5535 {
5536 tree l = ffecom_expr (ffebld_left (expr));
5537 tree r = ffecom_expr (ffebld_right (expr));
5538 tree ltype = TREE_TYPE (l);
5539 tree rtype = TREE_TYPE (r);
5540 tree result = NULL_TREE;
5541
5542 if (l == error_mark_node
5543 || r == error_mark_node)
5544 return error_mark_node;
5545
5546 if (TREE_CODE (r) == INTEGER_CST)
5547 {
5548 int sgn = tree_int_cst_sgn (r);
5549
5550 if (sgn == 0)
5551 return convert (ltype, integer_one_node);
5552
5553 if ((TREE_CODE (ltype) == INTEGER_TYPE)
5554 && (sgn < 0))
5555 {
5556 /* Reciprocal of integer is either 0, -1, or 1, so after
5557 calculating that (which we leave to the back end to do
5558 or not do optimally), don't bother with any multiplying. */
5559
5560 result = ffecom_tree_divide_ (ltype,
5561 convert (ltype, integer_one_node),
5562 l,
5563 NULL_TREE, NULL, NULL, NULL_TREE);
5564 r = ffecom_1 (NEGATE_EXPR,
5565 rtype,
5566 r);
5567 if ((TREE_INT_CST_LOW (r) & 1) == 0)
5568 result = ffecom_1 (ABS_EXPR, rtype,
5569 result);
5570 }
5571
5572 /* Generate appropriate series of multiplies, preceded
5573 by divide if the exponent is negative. */
5574
5575 l = save_expr (l);
5576
5577 if (sgn < 0)
5578 {
5579 l = ffecom_tree_divide_ (ltype,
5580 convert (ltype, integer_one_node),
5581 l,
5582 NULL_TREE, NULL, NULL,
5583 ffebld_nonter_hook (expr));
5584 r = ffecom_1 (NEGATE_EXPR, rtype, r);
5585 assert (TREE_CODE (r) == INTEGER_CST);
5586
5587 if (tree_int_cst_sgn (r) < 0)
5588 { /* The "most negative" number. */
5589 r = ffecom_1 (NEGATE_EXPR, rtype,
5590 ffecom_2 (RSHIFT_EXPR, rtype,
5591 r,
5592 integer_one_node));
5593 l = save_expr (l);
5594 l = ffecom_2 (MULT_EXPR, ltype,
5595 l,
5596 l);
5597 }
5598 }
5599
5600 for (;;)
5601 {
5602 if (TREE_INT_CST_LOW (r) & 1)
5603 {
5604 if (result == NULL_TREE)
5605 result = l;
5606 else
5607 result = ffecom_2 (MULT_EXPR, ltype,
5608 result,
5609 l);
5610 }
5611
5612 r = ffecom_2 (RSHIFT_EXPR, rtype,
5613 r,
5614 integer_one_node);
5615 if (integer_zerop (r))
5616 break;
5617 assert (TREE_CODE (r) == INTEGER_CST);
5618
5619 l = save_expr (l);
5620 l = ffecom_2 (MULT_EXPR, ltype,
5621 l,
5622 l);
5623 }
5624 return result;
5625 }
5626
5627 /* Though rhs isn't a constant, in-line code cannot be expanded
5628 while transforming dummies
5629 because the back end cannot be easily convinced to generate
5630 stores (MODIFY_EXPR), handle temporaries, and so on before
5631 all the appropriate rtx's have been generated for things like
5632 dummy args referenced in rhs -- which doesn't happen until
5633 store_parm_decls() is called (expand_function_start, I believe,
5634 does the actual rtx-stuffing of PARM_DECLs).
5635
5636 So, in this case, let the caller generate the call to the
5637 run-time-library function to evaluate the power for us. */
5638
5639 if (ffecom_transform_only_dummies_)
5640 return NULL_TREE;
5641
5642 /* Right-hand operand not a constant, expand in-line code to figure
5643 out how to do the multiplies, &c.
5644
5645 The returned expression is expressed this way in GNU C, where l and
5646 r are the "inputs":
5647
5648 ({ typeof (r) rtmp = r;
5649 typeof (l) ltmp = l;
5650 typeof (l) result;
5651
5652 if (rtmp == 0)
5653 result = 1;
5654 else
5655 {
5656 if ((basetypeof (l) == basetypeof (int))
5657 && (rtmp < 0))
5658 {
5659 result = ((typeof (l)) 1) / ltmp;
5660 if ((ltmp < 0) && (((-rtmp) & 1) == 0))
5661 result = -result;
5662 }
5663 else
5664 {
5665 result = 1;
5666 if ((basetypeof (l) != basetypeof (int))
5667 && (rtmp < 0))
5668 {
5669 ltmp = ((typeof (l)) 1) / ltmp;
5670 rtmp = -rtmp;
5671 if (rtmp < 0)
5672 {
5673 rtmp = -(rtmp >> 1);
5674 ltmp *= ltmp;
5675 }
5676 }
5677 for (;;)
5678 {
5679 if (rtmp & 1)
5680 result *= ltmp;
5681 if ((rtmp >>= 1) == 0)
5682 break;
5683 ltmp *= ltmp;
5684 }
5685 }
5686 }
5687 result;
5688 })
5689
5690 Note that some of the above is compile-time collapsable, such as
5691 the first part of the if statements that checks the base type of
5692 l against int. The if statements are phrased that way to suggest
5693 an easy way to generate the if/else constructs here, knowing that
5694 the back end should (and probably does) eliminate the resulting
5695 dead code (either the int case or the non-int case), something
5696 it couldn't do without the redundant phrasing, requiring explicit
5697 dead-code elimination here, which would be kind of difficult to
5698 read. */
5699
5700 {
5701 tree rtmp;
5702 tree ltmp;
5703 tree divide;
5704 tree basetypeof_l_is_int;
5705 tree se;
5706 tree t;
5707
5708 basetypeof_l_is_int
5709 = build_int_2 ((TREE_CODE (ltype) == INTEGER_TYPE), 0);
5710
5711 se = expand_start_stmt_expr ();
5712
5713 ffecom_start_compstmt ();
5714
5715 #ifndef HAHA
5716 rtmp = ffecom_make_tempvar ("power_r", rtype,
5717 FFETARGET_charactersizeNONE, -1);
5718 ltmp = ffecom_make_tempvar ("power_l", ltype,
5719 FFETARGET_charactersizeNONE, -1);
5720 result = ffecom_make_tempvar ("power_res", ltype,
5721 FFETARGET_charactersizeNONE, -1);
5722 if (TREE_CODE (ltype) == COMPLEX_TYPE
5723 || TREE_CODE (ltype) == RECORD_TYPE)
5724 divide = ffecom_make_tempvar ("power_div", ltype,
5725 FFETARGET_charactersizeNONE, -1);
5726 else
5727 divide = NULL_TREE;
5728 #else /* HAHA */
5729 {
5730 tree hook;
5731
5732 hook = ffebld_nonter_hook (expr);
5733 assert (hook);
5734 assert (TREE_CODE (hook) == TREE_VEC);
5735 assert (TREE_VEC_LENGTH (hook) == 4);
5736 rtmp = TREE_VEC_ELT (hook, 0);
5737 ltmp = TREE_VEC_ELT (hook, 1);
5738 result = TREE_VEC_ELT (hook, 2);
5739 divide = TREE_VEC_ELT (hook, 3);
5740 if (TREE_CODE (ltype) == COMPLEX_TYPE
5741 || TREE_CODE (ltype) == RECORD_TYPE)
5742 assert (divide);
5743 else
5744 assert (! divide);
5745 }
5746 #endif /* HAHA */
5747
5748 expand_expr_stmt (ffecom_modify (void_type_node,
5749 rtmp,
5750 r));
5751 expand_expr_stmt (ffecom_modify (void_type_node,
5752 ltmp,
5753 l));
5754 expand_start_cond (ffecom_truth_value
5755 (ffecom_2 (EQ_EXPR, integer_type_node,
5756 rtmp,
5757 convert (rtype, integer_zero_node))),
5758 0);
5759 expand_expr_stmt (ffecom_modify (void_type_node,
5760 result,
5761 convert (ltype, integer_one_node)));
5762 expand_start_else ();
5763 if (! integer_zerop (basetypeof_l_is_int))
5764 {
5765 expand_start_cond (ffecom_2 (LT_EXPR, integer_type_node,
5766 rtmp,
5767 convert (rtype,
5768 integer_zero_node)),
5769 0);
5770 expand_expr_stmt (ffecom_modify (void_type_node,
5771 result,
5772 ffecom_tree_divide_
5773 (ltype,
5774 convert (ltype, integer_one_node),
5775 ltmp,
5776 NULL_TREE, NULL, NULL,
5777 divide)));
5778 expand_start_cond (ffecom_truth_value
5779 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5780 ffecom_2 (LT_EXPR, integer_type_node,
5781 ltmp,
5782 convert (ltype,
5783 integer_zero_node)),
5784 ffecom_2 (EQ_EXPR, integer_type_node,
5785 ffecom_2 (BIT_AND_EXPR,
5786 rtype,
5787 ffecom_1 (NEGATE_EXPR,
5788 rtype,
5789 rtmp),
5790 convert (rtype,
5791 integer_one_node)),
5792 convert (rtype,
5793 integer_zero_node)))),
5794 0);
5795 expand_expr_stmt (ffecom_modify (void_type_node,
5796 result,
5797 ffecom_1 (NEGATE_EXPR,
5798 ltype,
5799 result)));
5800 expand_end_cond ();
5801 expand_start_else ();
5802 }
5803 expand_expr_stmt (ffecom_modify (void_type_node,
5804 result,
5805 convert (ltype, integer_one_node)));
5806 expand_start_cond (ffecom_truth_value
5807 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5808 ffecom_truth_value_invert
5809 (basetypeof_l_is_int),
5810 ffecom_2 (LT_EXPR, integer_type_node,
5811 rtmp,
5812 convert (rtype,
5813 integer_zero_node)))),
5814 0);
5815 expand_expr_stmt (ffecom_modify (void_type_node,
5816 ltmp,
5817 ffecom_tree_divide_
5818 (ltype,
5819 convert (ltype, integer_one_node),
5820 ltmp,
5821 NULL_TREE, NULL, NULL,
5822 divide)));
5823 expand_expr_stmt (ffecom_modify (void_type_node,
5824 rtmp,
5825 ffecom_1 (NEGATE_EXPR, rtype,
5826 rtmp)));
5827 expand_start_cond (ffecom_truth_value
5828 (ffecom_2 (LT_EXPR, integer_type_node,
5829 rtmp,
5830 convert (rtype, integer_zero_node))),
5831 0);
5832 expand_expr_stmt (ffecom_modify (void_type_node,
5833 rtmp,
5834 ffecom_1 (NEGATE_EXPR, rtype,
5835 ffecom_2 (RSHIFT_EXPR,
5836 rtype,
5837 rtmp,
5838 integer_one_node))));
5839 expand_expr_stmt (ffecom_modify (void_type_node,
5840 ltmp,
5841 ffecom_2 (MULT_EXPR, ltype,
5842 ltmp,
5843 ltmp)));
5844 expand_end_cond ();
5845 expand_end_cond ();
5846 expand_start_loop (1);
5847 expand_start_cond (ffecom_truth_value
5848 (ffecom_2 (BIT_AND_EXPR, rtype,
5849 rtmp,
5850 convert (rtype, integer_one_node))),
5851 0);
5852 expand_expr_stmt (ffecom_modify (void_type_node,
5853 result,
5854 ffecom_2 (MULT_EXPR, ltype,
5855 result,
5856 ltmp)));
5857 expand_end_cond ();
5858 expand_exit_loop_if_false (NULL,
5859 ffecom_truth_value
5860 (ffecom_modify (rtype,
5861 rtmp,
5862 ffecom_2 (RSHIFT_EXPR,
5863 rtype,
5864 rtmp,
5865 integer_one_node))));
5866 expand_expr_stmt (ffecom_modify (void_type_node,
5867 ltmp,
5868 ffecom_2 (MULT_EXPR, ltype,
5869 ltmp,
5870 ltmp)));
5871 expand_end_loop ();
5872 expand_end_cond ();
5873 if (!integer_zerop (basetypeof_l_is_int))
5874 expand_end_cond ();
5875 expand_expr_stmt (result);
5876
5877 t = ffecom_end_compstmt ();
5878
5879 result = expand_end_stmt_expr (se);
5880
5881 /* This code comes from c-parse.in, after its expand_end_stmt_expr. */
5882
5883 if (TREE_CODE (t) == BLOCK)
5884 {
5885 /* Make a BIND_EXPR for the BLOCK already made. */
5886 result = build (BIND_EXPR, TREE_TYPE (result),
5887 NULL_TREE, result, t);
5888 /* Remove the block from the tree at this point.
5889 It gets put back at the proper place
5890 when the BIND_EXPR is expanded. */
5891 delete_block (t);
5892 }
5893 else
5894 result = t;
5895 }
5896
5897 return result;
5898 }
5899
5900 #endif
5901 /* ffecom_expr_transform_ -- Transform symbols in expr
5902
5903 ffebld expr; // FFE expression.
5904 ffecom_expr_transform_ (expr);
5905
5906 Recursive descent on expr while transforming any untransformed SYMTERs. */
5907
5908 #if FFECOM_targetCURRENT == FFECOM_targetGCC
5909 static void
5910 ffecom_expr_transform_ (ffebld expr)
5911 {
5912 tree t;
5913 ffesymbol s;
5914
5915 tail_recurse: /* :::::::::::::::::::: */
5916
5917 if (expr == NULL)
5918 return;
5919
5920 switch (ffebld_op (expr))
5921 {
5922 case FFEBLD_opSYMTER:
5923 s = ffebld_symter (expr);
5924 t = ffesymbol_hook (s).decl_tree;
5925 if ((t == NULL_TREE)
5926 && ((ffesymbol_kind (s) != FFEINFO_kindNONE)
5927 || ((ffesymbol_where (s) != FFEINFO_whereNONE)
5928 && (ffesymbol_where (s) != FFEINFO_whereINTRINSIC))))
5929 {
5930 s = ffecom_sym_transform_ (s);
5931 t = ffesymbol_hook (s).decl_tree; /* Sfunc expr non-dummy,
5932 DIMENSION expr? */
5933 }
5934 break; /* Ok if (t == NULL) here. */
5935
5936 case FFEBLD_opITEM:
5937 ffecom_expr_transform_ (ffebld_head (expr));
5938 expr = ffebld_trail (expr);
5939 goto tail_recurse; /* :::::::::::::::::::: */
5940
5941 default:
5942 break;
5943 }
5944
5945 switch (ffebld_arity (expr))
5946 {
5947 case 2:
5948 ffecom_expr_transform_ (ffebld_left (expr));
5949 expr = ffebld_right (expr);
5950 goto tail_recurse; /* :::::::::::::::::::: */
5951
5952 case 1:
5953 expr = ffebld_left (expr);
5954 goto tail_recurse; /* :::::::::::::::::::: */
5955
5956 default:
5957 break;
5958 }
5959
5960 return;
5961 }
5962
5963 #endif
5964 /* Make a type based on info in live f2c.h file. */
5965
5966 #if FFECOM_targetCURRENT == FFECOM_targetGCC
5967 static void
5968 ffecom_f2c_make_type_ (tree *type, int tcode, const char *name)
5969 {
5970 switch (tcode)
5971 {
5972 case FFECOM_f2ccodeCHAR:
5973 *type = make_signed_type (CHAR_TYPE_SIZE);
5974 break;
5975
5976 case FFECOM_f2ccodeSHORT:
5977 *type = make_signed_type (SHORT_TYPE_SIZE);
5978 break;
5979
5980 case FFECOM_f2ccodeINT:
5981 *type = make_signed_type (INT_TYPE_SIZE);
5982 break;
5983
5984 case FFECOM_f2ccodeLONG:
5985 *type = make_signed_type (LONG_TYPE_SIZE);
5986 break;
5987
5988 case FFECOM_f2ccodeLONGLONG:
5989 *type = make_signed_type (LONG_LONG_TYPE_SIZE);
5990 break;
5991
5992 case FFECOM_f2ccodeCHARPTR:
5993 *type = build_pointer_type (DEFAULT_SIGNED_CHAR
5994 ? signed_char_type_node
5995 : unsigned_char_type_node);
5996 break;
5997
5998 case FFECOM_f2ccodeFLOAT:
5999 *type = make_node (REAL_TYPE);
6000 TYPE_PRECISION (*type) = FLOAT_TYPE_SIZE;
6001 layout_type (*type);
6002 break;
6003
6004 case FFECOM_f2ccodeDOUBLE:
6005 *type = make_node (REAL_TYPE);
6006 TYPE_PRECISION (*type) = DOUBLE_TYPE_SIZE;
6007 layout_type (*type);
6008 break;
6009
6010 case FFECOM_f2ccodeLONGDOUBLE:
6011 *type = make_node (REAL_TYPE);
6012 TYPE_PRECISION (*type) = LONG_DOUBLE_TYPE_SIZE;
6013 layout_type (*type);
6014 break;
6015
6016 case FFECOM_f2ccodeTWOREALS:
6017 *type = ffecom_make_complex_type_ (ffecom_f2c_real_type_node);
6018 break;
6019
6020 case FFECOM_f2ccodeTWODOUBLEREALS:
6021 *type = ffecom_make_complex_type_ (ffecom_f2c_doublereal_type_node);
6022 break;
6023
6024 default:
6025 assert ("unexpected FFECOM_f2ccodeXYZZY!" == NULL);
6026 *type = error_mark_node;
6027 return;
6028 }
6029
6030 pushdecl (build_decl (TYPE_DECL,
6031 ffecom_get_invented_identifier ("__g77_f2c_%s", name),
6032 *type));
6033 }
6034
6035 #endif
6036 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6037 /* Set the f2c list-directed-I/O code for whatever (integral) type has the
6038 given size. */
6039
6040 static void
6041 ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
6042 int code)
6043 {
6044 int j;
6045 tree t;
6046
6047 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
6048 if ((t = ffecom_tree_type[bt][j]) != NULL_TREE
6049 && compare_tree_int (TYPE_SIZE (t), size) == 0)
6050 {
6051 assert (code != -1);
6052 ffecom_f2c_typecode_[bt][j] = code;
6053 code = -1;
6054 }
6055 }
6056
6057 #endif
6058 /* Finish up globals after doing all program units in file
6059
6060 Need to handle only uninitialized COMMON areas. */
6061
6062 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6063 static ffeglobal
6064 ffecom_finish_global_ (ffeglobal global)
6065 {
6066 tree cbtype;
6067 tree cbt;
6068 tree size;
6069
6070 if (ffeglobal_type (global) != FFEGLOBAL_typeCOMMON)
6071 return global;
6072
6073 if (ffeglobal_common_init (global))
6074 return global;
6075
6076 cbt = ffeglobal_hook (global);
6077 if ((cbt == NULL_TREE)
6078 || !ffeglobal_common_have_size (global))
6079 return global; /* No need to make common, never ref'd. */
6080
6081 suspend_momentary ();
6082
6083 DECL_EXTERNAL (cbt) = 0;
6084
6085 /* Give the array a size now. */
6086
6087 size = build_int_2 ((ffeglobal_common_size (global)
6088 + ffeglobal_common_pad (global)) - 1,
6089 0);
6090
6091 cbtype = TREE_TYPE (cbt);
6092 TYPE_DOMAIN (cbtype) = build_range_type (integer_type_node,
6093 integer_zero_node,
6094 size);
6095 if (!TREE_TYPE (size))
6096 TREE_TYPE (size) = TYPE_DOMAIN (cbtype);
6097 layout_type (cbtype);
6098
6099 cbt = start_decl (cbt, FALSE);
6100 assert (cbt == ffeglobal_hook (global));
6101
6102 finish_decl (cbt, NULL_TREE, FALSE);
6103
6104 return global;
6105 }
6106
6107 #endif
6108 /* Finish up any untransformed symbols. */
6109
6110 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6111 static ffesymbol
6112 ffecom_finish_symbol_transform_ (ffesymbol s)
6113 {
6114 if ((s == NULL) || (TREE_CODE (current_function_decl) == ERROR_MARK))
6115 return s;
6116
6117 /* It's easy to know to transform an untransformed symbol, to make sure
6118 we put out debugging info for it. But COMMON variables, unlike
6119 EQUIVALENCE ones, aren't given declarations in addition to the
6120 tree expressions that specify offsets, because COMMON variables
6121 can be referenced in the outer scope where only dummy arguments
6122 (PARM_DECLs) should really be seen. To be safe, just don't do any
6123 VAR_DECLs for COMMON variables when we transform them for real
6124 use, and therefore we do all the VAR_DECL creating here. */
6125
6126 if (ffesymbol_hook (s).decl_tree == NULL_TREE)
6127 {
6128 if (ffesymbol_kind (s) != FFEINFO_kindNONE
6129 || (ffesymbol_where (s) != FFEINFO_whereNONE
6130 && ffesymbol_where (s) != FFEINFO_whereINTRINSIC
6131 && ffesymbol_where (s) != FFEINFO_whereDUMMY))
6132 /* Not transformed, and not CHARACTER*(*), and not a dummy
6133 argument, which can happen only if the entry point names
6134 it "rides in on" are all invalidated for other reasons. */
6135 s = ffecom_sym_transform_ (s);
6136 }
6137
6138 if ((ffesymbol_where (s) == FFEINFO_whereCOMMON)
6139 && (ffesymbol_hook (s).decl_tree != error_mark_node))
6140 {
6141 int yes = suspend_momentary ();
6142
6143 /* This isn't working, at least for dbxout. The .s file looks
6144 okay to me (burley), but in gdb 4.9 at least, the variables
6145 appear to reside somewhere outside of the common area, so
6146 it doesn't make sense to mislead anyone by generating the info
6147 on those variables until this is fixed. NOTE: Same problem
6148 with EQUIVALENCE, sadly...see similar #if later. */
6149 ffecom_member_phase2_ (ffesymbol_storage (ffesymbol_common (s)),
6150 ffesymbol_storage (s));
6151
6152 resume_momentary (yes);
6153 }
6154
6155 return s;
6156 }
6157
6158 #endif
6159 /* Append underscore(s) to name before calling get_identifier. "us"
6160 is nonzero if the name already contains an underscore and thus
6161 needs two underscores appended. */
6162
6163 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6164 static tree
6165 ffecom_get_appended_identifier_ (char us, const char *name)
6166 {
6167 int i;
6168 char *newname;
6169 tree id;
6170
6171 newname = xmalloc ((i = strlen (name)) + 1
6172 + ffe_is_underscoring ()
6173 + us);
6174 memcpy (newname, name, i);
6175 newname[i] = '_';
6176 newname[i + us] = '_';
6177 newname[i + 1 + us] = '\0';
6178 id = get_identifier (newname);
6179
6180 free (newname);
6181
6182 return id;
6183 }
6184
6185 #endif
6186 /* Decide whether to append underscore to name before calling
6187 get_identifier. */
6188
6189 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6190 static tree
6191 ffecom_get_external_identifier_ (ffesymbol s)
6192 {
6193 char us;
6194 const char *name = ffesymbol_text (s);
6195
6196 /* If name is a built-in name, just return it as is. */
6197
6198 if (!ffe_is_underscoring ()
6199 || (strcmp (name, FFETARGET_nameBLANK_COMMON) == 0)
6200 #if FFETARGET_isENFORCED_MAIN_NAME
6201 || (strcmp (name, FFETARGET_nameENFORCED_NAME) == 0)
6202 #else
6203 || (strcmp (name, FFETARGET_nameUNNAMED_MAIN) == 0)
6204 #endif
6205 || (strcmp (name, FFETARGET_nameUNNAMED_BLOCK_DATA) == 0))
6206 return get_identifier (name);
6207
6208 us = ffe_is_second_underscore ()
6209 ? (strchr (name, '_') != NULL)
6210 : 0;
6211
6212 return ffecom_get_appended_identifier_ (us, name);
6213 }
6214
6215 #endif
6216 /* Decide whether to append underscore to internal name before calling
6217 get_identifier.
6218
6219 This is for non-external, top-function-context names only. Transform
6220 identifier so it doesn't conflict with the transformed result
6221 of using a _different_ external name. E.g. if "CALL FOO" is
6222 transformed into "FOO_();", then the variable in "FOO_ = 3"
6223 must be transformed into something that does not conflict, since
6224 these two things should be independent.
6225
6226 The transformation is as follows. If the name does not contain
6227 an underscore, there is no possible conflict, so just return.
6228 If the name does contain an underscore, then transform it just
6229 like we transform an external identifier. */
6230
6231 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6232 static tree
6233 ffecom_get_identifier_ (const char *name)
6234 {
6235 /* If name does not contain an underscore, just return it as is. */
6236
6237 if (!ffe_is_underscoring ()
6238 || (strchr (name, '_') == NULL))
6239 return get_identifier (name);
6240
6241 return ffecom_get_appended_identifier_ (ffe_is_second_underscore (),
6242 name);
6243 }
6244
6245 #endif
6246 /* ffecom_gen_sfuncdef_ -- Generate definition of statement function
6247
6248 tree t;
6249 ffesymbol s; // kindFUNCTION, whereIMMEDIATE.
6250 t = ffecom_gen_sfuncdef_(s,ffesymbol_basictype(s),
6251 ffesymbol_kindtype(s));
6252
6253 Call after setting up containing function and getting trees for all
6254 other symbols. */
6255
6256 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6257 static tree
6258 ffecom_gen_sfuncdef_ (ffesymbol s, ffeinfoBasictype bt, ffeinfoKindtype kt)
6259 {
6260 ffebld expr = ffesymbol_sfexpr (s);
6261 tree type;
6262 tree func;
6263 tree result;
6264 bool charfunc = (bt == FFEINFO_basictypeCHARACTER);
6265 static bool recurse = FALSE;
6266 int yes;
6267 int old_lineno = lineno;
6268 const char *old_input_filename = input_filename;
6269
6270 ffecom_nested_entry_ = s;
6271
6272 /* For now, we don't have a handy pointer to where the sfunc is actually
6273 defined, though that should be easy to add to an ffesymbol. (The
6274 token/where info available might well point to the place where the type
6275 of the sfunc is declared, especially if that precedes the place where
6276 the sfunc itself is defined, which is typically the case.) We should
6277 put out a null pointer rather than point somewhere wrong, but I want to
6278 see how it works at this point. */
6279
6280 input_filename = ffesymbol_where_filename (s);
6281 lineno = ffesymbol_where_filelinenum (s);
6282
6283 /* Pretransform the expression so any newly discovered things belong to the
6284 outer program unit, not to the statement function. */
6285
6286 ffecom_expr_transform_ (expr);
6287
6288 /* Make sure no recursive invocation of this fn (a specific case of failing
6289 to pretransform an sfunc's expression, i.e. where its expression
6290 references another untransformed sfunc) happens. */
6291
6292 assert (!recurse);
6293 recurse = TRUE;
6294
6295 yes = suspend_momentary ();
6296
6297 push_f_function_context ();
6298
6299 if (charfunc)
6300 type = void_type_node;
6301 else
6302 {
6303 type = ffecom_tree_type[bt][kt];
6304 if (type == NULL_TREE)
6305 type = integer_type_node; /* _sym_exec_transition reports
6306 error. */
6307 }
6308
6309 start_function (ffecom_get_identifier_ (ffesymbol_text (s)),
6310 build_function_type (type, NULL_TREE),
6311 1, /* nested/inline */
6312 0); /* TREE_PUBLIC */
6313
6314 /* We don't worry about COMPLEX return values here, because this is
6315 entirely internal to our code, and gcc has the ability to return COMPLEX
6316 directly as a value. */
6317
6318 yes = suspend_momentary ();
6319
6320 if (charfunc)
6321 { /* Prepend arg for where result goes. */
6322 tree type;
6323
6324 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
6325
6326 result = ffecom_get_invented_identifier ("__g77_%s", "result");
6327
6328 ffecom_char_enhance_arg_ (&type, s); /* Ignore returned length. */
6329
6330 type = build_pointer_type (type);
6331 result = build_decl (PARM_DECL, result, type);
6332
6333 push_parm_decl (result);
6334 }
6335 else
6336 result = NULL_TREE; /* Not ref'd if !charfunc. */
6337
6338 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (s), TRUE);
6339
6340 resume_momentary (yes);
6341
6342 store_parm_decls (0);
6343
6344 ffecom_start_compstmt ();
6345
6346 if (expr != NULL)
6347 {
6348 if (charfunc)
6349 {
6350 ffetargetCharacterSize sz = ffesymbol_size (s);
6351 tree result_length;
6352
6353 result_length = build_int_2 (sz, 0);
6354 TREE_TYPE (result_length) = ffecom_f2c_ftnlen_type_node;
6355
6356 ffecom_prepare_let_char_ (sz, expr);
6357
6358 ffecom_prepare_end ();
6359
6360 ffecom_let_char_ (result, result_length, sz, expr);
6361 expand_null_return ();
6362 }
6363 else
6364 {
6365 ffecom_prepare_expr (expr);
6366
6367 ffecom_prepare_end ();
6368
6369 expand_return (ffecom_modify (NULL_TREE,
6370 DECL_RESULT (current_function_decl),
6371 ffecom_expr (expr)));
6372 }
6373
6374 clear_momentary ();
6375 }
6376
6377 ffecom_end_compstmt ();
6378
6379 func = current_function_decl;
6380 finish_function (1);
6381
6382 pop_f_function_context ();
6383
6384 resume_momentary (yes);
6385
6386 recurse = FALSE;
6387
6388 lineno = old_lineno;
6389 input_filename = old_input_filename;
6390
6391 ffecom_nested_entry_ = NULL;
6392
6393 return func;
6394 }
6395
6396 #endif
6397
6398 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6399 static const char *
6400 ffecom_gfrt_args_ (ffecomGfrt ix)
6401 {
6402 return ffecom_gfrt_argstring_[ix];
6403 }
6404
6405 #endif
6406 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6407 static tree
6408 ffecom_gfrt_tree_ (ffecomGfrt ix)
6409 {
6410 if (ffecom_gfrt_[ix] == NULL_TREE)
6411 ffecom_make_gfrt_ (ix);
6412
6413 return ffecom_1 (ADDR_EXPR,
6414 build_pointer_type (TREE_TYPE (ffecom_gfrt_[ix])),
6415 ffecom_gfrt_[ix]);
6416 }
6417
6418 #endif
6419 /* Return initialize-to-zero expression for this VAR_DECL. */
6420
6421 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6422 /* A somewhat evil way to prevent the garbage collector
6423 from collecting 'tree' structures. */
6424 #define NUM_TRACKED_CHUNK 63
6425 static struct tree_ggc_tracker
6426 {
6427 struct tree_ggc_tracker *next;
6428 tree trees[NUM_TRACKED_CHUNK];
6429 } *tracker_head = NULL;
6430
6431 static void
6432 mark_tracker_head (void *arg)
6433 {
6434 struct tree_ggc_tracker *head;
6435 int i;
6436
6437 for (head = * (struct tree_ggc_tracker **) arg;
6438 head != NULL;
6439 head = head->next)
6440 {
6441 ggc_mark (head);
6442 for (i = 0; i < NUM_TRACKED_CHUNK; i++)
6443 ggc_mark_tree (head->trees[i]);
6444 }
6445 }
6446
6447 void
6448 ffecom_save_tree_forever (tree t)
6449 {
6450 int i;
6451 if (tracker_head != NULL)
6452 for (i = 0; i < NUM_TRACKED_CHUNK; i++)
6453 if (tracker_head->trees[i] == NULL)
6454 {
6455 tracker_head->trees[i] = t;
6456 return;
6457 }
6458
6459 {
6460 /* Need to allocate a new block. */
6461 struct tree_ggc_tracker *old_head = tracker_head;
6462
6463 tracker_head = ggc_alloc (sizeof (*tracker_head));
6464 tracker_head->next = old_head;
6465 tracker_head->trees[0] = t;
6466 for (i = 1; i < NUM_TRACKED_CHUNK; i++)
6467 tracker_head->trees[i] = NULL;
6468 }
6469 }
6470
6471 static tree
6472 ffecom_init_zero_ (tree decl)
6473 {
6474 tree init;
6475 int incremental = TREE_STATIC (decl);
6476 tree type = TREE_TYPE (decl);
6477
6478 if (incremental)
6479 {
6480 make_decl_rtl (decl, NULL, TREE_PUBLIC (decl) ? 1 : 0);
6481 assemble_variable (decl, TREE_PUBLIC (decl) ? 1 : 0, 0, 1);
6482 }
6483
6484 push_momentary ();
6485
6486 if ((TREE_CODE (type) != ARRAY_TYPE)
6487 && (TREE_CODE (type) != RECORD_TYPE)
6488 && (TREE_CODE (type) != UNION_TYPE)
6489 && !incremental)
6490 init = convert (type, integer_zero_node);
6491 else if (!incremental)
6492 {
6493 int momentary = suspend_momentary ();
6494
6495 init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
6496 TREE_CONSTANT (init) = 1;
6497 TREE_STATIC (init) = 1;
6498
6499 resume_momentary (momentary);
6500 }
6501 else
6502 {
6503 int momentary = suspend_momentary ();
6504
6505 assemble_zeros (int_size_in_bytes (type));
6506 init = error_mark_node;
6507
6508 resume_momentary (momentary);
6509 }
6510
6511 pop_momentary_nofree ();
6512
6513 return init;
6514 }
6515
6516 #endif
6517 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6518 static tree
6519 ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
6520 tree *maybe_tree)
6521 {
6522 tree expr_tree;
6523 tree length_tree;
6524
6525 switch (ffebld_op (arg))
6526 {
6527 case FFEBLD_opCONTER: /* For F90, check 0-length. */
6528 if (ffetarget_length_character1
6529 (ffebld_constant_character1
6530 (ffebld_conter (arg))) == 0)
6531 {
6532 *maybe_tree = integer_zero_node;
6533 return convert (tree_type, integer_zero_node);
6534 }
6535
6536 *maybe_tree = integer_one_node;
6537 expr_tree = build_int_2 (*ffetarget_text_character1
6538 (ffebld_constant_character1
6539 (ffebld_conter (arg))),
6540 0);
6541 TREE_TYPE (expr_tree) = tree_type;
6542 return expr_tree;
6543
6544 case FFEBLD_opSYMTER:
6545 case FFEBLD_opARRAYREF:
6546 case FFEBLD_opFUNCREF:
6547 case FFEBLD_opSUBSTR:
6548 ffecom_char_args_ (&expr_tree, &length_tree, arg);
6549
6550 if ((expr_tree == error_mark_node)
6551 || (length_tree == error_mark_node))
6552 {
6553 *maybe_tree = error_mark_node;
6554 return error_mark_node;
6555 }
6556
6557 if (integer_zerop (length_tree))
6558 {
6559 *maybe_tree = integer_zero_node;
6560 return convert (tree_type, integer_zero_node);
6561 }
6562
6563 expr_tree
6564 = ffecom_1 (INDIRECT_REF,
6565 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6566 expr_tree);
6567 expr_tree
6568 = ffecom_2 (ARRAY_REF,
6569 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6570 expr_tree,
6571 integer_one_node);
6572 expr_tree = convert (tree_type, expr_tree);
6573
6574 if (TREE_CODE (length_tree) == INTEGER_CST)
6575 *maybe_tree = integer_one_node;
6576 else /* Must check length at run time. */
6577 *maybe_tree
6578 = ffecom_truth_value
6579 (ffecom_2 (GT_EXPR, integer_type_node,
6580 length_tree,
6581 ffecom_f2c_ftnlen_zero_node));
6582 return expr_tree;
6583
6584 case FFEBLD_opPAREN:
6585 case FFEBLD_opCONVERT:
6586 if (ffeinfo_size (ffebld_info (arg)) == 0)
6587 {
6588 *maybe_tree = integer_zero_node;
6589 return convert (tree_type, integer_zero_node);
6590 }
6591 return ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6592 maybe_tree);
6593
6594 case FFEBLD_opCONCATENATE:
6595 {
6596 tree maybe_left;
6597 tree maybe_right;
6598 tree expr_left;
6599 tree expr_right;
6600
6601 expr_left = ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6602 &maybe_left);
6603 expr_right = ffecom_intrinsic_ichar_ (tree_type, ffebld_right (arg),
6604 &maybe_right);
6605 *maybe_tree = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
6606 maybe_left,
6607 maybe_right);
6608 expr_tree = ffecom_3 (COND_EXPR, tree_type,
6609 maybe_left,
6610 expr_left,
6611 expr_right);
6612 return expr_tree;
6613 }
6614
6615 default:
6616 assert ("bad op in ICHAR" == NULL);
6617 return error_mark_node;
6618 }
6619 }
6620
6621 #endif
6622 /* ffecom_intrinsic_len_ -- Return length info for char arg (LEN())
6623
6624 tree length_arg;
6625 ffebld expr;
6626 length_arg = ffecom_intrinsic_len_ (expr);
6627
6628 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
6629 subexpressions by constructing the appropriate tree for the
6630 length-of-character-text argument in a calling sequence. */
6631
6632 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6633 static tree
6634 ffecom_intrinsic_len_ (ffebld expr)
6635 {
6636 ffetargetCharacter1 val;
6637 tree length;
6638
6639 switch (ffebld_op (expr))
6640 {
6641 case FFEBLD_opCONTER:
6642 val = ffebld_constant_character1 (ffebld_conter (expr));
6643 length = build_int_2 (ffetarget_length_character1 (val), 0);
6644 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6645 break;
6646
6647 case FFEBLD_opSYMTER:
6648 {
6649 ffesymbol s = ffebld_symter (expr);
6650 tree item;
6651
6652 item = ffesymbol_hook (s).decl_tree;
6653 if (item == NULL_TREE)
6654 {
6655 s = ffecom_sym_transform_ (s);
6656 item = ffesymbol_hook (s).decl_tree;
6657 }
6658 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
6659 {
6660 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
6661 length = ffesymbol_hook (s).length_tree;
6662 else
6663 {
6664 length = build_int_2 (ffesymbol_size (s), 0);
6665 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6666 }
6667 }
6668 else if (item == error_mark_node)
6669 length = error_mark_node;
6670 else /* FFEINFO_kindFUNCTION: */
6671 length = NULL_TREE;
6672 }
6673 break;
6674
6675 case FFEBLD_opARRAYREF:
6676 length = ffecom_intrinsic_len_ (ffebld_left (expr));
6677 break;
6678
6679 case FFEBLD_opSUBSTR:
6680 {
6681 ffebld start;
6682 ffebld end;
6683 ffebld thing = ffebld_right (expr);
6684 tree start_tree;
6685 tree end_tree;
6686
6687 assert (ffebld_op (thing) == FFEBLD_opITEM);
6688 start = ffebld_head (thing);
6689 thing = ffebld_trail (thing);
6690 assert (ffebld_trail (thing) == NULL);
6691 end = ffebld_head (thing);
6692
6693 length = ffecom_intrinsic_len_ (ffebld_left (expr));
6694
6695 if (length == error_mark_node)
6696 break;
6697
6698 if (start == NULL)
6699 {
6700 if (end == NULL)
6701 ;
6702 else
6703 {
6704 length = convert (ffecom_f2c_ftnlen_type_node,
6705 ffecom_expr (end));
6706 }
6707 }
6708 else
6709 {
6710 start_tree = convert (ffecom_f2c_ftnlen_type_node,
6711 ffecom_expr (start));
6712
6713 if (start_tree == error_mark_node)
6714 {
6715 length = error_mark_node;
6716 break;
6717 }
6718
6719 if (end == NULL)
6720 {
6721 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6722 ffecom_f2c_ftnlen_one_node,
6723 ffecom_2 (MINUS_EXPR,
6724 ffecom_f2c_ftnlen_type_node,
6725 length,
6726 start_tree));
6727 }
6728 else
6729 {
6730 end_tree = convert (ffecom_f2c_ftnlen_type_node,
6731 ffecom_expr (end));
6732
6733 if (end_tree == error_mark_node)
6734 {
6735 length = error_mark_node;
6736 break;
6737 }
6738
6739 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6740 ffecom_f2c_ftnlen_one_node,
6741 ffecom_2 (MINUS_EXPR,
6742 ffecom_f2c_ftnlen_type_node,
6743 end_tree, start_tree));
6744 }
6745 }
6746 }
6747 break;
6748
6749 case FFEBLD_opCONCATENATE:
6750 length
6751 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6752 ffecom_intrinsic_len_ (ffebld_left (expr)),
6753 ffecom_intrinsic_len_ (ffebld_right (expr)));
6754 break;
6755
6756 case FFEBLD_opFUNCREF:
6757 case FFEBLD_opCONVERT:
6758 length = build_int_2 (ffebld_size (expr), 0);
6759 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6760 break;
6761
6762 default:
6763 assert ("bad op for single char arg expr" == NULL);
6764 length = ffecom_f2c_ftnlen_zero_node;
6765 break;
6766 }
6767
6768 assert (length != NULL_TREE);
6769
6770 return length;
6771 }
6772
6773 #endif
6774 /* Handle CHARACTER assignments.
6775
6776 Generates code to do the assignment. Used by ordinary assignment
6777 statement handler ffecom_let_stmt and by statement-function
6778 handler to generate code for a statement function. */
6779
6780 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6781 static void
6782 ffecom_let_char_ (tree dest_tree, tree dest_length,
6783 ffetargetCharacterSize dest_size, ffebld source)
6784 {
6785 ffecomConcatList_ catlist;
6786 tree source_length;
6787 tree source_tree;
6788 tree expr_tree;
6789
6790 if ((dest_tree == error_mark_node)
6791 || (dest_length == error_mark_node))
6792 return;
6793
6794 assert (dest_tree != NULL_TREE);
6795 assert (dest_length != NULL_TREE);
6796
6797 /* Source might be an opCONVERT, which just means it is a different size
6798 than the destination. Since the underlying implementation here handles
6799 that (directly or via the s_copy or s_cat run-time-library functions),
6800 we don't need the "convenience" of an opCONVERT that tells us to
6801 truncate or blank-pad, particularly since the resulting implementation
6802 would probably be slower than otherwise. */
6803
6804 while (ffebld_op (source) == FFEBLD_opCONVERT)
6805 source = ffebld_left (source);
6806
6807 catlist = ffecom_concat_list_new_ (source, dest_size);
6808 switch (ffecom_concat_list_count_ (catlist))
6809 {
6810 case 0: /* Shouldn't happen, but in case it does... */
6811 ffecom_concat_list_kill_ (catlist);
6812 source_tree = null_pointer_node;
6813 source_length = ffecom_f2c_ftnlen_zero_node;
6814 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6815 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6816 TREE_CHAIN (TREE_CHAIN (expr_tree))
6817 = build_tree_list (NULL_TREE, dest_length);
6818 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6819 = build_tree_list (NULL_TREE, source_length);
6820
6821 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6822 TREE_SIDE_EFFECTS (expr_tree) = 1;
6823
6824 expand_expr_stmt (expr_tree);
6825
6826 return;
6827
6828 case 1: /* The (fairly) easy case. */
6829 ffecom_char_args_ (&source_tree, &source_length,
6830 ffecom_concat_list_expr_ (catlist, 0));
6831 ffecom_concat_list_kill_ (catlist);
6832 assert (source_tree != NULL_TREE);
6833 assert (source_length != NULL_TREE);
6834
6835 if ((source_tree == error_mark_node)
6836 || (source_length == error_mark_node))
6837 return;
6838
6839 if (dest_size == 1)
6840 {
6841 dest_tree
6842 = ffecom_1 (INDIRECT_REF,
6843 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6844 (dest_tree))),
6845 dest_tree);
6846 dest_tree
6847 = ffecom_2 (ARRAY_REF,
6848 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6849 (dest_tree))),
6850 dest_tree,
6851 integer_one_node);
6852 source_tree
6853 = ffecom_1 (INDIRECT_REF,
6854 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6855 (source_tree))),
6856 source_tree);
6857 source_tree
6858 = ffecom_2 (ARRAY_REF,
6859 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6860 (source_tree))),
6861 source_tree,
6862 integer_one_node);
6863
6864 expr_tree = ffecom_modify (void_type_node, dest_tree, source_tree);
6865
6866 expand_expr_stmt (expr_tree);
6867
6868 return;
6869 }
6870
6871 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6872 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6873 TREE_CHAIN (TREE_CHAIN (expr_tree))
6874 = build_tree_list (NULL_TREE, dest_length);
6875 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6876 = build_tree_list (NULL_TREE, source_length);
6877
6878 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6879 TREE_SIDE_EFFECTS (expr_tree) = 1;
6880
6881 expand_expr_stmt (expr_tree);
6882
6883 return;
6884
6885 default: /* Must actually concatenate things. */
6886 break;
6887 }
6888
6889 /* Heavy-duty concatenation. */
6890
6891 {
6892 int count = ffecom_concat_list_count_ (catlist);
6893 int i;
6894 tree lengths;
6895 tree items;
6896 tree length_array;
6897 tree item_array;
6898 tree citem;
6899 tree clength;
6900
6901 #ifdef HOHO
6902 length_array
6903 = lengths
6904 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
6905 FFETARGET_charactersizeNONE, count, TRUE);
6906 item_array = items = ffecom_push_tempvar (ffecom_f2c_address_type_node,
6907 FFETARGET_charactersizeNONE,
6908 count, TRUE);
6909 #else
6910 {
6911 tree hook;
6912
6913 hook = ffebld_nonter_hook (source);
6914 assert (hook);
6915 assert (TREE_CODE (hook) == TREE_VEC);
6916 assert (TREE_VEC_LENGTH (hook) == 2);
6917 length_array = lengths = TREE_VEC_ELT (hook, 0);
6918 item_array = items = TREE_VEC_ELT (hook, 1);
6919 }
6920 #endif
6921
6922 for (i = 0; i < count; ++i)
6923 {
6924 ffecom_char_args_ (&citem, &clength,
6925 ffecom_concat_list_expr_ (catlist, i));
6926 if ((citem == error_mark_node)
6927 || (clength == error_mark_node))
6928 {
6929 ffecom_concat_list_kill_ (catlist);
6930 return;
6931 }
6932
6933 items
6934 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
6935 ffecom_modify (void_type_node,
6936 ffecom_2 (ARRAY_REF,
6937 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
6938 item_array,
6939 build_int_2 (i, 0)),
6940 citem),
6941 items);
6942 lengths
6943 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
6944 ffecom_modify (void_type_node,
6945 ffecom_2 (ARRAY_REF,
6946 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
6947 length_array,
6948 build_int_2 (i, 0)),
6949 clength),
6950 lengths);
6951 }
6952
6953 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6954 TREE_CHAIN (expr_tree)
6955 = build_tree_list (NULL_TREE,
6956 ffecom_1 (ADDR_EXPR,
6957 build_pointer_type (TREE_TYPE (items)),
6958 items));
6959 TREE_CHAIN (TREE_CHAIN (expr_tree))
6960 = build_tree_list (NULL_TREE,
6961 ffecom_1 (ADDR_EXPR,
6962 build_pointer_type (TREE_TYPE (lengths)),
6963 lengths));
6964 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6965 = build_tree_list
6966 (NULL_TREE,
6967 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
6968 convert (ffecom_f2c_ftnlen_type_node,
6969 build_int_2 (count, 0))));
6970 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree))))
6971 = build_tree_list (NULL_TREE, dest_length);
6972
6973 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCAT, expr_tree, NULL_TREE);
6974 TREE_SIDE_EFFECTS (expr_tree) = 1;
6975
6976 expand_expr_stmt (expr_tree);
6977 }
6978
6979 ffecom_concat_list_kill_ (catlist);
6980 }
6981
6982 #endif
6983 /* ffecom_make_gfrt_ -- Make initial info for run-time routine
6984
6985 ffecomGfrt ix;
6986 ffecom_make_gfrt_(ix);
6987
6988 Assumes gfrt_[ix] is NULL_TREE, and replaces it with the FUNCTION_DECL
6989 for the indicated run-time routine (ix). */
6990
6991 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6992 static void
6993 ffecom_make_gfrt_ (ffecomGfrt ix)
6994 {
6995 tree t;
6996 tree ttype;
6997
6998 switch (ffecom_gfrt_type_[ix])
6999 {
7000 case FFECOM_rttypeVOID_:
7001 ttype = void_type_node;
7002 break;
7003
7004 case FFECOM_rttypeVOIDSTAR_:
7005 ttype = TREE_TYPE (null_pointer_node); /* `void *'. */
7006 break;
7007
7008 case FFECOM_rttypeFTNINT_:
7009 ttype = ffecom_f2c_ftnint_type_node;
7010 break;
7011
7012 case FFECOM_rttypeINTEGER_:
7013 ttype = ffecom_f2c_integer_type_node;
7014 break;
7015
7016 case FFECOM_rttypeLONGINT_:
7017 ttype = ffecom_f2c_longint_type_node;
7018 break;
7019
7020 case FFECOM_rttypeLOGICAL_:
7021 ttype = ffecom_f2c_logical_type_node;
7022 break;
7023
7024 case FFECOM_rttypeREAL_F2C_:
7025 ttype = double_type_node;
7026 break;
7027
7028 case FFECOM_rttypeREAL_GNU_:
7029 ttype = float_type_node;
7030 break;
7031
7032 case FFECOM_rttypeCOMPLEX_F2C_:
7033 ttype = void_type_node;
7034 break;
7035
7036 case FFECOM_rttypeCOMPLEX_GNU_:
7037 ttype = ffecom_f2c_complex_type_node;
7038 break;
7039
7040 case FFECOM_rttypeDOUBLE_:
7041 ttype = double_type_node;
7042 break;
7043
7044 case FFECOM_rttypeDOUBLEREAL_:
7045 ttype = ffecom_f2c_doublereal_type_node;
7046 break;
7047
7048 case FFECOM_rttypeDBLCMPLX_F2C_:
7049 ttype = void_type_node;
7050 break;
7051
7052 case FFECOM_rttypeDBLCMPLX_GNU_:
7053 ttype = ffecom_f2c_doublecomplex_type_node;
7054 break;
7055
7056 case FFECOM_rttypeCHARACTER_:
7057 ttype = void_type_node;
7058 break;
7059
7060 default:
7061 ttype = NULL;
7062 assert ("bad rttype" == NULL);
7063 break;
7064 }
7065
7066 ttype = build_function_type (ttype, NULL_TREE);
7067 t = build_decl (FUNCTION_DECL,
7068 get_identifier (ffecom_gfrt_name_[ix]),
7069 ttype);
7070 DECL_EXTERNAL (t) = 1;
7071 TREE_PUBLIC (t) = 1;
7072 TREE_THIS_VOLATILE (t) = ffecom_gfrt_volatile_[ix] ? 1 : 0;
7073
7074 t = start_decl (t, TRUE);
7075
7076 finish_decl (t, NULL_TREE, TRUE);
7077
7078 ffecom_gfrt_[ix] = t;
7079 }
7080
7081 #endif
7082 /* Phase 1 pass over each member of a COMMON/EQUIVALENCE group. */
7083
7084 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7085 static void
7086 ffecom_member_phase1_ (ffestorag mst UNUSED, ffestorag st)
7087 {
7088 ffesymbol s = ffestorag_symbol (st);
7089
7090 if (ffesymbol_namelisted (s))
7091 ffecom_member_namelisted_ = TRUE;
7092 }
7093
7094 #endif
7095 /* Phase 2 pass over each member of a COMMON/EQUIVALENCE group. Declare
7096 the member so debugger will see it. Otherwise nobody should be
7097 referencing the member. */
7098
7099 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7100 static void
7101 ffecom_member_phase2_ (ffestorag mst, ffestorag st)
7102 {
7103 ffesymbol s;
7104 tree t;
7105 tree mt;
7106 tree type;
7107
7108 if ((mst == NULL)
7109 || ((mt = ffestorag_hook (mst)) == NULL)
7110 || (mt == error_mark_node))
7111 return;
7112
7113 if ((st == NULL)
7114 || ((s = ffestorag_symbol (st)) == NULL))
7115 return;
7116
7117 type = ffecom_type_localvar_ (s,
7118 ffesymbol_basictype (s),
7119 ffesymbol_kindtype (s));
7120 if (type == error_mark_node)
7121 return;
7122
7123 t = build_decl (VAR_DECL,
7124 ffecom_get_identifier_ (ffesymbol_text (s)),
7125 type);
7126
7127 TREE_STATIC (t) = TREE_STATIC (mt);
7128 DECL_INITIAL (t) = NULL_TREE;
7129 TREE_ASM_WRITTEN (t) = 1;
7130
7131 DECL_RTL (t)
7132 = gen_rtx (MEM, TYPE_MODE (type),
7133 plus_constant (XEXP (DECL_RTL (mt), 0),
7134 ffestorag_modulo (mst)
7135 + ffestorag_offset (st)
7136 - ffestorag_offset (mst)));
7137
7138 t = start_decl (t, FALSE);
7139
7140 finish_decl (t, NULL_TREE, FALSE);
7141 }
7142
7143 #endif
7144 /* Prepare source expression for assignment into a destination perhaps known
7145 to be of a specific size. */
7146
7147 static void
7148 ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size, ffebld source)
7149 {
7150 ffecomConcatList_ catlist;
7151 int count;
7152 int i;
7153 tree ltmp;
7154 tree itmp;
7155 tree tempvar = NULL_TREE;
7156
7157 while (ffebld_op (source) == FFEBLD_opCONVERT)
7158 source = ffebld_left (source);
7159
7160 catlist = ffecom_concat_list_new_ (source, dest_size);
7161 count = ffecom_concat_list_count_ (catlist);
7162
7163 if (count >= 2)
7164 {
7165 ltmp
7166 = ffecom_make_tempvar ("let_char_len", ffecom_f2c_ftnlen_type_node,
7167 FFETARGET_charactersizeNONE, count);
7168 itmp
7169 = ffecom_make_tempvar ("let_char_item", ffecom_f2c_address_type_node,
7170 FFETARGET_charactersizeNONE, count);
7171
7172 tempvar = make_tree_vec (2);
7173 TREE_VEC_ELT (tempvar, 0) = ltmp;
7174 TREE_VEC_ELT (tempvar, 1) = itmp;
7175 }
7176
7177 for (i = 0; i < count; ++i)
7178 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist, i));
7179
7180 ffecom_concat_list_kill_ (catlist);
7181
7182 if (tempvar)
7183 {
7184 ffebld_nonter_set_hook (source, tempvar);
7185 current_binding_level->prep_state = 1;
7186 }
7187 }
7188
7189 /* ffecom_push_dummy_decls_ -- Transform dummy args, push parm decls in order
7190
7191 Ignores STAR (alternate-return) dummies. All other get exec-transitioned
7192 (which generates their trees) and then their trees get push_parm_decl'd.
7193
7194 The second arg is TRUE if the dummies are for a statement function, in
7195 which case lengths are not pushed for character arguments (since they are
7196 always known by both the caller and the callee, though the code allows
7197 for someday permitting CHAR*(*) stmtfunc dummies). */
7198
7199 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7200 static void
7201 ffecom_push_dummy_decls_ (ffebld dummy_list, bool stmtfunc)
7202 {
7203 ffebld dummy;
7204 ffebld dumlist;
7205 ffesymbol s;
7206 tree parm;
7207
7208 ffecom_transform_only_dummies_ = TRUE;
7209
7210 /* First push the parms corresponding to actual dummy "contents". */
7211
7212 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7213 {
7214 dummy = ffebld_head (dumlist);
7215 switch (ffebld_op (dummy))
7216 {
7217 case FFEBLD_opSTAR:
7218 case FFEBLD_opANY:
7219 continue; /* Forget alternate returns. */
7220
7221 default:
7222 break;
7223 }
7224 assert (ffebld_op (dummy) == FFEBLD_opSYMTER);
7225 s = ffebld_symter (dummy);
7226 parm = ffesymbol_hook (s).decl_tree;
7227 if (parm == NULL_TREE)
7228 {
7229 s = ffecom_sym_transform_ (s);
7230 parm = ffesymbol_hook (s).decl_tree;
7231 assert (parm != NULL_TREE);
7232 }
7233 if (parm != error_mark_node)
7234 push_parm_decl (parm);
7235 }
7236
7237 /* Then, for CHARACTER dummies, push the parms giving their lengths. */
7238
7239 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7240 {
7241 dummy = ffebld_head (dumlist);
7242 switch (ffebld_op (dummy))
7243 {
7244 case FFEBLD_opSTAR:
7245 case FFEBLD_opANY:
7246 continue; /* Forget alternate returns, they mean
7247 NOTHING! */
7248
7249 default:
7250 break;
7251 }
7252 s = ffebld_symter (dummy);
7253 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
7254 continue; /* Only looking for CHARACTER arguments. */
7255 if (stmtfunc && (ffesymbol_size (s) != FFETARGET_charactersizeNONE))
7256 continue; /* Stmtfunc arg with known size needs no
7257 length param. */
7258 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
7259 continue; /* Only looking for variables and arrays. */
7260 parm = ffesymbol_hook (s).length_tree;
7261 assert (parm != NULL_TREE);
7262 if (parm != error_mark_node)
7263 push_parm_decl (parm);
7264 }
7265
7266 ffecom_transform_only_dummies_ = FALSE;
7267 }
7268
7269 #endif
7270 /* ffecom_start_progunit_ -- Beginning of program unit
7271
7272 Does GNU back end stuff necessary to teach it about the start of its
7273 equivalent of a Fortran program unit. */
7274
7275 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7276 static void
7277 ffecom_start_progunit_ ()
7278 {
7279 ffesymbol fn = ffecom_primary_entry_;
7280 ffebld arglist;
7281 tree id; /* Identifier (name) of function. */
7282 tree type; /* Type of function. */
7283 tree result; /* Result of function. */
7284 ffeinfoBasictype bt;
7285 ffeinfoKindtype kt;
7286 ffeglobal g;
7287 ffeglobalType gt;
7288 ffeglobalType egt = FFEGLOBAL_type;
7289 bool charfunc;
7290 bool cmplxfunc;
7291 bool altentries = (ffecom_num_entrypoints_ != 0);
7292 bool multi
7293 = altentries
7294 && (ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
7295 && (ffecom_master_bt_ == FFEINFO_basictypeNONE);
7296 bool main_program = FALSE;
7297 int old_lineno = lineno;
7298 const char *old_input_filename = input_filename;
7299 int yes;
7300
7301 assert (fn != NULL);
7302 assert (ffesymbol_hook (fn).decl_tree == NULL_TREE);
7303
7304 input_filename = ffesymbol_where_filename (fn);
7305 lineno = ffesymbol_where_filelinenum (fn);
7306
7307 /* c-parse.y indeed does call suspend_momentary and not only ignores the
7308 return value, but also never calls resume_momentary, when starting an
7309 outer function (see "fndef:", "setspecs:", and so on). So g77 does the
7310 same thing. It shouldn't be a problem since start_function calls
7311 temporary_allocation, but it might be necessary. If it causes a problem
7312 here, then maybe there's a bug lurking in gcc. NOTE: This identical
7313 comment appears twice in thist file. */
7314
7315 suspend_momentary ();
7316
7317 switch (ffecom_primary_entry_kind_)
7318 {
7319 case FFEINFO_kindPROGRAM:
7320 main_program = TRUE;
7321 gt = FFEGLOBAL_typeMAIN;
7322 bt = FFEINFO_basictypeNONE;
7323 kt = FFEINFO_kindtypeNONE;
7324 type = ffecom_tree_fun_type_void;
7325 charfunc = FALSE;
7326 cmplxfunc = FALSE;
7327 break;
7328
7329 case FFEINFO_kindBLOCKDATA:
7330 gt = FFEGLOBAL_typeBDATA;
7331 bt = FFEINFO_basictypeNONE;
7332 kt = FFEINFO_kindtypeNONE;
7333 type = ffecom_tree_fun_type_void;
7334 charfunc = FALSE;
7335 cmplxfunc = FALSE;
7336 break;
7337
7338 case FFEINFO_kindFUNCTION:
7339 gt = FFEGLOBAL_typeFUNC;
7340 egt = FFEGLOBAL_typeEXT;
7341 bt = ffesymbol_basictype (fn);
7342 kt = ffesymbol_kindtype (fn);
7343 if (bt == FFEINFO_basictypeNONE)
7344 {
7345 ffeimplic_establish_symbol (fn);
7346 if (ffesymbol_funcresult (fn) != NULL)
7347 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
7348 bt = ffesymbol_basictype (fn);
7349 kt = ffesymbol_kindtype (fn);
7350 }
7351
7352 if (multi)
7353 charfunc = cmplxfunc = FALSE;
7354 else if (bt == FFEINFO_basictypeCHARACTER)
7355 charfunc = TRUE, cmplxfunc = FALSE;
7356 else if ((bt == FFEINFO_basictypeCOMPLEX)
7357 && ffesymbol_is_f2c (fn)
7358 && !altentries)
7359 charfunc = FALSE, cmplxfunc = TRUE;
7360 else
7361 charfunc = cmplxfunc = FALSE;
7362
7363 if (multi || charfunc)
7364 type = ffecom_tree_fun_type_void;
7365 else if (ffesymbol_is_f2c (fn) && !altentries)
7366 type = ffecom_tree_fun_type[bt][kt];
7367 else
7368 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
7369
7370 if ((type == NULL_TREE)
7371 || (TREE_TYPE (type) == NULL_TREE))
7372 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
7373 break;
7374
7375 case FFEINFO_kindSUBROUTINE:
7376 gt = FFEGLOBAL_typeSUBR;
7377 egt = FFEGLOBAL_typeEXT;
7378 bt = FFEINFO_basictypeNONE;
7379 kt = FFEINFO_kindtypeNONE;
7380 if (ffecom_is_altreturning_)
7381 type = ffecom_tree_subr_type;
7382 else
7383 type = ffecom_tree_fun_type_void;
7384 charfunc = FALSE;
7385 cmplxfunc = FALSE;
7386 break;
7387
7388 default:
7389 assert ("say what??" == NULL);
7390 /* Fall through. */
7391 case FFEINFO_kindANY:
7392 gt = FFEGLOBAL_typeANY;
7393 bt = FFEINFO_basictypeNONE;
7394 kt = FFEINFO_kindtypeNONE;
7395 type = error_mark_node;
7396 charfunc = FALSE;
7397 cmplxfunc = FALSE;
7398 break;
7399 }
7400
7401 if (altentries)
7402 {
7403 id = ffecom_get_invented_identifier ("__g77_masterfun_%s",
7404 ffesymbol_text (fn));
7405 }
7406 #if FFETARGET_isENFORCED_MAIN
7407 else if (main_program)
7408 id = get_identifier (FFETARGET_nameENFORCED_MAIN_NAME);
7409 #endif
7410 else
7411 id = ffecom_get_external_identifier_ (fn);
7412
7413 start_function (id,
7414 type,
7415 0, /* nested/inline */
7416 !altentries); /* TREE_PUBLIC */
7417
7418 TREE_USED (current_function_decl) = 1; /* Avoid spurious warning if altentries. */
7419
7420 if (!altentries
7421 && ((g = ffesymbol_global (fn)) != NULL)
7422 && ((ffeglobal_type (g) == gt)
7423 || (ffeglobal_type (g) == egt)))
7424 {
7425 ffeglobal_set_hook (g, current_function_decl);
7426 }
7427
7428 yes = suspend_momentary ();
7429
7430 /* Arg handling needs exec-transitioned ffesymbols to work with. But
7431 exec-transitioning needs current_function_decl to be filled in. So we
7432 do these things in two phases. */
7433
7434 if (altentries)
7435 { /* 1st arg identifies which entrypoint. */
7436 ffecom_which_entrypoint_decl_
7437 = build_decl (PARM_DECL,
7438 ffecom_get_invented_identifier ("__g77_%s",
7439 "which_entrypoint"),
7440 integer_type_node);
7441 push_parm_decl (ffecom_which_entrypoint_decl_);
7442 }
7443
7444 if (charfunc
7445 || cmplxfunc
7446 || multi)
7447 { /* Arg for result (return value). */
7448 tree type;
7449 tree length;
7450
7451 if (charfunc)
7452 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
7453 else if (cmplxfunc)
7454 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
7455 else
7456 type = ffecom_multi_type_node_;
7457
7458 result = ffecom_get_invented_identifier ("__g77_%s", "result");
7459
7460 /* Make length arg _and_ enhance type info for CHAR arg itself. */
7461
7462 if (charfunc)
7463 length = ffecom_char_enhance_arg_ (&type, fn);
7464 else
7465 length = NULL_TREE; /* Not ref'd if !charfunc. */
7466
7467 type = build_pointer_type (type);
7468 result = build_decl (PARM_DECL, result, type);
7469
7470 push_parm_decl (result);
7471 if (multi)
7472 ffecom_multi_retval_ = result;
7473 else
7474 ffecom_func_result_ = result;
7475
7476 if (charfunc)
7477 {
7478 push_parm_decl (length);
7479 ffecom_func_length_ = length;
7480 }
7481 }
7482
7483 if (ffecom_primary_entry_is_proc_)
7484 {
7485 if (altentries)
7486 arglist = ffecom_master_arglist_;
7487 else
7488 arglist = ffesymbol_dummyargs (fn);
7489 ffecom_push_dummy_decls_ (arglist, FALSE);
7490 }
7491
7492 resume_momentary (yes);
7493
7494 if (TREE_CODE (current_function_decl) != ERROR_MARK)
7495 store_parm_decls (main_program ? 1 : 0);
7496
7497 ffecom_start_compstmt ();
7498 /* Disallow temp vars at this level. */
7499 current_binding_level->prep_state = 2;
7500
7501 lineno = old_lineno;
7502 input_filename = old_input_filename;
7503
7504 /* This handles any symbols still untransformed, in case -g specified.
7505 This used to be done in ffecom_finish_progunit, but it turns out to
7506 be necessary to do it here so that statement functions are
7507 expanded before code. But don't bother for BLOCK DATA. */
7508
7509 if (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
7510 ffesymbol_drive (ffecom_finish_symbol_transform_);
7511 }
7512
7513 #endif
7514 /* ffecom_sym_transform_ -- Transform FFE sym into backend sym
7515
7516 ffesymbol s;
7517 ffecom_sym_transform_(s);
7518
7519 The ffesymbol_hook info for s is updated with appropriate backend info
7520 on the symbol. */
7521
7522 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7523 static ffesymbol
7524 ffecom_sym_transform_ (ffesymbol s)
7525 {
7526 tree t; /* Transformed thingy. */
7527 tree tlen; /* Length if CHAR*(*). */
7528 bool addr; /* Is t the address of the thingy? */
7529 ffeinfoBasictype bt;
7530 ffeinfoKindtype kt;
7531 ffeglobal g;
7532 int yes;
7533 int old_lineno = lineno;
7534 const char *old_input_filename = input_filename;
7535
7536 /* Must ensure special ASSIGN variables are declared at top of outermost
7537 block, else they'll end up in the innermost block when their first
7538 ASSIGN is seen, which leaves them out of scope when they're the
7539 subject of a GOTO or I/O statement.
7540
7541 We make this variable even if -fugly-assign. Just let it go unused,
7542 in case it turns out there are cases where we really want to use this
7543 variable anyway (e.g. ASSIGN to INTEGER*2 variable). */
7544
7545 if (! ffecom_transform_only_dummies_
7546 && ffesymbol_assigned (s)
7547 && ! ffesymbol_hook (s).assign_tree)
7548 s = ffecom_sym_transform_assign_ (s);
7549
7550 if (ffesymbol_sfdummyparent (s) == NULL)
7551 {
7552 input_filename = ffesymbol_where_filename (s);
7553 lineno = ffesymbol_where_filelinenum (s);
7554 }
7555 else
7556 {
7557 ffesymbol sf = ffesymbol_sfdummyparent (s);
7558
7559 input_filename = ffesymbol_where_filename (sf);
7560 lineno = ffesymbol_where_filelinenum (sf);
7561 }
7562
7563 bt = ffeinfo_basictype (ffebld_info (s));
7564 kt = ffeinfo_kindtype (ffebld_info (s));
7565
7566 t = NULL_TREE;
7567 tlen = NULL_TREE;
7568 addr = FALSE;
7569
7570 switch (ffesymbol_kind (s))
7571 {
7572 case FFEINFO_kindNONE:
7573 switch (ffesymbol_where (s))
7574 {
7575 case FFEINFO_whereDUMMY: /* Subroutine or function. */
7576 assert (ffecom_transform_only_dummies_);
7577
7578 /* Before 0.4, this could be ENTITY/DUMMY, but see
7579 ffestu_sym_end_transition -- no longer true (in particular, if
7580 it could be an ENTITY, it _will_ be made one, so that
7581 possibility won't come through here). So we never make length
7582 arg for CHARACTER type. */
7583
7584 t = build_decl (PARM_DECL,
7585 ffecom_get_identifier_ (ffesymbol_text (s)),
7586 ffecom_tree_ptr_to_subr_type);
7587 #if BUILT_FOR_270
7588 DECL_ARTIFICIAL (t) = 1;
7589 #endif
7590 addr = TRUE;
7591 break;
7592
7593 case FFEINFO_whereGLOBAL: /* Subroutine or function. */
7594 assert (!ffecom_transform_only_dummies_);
7595
7596 if (((g = ffesymbol_global (s)) != NULL)
7597 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7598 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7599 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
7600 && (ffeglobal_hook (g) != NULL_TREE)
7601 && ffe_is_globals ())
7602 {
7603 t = ffeglobal_hook (g);
7604 break;
7605 }
7606
7607 t = build_decl (FUNCTION_DECL,
7608 ffecom_get_external_identifier_ (s),
7609 ffecom_tree_subr_type); /* Assume subr. */
7610 DECL_EXTERNAL (t) = 1;
7611 TREE_PUBLIC (t) = 1;
7612
7613 t = start_decl (t, FALSE);
7614 finish_decl (t, NULL_TREE, FALSE);
7615
7616 if ((g != NULL)
7617 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7618 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7619 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
7620 ffeglobal_set_hook (g, t);
7621
7622 ffecom_save_tree_forever (t);
7623
7624 break;
7625
7626 default:
7627 assert ("NONE where unexpected" == NULL);
7628 /* Fall through. */
7629 case FFEINFO_whereANY:
7630 break;
7631 }
7632 break;
7633
7634 case FFEINFO_kindENTITY:
7635 switch (ffeinfo_where (ffesymbol_info (s)))
7636 {
7637
7638 case FFEINFO_whereCONSTANT:
7639 /* ~~Debugging info needed? */
7640 assert (!ffecom_transform_only_dummies_);
7641 t = error_mark_node; /* Shouldn't ever see this in expr. */
7642 break;
7643
7644 case FFEINFO_whereLOCAL:
7645 assert (!ffecom_transform_only_dummies_);
7646
7647 {
7648 ffestorag st = ffesymbol_storage (s);
7649 tree type;
7650
7651 if ((st != NULL)
7652 && (ffestorag_size (st) == 0))
7653 {
7654 t = error_mark_node;
7655 break;
7656 }
7657
7658 yes = suspend_momentary ();
7659 type = ffecom_type_localvar_ (s, bt, kt);
7660 resume_momentary (yes);
7661
7662 if (type == error_mark_node)
7663 {
7664 t = error_mark_node;
7665 break;
7666 }
7667
7668 if ((st != NULL)
7669 && (ffestorag_parent (st) != NULL))
7670 { /* Child of EQUIVALENCE parent. */
7671 ffestorag est;
7672 tree et;
7673 int yes;
7674 ffetargetOffset offset;
7675
7676 est = ffestorag_parent (st);
7677 ffecom_transform_equiv_ (est);
7678
7679 et = ffestorag_hook (est);
7680 assert (et != NULL_TREE);
7681
7682 if (! TREE_STATIC (et))
7683 put_var_into_stack (et);
7684
7685 yes = suspend_momentary ();
7686
7687 offset = ffestorag_modulo (est)
7688 + ffestorag_offset (ffesymbol_storage (s))
7689 - ffestorag_offset (est);
7690
7691 ffecom_debug_kludge_ (et, "EQUIVALENCE", s, type, offset);
7692
7693 /* (t_type *) (((char *) &et) + offset) */
7694
7695 t = convert (string_type_node, /* (char *) */
7696 ffecom_1 (ADDR_EXPR,
7697 build_pointer_type (TREE_TYPE (et)),
7698 et));
7699 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
7700 t,
7701 build_int_2 (offset, 0));
7702 t = convert (build_pointer_type (type),
7703 t);
7704 TREE_CONSTANT (t) = staticp (et);
7705
7706 addr = TRUE;
7707
7708 resume_momentary (yes);
7709 }
7710 else
7711 {
7712 tree initexpr;
7713 bool init = ffesymbol_is_init (s);
7714
7715 yes = suspend_momentary ();
7716
7717 t = build_decl (VAR_DECL,
7718 ffecom_get_identifier_ (ffesymbol_text (s)),
7719 type);
7720
7721 if (init
7722 || ffesymbol_namelisted (s)
7723 #ifdef FFECOM_sizeMAXSTACKITEM
7724 || ((st != NULL)
7725 && (ffestorag_size (st) > FFECOM_sizeMAXSTACKITEM))
7726 #endif
7727 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
7728 && (ffecom_primary_entry_kind_
7729 != FFEINFO_kindBLOCKDATA)
7730 && (ffesymbol_is_save (s) || ffe_is_saveall ())))
7731 TREE_STATIC (t) = !ffesymbol_attr (s, FFESYMBOL_attrADJUSTABLE);
7732 else
7733 TREE_STATIC (t) = 0; /* No need to make static. */
7734
7735 if (init || ffe_is_init_local_zero ())
7736 DECL_INITIAL (t) = error_mark_node;
7737
7738 /* Keep -Wunused from complaining about var if it
7739 is used as sfunc arg or DATA implied-DO. */
7740 if (ffesymbol_attrs (s) & FFESYMBOL_attrsSFARG)
7741 DECL_IN_SYSTEM_HEADER (t) = 1;
7742
7743 t = start_decl (t, FALSE);
7744
7745 if (init)
7746 {
7747 if (ffesymbol_init (s) != NULL)
7748 initexpr = ffecom_expr (ffesymbol_init (s));
7749 else
7750 initexpr = ffecom_init_zero_ (t);
7751 }
7752 else if (ffe_is_init_local_zero ())
7753 initexpr = ffecom_init_zero_ (t);
7754 else
7755 initexpr = NULL_TREE; /* Not ref'd if !init. */
7756
7757 finish_decl (t, initexpr, FALSE);
7758
7759 if (st != NULL && DECL_SIZE (t) != error_mark_node)
7760 {
7761 assert (TREE_CODE (DECL_SIZE_UNIT (t)) == INTEGER_CST);
7762 assert (0 == compare_tree_int (DECL_SIZE_UNIT (t),
7763 ffestorag_size (st)));
7764 }
7765
7766 resume_momentary (yes);
7767 }
7768 }
7769 break;
7770
7771 case FFEINFO_whereRESULT:
7772 assert (!ffecom_transform_only_dummies_);
7773
7774 if (bt == FFEINFO_basictypeCHARACTER)
7775 { /* Result is already in list of dummies, use
7776 it (& length). */
7777 t = ffecom_func_result_;
7778 tlen = ffecom_func_length_;
7779 addr = TRUE;
7780 break;
7781 }
7782 if ((ffecom_num_entrypoints_ == 0)
7783 && (bt == FFEINFO_basictypeCOMPLEX)
7784 && (ffesymbol_is_f2c (ffecom_primary_entry_)))
7785 { /* Result is already in list of dummies, use
7786 it. */
7787 t = ffecom_func_result_;
7788 addr = TRUE;
7789 break;
7790 }
7791 if (ffecom_func_result_ != NULL_TREE)
7792 {
7793 t = ffecom_func_result_;
7794 break;
7795 }
7796 if ((ffecom_num_entrypoints_ != 0)
7797 && (ffecom_master_bt_ == FFEINFO_basictypeNONE))
7798 {
7799 yes = suspend_momentary ();
7800
7801 assert (ffecom_multi_retval_ != NULL_TREE);
7802 t = ffecom_1 (INDIRECT_REF, ffecom_multi_type_node_,
7803 ffecom_multi_retval_);
7804 t = ffecom_2 (COMPONENT_REF, ffecom_tree_type[bt][kt],
7805 t, ffecom_multi_fields_[bt][kt]);
7806
7807 resume_momentary (yes);
7808 break;
7809 }
7810
7811 yes = suspend_momentary ();
7812
7813 t = build_decl (VAR_DECL,
7814 ffecom_get_identifier_ (ffesymbol_text (s)),
7815 ffecom_tree_type[bt][kt]);
7816 TREE_STATIC (t) = 0; /* Put result on stack. */
7817 t = start_decl (t, FALSE);
7818 finish_decl (t, NULL_TREE, FALSE);
7819
7820 ffecom_func_result_ = t;
7821
7822 resume_momentary (yes);
7823 break;
7824
7825 case FFEINFO_whereDUMMY:
7826 {
7827 tree type;
7828 ffebld dl;
7829 ffebld dim;
7830 tree low;
7831 tree high;
7832 tree old_sizes;
7833 bool adjustable = FALSE; /* Conditionally adjustable? */
7834
7835 type = ffecom_tree_type[bt][kt];
7836 if (ffesymbol_sfdummyparent (s) != NULL)
7837 {
7838 if (current_function_decl == ffecom_outer_function_decl_)
7839 { /* Exec transition before sfunc
7840 context; get it later. */
7841 break;
7842 }
7843 t = ffecom_get_identifier_ (ffesymbol_text
7844 (ffesymbol_sfdummyparent (s)));
7845 }
7846 else
7847 t = ffecom_get_identifier_ (ffesymbol_text (s));
7848
7849 assert (ffecom_transform_only_dummies_);
7850
7851 old_sizes = get_pending_sizes ();
7852 put_pending_sizes (old_sizes);
7853
7854 if (bt == FFEINFO_basictypeCHARACTER)
7855 tlen = ffecom_char_enhance_arg_ (&type, s);
7856 type = ffecom_check_size_overflow_ (s, type, TRUE);
7857
7858 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
7859 {
7860 if (type == error_mark_node)
7861 break;
7862
7863 dim = ffebld_head (dl);
7864 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
7865 if ((ffebld_left (dim) == NULL) || ffecom_doing_entry_)
7866 low = ffecom_integer_one_node;
7867 else
7868 low = ffecom_expr (ffebld_left (dim));
7869 assert (ffebld_right (dim) != NULL);
7870 if ((ffebld_op (ffebld_right (dim)) == FFEBLD_opSTAR)
7871 || ffecom_doing_entry_)
7872 {
7873 /* Used to just do high=low. But for ffecom_tree_
7874 canonize_ref_, it probably is important to correctly
7875 assess the size. E.g. given COMPLEX C(*),CFUNC and
7876 C(2)=CFUNC(C), overlap can happen, while it can't
7877 for, say, C(1)=CFUNC(C(2)). */
7878 /* Even more recently used to set to INT_MAX, but that
7879 broke when some overflow checking went into the back
7880 end. Now we just leave the upper bound unspecified. */
7881 high = NULL;
7882 }
7883 else
7884 high = ffecom_expr (ffebld_right (dim));
7885
7886 /* Determine whether array is conditionally adjustable,
7887 to decide whether back-end magic is needed.
7888
7889 Normally the front end uses the back-end function
7890 variable_size to wrap SAVE_EXPR's around expressions
7891 affecting the size/shape of an array so that the
7892 size/shape info doesn't change during execution
7893 of the compiled code even though variables and
7894 functions referenced in those expressions might.
7895
7896 variable_size also makes sure those saved expressions
7897 get evaluated immediately upon entry to the
7898 compiled procedure -- the front end normally doesn't
7899 have to worry about that.
7900
7901 However, there is a problem with this that affects
7902 g77's implementation of entry points, and that is
7903 that it is _not_ true that each invocation of the
7904 compiled procedure is permitted to evaluate
7905 array size/shape info -- because it is possible
7906 that, for some invocations, that info is invalid (in
7907 which case it is "promised" -- i.e. a violation of
7908 the Fortran standard -- that the compiled code
7909 won't reference the array or its size/shape
7910 during that particular invocation).
7911
7912 To phrase this in C terms, consider this gcc function:
7913
7914 void foo (int *n, float (*a)[*n])
7915 {
7916 // a is "pointer to array ...", fyi.
7917 }
7918
7919 Suppose that, for some invocations, it is permitted
7920 for a caller of foo to do this:
7921
7922 foo (NULL, NULL);
7923
7924 Now the _written_ code for foo can take such a call
7925 into account by either testing explicitly for whether
7926 (a == NULL) || (n == NULL) -- presumably it is
7927 not permitted to reference *a in various fashions
7928 if (n == NULL) I suppose -- or it can avoid it by
7929 looking at other info (other arguments, static/global
7930 data, etc.).
7931
7932 However, this won't work in gcc 2.5.8 because it'll
7933 automatically emit the code to save the "*n"
7934 expression, which'll yield a NULL dereference for
7935 the "foo (NULL, NULL)" call, something the code
7936 for foo cannot prevent.
7937
7938 g77 definitely needs to avoid executing such
7939 code anytime the pointer to the adjustable array
7940 is NULL, because even if its bounds expressions
7941 don't have any references to possible "absent"
7942 variables like "*n" -- say all variable references
7943 are to COMMON variables, i.e. global (though in C,
7944 local static could actually make sense) -- the
7945 expressions could yield other run-time problems
7946 for allowably "dead" values in those variables.
7947
7948 For example, let's consider a more complicated
7949 version of foo:
7950
7951 extern int i;
7952 extern int j;
7953
7954 void foo (float (*a)[i/j])
7955 {
7956 ...
7957 }
7958
7959 The above is (essentially) quite valid for Fortran
7960 but, again, for a call like "foo (NULL);", it is
7961 permitted for i and j to be undefined when the
7962 call is made. If j happened to be zero, for
7963 example, emitting the code to evaluate "i/j"
7964 could result in a run-time error.
7965
7966 Offhand, though I don't have my F77 or F90
7967 standards handy, it might even be valid for a
7968 bounds expression to contain a function reference,
7969 in which case I doubt it is permitted for an
7970 implementation to invoke that function in the
7971 Fortran case involved here (invocation of an
7972 alternate ENTRY point that doesn't have the adjustable
7973 array as one of its arguments).
7974
7975 So, the code that the compiler would normally emit
7976 to preevaluate the size/shape info for an
7977 adjustable array _must not_ be executed at run time
7978 in certain cases. Specifically, for Fortran,
7979 the case is when the pointer to the adjustable
7980 array == NULL. (For gnu-ish C, it might be nice
7981 for the source code itself to specify an expression
7982 that, if TRUE, inhibits execution of the code. Or
7983 reverse the sense for elegance.)
7984
7985 (Note that g77 could use a different test than NULL,
7986 actually, since it happens to always pass an
7987 integer to the called function that specifies which
7988 entry point is being invoked. Hmm, this might
7989 solve the next problem.)
7990
7991 One way a user could, I suppose, write "foo" so
7992 it works is to insert COND_EXPR's for the
7993 size/shape info so the dangerous stuff isn't
7994 actually done, as in:
7995
7996 void foo (int *n, float (*a)[(a == NULL) ? 0 : *n])
7997 {
7998 ...
7999 }
8000
8001 The next problem is that the front end needs to
8002 be able to tell the back end about the array's
8003 decl _before_ it tells it about the conditional
8004 expression to inhibit evaluation of size/shape info,
8005 as shown above.
8006
8007 To solve this, the front end needs to be able
8008 to give the back end the expression to inhibit
8009 generation of the preevaluation code _after_
8010 it makes the decl for the adjustable array.
8011
8012 Until then, the above example using the COND_EXPR
8013 doesn't pass muster with gcc because the "(a == NULL)"
8014 part has a reference to "a", which is still
8015 undefined at that point.
8016
8017 g77 will therefore use a different mechanism in the
8018 meantime. */
8019
8020 if (!adjustable
8021 && ((TREE_CODE (low) != INTEGER_CST)
8022 || (high && TREE_CODE (high) != INTEGER_CST)))
8023 adjustable = TRUE;
8024
8025 #if 0 /* Old approach -- see below. */
8026 if (TREE_CODE (low) != INTEGER_CST)
8027 low = ffecom_3 (COND_EXPR, integer_type_node,
8028 ffecom_adjarray_passed_ (s),
8029 low,
8030 ffecom_integer_zero_node);
8031
8032 if (high && TREE_CODE (high) != INTEGER_CST)
8033 high = ffecom_3 (COND_EXPR, integer_type_node,
8034 ffecom_adjarray_passed_ (s),
8035 high,
8036 ffecom_integer_zero_node);
8037 #endif
8038
8039 /* ~~~gcc/stor-layout.c (layout_type) should do this,
8040 probably. Fixes 950302-1.f. */
8041
8042 if (TREE_CODE (low) != INTEGER_CST)
8043 low = variable_size (low);
8044
8045 /* ~~~Similarly, this fixes dumb0.f. The C front end
8046 does this, which is why dumb0.c would work. */
8047
8048 if (high && TREE_CODE (high) != INTEGER_CST)
8049 high = variable_size (high);
8050
8051 type
8052 = build_array_type
8053 (type,
8054 build_range_type (ffecom_integer_type_node,
8055 low, high));
8056 type = ffecom_check_size_overflow_ (s, type, TRUE);
8057 }
8058
8059 if (type == error_mark_node)
8060 {
8061 t = error_mark_node;
8062 break;
8063 }
8064
8065 if ((ffesymbol_sfdummyparent (s) == NULL)
8066 || (ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER))
8067 {
8068 type = build_pointer_type (type);
8069 addr = TRUE;
8070 }
8071
8072 t = build_decl (PARM_DECL, t, type);
8073 #if BUILT_FOR_270
8074 DECL_ARTIFICIAL (t) = 1;
8075 #endif
8076
8077 /* If this arg is present in every entry point's list of
8078 dummy args, then we're done. */
8079
8080 if (ffesymbol_numentries (s)
8081 == (ffecom_num_entrypoints_ + 1))
8082 break;
8083
8084 #if 1
8085
8086 /* If variable_size in stor-layout has been called during
8087 the above, then get_pending_sizes should have the
8088 yet-to-be-evaluated saved expressions pending.
8089 Make the whole lot of them get emitted, conditionally
8090 on whether the array decl ("t" above) is not NULL. */
8091
8092 {
8093 tree sizes = get_pending_sizes ();
8094 tree tem;
8095
8096 for (tem = sizes;
8097 tem != old_sizes;
8098 tem = TREE_CHAIN (tem))
8099 {
8100 tree temv = TREE_VALUE (tem);
8101
8102 if (sizes == tem)
8103 sizes = temv;
8104 else
8105 sizes
8106 = ffecom_2 (COMPOUND_EXPR,
8107 TREE_TYPE (sizes),
8108 temv,
8109 sizes);
8110 }
8111
8112 if (sizes != tem)
8113 {
8114 sizes
8115 = ffecom_3 (COND_EXPR,
8116 TREE_TYPE (sizes),
8117 ffecom_2 (NE_EXPR,
8118 integer_type_node,
8119 t,
8120 null_pointer_node),
8121 sizes,
8122 convert (TREE_TYPE (sizes),
8123 integer_zero_node));
8124 sizes = ffecom_save_tree (sizes);
8125
8126 sizes
8127 = tree_cons (NULL_TREE, sizes, tem);
8128 }
8129
8130 if (sizes)
8131 put_pending_sizes (sizes);
8132 }
8133
8134 #else
8135 #if 0
8136 if (adjustable
8137 && (ffesymbol_numentries (s)
8138 != ffecom_num_entrypoints_ + 1))
8139 DECL_SOMETHING (t)
8140 = ffecom_2 (NE_EXPR, integer_type_node,
8141 t,
8142 null_pointer_node);
8143 #else
8144 #if 0
8145 if (adjustable
8146 && (ffesymbol_numentries (s)
8147 != ffecom_num_entrypoints_ + 1))
8148 {
8149 ffebad_start (FFEBAD_MISSING_ADJARRAY_UNSUPPORTED);
8150 ffebad_here (0, ffesymbol_where_line (s),
8151 ffesymbol_where_column (s));
8152 ffebad_string (ffesymbol_text (s));
8153 ffebad_finish ();
8154 }
8155 #endif
8156 #endif
8157 #endif
8158 }
8159 break;
8160
8161 case FFEINFO_whereCOMMON:
8162 {
8163 ffesymbol cs;
8164 ffeglobal cg;
8165 tree ct;
8166 ffestorag st = ffesymbol_storage (s);
8167 tree type;
8168 int yes;
8169
8170 cs = ffesymbol_common (s); /* The COMMON area itself. */
8171 if (st != NULL) /* Else not laid out. */
8172 {
8173 ffecom_transform_common_ (cs);
8174 st = ffesymbol_storage (s);
8175 }
8176
8177 yes = suspend_momentary ();
8178
8179 type = ffecom_type_localvar_ (s, bt, kt);
8180
8181 cg = ffesymbol_global (cs); /* The global COMMON info. */
8182 if ((cg == NULL)
8183 || (ffeglobal_type (cg) != FFEGLOBAL_typeCOMMON))
8184 ct = NULL_TREE;
8185 else
8186 ct = ffeglobal_hook (cg); /* The common area's tree. */
8187
8188 if ((ct == NULL_TREE)
8189 || (st == NULL)
8190 || (type == error_mark_node))
8191 t = error_mark_node;
8192 else
8193 {
8194 ffetargetOffset offset;
8195 ffestorag cst;
8196
8197 cst = ffestorag_parent (st);
8198 assert (cst == ffesymbol_storage (cs));
8199
8200 offset = ffestorag_modulo (cst)
8201 + ffestorag_offset (st)
8202 - ffestorag_offset (cst);
8203
8204 ffecom_debug_kludge_ (ct, "COMMON", s, type, offset);
8205
8206 /* (t_type *) (((char *) &ct) + offset) */
8207
8208 t = convert (string_type_node, /* (char *) */
8209 ffecom_1 (ADDR_EXPR,
8210 build_pointer_type (TREE_TYPE (ct)),
8211 ct));
8212 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
8213 t,
8214 build_int_2 (offset, 0));
8215 t = convert (build_pointer_type (type),
8216 t);
8217 TREE_CONSTANT (t) = 1;
8218
8219 addr = TRUE;
8220 }
8221
8222 resume_momentary (yes);
8223 }
8224 break;
8225
8226 case FFEINFO_whereIMMEDIATE:
8227 case FFEINFO_whereGLOBAL:
8228 case FFEINFO_whereFLEETING:
8229 case FFEINFO_whereFLEETING_CADDR:
8230 case FFEINFO_whereFLEETING_IADDR:
8231 case FFEINFO_whereINTRINSIC:
8232 case FFEINFO_whereCONSTANT_SUBOBJECT:
8233 default:
8234 assert ("ENTITY where unheard of" == NULL);
8235 /* Fall through. */
8236 case FFEINFO_whereANY:
8237 t = error_mark_node;
8238 break;
8239 }
8240 break;
8241
8242 case FFEINFO_kindFUNCTION:
8243 switch (ffeinfo_where (ffesymbol_info (s)))
8244 {
8245 case FFEINFO_whereLOCAL: /* Me. */
8246 assert (!ffecom_transform_only_dummies_);
8247 t = current_function_decl;
8248 break;
8249
8250 case FFEINFO_whereGLOBAL:
8251 assert (!ffecom_transform_only_dummies_);
8252
8253 if (((g = ffesymbol_global (s)) != NULL)
8254 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8255 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8256 && (ffeglobal_hook (g) != NULL_TREE)
8257 && ffe_is_globals ())
8258 {
8259 t = ffeglobal_hook (g);
8260 break;
8261 }
8262
8263 if (ffesymbol_is_f2c (s)
8264 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8265 t = ffecom_tree_fun_type[bt][kt];
8266 else
8267 t = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
8268
8269 t = build_decl (FUNCTION_DECL,
8270 ffecom_get_external_identifier_ (s),
8271 t);
8272 DECL_EXTERNAL (t) = 1;
8273 TREE_PUBLIC (t) = 1;
8274
8275 t = start_decl (t, FALSE);
8276 finish_decl (t, NULL_TREE, FALSE);
8277
8278 if ((g != NULL)
8279 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8280 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8281 ffeglobal_set_hook (g, t);
8282
8283 ffecom_save_tree_forever (t);
8284
8285 break;
8286
8287 case FFEINFO_whereDUMMY:
8288 assert (ffecom_transform_only_dummies_);
8289
8290 if (ffesymbol_is_f2c (s)
8291 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8292 t = ffecom_tree_ptr_to_fun_type[bt][kt];
8293 else
8294 t = build_pointer_type
8295 (build_function_type (ffecom_tree_type[bt][kt], NULL_TREE));
8296
8297 t = build_decl (PARM_DECL,
8298 ffecom_get_identifier_ (ffesymbol_text (s)),
8299 t);
8300 #if BUILT_FOR_270
8301 DECL_ARTIFICIAL (t) = 1;
8302 #endif
8303 addr = TRUE;
8304 break;
8305
8306 case FFEINFO_whereCONSTANT: /* Statement function. */
8307 assert (!ffecom_transform_only_dummies_);
8308 t = ffecom_gen_sfuncdef_ (s, bt, kt);
8309 break;
8310
8311 case FFEINFO_whereINTRINSIC:
8312 assert (!ffecom_transform_only_dummies_);
8313 break; /* Let actual references generate their
8314 decls. */
8315
8316 default:
8317 assert ("FUNCTION where unheard of" == NULL);
8318 /* Fall through. */
8319 case FFEINFO_whereANY:
8320 t = error_mark_node;
8321 break;
8322 }
8323 break;
8324
8325 case FFEINFO_kindSUBROUTINE:
8326 switch (ffeinfo_where (ffesymbol_info (s)))
8327 {
8328 case FFEINFO_whereLOCAL: /* Me. */
8329 assert (!ffecom_transform_only_dummies_);
8330 t = current_function_decl;
8331 break;
8332
8333 case FFEINFO_whereGLOBAL:
8334 assert (!ffecom_transform_only_dummies_);
8335
8336 if (((g = ffesymbol_global (s)) != NULL)
8337 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8338 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8339 && (ffeglobal_hook (g) != NULL_TREE)
8340 && ffe_is_globals ())
8341 {
8342 t = ffeglobal_hook (g);
8343 break;
8344 }
8345
8346 t = build_decl (FUNCTION_DECL,
8347 ffecom_get_external_identifier_ (s),
8348 ffecom_tree_subr_type);
8349 DECL_EXTERNAL (t) = 1;
8350 TREE_PUBLIC (t) = 1;
8351
8352 t = start_decl (t, FALSE);
8353 finish_decl (t, NULL_TREE, FALSE);
8354
8355 if ((g != NULL)
8356 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8357 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8358 ffeglobal_set_hook (g, t);
8359
8360 ffecom_save_tree_forever (t);
8361
8362 break;
8363
8364 case FFEINFO_whereDUMMY:
8365 assert (ffecom_transform_only_dummies_);
8366
8367 t = build_decl (PARM_DECL,
8368 ffecom_get_identifier_ (ffesymbol_text (s)),
8369 ffecom_tree_ptr_to_subr_type);
8370 #if BUILT_FOR_270
8371 DECL_ARTIFICIAL (t) = 1;
8372 #endif
8373 addr = TRUE;
8374 break;
8375
8376 case FFEINFO_whereINTRINSIC:
8377 assert (!ffecom_transform_only_dummies_);
8378 break; /* Let actual references generate their
8379 decls. */
8380
8381 default:
8382 assert ("SUBROUTINE where unheard of" == NULL);
8383 /* Fall through. */
8384 case FFEINFO_whereANY:
8385 t = error_mark_node;
8386 break;
8387 }
8388 break;
8389
8390 case FFEINFO_kindPROGRAM:
8391 switch (ffeinfo_where (ffesymbol_info (s)))
8392 {
8393 case FFEINFO_whereLOCAL: /* Me. */
8394 assert (!ffecom_transform_only_dummies_);
8395 t = current_function_decl;
8396 break;
8397
8398 case FFEINFO_whereCOMMON:
8399 case FFEINFO_whereDUMMY:
8400 case FFEINFO_whereGLOBAL:
8401 case FFEINFO_whereRESULT:
8402 case FFEINFO_whereFLEETING:
8403 case FFEINFO_whereFLEETING_CADDR:
8404 case FFEINFO_whereFLEETING_IADDR:
8405 case FFEINFO_whereIMMEDIATE:
8406 case FFEINFO_whereINTRINSIC:
8407 case FFEINFO_whereCONSTANT:
8408 case FFEINFO_whereCONSTANT_SUBOBJECT:
8409 default:
8410 assert ("PROGRAM where unheard of" == NULL);
8411 /* Fall through. */
8412 case FFEINFO_whereANY:
8413 t = error_mark_node;
8414 break;
8415 }
8416 break;
8417
8418 case FFEINFO_kindBLOCKDATA:
8419 switch (ffeinfo_where (ffesymbol_info (s)))
8420 {
8421 case FFEINFO_whereLOCAL: /* Me. */
8422 assert (!ffecom_transform_only_dummies_);
8423 t = current_function_decl;
8424 break;
8425
8426 case FFEINFO_whereGLOBAL:
8427 assert (!ffecom_transform_only_dummies_);
8428
8429 t = build_decl (FUNCTION_DECL,
8430 ffecom_get_external_identifier_ (s),
8431 ffecom_tree_blockdata_type);
8432 DECL_EXTERNAL (t) = 1;
8433 TREE_PUBLIC (t) = 1;
8434
8435 t = start_decl (t, FALSE);
8436 finish_decl (t, NULL_TREE, FALSE);
8437
8438 ffecom_save_tree_forever (t);
8439
8440 break;
8441
8442 case FFEINFO_whereCOMMON:
8443 case FFEINFO_whereDUMMY:
8444 case FFEINFO_whereRESULT:
8445 case FFEINFO_whereFLEETING:
8446 case FFEINFO_whereFLEETING_CADDR:
8447 case FFEINFO_whereFLEETING_IADDR:
8448 case FFEINFO_whereIMMEDIATE:
8449 case FFEINFO_whereINTRINSIC:
8450 case FFEINFO_whereCONSTANT:
8451 case FFEINFO_whereCONSTANT_SUBOBJECT:
8452 default:
8453 assert ("BLOCKDATA where unheard of" == NULL);
8454 /* Fall through. */
8455 case FFEINFO_whereANY:
8456 t = error_mark_node;
8457 break;
8458 }
8459 break;
8460
8461 case FFEINFO_kindCOMMON:
8462 switch (ffeinfo_where (ffesymbol_info (s)))
8463 {
8464 case FFEINFO_whereLOCAL:
8465 assert (!ffecom_transform_only_dummies_);
8466 ffecom_transform_common_ (s);
8467 break;
8468
8469 case FFEINFO_whereNONE:
8470 case FFEINFO_whereCOMMON:
8471 case FFEINFO_whereDUMMY:
8472 case FFEINFO_whereGLOBAL:
8473 case FFEINFO_whereRESULT:
8474 case FFEINFO_whereFLEETING:
8475 case FFEINFO_whereFLEETING_CADDR:
8476 case FFEINFO_whereFLEETING_IADDR:
8477 case FFEINFO_whereIMMEDIATE:
8478 case FFEINFO_whereINTRINSIC:
8479 case FFEINFO_whereCONSTANT:
8480 case FFEINFO_whereCONSTANT_SUBOBJECT:
8481 default:
8482 assert ("COMMON where unheard of" == NULL);
8483 /* Fall through. */
8484 case FFEINFO_whereANY:
8485 t = error_mark_node;
8486 break;
8487 }
8488 break;
8489
8490 case FFEINFO_kindCONSTRUCT:
8491 switch (ffeinfo_where (ffesymbol_info (s)))
8492 {
8493 case FFEINFO_whereLOCAL:
8494 assert (!ffecom_transform_only_dummies_);
8495 break;
8496
8497 case FFEINFO_whereNONE:
8498 case FFEINFO_whereCOMMON:
8499 case FFEINFO_whereDUMMY:
8500 case FFEINFO_whereGLOBAL:
8501 case FFEINFO_whereRESULT:
8502 case FFEINFO_whereFLEETING:
8503 case FFEINFO_whereFLEETING_CADDR:
8504 case FFEINFO_whereFLEETING_IADDR:
8505 case FFEINFO_whereIMMEDIATE:
8506 case FFEINFO_whereINTRINSIC:
8507 case FFEINFO_whereCONSTANT:
8508 case FFEINFO_whereCONSTANT_SUBOBJECT:
8509 default:
8510 assert ("CONSTRUCT where unheard of" == NULL);
8511 /* Fall through. */
8512 case FFEINFO_whereANY:
8513 t = error_mark_node;
8514 break;
8515 }
8516 break;
8517
8518 case FFEINFO_kindNAMELIST:
8519 switch (ffeinfo_where (ffesymbol_info (s)))
8520 {
8521 case FFEINFO_whereLOCAL:
8522 assert (!ffecom_transform_only_dummies_);
8523 t = ffecom_transform_namelist_ (s);
8524 break;
8525
8526 case FFEINFO_whereNONE:
8527 case FFEINFO_whereCOMMON:
8528 case FFEINFO_whereDUMMY:
8529 case FFEINFO_whereGLOBAL:
8530 case FFEINFO_whereRESULT:
8531 case FFEINFO_whereFLEETING:
8532 case FFEINFO_whereFLEETING_CADDR:
8533 case FFEINFO_whereFLEETING_IADDR:
8534 case FFEINFO_whereIMMEDIATE:
8535 case FFEINFO_whereINTRINSIC:
8536 case FFEINFO_whereCONSTANT:
8537 case FFEINFO_whereCONSTANT_SUBOBJECT:
8538 default:
8539 assert ("NAMELIST where unheard of" == NULL);
8540 /* Fall through. */
8541 case FFEINFO_whereANY:
8542 t = error_mark_node;
8543 break;
8544 }
8545 break;
8546
8547 default:
8548 assert ("kind unheard of" == NULL);
8549 /* Fall through. */
8550 case FFEINFO_kindANY:
8551 t = error_mark_node;
8552 break;
8553 }
8554
8555 ffesymbol_hook (s).decl_tree = t;
8556 ffesymbol_hook (s).length_tree = tlen;
8557 ffesymbol_hook (s).addr = addr;
8558
8559 lineno = old_lineno;
8560 input_filename = old_input_filename;
8561
8562 return s;
8563 }
8564
8565 #endif
8566 /* Transform into ASSIGNable symbol.
8567
8568 Symbol has already been transformed, but for whatever reason, the
8569 resulting decl_tree has been deemed not usable for an ASSIGN target.
8570 (E.g. it isn't wide enough to hold a pointer.) So, here we invent
8571 another local symbol of type void * and stuff that in the assign_tree
8572 argument. The F77/F90 standards allow this implementation. */
8573
8574 #if FFECOM_targetCURRENT == FFECOM_targetGCC
8575 static ffesymbol
8576 ffecom_sym_transform_assign_ (ffesymbol s)
8577 {
8578 tree t; /* Transformed thingy. */
8579 int yes;
8580 int old_lineno = lineno;
8581 const char *old_input_filename = input_filename;
8582
8583 if (ffesymbol_sfdummyparent (s) == NULL)
8584 {
8585 input_filename = ffesymbol_where_filename (s);
8586 lineno = ffesymbol_where_filelinenum (s);
8587 }
8588 else
8589 {
8590 ffesymbol sf = ffesymbol_sfdummyparent (s);
8591
8592 input_filename = ffesymbol_where_filename (sf);
8593 lineno = ffesymbol_where_filelinenum (sf);
8594 }
8595
8596 assert (!ffecom_transform_only_dummies_);
8597
8598 yes = suspend_momentary ();
8599
8600 t = build_decl (VAR_DECL,
8601 ffecom_get_invented_identifier ("__g77_ASSIGN_%s",
8602 ffesymbol_text (s)),
8603 TREE_TYPE (null_pointer_node));
8604
8605 switch (ffesymbol_where (s))
8606 {
8607 case FFEINFO_whereLOCAL:
8608 /* Unlike for regular vars, SAVE status is easy to determine for
8609 ASSIGNed vars, since there's no initialization, there's no
8610 effective storage association (so "SAVE J" does not apply to
8611 K even given "EQUIVALENCE (J,K)"), there's no size issue
8612 to worry about, etc. */
8613 if ((ffesymbol_is_save (s) || ffe_is_saveall ())
8614 && (ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8615 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA))
8616 TREE_STATIC (t) = 1; /* SAVEd in proc, make static. */
8617 else
8618 TREE_STATIC (t) = 0; /* No need to make static. */
8619 break;
8620
8621 case FFEINFO_whereCOMMON:
8622 TREE_STATIC (t) = 1; /* Assume COMMONs always SAVEd. */
8623 break;
8624
8625 case FFEINFO_whereDUMMY:
8626 /* Note that twinning a DUMMY means the caller won't see
8627 the ASSIGNed value. But both F77 and F90 allow implementations
8628 to do this, i.e. disallow Fortran code that would try and
8629 take advantage of actually putting a label into a variable
8630 via a dummy argument (or any other storage association, for
8631 that matter). */
8632 TREE_STATIC (t) = 0;
8633 break;
8634
8635 default:
8636 TREE_STATIC (t) = 0;
8637 break;
8638 }
8639
8640 t = start_decl (t, FALSE);
8641 finish_decl (t, NULL_TREE, FALSE);
8642
8643 resume_momentary (yes);
8644
8645 ffesymbol_hook (s).assign_tree = t;
8646
8647 lineno = old_lineno;
8648 input_filename = old_input_filename;
8649
8650 return s;
8651 }
8652
8653 #endif
8654 /* Implement COMMON area in back end.
8655
8656 Because COMMON-based variables can be referenced in the dimension
8657 expressions of dummy (adjustable) arrays, and because dummies
8658 (in the gcc back end) need to be put in the outer binding level
8659 of a function (which has two binding levels, the outer holding
8660 the dummies and the inner holding the other vars), special care
8661 must be taken to handle COMMON areas.
8662
8663 The current strategy is basically to always tell the back end about
8664 the COMMON area as a top-level external reference to just a block
8665 of storage of the master type of that area (e.g. integer, real,
8666 character, whatever -- not a structure). As a distinct action,
8667 if initial values are provided, tell the back end about the area
8668 as a top-level non-external (initialized) area and remember not to
8669 allow further initialization or expansion of the area. Meanwhile,
8670 if no initialization happens at all, tell the back end about
8671 the largest size we've seen declared so the space does get reserved.
8672 (This function doesn't handle all that stuff, but it does some
8673 of the important things.)
8674
8675 Meanwhile, for COMMON variables themselves, just keep creating
8676 references like *((float *) (&common_area + offset)) each time
8677 we reference the variable. In other words, don't make a VAR_DECL
8678 or any kind of component reference (like we used to do before 0.4),
8679 though we might do that as well just for debugging purposes (and
8680 stuff the rtl with the appropriate offset expression). */
8681
8682 #if FFECOM_targetCURRENT == FFECOM_targetGCC
8683 static void
8684 ffecom_transform_common_ (ffesymbol s)
8685 {
8686 ffestorag st = ffesymbol_storage (s);
8687 ffeglobal g = ffesymbol_global (s);
8688 tree cbt;
8689 tree cbtype;
8690 tree init;
8691 tree high;
8692 bool is_init = ffestorag_is_init (st);
8693
8694 assert (st != NULL);
8695
8696 if ((g == NULL)
8697 || (ffeglobal_type (g) != FFEGLOBAL_typeCOMMON))
8698 return;
8699
8700 /* First update the size of the area in global terms. */
8701
8702 ffeglobal_size_common (s, ffestorag_size (st));
8703
8704 if (!ffeglobal_common_init (g))
8705 is_init = FALSE; /* No explicit init, don't let erroneous joins init. */
8706
8707 cbt = ffeglobal_hook (g);
8708
8709 /* If we already have declared this common block for a previous program
8710 unit, and either we already initialized it or we don't have new
8711 initialization for it, just return what we have without changing it. */
8712
8713 if ((cbt != NULL_TREE)
8714 && (!is_init
8715 || !DECL_EXTERNAL (cbt)))
8716 {
8717 if (st->hook == NULL) ffestorag_set_hook (st, cbt);
8718 return;
8719 }
8720
8721 /* Process inits. */
8722
8723 if (is_init)
8724 {
8725 if (ffestorag_init (st) != NULL)
8726 {
8727 ffebld sexp;
8728
8729 /* Set the padding for the expression, so ffecom_expr
8730 knows to insert that many zeros. */
8731 switch (ffebld_op (sexp = ffestorag_init (st)))
8732 {
8733 case FFEBLD_opCONTER:
8734 ffebld_conter_set_pad (sexp, ffestorag_modulo (st));
8735 break;
8736
8737 case FFEBLD_opARRTER:
8738 ffebld_arrter_set_pad (sexp, ffestorag_modulo (st));
8739 break;
8740
8741 case FFEBLD_opACCTER:
8742 ffebld_accter_set_pad (sexp, ffestorag_modulo (st));
8743 break;
8744
8745 default:
8746 assert ("bad op for cmn init (pad)" == NULL);
8747 break;
8748 }
8749
8750 init = ffecom_expr (sexp);
8751 if (init == error_mark_node)
8752 { /* Hopefully the back end complained! */
8753 init = NULL_TREE;
8754 if (cbt != NULL_TREE)
8755 return;
8756 }
8757 }
8758 else
8759 init = error_mark_node;
8760 }
8761 else
8762 init = NULL_TREE;
8763
8764 /* cbtype must be permanently allocated! */
8765
8766 /* Allocate the MAX of the areas so far, seen filewide. */
8767 high = build_int_2 ((ffeglobal_common_size (g)
8768 + ffeglobal_common_pad (g)) - 1, 0);
8769 TREE_TYPE (high) = ffecom_integer_type_node;
8770
8771 if (init)
8772 cbtype = build_array_type (char_type_node,
8773 build_range_type (integer_type_node,
8774 integer_zero_node,
8775 high));
8776 else
8777 cbtype = build_array_type (char_type_node, NULL_TREE);
8778
8779 if (cbt == NULL_TREE)
8780 {
8781 cbt
8782 = build_decl (VAR_DECL,
8783 ffecom_get_external_identifier_ (s),
8784 cbtype);
8785 TREE_STATIC (cbt) = 1;
8786 TREE_PUBLIC (cbt) = 1;
8787 }
8788 else
8789 {
8790 assert (is_init);
8791 TREE_TYPE (cbt) = cbtype;
8792 }
8793 DECL_EXTERNAL (cbt) = init ? 0 : 1;
8794 DECL_INITIAL (cbt) = init ? error_mark_node : NULL_TREE;
8795
8796 cbt = start_decl (cbt, TRUE);
8797 if (ffeglobal_hook (g) != NULL)
8798 assert (cbt == ffeglobal_hook (g));
8799
8800 assert (!init || !DECL_EXTERNAL (cbt));
8801
8802 /* Make sure that any type can live in COMMON and be referenced
8803 without getting a bus error. We could pick the most restrictive
8804 alignment of all entities actually placed in the COMMON, but
8805 this seems easy enough. */
8806
8807 DECL_ALIGN (cbt) = BIGGEST_ALIGNMENT;
8808 DECL_USER_ALIGN (cbt) = 0;
8809
8810 if (is_init && (ffestorag_init (st) == NULL))
8811 init = ffecom_init_zero_ (cbt);
8812
8813 finish_decl (cbt, init, TRUE);
8814
8815 if (is_init)
8816 ffestorag_set_init (st, ffebld_new_any ());
8817
8818 if (init)
8819 {
8820 assert (DECL_SIZE_UNIT (cbt) != NULL_TREE);
8821 assert (TREE_CODE (DECL_SIZE_UNIT (cbt)) == INTEGER_CST);
8822 assert (0 == compare_tree_int (DECL_SIZE_UNIT (cbt),
8823 (ffeglobal_common_size (g)
8824 + ffeglobal_common_pad (g))));
8825 }
8826
8827 ffeglobal_set_hook (g, cbt);
8828
8829 ffestorag_set_hook (st, cbt);
8830
8831 ffecom_save_tree_forever (cbt);
8832 }
8833
8834 #endif
8835 /* Make master area for local EQUIVALENCE. */
8836
8837 #if FFECOM_targetCURRENT == FFECOM_targetGCC
8838 static void
8839 ffecom_transform_equiv_ (ffestorag eqst)
8840 {
8841 tree eqt;
8842 tree eqtype;
8843 tree init;
8844 tree high;
8845 bool is_init = ffestorag_is_init (eqst);
8846 int yes;
8847
8848 assert (eqst != NULL);
8849
8850 eqt = ffestorag_hook (eqst);
8851
8852 if (eqt != NULL_TREE)
8853 return;
8854
8855 /* Process inits. */
8856
8857 if (is_init)
8858 {
8859 if (ffestorag_init (eqst) != NULL)
8860 {
8861 ffebld sexp;
8862
8863 /* Set the padding for the expression, so ffecom_expr
8864 knows to insert that many zeros. */
8865 switch (ffebld_op (sexp = ffestorag_init (eqst)))
8866 {
8867 case FFEBLD_opCONTER:
8868 ffebld_conter_set_pad (sexp, ffestorag_modulo (eqst));
8869 break;
8870
8871 case FFEBLD_opARRTER:
8872 ffebld_arrter_set_pad (sexp, ffestorag_modulo (eqst));
8873 break;
8874
8875 case FFEBLD_opACCTER:
8876 ffebld_accter_set_pad (sexp, ffestorag_modulo (eqst));
8877 break;
8878
8879 default:
8880 assert ("bad op for eqv init (pad)" == NULL);
8881 break;
8882 }
8883
8884 init = ffecom_expr (sexp);
8885 if (init == error_mark_node)
8886 init = NULL_TREE; /* Hopefully the back end complained! */
8887 }
8888 else
8889 init = error_mark_node;
8890 }
8891 else if (ffe_is_init_local_zero ())
8892 init = error_mark_node;
8893 else
8894 init = NULL_TREE;
8895
8896 ffecom_member_namelisted_ = FALSE;
8897 ffestorag_drive (ffestorag_list_equivs (eqst),
8898 &ffecom_member_phase1_,
8899 eqst);
8900
8901 yes = suspend_momentary ();
8902
8903 high = build_int_2 ((ffestorag_size (eqst)
8904 + ffestorag_modulo (eqst)) - 1, 0);
8905 TREE_TYPE (high) = ffecom_integer_type_node;
8906
8907 eqtype = build_array_type (char_type_node,
8908 build_range_type (ffecom_integer_type_node,
8909 ffecom_integer_zero_node,
8910 high));
8911
8912 eqt = build_decl (VAR_DECL,
8913 ffecom_get_invented_identifier ("__g77_equiv_%s",
8914 ffesymbol_text
8915 (ffestorag_symbol (eqst))),
8916 eqtype);
8917 DECL_EXTERNAL (eqt) = 0;
8918 if (is_init
8919 || ffecom_member_namelisted_
8920 #ifdef FFECOM_sizeMAXSTACKITEM
8921 || (ffestorag_size (eqst) > FFECOM_sizeMAXSTACKITEM)
8922 #endif
8923 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8924 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
8925 && (ffestorag_is_save (eqst) || ffe_is_saveall ())))
8926 TREE_STATIC (eqt) = 1;
8927 else
8928 TREE_STATIC (eqt) = 0;
8929 TREE_PUBLIC (eqt) = 0;
8930 TREE_ADDRESSABLE (eqt) = 1; /* Ensure non-register allocation */
8931 DECL_CONTEXT (eqt) = current_function_decl;
8932 if (init)
8933 DECL_INITIAL (eqt) = error_mark_node;
8934 else
8935 DECL_INITIAL (eqt) = NULL_TREE;
8936
8937 eqt = start_decl (eqt, FALSE);
8938
8939 /* Make sure that any type can live in EQUIVALENCE and be referenced
8940 without getting a bus error. We could pick the most restrictive
8941 alignment of all entities actually placed in the EQUIVALENCE, but
8942 this seems easy enough. */
8943
8944 DECL_ALIGN (eqt) = BIGGEST_ALIGNMENT;
8945 DECL_USER_ALIGN (eqt) = 0;
8946
8947 if ((!is_init && ffe_is_init_local_zero ())
8948 || (is_init && (ffestorag_init (eqst) == NULL)))
8949 init = ffecom_init_zero_ (eqt);
8950
8951 finish_decl (eqt, init, FALSE);
8952
8953 if (is_init)
8954 ffestorag_set_init (eqst, ffebld_new_any ());
8955
8956 {
8957 assert (TREE_CODE (DECL_SIZE_UNIT (eqt)) == INTEGER_CST);
8958 assert (0 == compare_tree_int (DECL_SIZE_UNIT (eqt),
8959 (ffestorag_size (eqst)
8960 + ffestorag_modulo (eqst))));
8961 }
8962
8963 ffestorag_set_hook (eqst, eqt);
8964
8965 ffestorag_drive (ffestorag_list_equivs (eqst),
8966 &ffecom_member_phase2_,
8967 eqst);
8968
8969 resume_momentary (yes);
8970 }
8971
8972 #endif
8973 /* Implement NAMELIST in back end. See f2c/format.c for more info. */
8974
8975 #if FFECOM_targetCURRENT == FFECOM_targetGCC
8976 static tree
8977 ffecom_transform_namelist_ (ffesymbol s)
8978 {
8979 tree nmlt;
8980 tree nmltype = ffecom_type_namelist_ ();
8981 tree nmlinits;
8982 tree nameinit;
8983 tree varsinit;
8984 tree nvarsinit;
8985 tree field;
8986 tree high;
8987 int yes;
8988 int i;
8989 static int mynumber = 0;
8990
8991 yes = suspend_momentary ();
8992
8993 nmlt = build_decl (VAR_DECL,
8994 ffecom_get_invented_identifier ("__g77_namelist_%d",
8995 mynumber++),
8996 nmltype);
8997 TREE_STATIC (nmlt) = 1;
8998 DECL_INITIAL (nmlt) = error_mark_node;
8999
9000 nmlt = start_decl (nmlt, FALSE);
9001
9002 /* Process inits. */
9003
9004 i = strlen (ffesymbol_text (s));
9005
9006 high = build_int_2 (i, 0);
9007 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
9008
9009 nameinit = ffecom_build_f2c_string_ (i + 1,
9010 ffesymbol_text (s));
9011 TREE_TYPE (nameinit)
9012 = build_type_variant
9013 (build_array_type
9014 (char_type_node,
9015 build_range_type (ffecom_f2c_ftnlen_type_node,
9016 ffecom_f2c_ftnlen_one_node,
9017 high)),
9018 1, 0);
9019 TREE_CONSTANT (nameinit) = 1;
9020 TREE_STATIC (nameinit) = 1;
9021 nameinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (nameinit)),
9022 nameinit);
9023
9024 varsinit = ffecom_vardesc_array_ (s);
9025 varsinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (varsinit)),
9026 varsinit);
9027 TREE_CONSTANT (varsinit) = 1;
9028 TREE_STATIC (varsinit) = 1;
9029
9030 {
9031 ffebld b;
9032
9033 for (i = 0, b = ffesymbol_namelist (s); b != NULL; b = ffebld_trail (b))
9034 ++i;
9035 }
9036 nvarsinit = build_int_2 (i, 0);
9037 TREE_TYPE (nvarsinit) = integer_type_node;
9038 TREE_CONSTANT (nvarsinit) = 1;
9039 TREE_STATIC (nvarsinit) = 1;
9040
9041 nmlinits = build_tree_list ((field = TYPE_FIELDS (nmltype)), nameinit);
9042 TREE_CHAIN (nmlinits) = build_tree_list ((field = TREE_CHAIN (field)),
9043 varsinit);
9044 TREE_CHAIN (TREE_CHAIN (nmlinits))
9045 = build_tree_list ((field = TREE_CHAIN (field)), nvarsinit);
9046
9047 nmlinits = build (CONSTRUCTOR, nmltype, NULL_TREE, nmlinits);
9048 TREE_CONSTANT (nmlinits) = 1;
9049 TREE_STATIC (nmlinits) = 1;
9050
9051 finish_decl (nmlt, nmlinits, FALSE);
9052
9053 nmlt = ffecom_1 (ADDR_EXPR, build_pointer_type (nmltype), nmlt);
9054
9055 resume_momentary (yes);
9056
9057 return nmlt;
9058 }
9059
9060 #endif
9061
9062 /* A subroutine of ffecom_tree_canonize_ref_. The incoming tree is
9063 analyzed on the assumption it is calculating a pointer to be
9064 indirected through. It must return the proper decl and offset,
9065 taking into account different units of measurements for offsets. */
9066
9067 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9068 static void
9069 ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
9070 tree t)
9071 {
9072 switch (TREE_CODE (t))
9073 {
9074 case NOP_EXPR:
9075 case CONVERT_EXPR:
9076 case NON_LVALUE_EXPR:
9077 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
9078 break;
9079
9080 case PLUS_EXPR:
9081 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
9082 if ((*decl == NULL_TREE)
9083 || (*decl == error_mark_node))
9084 break;
9085
9086 if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST)
9087 {
9088 /* An offset into COMMON. */
9089 *offset = fold (build (PLUS_EXPR, TREE_TYPE (*offset),
9090 *offset, TREE_OPERAND (t, 1)));
9091 /* Convert offset (presumably in bytes) into canonical units
9092 (presumably bits). */
9093 *offset = size_binop (MULT_EXPR,
9094 convert (bitsizetype, *offset),
9095 TYPE_SIZE (TREE_TYPE (TREE_TYPE (t))));
9096 break;
9097 }
9098 /* Not a COMMON reference, so an unrecognized pattern. */
9099 *decl = error_mark_node;
9100 break;
9101
9102 case PARM_DECL:
9103 *decl = t;
9104 *offset = bitsize_zero_node;
9105 break;
9106
9107 case ADDR_EXPR:
9108 if (TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL)
9109 {
9110 /* A reference to COMMON. */
9111 *decl = TREE_OPERAND (t, 0);
9112 *offset = bitsize_zero_node;
9113 break;
9114 }
9115 /* Fall through. */
9116 default:
9117 /* Not a COMMON reference, so an unrecognized pattern. */
9118 *decl = error_mark_node;
9119 break;
9120 }
9121 }
9122 #endif
9123
9124 /* Given a tree that is possibly intended for use as an lvalue, return
9125 information representing a canonical view of that tree as a decl, an
9126 offset into that decl, and a size for the lvalue.
9127
9128 If there's no applicable decl, NULL_TREE is returned for the decl,
9129 and the other fields are left undefined.
9130
9131 If the tree doesn't fit the recognizable forms, an ERROR_MARK node
9132 is returned for the decl, and the other fields are left undefined.
9133
9134 Otherwise, the decl returned currently is either a VAR_DECL or a
9135 PARM_DECL.
9136
9137 The offset returned is always valid, but of course not necessarily
9138 a constant, and not necessarily converted into the appropriate
9139 type, leaving that up to the caller (so as to avoid that overhead
9140 if the decls being looked at are different anyway).
9141
9142 If the size cannot be determined (e.g. an adjustable array),
9143 an ERROR_MARK node is returned for the size. Otherwise, the
9144 size returned is valid, not necessarily a constant, and not
9145 necessarily converted into the appropriate type as with the
9146 offset.
9147
9148 Note that the offset and size expressions are expressed in the
9149 base storage units (usually bits) rather than in the units of
9150 the type of the decl, because two decls with different types
9151 might overlap but with apparently non-overlapping array offsets,
9152 whereas converting the array offsets to consistant offsets will
9153 reveal the overlap. */
9154
9155 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9156 static void
9157 ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
9158 tree *size, tree t)
9159 {
9160 /* The default path is to report a nonexistant decl. */
9161 *decl = NULL_TREE;
9162
9163 if (t == NULL_TREE)
9164 return;
9165
9166 switch (TREE_CODE (t))
9167 {
9168 case ERROR_MARK:
9169 case IDENTIFIER_NODE:
9170 case INTEGER_CST:
9171 case REAL_CST:
9172 case COMPLEX_CST:
9173 case STRING_CST:
9174 case CONST_DECL:
9175 case PLUS_EXPR:
9176 case MINUS_EXPR:
9177 case MULT_EXPR:
9178 case TRUNC_DIV_EXPR:
9179 case CEIL_DIV_EXPR:
9180 case FLOOR_DIV_EXPR:
9181 case ROUND_DIV_EXPR:
9182 case TRUNC_MOD_EXPR:
9183 case CEIL_MOD_EXPR:
9184 case FLOOR_MOD_EXPR:
9185 case ROUND_MOD_EXPR:
9186 case RDIV_EXPR:
9187 case EXACT_DIV_EXPR:
9188 case FIX_TRUNC_EXPR:
9189 case FIX_CEIL_EXPR:
9190 case FIX_FLOOR_EXPR:
9191 case FIX_ROUND_EXPR:
9192 case FLOAT_EXPR:
9193 case EXPON_EXPR:
9194 case NEGATE_EXPR:
9195 case MIN_EXPR:
9196 case MAX_EXPR:
9197 case ABS_EXPR:
9198 case FFS_EXPR:
9199 case LSHIFT_EXPR:
9200 case RSHIFT_EXPR:
9201 case LROTATE_EXPR:
9202 case RROTATE_EXPR:
9203 case BIT_IOR_EXPR:
9204 case BIT_XOR_EXPR:
9205 case BIT_AND_EXPR:
9206 case BIT_ANDTC_EXPR:
9207 case BIT_NOT_EXPR:
9208 case TRUTH_ANDIF_EXPR:
9209 case TRUTH_ORIF_EXPR:
9210 case TRUTH_AND_EXPR:
9211 case TRUTH_OR_EXPR:
9212 case TRUTH_XOR_EXPR:
9213 case TRUTH_NOT_EXPR:
9214 case LT_EXPR:
9215 case LE_EXPR:
9216 case GT_EXPR:
9217 case GE_EXPR:
9218 case EQ_EXPR:
9219 case NE_EXPR:
9220 case COMPLEX_EXPR:
9221 case CONJ_EXPR:
9222 case REALPART_EXPR:
9223 case IMAGPART_EXPR:
9224 case LABEL_EXPR:
9225 case COMPONENT_REF:
9226 case COMPOUND_EXPR:
9227 case ADDR_EXPR:
9228 return;
9229
9230 case VAR_DECL:
9231 case PARM_DECL:
9232 *decl = t;
9233 *offset = bitsize_zero_node;
9234 *size = TYPE_SIZE (TREE_TYPE (t));
9235 return;
9236
9237 case ARRAY_REF:
9238 {
9239 tree array = TREE_OPERAND (t, 0);
9240 tree element = TREE_OPERAND (t, 1);
9241 tree init_offset;
9242
9243 if ((array == NULL_TREE)
9244 || (element == NULL_TREE))
9245 {
9246 *decl = error_mark_node;
9247 return;
9248 }
9249
9250 ffecom_tree_canonize_ref_ (decl, &init_offset, size,
9251 array);
9252 if ((*decl == NULL_TREE)
9253 || (*decl == error_mark_node))
9254 return;
9255
9256 /* Calculate ((element - base) * NBBY) + init_offset. */
9257 *offset = fold (build (MINUS_EXPR, TREE_TYPE (element),
9258 element,
9259 TYPE_MIN_VALUE (TYPE_DOMAIN
9260 (TREE_TYPE (array)))));
9261
9262 *offset = size_binop (MULT_EXPR,
9263 convert (bitsizetype, *offset),
9264 TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))));
9265
9266 *offset = size_binop (PLUS_EXPR, init_offset, *offset);
9267
9268 *size = TYPE_SIZE (TREE_TYPE (t));
9269 return;
9270 }
9271
9272 case INDIRECT_REF:
9273
9274 /* Most of this code is to handle references to COMMON. And so
9275 far that is useful only for calling library functions, since
9276 external (user) functions might reference common areas. But
9277 even calling an external function, it's worthwhile to decode
9278 COMMON references because if not storing into COMMON, we don't
9279 want COMMON-based arguments to gratuitously force use of a
9280 temporary. */
9281
9282 *size = TYPE_SIZE (TREE_TYPE (t));
9283
9284 ffecom_tree_canonize_ptr_ (decl, offset,
9285 TREE_OPERAND (t, 0));
9286
9287 return;
9288
9289 case CONVERT_EXPR:
9290 case NOP_EXPR:
9291 case MODIFY_EXPR:
9292 case NON_LVALUE_EXPR:
9293 case RESULT_DECL:
9294 case FIELD_DECL:
9295 case COND_EXPR: /* More cases than we can handle. */
9296 case SAVE_EXPR:
9297 case REFERENCE_EXPR:
9298 case PREDECREMENT_EXPR:
9299 case PREINCREMENT_EXPR:
9300 case POSTDECREMENT_EXPR:
9301 case POSTINCREMENT_EXPR:
9302 case CALL_EXPR:
9303 default:
9304 *decl = error_mark_node;
9305 return;
9306 }
9307 }
9308 #endif
9309
9310 /* Do divide operation appropriate to type of operands. */
9311
9312 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9313 static tree
9314 ffecom_tree_divide_ (tree tree_type, tree left, tree right,
9315 tree dest_tree, ffebld dest, bool *dest_used,
9316 tree hook)
9317 {
9318 if ((left == error_mark_node)
9319 || (right == error_mark_node))
9320 return error_mark_node;
9321
9322 switch (TREE_CODE (tree_type))
9323 {
9324 case INTEGER_TYPE:
9325 return ffecom_2 (TRUNC_DIV_EXPR, tree_type,
9326 left,
9327 right);
9328
9329 case COMPLEX_TYPE:
9330 if (! optimize_size)
9331 return ffecom_2 (RDIV_EXPR, tree_type,
9332 left,
9333 right);
9334 {
9335 ffecomGfrt ix;
9336
9337 if (TREE_TYPE (tree_type)
9338 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9339 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9340 else
9341 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
9342
9343 left = ffecom_1 (ADDR_EXPR,
9344 build_pointer_type (TREE_TYPE (left)),
9345 left);
9346 left = build_tree_list (NULL_TREE, left);
9347 right = ffecom_1 (ADDR_EXPR,
9348 build_pointer_type (TREE_TYPE (right)),
9349 right);
9350 right = build_tree_list (NULL_TREE, right);
9351 TREE_CHAIN (left) = right;
9352
9353 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9354 ffecom_gfrt_kindtype (ix),
9355 ffe_is_f2c_library (),
9356 tree_type,
9357 left,
9358 dest_tree, dest, dest_used,
9359 NULL_TREE, TRUE, hook);
9360 }
9361 break;
9362
9363 case RECORD_TYPE:
9364 {
9365 ffecomGfrt ix;
9366
9367 if (TREE_TYPE (TYPE_FIELDS (tree_type))
9368 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9369 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9370 else
9371 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
9372
9373 left = ffecom_1 (ADDR_EXPR,
9374 build_pointer_type (TREE_TYPE (left)),
9375 left);
9376 left = build_tree_list (NULL_TREE, left);
9377 right = ffecom_1 (ADDR_EXPR,
9378 build_pointer_type (TREE_TYPE (right)),
9379 right);
9380 right = build_tree_list (NULL_TREE, right);
9381 TREE_CHAIN (left) = right;
9382
9383 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9384 ffecom_gfrt_kindtype (ix),
9385 ffe_is_f2c_library (),
9386 tree_type,
9387 left,
9388 dest_tree, dest, dest_used,
9389 NULL_TREE, TRUE, hook);
9390 }
9391 break;
9392
9393 default:
9394 return ffecom_2 (RDIV_EXPR, tree_type,
9395 left,
9396 right);
9397 }
9398 }
9399
9400 #endif
9401 /* Build type info for non-dummy variable. */
9402
9403 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9404 static tree
9405 ffecom_type_localvar_ (ffesymbol s, ffeinfoBasictype bt,
9406 ffeinfoKindtype kt)
9407 {
9408 tree type;
9409 ffebld dl;
9410 ffebld dim;
9411 tree lowt;
9412 tree hight;
9413
9414 type = ffecom_tree_type[bt][kt];
9415 if (bt == FFEINFO_basictypeCHARACTER)
9416 {
9417 hight = build_int_2 (ffesymbol_size (s), 0);
9418 TREE_TYPE (hight) = ffecom_f2c_ftnlen_type_node;
9419
9420 type
9421 = build_array_type
9422 (type,
9423 build_range_type (ffecom_f2c_ftnlen_type_node,
9424 ffecom_f2c_ftnlen_one_node,
9425 hight));
9426 type = ffecom_check_size_overflow_ (s, type, FALSE);
9427 }
9428
9429 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
9430 {
9431 if (type == error_mark_node)
9432 break;
9433
9434 dim = ffebld_head (dl);
9435 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
9436
9437 if (ffebld_left (dim) == NULL)
9438 lowt = integer_one_node;
9439 else
9440 lowt = ffecom_expr (ffebld_left (dim));
9441
9442 if (TREE_CODE (lowt) != INTEGER_CST)
9443 lowt = variable_size (lowt);
9444
9445 assert (ffebld_right (dim) != NULL);
9446 hight = ffecom_expr (ffebld_right (dim));
9447
9448 if (TREE_CODE (hight) != INTEGER_CST)
9449 hight = variable_size (hight);
9450
9451 type = build_array_type (type,
9452 build_range_type (ffecom_integer_type_node,
9453 lowt, hight));
9454 type = ffecom_check_size_overflow_ (s, type, FALSE);
9455 }
9456
9457 return type;
9458 }
9459
9460 #endif
9461 /* Build Namelist type. */
9462
9463 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9464 static tree
9465 ffecom_type_namelist_ ()
9466 {
9467 static tree type = NULL_TREE;
9468
9469 if (type == NULL_TREE)
9470 {
9471 static tree namefield, varsfield, nvarsfield;
9472 tree vardesctype;
9473
9474 vardesctype = ffecom_type_vardesc_ ();
9475
9476 type = make_node (RECORD_TYPE);
9477
9478 vardesctype = build_pointer_type (build_pointer_type (vardesctype));
9479
9480 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9481 string_type_node);
9482 varsfield = ffecom_decl_field (type, namefield, "vars", vardesctype);
9483 nvarsfield = ffecom_decl_field (type, varsfield, "nvars",
9484 integer_type_node);
9485
9486 TYPE_FIELDS (type) = namefield;
9487 layout_type (type);
9488
9489 ggc_add_tree_root (&type, 1);
9490 }
9491
9492 return type;
9493 }
9494
9495 #endif
9496
9497 /* Build Vardesc type. */
9498
9499 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9500 static tree
9501 ffecom_type_vardesc_ ()
9502 {
9503 static tree type = NULL_TREE;
9504 static tree namefield, addrfield, dimsfield, typefield;
9505
9506 if (type == NULL_TREE)
9507 {
9508 type = make_node (RECORD_TYPE);
9509
9510 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9511 string_type_node);
9512 addrfield = ffecom_decl_field (type, namefield, "addr",
9513 string_type_node);
9514 dimsfield = ffecom_decl_field (type, addrfield, "dims",
9515 ffecom_f2c_ptr_to_ftnlen_type_node);
9516 typefield = ffecom_decl_field (type, dimsfield, "type",
9517 integer_type_node);
9518
9519 TYPE_FIELDS (type) = namefield;
9520 layout_type (type);
9521
9522 ggc_add_tree_root (&type, 1);
9523 }
9524
9525 return type;
9526 }
9527
9528 #endif
9529
9530 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9531 static tree
9532 ffecom_vardesc_ (ffebld expr)
9533 {
9534 ffesymbol s;
9535
9536 assert (ffebld_op (expr) == FFEBLD_opSYMTER);
9537 s = ffebld_symter (expr);
9538
9539 if (ffesymbol_hook (s).vardesc_tree == NULL_TREE)
9540 {
9541 int i;
9542 tree vardesctype = ffecom_type_vardesc_ ();
9543 tree var;
9544 tree nameinit;
9545 tree dimsinit;
9546 tree addrinit;
9547 tree typeinit;
9548 tree field;
9549 tree varinits;
9550 int yes;
9551 static int mynumber = 0;
9552
9553 yes = suspend_momentary ();
9554
9555 var = build_decl (VAR_DECL,
9556 ffecom_get_invented_identifier ("__g77_vardesc_%d",
9557 mynumber++),
9558 vardesctype);
9559 TREE_STATIC (var) = 1;
9560 DECL_INITIAL (var) = error_mark_node;
9561
9562 var = start_decl (var, FALSE);
9563
9564 /* Process inits. */
9565
9566 nameinit = ffecom_build_f2c_string_ ((i = strlen (ffesymbol_text (s)))
9567 + 1,
9568 ffesymbol_text (s));
9569 TREE_TYPE (nameinit)
9570 = build_type_variant
9571 (build_array_type
9572 (char_type_node,
9573 build_range_type (integer_type_node,
9574 integer_one_node,
9575 build_int_2 (i, 0))),
9576 1, 0);
9577 TREE_CONSTANT (nameinit) = 1;
9578 TREE_STATIC (nameinit) = 1;
9579 nameinit = ffecom_1 (ADDR_EXPR,
9580 build_pointer_type (TREE_TYPE (nameinit)),
9581 nameinit);
9582
9583 addrinit = ffecom_arg_ptr_to_expr (expr, &typeinit);
9584
9585 dimsinit = ffecom_vardesc_dims_ (s);
9586
9587 if (typeinit == NULL_TREE)
9588 {
9589 ffeinfoBasictype bt = ffesymbol_basictype (s);
9590 ffeinfoKindtype kt = ffesymbol_kindtype (s);
9591 int tc = ffecom_f2c_typecode (bt, kt);
9592
9593 assert (tc != -1);
9594 typeinit = build_int_2 (tc, (tc < 0) ? -1 : 0);
9595 }
9596 else
9597 typeinit = ffecom_1 (NEGATE_EXPR, TREE_TYPE (typeinit), typeinit);
9598
9599 varinits = build_tree_list ((field = TYPE_FIELDS (vardesctype)),
9600 nameinit);
9601 TREE_CHAIN (varinits) = build_tree_list ((field = TREE_CHAIN (field)),
9602 addrinit);
9603 TREE_CHAIN (TREE_CHAIN (varinits))
9604 = build_tree_list ((field = TREE_CHAIN (field)), dimsinit);
9605 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (varinits)))
9606 = build_tree_list ((field = TREE_CHAIN (field)), typeinit);
9607
9608 varinits = build (CONSTRUCTOR, vardesctype, NULL_TREE, varinits);
9609 TREE_CONSTANT (varinits) = 1;
9610 TREE_STATIC (varinits) = 1;
9611
9612 finish_decl (var, varinits, FALSE);
9613
9614 var = ffecom_1 (ADDR_EXPR, build_pointer_type (vardesctype), var);
9615
9616 resume_momentary (yes);
9617
9618 ffesymbol_hook (s).vardesc_tree = var;
9619 }
9620
9621 return ffesymbol_hook (s).vardesc_tree;
9622 }
9623
9624 #endif
9625 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9626 static tree
9627 ffecom_vardesc_array_ (ffesymbol s)
9628 {
9629 ffebld b;
9630 tree list;
9631 tree item = NULL_TREE;
9632 tree var;
9633 int i;
9634 int yes;
9635 static int mynumber = 0;
9636
9637 for (i = 0, list = NULL_TREE, b = ffesymbol_namelist (s);
9638 b != NULL;
9639 b = ffebld_trail (b), ++i)
9640 {
9641 tree t;
9642
9643 t = ffecom_vardesc_ (ffebld_head (b));
9644
9645 if (list == NULL_TREE)
9646 list = item = build_tree_list (NULL_TREE, t);
9647 else
9648 {
9649 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9650 item = TREE_CHAIN (item);
9651 }
9652 }
9653
9654 yes = suspend_momentary ();
9655
9656 item = build_array_type (build_pointer_type (ffecom_type_vardesc_ ()),
9657 build_range_type (integer_type_node,
9658 integer_one_node,
9659 build_int_2 (i, 0)));
9660 list = build (CONSTRUCTOR, item, NULL_TREE, list);
9661 TREE_CONSTANT (list) = 1;
9662 TREE_STATIC (list) = 1;
9663
9664 var = ffecom_get_invented_identifier ("__g77_vardesc_array_%d", mynumber++);
9665 var = build_decl (VAR_DECL, var, item);
9666 TREE_STATIC (var) = 1;
9667 DECL_INITIAL (var) = error_mark_node;
9668 var = start_decl (var, FALSE);
9669 finish_decl (var, list, FALSE);
9670
9671 resume_momentary (yes);
9672
9673 return var;
9674 }
9675
9676 #endif
9677 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9678 static tree
9679 ffecom_vardesc_dims_ (ffesymbol s)
9680 {
9681 if (ffesymbol_dims (s) == NULL)
9682 return convert (ffecom_f2c_ptr_to_ftnlen_type_node,
9683 integer_zero_node);
9684
9685 {
9686 ffebld b;
9687 ffebld e;
9688 tree list;
9689 tree backlist;
9690 tree item = NULL_TREE;
9691 tree var;
9692 int yes;
9693 tree numdim;
9694 tree numelem;
9695 tree baseoff = NULL_TREE;
9696 static int mynumber = 0;
9697
9698 numdim = build_int_2 ((int) ffesymbol_rank (s), 0);
9699 TREE_TYPE (numdim) = ffecom_f2c_ftnlen_type_node;
9700
9701 numelem = ffecom_expr (ffesymbol_arraysize (s));
9702 TREE_TYPE (numelem) = ffecom_f2c_ftnlen_type_node;
9703
9704 list = NULL_TREE;
9705 backlist = NULL_TREE;
9706 for (b = ffesymbol_dims (s), e = ffesymbol_extents (s);
9707 b != NULL;
9708 b = ffebld_trail (b), e = ffebld_trail (e))
9709 {
9710 tree t;
9711 tree low;
9712 tree back;
9713
9714 if (ffebld_trail (b) == NULL)
9715 t = NULL_TREE;
9716 else
9717 {
9718 t = convert (ffecom_f2c_ftnlen_type_node,
9719 ffecom_expr (ffebld_head (e)));
9720
9721 if (list == NULL_TREE)
9722 list = item = build_tree_list (NULL_TREE, t);
9723 else
9724 {
9725 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9726 item = TREE_CHAIN (item);
9727 }
9728 }
9729
9730 if (ffebld_left (ffebld_head (b)) == NULL)
9731 low = ffecom_integer_one_node;
9732 else
9733 low = ffecom_expr (ffebld_left (ffebld_head (b)));
9734 low = convert (ffecom_f2c_ftnlen_type_node, low);
9735
9736 back = build_tree_list (low, t);
9737 TREE_CHAIN (back) = backlist;
9738 backlist = back;
9739 }
9740
9741 for (item = backlist; item != NULL_TREE; item = TREE_CHAIN (item))
9742 {
9743 if (TREE_VALUE (item) == NULL_TREE)
9744 baseoff = TREE_PURPOSE (item);
9745 else
9746 baseoff = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
9747 TREE_PURPOSE (item),
9748 ffecom_2 (MULT_EXPR,
9749 ffecom_f2c_ftnlen_type_node,
9750 TREE_VALUE (item),
9751 baseoff));
9752 }
9753
9754 /* backlist now dead, along with all TREE_PURPOSEs on it. */
9755
9756 baseoff = build_tree_list (NULL_TREE, baseoff);
9757 TREE_CHAIN (baseoff) = list;
9758
9759 numelem = build_tree_list (NULL_TREE, numelem);
9760 TREE_CHAIN (numelem) = baseoff;
9761
9762 numdim = build_tree_list (NULL_TREE, numdim);
9763 TREE_CHAIN (numdim) = numelem;
9764
9765 yes = suspend_momentary ();
9766
9767 item = build_array_type (ffecom_f2c_ftnlen_type_node,
9768 build_range_type (integer_type_node,
9769 integer_zero_node,
9770 build_int_2
9771 ((int) ffesymbol_rank (s)
9772 + 2, 0)));
9773 list = build (CONSTRUCTOR, item, NULL_TREE, numdim);
9774 TREE_CONSTANT (list) = 1;
9775 TREE_STATIC (list) = 1;
9776
9777 var = ffecom_get_invented_identifier ("__g77_dims_%d", mynumber++);
9778 var = build_decl (VAR_DECL, var, item);
9779 TREE_STATIC (var) = 1;
9780 DECL_INITIAL (var) = error_mark_node;
9781 var = start_decl (var, FALSE);
9782 finish_decl (var, list, FALSE);
9783
9784 var = ffecom_1 (ADDR_EXPR, build_pointer_type (item), var);
9785
9786 resume_momentary (yes);
9787
9788 return var;
9789 }
9790 }
9791
9792 #endif
9793 /* Essentially does a "fold (build1 (code, type, node))" while checking
9794 for certain housekeeping things.
9795
9796 NOTE: for building an ADDR_EXPR around a FUNCTION_DECL, use
9797 ffecom_1_fn instead. */
9798
9799 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9800 tree
9801 ffecom_1 (enum tree_code code, tree type, tree node)
9802 {
9803 tree item;
9804
9805 if ((node == error_mark_node)
9806 || (type == error_mark_node))
9807 return error_mark_node;
9808
9809 if (code == ADDR_EXPR)
9810 {
9811 if (!mark_addressable (node))
9812 assert ("can't mark_addressable this node!" == NULL);
9813 }
9814
9815 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
9816 {
9817 tree realtype;
9818
9819 case REALPART_EXPR:
9820 item = build (COMPONENT_REF, type, node, TYPE_FIELDS (TREE_TYPE (node)));
9821 break;
9822
9823 case IMAGPART_EXPR:
9824 item = build (COMPONENT_REF, type, node, TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (node))));
9825 break;
9826
9827
9828 case NEGATE_EXPR:
9829 if (TREE_CODE (type) != RECORD_TYPE)
9830 {
9831 item = build1 (code, type, node);
9832 break;
9833 }
9834 node = ffecom_stabilize_aggregate_ (node);
9835 realtype = TREE_TYPE (TYPE_FIELDS (type));
9836 item =
9837 ffecom_2 (COMPLEX_EXPR, type,
9838 ffecom_1 (NEGATE_EXPR, realtype,
9839 ffecom_1 (REALPART_EXPR, realtype,
9840 node)),
9841 ffecom_1 (NEGATE_EXPR, realtype,
9842 ffecom_1 (IMAGPART_EXPR, realtype,
9843 node)));
9844 break;
9845
9846 default:
9847 item = build1 (code, type, node);
9848 break;
9849 }
9850
9851 if (TREE_SIDE_EFFECTS (node))
9852 TREE_SIDE_EFFECTS (item) = 1;
9853 if ((code == ADDR_EXPR) && staticp (node))
9854 TREE_CONSTANT (item) = 1;
9855 return fold (item);
9856 }
9857 #endif
9858
9859 /* Like ffecom_1 (ADDR_EXPR, TREE_TYPE (node), node), except
9860 handles TREE_CODE (node) == FUNCTION_DECL. In particular,
9861 does not set TREE_ADDRESSABLE (because calling an inline
9862 function does not mean the function needs to be separately
9863 compiled). */
9864
9865 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9866 tree
9867 ffecom_1_fn (tree node)
9868 {
9869 tree item;
9870 tree type;
9871
9872 if (node == error_mark_node)
9873 return error_mark_node;
9874
9875 type = build_type_variant (TREE_TYPE (node),
9876 TREE_READONLY (node),
9877 TREE_THIS_VOLATILE (node));
9878 item = build1 (ADDR_EXPR,
9879 build_pointer_type (type), node);
9880 if (TREE_SIDE_EFFECTS (node))
9881 TREE_SIDE_EFFECTS (item) = 1;
9882 if (staticp (node))
9883 TREE_CONSTANT (item) = 1;
9884 return fold (item);
9885 }
9886 #endif
9887
9888 /* Essentially does a "fold (build (code, type, node1, node2))" while
9889 checking for certain housekeeping things. */
9890
9891 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9892 tree
9893 ffecom_2 (enum tree_code code, tree type, tree node1,
9894 tree node2)
9895 {
9896 tree item;
9897
9898 if ((node1 == error_mark_node)
9899 || (node2 == error_mark_node)
9900 || (type == error_mark_node))
9901 return error_mark_node;
9902
9903 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
9904 {
9905 tree a, b, c, d, realtype;
9906
9907 case CONJ_EXPR:
9908 assert ("no CONJ_EXPR support yet" == NULL);
9909 return error_mark_node;
9910
9911 case COMPLEX_EXPR:
9912 item = build_tree_list (TYPE_FIELDS (type), node1);
9913 TREE_CHAIN (item) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), node2);
9914 item = build (CONSTRUCTOR, type, NULL_TREE, item);
9915 break;
9916
9917 case PLUS_EXPR:
9918 if (TREE_CODE (type) != RECORD_TYPE)
9919 {
9920 item = build (code, type, node1, node2);
9921 break;
9922 }
9923 node1 = ffecom_stabilize_aggregate_ (node1);
9924 node2 = ffecom_stabilize_aggregate_ (node2);
9925 realtype = TREE_TYPE (TYPE_FIELDS (type));
9926 item =
9927 ffecom_2 (COMPLEX_EXPR, type,
9928 ffecom_2 (PLUS_EXPR, realtype,
9929 ffecom_1 (REALPART_EXPR, realtype,
9930 node1),
9931 ffecom_1 (REALPART_EXPR, realtype,
9932 node2)),
9933 ffecom_2 (PLUS_EXPR, realtype,
9934 ffecom_1 (IMAGPART_EXPR, realtype,
9935 node1),
9936 ffecom_1 (IMAGPART_EXPR, realtype,
9937 node2)));
9938 break;
9939
9940 case MINUS_EXPR:
9941 if (TREE_CODE (type) != RECORD_TYPE)
9942 {
9943 item = build (code, type, node1, node2);
9944 break;
9945 }
9946 node1 = ffecom_stabilize_aggregate_ (node1);
9947 node2 = ffecom_stabilize_aggregate_ (node2);
9948 realtype = TREE_TYPE (TYPE_FIELDS (type));
9949 item =
9950 ffecom_2 (COMPLEX_EXPR, type,
9951 ffecom_2 (MINUS_EXPR, realtype,
9952 ffecom_1 (REALPART_EXPR, realtype,
9953 node1),
9954 ffecom_1 (REALPART_EXPR, realtype,
9955 node2)),
9956 ffecom_2 (MINUS_EXPR, realtype,
9957 ffecom_1 (IMAGPART_EXPR, realtype,
9958 node1),
9959 ffecom_1 (IMAGPART_EXPR, realtype,
9960 node2)));
9961 break;
9962
9963 case MULT_EXPR:
9964 if (TREE_CODE (type) != RECORD_TYPE)
9965 {
9966 item = build (code, type, node1, node2);
9967 break;
9968 }
9969 node1 = ffecom_stabilize_aggregate_ (node1);
9970 node2 = ffecom_stabilize_aggregate_ (node2);
9971 realtype = TREE_TYPE (TYPE_FIELDS (type));
9972 a = save_expr (ffecom_1 (REALPART_EXPR, realtype,
9973 node1));
9974 b = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
9975 node1));
9976 c = save_expr (ffecom_1 (REALPART_EXPR, realtype,
9977 node2));
9978 d = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
9979 node2));
9980 item =
9981 ffecom_2 (COMPLEX_EXPR, type,
9982 ffecom_2 (MINUS_EXPR, realtype,
9983 ffecom_2 (MULT_EXPR, realtype,
9984 a,
9985 c),
9986 ffecom_2 (MULT_EXPR, realtype,
9987 b,
9988 d)),
9989 ffecom_2 (PLUS_EXPR, realtype,
9990 ffecom_2 (MULT_EXPR, realtype,
9991 a,
9992 d),
9993 ffecom_2 (MULT_EXPR, realtype,
9994 c,
9995 b)));
9996 break;
9997
9998 case EQ_EXPR:
9999 if ((TREE_CODE (node1) != RECORD_TYPE)
10000 && (TREE_CODE (node2) != RECORD_TYPE))
10001 {
10002 item = build (code, type, node1, node2);
10003 break;
10004 }
10005 assert (TREE_CODE (node1) == RECORD_TYPE);
10006 assert (TREE_CODE (node2) == RECORD_TYPE);
10007 node1 = ffecom_stabilize_aggregate_ (node1);
10008 node2 = ffecom_stabilize_aggregate_ (node2);
10009 realtype = TREE_TYPE (TYPE_FIELDS (type));
10010 item =
10011 ffecom_2 (TRUTH_ANDIF_EXPR, type,
10012 ffecom_2 (code, type,
10013 ffecom_1 (REALPART_EXPR, realtype,
10014 node1),
10015 ffecom_1 (REALPART_EXPR, realtype,
10016 node2)),
10017 ffecom_2 (code, type,
10018 ffecom_1 (IMAGPART_EXPR, realtype,
10019 node1),
10020 ffecom_1 (IMAGPART_EXPR, realtype,
10021 node2)));
10022 break;
10023
10024 case NE_EXPR:
10025 if ((TREE_CODE (node1) != RECORD_TYPE)
10026 && (TREE_CODE (node2) != RECORD_TYPE))
10027 {
10028 item = build (code, type, node1, node2);
10029 break;
10030 }
10031 assert (TREE_CODE (node1) == RECORD_TYPE);
10032 assert (TREE_CODE (node2) == RECORD_TYPE);
10033 node1 = ffecom_stabilize_aggregate_ (node1);
10034 node2 = ffecom_stabilize_aggregate_ (node2);
10035 realtype = TREE_TYPE (TYPE_FIELDS (type));
10036 item =
10037 ffecom_2 (TRUTH_ORIF_EXPR, type,
10038 ffecom_2 (code, type,
10039 ffecom_1 (REALPART_EXPR, realtype,
10040 node1),
10041 ffecom_1 (REALPART_EXPR, realtype,
10042 node2)),
10043 ffecom_2 (code, type,
10044 ffecom_1 (IMAGPART_EXPR, realtype,
10045 node1),
10046 ffecom_1 (IMAGPART_EXPR, realtype,
10047 node2)));
10048 break;
10049
10050 default:
10051 item = build (code, type, node1, node2);
10052 break;
10053 }
10054
10055 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2))
10056 TREE_SIDE_EFFECTS (item) = 1;
10057 return fold (item);
10058 }
10059
10060 #endif
10061 /* ffecom_2pass_advise_entrypoint -- Advise that there's this entrypoint
10062
10063 ffesymbol s; // the ENTRY point itself
10064 if (ffecom_2pass_advise_entrypoint(s))
10065 // the ENTRY point has been accepted
10066
10067 Does whatever compiler needs to do when it learns about the entrypoint,
10068 like determine the return type of the master function, count the
10069 number of entrypoints, etc. Returns FALSE if the return type is
10070 not compatible with the return type(s) of other entrypoint(s).
10071
10072 NOTE: for every call to this fn that returns TRUE, _do_entrypoint must
10073 later (after _finish_progunit) be called with the same entrypoint(s)
10074 as passed to this fn for which TRUE was returned.
10075
10076 03-Jan-92 JCB 2.0
10077 Return FALSE if the return type conflicts with previous entrypoints. */
10078
10079 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10080 bool
10081 ffecom_2pass_advise_entrypoint (ffesymbol entry)
10082 {
10083 ffebld list; /* opITEM. */
10084 ffebld mlist; /* opITEM. */
10085 ffebld plist; /* opITEM. */
10086 ffebld arg; /* ffebld_head(opITEM). */
10087 ffebld item; /* opITEM. */
10088 ffesymbol s; /* ffebld_symter(arg). */
10089 ffeinfoBasictype bt = ffesymbol_basictype (entry);
10090 ffeinfoKindtype kt = ffesymbol_kindtype (entry);
10091 ffetargetCharacterSize size = ffesymbol_size (entry);
10092 bool ok;
10093
10094 if (ffecom_num_entrypoints_ == 0)
10095 { /* First entrypoint, make list of main
10096 arglist's dummies. */
10097 assert (ffecom_primary_entry_ != NULL);
10098
10099 ffecom_master_bt_ = ffesymbol_basictype (ffecom_primary_entry_);
10100 ffecom_master_kt_ = ffesymbol_kindtype (ffecom_primary_entry_);
10101 ffecom_master_size_ = ffesymbol_size (ffecom_primary_entry_);
10102
10103 for (plist = NULL, list = ffesymbol_dummyargs (ffecom_primary_entry_);
10104 list != NULL;
10105 list = ffebld_trail (list))
10106 {
10107 arg = ffebld_head (list);
10108 if (ffebld_op (arg) != FFEBLD_opSYMTER)
10109 continue; /* Alternate return or some such thing. */
10110 item = ffebld_new_item (arg, NULL);
10111 if (plist == NULL)
10112 ffecom_master_arglist_ = item;
10113 else
10114 ffebld_set_trail (plist, item);
10115 plist = item;
10116 }
10117 }
10118
10119 /* If necessary, scan entry arglist for alternate returns. Do this scan
10120 apparently redundantly (it's done below to UNIONize the arglists) so
10121 that we don't complain about RETURN 1 if an offending ENTRY is the only
10122 one with an alternate return. */
10123
10124 if (!ffecom_is_altreturning_)
10125 {
10126 for (list = ffesymbol_dummyargs (entry);
10127 list != NULL;
10128 list = ffebld_trail (list))
10129 {
10130 arg = ffebld_head (list);
10131 if (ffebld_op (arg) == FFEBLD_opSTAR)
10132 {
10133 ffecom_is_altreturning_ = TRUE;
10134 break;
10135 }
10136 }
10137 }
10138
10139 /* Now check type compatibility. */
10140
10141 switch (ffecom_master_bt_)
10142 {
10143 case FFEINFO_basictypeNONE:
10144 ok = (bt != FFEINFO_basictypeCHARACTER);
10145 break;
10146
10147 case FFEINFO_basictypeCHARACTER:
10148 ok
10149 = (bt == FFEINFO_basictypeCHARACTER)
10150 && (kt == ffecom_master_kt_)
10151 && (size == ffecom_master_size_);
10152 break;
10153
10154 case FFEINFO_basictypeANY:
10155 return FALSE; /* Just don't bother. */
10156
10157 default:
10158 if (bt == FFEINFO_basictypeCHARACTER)
10159 {
10160 ok = FALSE;
10161 break;
10162 }
10163 ok = TRUE;
10164 if ((bt != ffecom_master_bt_) || (kt != ffecom_master_kt_))
10165 {
10166 ffecom_master_bt_ = FFEINFO_basictypeNONE;
10167 ffecom_master_kt_ = FFEINFO_kindtypeNONE;
10168 }
10169 break;
10170 }
10171
10172 if (!ok)
10173 {
10174 ffebad_start (FFEBAD_ENTRY_CONFLICTS);
10175 ffest_ffebad_here_current_stmt (0);
10176 ffebad_finish ();
10177 return FALSE; /* Can't handle entrypoint. */
10178 }
10179
10180 /* Entrypoint type compatible with previous types. */
10181
10182 ++ffecom_num_entrypoints_;
10183
10184 /* Master-arg-list = UNION(Master-arg-list,entry-arg-list). */
10185
10186 for (list = ffesymbol_dummyargs (entry);
10187 list != NULL;
10188 list = ffebld_trail (list))
10189 {
10190 arg = ffebld_head (list);
10191 if (ffebld_op (arg) != FFEBLD_opSYMTER)
10192 continue; /* Alternate return or some such thing. */
10193 s = ffebld_symter (arg);
10194 for (plist = NULL, mlist = ffecom_master_arglist_;
10195 mlist != NULL;
10196 plist = mlist, mlist = ffebld_trail (mlist))
10197 { /* plist points to previous item for easy
10198 appending of arg. */
10199 if (ffebld_symter (ffebld_head (mlist)) == s)
10200 break; /* Already have this arg in the master list. */
10201 }
10202 if (mlist != NULL)
10203 continue; /* Already have this arg in the master list. */
10204
10205 /* Append this arg to the master list. */
10206
10207 item = ffebld_new_item (arg, NULL);
10208 if (plist == NULL)
10209 ffecom_master_arglist_ = item;
10210 else
10211 ffebld_set_trail (plist, item);
10212 }
10213
10214 return TRUE;
10215 }
10216
10217 #endif
10218 /* ffecom_2pass_do_entrypoint -- Do compilation of entrypoint
10219
10220 ffesymbol s; // the ENTRY point itself
10221 ffecom_2pass_do_entrypoint(s);
10222
10223 Does whatever compiler needs to do to make the entrypoint actually
10224 happen. Must be called for each entrypoint after
10225 ffecom_finish_progunit is called. */
10226
10227 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10228 void
10229 ffecom_2pass_do_entrypoint (ffesymbol entry)
10230 {
10231 static int mfn_num = 0;
10232 static int ent_num;
10233
10234 if (mfn_num != ffecom_num_fns_)
10235 { /* First entrypoint for this program unit. */
10236 ent_num = 1;
10237 mfn_num = ffecom_num_fns_;
10238 ffecom_do_entry_ (ffecom_primary_entry_, 0);
10239 }
10240 else
10241 ++ent_num;
10242
10243 --ffecom_num_entrypoints_;
10244
10245 ffecom_do_entry_ (entry, ent_num);
10246 }
10247
10248 #endif
10249
10250 /* Essentially does a "fold (build (code, type, node1, node2))" while
10251 checking for certain housekeeping things. Always sets
10252 TREE_SIDE_EFFECTS. */
10253
10254 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10255 tree
10256 ffecom_2s (enum tree_code code, tree type, tree node1,
10257 tree node2)
10258 {
10259 tree item;
10260
10261 if ((node1 == error_mark_node)
10262 || (node2 == error_mark_node)
10263 || (type == error_mark_node))
10264 return error_mark_node;
10265
10266 item = build (code, type, node1, node2);
10267 TREE_SIDE_EFFECTS (item) = 1;
10268 return fold (item);
10269 }
10270
10271 #endif
10272 /* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10273 checking for certain housekeeping things. */
10274
10275 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10276 tree
10277 ffecom_3 (enum tree_code code, tree type, tree node1,
10278 tree node2, tree node3)
10279 {
10280 tree item;
10281
10282 if ((node1 == error_mark_node)
10283 || (node2 == error_mark_node)
10284 || (node3 == error_mark_node)
10285 || (type == error_mark_node))
10286 return error_mark_node;
10287
10288 item = build (code, type, node1, node2, node3);
10289 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2)
10290 || (node3 != NULL_TREE && TREE_SIDE_EFFECTS (node3)))
10291 TREE_SIDE_EFFECTS (item) = 1;
10292 return fold (item);
10293 }
10294
10295 #endif
10296 /* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10297 checking for certain housekeeping things. Always sets
10298 TREE_SIDE_EFFECTS. */
10299
10300 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10301 tree
10302 ffecom_3s (enum tree_code code, tree type, tree node1,
10303 tree node2, tree node3)
10304 {
10305 tree item;
10306
10307 if ((node1 == error_mark_node)
10308 || (node2 == error_mark_node)
10309 || (node3 == error_mark_node)
10310 || (type == error_mark_node))
10311 return error_mark_node;
10312
10313 item = build (code, type, node1, node2, node3);
10314 TREE_SIDE_EFFECTS (item) = 1;
10315 return fold (item);
10316 }
10317
10318 #endif
10319
10320 /* ffecom_arg_expr -- Transform argument expr into gcc tree
10321
10322 See use by ffecom_list_expr.
10323
10324 If expression is NULL, returns an integer zero tree. If it is not
10325 a CHARACTER expression, returns whatever ffecom_expr
10326 returns and sets the length return value to NULL_TREE. Otherwise
10327 generates code to evaluate the character expression, returns the proper
10328 pointer to the result, but does NOT set the length return value to a tree
10329 that specifies the length of the result. (In other words, the length
10330 variable is always set to NULL_TREE, because a length is never passed.)
10331
10332 21-Dec-91 JCB 1.1
10333 Don't set returned length, since nobody needs it (yet; someday if
10334 we allow CHARACTER*(*) dummies to statement functions, we'll need
10335 it). */
10336
10337 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10338 tree
10339 ffecom_arg_expr (ffebld expr, tree *length)
10340 {
10341 tree ign;
10342
10343 *length = NULL_TREE;
10344
10345 if (expr == NULL)
10346 return integer_zero_node;
10347
10348 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10349 return ffecom_expr (expr);
10350
10351 return ffecom_arg_ptr_to_expr (expr, &ign);
10352 }
10353
10354 #endif
10355 /* Transform expression into constant argument-pointer-to-expression tree.
10356
10357 If the expression can be transformed into a argument-pointer-to-expression
10358 tree that is constant, that is done, and the tree returned. Else
10359 NULL_TREE is returned.
10360
10361 That way, a caller can attempt to provide compile-time initialization
10362 of a variable and, if that fails, *then* choose to start a new block
10363 and resort to using temporaries, as appropriate. */
10364
10365 tree
10366 ffecom_arg_ptr_to_const_expr (ffebld expr, tree *length)
10367 {
10368 if (! expr)
10369 return integer_zero_node;
10370
10371 if (ffebld_op (expr) == FFEBLD_opANY)
10372 {
10373 if (length)
10374 *length = error_mark_node;
10375 return error_mark_node;
10376 }
10377
10378 if (ffebld_arity (expr) == 0
10379 && (ffebld_op (expr) != FFEBLD_opSYMTER
10380 || ffebld_where (expr) == FFEINFO_whereCOMMON
10381 || ffebld_where (expr) == FFEINFO_whereGLOBAL
10382 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
10383 {
10384 tree t;
10385
10386 t = ffecom_arg_ptr_to_expr (expr, length);
10387 assert (TREE_CONSTANT (t));
10388 assert (! length || TREE_CONSTANT (*length));
10389 return t;
10390 }
10391
10392 if (length
10393 && ffebld_size (expr) != FFETARGET_charactersizeNONE)
10394 *length = build_int_2 (ffebld_size (expr), 0);
10395 else if (length)
10396 *length = NULL_TREE;
10397 return NULL_TREE;
10398 }
10399
10400 /* ffecom_arg_ptr_to_expr -- Transform argument expr into gcc tree
10401
10402 See use by ffecom_list_ptr_to_expr.
10403
10404 If expression is NULL, returns an integer zero tree. If it is not
10405 a CHARACTER expression, returns whatever ffecom_ptr_to_expr
10406 returns and sets the length return value to NULL_TREE. Otherwise
10407 generates code to evaluate the character expression, returns the proper
10408 pointer to the result, AND sets the length return value to a tree that
10409 specifies the length of the result.
10410
10411 If the length argument is NULL, this is a slightly special
10412 case of building a FORMAT expression, that is, an expression that
10413 will be used at run time without regard to length. For the current
10414 implementation, which uses the libf2c library, this means it is nice
10415 to append a null byte to the end of the expression, where feasible,
10416 to make sure any diagnostic about the FORMAT string terminates at
10417 some useful point.
10418
10419 For now, treat %REF(char-expr) as the same as char-expr with a NULL
10420 length argument. This might even be seen as a feature, if a null
10421 byte can always be appended. */
10422
10423 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10424 tree
10425 ffecom_arg_ptr_to_expr (ffebld expr, tree *length)
10426 {
10427 tree item;
10428 tree ign_length;
10429 ffecomConcatList_ catlist;
10430
10431 if (length != NULL)
10432 *length = NULL_TREE;
10433
10434 if (expr == NULL)
10435 return integer_zero_node;
10436
10437 switch (ffebld_op (expr))
10438 {
10439 case FFEBLD_opPERCENT_VAL:
10440 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10441 return ffecom_expr (ffebld_left (expr));
10442 {
10443 tree temp_exp;
10444 tree temp_length;
10445
10446 temp_exp = ffecom_arg_ptr_to_expr (ffebld_left (expr), &temp_length);
10447 if (temp_exp == error_mark_node)
10448 return error_mark_node;
10449
10450 return ffecom_1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (temp_exp)),
10451 temp_exp);
10452 }
10453
10454 case FFEBLD_opPERCENT_REF:
10455 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10456 return ffecom_ptr_to_expr (ffebld_left (expr));
10457 if (length != NULL)
10458 {
10459 ign_length = NULL_TREE;
10460 length = &ign_length;
10461 }
10462 expr = ffebld_left (expr);
10463 break;
10464
10465 case FFEBLD_opPERCENT_DESCR:
10466 switch (ffeinfo_basictype (ffebld_info (expr)))
10467 {
10468 #ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10469 case FFEINFO_basictypeHOLLERITH:
10470 #endif
10471 case FFEINFO_basictypeCHARACTER:
10472 break; /* Passed by descriptor anyway. */
10473
10474 default:
10475 item = ffecom_ptr_to_expr (expr);
10476 if (item != error_mark_node)
10477 *length = TYPE_SIZE (TREE_TYPE (TREE_TYPE (item)));
10478 break;
10479 }
10480 break;
10481
10482 default:
10483 break;
10484 }
10485
10486 #ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10487 if ((ffeinfo_basictype (ffebld_info (expr)) == FFEINFO_basictypeHOLLERITH)
10488 && (length != NULL))
10489 { /* Pass Hollerith by descriptor. */
10490 ffetargetHollerith h;
10491
10492 assert (ffebld_op (expr) == FFEBLD_opCONTER);
10493 h = ffebld_cu_val_hollerith (ffebld_constant_union
10494 (ffebld_conter (expr)));
10495 *length
10496 = build_int_2 (h.length, 0);
10497 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10498 }
10499 #endif
10500
10501 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10502 return ffecom_ptr_to_expr (expr);
10503
10504 assert (ffeinfo_kindtype (ffebld_info (expr))
10505 == FFEINFO_kindtypeCHARACTER1);
10506
10507 while (ffebld_op (expr) == FFEBLD_opPAREN)
10508 expr = ffebld_left (expr);
10509
10510 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
10511 switch (ffecom_concat_list_count_ (catlist))
10512 {
10513 case 0: /* Shouldn't happen, but in case it does... */
10514 if (length != NULL)
10515 {
10516 *length = ffecom_f2c_ftnlen_zero_node;
10517 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10518 }
10519 ffecom_concat_list_kill_ (catlist);
10520 return null_pointer_node;
10521
10522 case 1: /* The (fairly) easy case. */
10523 if (length == NULL)
10524 ffecom_char_args_with_null_ (&item, &ign_length,
10525 ffecom_concat_list_expr_ (catlist, 0));
10526 else
10527 ffecom_char_args_ (&item, length,
10528 ffecom_concat_list_expr_ (catlist, 0));
10529 ffecom_concat_list_kill_ (catlist);
10530 assert (item != NULL_TREE);
10531 return item;
10532
10533 default: /* Must actually concatenate things. */
10534 break;
10535 }
10536
10537 {
10538 int count = ffecom_concat_list_count_ (catlist);
10539 int i;
10540 tree lengths;
10541 tree items;
10542 tree length_array;
10543 tree item_array;
10544 tree citem;
10545 tree clength;
10546 tree temporary;
10547 tree num;
10548 tree known_length;
10549 ffetargetCharacterSize sz;
10550
10551 sz = ffecom_concat_list_maxlen_ (catlist);
10552 /* ~~Kludge! */
10553 assert (sz != FFETARGET_charactersizeNONE);
10554
10555 #ifdef HOHO
10556 length_array
10557 = lengths
10558 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
10559 FFETARGET_charactersizeNONE, count, TRUE);
10560 item_array
10561 = items
10562 = ffecom_push_tempvar (ffecom_f2c_address_type_node,
10563 FFETARGET_charactersizeNONE, count, TRUE);
10564 temporary = ffecom_push_tempvar (char_type_node,
10565 sz, -1, TRUE);
10566 #else
10567 {
10568 tree hook;
10569
10570 hook = ffebld_nonter_hook (expr);
10571 assert (hook);
10572 assert (TREE_CODE (hook) == TREE_VEC);
10573 assert (TREE_VEC_LENGTH (hook) == 3);
10574 length_array = lengths = TREE_VEC_ELT (hook, 0);
10575 item_array = items = TREE_VEC_ELT (hook, 1);
10576 temporary = TREE_VEC_ELT (hook, 2);
10577 }
10578 #endif
10579
10580 known_length = ffecom_f2c_ftnlen_zero_node;
10581
10582 for (i = 0; i < count; ++i)
10583 {
10584 if ((i == count)
10585 && (length == NULL))
10586 ffecom_char_args_with_null_ (&citem, &clength,
10587 ffecom_concat_list_expr_ (catlist, i));
10588 else
10589 ffecom_char_args_ (&citem, &clength,
10590 ffecom_concat_list_expr_ (catlist, i));
10591 if ((citem == error_mark_node)
10592 || (clength == error_mark_node))
10593 {
10594 ffecom_concat_list_kill_ (catlist);
10595 *length = error_mark_node;
10596 return error_mark_node;
10597 }
10598
10599 items
10600 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
10601 ffecom_modify (void_type_node,
10602 ffecom_2 (ARRAY_REF,
10603 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
10604 item_array,
10605 build_int_2 (i, 0)),
10606 citem),
10607 items);
10608 clength = ffecom_save_tree (clength);
10609 if (length != NULL)
10610 known_length
10611 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
10612 known_length,
10613 clength);
10614 lengths
10615 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
10616 ffecom_modify (void_type_node,
10617 ffecom_2 (ARRAY_REF,
10618 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
10619 length_array,
10620 build_int_2 (i, 0)),
10621 clength),
10622 lengths);
10623 }
10624
10625 temporary = ffecom_1 (ADDR_EXPR,
10626 build_pointer_type (TREE_TYPE (temporary)),
10627 temporary);
10628
10629 item = build_tree_list (NULL_TREE, temporary);
10630 TREE_CHAIN (item)
10631 = build_tree_list (NULL_TREE,
10632 ffecom_1 (ADDR_EXPR,
10633 build_pointer_type (TREE_TYPE (items)),
10634 items));
10635 TREE_CHAIN (TREE_CHAIN (item))
10636 = build_tree_list (NULL_TREE,
10637 ffecom_1 (ADDR_EXPR,
10638 build_pointer_type (TREE_TYPE (lengths)),
10639 lengths));
10640 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
10641 = build_tree_list
10642 (NULL_TREE,
10643 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
10644 convert (ffecom_f2c_ftnlen_type_node,
10645 build_int_2 (count, 0))));
10646 num = build_int_2 (sz, 0);
10647 TREE_TYPE (num) = ffecom_f2c_ftnlen_type_node;
10648 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item))))
10649 = build_tree_list (NULL_TREE, num);
10650
10651 item = ffecom_call_gfrt (FFECOM_gfrtCAT, item, NULL_TREE);
10652 TREE_SIDE_EFFECTS (item) = 1;
10653 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (temporary),
10654 item,
10655 temporary);
10656
10657 if (length != NULL)
10658 *length = known_length;
10659 }
10660
10661 ffecom_concat_list_kill_ (catlist);
10662 assert (item != NULL_TREE);
10663 return item;
10664 }
10665
10666 #endif
10667 /* Generate call to run-time function.
10668
10669 The first arg is the GNU Fortran Run-Time function index, the second
10670 arg is the list of arguments to pass to it. Returned is the expression
10671 (WITHOUT TREE_SIDE_EFFECTS set!) that makes the call and returns the
10672 result (which may be void). */
10673
10674 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10675 tree
10676 ffecom_call_gfrt (ffecomGfrt ix, tree args, tree hook)
10677 {
10678 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
10679 ffecom_gfrt_kindtype (ix),
10680 ffe_is_f2c_library () && ffecom_gfrt_complex_[ix],
10681 NULL_TREE, args, NULL_TREE, NULL,
10682 NULL, NULL_TREE, TRUE, hook);
10683 }
10684 #endif
10685
10686 /* Transform constant-union to tree. */
10687
10688 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10689 tree
10690 ffecom_constantunion (ffebldConstantUnion *cu, ffeinfoBasictype bt,
10691 ffeinfoKindtype kt, tree tree_type)
10692 {
10693 tree item;
10694
10695 switch (bt)
10696 {
10697 case FFEINFO_basictypeINTEGER:
10698 {
10699 int val;
10700
10701 switch (kt)
10702 {
10703 #if FFETARGET_okINTEGER1
10704 case FFEINFO_kindtypeINTEGER1:
10705 val = ffebld_cu_val_integer1 (*cu);
10706 break;
10707 #endif
10708
10709 #if FFETARGET_okINTEGER2
10710 case FFEINFO_kindtypeINTEGER2:
10711 val = ffebld_cu_val_integer2 (*cu);
10712 break;
10713 #endif
10714
10715 #if FFETARGET_okINTEGER3
10716 case FFEINFO_kindtypeINTEGER3:
10717 val = ffebld_cu_val_integer3 (*cu);
10718 break;
10719 #endif
10720
10721 #if FFETARGET_okINTEGER4
10722 case FFEINFO_kindtypeINTEGER4:
10723 val = ffebld_cu_val_integer4 (*cu);
10724 break;
10725 #endif
10726
10727 default:
10728 assert ("bad INTEGER constant kind type" == NULL);
10729 /* Fall through. */
10730 case FFEINFO_kindtypeANY:
10731 return error_mark_node;
10732 }
10733 item = build_int_2 (val, (val < 0) ? -1 : 0);
10734 TREE_TYPE (item) = tree_type;
10735 }
10736 break;
10737
10738 case FFEINFO_basictypeLOGICAL:
10739 {
10740 int val;
10741
10742 switch (kt)
10743 {
10744 #if FFETARGET_okLOGICAL1
10745 case FFEINFO_kindtypeLOGICAL1:
10746 val = ffebld_cu_val_logical1 (*cu);
10747 break;
10748 #endif
10749
10750 #if FFETARGET_okLOGICAL2
10751 case FFEINFO_kindtypeLOGICAL2:
10752 val = ffebld_cu_val_logical2 (*cu);
10753 break;
10754 #endif
10755
10756 #if FFETARGET_okLOGICAL3
10757 case FFEINFO_kindtypeLOGICAL3:
10758 val = ffebld_cu_val_logical3 (*cu);
10759 break;
10760 #endif
10761
10762 #if FFETARGET_okLOGICAL4
10763 case FFEINFO_kindtypeLOGICAL4:
10764 val = ffebld_cu_val_logical4 (*cu);
10765 break;
10766 #endif
10767
10768 default:
10769 assert ("bad LOGICAL constant kind type" == NULL);
10770 /* Fall through. */
10771 case FFEINFO_kindtypeANY:
10772 return error_mark_node;
10773 }
10774 item = build_int_2 (val, (val < 0) ? -1 : 0);
10775 TREE_TYPE (item) = tree_type;
10776 }
10777 break;
10778
10779 case FFEINFO_basictypeREAL:
10780 {
10781 REAL_VALUE_TYPE val;
10782
10783 switch (kt)
10784 {
10785 #if FFETARGET_okREAL1
10786 case FFEINFO_kindtypeREAL1:
10787 val = ffetarget_value_real1 (ffebld_cu_val_real1 (*cu));
10788 break;
10789 #endif
10790
10791 #if FFETARGET_okREAL2
10792 case FFEINFO_kindtypeREAL2:
10793 val = ffetarget_value_real2 (ffebld_cu_val_real2 (*cu));
10794 break;
10795 #endif
10796
10797 #if FFETARGET_okREAL3
10798 case FFEINFO_kindtypeREAL3:
10799 val = ffetarget_value_real3 (ffebld_cu_val_real3 (*cu));
10800 break;
10801 #endif
10802
10803 #if FFETARGET_okREAL4
10804 case FFEINFO_kindtypeREAL4:
10805 val = ffetarget_value_real4 (ffebld_cu_val_real4 (*cu));
10806 break;
10807 #endif
10808
10809 default:
10810 assert ("bad REAL constant kind type" == NULL);
10811 /* Fall through. */
10812 case FFEINFO_kindtypeANY:
10813 return error_mark_node;
10814 }
10815 item = build_real (tree_type, val);
10816 }
10817 break;
10818
10819 case FFEINFO_basictypeCOMPLEX:
10820 {
10821 REAL_VALUE_TYPE real;
10822 REAL_VALUE_TYPE imag;
10823 tree el_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
10824
10825 switch (kt)
10826 {
10827 #if FFETARGET_okCOMPLEX1
10828 case FFEINFO_kindtypeREAL1:
10829 real = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).real);
10830 imag = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).imaginary);
10831 break;
10832 #endif
10833
10834 #if FFETARGET_okCOMPLEX2
10835 case FFEINFO_kindtypeREAL2:
10836 real = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).real);
10837 imag = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).imaginary);
10838 break;
10839 #endif
10840
10841 #if FFETARGET_okCOMPLEX3
10842 case FFEINFO_kindtypeREAL3:
10843 real = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).real);
10844 imag = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).imaginary);
10845 break;
10846 #endif
10847
10848 #if FFETARGET_okCOMPLEX4
10849 case FFEINFO_kindtypeREAL4:
10850 real = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).real);
10851 imag = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).imaginary);
10852 break;
10853 #endif
10854
10855 default:
10856 assert ("bad REAL constant kind type" == NULL);
10857 /* Fall through. */
10858 case FFEINFO_kindtypeANY:
10859 return error_mark_node;
10860 }
10861 item = ffecom_build_complex_constant_ (tree_type,
10862 build_real (el_type, real),
10863 build_real (el_type, imag));
10864 }
10865 break;
10866
10867 case FFEINFO_basictypeCHARACTER:
10868 { /* Happens only in DATA and similar contexts. */
10869 ffetargetCharacter1 val;
10870
10871 switch (kt)
10872 {
10873 #if FFETARGET_okCHARACTER1
10874 case FFEINFO_kindtypeLOGICAL1:
10875 val = ffebld_cu_val_character1 (*cu);
10876 break;
10877 #endif
10878
10879 default:
10880 assert ("bad CHARACTER constant kind type" == NULL);
10881 /* Fall through. */
10882 case FFEINFO_kindtypeANY:
10883 return error_mark_node;
10884 }
10885 item = build_string (ffetarget_length_character1 (val),
10886 ffetarget_text_character1 (val));
10887 TREE_TYPE (item)
10888 = build_type_variant (build_array_type (char_type_node,
10889 build_range_type
10890 (integer_type_node,
10891 integer_one_node,
10892 build_int_2
10893 (ffetarget_length_character1
10894 (val), 0))),
10895 1, 0);
10896 }
10897 break;
10898
10899 case FFEINFO_basictypeHOLLERITH:
10900 {
10901 ffetargetHollerith h;
10902
10903 h = ffebld_cu_val_hollerith (*cu);
10904
10905 /* If not at least as wide as default INTEGER, widen it. */
10906 if (h.length >= FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE)
10907 item = build_string (h.length, h.text);
10908 else
10909 {
10910 char str[FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE];
10911
10912 memcpy (str, h.text, h.length);
10913 memset (&str[h.length], ' ',
10914 FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE
10915 - h.length);
10916 item = build_string (FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE,
10917 str);
10918 }
10919 TREE_TYPE (item)
10920 = build_type_variant (build_array_type (char_type_node,
10921 build_range_type
10922 (integer_type_node,
10923 integer_one_node,
10924 build_int_2
10925 (h.length, 0))),
10926 1, 0);
10927 }
10928 break;
10929
10930 case FFEINFO_basictypeTYPELESS:
10931 {
10932 ffetargetInteger1 ival;
10933 ffetargetTypeless tless;
10934 ffebad error;
10935
10936 tless = ffebld_cu_val_typeless (*cu);
10937 error = ffetarget_convert_integer1_typeless (&ival, tless);
10938 assert (error == FFEBAD);
10939
10940 item = build_int_2 ((int) ival, 0);
10941 }
10942 break;
10943
10944 default:
10945 assert ("not yet on constant type" == NULL);
10946 /* Fall through. */
10947 case FFEINFO_basictypeANY:
10948 return error_mark_node;
10949 }
10950
10951 TREE_CONSTANT (item) = 1;
10952
10953 return item;
10954 }
10955
10956 #endif
10957
10958 /* Transform expression into constant tree.
10959
10960 If the expression can be transformed into a tree that is constant,
10961 that is done, and the tree returned. Else NULL_TREE is returned.
10962
10963 That way, a caller can attempt to provide compile-time initialization
10964 of a variable and, if that fails, *then* choose to start a new block
10965 and resort to using temporaries, as appropriate. */
10966
10967 tree
10968 ffecom_const_expr (ffebld expr)
10969 {
10970 if (! expr)
10971 return integer_zero_node;
10972
10973 if (ffebld_op (expr) == FFEBLD_opANY)
10974 return error_mark_node;
10975
10976 if (ffebld_arity (expr) == 0
10977 && (ffebld_op (expr) != FFEBLD_opSYMTER
10978 #if NEWCOMMON
10979 /* ~~Enable once common/equivalence is handled properly? */
10980 || ffebld_where (expr) == FFEINFO_whereCOMMON
10981 #endif
10982 || ffebld_where (expr) == FFEINFO_whereGLOBAL
10983 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
10984 {
10985 tree t;
10986
10987 t = ffecom_expr (expr);
10988 assert (TREE_CONSTANT (t));
10989 return t;
10990 }
10991
10992 return NULL_TREE;
10993 }
10994
10995 /* Handy way to make a field in a struct/union. */
10996
10997 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10998 tree
10999 ffecom_decl_field (tree context, tree prevfield,
11000 const char *name, tree type)
11001 {
11002 tree field;
11003
11004 field = build_decl (FIELD_DECL, get_identifier (name), type);
11005 DECL_CONTEXT (field) = context;
11006 DECL_ALIGN (field) = 0;
11007 DECL_USER_ALIGN (field) = 0;
11008 if (prevfield != NULL_TREE)
11009 TREE_CHAIN (prevfield) = field;
11010
11011 return field;
11012 }
11013
11014 #endif
11015
11016 void
11017 ffecom_close_include (FILE *f)
11018 {
11019 #if FFECOM_GCC_INCLUDE
11020 ffecom_close_include_ (f);
11021 #endif
11022 }
11023
11024 int
11025 ffecom_decode_include_option (char *spec)
11026 {
11027 #if FFECOM_GCC_INCLUDE
11028 return ffecom_decode_include_option_ (spec);
11029 #else
11030 return 1;
11031 #endif
11032 }
11033
11034 /* End a compound statement (block). */
11035
11036 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11037 tree
11038 ffecom_end_compstmt (void)
11039 {
11040 return bison_rule_compstmt_ ();
11041 }
11042 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
11043
11044 /* ffecom_end_transition -- Perform end transition on all symbols
11045
11046 ffecom_end_transition();
11047
11048 Calls ffecom_sym_end_transition for each global and local symbol. */
11049
11050 void
11051 ffecom_end_transition ()
11052 {
11053 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11054 ffebld item;
11055 #endif
11056
11057 if (ffe_is_ffedebug ())
11058 fprintf (dmpout, "; end_stmt_transition\n");
11059
11060 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11061 ffecom_list_blockdata_ = NULL;
11062 ffecom_list_common_ = NULL;
11063 #endif
11064
11065 ffesymbol_drive (ffecom_sym_end_transition);
11066 if (ffe_is_ffedebug ())
11067 {
11068 ffestorag_report ();
11069 #if FFECOM_targetCURRENT == FFECOM_targetFFE
11070 ffesymbol_report_all ();
11071 #endif
11072 }
11073
11074 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11075 ffecom_start_progunit_ ();
11076
11077 for (item = ffecom_list_blockdata_;
11078 item != NULL;
11079 item = ffebld_trail (item))
11080 {
11081 ffebld callee;
11082 ffesymbol s;
11083 tree dt;
11084 tree t;
11085 tree var;
11086 int yes;
11087 static int number = 0;
11088
11089 callee = ffebld_head (item);
11090 s = ffebld_symter (callee);
11091 t = ffesymbol_hook (s).decl_tree;
11092 if (t == NULL_TREE)
11093 {
11094 s = ffecom_sym_transform_ (s);
11095 t = ffesymbol_hook (s).decl_tree;
11096 }
11097
11098 yes = suspend_momentary ();
11099
11100 dt = build_pointer_type (TREE_TYPE (t));
11101
11102 var = build_decl (VAR_DECL,
11103 ffecom_get_invented_identifier ("__g77_forceload_%d",
11104 number++),
11105 dt);
11106 DECL_EXTERNAL (var) = 0;
11107 TREE_STATIC (var) = 1;
11108 TREE_PUBLIC (var) = 0;
11109 DECL_INITIAL (var) = error_mark_node;
11110 TREE_USED (var) = 1;
11111
11112 var = start_decl (var, FALSE);
11113
11114 t = ffecom_1 (ADDR_EXPR, dt, t);
11115
11116 finish_decl (var, t, FALSE);
11117
11118 resume_momentary (yes);
11119 }
11120
11121 /* This handles any COMMON areas that weren't referenced but have, for
11122 example, important initial data. */
11123
11124 for (item = ffecom_list_common_;
11125 item != NULL;
11126 item = ffebld_trail (item))
11127 ffecom_transform_common_ (ffebld_symter (ffebld_head (item)));
11128
11129 ffecom_list_common_ = NULL;
11130 #endif
11131 }
11132
11133 /* ffecom_exec_transition -- Perform exec transition on all symbols
11134
11135 ffecom_exec_transition();
11136
11137 Calls ffecom_sym_exec_transition for each global and local symbol.
11138 Make sure error updating not inhibited. */
11139
11140 void
11141 ffecom_exec_transition ()
11142 {
11143 bool inhibited;
11144
11145 if (ffe_is_ffedebug ())
11146 fprintf (dmpout, "; exec_stmt_transition\n");
11147
11148 inhibited = ffebad_inhibit ();
11149 ffebad_set_inhibit (FALSE);
11150
11151 ffesymbol_drive (ffecom_sym_exec_transition); /* Don't retract! */
11152 ffeequiv_exec_transition (); /* Handle all pending EQUIVALENCEs. */
11153 if (ffe_is_ffedebug ())
11154 {
11155 ffestorag_report ();
11156 #if FFECOM_targetCURRENT == FFECOM_targetFFE
11157 ffesymbol_report_all ();
11158 #endif
11159 }
11160
11161 if (inhibited)
11162 ffebad_set_inhibit (TRUE);
11163 }
11164
11165 /* Handle assignment statement.
11166
11167 Convert dest and source using ffecom_expr, then join them
11168 with an ASSIGN op and pass the whole thing to expand_expr_stmt. */
11169
11170 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11171 void
11172 ffecom_expand_let_stmt (ffebld dest, ffebld source)
11173 {
11174 tree dest_tree;
11175 tree dest_length;
11176 tree source_tree;
11177 tree expr_tree;
11178
11179 if (ffeinfo_basictype (ffebld_info (dest)) != FFEINFO_basictypeCHARACTER)
11180 {
11181 bool dest_used;
11182 tree assign_temp;
11183
11184 /* This attempts to replicate the test below, but must not be
11185 true when the test below is false. (Always err on the side
11186 of creating unused temporaries, to avoid ICEs.) */
11187 if (ffebld_op (dest) != FFEBLD_opSYMTER
11188 || ((dest_tree = ffesymbol_hook (ffebld_symter (dest)).decl_tree)
11189 && (TREE_CODE (dest_tree) != VAR_DECL
11190 || TREE_ADDRESSABLE (dest_tree))))
11191 {
11192 ffecom_prepare_expr_ (source, dest);
11193 dest_used = TRUE;
11194 }
11195 else
11196 {
11197 ffecom_prepare_expr_ (source, NULL);
11198 dest_used = FALSE;
11199 }
11200
11201 ffecom_prepare_expr_w (NULL_TREE, dest);
11202
11203 /* For COMPLEX assignment like C1=C2, if partial overlap is possible,
11204 create a temporary through which the assignment is to take place,
11205 since MODIFY_EXPR doesn't handle partial overlap properly. */
11206 if (ffebld_basictype (dest) == FFEINFO_basictypeCOMPLEX
11207 && ffecom_possible_partial_overlap_ (dest, source))
11208 {
11209 assign_temp = ffecom_make_tempvar ("complex_let",
11210 ffecom_tree_type
11211 [ffebld_basictype (dest)]
11212 [ffebld_kindtype (dest)],
11213 FFETARGET_charactersizeNONE,
11214 -1);
11215 }
11216 else
11217 assign_temp = NULL_TREE;
11218
11219 ffecom_prepare_end ();
11220
11221 dest_tree = ffecom_expr_w (NULL_TREE, dest);
11222 if (dest_tree == error_mark_node)
11223 return;
11224
11225 if ((TREE_CODE (dest_tree) != VAR_DECL)
11226 || TREE_ADDRESSABLE (dest_tree))
11227 source_tree = ffecom_expr_ (source, dest_tree, dest, &dest_used,
11228 FALSE, FALSE);
11229 else
11230 {
11231 assert (! dest_used);
11232 dest_used = FALSE;
11233 source_tree = ffecom_expr (source);
11234 }
11235 if (source_tree == error_mark_node)
11236 return;
11237
11238 if (dest_used)
11239 expr_tree = source_tree;
11240 else if (assign_temp)
11241 {
11242 #ifdef MOVE_EXPR
11243 /* The back end understands a conceptual move (evaluate source;
11244 store into dest), so use that, in case it can determine
11245 that it is going to use, say, two registers as temporaries
11246 anyway. So don't use the temp (and someday avoid generating
11247 it, once this code starts triggering regularly). */
11248 expr_tree = ffecom_2s (MOVE_EXPR, void_type_node,
11249 dest_tree,
11250 source_tree);
11251 #else
11252 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11253 assign_temp,
11254 source_tree);
11255 expand_expr_stmt (expr_tree);
11256 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11257 dest_tree,
11258 assign_temp);
11259 #endif
11260 }
11261 else
11262 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11263 dest_tree,
11264 source_tree);
11265
11266 expand_expr_stmt (expr_tree);
11267 return;
11268 }
11269
11270 ffecom_prepare_let_char_ (ffebld_size_known (dest), source);
11271 ffecom_prepare_expr_w (NULL_TREE, dest);
11272
11273 ffecom_prepare_end ();
11274
11275 ffecom_char_args_ (&dest_tree, &dest_length, dest);
11276 ffecom_let_char_ (dest_tree, dest_length, ffebld_size_known (dest),
11277 source);
11278 }
11279
11280 #endif
11281 /* ffecom_expr -- Transform expr into gcc tree
11282
11283 tree t;
11284 ffebld expr; // FFE expression.
11285 tree = ffecom_expr(expr);
11286
11287 Recursive descent on expr while making corresponding tree nodes and
11288 attaching type info and such. */
11289
11290 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11291 tree
11292 ffecom_expr (ffebld expr)
11293 {
11294 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, FALSE, FALSE);
11295 }
11296
11297 #endif
11298 /* Like ffecom_expr, but return tree usable for assigned GOTO or FORMAT. */
11299
11300 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11301 tree
11302 ffecom_expr_assign (ffebld expr)
11303 {
11304 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
11305 }
11306
11307 #endif
11308 /* Like ffecom_expr_rw, but return tree usable for ASSIGN. */
11309
11310 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11311 tree
11312 ffecom_expr_assign_w (ffebld expr)
11313 {
11314 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
11315 }
11316
11317 #endif
11318 /* Transform expr for use as into read/write tree and stabilize the
11319 reference. Not for use on CHARACTER expressions.
11320
11321 Recursive descent on expr while making corresponding tree nodes and
11322 attaching type info and such. */
11323
11324 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11325 tree
11326 ffecom_expr_rw (tree type, ffebld expr)
11327 {
11328 assert (expr != NULL);
11329 /* Different target types not yet supported. */
11330 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
11331
11332 return stabilize_reference (ffecom_expr (expr));
11333 }
11334
11335 #endif
11336 /* Transform expr for use as into write tree and stabilize the
11337 reference. Not for use on CHARACTER expressions.
11338
11339 Recursive descent on expr while making corresponding tree nodes and
11340 attaching type info and such. */
11341
11342 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11343 tree
11344 ffecom_expr_w (tree type, ffebld expr)
11345 {
11346 assert (expr != NULL);
11347 /* Different target types not yet supported. */
11348 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
11349
11350 return stabilize_reference (ffecom_expr (expr));
11351 }
11352
11353 #endif
11354 /* Do global stuff. */
11355
11356 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11357 void
11358 ffecom_finish_compile ()
11359 {
11360 assert (ffecom_outer_function_decl_ == NULL_TREE);
11361 assert (current_function_decl == NULL_TREE);
11362
11363 ffeglobal_drive (ffecom_finish_global_);
11364 }
11365
11366 #endif
11367 /* Public entry point for front end to access finish_decl. */
11368
11369 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11370 void
11371 ffecom_finish_decl (tree decl, tree init, bool is_top_level)
11372 {
11373 assert (!is_top_level);
11374 finish_decl (decl, init, FALSE);
11375 }
11376
11377 #endif
11378 /* Finish a program unit. */
11379
11380 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11381 void
11382 ffecom_finish_progunit ()
11383 {
11384 ffecom_end_compstmt ();
11385
11386 ffecom_previous_function_decl_ = current_function_decl;
11387 ffecom_which_entrypoint_decl_ = NULL_TREE;
11388
11389 finish_function (0);
11390 }
11391
11392 #endif
11393
11394 /* Wrapper for get_identifier. pattern is sprintf-like. */
11395
11396 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11397 tree
11398 ffecom_get_invented_identifier (const char *pattern, ...)
11399 {
11400 tree decl;
11401 char *nam;
11402 va_list ap;
11403
11404 va_start (ap, pattern);
11405 if (vasprintf (&nam, pattern, ap) == 0)
11406 abort ();
11407 va_end (ap);
11408 decl = get_identifier (nam);
11409 free (nam);
11410 IDENTIFIER_INVENTED (decl) = 1;
11411 return decl;
11412 }
11413
11414 ffeinfoBasictype
11415 ffecom_gfrt_basictype (ffecomGfrt gfrt)
11416 {
11417 assert (gfrt < FFECOM_gfrt);
11418
11419 switch (ffecom_gfrt_type_[gfrt])
11420 {
11421 case FFECOM_rttypeVOID_:
11422 case FFECOM_rttypeVOIDSTAR_:
11423 return FFEINFO_basictypeNONE;
11424
11425 case FFECOM_rttypeFTNINT_:
11426 return FFEINFO_basictypeINTEGER;
11427
11428 case FFECOM_rttypeINTEGER_:
11429 return FFEINFO_basictypeINTEGER;
11430
11431 case FFECOM_rttypeLONGINT_:
11432 return FFEINFO_basictypeINTEGER;
11433
11434 case FFECOM_rttypeLOGICAL_:
11435 return FFEINFO_basictypeLOGICAL;
11436
11437 case FFECOM_rttypeREAL_F2C_:
11438 case FFECOM_rttypeREAL_GNU_:
11439 return FFEINFO_basictypeREAL;
11440
11441 case FFECOM_rttypeCOMPLEX_F2C_:
11442 case FFECOM_rttypeCOMPLEX_GNU_:
11443 return FFEINFO_basictypeCOMPLEX;
11444
11445 case FFECOM_rttypeDOUBLE_:
11446 case FFECOM_rttypeDOUBLEREAL_:
11447 return FFEINFO_basictypeREAL;
11448
11449 case FFECOM_rttypeDBLCMPLX_F2C_:
11450 case FFECOM_rttypeDBLCMPLX_GNU_:
11451 return FFEINFO_basictypeCOMPLEX;
11452
11453 case FFECOM_rttypeCHARACTER_:
11454 return FFEINFO_basictypeCHARACTER;
11455
11456 default:
11457 return FFEINFO_basictypeANY;
11458 }
11459 }
11460
11461 ffeinfoKindtype
11462 ffecom_gfrt_kindtype (ffecomGfrt gfrt)
11463 {
11464 assert (gfrt < FFECOM_gfrt);
11465
11466 switch (ffecom_gfrt_type_[gfrt])
11467 {
11468 case FFECOM_rttypeVOID_:
11469 case FFECOM_rttypeVOIDSTAR_:
11470 return FFEINFO_kindtypeNONE;
11471
11472 case FFECOM_rttypeFTNINT_:
11473 return FFEINFO_kindtypeINTEGER1;
11474
11475 case FFECOM_rttypeINTEGER_:
11476 return FFEINFO_kindtypeINTEGER1;
11477
11478 case FFECOM_rttypeLONGINT_:
11479 return FFEINFO_kindtypeINTEGER4;
11480
11481 case FFECOM_rttypeLOGICAL_:
11482 return FFEINFO_kindtypeLOGICAL1;
11483
11484 case FFECOM_rttypeREAL_F2C_:
11485 case FFECOM_rttypeREAL_GNU_:
11486 return FFEINFO_kindtypeREAL1;
11487
11488 case FFECOM_rttypeCOMPLEX_F2C_:
11489 case FFECOM_rttypeCOMPLEX_GNU_:
11490 return FFEINFO_kindtypeREAL1;
11491
11492 case FFECOM_rttypeDOUBLE_:
11493 case FFECOM_rttypeDOUBLEREAL_:
11494 return FFEINFO_kindtypeREAL2;
11495
11496 case FFECOM_rttypeDBLCMPLX_F2C_:
11497 case FFECOM_rttypeDBLCMPLX_GNU_:
11498 return FFEINFO_kindtypeREAL2;
11499
11500 case FFECOM_rttypeCHARACTER_:
11501 return FFEINFO_kindtypeCHARACTER1;
11502
11503 default:
11504 return FFEINFO_kindtypeANY;
11505 }
11506 }
11507
11508 void
11509 ffecom_init_0 ()
11510 {
11511 tree endlink;
11512 int i;
11513 int j;
11514 tree t;
11515 tree field;
11516 ffetype type;
11517 ffetype base_type;
11518 tree double_ftype_double;
11519 tree float_ftype_float;
11520 tree ldouble_ftype_ldouble;
11521 tree ffecom_tree_ptr_to_fun_type_void;
11522
11523 /* This block of code comes from the now-obsolete cktyps.c. It checks
11524 whether the compiler environment is buggy in known ways, some of which
11525 would, if not explicitly checked here, result in subtle bugs in g77. */
11526
11527 if (ffe_is_do_internal_checks ())
11528 {
11529 static char names[][12]
11530 =
11531 {"bar", "bletch", "foo", "foobar"};
11532 char *name;
11533 unsigned long ul;
11534 double fl;
11535
11536 name = bsearch ("foo", &names[0], ARRAY_SIZE (names), sizeof (names[0]),
11537 (int (*)(const void *, const void *)) strcmp);
11538 if (name != (char *) &names[2])
11539 {
11540 assert ("bsearch doesn't work, #define FFEPROJ_BSEARCH 0 in proj.h"
11541 == NULL);
11542 abort ();
11543 }
11544
11545 ul = strtoul ("123456789", NULL, 10);
11546 if (ul != 123456789L)
11547 {
11548 assert ("strtoul doesn't have enough range, #define FFEPROJ_STRTOUL 0\
11549 in proj.h" == NULL);
11550 abort ();
11551 }
11552
11553 fl = atof ("56.789");
11554 if ((fl < 56.788) || (fl > 56.79))
11555 {
11556 assert ("atof not type double, fix your #include <stdio.h>"
11557 == NULL);
11558 abort ();
11559 }
11560 }
11561
11562 #if FFECOM_GCC_INCLUDE
11563 ffecom_initialize_char_syntax_ ();
11564 #endif
11565
11566 ffecom_outer_function_decl_ = NULL_TREE;
11567 current_function_decl = NULL_TREE;
11568 named_labels = NULL_TREE;
11569 current_binding_level = NULL_BINDING_LEVEL;
11570 free_binding_level = NULL_BINDING_LEVEL;
11571 /* Make the binding_level structure for global names. */
11572 pushlevel (0);
11573 global_binding_level = current_binding_level;
11574 current_binding_level->prep_state = 2;
11575
11576 build_common_tree_nodes (1);
11577
11578 /* Define `int' and `char' first so that dbx will output them first. */
11579 pushdecl (build_decl (TYPE_DECL, get_identifier ("int"),
11580 integer_type_node));
11581 pushdecl (build_decl (TYPE_DECL, get_identifier ("char"),
11582 char_type_node));
11583 pushdecl (build_decl (TYPE_DECL, get_identifier ("long int"),
11584 long_integer_type_node));
11585 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned int"),
11586 unsigned_type_node));
11587 pushdecl (build_decl (TYPE_DECL, get_identifier ("long unsigned int"),
11588 long_unsigned_type_node));
11589 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long int"),
11590 long_long_integer_type_node));
11591 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"),
11592 long_long_unsigned_type_node));
11593 pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"),
11594 short_integer_type_node));
11595 pushdecl (build_decl (TYPE_DECL, get_identifier ("short unsigned int"),
11596 short_unsigned_type_node));
11597
11598 /* Set the sizetype before we make other types. This *should* be the
11599 first type we create. */
11600
11601 set_sizetype
11602 (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))));
11603 ffecom_typesize_pointer_
11604 = TREE_INT_CST_LOW (TYPE_SIZE (sizetype)) / BITS_PER_UNIT;
11605
11606 build_common_tree_nodes_2 (0);
11607
11608 /* Define both `signed char' and `unsigned char'. */
11609 pushdecl (build_decl (TYPE_DECL, get_identifier ("signed char"),
11610 signed_char_type_node));
11611
11612 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned char"),
11613 unsigned_char_type_node));
11614
11615 pushdecl (build_decl (TYPE_DECL, get_identifier ("float"),
11616 float_type_node));
11617 pushdecl (build_decl (TYPE_DECL, get_identifier ("double"),
11618 double_type_node));
11619 pushdecl (build_decl (TYPE_DECL, get_identifier ("long double"),
11620 long_double_type_node));
11621
11622 /* For now, override what build_common_tree_nodes has done. */
11623 complex_integer_type_node = ffecom_make_complex_type_ (integer_type_node);
11624 complex_float_type_node = ffecom_make_complex_type_ (float_type_node);
11625 complex_double_type_node = ffecom_make_complex_type_ (double_type_node);
11626 complex_long_double_type_node
11627 = ffecom_make_complex_type_ (long_double_type_node);
11628
11629 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"),
11630 complex_integer_type_node));
11631 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"),
11632 complex_float_type_node));
11633 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"),
11634 complex_double_type_node));
11635 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"),
11636 complex_long_double_type_node));
11637
11638 pushdecl (build_decl (TYPE_DECL, get_identifier ("void"),
11639 void_type_node));
11640 /* We are not going to have real types in C with less than byte alignment,
11641 so we might as well not have any types that claim to have it. */
11642 TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
11643 TYPE_USER_ALIGN (void_type_node) = 0;
11644
11645 string_type_node = build_pointer_type (char_type_node);
11646
11647 ffecom_tree_fun_type_void
11648 = build_function_type (void_type_node, NULL_TREE);
11649
11650 ffecom_tree_ptr_to_fun_type_void
11651 = build_pointer_type (ffecom_tree_fun_type_void);
11652
11653 endlink = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
11654
11655 float_ftype_float
11656 = build_function_type (float_type_node,
11657 tree_cons (NULL_TREE, float_type_node, endlink));
11658
11659 double_ftype_double
11660 = build_function_type (double_type_node,
11661 tree_cons (NULL_TREE, double_type_node, endlink));
11662
11663 ldouble_ftype_ldouble
11664 = build_function_type (long_double_type_node,
11665 tree_cons (NULL_TREE, long_double_type_node,
11666 endlink));
11667
11668 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11669 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11670 {
11671 ffecom_tree_type[i][j] = NULL_TREE;
11672 ffecom_tree_fun_type[i][j] = NULL_TREE;
11673 ffecom_tree_ptr_to_fun_type[i][j] = NULL_TREE;
11674 ffecom_f2c_typecode_[i][j] = -1;
11675 }
11676
11677 /* Set up standard g77 types. Note that INTEGER and LOGICAL are set
11678 to size FLOAT_TYPE_SIZE because they have to be the same size as
11679 REAL, which also is FLOAT_TYPE_SIZE, according to the standard.
11680 Compiler options and other such stuff that change the ways these
11681 types are set should not affect this particular setup. */
11682
11683 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1]
11684 = t = make_signed_type (FLOAT_TYPE_SIZE);
11685 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer"),
11686 t));
11687 type = ffetype_new ();
11688 base_type = type;
11689 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER1,
11690 type);
11691 ffetype_set_ams (type,
11692 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11693 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11694 ffetype_set_star (base_type,
11695 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11696 type);
11697 ffetype_set_kind (base_type, 1, type);
11698 ffecom_typesize_integer1_ = ffetype_size (type);
11699 assert (ffetype_size (type) == sizeof (ffetargetInteger1));
11700
11701 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER1]
11702 = t = make_unsigned_type (FLOAT_TYPE_SIZE); /* HOLLERITH means unsigned. */
11703 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned"),
11704 t));
11705
11706 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER2]
11707 = t = make_signed_type (CHAR_TYPE_SIZE);
11708 pushdecl (build_decl (TYPE_DECL, get_identifier ("byte"),
11709 t));
11710 type = ffetype_new ();
11711 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER2,
11712 type);
11713 ffetype_set_ams (type,
11714 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11715 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11716 ffetype_set_star (base_type,
11717 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11718 type);
11719 ffetype_set_kind (base_type, 3, type);
11720 assert (ffetype_size (type) == sizeof (ffetargetInteger2));
11721
11722 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER2]
11723 = t = make_unsigned_type (CHAR_TYPE_SIZE);
11724 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned byte"),
11725 t));
11726
11727 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER3]
11728 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11729 pushdecl (build_decl (TYPE_DECL, get_identifier ("word"),
11730 t));
11731 type = ffetype_new ();
11732 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER3,
11733 type);
11734 ffetype_set_ams (type,
11735 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11736 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11737 ffetype_set_star (base_type,
11738 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11739 type);
11740 ffetype_set_kind (base_type, 6, type);
11741 assert (ffetype_size (type) == sizeof (ffetargetInteger3));
11742
11743 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER3]
11744 = t = make_unsigned_type (CHAR_TYPE_SIZE * 2);
11745 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned word"),
11746 t));
11747
11748 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER4]
11749 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11750 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer4"),
11751 t));
11752 type = ffetype_new ();
11753 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER4,
11754 type);
11755 ffetype_set_ams (type,
11756 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11757 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11758 ffetype_set_star (base_type,
11759 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11760 type);
11761 ffetype_set_kind (base_type, 2, type);
11762 assert (ffetype_size (type) == sizeof (ffetargetInteger4));
11763
11764 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER4]
11765 = t = make_unsigned_type (FLOAT_TYPE_SIZE * 2);
11766 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned4"),
11767 t));
11768
11769 #if 0
11770 if (ffe_is_do_internal_checks ()
11771 && LONG_TYPE_SIZE != FLOAT_TYPE_SIZE
11772 && LONG_TYPE_SIZE != CHAR_TYPE_SIZE
11773 && LONG_TYPE_SIZE != SHORT_TYPE_SIZE
11774 && LONG_TYPE_SIZE != LONG_LONG_TYPE_SIZE)
11775 {
11776 fprintf (stderr, "Sorry, no g77 support for LONG_TYPE_SIZE (%d bits) yet.\n",
11777 LONG_TYPE_SIZE);
11778 }
11779 #endif
11780
11781 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL1]
11782 = t = make_signed_type (FLOAT_TYPE_SIZE);
11783 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical"),
11784 t));
11785 type = ffetype_new ();
11786 base_type = type;
11787 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL1,
11788 type);
11789 ffetype_set_ams (type,
11790 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11791 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11792 ffetype_set_star (base_type,
11793 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11794 type);
11795 ffetype_set_kind (base_type, 1, type);
11796 assert (ffetype_size (type) == sizeof (ffetargetLogical1));
11797
11798 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL2]
11799 = t = make_signed_type (CHAR_TYPE_SIZE);
11800 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical2"),
11801 t));
11802 type = ffetype_new ();
11803 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL2,
11804 type);
11805 ffetype_set_ams (type,
11806 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11807 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11808 ffetype_set_star (base_type,
11809 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11810 type);
11811 ffetype_set_kind (base_type, 3, type);
11812 assert (ffetype_size (type) == sizeof (ffetargetLogical2));
11813
11814 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL3]
11815 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11816 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical3"),
11817 t));
11818 type = ffetype_new ();
11819 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL3,
11820 type);
11821 ffetype_set_ams (type,
11822 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11823 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11824 ffetype_set_star (base_type,
11825 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11826 type);
11827 ffetype_set_kind (base_type, 6, type);
11828 assert (ffetype_size (type) == sizeof (ffetargetLogical3));
11829
11830 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL4]
11831 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11832 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical4"),
11833 t));
11834 type = ffetype_new ();
11835 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL4,
11836 type);
11837 ffetype_set_ams (type,
11838 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11839 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11840 ffetype_set_star (base_type,
11841 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11842 type);
11843 ffetype_set_kind (base_type, 2, type);
11844 assert (ffetype_size (type) == sizeof (ffetargetLogical4));
11845
11846 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
11847 = t = make_node (REAL_TYPE);
11848 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE;
11849 pushdecl (build_decl (TYPE_DECL, get_identifier ("real"),
11850 t));
11851 layout_type (t);
11852 type = ffetype_new ();
11853 base_type = type;
11854 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREAL1,
11855 type);
11856 ffetype_set_ams (type,
11857 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11858 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11859 ffetype_set_star (base_type,
11860 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11861 type);
11862 ffetype_set_kind (base_type, 1, type);
11863 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
11864 = FFETARGET_f2cTYREAL;
11865 assert (ffetype_size (type) == sizeof (ffetargetReal1));
11866
11867 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREALDOUBLE]
11868 = t = make_node (REAL_TYPE);
11869 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE * 2; /* Always twice REAL. */
11870 pushdecl (build_decl (TYPE_DECL, get_identifier ("double precision"),
11871 t));
11872 layout_type (t);
11873 type = ffetype_new ();
11874 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREALDOUBLE,
11875 type);
11876 ffetype_set_ams (type,
11877 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11878 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11879 ffetype_set_star (base_type,
11880 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11881 type);
11882 ffetype_set_kind (base_type, 2, type);
11883 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]
11884 = FFETARGET_f2cTYDREAL;
11885 assert (ffetype_size (type) == sizeof (ffetargetReal2));
11886
11887 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
11888 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]);
11889 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex"),
11890 t));
11891 type = ffetype_new ();
11892 base_type = type;
11893 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREAL1,
11894 type);
11895 ffetype_set_ams (type,
11896 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11897 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11898 ffetype_set_star (base_type,
11899 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11900 type);
11901 ffetype_set_kind (base_type, 1, type);
11902 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
11903 = FFETARGET_f2cTYCOMPLEX;
11904 assert (ffetype_size (type) == sizeof (ffetargetComplex1));
11905
11906 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREALDOUBLE]
11907 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]);
11908 pushdecl (build_decl (TYPE_DECL, get_identifier ("double complex"),
11909 t));
11910 type = ffetype_new ();
11911 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREALDOUBLE,
11912 type);
11913 ffetype_set_ams (type,
11914 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11915 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11916 ffetype_set_star (base_type,
11917 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11918 type);
11919 ffetype_set_kind (base_type, 2,
11920 type);
11921 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL2]
11922 = FFETARGET_f2cTYDCOMPLEX;
11923 assert (ffetype_size (type) == sizeof (ffetargetComplex2));
11924
11925 /* Make function and ptr-to-function types for non-CHARACTER types. */
11926
11927 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11928 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11929 {
11930 if ((t = ffecom_tree_type[i][j]) != NULL_TREE)
11931 {
11932 if (i == FFEINFO_basictypeINTEGER)
11933 {
11934 /* Figure out the smallest INTEGER type that can hold
11935 a pointer on this machine. */
11936 if (GET_MODE_SIZE (TYPE_MODE (t))
11937 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
11938 {
11939 if ((ffecom_pointer_kind_ == FFEINFO_kindtypeNONE)
11940 || (GET_MODE_SIZE (TYPE_MODE (ffecom_tree_type[i][ffecom_pointer_kind_]))
11941 > GET_MODE_SIZE (TYPE_MODE (t))))
11942 ffecom_pointer_kind_ = j;
11943 }
11944 }
11945 else if (i == FFEINFO_basictypeCOMPLEX)
11946 t = void_type_node;
11947 /* For f2c compatibility, REAL functions are really
11948 implemented as DOUBLE PRECISION. */
11949 else if ((i == FFEINFO_basictypeREAL)
11950 && (j == FFEINFO_kindtypeREAL1))
11951 t = ffecom_tree_type
11952 [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2];
11953
11954 t = ffecom_tree_fun_type[i][j] = build_function_type (t,
11955 NULL_TREE);
11956 ffecom_tree_ptr_to_fun_type[i][j] = build_pointer_type (t);
11957 }
11958 }
11959
11960 /* Set up pointer types. */
11961
11962 if (ffecom_pointer_kind_ == FFEINFO_basictypeNONE)
11963 fatal ("no INTEGER type can hold a pointer on this configuration");
11964 else if (0 && ffe_is_do_internal_checks ())
11965 fprintf (stderr, "Pointer type kt=%d\n", ffecom_pointer_kind_);
11966 ffetype_set_kind (ffeinfo_type (FFEINFO_basictypeINTEGER,
11967 FFEINFO_kindtypeINTEGERDEFAULT),
11968 7,
11969 ffeinfo_type (FFEINFO_basictypeINTEGER,
11970 ffecom_pointer_kind_));
11971
11972 if (ffe_is_ugly_assign ())
11973 ffecom_label_kind_ = ffecom_pointer_kind_; /* Require ASSIGN etc to this. */
11974 else
11975 ffecom_label_kind_ = FFEINFO_kindtypeINTEGERDEFAULT;
11976 if (0 && ffe_is_do_internal_checks ())
11977 fprintf (stderr, "Label type kt=%d\n", ffecom_label_kind_);
11978
11979 ffecom_integer_type_node
11980 = ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1];
11981 ffecom_integer_zero_node = convert (ffecom_integer_type_node,
11982 integer_zero_node);
11983 ffecom_integer_one_node = convert (ffecom_integer_type_node,
11984 integer_one_node);
11985
11986 /* Yes, the "FLOAT_TYPE_SIZE" references below are intentional.
11987 Turns out that by TYLONG, runtime/libI77/lio.h really means
11988 "whatever size an ftnint is". For consistency and sanity,
11989 com.h and runtime/f2c.h.in agree that flag, ftnint, and ftlen
11990 all are INTEGER, which we also make out of whatever back-end
11991 integer type is FLOAT_TYPE_SIZE bits wide. This change, from
11992 LONG_TYPE_SIZE, for TYLONG and TYLOGICAL, was necessary to
11993 accommodate machines like the Alpha. Note that this suggests
11994 f2c and libf2c are missing a distinction perhaps needed on
11995 some machines between "int" and "long int". -- burley 0.5.5 950215 */
11996
11997 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, FLOAT_TYPE_SIZE,
11998 FFETARGET_f2cTYLONG);
11999 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, SHORT_TYPE_SIZE,
12000 FFETARGET_f2cTYSHORT);
12001 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, CHAR_TYPE_SIZE,
12002 FFETARGET_f2cTYINT1);
12003 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, LONG_LONG_TYPE_SIZE,
12004 FFETARGET_f2cTYQUAD);
12005 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, FLOAT_TYPE_SIZE,
12006 FFETARGET_f2cTYLOGICAL);
12007 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, SHORT_TYPE_SIZE,
12008 FFETARGET_f2cTYLOGICAL2);
12009 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, CHAR_TYPE_SIZE,
12010 FFETARGET_f2cTYLOGICAL1);
12011 /* ~~~Not really such a type in libf2c, e.g. I/O support? */
12012 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, LONG_LONG_TYPE_SIZE,
12013 FFETARGET_f2cTYQUAD);
12014
12015 /* CHARACTER stuff is all special-cased, so it is not handled in the above
12016 loop. CHARACTER items are built as arrays of unsigned char. */
12017
12018 ffecom_tree_type[FFEINFO_basictypeCHARACTER]
12019 [FFEINFO_kindtypeCHARACTER1] = t = char_type_node;
12020 type = ffetype_new ();
12021 base_type = type;
12022 ffeinfo_set_type (FFEINFO_basictypeCHARACTER,
12023 FFEINFO_kindtypeCHARACTER1,
12024 type);
12025 ffetype_set_ams (type,
12026 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12027 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12028 ffetype_set_kind (base_type, 1, type);
12029 assert (ffetype_size (type)
12030 == sizeof (((ffetargetCharacter1) { 0, NULL }).text[0]));
12031
12032 ffecom_tree_fun_type[FFEINFO_basictypeCHARACTER]
12033 [FFEINFO_kindtypeCHARACTER1] = ffecom_tree_fun_type_void;
12034 ffecom_tree_ptr_to_fun_type[FFEINFO_basictypeCHARACTER]
12035 [FFEINFO_kindtypeCHARACTER1]
12036 = ffecom_tree_ptr_to_fun_type_void;
12037 ffecom_f2c_typecode_[FFEINFO_basictypeCHARACTER][FFEINFO_kindtypeCHARACTER1]
12038 = FFETARGET_f2cTYCHAR;
12039
12040 ffecom_f2c_typecode_[FFEINFO_basictypeANY][FFEINFO_kindtypeANY]
12041 = 0;
12042
12043 /* Make multi-return-value type and fields. */
12044
12045 ffecom_multi_type_node_ = make_node (UNION_TYPE);
12046
12047 field = NULL_TREE;
12048
12049 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
12050 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
12051 {
12052 char name[30];
12053
12054 if (ffecom_tree_type[i][j] == NULL_TREE)
12055 continue; /* Not supported. */
12056 sprintf (&name[0], "bt_%s_kt_%s",
12057 ffeinfo_basictype_string ((ffeinfoBasictype) i),
12058 ffeinfo_kindtype_string ((ffeinfoKindtype) j));
12059 ffecom_multi_fields_[i][j] = build_decl (FIELD_DECL,
12060 get_identifier (name),
12061 ffecom_tree_type[i][j]);
12062 DECL_CONTEXT (ffecom_multi_fields_[i][j])
12063 = ffecom_multi_type_node_;
12064 DECL_ALIGN (ffecom_multi_fields_[i][j]) = 0;
12065 DECL_USER_ALIGN (ffecom_multi_fields_[i][j]) = 0;
12066 TREE_CHAIN (ffecom_multi_fields_[i][j]) = field;
12067 field = ffecom_multi_fields_[i][j];
12068 }
12069
12070 TYPE_FIELDS (ffecom_multi_type_node_) = field;
12071 layout_type (ffecom_multi_type_node_);
12072
12073 /* Subroutines usually return integer because they might have alternate
12074 returns. */
12075
12076 ffecom_tree_subr_type
12077 = build_function_type (integer_type_node, NULL_TREE);
12078 ffecom_tree_ptr_to_subr_type
12079 = build_pointer_type (ffecom_tree_subr_type);
12080 ffecom_tree_blockdata_type
12081 = build_function_type (void_type_node, NULL_TREE);
12082
12083 builtin_function ("__builtin_sqrtf", float_ftype_float,
12084 BUILT_IN_FSQRT, BUILT_IN_NORMAL, "sqrtf");
12085 builtin_function ("__builtin_fsqrt", double_ftype_double,
12086 BUILT_IN_FSQRT, BUILT_IN_NORMAL, "sqrt");
12087 builtin_function ("__builtin_sqrtl", ldouble_ftype_ldouble,
12088 BUILT_IN_FSQRT, BUILT_IN_NORMAL, "sqrtl");
12089 builtin_function ("__builtin_sinf", float_ftype_float,
12090 BUILT_IN_SIN, BUILT_IN_NORMAL, "sinf");
12091 builtin_function ("__builtin_sin", double_ftype_double,
12092 BUILT_IN_SIN, BUILT_IN_NORMAL, "sin");
12093 builtin_function ("__builtin_sinl", ldouble_ftype_ldouble,
12094 BUILT_IN_SIN, BUILT_IN_NORMAL, "sinl");
12095 builtin_function ("__builtin_cosf", float_ftype_float,
12096 BUILT_IN_COS, BUILT_IN_NORMAL, "cosf");
12097 builtin_function ("__builtin_cos", double_ftype_double,
12098 BUILT_IN_COS, BUILT_IN_NORMAL, "cos");
12099 builtin_function ("__builtin_cosl", ldouble_ftype_ldouble,
12100 BUILT_IN_COS, BUILT_IN_NORMAL, "cosl");
12101
12102 #if BUILT_FOR_270
12103 pedantic_lvalues = FALSE;
12104 #endif
12105
12106 ffecom_f2c_make_type_ (&ffecom_f2c_integer_type_node,
12107 FFECOM_f2cINTEGER,
12108 "integer");
12109 ffecom_f2c_make_type_ (&ffecom_f2c_address_type_node,
12110 FFECOM_f2cADDRESS,
12111 "address");
12112 ffecom_f2c_make_type_ (&ffecom_f2c_real_type_node,
12113 FFECOM_f2cREAL,
12114 "real");
12115 ffecom_f2c_make_type_ (&ffecom_f2c_doublereal_type_node,
12116 FFECOM_f2cDOUBLEREAL,
12117 "doublereal");
12118 ffecom_f2c_make_type_ (&ffecom_f2c_complex_type_node,
12119 FFECOM_f2cCOMPLEX,
12120 "complex");
12121 ffecom_f2c_make_type_ (&ffecom_f2c_doublecomplex_type_node,
12122 FFECOM_f2cDOUBLECOMPLEX,
12123 "doublecomplex");
12124 ffecom_f2c_make_type_ (&ffecom_f2c_longint_type_node,
12125 FFECOM_f2cLONGINT,
12126 "longint");
12127 ffecom_f2c_make_type_ (&ffecom_f2c_logical_type_node,
12128 FFECOM_f2cLOGICAL,
12129 "logical");
12130 ffecom_f2c_make_type_ (&ffecom_f2c_flag_type_node,
12131 FFECOM_f2cFLAG,
12132 "flag");
12133 ffecom_f2c_make_type_ (&ffecom_f2c_ftnlen_type_node,
12134 FFECOM_f2cFTNLEN,
12135 "ftnlen");
12136 ffecom_f2c_make_type_ (&ffecom_f2c_ftnint_type_node,
12137 FFECOM_f2cFTNINT,
12138 "ftnint");
12139
12140 ffecom_f2c_ftnlen_zero_node
12141 = convert (ffecom_f2c_ftnlen_type_node, integer_zero_node);
12142
12143 ffecom_f2c_ftnlen_one_node
12144 = convert (ffecom_f2c_ftnlen_type_node, integer_one_node);
12145
12146 ffecom_f2c_ftnlen_two_node = build_int_2 (2, 0);
12147 TREE_TYPE (ffecom_f2c_ftnlen_two_node) = ffecom_integer_type_node;
12148
12149 ffecom_f2c_ptr_to_ftnlen_type_node
12150 = build_pointer_type (ffecom_f2c_ftnlen_type_node);
12151
12152 ffecom_f2c_ptr_to_ftnint_type_node
12153 = build_pointer_type (ffecom_f2c_ftnint_type_node);
12154
12155 ffecom_f2c_ptr_to_integer_type_node
12156 = build_pointer_type (ffecom_f2c_integer_type_node);
12157
12158 ffecom_f2c_ptr_to_real_type_node
12159 = build_pointer_type (ffecom_f2c_real_type_node);
12160
12161 ffecom_float_zero_ = build_real (float_type_node, dconst0);
12162 ffecom_double_zero_ = build_real (double_type_node, dconst0);
12163 {
12164 REAL_VALUE_TYPE point_5;
12165
12166 #ifdef REAL_ARITHMETIC
12167 REAL_ARITHMETIC (point_5, RDIV_EXPR, dconst1, dconst2);
12168 #else
12169 point_5 = .5;
12170 #endif
12171 ffecom_float_half_ = build_real (float_type_node, point_5);
12172 ffecom_double_half_ = build_real (double_type_node, point_5);
12173 }
12174
12175 /* Do "extern int xargc;". */
12176
12177 ffecom_tree_xargc_ = build_decl (VAR_DECL,
12178 get_identifier ("f__xargc"),
12179 integer_type_node);
12180 DECL_EXTERNAL (ffecom_tree_xargc_) = 1;
12181 TREE_STATIC (ffecom_tree_xargc_) = 1;
12182 TREE_PUBLIC (ffecom_tree_xargc_) = 1;
12183 ffecom_tree_xargc_ = start_decl (ffecom_tree_xargc_, FALSE);
12184 finish_decl (ffecom_tree_xargc_, NULL_TREE, FALSE);
12185
12186 #if 0 /* This is being fixed, and seems to be working now. */
12187 if ((FLOAT_TYPE_SIZE != 32)
12188 || (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))) != 32))
12189 {
12190 warning ("configuration: REAL, INTEGER, and LOGICAL are %d bits wide,",
12191 (int) FLOAT_TYPE_SIZE);
12192 warning ("and pointers are %d bits wide, but g77 doesn't yet work",
12193 (int) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))));
12194 warning ("properly unless they all are 32 bits wide.");
12195 warning ("Please keep this in mind before you report bugs. g77 should");
12196 warning ("support non-32-bit machines better as of version 0.6.");
12197 }
12198 #endif
12199
12200 #if 0 /* Code in ste.c that would crash has been commented out. */
12201 if (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
12202 < TYPE_PRECISION (string_type_node))
12203 /* I/O will probably crash. */
12204 warning ("configuration: char * holds %d bits, but ftnlen only %d",
12205 TYPE_PRECISION (string_type_node),
12206 TYPE_PRECISION (ffecom_f2c_ftnlen_type_node));
12207 #endif
12208
12209 #if 0 /* ASSIGN-related stuff has been changed to accommodate this. */
12210 if (TYPE_PRECISION (ffecom_integer_type_node)
12211 < TYPE_PRECISION (string_type_node))
12212 /* ASSIGN 10 TO I will crash. */
12213 warning ("configuration: char * holds %d bits, but INTEGER only %d --\n\
12214 ASSIGN statement might fail",
12215 TYPE_PRECISION (string_type_node),
12216 TYPE_PRECISION (ffecom_integer_type_node));
12217 #endif
12218 }
12219
12220 #endif
12221 /* ffecom_init_2 -- Initialize
12222
12223 ffecom_init_2(); */
12224
12225 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12226 void
12227 ffecom_init_2 ()
12228 {
12229 assert (ffecom_outer_function_decl_ == NULL_TREE);
12230 assert (current_function_decl == NULL_TREE);
12231 assert (ffecom_which_entrypoint_decl_ == NULL_TREE);
12232
12233 ffecom_master_arglist_ = NULL;
12234 ++ffecom_num_fns_;
12235 ffecom_primary_entry_ = NULL;
12236 ffecom_is_altreturning_ = FALSE;
12237 ffecom_func_result_ = NULL_TREE;
12238 ffecom_multi_retval_ = NULL_TREE;
12239 }
12240
12241 #endif
12242 /* ffecom_list_expr -- Transform list of exprs into gcc tree
12243
12244 tree t;
12245 ffebld expr; // FFE opITEM list.
12246 tree = ffecom_list_expr(expr);
12247
12248 List of actual args is transformed into corresponding gcc backend list. */
12249
12250 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12251 tree
12252 ffecom_list_expr (ffebld expr)
12253 {
12254 tree list;
12255 tree *plist = &list;
12256 tree trail = NULL_TREE; /* Append char length args here. */
12257 tree *ptrail = &trail;
12258 tree length;
12259
12260 while (expr != NULL)
12261 {
12262 tree texpr = ffecom_arg_expr (ffebld_head (expr), &length);
12263
12264 if (texpr == error_mark_node)
12265 return error_mark_node;
12266
12267 *plist = build_tree_list (NULL_TREE, texpr);
12268 plist = &TREE_CHAIN (*plist);
12269 expr = ffebld_trail (expr);
12270 if (length != NULL_TREE)
12271 {
12272 *ptrail = build_tree_list (NULL_TREE, length);
12273 ptrail = &TREE_CHAIN (*ptrail);
12274 }
12275 }
12276
12277 *plist = trail;
12278
12279 return list;
12280 }
12281
12282 #endif
12283 /* ffecom_list_ptr_to_expr -- Transform list of exprs into gcc tree
12284
12285 tree t;
12286 ffebld expr; // FFE opITEM list.
12287 tree = ffecom_list_ptr_to_expr(expr);
12288
12289 List of actual args is transformed into corresponding gcc backend list for
12290 use in calling an external procedure (vs. a statement function). */
12291
12292 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12293 tree
12294 ffecom_list_ptr_to_expr (ffebld expr)
12295 {
12296 tree list;
12297 tree *plist = &list;
12298 tree trail = NULL_TREE; /* Append char length args here. */
12299 tree *ptrail = &trail;
12300 tree length;
12301
12302 while (expr != NULL)
12303 {
12304 tree texpr = ffecom_arg_ptr_to_expr (ffebld_head (expr), &length);
12305
12306 if (texpr == error_mark_node)
12307 return error_mark_node;
12308
12309 *plist = build_tree_list (NULL_TREE, texpr);
12310 plist = &TREE_CHAIN (*plist);
12311 expr = ffebld_trail (expr);
12312 if (length != NULL_TREE)
12313 {
12314 *ptrail = build_tree_list (NULL_TREE, length);
12315 ptrail = &TREE_CHAIN (*ptrail);
12316 }
12317 }
12318
12319 *plist = trail;
12320
12321 return list;
12322 }
12323
12324 #endif
12325 /* Obtain gcc's LABEL_DECL tree for label. */
12326
12327 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12328 tree
12329 ffecom_lookup_label (ffelab label)
12330 {
12331 tree glabel;
12332
12333 if (ffelab_hook (label) == NULL_TREE)
12334 {
12335 char labelname[16];
12336
12337 switch (ffelab_type (label))
12338 {
12339 case FFELAB_typeLOOPEND:
12340 case FFELAB_typeNOTLOOP:
12341 case FFELAB_typeENDIF:
12342 sprintf (labelname, "%" ffelabValue_f "u", ffelab_value (label));
12343 glabel = build_decl (LABEL_DECL, get_identifier (labelname),
12344 void_type_node);
12345 DECL_CONTEXT (glabel) = current_function_decl;
12346 DECL_MODE (glabel) = VOIDmode;
12347 break;
12348
12349 case FFELAB_typeFORMAT:
12350 glabel = build_decl (VAR_DECL,
12351 ffecom_get_invented_identifier
12352 ("__g77_format_%d", (int) ffelab_value (label)),
12353 build_type_variant (build_array_type
12354 (char_type_node,
12355 NULL_TREE),
12356 1, 0));
12357 TREE_CONSTANT (glabel) = 1;
12358 TREE_STATIC (glabel) = 1;
12359 DECL_CONTEXT (glabel) = 0;
12360 DECL_INITIAL (glabel) = NULL;
12361 make_decl_rtl (glabel, NULL, 0);
12362 expand_decl (glabel);
12363
12364 ffecom_save_tree_forever (glabel);
12365
12366 break;
12367
12368 case FFELAB_typeANY:
12369 glabel = error_mark_node;
12370 break;
12371
12372 default:
12373 assert ("bad label type" == NULL);
12374 glabel = NULL;
12375 break;
12376 }
12377 ffelab_set_hook (label, glabel);
12378 }
12379 else
12380 {
12381 glabel = ffelab_hook (label);
12382 }
12383
12384 return glabel;
12385 }
12386
12387 #endif
12388 /* Stabilizes the arguments. Don't use this if the lhs and rhs come from
12389 a single source specification (as in the fourth argument of MVBITS).
12390 If the type is NULL_TREE, the type of lhs is used to make the type of
12391 the MODIFY_EXPR. */
12392
12393 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12394 tree
12395 ffecom_modify (tree newtype, tree lhs,
12396 tree rhs)
12397 {
12398 if (lhs == error_mark_node || rhs == error_mark_node)
12399 return error_mark_node;
12400
12401 if (newtype == NULL_TREE)
12402 newtype = TREE_TYPE (lhs);
12403
12404 if (TREE_SIDE_EFFECTS (lhs))
12405 lhs = stabilize_reference (lhs);
12406
12407 return ffecom_2s (MODIFY_EXPR, newtype, lhs, rhs);
12408 }
12409
12410 #endif
12411
12412 /* Register source file name. */
12413
12414 void
12415 ffecom_file (const char *name)
12416 {
12417 #if FFECOM_GCC_INCLUDE
12418 ffecom_file_ (name);
12419 #endif
12420 }
12421
12422 /* ffecom_notify_init_storage -- An aggregate storage is now fully init'ed
12423
12424 ffestorag st;
12425 ffecom_notify_init_storage(st);
12426
12427 Gets called when all possible units in an aggregate storage area (a LOCAL
12428 with equivalences or a COMMON) have been initialized. The initialization
12429 info either is in ffestorag_init or, if that is NULL,
12430 ffestorag_accretion:
12431
12432 ffestorag_init may contain an opCONTER or opARRTER. opCONTER may occur
12433 even for an array if the array is one element in length!
12434
12435 ffestorag_accretion will contain an opACCTER. It is much like an
12436 opARRTER except it has an ffebit object in it instead of just a size.
12437 The back end can use the info in the ffebit object, if it wants, to
12438 reduce the amount of actual initialization, but in any case it should
12439 kill the ffebit object when done. Also, set accretion to NULL but
12440 init to a non-NULL value.
12441
12442 After performing initialization, DO NOT set init to NULL, because that'll
12443 tell the front end it is ok for more initialization to happen. Instead,
12444 set init to an opANY expression or some such thing that you can use to
12445 tell that you've already initialized the object.
12446
12447 27-Oct-91 JCB 1.1
12448 Support two-pass FFE. */
12449
12450 void
12451 ffecom_notify_init_storage (ffestorag st)
12452 {
12453 ffebld init; /* The initialization expression. */
12454 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12455 ffetargetOffset size; /* The size of the entity. */
12456 ffetargetAlign pad; /* Its initial padding. */
12457 #endif
12458
12459 if (ffestorag_init (st) == NULL)
12460 {
12461 init = ffestorag_accretion (st);
12462 assert (init != NULL);
12463 ffestorag_set_accretion (st, NULL);
12464 ffestorag_set_accretes (st, 0);
12465
12466 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12467 /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12468 size = ffebld_accter_size (init);
12469 pad = ffebld_accter_pad (init);
12470 ffebit_kill (ffebld_accter_bits (init));
12471 ffebld_set_op (init, FFEBLD_opARRTER);
12472 ffebld_set_arrter (init, ffebld_accter (init));
12473 ffebld_arrter_set_size (init, size);
12474 ffebld_arrter_set_pad (init, size);
12475 #endif
12476
12477 #if FFECOM_TWOPASS
12478 ffestorag_set_init (st, init);
12479 #endif
12480 }
12481 #if FFECOM_ONEPASS
12482 else
12483 init = ffestorag_init (st);
12484 #endif
12485
12486 #if FFECOM_ONEPASS /* Process the inits, wipe 'em out. */
12487 ffestorag_set_init (st, ffebld_new_any ());
12488
12489 if (ffebld_op (init) == FFEBLD_opANY)
12490 return; /* Oh, we already did this! */
12491
12492 #if FFECOM_targetCURRENT == FFECOM_targetFFE
12493 {
12494 ffesymbol s;
12495
12496 if (ffestorag_symbol (st) != NULL)
12497 s = ffestorag_symbol (st);
12498 else
12499 s = ffestorag_typesymbol (st);
12500
12501 fprintf (dmpout, "= initialize_storage \"%s\" ",
12502 (s != NULL) ? ffesymbol_text (s) : "(unnamed)");
12503 ffebld_dump (init);
12504 fputc ('\n', dmpout);
12505 }
12506 #endif
12507
12508 #endif /* if FFECOM_ONEPASS */
12509 }
12510
12511 /* ffecom_notify_init_symbol -- A symbol is now fully init'ed
12512
12513 ffesymbol s;
12514 ffecom_notify_init_symbol(s);
12515
12516 Gets called when all possible units in a symbol (not placed in COMMON
12517 or involved in EQUIVALENCE, unless it as yet has no ffestorag object)
12518 have been initialized. The initialization info either is in
12519 ffesymbol_init or, if that is NULL, ffesymbol_accretion:
12520
12521 ffesymbol_init may contain an opCONTER or opARRTER. opCONTER may occur
12522 even for an array if the array is one element in length!
12523
12524 ffesymbol_accretion will contain an opACCTER. It is much like an
12525 opARRTER except it has an ffebit object in it instead of just a size.
12526 The back end can use the info in the ffebit object, if it wants, to
12527 reduce the amount of actual initialization, but in any case it should
12528 kill the ffebit object when done. Also, set accretion to NULL but
12529 init to a non-NULL value.
12530
12531 After performing initialization, DO NOT set init to NULL, because that'll
12532 tell the front end it is ok for more initialization to happen. Instead,
12533 set init to an opANY expression or some such thing that you can use to
12534 tell that you've already initialized the object.
12535
12536 27-Oct-91 JCB 1.1
12537 Support two-pass FFE. */
12538
12539 void
12540 ffecom_notify_init_symbol (ffesymbol s)
12541 {
12542 ffebld init; /* The initialization expression. */
12543 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12544 ffetargetOffset size; /* The size of the entity. */
12545 ffetargetAlign pad; /* Its initial padding. */
12546 #endif
12547
12548 if (ffesymbol_storage (s) == NULL)
12549 return; /* Do nothing until COMMON/EQUIVALENCE
12550 possibilities checked. */
12551
12552 if ((ffesymbol_init (s) == NULL)
12553 && ((init = ffesymbol_accretion (s)) != NULL))
12554 {
12555 ffesymbol_set_accretion (s, NULL);
12556 ffesymbol_set_accretes (s, 0);
12557
12558 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12559 /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12560 size = ffebld_accter_size (init);
12561 pad = ffebld_accter_pad (init);
12562 ffebit_kill (ffebld_accter_bits (init));
12563 ffebld_set_op (init, FFEBLD_opARRTER);
12564 ffebld_set_arrter (init, ffebld_accter (init));
12565 ffebld_arrter_set_size (init, size);
12566 ffebld_arrter_set_pad (init, size);
12567 #endif
12568
12569 #if FFECOM_TWOPASS
12570 ffesymbol_set_init (s, init);
12571 #endif
12572 }
12573 #if FFECOM_ONEPASS
12574 else
12575 init = ffesymbol_init (s);
12576 #endif
12577
12578 #if FFECOM_ONEPASS
12579 ffesymbol_set_init (s, ffebld_new_any ());
12580
12581 if (ffebld_op (init) == FFEBLD_opANY)
12582 return; /* Oh, we already did this! */
12583
12584 #if FFECOM_targetCURRENT == FFECOM_targetFFE
12585 fprintf (dmpout, "= initialize_symbol \"%s\" ", ffesymbol_text (s));
12586 ffebld_dump (init);
12587 fputc ('\n', dmpout);
12588 #endif
12589
12590 #endif /* if FFECOM_ONEPASS */
12591 }
12592
12593 /* ffecom_notify_primary_entry -- Learn which is the primary entry point
12594
12595 ffesymbol s;
12596 ffecom_notify_primary_entry(s);
12597
12598 Gets called when implicit or explicit PROGRAM statement seen or when
12599 FUNCTION, SUBROUTINE, or BLOCK DATA statement seen, with the primary
12600 global symbol that serves as the entry point. */
12601
12602 void
12603 ffecom_notify_primary_entry (ffesymbol s)
12604 {
12605 ffecom_primary_entry_ = s;
12606 ffecom_primary_entry_kind_ = ffesymbol_kind (s);
12607
12608 if ((ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
12609 || (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE))
12610 ffecom_primary_entry_is_proc_ = TRUE;
12611 else
12612 ffecom_primary_entry_is_proc_ = FALSE;
12613
12614 if (!ffe_is_silent ())
12615 {
12616 if (ffecom_primary_entry_kind_ == FFEINFO_kindPROGRAM)
12617 fprintf (stderr, "%s:\n", ffesymbol_text (s));
12618 else
12619 fprintf (stderr, " %s:\n", ffesymbol_text (s));
12620 }
12621
12622 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12623 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
12624 {
12625 ffebld list;
12626 ffebld arg;
12627
12628 for (list = ffesymbol_dummyargs (s);
12629 list != NULL;
12630 list = ffebld_trail (list))
12631 {
12632 arg = ffebld_head (list);
12633 if (ffebld_op (arg) == FFEBLD_opSTAR)
12634 {
12635 ffecom_is_altreturning_ = TRUE;
12636 break;
12637 }
12638 }
12639 }
12640 #endif
12641 }
12642
12643 FILE *
12644 ffecom_open_include (char *name, ffewhereLine l, ffewhereColumn c)
12645 {
12646 #if FFECOM_GCC_INCLUDE
12647 return ffecom_open_include_ (name, l, c);
12648 #else
12649 return fopen (name, "r");
12650 #endif
12651 }
12652
12653 /* ffecom_ptr_to_expr -- Transform expr into gcc tree with & in front
12654
12655 tree t;
12656 ffebld expr; // FFE expression.
12657 tree = ffecom_ptr_to_expr(expr);
12658
12659 Like ffecom_expr, but sticks address-of in front of most things. */
12660
12661 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12662 tree
12663 ffecom_ptr_to_expr (ffebld expr)
12664 {
12665 tree item;
12666 ffeinfoBasictype bt;
12667 ffeinfoKindtype kt;
12668 ffesymbol s;
12669
12670 assert (expr != NULL);
12671
12672 switch (ffebld_op (expr))
12673 {
12674 case FFEBLD_opSYMTER:
12675 s = ffebld_symter (expr);
12676 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
12677 {
12678 ffecomGfrt ix;
12679
12680 ix = ffeintrin_gfrt_indirect (ffebld_symter_implementation (expr));
12681 assert (ix != FFECOM_gfrt);
12682 if ((item = ffecom_gfrt_[ix]) == NULL_TREE)
12683 {
12684 ffecom_make_gfrt_ (ix);
12685 item = ffecom_gfrt_[ix];
12686 }
12687 }
12688 else
12689 {
12690 item = ffesymbol_hook (s).decl_tree;
12691 if (item == NULL_TREE)
12692 {
12693 s = ffecom_sym_transform_ (s);
12694 item = ffesymbol_hook (s).decl_tree;
12695 }
12696 }
12697 assert (item != NULL);
12698 if (item == error_mark_node)
12699 return item;
12700 if (!ffesymbol_hook (s).addr)
12701 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12702 item);
12703 return item;
12704
12705 case FFEBLD_opARRAYREF:
12706 return ffecom_arrayref_ (NULL_TREE, expr, 1);
12707
12708 case FFEBLD_opCONTER:
12709
12710 bt = ffeinfo_basictype (ffebld_info (expr));
12711 kt = ffeinfo_kindtype (ffebld_info (expr));
12712
12713 item = ffecom_constantunion (&ffebld_constant_union
12714 (ffebld_conter (expr)), bt, kt,
12715 ffecom_tree_type[bt][kt]);
12716 if (item == error_mark_node)
12717 return error_mark_node;
12718 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12719 item);
12720 return item;
12721
12722 case FFEBLD_opANY:
12723 return error_mark_node;
12724
12725 default:
12726 bt = ffeinfo_basictype (ffebld_info (expr));
12727 kt = ffeinfo_kindtype (ffebld_info (expr));
12728
12729 item = ffecom_expr (expr);
12730 if (item == error_mark_node)
12731 return error_mark_node;
12732
12733 /* The back end currently optimizes a bit too zealously for us, in that
12734 we fail JCB001 if the following block of code is omitted. It checks
12735 to see if the transformed expression is a symbol or array reference,
12736 and encloses it in a SAVE_EXPR if that is the case. */
12737
12738 STRIP_NOPS (item);
12739 if ((TREE_CODE (item) == VAR_DECL)
12740 || (TREE_CODE (item) == PARM_DECL)
12741 || (TREE_CODE (item) == RESULT_DECL)
12742 || (TREE_CODE (item) == INDIRECT_REF)
12743 || (TREE_CODE (item) == ARRAY_REF)
12744 || (TREE_CODE (item) == COMPONENT_REF)
12745 #ifdef OFFSET_REF
12746 || (TREE_CODE (item) == OFFSET_REF)
12747 #endif
12748 || (TREE_CODE (item) == BUFFER_REF)
12749 || (TREE_CODE (item) == REALPART_EXPR)
12750 || (TREE_CODE (item) == IMAGPART_EXPR))
12751 {
12752 item = ffecom_save_tree (item);
12753 }
12754
12755 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12756 item);
12757 return item;
12758 }
12759
12760 assert ("fall-through error" == NULL);
12761 return error_mark_node;
12762 }
12763
12764 #endif
12765 /* Obtain a temp var with given data type.
12766
12767 size is FFETARGET_charactersizeNONE for a non-CHARACTER type
12768 or >= 0 for a CHARACTER type.
12769
12770 elements is -1 for a scalar or > 0 for an array of type. */
12771
12772 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12773 tree
12774 ffecom_make_tempvar (const char *commentary, tree type,
12775 ffetargetCharacterSize size, int elements)
12776 {
12777 int yes;
12778 tree t;
12779 static int mynumber;
12780
12781 assert (current_binding_level->prep_state < 2);
12782
12783 if (type == error_mark_node)
12784 return error_mark_node;
12785
12786 yes = suspend_momentary ();
12787
12788 if (size != FFETARGET_charactersizeNONE)
12789 type = build_array_type (type,
12790 build_range_type (ffecom_f2c_ftnlen_type_node,
12791 ffecom_f2c_ftnlen_one_node,
12792 build_int_2 (size, 0)));
12793 if (elements != -1)
12794 type = build_array_type (type,
12795 build_range_type (integer_type_node,
12796 integer_zero_node,
12797 build_int_2 (elements - 1,
12798 0)));
12799 t = build_decl (VAR_DECL,
12800 ffecom_get_invented_identifier ("__g77_%s_%d",
12801 commentary,
12802 mynumber++),
12803 type);
12804
12805 t = start_decl (t, FALSE);
12806 finish_decl (t, NULL_TREE, FALSE);
12807
12808 resume_momentary (yes);
12809
12810 return t;
12811 }
12812 #endif
12813
12814 /* Prepare argument pointer to expression.
12815
12816 Like ffecom_prepare_expr, except for expressions to be evaluated
12817 via ffecom_arg_ptr_to_expr. */
12818
12819 void
12820 ffecom_prepare_arg_ptr_to_expr (ffebld expr)
12821 {
12822 /* ~~For now, it seems to be the same thing. */
12823 ffecom_prepare_expr (expr);
12824 return;
12825 }
12826
12827 /* End of preparations. */
12828
12829 bool
12830 ffecom_prepare_end (void)
12831 {
12832 int prep_state = current_binding_level->prep_state;
12833
12834 assert (prep_state < 2);
12835 current_binding_level->prep_state = 2;
12836
12837 return (prep_state == 1) ? TRUE : FALSE;
12838 }
12839
12840 /* Prepare expression.
12841
12842 This is called before any code is generated for the current block.
12843 It scans the expression, declares any temporaries that might be needed
12844 during evaluation of the expression, and stores those temporaries in
12845 the appropriate "hook" fields of the expression. `dest', if not NULL,
12846 specifies the destination that ffecom_expr_ will see, in case that
12847 helps avoid generating unused temporaries.
12848
12849 ~~Improve to avoid allocating unused temporaries by taking `dest'
12850 into account vis-a-vis aliasing requirements of complex/character
12851 functions. */
12852
12853 void
12854 ffecom_prepare_expr_ (ffebld expr, ffebld dest UNUSED)
12855 {
12856 ffeinfoBasictype bt;
12857 ffeinfoKindtype kt;
12858 ffetargetCharacterSize sz;
12859 tree tempvar = NULL_TREE;
12860
12861 assert (current_binding_level->prep_state < 2);
12862
12863 if (! expr)
12864 return;
12865
12866 bt = ffeinfo_basictype (ffebld_info (expr));
12867 kt = ffeinfo_kindtype (ffebld_info (expr));
12868 sz = ffeinfo_size (ffebld_info (expr));
12869
12870 /* Generate whatever temporaries are needed to represent the result
12871 of the expression. */
12872
12873 if (bt == FFEINFO_basictypeCHARACTER)
12874 {
12875 while (ffebld_op (expr) == FFEBLD_opPAREN)
12876 expr = ffebld_left (expr);
12877 }
12878
12879 switch (ffebld_op (expr))
12880 {
12881 default:
12882 /* Don't make temps for SYMTER, CONTER, etc. */
12883 if (ffebld_arity (expr) == 0)
12884 break;
12885
12886 switch (bt)
12887 {
12888 case FFEINFO_basictypeCOMPLEX:
12889 if (ffebld_op (expr) == FFEBLD_opFUNCREF)
12890 {
12891 ffesymbol s;
12892
12893 if (ffebld_op (ffebld_left (expr)) != FFEBLD_opSYMTER)
12894 break;
12895
12896 s = ffebld_symter (ffebld_left (expr));
12897 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT
12898 || (ffesymbol_where (s) != FFEINFO_whereINTRINSIC
12899 && ! ffesymbol_is_f2c (s))
12900 || (ffesymbol_where (s) == FFEINFO_whereINTRINSIC
12901 && ! ffe_is_f2c_library ()))
12902 break;
12903 }
12904 else if (ffebld_op (expr) == FFEBLD_opPOWER)
12905 {
12906 /* Requires special treatment. There's no POW_CC function
12907 in libg2c, so POW_ZZ is used, which means we always
12908 need a double-complex temp, not a single-complex. */
12909 kt = FFEINFO_kindtypeREAL2;
12910 }
12911 else if (ffebld_op (expr) != FFEBLD_opDIVIDE)
12912 /* The other ops don't need temps for complex operands. */
12913 break;
12914
12915 /* ~~~Avoid making temps for some intrinsics, such as AIMAG(C),
12916 REAL(C). See 19990325-0.f, routine `check', for cases. */
12917 tempvar = ffecom_make_tempvar ("complex",
12918 ffecom_tree_type
12919 [FFEINFO_basictypeCOMPLEX][kt],
12920 FFETARGET_charactersizeNONE,
12921 -1);
12922 break;
12923
12924 case FFEINFO_basictypeCHARACTER:
12925 if (ffebld_op (expr) != FFEBLD_opFUNCREF)
12926 break;
12927
12928 if (sz == FFETARGET_charactersizeNONE)
12929 /* ~~Kludge alert! This should someday be fixed. */
12930 sz = 24;
12931
12932 tempvar = ffecom_make_tempvar ("char", char_type_node, sz, -1);
12933 break;
12934
12935 default:
12936 break;
12937 }
12938 break;
12939
12940 #ifdef HAHA
12941 case FFEBLD_opPOWER:
12942 {
12943 tree rtype, ltype;
12944 tree rtmp, ltmp, result;
12945
12946 ltype = ffecom_type_expr (ffebld_left (expr));
12947 rtype = ffecom_type_expr (ffebld_right (expr));
12948
12949 rtmp = ffecom_make_tempvar (rtype, FFETARGET_charactersizeNONE, -1);
12950 ltmp = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
12951 result = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
12952
12953 tempvar = make_tree_vec (3);
12954 TREE_VEC_ELT (tempvar, 0) = rtmp;
12955 TREE_VEC_ELT (tempvar, 1) = ltmp;
12956 TREE_VEC_ELT (tempvar, 2) = result;
12957 }
12958 break;
12959 #endif /* HAHA */
12960
12961 case FFEBLD_opCONCATENATE:
12962 {
12963 /* This gets special handling, because only one set of temps
12964 is needed for a tree of these -- the tree is treated as
12965 a flattened list of concatenations when generating code. */
12966
12967 ffecomConcatList_ catlist;
12968 tree ltmp, itmp, result;
12969 int count;
12970 int i;
12971
12972 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
12973 count = ffecom_concat_list_count_ (catlist);
12974
12975 if (count >= 2)
12976 {
12977 ltmp
12978 = ffecom_make_tempvar ("concat_len",
12979 ffecom_f2c_ftnlen_type_node,
12980 FFETARGET_charactersizeNONE, count);
12981 itmp
12982 = ffecom_make_tempvar ("concat_item",
12983 ffecom_f2c_address_type_node,
12984 FFETARGET_charactersizeNONE, count);
12985 result
12986 = ffecom_make_tempvar ("concat_res",
12987 char_type_node,
12988 ffecom_concat_list_maxlen_ (catlist),
12989 -1);
12990
12991 tempvar = make_tree_vec (3);
12992 TREE_VEC_ELT (tempvar, 0) = ltmp;
12993 TREE_VEC_ELT (tempvar, 1) = itmp;
12994 TREE_VEC_ELT (tempvar, 2) = result;
12995 }
12996
12997 for (i = 0; i < count; ++i)
12998 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist,
12999 i));
13000
13001 ffecom_concat_list_kill_ (catlist);
13002
13003 if (tempvar)
13004 {
13005 ffebld_nonter_set_hook (expr, tempvar);
13006 current_binding_level->prep_state = 1;
13007 }
13008 }
13009 return;
13010
13011 case FFEBLD_opCONVERT:
13012 if (bt == FFEINFO_basictypeCHARACTER
13013 && ((ffebld_size_known (ffebld_left (expr))
13014 == FFETARGET_charactersizeNONE)
13015 || (ffebld_size_known (ffebld_left (expr)) >= sz)))
13016 tempvar = ffecom_make_tempvar ("convert", char_type_node, sz, -1);
13017 break;
13018 }
13019
13020 if (tempvar)
13021 {
13022 ffebld_nonter_set_hook (expr, tempvar);
13023 current_binding_level->prep_state = 1;
13024 }
13025
13026 /* Prepare subexpressions for this expr. */
13027
13028 switch (ffebld_op (expr))
13029 {
13030 case FFEBLD_opPERCENT_LOC:
13031 ffecom_prepare_ptr_to_expr (ffebld_left (expr));
13032 break;
13033
13034 case FFEBLD_opPERCENT_VAL:
13035 case FFEBLD_opPERCENT_REF:
13036 ffecom_prepare_expr (ffebld_left (expr));
13037 break;
13038
13039 case FFEBLD_opPERCENT_DESCR:
13040 ffecom_prepare_arg_ptr_to_expr (ffebld_left (expr));
13041 break;
13042
13043 case FFEBLD_opITEM:
13044 {
13045 ffebld item;
13046
13047 for (item = expr;
13048 item != NULL;
13049 item = ffebld_trail (item))
13050 if (ffebld_head (item) != NULL)
13051 ffecom_prepare_expr (ffebld_head (item));
13052 }
13053 break;
13054
13055 default:
13056 /* Need to handle character conversion specially. */
13057 switch (ffebld_arity (expr))
13058 {
13059 case 2:
13060 ffecom_prepare_expr (ffebld_left (expr));
13061 ffecom_prepare_expr (ffebld_right (expr));
13062 break;
13063
13064 case 1:
13065 ffecom_prepare_expr (ffebld_left (expr));
13066 break;
13067
13068 default:
13069 break;
13070 }
13071 }
13072
13073 return;
13074 }
13075
13076 /* Prepare expression for reading and writing.
13077
13078 Like ffecom_prepare_expr, except for expressions to be evaluated
13079 via ffecom_expr_rw. */
13080
13081 void
13082 ffecom_prepare_expr_rw (tree type, ffebld expr)
13083 {
13084 /* This is all we support for now. */
13085 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
13086
13087 /* ~~For now, it seems to be the same thing. */
13088 ffecom_prepare_expr (expr);
13089 return;
13090 }
13091
13092 /* Prepare expression for writing.
13093
13094 Like ffecom_prepare_expr, except for expressions to be evaluated
13095 via ffecom_expr_w. */
13096
13097 void
13098 ffecom_prepare_expr_w (tree type, ffebld expr)
13099 {
13100 /* This is all we support for now. */
13101 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
13102
13103 /* ~~For now, it seems to be the same thing. */
13104 ffecom_prepare_expr (expr);
13105 return;
13106 }
13107
13108 /* Prepare expression for returning.
13109
13110 Like ffecom_prepare_expr, except for expressions to be evaluated
13111 via ffecom_return_expr. */
13112
13113 void
13114 ffecom_prepare_return_expr (ffebld expr)
13115 {
13116 assert (current_binding_level->prep_state < 2);
13117
13118 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE
13119 && ffecom_is_altreturning_
13120 && expr != NULL)
13121 ffecom_prepare_expr (expr);
13122 }
13123
13124 /* Prepare pointer to expression.
13125
13126 Like ffecom_prepare_expr, except for expressions to be evaluated
13127 via ffecom_ptr_to_expr. */
13128
13129 void
13130 ffecom_prepare_ptr_to_expr (ffebld expr)
13131 {
13132 /* ~~For now, it seems to be the same thing. */
13133 ffecom_prepare_expr (expr);
13134 return;
13135 }
13136
13137 /* Transform expression into constant pointer-to-expression tree.
13138
13139 If the expression can be transformed into a pointer-to-expression tree
13140 that is constant, that is done, and the tree returned. Else NULL_TREE
13141 is returned.
13142
13143 That way, a caller can attempt to provide compile-time initialization
13144 of a variable and, if that fails, *then* choose to start a new block
13145 and resort to using temporaries, as appropriate. */
13146
13147 tree
13148 ffecom_ptr_to_const_expr (ffebld expr)
13149 {
13150 if (! expr)
13151 return integer_zero_node;
13152
13153 if (ffebld_op (expr) == FFEBLD_opANY)
13154 return error_mark_node;
13155
13156 if (ffebld_arity (expr) == 0
13157 && (ffebld_op (expr) != FFEBLD_opSYMTER
13158 || ffebld_where (expr) == FFEINFO_whereCOMMON
13159 || ffebld_where (expr) == FFEINFO_whereGLOBAL
13160 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
13161 {
13162 tree t;
13163
13164 t = ffecom_ptr_to_expr (expr);
13165 assert (TREE_CONSTANT (t));
13166 return t;
13167 }
13168
13169 return NULL_TREE;
13170 }
13171
13172 /* ffecom_return_expr -- Returns return-value expr given alt return expr
13173
13174 tree rtn; // NULL_TREE means use expand_null_return()
13175 ffebld expr; // NULL if no alt return expr to RETURN stmt
13176 rtn = ffecom_return_expr(expr);
13177
13178 Based on the program unit type and other info (like return function
13179 type, return master function type when alternate ENTRY points,
13180 whether subroutine has any alternate RETURN points, etc), returns the
13181 appropriate expression to be returned to the caller, or NULL_TREE
13182 meaning no return value or the caller expects it to be returned somewhere
13183 else (which is handled by other parts of this module). */
13184
13185 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13186 tree
13187 ffecom_return_expr (ffebld expr)
13188 {
13189 tree rtn;
13190
13191 switch (ffecom_primary_entry_kind_)
13192 {
13193 case FFEINFO_kindPROGRAM:
13194 case FFEINFO_kindBLOCKDATA:
13195 rtn = NULL_TREE;
13196 break;
13197
13198 case FFEINFO_kindSUBROUTINE:
13199 if (!ffecom_is_altreturning_)
13200 rtn = NULL_TREE; /* No alt returns, never an expr. */
13201 else if (expr == NULL)
13202 rtn = integer_zero_node;
13203 else
13204 rtn = ffecom_expr (expr);
13205 break;
13206
13207 case FFEINFO_kindFUNCTION:
13208 if ((ffecom_multi_retval_ != NULL_TREE)
13209 || (ffesymbol_basictype (ffecom_primary_entry_)
13210 == FFEINFO_basictypeCHARACTER)
13211 || ((ffesymbol_basictype (ffecom_primary_entry_)
13212 == FFEINFO_basictypeCOMPLEX)
13213 && (ffecom_num_entrypoints_ == 0)
13214 && ffesymbol_is_f2c (ffecom_primary_entry_)))
13215 { /* Value is returned by direct assignment
13216 into (implicit) dummy. */
13217 rtn = NULL_TREE;
13218 break;
13219 }
13220 rtn = ffecom_func_result_;
13221 #if 0
13222 /* Spurious error if RETURN happens before first reference! So elide
13223 this code. In particular, for debugging registry, rtn should always
13224 be non-null after all, but TREE_USED won't be set until we encounter
13225 a reference in the code. Perfectly okay (but weird) code that,
13226 e.g., has "GOTO 20;10 RETURN;20 RTN=0;GOTO 10", would result in
13227 this diagnostic for no reason. Have people use -O -Wuninitialized
13228 and leave it to the back end to find obviously weird cases. */
13229
13230 /* Used to "assert(rtn != NULL_TREE);" here, but it's kind of a valid
13231 situation; if the return value has never been referenced, it won't
13232 have a tree under 2pass mode. */
13233 if ((rtn == NULL_TREE)
13234 || !TREE_USED (rtn))
13235 {
13236 ffebad_start (FFEBAD_RETURN_VALUE_UNSET);
13237 ffebad_here (0, ffesymbol_where_line (ffecom_primary_entry_),
13238 ffesymbol_where_column (ffecom_primary_entry_));
13239 ffebad_string (ffesymbol_text (ffesymbol_funcresult
13240 (ffecom_primary_entry_)));
13241 ffebad_finish ();
13242 }
13243 #endif
13244 break;
13245
13246 default:
13247 assert ("bad unit kind" == NULL);
13248 case FFEINFO_kindANY:
13249 rtn = error_mark_node;
13250 break;
13251 }
13252
13253 return rtn;
13254 }
13255
13256 #endif
13257 /* Do save_expr only if tree is not error_mark_node. */
13258
13259 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13260 tree
13261 ffecom_save_tree (tree t)
13262 {
13263 return save_expr (t);
13264 }
13265 #endif
13266
13267 /* Start a compound statement (block). */
13268
13269 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13270 void
13271 ffecom_start_compstmt (void)
13272 {
13273 bison_rule_pushlevel_ ();
13274 }
13275 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
13276
13277 /* Public entry point for front end to access start_decl. */
13278
13279 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13280 tree
13281 ffecom_start_decl (tree decl, bool is_initialized)
13282 {
13283 DECL_INITIAL (decl) = is_initialized ? error_mark_node : NULL_TREE;
13284 return start_decl (decl, FALSE);
13285 }
13286
13287 #endif
13288 /* ffecom_sym_commit -- Symbol's state being committed to reality
13289
13290 ffesymbol s;
13291 ffecom_sym_commit(s);
13292
13293 Does whatever the backend needs when a symbol is committed after having
13294 been backtrackable for a period of time. */
13295
13296 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13297 void
13298 ffecom_sym_commit (ffesymbol s UNUSED)
13299 {
13300 assert (!ffesymbol_retractable ());
13301 }
13302
13303 #endif
13304 /* ffecom_sym_end_transition -- Perform end transition on all symbols
13305
13306 ffecom_sym_end_transition();
13307
13308 Does backend-specific stuff and also calls ffest_sym_end_transition
13309 to do the necessary FFE stuff.
13310
13311 Backtracking is never enabled when this fn is called, so don't worry
13312 about it. */
13313
13314 ffesymbol
13315 ffecom_sym_end_transition (ffesymbol s)
13316 {
13317 ffestorag st;
13318
13319 assert (!ffesymbol_retractable ());
13320
13321 s = ffest_sym_end_transition (s);
13322
13323 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13324 if ((ffesymbol_kind (s) == FFEINFO_kindBLOCKDATA)
13325 && (ffesymbol_where (s) == FFEINFO_whereGLOBAL))
13326 {
13327 ffecom_list_blockdata_
13328 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13329 FFEINTRIN_specNONE,
13330 FFEINTRIN_impNONE),
13331 ffecom_list_blockdata_);
13332 }
13333 #endif
13334
13335 /* This is where we finally notice that a symbol has partial initialization
13336 and finalize it. */
13337
13338 if (ffesymbol_accretion (s) != NULL)
13339 {
13340 assert (ffesymbol_init (s) == NULL);
13341 ffecom_notify_init_symbol (s);
13342 }
13343 else if (((st = ffesymbol_storage (s)) != NULL)
13344 && ((st = ffestorag_parent (st)) != NULL)
13345 && (ffestorag_accretion (st) != NULL))
13346 {
13347 assert (ffestorag_init (st) == NULL);
13348 ffecom_notify_init_storage (st);
13349 }
13350
13351 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13352 if ((ffesymbol_kind (s) == FFEINFO_kindCOMMON)
13353 && (ffesymbol_where (s) == FFEINFO_whereLOCAL)
13354 && (ffesymbol_storage (s) != NULL))
13355 {
13356 ffecom_list_common_
13357 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13358 FFEINTRIN_specNONE,
13359 FFEINTRIN_impNONE),
13360 ffecom_list_common_);
13361 }
13362 #endif
13363
13364 return s;
13365 }
13366
13367 /* ffecom_sym_exec_transition -- Perform exec transition on all symbols
13368
13369 ffecom_sym_exec_transition();
13370
13371 Does backend-specific stuff and also calls ffest_sym_exec_transition
13372 to do the necessary FFE stuff.
13373
13374 See the long-winded description in ffecom_sym_learned for info
13375 on handling the situation where backtracking is inhibited. */
13376
13377 ffesymbol
13378 ffecom_sym_exec_transition (ffesymbol s)
13379 {
13380 s = ffest_sym_exec_transition (s);
13381
13382 return s;
13383 }
13384
13385 /* ffecom_sym_learned -- Initial or more info gained on symbol after exec
13386
13387 ffesymbol s;
13388 s = ffecom_sym_learned(s);
13389
13390 Called when a new symbol is seen after the exec transition or when more
13391 info (perhaps) is gained for an UNCERTAIN symbol. The symbol state when
13392 it arrives here is that all its latest info is updated already, so its
13393 state may be UNCERTAIN or UNDERSTOOD, it might already have the hook
13394 field filled in if its gone through here or exec_transition first, and
13395 so on.
13396
13397 The backend probably wants to check ffesymbol_retractable() to see if
13398 backtracking is in effect. If so, the FFE's changes to the symbol may
13399 be retracted (undone) or committed (ratified), at which time the
13400 appropriate ffecom_sym_retract or _commit function will be called
13401 for that function.
13402
13403 If the backend has its own backtracking mechanism, great, use it so that
13404 committal is a simple operation. Though it doesn't make much difference,
13405 I suppose: the reason for tentative symbol evolution in the FFE is to
13406 enable error detection in weird incorrect statements early and to disable
13407 incorrect error detection on a correct statement. The backend is not
13408 likely to introduce any information that'll get involved in these
13409 considerations, so it is probably just fine that the implementation
13410 model for this fn and for _exec_transition is to not do anything
13411 (besides the required FFE stuff) if ffesymbol_retractable() returns TRUE
13412 and instead wait until ffecom_sym_commit is called (which it never
13413 will be as long as we're using ambiguity-detecting statement analysis in
13414 the FFE, which we are initially to shake out the code, but don't depend
13415 on this), otherwise go ahead and do whatever is needed.
13416
13417 In essence, then, when this fn and _exec_transition get called while
13418 backtracking is enabled, a general mechanism would be to flag which (or
13419 both) of these were called (and in what order? neat question as to what
13420 might happen that I'm too lame to think through right now) and then when
13421 _commit is called reproduce the original calling sequence, if any, for
13422 the two fns (at which point backtracking will, of course, be disabled). */
13423
13424 ffesymbol
13425 ffecom_sym_learned (ffesymbol s)
13426 {
13427 ffestorag_exec_layout (s);
13428
13429 return s;
13430 }
13431
13432 /* ffecom_sym_retract -- Symbol's state being retracted from reality
13433
13434 ffesymbol s;
13435 ffecom_sym_retract(s);
13436
13437 Does whatever the backend needs when a symbol is retracted after having
13438 been backtrackable for a period of time. */
13439
13440 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13441 void
13442 ffecom_sym_retract (ffesymbol s UNUSED)
13443 {
13444 assert (!ffesymbol_retractable ());
13445
13446 #if 0 /* GCC doesn't commit any backtrackable sins,
13447 so nothing needed here. */
13448 switch (ffesymbol_hook (s).state)
13449 {
13450 case 0: /* nothing happened yet. */
13451 break;
13452
13453 case 1: /* exec transition happened. */
13454 break;
13455
13456 case 2: /* learned happened. */
13457 break;
13458
13459 case 3: /* learned then exec. */
13460 break;
13461
13462 case 4: /* exec then learned. */
13463 break;
13464
13465 default:
13466 assert ("bad hook state" == NULL);
13467 break;
13468 }
13469 #endif
13470 }
13471
13472 #endif
13473 /* Create temporary gcc label. */
13474
13475 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13476 tree
13477 ffecom_temp_label ()
13478 {
13479 tree glabel;
13480 static int mynumber = 0;
13481
13482 glabel = build_decl (LABEL_DECL,
13483 ffecom_get_invented_identifier ("__g77_label_%d",
13484 mynumber++),
13485 void_type_node);
13486 DECL_CONTEXT (glabel) = current_function_decl;
13487 DECL_MODE (glabel) = VOIDmode;
13488
13489 return glabel;
13490 }
13491
13492 #endif
13493 /* Return an expression that is usable as an arg in a conditional context
13494 (IF, DO WHILE, .NOT., and so on).
13495
13496 Use the one provided for the back end as of >2.6.0. */
13497
13498 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13499 tree
13500 ffecom_truth_value (tree expr)
13501 {
13502 return truthvalue_conversion (expr);
13503 }
13504
13505 #endif
13506 /* Return the inversion of a truth value (the inversion of what
13507 ffecom_truth_value builds).
13508
13509 Apparently invert_truthvalue, which is properly in the back end, is
13510 enough for now, so just use it. */
13511
13512 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13513 tree
13514 ffecom_truth_value_invert (tree expr)
13515 {
13516 return invert_truthvalue (ffecom_truth_value (expr));
13517 }
13518
13519 #endif
13520
13521 /* Return the tree that is the type of the expression, as would be
13522 returned in TREE_TYPE(ffecom_expr(expr)), without otherwise
13523 transforming the expression, generating temporaries, etc. */
13524
13525 tree
13526 ffecom_type_expr (ffebld expr)
13527 {
13528 ffeinfoBasictype bt;
13529 ffeinfoKindtype kt;
13530 tree tree_type;
13531
13532 assert (expr != NULL);
13533
13534 bt = ffeinfo_basictype (ffebld_info (expr));
13535 kt = ffeinfo_kindtype (ffebld_info (expr));
13536 tree_type = ffecom_tree_type[bt][kt];
13537
13538 switch (ffebld_op (expr))
13539 {
13540 case FFEBLD_opCONTER:
13541 case FFEBLD_opSYMTER:
13542 case FFEBLD_opARRAYREF:
13543 case FFEBLD_opUPLUS:
13544 case FFEBLD_opPAREN:
13545 case FFEBLD_opUMINUS:
13546 case FFEBLD_opADD:
13547 case FFEBLD_opSUBTRACT:
13548 case FFEBLD_opMULTIPLY:
13549 case FFEBLD_opDIVIDE:
13550 case FFEBLD_opPOWER:
13551 case FFEBLD_opNOT:
13552 case FFEBLD_opFUNCREF:
13553 case FFEBLD_opSUBRREF:
13554 case FFEBLD_opAND:
13555 case FFEBLD_opOR:
13556 case FFEBLD_opXOR:
13557 case FFEBLD_opNEQV:
13558 case FFEBLD_opEQV:
13559 case FFEBLD_opCONVERT:
13560 case FFEBLD_opLT:
13561 case FFEBLD_opLE:
13562 case FFEBLD_opEQ:
13563 case FFEBLD_opNE:
13564 case FFEBLD_opGT:
13565 case FFEBLD_opGE:
13566 case FFEBLD_opPERCENT_LOC:
13567 return tree_type;
13568
13569 case FFEBLD_opACCTER:
13570 case FFEBLD_opARRTER:
13571 case FFEBLD_opITEM:
13572 case FFEBLD_opSTAR:
13573 case FFEBLD_opBOUNDS:
13574 case FFEBLD_opREPEAT:
13575 case FFEBLD_opLABTER:
13576 case FFEBLD_opLABTOK:
13577 case FFEBLD_opIMPDO:
13578 case FFEBLD_opCONCATENATE:
13579 case FFEBLD_opSUBSTR:
13580 default:
13581 assert ("bad op for ffecom_type_expr" == NULL);
13582 /* Fall through. */
13583 case FFEBLD_opANY:
13584 return error_mark_node;
13585 }
13586 }
13587
13588 /* Return PARM_DECL for arg#1 of master fn containing alternate ENTRY points
13589
13590 If the PARM_DECL already exists, return it, else create it. It's an
13591 integer_type_node argument for the master function that implements a
13592 subroutine or function with more than one entrypoint and is bound at
13593 run time with the entrypoint number (0 for SUBROUTINE/FUNCTION, 1 for
13594 first ENTRY statement, and so on). */
13595
13596 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13597 tree
13598 ffecom_which_entrypoint_decl ()
13599 {
13600 assert (ffecom_which_entrypoint_decl_ != NULL_TREE);
13601
13602 return ffecom_which_entrypoint_decl_;
13603 }
13604
13605 #endif
13606 \f
13607 /* The following sections consists of private and public functions
13608 that have the same names and perform roughly the same functions
13609 as counterparts in the C front end. Changes in the C front end
13610 might affect how things should be done here. Only functions
13611 needed by the back end should be public here; the rest should
13612 be private (static in the C sense). Functions needed by other
13613 g77 front-end modules should be accessed by them via public
13614 ffecom_* names, which should themselves call private versions
13615 in this section so the private versions are easy to recognize
13616 when upgrading to a new gcc and finding interesting changes
13617 in the front end.
13618
13619 Functions named after rule "foo:" in c-parse.y are named
13620 "bison_rule_foo_" so they are easy to find. */
13621
13622 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13623
13624 static void
13625 bison_rule_pushlevel_ ()
13626 {
13627 emit_line_note (input_filename, lineno);
13628 pushlevel (0);
13629 clear_last_expr ();
13630 push_momentary ();
13631 expand_start_bindings (0);
13632 }
13633
13634 static tree
13635 bison_rule_compstmt_ ()
13636 {
13637 tree t;
13638 int keep = kept_level_p ();
13639
13640 /* Make the temps go away. */
13641 if (! keep)
13642 current_binding_level->names = NULL_TREE;
13643
13644 emit_line_note (input_filename, lineno);
13645 expand_end_bindings (getdecls (), keep, 0);
13646 t = poplevel (keep, 1, 0);
13647 pop_momentary ();
13648
13649 return t;
13650 }
13651
13652 /* Return a definition for a builtin function named NAME and whose data type
13653 is TYPE. TYPE should be a function type with argument types.
13654 FUNCTION_CODE tells later passes how to compile calls to this function.
13655 See tree.h for its possible values.
13656
13657 If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
13658 the name to be called if we can't opencode the function. */
13659
13660 tree
13661 builtin_function (const char *name, tree type, int function_code,
13662 enum built_in_class class,
13663 const char *library_name)
13664 {
13665 tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
13666 DECL_EXTERNAL (decl) = 1;
13667 TREE_PUBLIC (decl) = 1;
13668 if (library_name)
13669 DECL_ASSEMBLER_NAME (decl) = get_identifier (library_name);
13670 make_decl_rtl (decl, NULL_PTR, 1);
13671 pushdecl (decl);
13672 DECL_BUILT_IN_CLASS (decl) = class;
13673 DECL_FUNCTION_CODE (decl) = function_code;
13674
13675 return decl;
13676 }
13677
13678 /* Handle when a new declaration NEWDECL
13679 has the same name as an old one OLDDECL
13680 in the same binding contour.
13681 Prints an error message if appropriate.
13682
13683 If safely possible, alter OLDDECL to look like NEWDECL, and return 1.
13684 Otherwise, return 0. */
13685
13686 static int
13687 duplicate_decls (tree newdecl, tree olddecl)
13688 {
13689 int types_match = 1;
13690 int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
13691 && DECL_INITIAL (newdecl) != 0);
13692 tree oldtype = TREE_TYPE (olddecl);
13693 tree newtype = TREE_TYPE (newdecl);
13694
13695 if (olddecl == newdecl)
13696 return 1;
13697
13698 if (TREE_CODE (newtype) == ERROR_MARK
13699 || TREE_CODE (oldtype) == ERROR_MARK)
13700 types_match = 0;
13701
13702 /* New decl is completely inconsistent with the old one =>
13703 tell caller to replace the old one.
13704 This is always an error except in the case of shadowing a builtin. */
13705 if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
13706 return 0;
13707
13708 /* For real parm decl following a forward decl,
13709 return 1 so old decl will be reused. */
13710 if (types_match && TREE_CODE (newdecl) == PARM_DECL
13711 && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
13712 return 1;
13713
13714 /* The new declaration is the same kind of object as the old one.
13715 The declarations may partially match. Print warnings if they don't
13716 match enough. Ultimately, copy most of the information from the new
13717 decl to the old one, and keep using the old one. */
13718
13719 if (TREE_CODE (olddecl) == FUNCTION_DECL
13720 && DECL_BUILT_IN (olddecl))
13721 {
13722 /* A function declaration for a built-in function. */
13723 if (!TREE_PUBLIC (newdecl))
13724 return 0;
13725 else if (!types_match)
13726 {
13727 /* Accept the return type of the new declaration if same modes. */
13728 tree oldreturntype = TREE_TYPE (TREE_TYPE (olddecl));
13729 tree newreturntype = TREE_TYPE (TREE_TYPE (newdecl));
13730
13731 if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
13732 {
13733 /* Function types may be shared, so we can't just modify
13734 the return type of olddecl's function type. */
13735 tree newtype
13736 = build_function_type (newreturntype,
13737 TYPE_ARG_TYPES (TREE_TYPE (olddecl)));
13738
13739 types_match = 1;
13740 if (types_match)
13741 TREE_TYPE (olddecl) = newtype;
13742 }
13743 }
13744 if (!types_match)
13745 return 0;
13746 }
13747 else if (TREE_CODE (olddecl) == FUNCTION_DECL
13748 && DECL_SOURCE_LINE (olddecl) == 0)
13749 {
13750 /* A function declaration for a predeclared function
13751 that isn't actually built in. */
13752 if (!TREE_PUBLIC (newdecl))
13753 return 0;
13754 else if (!types_match)
13755 {
13756 /* If the types don't match, preserve volatility indication.
13757 Later on, we will discard everything else about the
13758 default declaration. */
13759 TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
13760 }
13761 }
13762
13763 /* Copy all the DECL_... slots specified in the new decl
13764 except for any that we copy here from the old type.
13765
13766 Past this point, we don't change OLDTYPE and NEWTYPE
13767 even if we change the types of NEWDECL and OLDDECL. */
13768
13769 if (types_match)
13770 {
13771 /* Merge the data types specified in the two decls. */
13772 if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
13773 TREE_TYPE (newdecl)
13774 = TREE_TYPE (olddecl)
13775 = TREE_TYPE (newdecl);
13776
13777 /* Lay the type out, unless already done. */
13778 if (oldtype != TREE_TYPE (newdecl))
13779 {
13780 if (TREE_TYPE (newdecl) != error_mark_node)
13781 layout_type (TREE_TYPE (newdecl));
13782 if (TREE_CODE (newdecl) != FUNCTION_DECL
13783 && TREE_CODE (newdecl) != TYPE_DECL
13784 && TREE_CODE (newdecl) != CONST_DECL)
13785 layout_decl (newdecl, 0);
13786 }
13787 else
13788 {
13789 /* Since the type is OLDDECL's, make OLDDECL's size go with. */
13790 DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
13791 DECL_SIZE_UNIT (newdecl) = DECL_SIZE_UNIT (olddecl);
13792 if (TREE_CODE (olddecl) != FUNCTION_DECL)
13793 if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
13794 {
13795 DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
13796 DECL_USER_ALIGN (newdecl) |= DECL_USER_ALIGN (olddecl);
13797 }
13798 }
13799
13800 /* Keep the old rtl since we can safely use it. */
13801 DECL_RTL (newdecl) = DECL_RTL (olddecl);
13802
13803 /* Merge the type qualifiers. */
13804 if (DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl)
13805 && !TREE_THIS_VOLATILE (newdecl))
13806 TREE_THIS_VOLATILE (olddecl) = 0;
13807 if (TREE_READONLY (newdecl))
13808 TREE_READONLY (olddecl) = 1;
13809 if (TREE_THIS_VOLATILE (newdecl))
13810 {
13811 TREE_THIS_VOLATILE (olddecl) = 1;
13812 if (TREE_CODE (newdecl) == VAR_DECL)
13813 make_var_volatile (newdecl);
13814 }
13815
13816 /* Keep source location of definition rather than declaration.
13817 Likewise, keep decl at outer scope. */
13818 if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
13819 || (DECL_CONTEXT (newdecl) != 0 && DECL_CONTEXT (olddecl) == 0))
13820 {
13821 DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
13822 DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl);
13823
13824 if (DECL_CONTEXT (olddecl) == 0
13825 && TREE_CODE (newdecl) != FUNCTION_DECL)
13826 DECL_CONTEXT (newdecl) = 0;
13827 }
13828
13829 /* Merge the unused-warning information. */
13830 if (DECL_IN_SYSTEM_HEADER (olddecl))
13831 DECL_IN_SYSTEM_HEADER (newdecl) = 1;
13832 else if (DECL_IN_SYSTEM_HEADER (newdecl))
13833 DECL_IN_SYSTEM_HEADER (olddecl) = 1;
13834
13835 /* Merge the initialization information. */
13836 if (DECL_INITIAL (newdecl) == 0)
13837 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
13838
13839 /* Merge the section attribute.
13840 We want to issue an error if the sections conflict but that must be
13841 done later in decl_attributes since we are called before attributes
13842 are assigned. */
13843 if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
13844 DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
13845
13846 #if BUILT_FOR_270
13847 if (TREE_CODE (newdecl) == FUNCTION_DECL)
13848 {
13849 DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
13850 DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
13851 }
13852 #endif
13853 }
13854 /* If cannot merge, then use the new type and qualifiers,
13855 and don't preserve the old rtl. */
13856 else
13857 {
13858 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
13859 TREE_READONLY (olddecl) = TREE_READONLY (newdecl);
13860 TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl);
13861 TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl);
13862 }
13863
13864 /* Merge the storage class information. */
13865 /* For functions, static overrides non-static. */
13866 if (TREE_CODE (newdecl) == FUNCTION_DECL)
13867 {
13868 TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
13869 /* This is since we don't automatically
13870 copy the attributes of NEWDECL into OLDDECL. */
13871 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
13872 /* If this clears `static', clear it in the identifier too. */
13873 if (! TREE_PUBLIC (olddecl))
13874 TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
13875 }
13876 if (DECL_EXTERNAL (newdecl))
13877 {
13878 TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
13879 DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
13880 /* An extern decl does not override previous storage class. */
13881 TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
13882 }
13883 else
13884 {
13885 TREE_STATIC (olddecl) = TREE_STATIC (newdecl);
13886 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
13887 }
13888
13889 /* If either decl says `inline', this fn is inline,
13890 unless its definition was passed already. */
13891 if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
13892 DECL_INLINE (olddecl) = 1;
13893 DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
13894
13895 /* Get rid of any built-in function if new arg types don't match it
13896 or if we have a function definition. */
13897 if (TREE_CODE (newdecl) == FUNCTION_DECL
13898 && DECL_BUILT_IN (olddecl)
13899 && (!types_match || new_is_definition))
13900 {
13901 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
13902 DECL_BUILT_IN_CLASS (olddecl) = NOT_BUILT_IN;
13903 }
13904
13905 /* If redeclaring a builtin function, and not a definition,
13906 it stays built in.
13907 Also preserve various other info from the definition. */
13908 if (TREE_CODE (newdecl) == FUNCTION_DECL && !new_is_definition)
13909 {
13910 if (DECL_BUILT_IN (olddecl))
13911 {
13912 DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
13913 DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
13914 }
13915 else
13916 DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl);
13917
13918 DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
13919 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
13920 DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
13921 DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
13922 }
13923
13924 /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
13925 But preserve olddecl's DECL_UID. */
13926 {
13927 register unsigned olddecl_uid = DECL_UID (olddecl);
13928
13929 memcpy ((char *) olddecl + sizeof (struct tree_common),
13930 (char *) newdecl + sizeof (struct tree_common),
13931 sizeof (struct tree_decl) - sizeof (struct tree_common));
13932 DECL_UID (olddecl) = olddecl_uid;
13933 }
13934
13935 return 1;
13936 }
13937
13938 /* Finish processing of a declaration;
13939 install its initial value.
13940 If the length of an array type is not known before,
13941 it must be determined now, from the initial value, or it is an error. */
13942
13943 static void
13944 finish_decl (tree decl, tree init, bool is_top_level)
13945 {
13946 register tree type = TREE_TYPE (decl);
13947 int was_incomplete = (DECL_SIZE (decl) == 0);
13948 int temporary = allocation_temporary_p ();
13949 bool at_top_level = (current_binding_level == global_binding_level);
13950 bool top_level = is_top_level || at_top_level;
13951
13952 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
13953 level anyway. */
13954 assert (!is_top_level || !at_top_level);
13955
13956 if (TREE_CODE (decl) == PARM_DECL)
13957 assert (init == NULL_TREE);
13958 /* Remember that PARM_DECL doesn't have a DECL_INITIAL field per se -- it
13959 overlaps DECL_ARG_TYPE. */
13960 else if (init == NULL_TREE)
13961 assert (DECL_INITIAL (decl) == NULL_TREE);
13962 else
13963 assert (DECL_INITIAL (decl) == error_mark_node);
13964
13965 if (init != NULL_TREE)
13966 {
13967 if (TREE_CODE (decl) != TYPE_DECL)
13968 DECL_INITIAL (decl) = init;
13969 else
13970 {
13971 /* typedef foo = bar; store the type of bar as the type of foo. */
13972 TREE_TYPE (decl) = TREE_TYPE (init);
13973 DECL_INITIAL (decl) = init = 0;
13974 }
13975 }
13976
13977 /* Pop back to the obstack that is current for this binding level. This is
13978 because MAXINDEX, rtl, etc. to be made below must go in the permanent
13979 obstack. But don't discard the temporary data yet. */
13980 pop_obstacks ();
13981
13982 /* Deduce size of array from initialization, if not already known */
13983
13984 if (TREE_CODE (type) == ARRAY_TYPE
13985 && TYPE_DOMAIN (type) == 0
13986 && TREE_CODE (decl) != TYPE_DECL)
13987 {
13988 assert (top_level);
13989 assert (was_incomplete);
13990
13991 layout_decl (decl, 0);
13992 }
13993
13994 if (TREE_CODE (decl) == VAR_DECL)
13995 {
13996 if (DECL_SIZE (decl) == NULL_TREE
13997 && TYPE_SIZE (TREE_TYPE (decl)) != NULL_TREE)
13998 layout_decl (decl, 0);
13999
14000 if (DECL_SIZE (decl) == NULL_TREE
14001 && (TREE_STATIC (decl)
14002 ?
14003 /* A static variable with an incomplete type is an error if it is
14004 initialized. Also if it is not file scope. Otherwise, let it
14005 through, but if it is not `extern' then it may cause an error
14006 message later. */
14007 (DECL_INITIAL (decl) != 0 || DECL_CONTEXT (decl) != 0)
14008 :
14009 /* An automatic variable with an incomplete type is an error. */
14010 !DECL_EXTERNAL (decl)))
14011 {
14012 assert ("storage size not known" == NULL);
14013 abort ();
14014 }
14015
14016 if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
14017 && (DECL_SIZE (decl) != 0)
14018 && (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST))
14019 {
14020 assert ("storage size not constant" == NULL);
14021 abort ();
14022 }
14023 }
14024
14025 /* Output the assembler code and/or RTL code for variables and functions,
14026 unless the type is an undefined structure or union. If not, it will get
14027 done when the type is completed. */
14028
14029 if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
14030 {
14031 rest_of_decl_compilation (decl, NULL,
14032 DECL_CONTEXT (decl) == 0,
14033 0);
14034
14035 if (DECL_CONTEXT (decl) != 0)
14036 {
14037 /* Recompute the RTL of a local array now if it used to be an
14038 incomplete type. */
14039 if (was_incomplete
14040 && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
14041 {
14042 /* If we used it already as memory, it must stay in memory. */
14043 TREE_ADDRESSABLE (decl) = TREE_USED (decl);
14044 /* If it's still incomplete now, no init will save it. */
14045 if (DECL_SIZE (decl) == 0)
14046 DECL_INITIAL (decl) = 0;
14047 expand_decl (decl);
14048 }
14049 /* Compute and store the initial value. */
14050 if (TREE_CODE (decl) != FUNCTION_DECL)
14051 expand_decl_init (decl);
14052 }
14053 }
14054 else if (TREE_CODE (decl) == TYPE_DECL)
14055 {
14056 rest_of_decl_compilation (decl, NULL_PTR,
14057 DECL_CONTEXT (decl) == 0,
14058 0);
14059 }
14060
14061 if (!(TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))
14062 && temporary
14063 /* DECL_INITIAL is not defined in PARM_DECLs, since it shares space with
14064 DECL_ARG_TYPE. */
14065 && TREE_CODE (decl) != PARM_DECL)
14066 {
14067 /* We need to remember that this array HAD an initialization, but
14068 discard the actual temporary nodes, since we can't have a permanent
14069 node keep pointing to them. */
14070 /* We make an exception for inline functions, since it's normal for a
14071 local extern redeclaration of an inline function to have a copy of
14072 the top-level decl's DECL_INLINE. */
14073 if ((DECL_INITIAL (decl) != 0)
14074 && (DECL_INITIAL (decl) != error_mark_node))
14075 {
14076 /* If this is a const variable, then preserve the
14077 initializer instead of discarding it so that we can optimize
14078 references to it. */
14079 /* This test used to include TREE_STATIC, but this won't be set
14080 for function level initializers. */
14081 if (TREE_READONLY (decl))
14082 {
14083 preserve_initializer ();
14084
14085 /* The initializer and DECL must have the same (or equivalent
14086 types), but if the initializer is a STRING_CST, its type
14087 might not be on the right obstack, so copy the type
14088 of DECL. */
14089 TREE_TYPE (DECL_INITIAL (decl)) = type;
14090 }
14091 else
14092 DECL_INITIAL (decl) = error_mark_node;
14093 }
14094 }
14095
14096 /* If we have gone back from temporary to permanent allocation, actually
14097 free the temporary space that we no longer need. */
14098 if (temporary && !allocation_temporary_p ())
14099 permanent_allocation (0);
14100
14101 /* At the end of a declaration, throw away any variable type sizes of types
14102 defined inside that declaration. There is no use computing them in the
14103 following function definition. */
14104 if (current_binding_level == global_binding_level)
14105 get_pending_sizes ();
14106 }
14107
14108 /* Finish up a function declaration and compile that function
14109 all the way to assembler language output. The free the storage
14110 for the function definition.
14111
14112 This is called after parsing the body of the function definition.
14113
14114 NESTED is nonzero if the function being finished is nested in another. */
14115
14116 static void
14117 finish_function (int nested)
14118 {
14119 register tree fndecl = current_function_decl;
14120
14121 assert (fndecl != NULL_TREE);
14122 if (TREE_CODE (fndecl) != ERROR_MARK)
14123 {
14124 if (nested)
14125 assert (DECL_CONTEXT (fndecl) != NULL_TREE);
14126 else
14127 assert (DECL_CONTEXT (fndecl) == NULL_TREE);
14128 }
14129
14130 /* TREE_READONLY (fndecl) = 1;
14131 This caused &foo to be of type ptr-to-const-function
14132 which then got a warning when stored in a ptr-to-function variable. */
14133
14134 poplevel (1, 0, 1);
14135
14136 if (TREE_CODE (fndecl) != ERROR_MARK)
14137 {
14138 BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
14139
14140 /* Must mark the RESULT_DECL as being in this function. */
14141
14142 DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
14143
14144 /* Obey `register' declarations if `setjmp' is called in this fn. */
14145 /* Generate rtl for function exit. */
14146 expand_function_end (input_filename, lineno, 0);
14147
14148 /* So we can tell if jump_optimize sets it to 1. */
14149 can_reach_end = 0;
14150
14151 /* If this is a nested function, protect the local variables in the stack
14152 above us from being collected while we're compiling this function. */
14153 if (ggc_p && nested)
14154 ggc_push_context ();
14155
14156 /* Run the optimizers and output the assembler code for this function. */
14157 rest_of_compilation (fndecl);
14158
14159 /* Undo the GC context switch. */
14160 if (ggc_p && nested)
14161 ggc_pop_context ();
14162 }
14163
14164 /* Free all the tree nodes making up this function. */
14165 /* Switch back to allocating nodes permanently until we start another
14166 function. */
14167 if (!nested)
14168 permanent_allocation (1);
14169
14170 if (TREE_CODE (fndecl) != ERROR_MARK
14171 && !nested
14172 && DECL_SAVED_INSNS (fndecl) == 0)
14173 {
14174 /* Stop pointing to the local nodes about to be freed. */
14175 /* But DECL_INITIAL must remain nonzero so we know this was an actual
14176 function definition. */
14177 /* For a nested function, this is done in pop_f_function_context. */
14178 /* If rest_of_compilation set this to 0, leave it 0. */
14179 if (DECL_INITIAL (fndecl) != 0)
14180 DECL_INITIAL (fndecl) = error_mark_node;
14181 DECL_ARGUMENTS (fndecl) = 0;
14182 }
14183
14184 if (!nested)
14185 {
14186 /* Let the error reporting routines know that we're outside a function.
14187 For a nested function, this value is used in pop_c_function_context
14188 and then reset via pop_function_context. */
14189 ffecom_outer_function_decl_ = current_function_decl = NULL;
14190 }
14191 }
14192
14193 /* Plug-in replacement for identifying the name of a decl and, for a
14194 function, what we call it in diagnostics. For now, "program unit"
14195 should suffice, since it's a bit of a hassle to figure out which
14196 of several kinds of things it is. Note that it could conceivably
14197 be a statement function, which probably isn't really a program unit
14198 per se, but if that comes up, it should be easy to check (being a
14199 nested function and all). */
14200
14201 static const char *
14202 lang_printable_name (tree decl, int v)
14203 {
14204 /* Just to keep GCC quiet about the unused variable.
14205 In theory, differing values of V should produce different
14206 output. */
14207 switch (v)
14208 {
14209 default:
14210 if (TREE_CODE (decl) == ERROR_MARK)
14211 return "erroneous code";
14212 return IDENTIFIER_POINTER (DECL_NAME (decl));
14213 }
14214 }
14215
14216 /* g77's function to print out name of current function that caused
14217 an error. */
14218
14219 #if BUILT_FOR_270
14220 static void
14221 lang_print_error_function (const char *file)
14222 {
14223 static ffeglobal last_g = NULL;
14224 static ffesymbol last_s = NULL;
14225 ffeglobal g;
14226 ffesymbol s;
14227 const char *kind;
14228
14229 if ((ffecom_primary_entry_ == NULL)
14230 || (ffesymbol_global (ffecom_primary_entry_) == NULL))
14231 {
14232 g = NULL;
14233 s = NULL;
14234 kind = NULL;
14235 }
14236 else
14237 {
14238 g = ffesymbol_global (ffecom_primary_entry_);
14239 if (ffecom_nested_entry_ == NULL)
14240 {
14241 s = ffecom_primary_entry_;
14242 switch (ffesymbol_kind (s))
14243 {
14244 case FFEINFO_kindFUNCTION:
14245 kind = "function";
14246 break;
14247
14248 case FFEINFO_kindSUBROUTINE:
14249 kind = "subroutine";
14250 break;
14251
14252 case FFEINFO_kindPROGRAM:
14253 kind = "program";
14254 break;
14255
14256 case FFEINFO_kindBLOCKDATA:
14257 kind = "block-data";
14258 break;
14259
14260 default:
14261 kind = ffeinfo_kind_message (ffesymbol_kind (s));
14262 break;
14263 }
14264 }
14265 else
14266 {
14267 s = ffecom_nested_entry_;
14268 kind = "statement function";
14269 }
14270 }
14271
14272 if ((last_g != g) || (last_s != s))
14273 {
14274 if (file)
14275 fprintf (stderr, "%s: ", file);
14276
14277 if (s == NULL)
14278 fprintf (stderr, "Outside of any program unit:\n");
14279 else
14280 {
14281 const char *name = ffesymbol_text (s);
14282
14283 fprintf (stderr, "In %s `%s':\n", kind, name);
14284 }
14285
14286 last_g = g;
14287 last_s = s;
14288 }
14289 }
14290 #endif
14291
14292 /* Similar to `lookup_name' but look only at current binding level. */
14293
14294 static tree
14295 lookup_name_current_level (tree name)
14296 {
14297 register tree t;
14298
14299 if (current_binding_level == global_binding_level)
14300 return IDENTIFIER_GLOBAL_VALUE (name);
14301
14302 if (IDENTIFIER_LOCAL_VALUE (name) == 0)
14303 return 0;
14304
14305 for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
14306 if (DECL_NAME (t) == name)
14307 break;
14308
14309 return t;
14310 }
14311
14312 /* Create a new `struct binding_level'. */
14313
14314 static struct binding_level *
14315 make_binding_level ()
14316 {
14317 /* NOSTRICT */
14318 return (struct binding_level *) xmalloc (sizeof (struct binding_level));
14319 }
14320
14321 /* Save and restore the variables in this file and elsewhere
14322 that keep track of the progress of compilation of the current function.
14323 Used for nested functions. */
14324
14325 struct f_function
14326 {
14327 struct f_function *next;
14328 tree named_labels;
14329 tree shadowed_labels;
14330 struct binding_level *binding_level;
14331 };
14332
14333 struct f_function *f_function_chain;
14334
14335 /* Restore the variables used during compilation of a C function. */
14336
14337 static void
14338 pop_f_function_context ()
14339 {
14340 struct f_function *p = f_function_chain;
14341 tree link;
14342
14343 /* Bring back all the labels that were shadowed. */
14344 for (link = shadowed_labels; link; link = TREE_CHAIN (link))
14345 if (DECL_NAME (TREE_VALUE (link)) != 0)
14346 IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)))
14347 = TREE_VALUE (link);
14348
14349 if (current_function_decl != error_mark_node
14350 && DECL_SAVED_INSNS (current_function_decl) == 0)
14351 {
14352 /* Stop pointing to the local nodes about to be freed. */
14353 /* But DECL_INITIAL must remain nonzero so we know this was an actual
14354 function definition. */
14355 DECL_INITIAL (current_function_decl) = error_mark_node;
14356 DECL_ARGUMENTS (current_function_decl) = 0;
14357 }
14358
14359 pop_function_context ();
14360
14361 f_function_chain = p->next;
14362
14363 named_labels = p->named_labels;
14364 shadowed_labels = p->shadowed_labels;
14365 current_binding_level = p->binding_level;
14366
14367 free (p);
14368 }
14369
14370 /* Save and reinitialize the variables
14371 used during compilation of a C function. */
14372
14373 static void
14374 push_f_function_context ()
14375 {
14376 struct f_function *p
14377 = (struct f_function *) xmalloc (sizeof (struct f_function));
14378
14379 push_function_context ();
14380
14381 p->next = f_function_chain;
14382 f_function_chain = p;
14383
14384 p->named_labels = named_labels;
14385 p->shadowed_labels = shadowed_labels;
14386 p->binding_level = current_binding_level;
14387 }
14388
14389 static void
14390 push_parm_decl (tree parm)
14391 {
14392 int old_immediate_size_expand = immediate_size_expand;
14393
14394 /* Don't try computing parm sizes now -- wait till fn is called. */
14395
14396 immediate_size_expand = 0;
14397
14398 push_obstacks_nochange ();
14399
14400 /* Fill in arg stuff. */
14401
14402 DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
14403 DECL_ARG_TYPE_AS_WRITTEN (parm) = TREE_TYPE (parm);
14404 TREE_READONLY (parm) = 1; /* All implementation args are read-only. */
14405
14406 parm = pushdecl (parm);
14407
14408 immediate_size_expand = old_immediate_size_expand;
14409
14410 finish_decl (parm, NULL_TREE, FALSE);
14411 }
14412
14413 /* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, if appropriate. */
14414
14415 static tree
14416 pushdecl_top_level (x)
14417 tree x;
14418 {
14419 register tree t;
14420 register struct binding_level *b = current_binding_level;
14421 register tree f = current_function_decl;
14422
14423 current_binding_level = global_binding_level;
14424 current_function_decl = NULL_TREE;
14425 t = pushdecl (x);
14426 current_binding_level = b;
14427 current_function_decl = f;
14428 return t;
14429 }
14430
14431 /* Store the list of declarations of the current level.
14432 This is done for the parameter declarations of a function being defined,
14433 after they are modified in the light of any missing parameters. */
14434
14435 static tree
14436 storedecls (decls)
14437 tree decls;
14438 {
14439 return current_binding_level->names = decls;
14440 }
14441
14442 /* Store the parameter declarations into the current function declaration.
14443 This is called after parsing the parameter declarations, before
14444 digesting the body of the function.
14445
14446 For an old-style definition, modify the function's type
14447 to specify at least the number of arguments. */
14448
14449 static void
14450 store_parm_decls (int is_main_program UNUSED)
14451 {
14452 register tree fndecl = current_function_decl;
14453
14454 if (fndecl == error_mark_node)
14455 return;
14456
14457 /* This is a chain of PARM_DECLs from old-style parm declarations. */
14458 DECL_ARGUMENTS (fndecl) = storedecls (nreverse (getdecls ()));
14459
14460 /* Initialize the RTL code for the function. */
14461
14462 init_function_start (fndecl, input_filename, lineno);
14463
14464 /* Set up parameters and prepare for return, for the function. */
14465
14466 expand_function_start (fndecl, 0);
14467 }
14468
14469 static tree
14470 start_decl (tree decl, bool is_top_level)
14471 {
14472 register tree tem;
14473 bool at_top_level = (current_binding_level == global_binding_level);
14474 bool top_level = is_top_level || at_top_level;
14475
14476 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
14477 level anyway. */
14478 assert (!is_top_level || !at_top_level);
14479
14480 /* The corresponding pop_obstacks is in finish_decl. */
14481 push_obstacks_nochange ();
14482
14483 if (DECL_INITIAL (decl) != NULL_TREE)
14484 {
14485 assert (DECL_INITIAL (decl) == error_mark_node);
14486 assert (!DECL_EXTERNAL (decl));
14487 }
14488 else if (top_level)
14489 assert ((TREE_STATIC (decl) == 1) || DECL_EXTERNAL (decl) == 1);
14490
14491 /* For Fortran, we by default put things in .common when possible. */
14492 DECL_COMMON (decl) = 1;
14493
14494 /* Add this decl to the current binding level. TEM may equal DECL or it may
14495 be a previous decl of the same name. */
14496 if (is_top_level)
14497 tem = pushdecl_top_level (decl);
14498 else
14499 tem = pushdecl (decl);
14500
14501 /* For a local variable, define the RTL now. */
14502 if (!top_level
14503 /* But not if this is a duplicate decl and we preserved the rtl from the
14504 previous one (which may or may not happen). */
14505 && DECL_RTL (tem) == 0)
14506 {
14507 if (TYPE_SIZE (TREE_TYPE (tem)) != 0)
14508 expand_decl (tem);
14509 else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
14510 && DECL_INITIAL (tem) != 0)
14511 expand_decl (tem);
14512 }
14513
14514 if (DECL_INITIAL (tem) != NULL_TREE)
14515 {
14516 /* When parsing and digesting the initializer, use temporary storage.
14517 Do this even if we will ignore the value. */
14518 if (at_top_level)
14519 temporary_allocation ();
14520 }
14521
14522 return tem;
14523 }
14524
14525 /* Create the FUNCTION_DECL for a function definition.
14526 DECLSPECS and DECLARATOR are the parts of the declaration;
14527 they describe the function's name and the type it returns,
14528 but twisted together in a fashion that parallels the syntax of C.
14529
14530 This function creates a binding context for the function body
14531 as well as setting up the FUNCTION_DECL in current_function_decl.
14532
14533 Returns 1 on success. If the DECLARATOR is not suitable for a function
14534 (it defines a datum instead), we return 0, which tells
14535 yyparse to report a parse error.
14536
14537 NESTED is nonzero for a function nested within another function. */
14538
14539 static void
14540 start_function (tree name, tree type, int nested, int public)
14541 {
14542 tree decl1;
14543 tree restype;
14544 int old_immediate_size_expand = immediate_size_expand;
14545
14546 named_labels = 0;
14547 shadowed_labels = 0;
14548
14549 /* Don't expand any sizes in the return type of the function. */
14550 immediate_size_expand = 0;
14551
14552 if (nested)
14553 {
14554 assert (!public);
14555 assert (current_function_decl != NULL_TREE);
14556 assert (DECL_CONTEXT (current_function_decl) == NULL_TREE);
14557 }
14558 else
14559 {
14560 assert (current_function_decl == NULL_TREE);
14561 }
14562
14563 if (TREE_CODE (type) == ERROR_MARK)
14564 decl1 = current_function_decl = error_mark_node;
14565 else
14566 {
14567 decl1 = build_decl (FUNCTION_DECL,
14568 name,
14569 type);
14570 TREE_PUBLIC (decl1) = public ? 1 : 0;
14571 if (nested)
14572 DECL_INLINE (decl1) = 1;
14573 TREE_STATIC (decl1) = 1;
14574 DECL_EXTERNAL (decl1) = 0;
14575
14576 announce_function (decl1);
14577
14578 /* Make the init_value nonzero so pushdecl knows this is not tentative.
14579 error_mark_node is replaced below (in poplevel) with the BLOCK. */
14580 DECL_INITIAL (decl1) = error_mark_node;
14581
14582 /* Record the decl so that the function name is defined. If we already have
14583 a decl for this name, and it is a FUNCTION_DECL, use the old decl. */
14584
14585 current_function_decl = pushdecl (decl1);
14586 }
14587
14588 if (!nested)
14589 ffecom_outer_function_decl_ = current_function_decl;
14590
14591 pushlevel (0);
14592 current_binding_level->prep_state = 2;
14593
14594 if (TREE_CODE (current_function_decl) != ERROR_MARK)
14595 {
14596 make_function_rtl (current_function_decl);
14597
14598 restype = TREE_TYPE (TREE_TYPE (current_function_decl));
14599 DECL_RESULT (current_function_decl)
14600 = build_decl (RESULT_DECL, NULL_TREE, restype);
14601 }
14602
14603 if (!nested)
14604 /* Allocate further tree nodes temporarily during compilation of this
14605 function only. */
14606 temporary_allocation ();
14607
14608 if (!nested && (TREE_CODE (current_function_decl) != ERROR_MARK))
14609 TREE_ADDRESSABLE (current_function_decl) = 1;
14610
14611 immediate_size_expand = old_immediate_size_expand;
14612 }
14613 \f
14614 /* Here are the public functions the GNU back end needs. */
14615
14616 tree
14617 convert (type, expr)
14618 tree type, expr;
14619 {
14620 register tree e = expr;
14621 register enum tree_code code = TREE_CODE (type);
14622
14623 if (type == TREE_TYPE (e)
14624 || TREE_CODE (e) == ERROR_MARK)
14625 return e;
14626 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
14627 return fold (build1 (NOP_EXPR, type, e));
14628 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
14629 || code == ERROR_MARK)
14630 return error_mark_node;
14631 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
14632 {
14633 assert ("void value not ignored as it ought to be" == NULL);
14634 return error_mark_node;
14635 }
14636 if (code == VOID_TYPE)
14637 return build1 (CONVERT_EXPR, type, e);
14638 if ((code != RECORD_TYPE)
14639 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
14640 e = ffecom_1 (REALPART_EXPR, TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e))),
14641 e);
14642 if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
14643 return fold (convert_to_integer (type, e));
14644 if (code == POINTER_TYPE)
14645 return fold (convert_to_pointer (type, e));
14646 if (code == REAL_TYPE)
14647 return fold (convert_to_real (type, e));
14648 if (code == COMPLEX_TYPE)
14649 return fold (convert_to_complex (type, e));
14650 if (code == RECORD_TYPE)
14651 return fold (ffecom_convert_to_complex_ (type, e));
14652
14653 assert ("conversion to non-scalar type requested" == NULL);
14654 return error_mark_node;
14655 }
14656
14657 /* integrate_decl_tree calls this function, but since we don't use the
14658 DECL_LANG_SPECIFIC field, this is a no-op. */
14659
14660 void
14661 copy_lang_decl (node)
14662 tree node UNUSED;
14663 {
14664 }
14665
14666 /* Return the list of declarations of the current level.
14667 Note that this list is in reverse order unless/until
14668 you nreverse it; and when you do nreverse it, you must
14669 store the result back using `storedecls' or you will lose. */
14670
14671 tree
14672 getdecls ()
14673 {
14674 return current_binding_level->names;
14675 }
14676
14677 /* Nonzero if we are currently in the global binding level. */
14678
14679 int
14680 global_bindings_p ()
14681 {
14682 return current_binding_level == global_binding_level;
14683 }
14684
14685 /* Print an error message for invalid use of an incomplete type.
14686 VALUE is the expression that was used (or 0 if that isn't known)
14687 and TYPE is the type that was invalid. */
14688
14689 void
14690 incomplete_type_error (value, type)
14691 tree value UNUSED;
14692 tree type;
14693 {
14694 if (TREE_CODE (type) == ERROR_MARK)
14695 return;
14696
14697 assert ("incomplete type?!?" == NULL);
14698 }
14699
14700 /* Mark ARG for GC. */
14701 static void
14702 mark_binding_level (void *arg)
14703 {
14704 struct binding_level *level = *(struct binding_level **) arg;
14705
14706 while (level)
14707 {
14708 ggc_mark_tree (level->names);
14709 ggc_mark_tree (level->blocks);
14710 ggc_mark_tree (level->this_block);
14711 level = level->level_chain;
14712 }
14713 }
14714
14715 void
14716 init_decl_processing ()
14717 {
14718 static tree *const tree_roots[] = {
14719 &current_function_decl,
14720 &string_type_node,
14721 &ffecom_tree_fun_type_void,
14722 &ffecom_integer_zero_node,
14723 &ffecom_integer_one_node,
14724 &ffecom_tree_subr_type,
14725 &ffecom_tree_ptr_to_subr_type,
14726 &ffecom_tree_blockdata_type,
14727 &ffecom_tree_xargc_,
14728 &ffecom_f2c_integer_type_node,
14729 &ffecom_f2c_ptr_to_integer_type_node,
14730 &ffecom_f2c_address_type_node,
14731 &ffecom_f2c_real_type_node,
14732 &ffecom_f2c_ptr_to_real_type_node,
14733 &ffecom_f2c_doublereal_type_node,
14734 &ffecom_f2c_complex_type_node,
14735 &ffecom_f2c_doublecomplex_type_node,
14736 &ffecom_f2c_longint_type_node,
14737 &ffecom_f2c_logical_type_node,
14738 &ffecom_f2c_flag_type_node,
14739 &ffecom_f2c_ftnlen_type_node,
14740 &ffecom_f2c_ftnlen_zero_node,
14741 &ffecom_f2c_ftnlen_one_node,
14742 &ffecom_f2c_ftnlen_two_node,
14743 &ffecom_f2c_ptr_to_ftnlen_type_node,
14744 &ffecom_f2c_ftnint_type_node,
14745 &ffecom_f2c_ptr_to_ftnint_type_node,
14746 &ffecom_outer_function_decl_,
14747 &ffecom_previous_function_decl_,
14748 &ffecom_which_entrypoint_decl_,
14749 &ffecom_float_zero_,
14750 &ffecom_float_half_,
14751 &ffecom_double_zero_,
14752 &ffecom_double_half_,
14753 &ffecom_func_result_,
14754 &ffecom_func_length_,
14755 &ffecom_multi_type_node_,
14756 &ffecom_multi_retval_,
14757 &named_labels,
14758 &shadowed_labels
14759 };
14760 size_t i;
14761
14762 malloc_init ();
14763
14764 /* Record our roots. */
14765 for (i = 0; i < sizeof(tree_roots)/sizeof(tree_roots[0]); i++)
14766 ggc_add_tree_root (tree_roots[i], 1);
14767 ggc_add_tree_root (&ffecom_tree_type[0][0],
14768 FFEINFO_basictype*FFEINFO_kindtype);
14769 ggc_add_tree_root (&ffecom_tree_fun_type[0][0],
14770 FFEINFO_basictype*FFEINFO_kindtype);
14771 ggc_add_tree_root (&ffecom_tree_ptr_to_fun_type[0][0],
14772 FFEINFO_basictype*FFEINFO_kindtype);
14773 ggc_add_tree_root (ffecom_gfrt_, FFECOM_gfrt);
14774 ggc_add_root (&current_binding_level, 1, sizeof current_binding_level,
14775 mark_binding_level);
14776 ggc_add_root (&free_binding_level, 1, sizeof current_binding_level,
14777 mark_binding_level);
14778 ggc_add_root (&tracker_head, 1, sizeof tracker_head, mark_tracker_head);
14779
14780 ffe_init_0 ();
14781 }
14782
14783 const char *
14784 init_parse (filename)
14785 const char *filename;
14786 {
14787 /* Open input file. */
14788 if (filename == 0 || !strcmp (filename, "-"))
14789 {
14790 finput = stdin;
14791 filename = "stdin";
14792 }
14793 else
14794 finput = fopen (filename, "r");
14795 if (finput == 0)
14796 pfatal_with_name (filename);
14797
14798 #ifdef IO_BUFFER_SIZE
14799 setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);
14800 #endif
14801
14802 /* Make identifier nodes long enough for the language-specific slots. */
14803 set_identifier_size (sizeof (struct lang_identifier));
14804 decl_printable_name = lang_printable_name;
14805 #if BUILT_FOR_270
14806 print_error_function = lang_print_error_function;
14807 #endif
14808
14809 return filename;
14810 }
14811
14812 void
14813 finish_parse ()
14814 {
14815 fclose (finput);
14816 }
14817
14818 /* Delete the node BLOCK from the current binding level.
14819 This is used for the block inside a stmt expr ({...})
14820 so that the block can be reinserted where appropriate. */
14821
14822 static void
14823 delete_block (block)
14824 tree block;
14825 {
14826 tree t;
14827 if (current_binding_level->blocks == block)
14828 current_binding_level->blocks = TREE_CHAIN (block);
14829 for (t = current_binding_level->blocks; t;)
14830 {
14831 if (TREE_CHAIN (t) == block)
14832 TREE_CHAIN (t) = TREE_CHAIN (block);
14833 else
14834 t = TREE_CHAIN (t);
14835 }
14836 TREE_CHAIN (block) = NULL;
14837 /* Clear TREE_USED which is always set by poplevel.
14838 The flag is set again if insert_block is called. */
14839 TREE_USED (block) = 0;
14840 }
14841
14842 void
14843 insert_block (block)
14844 tree block;
14845 {
14846 TREE_USED (block) = 1;
14847 current_binding_level->blocks
14848 = chainon (current_binding_level->blocks, block);
14849 }
14850
14851 int
14852 lang_decode_option (argc, argv)
14853 int argc;
14854 char **argv;
14855 {
14856 return ffe_decode_option (argc, argv);
14857 }
14858
14859 /* used by print-tree.c */
14860
14861 void
14862 lang_print_xnode (file, node, indent)
14863 FILE *file UNUSED;
14864 tree node UNUSED;
14865 int indent UNUSED;
14866 {
14867 }
14868
14869 void
14870 lang_finish ()
14871 {
14872 ffe_terminate_0 ();
14873
14874 if (ffe_is_ffedebug ())
14875 malloc_pool_display (malloc_pool_image ());
14876 }
14877
14878 const char *
14879 lang_identify ()
14880 {
14881 return "f77";
14882 }
14883
14884 /* Return the typed-based alias set for T, which may be an expression
14885 or a type. Return -1 if we don't do anything special. */
14886
14887 HOST_WIDE_INT
14888 lang_get_alias_set (t)
14889 tree t ATTRIBUTE_UNUSED;
14890 {
14891 /* We do not wish to use alias-set based aliasing at all. Used in the
14892 extreme (every object with its own set, with equivalences recorded)
14893 it might be helpful, but there are problems when it comes to inlining.
14894 We get on ok with flag_argument_noalias, and alias-set aliasing does
14895 currently limit how stack slots can be reused, which is a lose. */
14896 return 0;
14897 }
14898
14899 void
14900 lang_init_options ()
14901 {
14902 /* Set default options for Fortran. */
14903 flag_move_all_movables = 1;
14904 flag_reduce_all_givs = 1;
14905 flag_argument_noalias = 2;
14906 flag_errno_math = 0;
14907 flag_complex_divide_method = 1;
14908 }
14909
14910 void
14911 lang_init ()
14912 {
14913 /* If the file is output from cpp, it should contain a first line
14914 `# 1 "real-filename"', and the current design of gcc (toplev.c
14915 in particular and the way it sets up information relied on by
14916 INCLUDE) requires that we read this now, and store the
14917 "real-filename" info in master_input_filename. Ask the lexer
14918 to try doing this. */
14919 ffelex_hash_kludge (finput);
14920 }
14921
14922 int
14923 mark_addressable (exp)
14924 tree exp;
14925 {
14926 register tree x = exp;
14927 while (1)
14928 switch (TREE_CODE (x))
14929 {
14930 case ADDR_EXPR:
14931 case COMPONENT_REF:
14932 case ARRAY_REF:
14933 x = TREE_OPERAND (x, 0);
14934 break;
14935
14936 case CONSTRUCTOR:
14937 TREE_ADDRESSABLE (x) = 1;
14938 return 1;
14939
14940 case VAR_DECL:
14941 case CONST_DECL:
14942 case PARM_DECL:
14943 case RESULT_DECL:
14944 if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)
14945 && DECL_NONLOCAL (x))
14946 {
14947 if (TREE_PUBLIC (x))
14948 {
14949 assert ("address of global register var requested" == NULL);
14950 return 0;
14951 }
14952 assert ("address of register variable requested" == NULL);
14953 }
14954 else if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x))
14955 {
14956 if (TREE_PUBLIC (x))
14957 {
14958 assert ("address of global register var requested" == NULL);
14959 return 0;
14960 }
14961 assert ("address of register var requested" == NULL);
14962 }
14963 put_var_into_stack (x);
14964
14965 /* drops in */
14966 case FUNCTION_DECL:
14967 TREE_ADDRESSABLE (x) = 1;
14968 #if 0 /* poplevel deals with this now. */
14969 if (DECL_CONTEXT (x) == 0)
14970 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
14971 #endif
14972
14973 default:
14974 return 1;
14975 }
14976 }
14977
14978 /* If DECL has a cleanup, build and return that cleanup here.
14979 This is a callback called by expand_expr. */
14980
14981 tree
14982 maybe_build_cleanup (decl)
14983 tree decl UNUSED;
14984 {
14985 /* There are no cleanups in Fortran. */
14986 return NULL_TREE;
14987 }
14988
14989 /* Exit a binding level.
14990 Pop the level off, and restore the state of the identifier-decl mappings
14991 that were in effect when this level was entered.
14992
14993 If KEEP is nonzero, this level had explicit declarations, so
14994 and create a "block" (a BLOCK node) for the level
14995 to record its declarations and subblocks for symbol table output.
14996
14997 If FUNCTIONBODY is nonzero, this level is the body of a function,
14998 so create a block as if KEEP were set and also clear out all
14999 label names.
15000
15001 If REVERSE is nonzero, reverse the order of decls before putting
15002 them into the BLOCK. */
15003
15004 tree
15005 poplevel (keep, reverse, functionbody)
15006 int keep;
15007 int reverse;
15008 int functionbody;
15009 {
15010 register tree link;
15011 /* The chain of decls was accumulated in reverse order.
15012 Put it into forward order, just for cleanliness. */
15013 tree decls;
15014 tree subblocks = current_binding_level->blocks;
15015 tree block = 0;
15016 tree decl;
15017 int block_previously_created;
15018
15019 /* Get the decls in the order they were written.
15020 Usually current_binding_level->names is in reverse order.
15021 But parameter decls were previously put in forward order. */
15022
15023 if (reverse)
15024 current_binding_level->names
15025 = decls = nreverse (current_binding_level->names);
15026 else
15027 decls = current_binding_level->names;
15028
15029 /* Output any nested inline functions within this block
15030 if they weren't already output. */
15031
15032 for (decl = decls; decl; decl = TREE_CHAIN (decl))
15033 if (TREE_CODE (decl) == FUNCTION_DECL
15034 && ! TREE_ASM_WRITTEN (decl)
15035 && DECL_INITIAL (decl) != 0
15036 && TREE_ADDRESSABLE (decl))
15037 {
15038 /* If this decl was copied from a file-scope decl
15039 on account of a block-scope extern decl,
15040 propagate TREE_ADDRESSABLE to the file-scope decl.
15041
15042 DECL_ABSTRACT_ORIGIN can be set to itself if warn_return_type is
15043 true, since then the decl goes through save_for_inline_copying. */
15044 if (DECL_ABSTRACT_ORIGIN (decl) != 0
15045 && DECL_ABSTRACT_ORIGIN (decl) != decl)
15046 TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
15047 else if (DECL_SAVED_INSNS (decl) != 0)
15048 {
15049 push_function_context ();
15050 output_inline_function (decl);
15051 pop_function_context ();
15052 }
15053 }
15054
15055 /* If there were any declarations or structure tags in that level,
15056 or if this level is a function body,
15057 create a BLOCK to record them for the life of this function. */
15058
15059 block = 0;
15060 block_previously_created = (current_binding_level->this_block != 0);
15061 if (block_previously_created)
15062 block = current_binding_level->this_block;
15063 else if (keep || functionbody)
15064 block = make_node (BLOCK);
15065 if (block != 0)
15066 {
15067 BLOCK_VARS (block) = decls;
15068 BLOCK_SUBBLOCKS (block) = subblocks;
15069 }
15070
15071 /* In each subblock, record that this is its superior. */
15072
15073 for (link = subblocks; link; link = TREE_CHAIN (link))
15074 BLOCK_SUPERCONTEXT (link) = block;
15075
15076 /* Clear out the meanings of the local variables of this level. */
15077
15078 for (link = decls; link; link = TREE_CHAIN (link))
15079 {
15080 if (DECL_NAME (link) != 0)
15081 {
15082 /* If the ident. was used or addressed via a local extern decl,
15083 don't forget that fact. */
15084 if (DECL_EXTERNAL (link))
15085 {
15086 if (TREE_USED (link))
15087 TREE_USED (DECL_NAME (link)) = 1;
15088 if (TREE_ADDRESSABLE (link))
15089 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
15090 }
15091 IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0;
15092 }
15093 }
15094
15095 /* If the level being exited is the top level of a function,
15096 check over all the labels, and clear out the current
15097 (function local) meanings of their names. */
15098
15099 if (functionbody)
15100 {
15101 /* If this is the top level block of a function,
15102 the vars are the function's parameters.
15103 Don't leave them in the BLOCK because they are
15104 found in the FUNCTION_DECL instead. */
15105
15106 BLOCK_VARS (block) = 0;
15107 }
15108
15109 /* Pop the current level, and free the structure for reuse. */
15110
15111 {
15112 register struct binding_level *level = current_binding_level;
15113 current_binding_level = current_binding_level->level_chain;
15114
15115 level->level_chain = free_binding_level;
15116 free_binding_level = level;
15117 }
15118
15119 /* Dispose of the block that we just made inside some higher level. */
15120 if (functionbody
15121 && current_function_decl != error_mark_node)
15122 DECL_INITIAL (current_function_decl) = block;
15123 else if (block)
15124 {
15125 if (!block_previously_created)
15126 current_binding_level->blocks
15127 = chainon (current_binding_level->blocks, block);
15128 }
15129 /* If we did not make a block for the level just exited,
15130 any blocks made for inner levels
15131 (since they cannot be recorded as subblocks in that level)
15132 must be carried forward so they will later become subblocks
15133 of something else. */
15134 else if (subblocks)
15135 current_binding_level->blocks
15136 = chainon (current_binding_level->blocks, subblocks);
15137
15138 if (block)
15139 TREE_USED (block) = 1;
15140 return block;
15141 }
15142
15143 void
15144 print_lang_decl (file, node, indent)
15145 FILE *file UNUSED;
15146 tree node UNUSED;
15147 int indent UNUSED;
15148 {
15149 }
15150
15151 void
15152 print_lang_identifier (file, node, indent)
15153 FILE *file;
15154 tree node;
15155 int indent;
15156 {
15157 print_node (file, "global", IDENTIFIER_GLOBAL_VALUE (node), indent + 4);
15158 print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4);
15159 }
15160
15161 void
15162 print_lang_statistics ()
15163 {
15164 }
15165
15166 void
15167 print_lang_type (file, node, indent)
15168 FILE *file UNUSED;
15169 tree node UNUSED;
15170 int indent UNUSED;
15171 {
15172 }
15173
15174 /* Record a decl-node X as belonging to the current lexical scope.
15175 Check for errors (such as an incompatible declaration for the same
15176 name already seen in the same scope).
15177
15178 Returns either X or an old decl for the same name.
15179 If an old decl is returned, it may have been smashed
15180 to agree with what X says. */
15181
15182 tree
15183 pushdecl (x)
15184 tree x;
15185 {
15186 register tree t;
15187 register tree name = DECL_NAME (x);
15188 register struct binding_level *b = current_binding_level;
15189
15190 if ((TREE_CODE (x) == FUNCTION_DECL)
15191 && (DECL_INITIAL (x) == 0)
15192 && DECL_EXTERNAL (x))
15193 DECL_CONTEXT (x) = NULL_TREE;
15194 else
15195 DECL_CONTEXT (x) = current_function_decl;
15196
15197 if (name)
15198 {
15199 if (IDENTIFIER_INVENTED (name))
15200 {
15201 #if BUILT_FOR_270
15202 DECL_ARTIFICIAL (x) = 1;
15203 #endif
15204 DECL_IN_SYSTEM_HEADER (x) = 1;
15205 }
15206
15207 t = lookup_name_current_level (name);
15208
15209 assert ((t == NULL_TREE) || (DECL_CONTEXT (x) == NULL_TREE));
15210
15211 /* Don't push non-parms onto list for parms until we understand
15212 why we're doing this and whether it works. */
15213
15214 assert ((b == global_binding_level)
15215 || !ffecom_transform_only_dummies_
15216 || TREE_CODE (x) == PARM_DECL);
15217
15218 if ((t != NULL_TREE) && duplicate_decls (x, t))
15219 return t;
15220
15221 /* If we are processing a typedef statement, generate a whole new
15222 ..._TYPE node (which will be just an variant of the existing
15223 ..._TYPE node with identical properties) and then install the
15224 TYPE_DECL node generated to represent the typedef name as the
15225 TYPE_NAME of this brand new (duplicate) ..._TYPE node.
15226
15227 The whole point here is to end up with a situation where each and every
15228 ..._TYPE node the compiler creates will be uniquely associated with
15229 AT MOST one node representing a typedef name. This way, even though
15230 the compiler substitutes corresponding ..._TYPE nodes for TYPE_DECL
15231 (i.e. "typedef name") nodes very early on, later parts of the
15232 compiler can always do the reverse translation and get back the
15233 corresponding typedef name. For example, given:
15234
15235 typedef struct S MY_TYPE; MY_TYPE object;
15236
15237 Later parts of the compiler might only know that `object' was of type
15238 `struct S' if it were not for code just below. With this code
15239 however, later parts of the compiler see something like:
15240
15241 struct S' == struct S typedef struct S' MY_TYPE; struct S' object;
15242
15243 And they can then deduce (from the node for type struct S') that the
15244 original object declaration was:
15245
15246 MY_TYPE object;
15247
15248 Being able to do this is important for proper support of protoize, and
15249 also for generating precise symbolic debugging information which
15250 takes full account of the programmer's (typedef) vocabulary.
15251
15252 Obviously, we don't want to generate a duplicate ..._TYPE node if the
15253 TYPE_DECL node that we are now processing really represents a
15254 standard built-in type.
15255
15256 Since all standard types are effectively declared at line zero in the
15257 source file, we can easily check to see if we are working on a
15258 standard type by checking the current value of lineno. */
15259
15260 if (TREE_CODE (x) == TYPE_DECL)
15261 {
15262 if (DECL_SOURCE_LINE (x) == 0)
15263 {
15264 if (TYPE_NAME (TREE_TYPE (x)) == 0)
15265 TYPE_NAME (TREE_TYPE (x)) = x;
15266 }
15267 else if (TREE_TYPE (x) != error_mark_node)
15268 {
15269 tree tt = TREE_TYPE (x);
15270
15271 tt = build_type_copy (tt);
15272 TYPE_NAME (tt) = x;
15273 TREE_TYPE (x) = tt;
15274 }
15275 }
15276
15277 /* This name is new in its binding level. Install the new declaration
15278 and return it. */
15279 if (b == global_binding_level)
15280 IDENTIFIER_GLOBAL_VALUE (name) = x;
15281 else
15282 IDENTIFIER_LOCAL_VALUE (name) = x;
15283 }
15284
15285 /* Put decls on list in reverse order. We will reverse them later if
15286 necessary. */
15287 TREE_CHAIN (x) = b->names;
15288 b->names = x;
15289
15290 return x;
15291 }
15292
15293 /* Nonzero if the current level needs to have a BLOCK made. */
15294
15295 static int
15296 kept_level_p ()
15297 {
15298 tree decl;
15299
15300 for (decl = current_binding_level->names;
15301 decl;
15302 decl = TREE_CHAIN (decl))
15303 {
15304 if (TREE_USED (decl) || TREE_CODE (decl) != VAR_DECL
15305 || (DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl)))
15306 /* Currently, there aren't supposed to be non-artificial names
15307 at other than the top block for a function -- they're
15308 believed to always be temps. But it's wise to check anyway. */
15309 return 1;
15310 }
15311 return 0;
15312 }
15313
15314 /* Enter a new binding level.
15315 If TAG_TRANSPARENT is nonzero, do so only for the name space of variables,
15316 not for that of tags. */
15317
15318 void
15319 pushlevel (tag_transparent)
15320 int tag_transparent;
15321 {
15322 register struct binding_level *newlevel = NULL_BINDING_LEVEL;
15323
15324 assert (! tag_transparent);
15325
15326 if (current_binding_level == global_binding_level)
15327 {
15328 named_labels = 0;
15329 }
15330
15331 /* Reuse or create a struct for this binding level. */
15332
15333 if (free_binding_level)
15334 {
15335 newlevel = free_binding_level;
15336 free_binding_level = free_binding_level->level_chain;
15337 }
15338 else
15339 {
15340 newlevel = make_binding_level ();
15341 }
15342
15343 /* Add this level to the front of the chain (stack) of levels that
15344 are active. */
15345
15346 *newlevel = clear_binding_level;
15347 newlevel->level_chain = current_binding_level;
15348 current_binding_level = newlevel;
15349 }
15350
15351 /* Set the BLOCK node for the innermost scope
15352 (the one we are currently in). */
15353
15354 void
15355 set_block (block)
15356 register tree block;
15357 {
15358 current_binding_level->this_block = block;
15359 }
15360
15361 /* ~~gcc/tree.h *should* declare this, because toplev.c references it. */
15362
15363 /* Can't 'yydebug' a front end not generated by yacc/bison! */
15364
15365 void
15366 set_yydebug (value)
15367 int value;
15368 {
15369 if (value)
15370 fprintf (stderr, "warning: no yacc/bison-generated output to debug!\n");
15371 }
15372
15373 tree
15374 signed_or_unsigned_type (unsignedp, type)
15375 int unsignedp;
15376 tree type;
15377 {
15378 tree type2;
15379
15380 if (! INTEGRAL_TYPE_P (type))
15381 return type;
15382 if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
15383 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15384 if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
15385 return unsignedp ? unsigned_type_node : integer_type_node;
15386 if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node))
15387 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15388 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node))
15389 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15390 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node))
15391 return (unsignedp ? long_long_unsigned_type_node
15392 : long_long_integer_type_node);
15393
15394 type2 = type_for_size (TYPE_PRECISION (type), unsignedp);
15395 if (type2 == NULL_TREE)
15396 return type;
15397
15398 return type2;
15399 }
15400
15401 tree
15402 signed_type (type)
15403 tree type;
15404 {
15405 tree type1 = TYPE_MAIN_VARIANT (type);
15406 ffeinfoKindtype kt;
15407 tree type2;
15408
15409 if (type1 == unsigned_char_type_node || type1 == char_type_node)
15410 return signed_char_type_node;
15411 if (type1 == unsigned_type_node)
15412 return integer_type_node;
15413 if (type1 == short_unsigned_type_node)
15414 return short_integer_type_node;
15415 if (type1 == long_unsigned_type_node)
15416 return long_integer_type_node;
15417 if (type1 == long_long_unsigned_type_node)
15418 return long_long_integer_type_node;
15419 #if 0 /* gcc/c-* files only */
15420 if (type1 == unsigned_intDI_type_node)
15421 return intDI_type_node;
15422 if (type1 == unsigned_intSI_type_node)
15423 return intSI_type_node;
15424 if (type1 == unsigned_intHI_type_node)
15425 return intHI_type_node;
15426 if (type1 == unsigned_intQI_type_node)
15427 return intQI_type_node;
15428 #endif
15429
15430 type2 = type_for_size (TYPE_PRECISION (type1), 0);
15431 if (type2 != NULL_TREE)
15432 return type2;
15433
15434 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15435 {
15436 type2 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
15437
15438 if (type1 == type2)
15439 return ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15440 }
15441
15442 return type;
15443 }
15444
15445 /* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
15446 or validate its data type for an `if' or `while' statement or ?..: exp.
15447
15448 This preparation consists of taking the ordinary
15449 representation of an expression expr and producing a valid tree
15450 boolean expression describing whether expr is nonzero. We could
15451 simply always do build_binary_op (NE_EXPR, expr, integer_zero_node, 1),
15452 but we optimize comparisons, &&, ||, and !.
15453
15454 The resulting type should always be `integer_type_node'. */
15455
15456 tree
15457 truthvalue_conversion (expr)
15458 tree expr;
15459 {
15460 if (TREE_CODE (expr) == ERROR_MARK)
15461 return expr;
15462
15463 #if 0 /* This appears to be wrong for C++. */
15464 /* These really should return error_mark_node after 2.4 is stable.
15465 But not all callers handle ERROR_MARK properly. */
15466 switch (TREE_CODE (TREE_TYPE (expr)))
15467 {
15468 case RECORD_TYPE:
15469 error ("struct type value used where scalar is required");
15470 return integer_zero_node;
15471
15472 case UNION_TYPE:
15473 error ("union type value used where scalar is required");
15474 return integer_zero_node;
15475
15476 case ARRAY_TYPE:
15477 error ("array type value used where scalar is required");
15478 return integer_zero_node;
15479
15480 default:
15481 break;
15482 }
15483 #endif /* 0 */
15484
15485 switch (TREE_CODE (expr))
15486 {
15487 /* It is simpler and generates better code to have only TRUTH_*_EXPR
15488 or comparison expressions as truth values at this level. */
15489 #if 0
15490 case COMPONENT_REF:
15491 /* A one-bit unsigned bit-field is already acceptable. */
15492 if (1 == TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (expr, 1)))
15493 && TREE_UNSIGNED (TREE_OPERAND (expr, 1)))
15494 return expr;
15495 break;
15496 #endif
15497
15498 case EQ_EXPR:
15499 /* It is simpler and generates better code to have only TRUTH_*_EXPR
15500 or comparison expressions as truth values at this level. */
15501 #if 0
15502 if (integer_zerop (TREE_OPERAND (expr, 1)))
15503 return build_unary_op (TRUTH_NOT_EXPR, TREE_OPERAND (expr, 0), 0);
15504 #endif
15505 case NE_EXPR: case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
15506 case TRUTH_ANDIF_EXPR:
15507 case TRUTH_ORIF_EXPR:
15508 case TRUTH_AND_EXPR:
15509 case TRUTH_OR_EXPR:
15510 case TRUTH_XOR_EXPR:
15511 TREE_TYPE (expr) = integer_type_node;
15512 return expr;
15513
15514 case ERROR_MARK:
15515 return expr;
15516
15517 case INTEGER_CST:
15518 return integer_zerop (expr) ? integer_zero_node : integer_one_node;
15519
15520 case REAL_CST:
15521 return real_zerop (expr) ? integer_zero_node : integer_one_node;
15522
15523 case ADDR_EXPR:
15524 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0)))
15525 return build (COMPOUND_EXPR, integer_type_node,
15526 TREE_OPERAND (expr, 0), integer_one_node);
15527 else
15528 return integer_one_node;
15529
15530 case COMPLEX_EXPR:
15531 return ffecom_2 ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
15532 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15533 integer_type_node,
15534 truthvalue_conversion (TREE_OPERAND (expr, 0)),
15535 truthvalue_conversion (TREE_OPERAND (expr, 1)));
15536
15537 case NEGATE_EXPR:
15538 case ABS_EXPR:
15539 case FLOAT_EXPR:
15540 case FFS_EXPR:
15541 /* These don't change whether an object is non-zero or zero. */
15542 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15543
15544 case LROTATE_EXPR:
15545 case RROTATE_EXPR:
15546 /* These don't change whether an object is zero or non-zero, but
15547 we can't ignore them if their second arg has side-effects. */
15548 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
15549 return build (COMPOUND_EXPR, integer_type_node, TREE_OPERAND (expr, 1),
15550 truthvalue_conversion (TREE_OPERAND (expr, 0)));
15551 else
15552 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15553
15554 case COND_EXPR:
15555 /* Distribute the conversion into the arms of a COND_EXPR. */
15556 return fold (build (COND_EXPR, integer_type_node, TREE_OPERAND (expr, 0),
15557 truthvalue_conversion (TREE_OPERAND (expr, 1)),
15558 truthvalue_conversion (TREE_OPERAND (expr, 2))));
15559
15560 case CONVERT_EXPR:
15561 /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
15562 since that affects how `default_conversion' will behave. */
15563 if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE
15564 || TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
15565 break;
15566 /* fall through... */
15567 case NOP_EXPR:
15568 /* If this is widening the argument, we can ignore it. */
15569 if (TYPE_PRECISION (TREE_TYPE (expr))
15570 >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
15571 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15572 break;
15573
15574 case MINUS_EXPR:
15575 /* With IEEE arithmetic, x - x may not equal 0, so we can't optimize
15576 this case. */
15577 if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
15578 && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE)
15579 break;
15580 /* fall through... */
15581 case BIT_XOR_EXPR:
15582 /* This and MINUS_EXPR can be changed into a comparison of the
15583 two objects. */
15584 if (TREE_TYPE (TREE_OPERAND (expr, 0))
15585 == TREE_TYPE (TREE_OPERAND (expr, 1)))
15586 return ffecom_2 (NE_EXPR, integer_type_node,
15587 TREE_OPERAND (expr, 0),
15588 TREE_OPERAND (expr, 1));
15589 return ffecom_2 (NE_EXPR, integer_type_node,
15590 TREE_OPERAND (expr, 0),
15591 fold (build1 (NOP_EXPR,
15592 TREE_TYPE (TREE_OPERAND (expr, 0)),
15593 TREE_OPERAND (expr, 1))));
15594
15595 case BIT_AND_EXPR:
15596 if (integer_onep (TREE_OPERAND (expr, 1)))
15597 return expr;
15598 break;
15599
15600 case MODIFY_EXPR:
15601 #if 0 /* No such thing in Fortran. */
15602 if (warn_parentheses && C_EXP_ORIGINAL_CODE (expr) == MODIFY_EXPR)
15603 warning ("suggest parentheses around assignment used as truth value");
15604 #endif
15605 break;
15606
15607 default:
15608 break;
15609 }
15610
15611 if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
15612 return (ffecom_2
15613 ((TREE_SIDE_EFFECTS (expr)
15614 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15615 integer_type_node,
15616 truthvalue_conversion (ffecom_1 (REALPART_EXPR,
15617 TREE_TYPE (TREE_TYPE (expr)),
15618 expr)),
15619 truthvalue_conversion (ffecom_1 (IMAGPART_EXPR,
15620 TREE_TYPE (TREE_TYPE (expr)),
15621 expr))));
15622
15623 return ffecom_2 (NE_EXPR, integer_type_node,
15624 expr,
15625 convert (TREE_TYPE (expr), integer_zero_node));
15626 }
15627
15628 tree
15629 type_for_mode (mode, unsignedp)
15630 enum machine_mode mode;
15631 int unsignedp;
15632 {
15633 int i;
15634 int j;
15635 tree t;
15636
15637 if (mode == TYPE_MODE (integer_type_node))
15638 return unsignedp ? unsigned_type_node : integer_type_node;
15639
15640 if (mode == TYPE_MODE (signed_char_type_node))
15641 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15642
15643 if (mode == TYPE_MODE (short_integer_type_node))
15644 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15645
15646 if (mode == TYPE_MODE (long_integer_type_node))
15647 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15648
15649 if (mode == TYPE_MODE (long_long_integer_type_node))
15650 return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
15651
15652 #if HOST_BITS_PER_WIDE_INT >= 64
15653 if (mode == TYPE_MODE (intTI_type_node))
15654 return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
15655 #endif
15656
15657 if (mode == TYPE_MODE (float_type_node))
15658 return float_type_node;
15659
15660 if (mode == TYPE_MODE (double_type_node))
15661 return double_type_node;
15662
15663 if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
15664 return build_pointer_type (char_type_node);
15665
15666 if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
15667 return build_pointer_type (integer_type_node);
15668
15669 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
15670 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
15671 {
15672 if (((t = ffecom_tree_type[i][j]) != NULL_TREE)
15673 && (mode == TYPE_MODE (t)))
15674 {
15675 if ((i == FFEINFO_basictypeINTEGER) && unsignedp)
15676 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][j];
15677 else
15678 return t;
15679 }
15680 }
15681
15682 return 0;
15683 }
15684
15685 tree
15686 type_for_size (bits, unsignedp)
15687 unsigned bits;
15688 int unsignedp;
15689 {
15690 ffeinfoKindtype kt;
15691 tree type_node;
15692
15693 if (bits == TYPE_PRECISION (integer_type_node))
15694 return unsignedp ? unsigned_type_node : integer_type_node;
15695
15696 if (bits == TYPE_PRECISION (signed_char_type_node))
15697 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15698
15699 if (bits == TYPE_PRECISION (short_integer_type_node))
15700 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15701
15702 if (bits == TYPE_PRECISION (long_integer_type_node))
15703 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15704
15705 if (bits == TYPE_PRECISION (long_long_integer_type_node))
15706 return (unsignedp ? long_long_unsigned_type_node
15707 : long_long_integer_type_node);
15708
15709 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15710 {
15711 type_node = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15712
15713 if ((type_node != NULL_TREE) && (bits == TYPE_PRECISION (type_node)))
15714 return unsignedp ? ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt]
15715 : type_node;
15716 }
15717
15718 return 0;
15719 }
15720
15721 tree
15722 unsigned_type (type)
15723 tree type;
15724 {
15725 tree type1 = TYPE_MAIN_VARIANT (type);
15726 ffeinfoKindtype kt;
15727 tree type2;
15728
15729 if (type1 == signed_char_type_node || type1 == char_type_node)
15730 return unsigned_char_type_node;
15731 if (type1 == integer_type_node)
15732 return unsigned_type_node;
15733 if (type1 == short_integer_type_node)
15734 return short_unsigned_type_node;
15735 if (type1 == long_integer_type_node)
15736 return long_unsigned_type_node;
15737 if (type1 == long_long_integer_type_node)
15738 return long_long_unsigned_type_node;
15739 #if 0 /* gcc/c-* files only */
15740 if (type1 == intDI_type_node)
15741 return unsigned_intDI_type_node;
15742 if (type1 == intSI_type_node)
15743 return unsigned_intSI_type_node;
15744 if (type1 == intHI_type_node)
15745 return unsigned_intHI_type_node;
15746 if (type1 == intQI_type_node)
15747 return unsigned_intQI_type_node;
15748 #endif
15749
15750 type2 = type_for_size (TYPE_PRECISION (type1), 1);
15751 if (type2 != NULL_TREE)
15752 return type2;
15753
15754 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15755 {
15756 type2 = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15757
15758 if (type1 == type2)
15759 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
15760 }
15761
15762 return type;
15763 }
15764
15765 /* Callback routines for garbage collection. */
15766
15767 int ggc_p = 1;
15768
15769 void
15770 lang_mark_tree (t)
15771 union tree_node *t ATTRIBUTE_UNUSED;
15772 {
15773 if (TREE_CODE (t) == IDENTIFIER_NODE)
15774 {
15775 struct lang_identifier *i = (struct lang_identifier *) t;
15776 ggc_mark_tree (IDENTIFIER_GLOBAL_VALUE (i));
15777 ggc_mark_tree (IDENTIFIER_LOCAL_VALUE (i));
15778 ggc_mark_tree (IDENTIFIER_LABEL_VALUE (i));
15779 }
15780 else if (TYPE_P (t) && TYPE_LANG_SPECIFIC (t))
15781 ggc_mark (TYPE_LANG_SPECIFIC (t));
15782 }
15783
15784 void
15785 lang_mark_false_label_stack (l)
15786 struct label_node *l;
15787 {
15788 /* Fortran doesn't use false_label_stack. It better be NULL. */
15789 if (l != NULL)
15790 abort();
15791 }
15792
15793 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
15794 \f
15795 #if FFECOM_GCC_INCLUDE
15796
15797 /* From gcc/cccp.c, the code to handle -I. */
15798
15799 /* Skip leading "./" from a directory name.
15800 This may yield the empty string, which represents the current directory. */
15801
15802 static const char *
15803 skip_redundant_dir_prefix (const char *dir)
15804 {
15805 while (dir[0] == '.' && dir[1] == '/')
15806 for (dir += 2; *dir == '/'; dir++)
15807 continue;
15808 if (dir[0] == '.' && !dir[1])
15809 dir++;
15810 return dir;
15811 }
15812
15813 /* The file_name_map structure holds a mapping of file names for a
15814 particular directory. This mapping is read from the file named
15815 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
15816 map filenames on a file system with severe filename restrictions,
15817 such as DOS. The format of the file name map file is just a series
15818 of lines with two tokens on each line. The first token is the name
15819 to map, and the second token is the actual name to use. */
15820
15821 struct file_name_map
15822 {
15823 struct file_name_map *map_next;
15824 char *map_from;
15825 char *map_to;
15826 };
15827
15828 #define FILE_NAME_MAP_FILE "header.gcc"
15829
15830 /* Current maximum length of directory names in the search path
15831 for include files. (Altered as we get more of them.) */
15832
15833 static int max_include_len = 0;
15834
15835 struct file_name_list
15836 {
15837 struct file_name_list *next;
15838 char *fname;
15839 /* Mapping of file names for this directory. */
15840 struct file_name_map *name_map;
15841 /* Non-zero if name_map is valid. */
15842 int got_name_map;
15843 };
15844
15845 static struct file_name_list *include = NULL; /* First dir to search */
15846 static struct file_name_list *last_include = NULL; /* Last in chain */
15847
15848 /* I/O buffer structure.
15849 The `fname' field is nonzero for source files and #include files
15850 and for the dummy text used for -D and -U.
15851 It is zero for rescanning results of macro expansion
15852 and for expanding macro arguments. */
15853 #define INPUT_STACK_MAX 400
15854 static struct file_buf {
15855 const char *fname;
15856 /* Filename specified with #line command. */
15857 const char *nominal_fname;
15858 /* Record where in the search path this file was found.
15859 For #include_next. */
15860 struct file_name_list *dir;
15861 ffewhereLine line;
15862 ffewhereColumn column;
15863 } instack[INPUT_STACK_MAX];
15864
15865 static int last_error_tick = 0; /* Incremented each time we print it. */
15866 static int input_file_stack_tick = 0; /* Incremented when status changes. */
15867
15868 /* Current nesting level of input sources.
15869 `instack[indepth]' is the level currently being read. */
15870 static int indepth = -1;
15871
15872 typedef struct file_buf FILE_BUF;
15873
15874 typedef unsigned char U_CHAR;
15875
15876 /* table to tell if char can be part of a C identifier. */
15877 U_CHAR is_idchar[256];
15878 /* table to tell if char can be first char of a c identifier. */
15879 U_CHAR is_idstart[256];
15880 /* table to tell if c is horizontal space. */
15881 U_CHAR is_hor_space[256];
15882 /* table to tell if c is horizontal or vertical space. */
15883 static U_CHAR is_space[256];
15884
15885 #define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
15886 #define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*p]) p++; } while (0)
15887
15888 /* Nonzero means -I- has been seen,
15889 so don't look for #include "foo" the source-file directory. */
15890 static int ignore_srcdir;
15891
15892 #ifndef INCLUDE_LEN_FUDGE
15893 #define INCLUDE_LEN_FUDGE 0
15894 #endif
15895
15896 static void append_include_chain (struct file_name_list *first,
15897 struct file_name_list *last);
15898 static FILE *open_include_file (char *filename,
15899 struct file_name_list *searchptr);
15900 static void print_containing_files (ffebadSeverity sev);
15901 static const char *skip_redundant_dir_prefix (const char *);
15902 static char *read_filename_string (int ch, FILE *f);
15903 static struct file_name_map *read_name_map (const char *dirname);
15904
15905 /* Append a chain of `struct file_name_list's
15906 to the end of the main include chain.
15907 FIRST is the beginning of the chain to append, and LAST is the end. */
15908
15909 static void
15910 append_include_chain (first, last)
15911 struct file_name_list *first, *last;
15912 {
15913 struct file_name_list *dir;
15914
15915 if (!first || !last)
15916 return;
15917
15918 if (include == 0)
15919 include = first;
15920 else
15921 last_include->next = first;
15922
15923 for (dir = first; ; dir = dir->next) {
15924 int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE;
15925 if (len > max_include_len)
15926 max_include_len = len;
15927 if (dir == last)
15928 break;
15929 }
15930
15931 last->next = NULL;
15932 last_include = last;
15933 }
15934
15935 /* Try to open include file FILENAME. SEARCHPTR is the directory
15936 being tried from the include file search path. This function maps
15937 filenames on file systems based on information read by
15938 read_name_map. */
15939
15940 static FILE *
15941 open_include_file (filename, searchptr)
15942 char *filename;
15943 struct file_name_list *searchptr;
15944 {
15945 register struct file_name_map *map;
15946 register char *from;
15947 char *p, *dir;
15948
15949 if (searchptr && ! searchptr->got_name_map)
15950 {
15951 searchptr->name_map = read_name_map (searchptr->fname
15952 ? searchptr->fname : ".");
15953 searchptr->got_name_map = 1;
15954 }
15955
15956 /* First check the mapping for the directory we are using. */
15957 if (searchptr && searchptr->name_map)
15958 {
15959 from = filename;
15960 if (searchptr->fname)
15961 from += strlen (searchptr->fname) + 1;
15962 for (map = searchptr->name_map; map; map = map->map_next)
15963 {
15964 if (! strcmp (map->map_from, from))
15965 {
15966 /* Found a match. */
15967 return fopen (map->map_to, "r");
15968 }
15969 }
15970 }
15971
15972 /* Try to find a mapping file for the particular directory we are
15973 looking in. Thus #include <sys/types.h> will look up sys/types.h
15974 in /usr/include/header.gcc and look up types.h in
15975 /usr/include/sys/header.gcc. */
15976 p = rindex (filename, '/');
15977 #ifdef DIR_SEPARATOR
15978 if (! p) p = rindex (filename, DIR_SEPARATOR);
15979 else {
15980 char *tmp = rindex (filename, DIR_SEPARATOR);
15981 if (tmp != NULL && tmp > p) p = tmp;
15982 }
15983 #endif
15984 if (! p)
15985 p = filename;
15986 if (searchptr
15987 && searchptr->fname
15988 && strlen (searchptr->fname) == (size_t) (p - filename)
15989 && ! strncmp (searchptr->fname, filename, (int) (p - filename)))
15990 {
15991 /* FILENAME is in SEARCHPTR, which we've already checked. */
15992 return fopen (filename, "r");
15993 }
15994
15995 if (p == filename)
15996 {
15997 from = filename;
15998 map = read_name_map (".");
15999 }
16000 else
16001 {
16002 dir = (char *) xmalloc (p - filename + 1);
16003 memcpy (dir, filename, p - filename);
16004 dir[p - filename] = '\0';
16005 from = p + 1;
16006 map = read_name_map (dir);
16007 free (dir);
16008 }
16009 for (; map; map = map->map_next)
16010 if (! strcmp (map->map_from, from))
16011 return fopen (map->map_to, "r");
16012
16013 return fopen (filename, "r");
16014 }
16015
16016 /* Print the file names and line numbers of the #include
16017 commands which led to the current file. */
16018
16019 static void
16020 print_containing_files (ffebadSeverity sev)
16021 {
16022 FILE_BUF *ip = NULL;
16023 int i;
16024 int first = 1;
16025 const char *str1;
16026 const char *str2;
16027
16028 /* If stack of files hasn't changed since we last printed
16029 this info, don't repeat it. */
16030 if (last_error_tick == input_file_stack_tick)
16031 return;
16032
16033 for (i = indepth; i >= 0; i--)
16034 if (instack[i].fname != NULL) {
16035 ip = &instack[i];
16036 break;
16037 }
16038
16039 /* Give up if we don't find a source file. */
16040 if (ip == NULL)
16041 return;
16042
16043 /* Find the other, outer source files. */
16044 for (i--; i >= 0; i--)
16045 if (instack[i].fname != NULL)
16046 {
16047 ip = &instack[i];
16048 if (first)
16049 {
16050 first = 0;
16051 str1 = "In file included";
16052 }
16053 else
16054 {
16055 str1 = "... ...";
16056 }
16057
16058 if (i == 1)
16059 str2 = ":";
16060 else
16061 str2 = "";
16062
16063 ffebad_start_msg ("%A from %B at %0%C", sev);
16064 ffebad_here (0, ip->line, ip->column);
16065 ffebad_string (str1);
16066 ffebad_string (ip->nominal_fname);
16067 ffebad_string (str2);
16068 ffebad_finish ();
16069 }
16070
16071 /* Record we have printed the status as of this time. */
16072 last_error_tick = input_file_stack_tick;
16073 }
16074
16075 /* Read a space delimited string of unlimited length from a stdio
16076 file. */
16077
16078 static char *
16079 read_filename_string (ch, f)
16080 int ch;
16081 FILE *f;
16082 {
16083 char *alloc, *set;
16084 int len;
16085
16086 len = 20;
16087 set = alloc = xmalloc (len + 1);
16088 if (! is_space[ch])
16089 {
16090 *set++ = ch;
16091 while ((ch = getc (f)) != EOF && ! is_space[ch])
16092 {
16093 if (set - alloc == len)
16094 {
16095 len *= 2;
16096 alloc = xrealloc (alloc, len + 1);
16097 set = alloc + len / 2;
16098 }
16099 *set++ = ch;
16100 }
16101 }
16102 *set = '\0';
16103 ungetc (ch, f);
16104 return alloc;
16105 }
16106
16107 /* Read the file name map file for DIRNAME. */
16108
16109 static struct file_name_map *
16110 read_name_map (dirname)
16111 const char *dirname;
16112 {
16113 /* This structure holds a linked list of file name maps, one per
16114 directory. */
16115 struct file_name_map_list
16116 {
16117 struct file_name_map_list *map_list_next;
16118 char *map_list_name;
16119 struct file_name_map *map_list_map;
16120 };
16121 static struct file_name_map_list *map_list;
16122 register struct file_name_map_list *map_list_ptr;
16123 char *name;
16124 FILE *f;
16125 size_t dirlen;
16126 int separator_needed;
16127
16128 dirname = skip_redundant_dir_prefix (dirname);
16129
16130 for (map_list_ptr = map_list; map_list_ptr;
16131 map_list_ptr = map_list_ptr->map_list_next)
16132 if (! strcmp (map_list_ptr->map_list_name, dirname))
16133 return map_list_ptr->map_list_map;
16134
16135 map_list_ptr = ((struct file_name_map_list *)
16136 xmalloc (sizeof (struct file_name_map_list)));
16137 map_list_ptr->map_list_name = xstrdup (dirname);
16138 map_list_ptr->map_list_map = NULL;
16139
16140 dirlen = strlen (dirname);
16141 separator_needed = dirlen != 0 && dirname[dirlen - 1] != '/';
16142 name = (char *) xmalloc (dirlen + strlen (FILE_NAME_MAP_FILE) + 2);
16143 strcpy (name, dirname);
16144 name[dirlen] = '/';
16145 strcpy (name + dirlen + separator_needed, FILE_NAME_MAP_FILE);
16146 f = fopen (name, "r");
16147 free (name);
16148 if (!f)
16149 map_list_ptr->map_list_map = NULL;
16150 else
16151 {
16152 int ch;
16153
16154 while ((ch = getc (f)) != EOF)
16155 {
16156 char *from, *to;
16157 struct file_name_map *ptr;
16158
16159 if (is_space[ch])
16160 continue;
16161 from = read_filename_string (ch, f);
16162 while ((ch = getc (f)) != EOF && is_hor_space[ch])
16163 ;
16164 to = read_filename_string (ch, f);
16165
16166 ptr = ((struct file_name_map *)
16167 xmalloc (sizeof (struct file_name_map)));
16168 ptr->map_from = from;
16169
16170 /* Make the real filename absolute. */
16171 if (*to == '/')
16172 ptr->map_to = to;
16173 else
16174 {
16175 ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
16176 strcpy (ptr->map_to, dirname);
16177 ptr->map_to[dirlen] = '/';
16178 strcpy (ptr->map_to + dirlen + separator_needed, to);
16179 free (to);
16180 }
16181
16182 ptr->map_next = map_list_ptr->map_list_map;
16183 map_list_ptr->map_list_map = ptr;
16184
16185 while ((ch = getc (f)) != '\n')
16186 if (ch == EOF)
16187 break;
16188 }
16189 fclose (f);
16190 }
16191
16192 map_list_ptr->map_list_next = map_list;
16193 map_list = map_list_ptr;
16194
16195 return map_list_ptr->map_list_map;
16196 }
16197
16198 static void
16199 ffecom_file_ (const char *name)
16200 {
16201 FILE_BUF *fp;
16202
16203 /* Do partial setup of input buffer for the sake of generating
16204 early #line directives (when -g is in effect). */
16205
16206 fp = &instack[++indepth];
16207 memset ((char *) fp, 0, sizeof (FILE_BUF));
16208 if (name == NULL)
16209 name = "";
16210 fp->nominal_fname = fp->fname = name;
16211 }
16212
16213 /* Initialize syntactic classifications of characters. */
16214
16215 static void
16216 ffecom_initialize_char_syntax_ ()
16217 {
16218 register int i;
16219
16220 /*
16221 * Set up is_idchar and is_idstart tables. These should be
16222 * faster than saying (is_alpha (c) || c == '_'), etc.
16223 * Set up these things before calling any routines tthat
16224 * refer to them.
16225 */
16226 for (i = 'a'; i <= 'z'; i++) {
16227 is_idchar[i - 'a' + 'A'] = 1;
16228 is_idchar[i] = 1;
16229 is_idstart[i - 'a' + 'A'] = 1;
16230 is_idstart[i] = 1;
16231 }
16232 for (i = '0'; i <= '9'; i++)
16233 is_idchar[i] = 1;
16234 is_idchar['_'] = 1;
16235 is_idstart['_'] = 1;
16236
16237 /* horizontal space table */
16238 is_hor_space[' '] = 1;
16239 is_hor_space['\t'] = 1;
16240 is_hor_space['\v'] = 1;
16241 is_hor_space['\f'] = 1;
16242 is_hor_space['\r'] = 1;
16243
16244 is_space[' '] = 1;
16245 is_space['\t'] = 1;
16246 is_space['\v'] = 1;
16247 is_space['\f'] = 1;
16248 is_space['\n'] = 1;
16249 is_space['\r'] = 1;
16250 }
16251
16252 static void
16253 ffecom_close_include_ (FILE *f)
16254 {
16255 fclose (f);
16256
16257 indepth--;
16258 input_file_stack_tick++;
16259
16260 ffewhere_line_kill (instack[indepth].line);
16261 ffewhere_column_kill (instack[indepth].column);
16262 }
16263
16264 static int
16265 ffecom_decode_include_option_ (char *spec)
16266 {
16267 struct file_name_list *dirtmp;
16268
16269 if (! ignore_srcdir && !strcmp (spec, "-"))
16270 ignore_srcdir = 1;
16271 else
16272 {
16273 dirtmp = (struct file_name_list *)
16274 xmalloc (sizeof (struct file_name_list));
16275 dirtmp->next = 0; /* New one goes on the end */
16276 if (spec[0] != 0)
16277 dirtmp->fname = spec;
16278 else
16279 fatal ("Directory name must immediately follow -I option with no intervening spaces, as in `-Idir', not `-I dir'");
16280 dirtmp->got_name_map = 0;
16281 append_include_chain (dirtmp, dirtmp);
16282 }
16283 return 1;
16284 }
16285
16286 /* Open INCLUDEd file. */
16287
16288 static FILE *
16289 ffecom_open_include_ (char *name, ffewhereLine l, ffewhereColumn c)
16290 {
16291 char *fbeg = name;
16292 size_t flen = strlen (fbeg);
16293 struct file_name_list *search_start = include; /* Chain of dirs to search */
16294 struct file_name_list dsp[1]; /* First in chain, if #include "..." */
16295 struct file_name_list *searchptr = 0;
16296 char *fname; /* Dynamically allocated fname buffer */
16297 FILE *f;
16298 FILE_BUF *fp;
16299
16300 if (flen == 0)
16301 return NULL;
16302
16303 dsp[0].fname = NULL;
16304
16305 /* If -I- was specified, don't search current dir, only spec'd ones. */
16306 if (!ignore_srcdir)
16307 {
16308 for (fp = &instack[indepth]; fp >= instack; fp--)
16309 {
16310 int n;
16311 char *ep;
16312 const char *nam;
16313
16314 if ((nam = fp->nominal_fname) != NULL)
16315 {
16316 /* Found a named file. Figure out dir of the file,
16317 and put it in front of the search list. */
16318 dsp[0].next = search_start;
16319 search_start = dsp;
16320 #ifndef VMS
16321 ep = rindex (nam, '/');
16322 #ifdef DIR_SEPARATOR
16323 if (ep == NULL) ep = rindex (nam, DIR_SEPARATOR);
16324 else {
16325 char *tmp = rindex (nam, DIR_SEPARATOR);
16326 if (tmp != NULL && tmp > ep) ep = tmp;
16327 }
16328 #endif
16329 #else /* VMS */
16330 ep = rindex (nam, ']');
16331 if (ep == NULL) ep = rindex (nam, '>');
16332 if (ep == NULL) ep = rindex (nam, ':');
16333 if (ep != NULL) ep++;
16334 #endif /* VMS */
16335 if (ep != NULL)
16336 {
16337 n = ep - nam;
16338 dsp[0].fname = (char *) xmalloc (n + 1);
16339 strncpy (dsp[0].fname, nam, n);
16340 dsp[0].fname[n] = '\0';
16341 if (n + INCLUDE_LEN_FUDGE > max_include_len)
16342 max_include_len = n + INCLUDE_LEN_FUDGE;
16343 }
16344 else
16345 dsp[0].fname = NULL; /* Current directory */
16346 dsp[0].got_name_map = 0;
16347 break;
16348 }
16349 }
16350 }
16351
16352 /* Allocate this permanently, because it gets stored in the definitions
16353 of macros. */
16354 fname = xmalloc (max_include_len + flen + 4);
16355 /* + 2 above for slash and terminating null. */
16356 /* + 2 added for '.h' on VMS (to support '#include filename') (NOT USED
16357 for g77 yet). */
16358
16359 /* If specified file name is absolute, just open it. */
16360
16361 if (*fbeg == '/'
16362 #ifdef DIR_SEPARATOR
16363 || *fbeg == DIR_SEPARATOR
16364 #endif
16365 )
16366 {
16367 strncpy (fname, (char *) fbeg, flen);
16368 fname[flen] = 0;
16369 f = open_include_file (fname, NULL_PTR);
16370 }
16371 else
16372 {
16373 f = NULL;
16374
16375 /* Search directory path, trying to open the file.
16376 Copy each filename tried into FNAME. */
16377
16378 for (searchptr = search_start; searchptr; searchptr = searchptr->next)
16379 {
16380 if (searchptr->fname)
16381 {
16382 /* The empty string in a search path is ignored.
16383 This makes it possible to turn off entirely
16384 a standard piece of the list. */
16385 if (searchptr->fname[0] == 0)
16386 continue;
16387 strcpy (fname, skip_redundant_dir_prefix (searchptr->fname));
16388 if (fname[0] && fname[strlen (fname) - 1] != '/')
16389 strcat (fname, "/");
16390 fname[strlen (fname) + flen] = 0;
16391 }
16392 else
16393 fname[0] = 0;
16394
16395 strncat (fname, fbeg, flen);
16396 #ifdef VMS
16397 /* Change this 1/2 Unix 1/2 VMS file specification into a
16398 full VMS file specification */
16399 if (searchptr->fname && (searchptr->fname[0] != 0))
16400 {
16401 /* Fix up the filename */
16402 hack_vms_include_specification (fname);
16403 }
16404 else
16405 {
16406 /* This is a normal VMS filespec, so use it unchanged. */
16407 strncpy (fname, (char *) fbeg, flen);
16408 fname[flen] = 0;
16409 #if 0 /* Not for g77. */
16410 /* if it's '#include filename', add the missing .h */
16411 if (index (fname, '.') == NULL)
16412 strcat (fname, ".h");
16413 #endif
16414 }
16415 #endif /* VMS */
16416 f = open_include_file (fname, searchptr);
16417 #ifdef EACCES
16418 if (f == NULL && errno == EACCES)
16419 {
16420 print_containing_files (FFEBAD_severityWARNING);
16421 ffebad_start_msg ("At %0, INCLUDE file %A exists, but is not readable",
16422 FFEBAD_severityWARNING);
16423 ffebad_string (fname);
16424 ffebad_here (0, l, c);
16425 ffebad_finish ();
16426 }
16427 #endif
16428 if (f != NULL)
16429 break;
16430 }
16431 }
16432
16433 if (f == NULL)
16434 {
16435 /* A file that was not found. */
16436
16437 strncpy (fname, (char *) fbeg, flen);
16438 fname[flen] = 0;
16439 print_containing_files (ffebad_severity (FFEBAD_OPEN_INCLUDE));
16440 ffebad_start (FFEBAD_OPEN_INCLUDE);
16441 ffebad_here (0, l, c);
16442 ffebad_string (fname);
16443 ffebad_finish ();
16444 }
16445
16446 if (dsp[0].fname != NULL)
16447 free (dsp[0].fname);
16448
16449 if (f == NULL)
16450 return NULL;
16451
16452 if (indepth >= (INPUT_STACK_MAX - 1))
16453 {
16454 print_containing_files (FFEBAD_severityFATAL);
16455 ffebad_start_msg ("At %0, INCLUDE nesting too deep",
16456 FFEBAD_severityFATAL);
16457 ffebad_string (fname);
16458 ffebad_here (0, l, c);
16459 ffebad_finish ();
16460 return NULL;
16461 }
16462
16463 instack[indepth].line = ffewhere_line_use (l);
16464 instack[indepth].column = ffewhere_column_use (c);
16465
16466 fp = &instack[indepth + 1];
16467 memset ((char *) fp, 0, sizeof (FILE_BUF));
16468 fp->nominal_fname = fp->fname = fname;
16469 fp->dir = searchptr;
16470
16471 indepth++;
16472 input_file_stack_tick++;
16473
16474 return f;
16475 }
16476 #endif /* FFECOM_GCC_INCLUDE */
16477
16478 /**INDENT* (Do not reformat this comment even with -fca option.)
16479 Data-gathering files: Given the source file listed below, compiled with
16480 f2c I obtained the output file listed after that, and from the output
16481 file I derived the above code.
16482
16483 -------- (begin input file to f2c)
16484 implicit none
16485 character*10 A1,A2
16486 complex C1,C2
16487 integer I1,I2
16488 real R1,R2
16489 double precision D1,D2
16490 C
16491 call getem(A1,A2,C1,C2,I1,I2,R1,R2,D1,D2)
16492 c /
16493 call fooI(I1/I2)
16494 call fooR(R1/I1)
16495 call fooD(D1/I1)
16496 call fooC(C1/I1)
16497 call fooR(R1/R2)
16498 call fooD(R1/D1)
16499 call fooD(D1/D2)
16500 call fooD(D1/R1)
16501 call fooC(C1/C2)
16502 call fooC(C1/R1)
16503 call fooZ(C1/D1)
16504 c **
16505 call fooI(I1**I2)
16506 call fooR(R1**I1)
16507 call fooD(D1**I1)
16508 call fooC(C1**I1)
16509 call fooR(R1**R2)
16510 call fooD(R1**D1)
16511 call fooD(D1**D2)
16512 call fooD(D1**R1)
16513 call fooC(C1**C2)
16514 call fooC(C1**R1)
16515 call fooZ(C1**D1)
16516 c FFEINTRIN_impABS
16517 call fooR(ABS(R1))
16518 c FFEINTRIN_impACOS
16519 call fooR(ACOS(R1))
16520 c FFEINTRIN_impAIMAG
16521 call fooR(AIMAG(C1))
16522 c FFEINTRIN_impAINT
16523 call fooR(AINT(R1))
16524 c FFEINTRIN_impALOG
16525 call fooR(ALOG(R1))
16526 c FFEINTRIN_impALOG10
16527 call fooR(ALOG10(R1))
16528 c FFEINTRIN_impAMAX0
16529 call fooR(AMAX0(I1,I2))
16530 c FFEINTRIN_impAMAX1
16531 call fooR(AMAX1(R1,R2))
16532 c FFEINTRIN_impAMIN0
16533 call fooR(AMIN0(I1,I2))
16534 c FFEINTRIN_impAMIN1
16535 call fooR(AMIN1(R1,R2))
16536 c FFEINTRIN_impAMOD
16537 call fooR(AMOD(R1,R2))
16538 c FFEINTRIN_impANINT
16539 call fooR(ANINT(R1))
16540 c FFEINTRIN_impASIN
16541 call fooR(ASIN(R1))
16542 c FFEINTRIN_impATAN
16543 call fooR(ATAN(R1))
16544 c FFEINTRIN_impATAN2
16545 call fooR(ATAN2(R1,R2))
16546 c FFEINTRIN_impCABS
16547 call fooR(CABS(C1))
16548 c FFEINTRIN_impCCOS
16549 call fooC(CCOS(C1))
16550 c FFEINTRIN_impCEXP
16551 call fooC(CEXP(C1))
16552 c FFEINTRIN_impCHAR
16553 call fooA(CHAR(I1))
16554 c FFEINTRIN_impCLOG
16555 call fooC(CLOG(C1))
16556 c FFEINTRIN_impCONJG
16557 call fooC(CONJG(C1))
16558 c FFEINTRIN_impCOS
16559 call fooR(COS(R1))
16560 c FFEINTRIN_impCOSH
16561 call fooR(COSH(R1))
16562 c FFEINTRIN_impCSIN
16563 call fooC(CSIN(C1))
16564 c FFEINTRIN_impCSQRT
16565 call fooC(CSQRT(C1))
16566 c FFEINTRIN_impDABS
16567 call fooD(DABS(D1))
16568 c FFEINTRIN_impDACOS
16569 call fooD(DACOS(D1))
16570 c FFEINTRIN_impDASIN
16571 call fooD(DASIN(D1))
16572 c FFEINTRIN_impDATAN
16573 call fooD(DATAN(D1))
16574 c FFEINTRIN_impDATAN2
16575 call fooD(DATAN2(D1,D2))
16576 c FFEINTRIN_impDCOS
16577 call fooD(DCOS(D1))
16578 c FFEINTRIN_impDCOSH
16579 call fooD(DCOSH(D1))
16580 c FFEINTRIN_impDDIM
16581 call fooD(DDIM(D1,D2))
16582 c FFEINTRIN_impDEXP
16583 call fooD(DEXP(D1))
16584 c FFEINTRIN_impDIM
16585 call fooR(DIM(R1,R2))
16586 c FFEINTRIN_impDINT
16587 call fooD(DINT(D1))
16588 c FFEINTRIN_impDLOG
16589 call fooD(DLOG(D1))
16590 c FFEINTRIN_impDLOG10
16591 call fooD(DLOG10(D1))
16592 c FFEINTRIN_impDMAX1
16593 call fooD(DMAX1(D1,D2))
16594 c FFEINTRIN_impDMIN1
16595 call fooD(DMIN1(D1,D2))
16596 c FFEINTRIN_impDMOD
16597 call fooD(DMOD(D1,D2))
16598 c FFEINTRIN_impDNINT
16599 call fooD(DNINT(D1))
16600 c FFEINTRIN_impDPROD
16601 call fooD(DPROD(R1,R2))
16602 c FFEINTRIN_impDSIGN
16603 call fooD(DSIGN(D1,D2))
16604 c FFEINTRIN_impDSIN
16605 call fooD(DSIN(D1))
16606 c FFEINTRIN_impDSINH
16607 call fooD(DSINH(D1))
16608 c FFEINTRIN_impDSQRT
16609 call fooD(DSQRT(D1))
16610 c FFEINTRIN_impDTAN
16611 call fooD(DTAN(D1))
16612 c FFEINTRIN_impDTANH
16613 call fooD(DTANH(D1))
16614 c FFEINTRIN_impEXP
16615 call fooR(EXP(R1))
16616 c FFEINTRIN_impIABS
16617 call fooI(IABS(I1))
16618 c FFEINTRIN_impICHAR
16619 call fooI(ICHAR(A1))
16620 c FFEINTRIN_impIDIM
16621 call fooI(IDIM(I1,I2))
16622 c FFEINTRIN_impIDNINT
16623 call fooI(IDNINT(D1))
16624 c FFEINTRIN_impINDEX
16625 call fooI(INDEX(A1,A2))
16626 c FFEINTRIN_impISIGN
16627 call fooI(ISIGN(I1,I2))
16628 c FFEINTRIN_impLEN
16629 call fooI(LEN(A1))
16630 c FFEINTRIN_impLGE
16631 call fooL(LGE(A1,A2))
16632 c FFEINTRIN_impLGT
16633 call fooL(LGT(A1,A2))
16634 c FFEINTRIN_impLLE
16635 call fooL(LLE(A1,A2))
16636 c FFEINTRIN_impLLT
16637 call fooL(LLT(A1,A2))
16638 c FFEINTRIN_impMAX0
16639 call fooI(MAX0(I1,I2))
16640 c FFEINTRIN_impMAX1
16641 call fooI(MAX1(R1,R2))
16642 c FFEINTRIN_impMIN0
16643 call fooI(MIN0(I1,I2))
16644 c FFEINTRIN_impMIN1
16645 call fooI(MIN1(R1,R2))
16646 c FFEINTRIN_impMOD
16647 call fooI(MOD(I1,I2))
16648 c FFEINTRIN_impNINT
16649 call fooI(NINT(R1))
16650 c FFEINTRIN_impSIGN
16651 call fooR(SIGN(R1,R2))
16652 c FFEINTRIN_impSIN
16653 call fooR(SIN(R1))
16654 c FFEINTRIN_impSINH
16655 call fooR(SINH(R1))
16656 c FFEINTRIN_impSQRT
16657 call fooR(SQRT(R1))
16658 c FFEINTRIN_impTAN
16659 call fooR(TAN(R1))
16660 c FFEINTRIN_impTANH
16661 call fooR(TANH(R1))
16662 c FFEINTRIN_imp_CMPLX_C
16663 call fooC(cmplx(C1,C2))
16664 c FFEINTRIN_imp_CMPLX_D
16665 call fooZ(cmplx(D1,D2))
16666 c FFEINTRIN_imp_CMPLX_I
16667 call fooC(cmplx(I1,I2))
16668 c FFEINTRIN_imp_CMPLX_R
16669 call fooC(cmplx(R1,R2))
16670 c FFEINTRIN_imp_DBLE_C
16671 call fooD(dble(C1))
16672 c FFEINTRIN_imp_DBLE_D
16673 call fooD(dble(D1))
16674 c FFEINTRIN_imp_DBLE_I
16675 call fooD(dble(I1))
16676 c FFEINTRIN_imp_DBLE_R
16677 call fooD(dble(R1))
16678 c FFEINTRIN_imp_INT_C
16679 call fooI(int(C1))
16680 c FFEINTRIN_imp_INT_D
16681 call fooI(int(D1))
16682 c FFEINTRIN_imp_INT_I
16683 call fooI(int(I1))
16684 c FFEINTRIN_imp_INT_R
16685 call fooI(int(R1))
16686 c FFEINTRIN_imp_REAL_C
16687 call fooR(real(C1))
16688 c FFEINTRIN_imp_REAL_D
16689 call fooR(real(D1))
16690 c FFEINTRIN_imp_REAL_I
16691 call fooR(real(I1))
16692 c FFEINTRIN_imp_REAL_R
16693 call fooR(real(R1))
16694 c
16695 c FFEINTRIN_imp_INT_D:
16696 c
16697 c FFEINTRIN_specIDINT
16698 call fooI(IDINT(D1))
16699 c
16700 c FFEINTRIN_imp_INT_R:
16701 c
16702 c FFEINTRIN_specIFIX
16703 call fooI(IFIX(R1))
16704 c FFEINTRIN_specINT
16705 call fooI(INT(R1))
16706 c
16707 c FFEINTRIN_imp_REAL_D:
16708 c
16709 c FFEINTRIN_specSNGL
16710 call fooR(SNGL(D1))
16711 c
16712 c FFEINTRIN_imp_REAL_I:
16713 c
16714 c FFEINTRIN_specFLOAT
16715 call fooR(FLOAT(I1))
16716 c FFEINTRIN_specREAL
16717 call fooR(REAL(I1))
16718 c
16719 end
16720 -------- (end input file to f2c)
16721
16722 -------- (begin output from providing above input file as input to:
16723 -------- `f2c | gcc -E -C - | sed -e "s:/[*]*://:g" -e "s:[*]*[/]://:g" \
16724 -------- -e "s:^#.*$::g"')
16725
16726 // -- translated by f2c (version 19950223).
16727 You must link the resulting object file with the libraries:
16728 -lf2c -lm (in that order)
16729 //
16730
16731
16732 // f2c.h -- Standard Fortran to C header file //
16733
16734 /// barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed."
16735
16736 - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) //
16737
16738
16739
16740
16741 // F2C_INTEGER will normally be `int' but would be `long' on 16-bit systems //
16742 // we assume short, float are OK //
16743 typedef long int // long int // integer;
16744 typedef char *address;
16745 typedef short int shortint;
16746 typedef float real;
16747 typedef double doublereal;
16748 typedef struct { real r, i; } complex;
16749 typedef struct { doublereal r, i; } doublecomplex;
16750 typedef long int // long int // logical;
16751 typedef short int shortlogical;
16752 typedef char logical1;
16753 typedef char integer1;
16754 // typedef long long longint; // // system-dependent //
16755
16756
16757
16758
16759 // Extern is for use with -E //
16760
16761
16762
16763
16764 // I/O stuff //
16765
16766
16767
16768
16769
16770
16771
16772
16773 typedef long int // int or long int // flag;
16774 typedef long int // int or long int // ftnlen;
16775 typedef long int // int or long int // ftnint;
16776
16777
16778 //external read, write//
16779 typedef struct
16780 { flag cierr;
16781 ftnint ciunit;
16782 flag ciend;
16783 char *cifmt;
16784 ftnint cirec;
16785 } cilist;
16786
16787 //internal read, write//
16788 typedef struct
16789 { flag icierr;
16790 char *iciunit;
16791 flag iciend;
16792 char *icifmt;
16793 ftnint icirlen;
16794 ftnint icirnum;
16795 } icilist;
16796
16797 //open//
16798 typedef struct
16799 { flag oerr;
16800 ftnint ounit;
16801 char *ofnm;
16802 ftnlen ofnmlen;
16803 char *osta;
16804 char *oacc;
16805 char *ofm;
16806 ftnint orl;
16807 char *oblnk;
16808 } olist;
16809
16810 //close//
16811 typedef struct
16812 { flag cerr;
16813 ftnint cunit;
16814 char *csta;
16815 } cllist;
16816
16817 //rewind, backspace, endfile//
16818 typedef struct
16819 { flag aerr;
16820 ftnint aunit;
16821 } alist;
16822
16823 // inquire //
16824 typedef struct
16825 { flag inerr;
16826 ftnint inunit;
16827 char *infile;
16828 ftnlen infilen;
16829 ftnint *inex; //parameters in standard's order//
16830 ftnint *inopen;
16831 ftnint *innum;
16832 ftnint *innamed;
16833 char *inname;
16834 ftnlen innamlen;
16835 char *inacc;
16836 ftnlen inacclen;
16837 char *inseq;
16838 ftnlen inseqlen;
16839 char *indir;
16840 ftnlen indirlen;
16841 char *infmt;
16842 ftnlen infmtlen;
16843 char *inform;
16844 ftnint informlen;
16845 char *inunf;
16846 ftnlen inunflen;
16847 ftnint *inrecl;
16848 ftnint *innrec;
16849 char *inblank;
16850 ftnlen inblanklen;
16851 } inlist;
16852
16853
16854
16855 union Multitype { // for multiple entry points //
16856 integer1 g;
16857 shortint h;
16858 integer i;
16859 // longint j; //
16860 real r;
16861 doublereal d;
16862 complex c;
16863 doublecomplex z;
16864 };
16865
16866 typedef union Multitype Multitype;
16867
16868 typedef long Long; // No longer used; formerly in Namelist //
16869
16870 struct Vardesc { // for Namelist //
16871 char *name;
16872 char *addr;
16873 ftnlen *dims;
16874 int type;
16875 };
16876 typedef struct Vardesc Vardesc;
16877
16878 struct Namelist {
16879 char *name;
16880 Vardesc **vars;
16881 int nvars;
16882 };
16883 typedef struct Namelist Namelist;
16884
16885
16886
16887
16888
16889
16890
16891
16892 // procedure parameter types for -A and -C++ //
16893
16894
16895
16896
16897 typedef int // Unknown procedure type // (*U_fp)();
16898 typedef shortint (*J_fp)();
16899 typedef integer (*I_fp)();
16900 typedef real (*R_fp)();
16901 typedef doublereal (*D_fp)(), (*E_fp)();
16902 typedef // Complex // void (*C_fp)();
16903 typedef // Double Complex // void (*Z_fp)();
16904 typedef logical (*L_fp)();
16905 typedef shortlogical (*K_fp)();
16906 typedef // Character // void (*H_fp)();
16907 typedef // Subroutine // int (*S_fp)();
16908
16909 // E_fp is for real functions when -R is not specified //
16910 typedef void C_f; // complex function //
16911 typedef void H_f; // character function //
16912 typedef void Z_f; // double complex function //
16913 typedef doublereal E_f; // real function with -R not specified //
16914
16915 // undef any lower-case symbols that your C compiler predefines, e.g.: //
16916
16917
16918 // (No such symbols should be defined in a strict ANSI C compiler.
16919 We can avoid trouble with f2c-translated code by using
16920 gcc -ansi [-traditional].) //
16921
16922
16923
16924
16925
16926
16927
16928
16929
16930
16931
16932
16933
16934
16935
16936
16937
16938
16939
16940
16941
16942
16943
16944 // Main program // MAIN__()
16945 {
16946 // System generated locals //
16947 integer i__1;
16948 real r__1, r__2;
16949 doublereal d__1, d__2;
16950 complex q__1;
16951 doublecomplex z__1, z__2, z__3;
16952 logical L__1;
16953 char ch__1[1];
16954
16955 // Builtin functions //
16956 void c_div();
16957 integer pow_ii();
16958 double pow_ri(), pow_di();
16959 void pow_ci();
16960 double pow_dd();
16961 void pow_zz();
16962 double acos(), r_imag(), r_int(), log(), r_lg10(), r_mod(), r_nint(),
16963 asin(), atan(), atan2(), c_abs();
16964 void c_cos(), c_exp(), c_log(), r_cnjg();
16965 double cos(), cosh();
16966 void c_sin(), c_sqrt();
16967 double d_dim(), exp(), r_dim(), d_int(), d_lg10(), d_mod(), d_nint(),
16968 d_sign(), sin(), sinh(), sqrt(), tan(), tanh();
16969 integer i_dim(), i_dnnt(), i_indx(), i_sign(), i_len();
16970 logical l_ge(), l_gt(), l_le(), l_lt();
16971 integer i_nint();
16972 double r_sign();
16973
16974 // Local variables //
16975 extern // Subroutine // int fooa_(), fooc_(), food_(), fooi_(), foor_(),
16976 fool_(), fooz_(), getem_();
16977 static char a1[10], a2[10];
16978 static complex c1, c2;
16979 static doublereal d1, d2;
16980 static integer i1, i2;
16981 static real r1, r2;
16982
16983
16984 getem_(a1, a2, &c1, &c2, &i1, &i2, &r1, &r2, &d1, &d2, 10L, 10L);
16985 // / //
16986 i__1 = i1 / i2;
16987 fooi_(&i__1);
16988 r__1 = r1 / i1;
16989 foor_(&r__1);
16990 d__1 = d1 / i1;
16991 food_(&d__1);
16992 d__1 = (doublereal) i1;
16993 q__1.r = c1.r / d__1, q__1.i = c1.i / d__1;
16994 fooc_(&q__1);
16995 r__1 = r1 / r2;
16996 foor_(&r__1);
16997 d__1 = r1 / d1;
16998 food_(&d__1);
16999 d__1 = d1 / d2;
17000 food_(&d__1);
17001 d__1 = d1 / r1;
17002 food_(&d__1);
17003 c_div(&q__1, &c1, &c2);
17004 fooc_(&q__1);
17005 q__1.r = c1.r / r1, q__1.i = c1.i / r1;
17006 fooc_(&q__1);
17007 z__1.r = c1.r / d1, z__1.i = c1.i / d1;
17008 fooz_(&z__1);
17009 // ** //
17010 i__1 = pow_ii(&i1, &i2);
17011 fooi_(&i__1);
17012 r__1 = pow_ri(&r1, &i1);
17013 foor_(&r__1);
17014 d__1 = pow_di(&d1, &i1);
17015 food_(&d__1);
17016 pow_ci(&q__1, &c1, &i1);
17017 fooc_(&q__1);
17018 d__1 = (doublereal) r1;
17019 d__2 = (doublereal) r2;
17020 r__1 = pow_dd(&d__1, &d__2);
17021 foor_(&r__1);
17022 d__2 = (doublereal) r1;
17023 d__1 = pow_dd(&d__2, &d1);
17024 food_(&d__1);
17025 d__1 = pow_dd(&d1, &d2);
17026 food_(&d__1);
17027 d__2 = (doublereal) r1;
17028 d__1 = pow_dd(&d1, &d__2);
17029 food_(&d__1);
17030 z__2.r = c1.r, z__2.i = c1.i;
17031 z__3.r = c2.r, z__3.i = c2.i;
17032 pow_zz(&z__1, &z__2, &z__3);
17033 q__1.r = z__1.r, q__1.i = z__1.i;
17034 fooc_(&q__1);
17035 z__2.r = c1.r, z__2.i = c1.i;
17036 z__3.r = r1, z__3.i = 0.;
17037 pow_zz(&z__1, &z__2, &z__3);
17038 q__1.r = z__1.r, q__1.i = z__1.i;
17039 fooc_(&q__1);
17040 z__2.r = c1.r, z__2.i = c1.i;
17041 z__3.r = d1, z__3.i = 0.;
17042 pow_zz(&z__1, &z__2, &z__3);
17043 fooz_(&z__1);
17044 // FFEINTRIN_impABS //
17045 r__1 = (doublereal)(( r1 ) >= 0 ? ( r1 ) : -( r1 )) ;
17046 foor_(&r__1);
17047 // FFEINTRIN_impACOS //
17048 r__1 = acos(r1);
17049 foor_(&r__1);
17050 // FFEINTRIN_impAIMAG //
17051 r__1 = r_imag(&c1);
17052 foor_(&r__1);
17053 // FFEINTRIN_impAINT //
17054 r__1 = r_int(&r1);
17055 foor_(&r__1);
17056 // FFEINTRIN_impALOG //
17057 r__1 = log(r1);
17058 foor_(&r__1);
17059 // FFEINTRIN_impALOG10 //
17060 r__1 = r_lg10(&r1);
17061 foor_(&r__1);
17062 // FFEINTRIN_impAMAX0 //
17063 r__1 = (real) (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
17064 foor_(&r__1);
17065 // FFEINTRIN_impAMAX1 //
17066 r__1 = (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
17067 foor_(&r__1);
17068 // FFEINTRIN_impAMIN0 //
17069 r__1 = (real) (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
17070 foor_(&r__1);
17071 // FFEINTRIN_impAMIN1 //
17072 r__1 = (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
17073 foor_(&r__1);
17074 // FFEINTRIN_impAMOD //
17075 r__1 = r_mod(&r1, &r2);
17076 foor_(&r__1);
17077 // FFEINTRIN_impANINT //
17078 r__1 = r_nint(&r1);
17079 foor_(&r__1);
17080 // FFEINTRIN_impASIN //
17081 r__1 = asin(r1);
17082 foor_(&r__1);
17083 // FFEINTRIN_impATAN //
17084 r__1 = atan(r1);
17085 foor_(&r__1);
17086 // FFEINTRIN_impATAN2 //
17087 r__1 = atan2(r1, r2);
17088 foor_(&r__1);
17089 // FFEINTRIN_impCABS //
17090 r__1 = c_abs(&c1);
17091 foor_(&r__1);
17092 // FFEINTRIN_impCCOS //
17093 c_cos(&q__1, &c1);
17094 fooc_(&q__1);
17095 // FFEINTRIN_impCEXP //
17096 c_exp(&q__1, &c1);
17097 fooc_(&q__1);
17098 // FFEINTRIN_impCHAR //
17099 *(unsigned char *)&ch__1[0] = i1;
17100 fooa_(ch__1, 1L);
17101 // FFEINTRIN_impCLOG //
17102 c_log(&q__1, &c1);
17103 fooc_(&q__1);
17104 // FFEINTRIN_impCONJG //
17105 r_cnjg(&q__1, &c1);
17106 fooc_(&q__1);
17107 // FFEINTRIN_impCOS //
17108 r__1 = cos(r1);
17109 foor_(&r__1);
17110 // FFEINTRIN_impCOSH //
17111 r__1 = cosh(r1);
17112 foor_(&r__1);
17113 // FFEINTRIN_impCSIN //
17114 c_sin(&q__1, &c1);
17115 fooc_(&q__1);
17116 // FFEINTRIN_impCSQRT //
17117 c_sqrt(&q__1, &c1);
17118 fooc_(&q__1);
17119 // FFEINTRIN_impDABS //
17120 d__1 = (( d1 ) >= 0 ? ( d1 ) : -( d1 )) ;
17121 food_(&d__1);
17122 // FFEINTRIN_impDACOS //
17123 d__1 = acos(d1);
17124 food_(&d__1);
17125 // FFEINTRIN_impDASIN //
17126 d__1 = asin(d1);
17127 food_(&d__1);
17128 // FFEINTRIN_impDATAN //
17129 d__1 = atan(d1);
17130 food_(&d__1);
17131 // FFEINTRIN_impDATAN2 //
17132 d__1 = atan2(d1, d2);
17133 food_(&d__1);
17134 // FFEINTRIN_impDCOS //
17135 d__1 = cos(d1);
17136 food_(&d__1);
17137 // FFEINTRIN_impDCOSH //
17138 d__1 = cosh(d1);
17139 food_(&d__1);
17140 // FFEINTRIN_impDDIM //
17141 d__1 = d_dim(&d1, &d2);
17142 food_(&d__1);
17143 // FFEINTRIN_impDEXP //
17144 d__1 = exp(d1);
17145 food_(&d__1);
17146 // FFEINTRIN_impDIM //
17147 r__1 = r_dim(&r1, &r2);
17148 foor_(&r__1);
17149 // FFEINTRIN_impDINT //
17150 d__1 = d_int(&d1);
17151 food_(&d__1);
17152 // FFEINTRIN_impDLOG //
17153 d__1 = log(d1);
17154 food_(&d__1);
17155 // FFEINTRIN_impDLOG10 //
17156 d__1 = d_lg10(&d1);
17157 food_(&d__1);
17158 // FFEINTRIN_impDMAX1 //
17159 d__1 = (( d1 ) >= ( d2 ) ? ( d1 ) : ( d2 )) ;
17160 food_(&d__1);
17161 // FFEINTRIN_impDMIN1 //
17162 d__1 = (( d1 ) <= ( d2 ) ? ( d1 ) : ( d2 )) ;
17163 food_(&d__1);
17164 // FFEINTRIN_impDMOD //
17165 d__1 = d_mod(&d1, &d2);
17166 food_(&d__1);
17167 // FFEINTRIN_impDNINT //
17168 d__1 = d_nint(&d1);
17169 food_(&d__1);
17170 // FFEINTRIN_impDPROD //
17171 d__1 = (doublereal) r1 * r2;
17172 food_(&d__1);
17173 // FFEINTRIN_impDSIGN //
17174 d__1 = d_sign(&d1, &d2);
17175 food_(&d__1);
17176 // FFEINTRIN_impDSIN //
17177 d__1 = sin(d1);
17178 food_(&d__1);
17179 // FFEINTRIN_impDSINH //
17180 d__1 = sinh(d1);
17181 food_(&d__1);
17182 // FFEINTRIN_impDSQRT //
17183 d__1 = sqrt(d1);
17184 food_(&d__1);
17185 // FFEINTRIN_impDTAN //
17186 d__1 = tan(d1);
17187 food_(&d__1);
17188 // FFEINTRIN_impDTANH //
17189 d__1 = tanh(d1);
17190 food_(&d__1);
17191 // FFEINTRIN_impEXP //
17192 r__1 = exp(r1);
17193 foor_(&r__1);
17194 // FFEINTRIN_impIABS //
17195 i__1 = (( i1 ) >= 0 ? ( i1 ) : -( i1 )) ;
17196 fooi_(&i__1);
17197 // FFEINTRIN_impICHAR //
17198 i__1 = *(unsigned char *)a1;
17199 fooi_(&i__1);
17200 // FFEINTRIN_impIDIM //
17201 i__1 = i_dim(&i1, &i2);
17202 fooi_(&i__1);
17203 // FFEINTRIN_impIDNINT //
17204 i__1 = i_dnnt(&d1);
17205 fooi_(&i__1);
17206 // FFEINTRIN_impINDEX //
17207 i__1 = i_indx(a1, a2, 10L, 10L);
17208 fooi_(&i__1);
17209 // FFEINTRIN_impISIGN //
17210 i__1 = i_sign(&i1, &i2);
17211 fooi_(&i__1);
17212 // FFEINTRIN_impLEN //
17213 i__1 = i_len(a1, 10L);
17214 fooi_(&i__1);
17215 // FFEINTRIN_impLGE //
17216 L__1 = l_ge(a1, a2, 10L, 10L);
17217 fool_(&L__1);
17218 // FFEINTRIN_impLGT //
17219 L__1 = l_gt(a1, a2, 10L, 10L);
17220 fool_(&L__1);
17221 // FFEINTRIN_impLLE //
17222 L__1 = l_le(a1, a2, 10L, 10L);
17223 fool_(&L__1);
17224 // FFEINTRIN_impLLT //
17225 L__1 = l_lt(a1, a2, 10L, 10L);
17226 fool_(&L__1);
17227 // FFEINTRIN_impMAX0 //
17228 i__1 = (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
17229 fooi_(&i__1);
17230 // FFEINTRIN_impMAX1 //
17231 i__1 = (integer) (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
17232 fooi_(&i__1);
17233 // FFEINTRIN_impMIN0 //
17234 i__1 = (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
17235 fooi_(&i__1);
17236 // FFEINTRIN_impMIN1 //
17237 i__1 = (integer) (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
17238 fooi_(&i__1);
17239 // FFEINTRIN_impMOD //
17240 i__1 = i1 % i2;
17241 fooi_(&i__1);
17242 // FFEINTRIN_impNINT //
17243 i__1 = i_nint(&r1);
17244 fooi_(&i__1);
17245 // FFEINTRIN_impSIGN //
17246 r__1 = r_sign(&r1, &r2);
17247 foor_(&r__1);
17248 // FFEINTRIN_impSIN //
17249 r__1 = sin(r1);
17250 foor_(&r__1);
17251 // FFEINTRIN_impSINH //
17252 r__1 = sinh(r1);
17253 foor_(&r__1);
17254 // FFEINTRIN_impSQRT //
17255 r__1 = sqrt(r1);
17256 foor_(&r__1);
17257 // FFEINTRIN_impTAN //
17258 r__1 = tan(r1);
17259 foor_(&r__1);
17260 // FFEINTRIN_impTANH //
17261 r__1 = tanh(r1);
17262 foor_(&r__1);
17263 // FFEINTRIN_imp_CMPLX_C //
17264 r__1 = c1.r;
17265 r__2 = c2.r;
17266 q__1.r = r__1, q__1.i = r__2;
17267 fooc_(&q__1);
17268 // FFEINTRIN_imp_CMPLX_D //
17269 z__1.r = d1, z__1.i = d2;
17270 fooz_(&z__1);
17271 // FFEINTRIN_imp_CMPLX_I //
17272 r__1 = (real) i1;
17273 r__2 = (real) i2;
17274 q__1.r = r__1, q__1.i = r__2;
17275 fooc_(&q__1);
17276 // FFEINTRIN_imp_CMPLX_R //
17277 q__1.r = r1, q__1.i = r2;
17278 fooc_(&q__1);
17279 // FFEINTRIN_imp_DBLE_C //
17280 d__1 = (doublereal) c1.r;
17281 food_(&d__1);
17282 // FFEINTRIN_imp_DBLE_D //
17283 d__1 = d1;
17284 food_(&d__1);
17285 // FFEINTRIN_imp_DBLE_I //
17286 d__1 = (doublereal) i1;
17287 food_(&d__1);
17288 // FFEINTRIN_imp_DBLE_R //
17289 d__1 = (doublereal) r1;
17290 food_(&d__1);
17291 // FFEINTRIN_imp_INT_C //
17292 i__1 = (integer) c1.r;
17293 fooi_(&i__1);
17294 // FFEINTRIN_imp_INT_D //
17295 i__1 = (integer) d1;
17296 fooi_(&i__1);
17297 // FFEINTRIN_imp_INT_I //
17298 i__1 = i1;
17299 fooi_(&i__1);
17300 // FFEINTRIN_imp_INT_R //
17301 i__1 = (integer) r1;
17302 fooi_(&i__1);
17303 // FFEINTRIN_imp_REAL_C //
17304 r__1 = c1.r;
17305 foor_(&r__1);
17306 // FFEINTRIN_imp_REAL_D //
17307 r__1 = (real) d1;
17308 foor_(&r__1);
17309 // FFEINTRIN_imp_REAL_I //
17310 r__1 = (real) i1;
17311 foor_(&r__1);
17312 // FFEINTRIN_imp_REAL_R //
17313 r__1 = r1;
17314 foor_(&r__1);
17315
17316 // FFEINTRIN_imp_INT_D: //
17317
17318 // FFEINTRIN_specIDINT //
17319 i__1 = (integer) d1;
17320 fooi_(&i__1);
17321
17322 // FFEINTRIN_imp_INT_R: //
17323
17324 // FFEINTRIN_specIFIX //
17325 i__1 = (integer) r1;
17326 fooi_(&i__1);
17327 // FFEINTRIN_specINT //
17328 i__1 = (integer) r1;
17329 fooi_(&i__1);
17330
17331 // FFEINTRIN_imp_REAL_D: //
17332
17333 // FFEINTRIN_specSNGL //
17334 r__1 = (real) d1;
17335 foor_(&r__1);
17336
17337 // FFEINTRIN_imp_REAL_I: //
17338
17339 // FFEINTRIN_specFLOAT //
17340 r__1 = (real) i1;
17341 foor_(&r__1);
17342 // FFEINTRIN_specREAL //
17343 r__1 = (real) i1;
17344 foor_(&r__1);
17345
17346 } // MAIN__ //
17347
17348 -------- (end output file from f2c)
17349
17350 */