Another bunch of patches from Craig. See ChangeLogs for details.
[gcc.git] / gcc / f / com.c
1 /* com.c -- Implementation File (module.c template V1.0)
2 Copyright (C) 1995-1997 Free Software Foundation, Inc.
3 Contributed by James Craig Burley (burley@gnu.ai.mit.edu).
4
5 This file is part of GNU Fortran.
6
7 GNU Fortran is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU Fortran is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Fortran; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.
21
22 Related Modules:
23 None
24
25 Description:
26 Contains compiler-specific functions.
27
28 Modifications:
29 */
30
31 /* Understanding this module means understanding the interface between
32 the g77 front end and the gcc back end (or, perhaps, some other
33 back end). In here are the functions called by the front end proper
34 to notify whatever back end is in place about certain things, and
35 also the back-end-specific functions. It's a bear to deal with, so
36 lately I've been trying to simplify things, especially with regard
37 to the gcc-back-end-specific stuff.
38
39 Building expressions generally seems quite easy, but building decls
40 has been challenging and is undergoing revision. gcc has several
41 kinds of decls:
42
43 TYPE_DECL -- a type (int, float, struct, function, etc.)
44 CONST_DECL -- a constant of some type other than function
45 LABEL_DECL -- a variable or a constant?
46 PARM_DECL -- an argument to a function (a variable that is a dummy)
47 RESULT_DECL -- the return value of a function (a variable)
48 VAR_DECL -- other variable (can hold a ptr-to-function, struct, int, etc.)
49 FUNCTION_DECL -- a function (either the actual function or an extern ref)
50 FIELD_DECL -- a field in a struct or union (goes into types)
51
52 g77 has a set of functions that somewhat parallels the gcc front end
53 when it comes to building decls:
54
55 Internal Function (one we define, not just declare as extern):
56 int yes;
57 yes = suspend_momentary ();
58 if (is_nested) push_f_function_context ();
59 start_function (get_identifier ("function_name"), function_type,
60 is_nested, is_public);
61 // for each arg, build PARM_DECL and call push_parm_decl (decl) with it;
62 store_parm_decls (is_main_program);
63 ffecom_start_compstmt_ ();
64 // for stmts and decls inside function, do appropriate things;
65 ffecom_end_compstmt_ ();
66 finish_function (is_nested);
67 if (is_nested) pop_f_function_context ();
68 if (is_nested) resume_momentary (yes);
69
70 Everything Else:
71 int yes;
72 tree d;
73 tree init;
74 yes = suspend_momentary ();
75 // fill in external, public, static, &c for decl, and
76 // set DECL_INITIAL to error_mark_node if going to initialize
77 // set is_top_level TRUE only if not at top level and decl
78 // must go in top level (i.e. not within current function decl context)
79 d = start_decl (decl, is_top_level);
80 init = ...; // if have initializer
81 finish_decl (d, init, is_top_level);
82 resume_momentary (yes);
83
84 */
85
86 /* Include files. */
87
88 #if FFECOM_targetCURRENT == FFECOM_targetGCC
89 #include "config.j"
90 #include "flags.j"
91 #include "rtl.j"
92 #include "tree.j"
93 #include "convert.j"
94 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
95
96 #define FFECOM_GCC_INCLUDE 1 /* Enable -I. */
97
98 /* BEGIN stuff from gcc/cccp.c. */
99
100 /* The following symbols should be autoconfigured:
101 HAVE_FCNTL_H
102 HAVE_STDLIB_H
103 HAVE_SYS_TIME_H
104 HAVE_UNISTD_H
105 STDC_HEADERS
106 TIME_WITH_SYS_TIME
107 In the mean time, we'll get by with approximations based
108 on existing GCC configuration symbols. */
109
110 #ifdef POSIX
111 # ifndef HAVE_STDLIB_H
112 # define HAVE_STDLIB_H 1
113 # endif
114 # ifndef HAVE_UNISTD_H
115 # define HAVE_UNISTD_H 1
116 # endif
117 # ifndef STDC_HEADERS
118 # define STDC_HEADERS 1
119 # endif
120 #endif /* defined (POSIX) */
121
122 #if defined (POSIX) || (defined (USG) && !defined (VMS))
123 # ifndef HAVE_FCNTL_H
124 # define HAVE_FCNTL_H 1
125 # endif
126 #endif
127
128 #ifndef RLIMIT_STACK
129 # include <time.h>
130 #else
131 # if TIME_WITH_SYS_TIME
132 # include <sys/time.h>
133 # include <time.h>
134 # else
135 # if HAVE_SYS_TIME_H
136 # include <sys/time.h>
137 # else
138 # include <time.h>
139 # endif
140 # endif
141 # include <sys/resource.h>
142 #endif
143
144 #if HAVE_FCNTL_H
145 # include <fcntl.h>
146 #endif
147
148 /* This defines "errno" properly for VMS, and gives us EACCES. */
149 #include <errno.h>
150
151 #if HAVE_STDLIB_H
152 # include <stdlib.h>
153 #else
154 char *getenv ();
155 #endif
156
157 char *index ();
158 char *rindex ();
159
160 #if HAVE_UNISTD_H
161 # include <unistd.h>
162 #endif
163
164 /* VMS-specific definitions */
165 #ifdef VMS
166 #include <descrip.h>
167 #define O_RDONLY 0 /* Open arg for Read/Only */
168 #define O_WRONLY 1 /* Open arg for Write/Only */
169 #define read(fd,buf,size) VMS_read (fd,buf,size)
170 #define write(fd,buf,size) VMS_write (fd,buf,size)
171 #define open(fname,mode,prot) VMS_open (fname,mode,prot)
172 #define fopen(fname,mode) VMS_fopen (fname,mode)
173 #define freopen(fname,mode,ofile) VMS_freopen (fname,mode,ofile)
174 #define strncat(dst,src,cnt) VMS_strncat (dst,src,cnt)
175 #define fstat(fd,stbuf) VMS_fstat (fd,stbuf)
176 static int VMS_fstat (), VMS_stat ();
177 static char * VMS_strncat ();
178 static int VMS_read ();
179 static int VMS_write ();
180 static int VMS_open ();
181 static FILE * VMS_fopen ();
182 static FILE * VMS_freopen ();
183 static void hack_vms_include_specification ();
184 typedef struct { unsigned :16, :16, :16; } vms_ino_t;
185 #define ino_t vms_ino_t
186 #define INCLUDE_LEN_FUDGE 10 /* leave room for VMS syntax conversion */
187 #ifdef __GNUC__
188 #define BSTRING /* VMS/GCC supplies the bstring routines */
189 #endif /* __GNUC__ */
190 #endif /* VMS */
191
192 #ifndef O_RDONLY
193 #define O_RDONLY 0
194 #endif
195
196 /* END stuff from gcc/cccp.c. */
197
198 #include "proj.h"
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 #define FFECOM_FASTER_ARRAY_REFS 0 /* Generates faster code? */
219
220 #if FFECOM_targetCURRENT == FFECOM_targetGCC
221
222 /* tree.h declares a bunch of stuff that it expects the front end to
223 define. Here are the definitions, which in the C front end are
224 found in the file c-decl.c. */
225
226 tree integer_zero_node;
227 tree integer_one_node;
228 tree null_pointer_node;
229 tree error_mark_node;
230 tree void_type_node;
231 tree integer_type_node;
232 tree unsigned_type_node;
233 tree char_type_node;
234 tree current_function_decl;
235
236 /* ~~tree.h SHOULD declare this, because toplev.c and dwarfout.c reference
237 it. */
238
239 char *language_string = "GNU F77";
240
241 /* These definitions parallel those in c-decl.c so that code from that
242 module can be used pretty much as is. Much of these defs aren't
243 otherwise used, i.e. by g77 code per se, except some of them are used
244 to build some of them that are. The ones that are global (i.e. not
245 "static") are those that ste.c and such might use (directly
246 or by using com macros that reference them in their definitions). */
247
248 static tree short_integer_type_node;
249 tree long_integer_type_node;
250 static tree long_long_integer_type_node;
251
252 static tree short_unsigned_type_node;
253 static tree long_unsigned_type_node;
254 static tree long_long_unsigned_type_node;
255
256 static tree unsigned_char_type_node;
257 static tree signed_char_type_node;
258
259 static tree float_type_node;
260 static tree double_type_node;
261 static tree complex_float_type_node;
262 tree complex_double_type_node;
263 static tree long_double_type_node;
264 static tree complex_integer_type_node;
265 static tree complex_long_double_type_node;
266
267 tree string_type_node;
268
269 static tree double_ftype_double;
270 static tree float_ftype_float;
271 static tree ldouble_ftype_ldouble;
272
273 /* The rest of these are inventions for g77, though there might be
274 similar things in the C front end. As they are found, these
275 inventions should be renamed to be canonical. Note that only
276 the ones currently required to be global are so. */
277
278 static tree ffecom_tree_fun_type_void;
279 static tree ffecom_tree_ptr_to_fun_type_void;
280
281 tree ffecom_integer_type_node; /* Abbrev for _tree_type[blah][blah]. */
282 tree ffecom_integer_zero_node; /* Like *_*_* with g77's integer type. */
283 tree ffecom_integer_one_node; /* " */
284 tree ffecom_tree_type[FFEINFO_basictype][FFEINFO_kindtype];
285
286 /* _fun_type things are the f2c-specific versions. For -fno-f2c,
287 just use build_function_type and build_pointer_type on the
288 appropriate _tree_type array element. */
289
290 static tree ffecom_tree_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
291 static tree ffecom_tree_ptr_to_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
292 static tree ffecom_tree_subr_type;
293 static tree ffecom_tree_ptr_to_subr_type;
294 static tree ffecom_tree_blockdata_type;
295
296 static tree ffecom_tree_xargc_;
297
298 ffecomSymbol ffecom_symbol_null_
299 =
300 {
301 NULL_TREE,
302 NULL_TREE,
303 NULL_TREE,
304 };
305 ffeinfoKindtype ffecom_pointer_kind_ = FFEINFO_basictypeNONE;
306 ffeinfoKindtype ffecom_label_kind_ = FFEINFO_basictypeNONE;
307
308 int ffecom_f2c_typecode_[FFEINFO_basictype][FFEINFO_kindtype];
309 tree ffecom_f2c_integer_type_node;
310 tree ffecom_f2c_ptr_to_integer_type_node;
311 tree ffecom_f2c_address_type_node;
312 tree ffecom_f2c_real_type_node;
313 tree ffecom_f2c_ptr_to_real_type_node;
314 tree ffecom_f2c_doublereal_type_node;
315 tree ffecom_f2c_complex_type_node;
316 tree ffecom_f2c_doublecomplex_type_node;
317 tree ffecom_f2c_longint_type_node;
318 tree ffecom_f2c_logical_type_node;
319 tree ffecom_f2c_flag_type_node;
320 tree ffecom_f2c_ftnlen_type_node;
321 tree ffecom_f2c_ftnlen_zero_node;
322 tree ffecom_f2c_ftnlen_one_node;
323 tree ffecom_f2c_ftnlen_two_node;
324 tree ffecom_f2c_ptr_to_ftnlen_type_node;
325 tree ffecom_f2c_ftnint_type_node;
326 tree ffecom_f2c_ptr_to_ftnint_type_node;
327 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
328
329 /* Simple definitions and enumerations. */
330
331 #ifndef FFECOM_sizeMAXSTACKITEM
332 #define FFECOM_sizeMAXSTACKITEM 32*1024 /* Keep user-declared things
333 larger than this # bytes
334 off stack if possible. */
335 #endif
336
337 /* For systems that have large enough stacks, they should define
338 this to 0, and here, for ease of use later on, we just undefine
339 it if it is 0. */
340
341 #if FFECOM_sizeMAXSTACKITEM == 0
342 #undef FFECOM_sizeMAXSTACKITEM
343 #endif
344
345 typedef enum
346 {
347 FFECOM_rttypeVOID_,
348 FFECOM_rttypeVOIDSTAR_, /* C's `void *' type. */
349 FFECOM_rttypeFTNINT_, /* f2c's `ftnint' type. */
350 FFECOM_rttypeINTEGER_, /* f2c's `integer' type. */
351 FFECOM_rttypeLONGINT_, /* f2c's `longint' type. */
352 FFECOM_rttypeLOGICAL_, /* f2c's `logical' type. */
353 FFECOM_rttypeREAL_F2C_, /* f2c's `real' returned as `double'. */
354 FFECOM_rttypeREAL_GNU_, /* `real' returned as such. */
355 FFECOM_rttypeCOMPLEX_F2C_, /* f2c's `complex' returned via 1st arg. */
356 FFECOM_rttypeCOMPLEX_GNU_, /* f2c's `complex' returned directly. */
357 FFECOM_rttypeDOUBLE_, /* C's `double' type. */
358 FFECOM_rttypeDOUBLEREAL_, /* f2c's `doublereal' type. */
359 FFECOM_rttypeDBLCMPLX_F2C_, /* f2c's `doublecomplex' returned via 1st arg. */
360 FFECOM_rttypeDBLCMPLX_GNU_, /* f2c's `doublecomplex' returned directly. */
361 FFECOM_rttypeCHARACTER_, /* f2c `char *'/`ftnlen' pair. */
362 FFECOM_rttype_
363 } ffecomRttype_;
364
365 /* Internal typedefs. */
366
367 #if FFECOM_targetCURRENT == FFECOM_targetGCC
368 typedef struct _ffecom_concat_list_ ffecomConcatList_;
369 typedef struct _ffecom_temp_ *ffecomTemp_;
370 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
371
372 /* Private include files. */
373
374
375 /* Internal structure definitions. */
376
377 #if FFECOM_targetCURRENT == FFECOM_targetGCC
378 struct _ffecom_concat_list_
379 {
380 ffebld *exprs;
381 int count;
382 int max;
383 ffetargetCharacterSize minlen;
384 ffetargetCharacterSize maxlen;
385 };
386
387 struct _ffecom_temp_
388 {
389 ffecomTemp_ next;
390 tree type; /* Base type (w/o size/array applied). */
391 tree t;
392 ffetargetCharacterSize size;
393 int elements;
394 bool in_use;
395 bool auto_pop;
396 };
397
398 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
399
400 /* Static functions (internal). */
401
402 #if FFECOM_targetCURRENT == FFECOM_targetGCC
403 static tree ffecom_arglist_expr_ (char *argstring, ffebld args);
404 static tree ffecom_widest_expr_type_ (ffebld list);
405 static bool ffecom_overlap_ (tree dest_decl, tree dest_offset,
406 tree dest_size, tree source_tree,
407 ffebld source, bool scalar_arg);
408 static bool ffecom_args_overlapping_ (tree dest_tree, ffebld dest,
409 tree args, tree callee_commons,
410 bool scalar_args);
411 static tree ffecom_build_f2c_string_ (int i, char *s);
412 static tree ffecom_call_ (tree fn, ffeinfoKindtype kt,
413 bool is_f2c_complex, tree type,
414 tree args, tree dest_tree,
415 ffebld dest, bool *dest_used,
416 tree callee_commons, bool scalar_args);
417 static tree ffecom_call_binop_ (tree fn, ffeinfoKindtype kt,
418 bool is_f2c_complex, tree type,
419 ffebld left, ffebld right,
420 tree dest_tree, ffebld dest,
421 bool *dest_used, tree callee_commons,
422 bool scalar_args);
423 static void ffecom_char_args_x_ (tree *xitem, tree *length,
424 ffebld expr, bool with_null);
425 static tree ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy);
426 static tree ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s);
427 static ffecomConcatList_
428 ffecom_concat_list_gather_ (ffecomConcatList_ catlist,
429 ffebld expr,
430 ffetargetCharacterSize max);
431 static void ffecom_concat_list_kill_ (ffecomConcatList_ catlist);
432 static ffecomConcatList_ ffecom_concat_list_new_ (ffebld expr,
433 ffetargetCharacterSize max);
434 static void ffecom_debug_kludge_ (tree aggr, char *aggr_type, ffesymbol member,
435 tree member_type, ffetargetOffset offset);
436 static void ffecom_do_entry_ (ffesymbol fn, int entrynum);
437 static tree ffecom_expr_ (ffebld expr, tree type_tree, tree dest_tree,
438 ffebld dest, bool *dest_used,
439 bool assignp);
440 static tree ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
441 ffebld dest, bool *dest_used);
442 static tree ffecom_expr_power_integer_ (ffebld left, ffebld right);
443 static void ffecom_expr_transform_ (ffebld expr);
444 static void ffecom_f2c_make_type_ (tree *type, int tcode, char *name);
445 static void ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
446 int code);
447 static ffeglobal ffecom_finish_global_ (ffeglobal global);
448 static ffesymbol ffecom_finish_symbol_transform_ (ffesymbol s);
449 static tree ffecom_get_appended_identifier_ (char us, char *text);
450 static tree ffecom_get_external_identifier_ (ffesymbol s);
451 static tree ffecom_get_identifier_ (char *text);
452 static tree ffecom_gen_sfuncdef_ (ffesymbol s,
453 ffeinfoBasictype bt,
454 ffeinfoKindtype kt);
455 static char *ffecom_gfrt_args_ (ffecomGfrt ix);
456 static tree ffecom_gfrt_tree_ (ffecomGfrt ix);
457 static tree ffecom_init_zero_ (tree decl);
458 static tree ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
459 tree *maybe_tree);
460 static tree ffecom_intrinsic_len_ (ffebld expr);
461 static void ffecom_let_char_ (tree dest_tree,
462 tree dest_length,
463 ffetargetCharacterSize dest_size,
464 ffebld source);
465 static void ffecom_make_gfrt_ (ffecomGfrt ix);
466 static void ffecom_member_phase1_ (ffestorag mst, ffestorag st);
467 #ifdef SOMEONE_GETS_DEBUG_SUPPORT_WORKING
468 static void ffecom_member_phase2_ (ffestorag mst, ffestorag st);
469 #endif
470 static void ffecom_push_dummy_decls_ (ffebld dumlist,
471 bool stmtfunc);
472 static void ffecom_start_progunit_ (void);
473 static ffesymbol ffecom_sym_transform_ (ffesymbol s);
474 static ffesymbol ffecom_sym_transform_assign_ (ffesymbol s);
475 static void ffecom_transform_common_ (ffesymbol s);
476 static void ffecom_transform_equiv_ (ffestorag st);
477 static tree ffecom_transform_namelist_ (ffesymbol s);
478 static void ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
479 tree t);
480 static void ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
481 tree *size, tree tree);
482 static tree ffecom_tree_divide_ (tree tree_type, tree left, tree right,
483 tree dest_tree, ffebld dest,
484 bool *dest_used);
485 static tree ffecom_type_localvar_ (ffesymbol s,
486 ffeinfoBasictype bt,
487 ffeinfoKindtype kt);
488 static tree ffecom_type_namelist_ (void);
489 #if 0
490 static tree ffecom_type_permanent_copy_ (tree t);
491 #endif
492 static tree ffecom_type_vardesc_ (void);
493 static tree ffecom_vardesc_ (ffebld expr);
494 static tree ffecom_vardesc_array_ (ffesymbol s);
495 static tree ffecom_vardesc_dims_ (ffesymbol s);
496 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
497
498 /* These are static functions that parallel those found in the C front
499 end and thus have the same names. */
500
501 #if FFECOM_targetCURRENT == FFECOM_targetGCC
502 static void bison_rule_compstmt_ (void);
503 static void bison_rule_pushlevel_ (void);
504 static tree builtin_function (char *name, tree type,
505 enum built_in_function function_code,
506 char *library_name);
507 static int duplicate_decls (tree newdecl, tree olddecl);
508 static void finish_decl (tree decl, tree init, bool is_top_level);
509 static void finish_function (int nested);
510 static char *lang_printable_name (tree decl, int v);
511 static tree lookup_name_current_level (tree name);
512 static struct binding_level *make_binding_level (void);
513 static void pop_f_function_context (void);
514 static void push_f_function_context (void);
515 static void push_parm_decl (tree parm);
516 static tree pushdecl_top_level (tree decl);
517 static tree storedecls (tree decls);
518 static void store_parm_decls (int is_main_program);
519 static tree start_decl (tree decl, bool is_top_level);
520 static void start_function (tree name, tree type, int nested, int public);
521 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
522 #if FFECOM_GCC_INCLUDE
523 static void ffecom_file_ (char *name);
524 static void ffecom_initialize_char_syntax_ (void);
525 static void ffecom_close_include_ (FILE *f);
526 static int ffecom_decode_include_option_ (char *spec);
527 static FILE *ffecom_open_include_ (char *name, ffewhereLine l,
528 ffewhereColumn c);
529 #endif /* FFECOM_GCC_INCLUDE */
530
531 /* Static objects accessed by functions in this module. */
532
533 static ffesymbol ffecom_primary_entry_ = NULL;
534 static ffesymbol ffecom_nested_entry_ = NULL;
535 static ffeinfoKind ffecom_primary_entry_kind_;
536 static bool ffecom_primary_entry_is_proc_;
537 #if FFECOM_targetCURRENT == FFECOM_targetGCC
538 static tree ffecom_outer_function_decl_;
539 static tree ffecom_previous_function_decl_;
540 static tree ffecom_which_entrypoint_decl_;
541 static ffecomTemp_ ffecom_latest_temp_;
542 static int ffecom_pending_calls_ = 0;
543 static tree ffecom_float_zero_ = NULL_TREE;
544 static tree ffecom_float_half_ = NULL_TREE;
545 static tree ffecom_double_zero_ = NULL_TREE;
546 static tree ffecom_double_half_ = NULL_TREE;
547 static tree ffecom_func_result_;/* For functions. */
548 static tree ffecom_func_length_;/* For CHARACTER fns. */
549 static ffebld ffecom_list_blockdata_;
550 static ffebld ffecom_list_common_;
551 static ffebld ffecom_master_arglist_;
552 static ffeinfoBasictype ffecom_master_bt_;
553 static ffeinfoKindtype ffecom_master_kt_;
554 static ffetargetCharacterSize ffecom_master_size_;
555 static int ffecom_num_fns_ = 0;
556 static int ffecom_num_entrypoints_ = 0;
557 static bool ffecom_is_altreturning_ = FALSE;
558 static tree ffecom_multi_type_node_;
559 static tree ffecom_multi_retval_;
560 static tree
561 ffecom_multi_fields_[FFEINFO_basictype][FFEINFO_kindtype];
562 static bool ffecom_member_namelisted_; /* _member_phase1_ namelisted? */
563 static bool ffecom_doing_entry_ = FALSE;
564 static bool ffecom_transform_only_dummies_ = FALSE;
565
566 /* Holds pointer-to-function expressions. */
567
568 static tree ffecom_gfrt_[FFECOM_gfrt]
569 =
570 {
571 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) NULL_TREE,
572 #include "com-rt.def"
573 #undef DEFGFRT
574 };
575
576 /* Holds the external names of the functions. */
577
578 static char *ffecom_gfrt_name_[FFECOM_gfrt]
579 =
580 {
581 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) NAME,
582 #include "com-rt.def"
583 #undef DEFGFRT
584 };
585
586 /* Whether the function returns. */
587
588 static bool ffecom_gfrt_volatile_[FFECOM_gfrt]
589 =
590 {
591 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) VOLATILE,
592 #include "com-rt.def"
593 #undef DEFGFRT
594 };
595
596 /* Whether the function returns type complex. */
597
598 static bool ffecom_gfrt_complex_[FFECOM_gfrt]
599 =
600 {
601 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) COMPLEX,
602 #include "com-rt.def"
603 #undef DEFGFRT
604 };
605
606 /* Type code for the function return value. */
607
608 static ffecomRttype_ ffecom_gfrt_type_[FFECOM_gfrt]
609 =
610 {
611 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) TYPE,
612 #include "com-rt.def"
613 #undef DEFGFRT
614 };
615
616 /* String of codes for the function's arguments. */
617
618 static char *ffecom_gfrt_argstring_[FFECOM_gfrt]
619 =
620 {
621 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) ARGS,
622 #include "com-rt.def"
623 #undef DEFGFRT
624 };
625 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
626
627 /* Internal macros. */
628
629 #if FFECOM_targetCURRENT == FFECOM_targetGCC
630
631 /* We let tm.h override the types used here, to handle trivial differences
632 such as the choice of unsigned int or long unsigned int for size_t.
633 When machines start needing nontrivial differences in the size type,
634 it would be best to do something here to figure out automatically
635 from other information what type to use. */
636
637 /* NOTE: g77 currently doesn't use these; see setting of sizetype and
638 change that if you need to. -- jcb 09/01/91. */
639
640 #ifndef SIZE_TYPE
641 #define SIZE_TYPE "long unsigned int"
642 #endif
643
644 #ifndef WCHAR_TYPE
645 #define WCHAR_TYPE "int"
646 #endif
647
648 #define ffecom_concat_list_count_(catlist) ((catlist).count)
649 #define ffecom_concat_list_expr_(catlist,i) ((catlist).exprs[(i)])
650 #define ffecom_concat_list_maxlen_(catlist) ((catlist).maxlen)
651 #define ffecom_concat_list_minlen_(catlist) ((catlist).minlen)
652
653 #define ffecom_start_compstmt_ bison_rule_pushlevel_
654 #define ffecom_end_compstmt_ bison_rule_compstmt_
655
656 #define ffecom_char_args_(i,l,e) ffecom_char_args_x_((i),(l),(e),FALSE)
657 #define ffecom_char_args_with_null_(i,l,e) ffecom_char_args_x_((i),(l),(e),TRUE)
658
659 /* For each binding contour we allocate a binding_level structure
660 * which records the names defined in that contour.
661 * Contours include:
662 * 0) the global one
663 * 1) one for each function definition,
664 * where internal declarations of the parameters appear.
665 *
666 * The current meaning of a name can be found by searching the levels from
667 * the current one out to the global one.
668 */
669
670 /* Note that the information in the `names' component of the global contour
671 is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
672
673 struct binding_level
674 {
675 /* A chain of _DECL nodes for all variables, constants, functions, and
676 typedef types. These are in the reverse of the order supplied. */
677 tree names;
678
679 /* For each level (except not the global one), a chain of BLOCK nodes for
680 all the levels that were entered and exited one level down. */
681 tree blocks;
682
683 /* The BLOCK node for this level, if one has been preallocated. If 0, the
684 BLOCK is allocated (if needed) when the level is popped. */
685 tree this_block;
686
687 /* The binding level which this one is contained in (inherits from). */
688 struct binding_level *level_chain;
689 };
690
691 #define NULL_BINDING_LEVEL (struct binding_level *) NULL
692
693 /* The binding level currently in effect. */
694
695 static struct binding_level *current_binding_level;
696
697 /* A chain of binding_level structures awaiting reuse. */
698
699 static struct binding_level *free_binding_level;
700
701 /* The outermost binding level, for names of file scope.
702 This is created when the compiler is started and exists
703 through the entire run. */
704
705 static struct binding_level *global_binding_level;
706
707 /* Binding level structures are initialized by copying this one. */
708
709 static struct binding_level clear_binding_level
710 =
711 {NULL, NULL, NULL, NULL_BINDING_LEVEL};
712
713 /* Language-dependent contents of an identifier. */
714
715 struct lang_identifier
716 {
717 struct tree_identifier ignore;
718 tree global_value, local_value, label_value;
719 bool invented;
720 };
721
722 /* Macros for access to language-specific slots in an identifier. */
723 /* Each of these slots contains a DECL node or null. */
724
725 /* This represents the value which the identifier has in the
726 file-scope namespace. */
727 #define IDENTIFIER_GLOBAL_VALUE(NODE) \
728 (((struct lang_identifier *)(NODE))->global_value)
729 /* This represents the value which the identifier has in the current
730 scope. */
731 #define IDENTIFIER_LOCAL_VALUE(NODE) \
732 (((struct lang_identifier *)(NODE))->local_value)
733 /* This represents the value which the identifier has as a label in
734 the current label scope. */
735 #define IDENTIFIER_LABEL_VALUE(NODE) \
736 (((struct lang_identifier *)(NODE))->label_value)
737 /* This is nonzero if the identifier was "made up" by g77 code. */
738 #define IDENTIFIER_INVENTED(NODE) \
739 (((struct lang_identifier *)(NODE))->invented)
740
741 /* In identifiers, C uses the following fields in a special way:
742 TREE_PUBLIC to record that there was a previous local extern decl.
743 TREE_USED to record that such a decl was used.
744 TREE_ADDRESSABLE to record that the address of such a decl was used. */
745
746 /* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
747 that have names. Here so we can clear out their names' definitions
748 at the end of the function. */
749
750 static tree named_labels;
751
752 /* A list of LABEL_DECLs from outer contexts that are currently shadowed. */
753
754 static tree shadowed_labels;
755
756 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
757 \f
758
759 /* This is like gcc's stabilize_reference -- in fact, most of the code
760 comes from that -- but it handles the situation where the reference
761 is going to have its subparts picked at, and it shouldn't change
762 (or trigger extra invocations of functions in the subtrees) due to
763 this. save_expr is a bit overzealous, because we don't need the
764 entire thing calculated and saved like a temp. So, for DECLs, no
765 change is needed, because these are stable aggregates, and ARRAY_REF
766 and such might well be stable too, but for things like calculations,
767 we do need to calculate a snapshot of a value before picking at it. */
768
769 #if FFECOM_targetCURRENT == FFECOM_targetGCC
770 static tree
771 ffecom_stabilize_aggregate_ (tree ref)
772 {
773 tree result;
774 enum tree_code code = TREE_CODE (ref);
775
776 switch (code)
777 {
778 case VAR_DECL:
779 case PARM_DECL:
780 case RESULT_DECL:
781 /* No action is needed in this case. */
782 return ref;
783
784 case NOP_EXPR:
785 case CONVERT_EXPR:
786 case FLOAT_EXPR:
787 case FIX_TRUNC_EXPR:
788 case FIX_FLOOR_EXPR:
789 case FIX_ROUND_EXPR:
790 case FIX_CEIL_EXPR:
791 result = build_nt (code, stabilize_reference (TREE_OPERAND (ref, 0)));
792 break;
793
794 case INDIRECT_REF:
795 result = build_nt (INDIRECT_REF,
796 stabilize_reference_1 (TREE_OPERAND (ref, 0)));
797 break;
798
799 case COMPONENT_REF:
800 result = build_nt (COMPONENT_REF,
801 stabilize_reference (TREE_OPERAND (ref, 0)),
802 TREE_OPERAND (ref, 1));
803 break;
804
805 case BIT_FIELD_REF:
806 result = build_nt (BIT_FIELD_REF,
807 stabilize_reference (TREE_OPERAND (ref, 0)),
808 stabilize_reference_1 (TREE_OPERAND (ref, 1)),
809 stabilize_reference_1 (TREE_OPERAND (ref, 2)));
810 break;
811
812 case ARRAY_REF:
813 result = build_nt (ARRAY_REF,
814 stabilize_reference (TREE_OPERAND (ref, 0)),
815 stabilize_reference_1 (TREE_OPERAND (ref, 1)));
816 break;
817
818 case COMPOUND_EXPR:
819 result = build_nt (COMPOUND_EXPR,
820 stabilize_reference_1 (TREE_OPERAND (ref, 0)),
821 stabilize_reference (TREE_OPERAND (ref, 1)));
822 break;
823
824 case RTL_EXPR:
825 result = build1 (INDIRECT_REF, TREE_TYPE (ref),
826 save_expr (build1 (ADDR_EXPR,
827 build_pointer_type (TREE_TYPE (ref)),
828 ref)));
829 break;
830
831
832 default:
833 return save_expr (ref);
834
835 case ERROR_MARK:
836 return error_mark_node;
837 }
838
839 TREE_TYPE (result) = TREE_TYPE (ref);
840 TREE_READONLY (result) = TREE_READONLY (ref);
841 TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (ref);
842 TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (ref);
843 TREE_RAISES (result) = TREE_RAISES (ref);
844
845 return result;
846 }
847 #endif
848
849 /* A rip-off of gcc's convert.c convert_to_complex function,
850 reworked to handle complex implemented as C structures
851 (RECORD_TYPE with two fields, real and imaginary `r' and `i'). */
852
853 #if FFECOM_targetCURRENT == FFECOM_targetGCC
854 static tree
855 ffecom_convert_to_complex_ (tree type, tree expr)
856 {
857 register enum tree_code form = TREE_CODE (TREE_TYPE (expr));
858 tree subtype;
859
860 assert (TREE_CODE (type) == RECORD_TYPE);
861
862 subtype = TREE_TYPE (TYPE_FIELDS (type));
863
864 if (form == REAL_TYPE || form == INTEGER_TYPE || form == ENUMERAL_TYPE)
865 {
866 expr = convert (subtype, expr);
867 return ffecom_2 (COMPLEX_EXPR, type, expr,
868 convert (subtype, integer_zero_node));
869 }
870
871 if (form == RECORD_TYPE)
872 {
873 tree elt_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr)));
874 if (TYPE_MAIN_VARIANT (elt_type) == TYPE_MAIN_VARIANT (subtype))
875 return expr;
876 else
877 {
878 expr = save_expr (expr);
879 return ffecom_2 (COMPLEX_EXPR,
880 type,
881 convert (subtype,
882 ffecom_1 (REALPART_EXPR,
883 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
884 expr)),
885 convert (subtype,
886 ffecom_1 (IMAGPART_EXPR,
887 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
888 expr)));
889 }
890 }
891
892 if (form == POINTER_TYPE || form == REFERENCE_TYPE)
893 error ("pointer value used where a complex was expected");
894 else
895 error ("aggregate value used where a complex was expected");
896
897 return ffecom_2 (COMPLEX_EXPR, type,
898 convert (subtype, integer_zero_node),
899 convert (subtype, integer_zero_node));
900 }
901 #endif
902
903 /* Like gcc's convert(), but crashes if widening might happen. */
904
905 #if FFECOM_targetCURRENT == FFECOM_targetGCC
906 static tree
907 ffecom_convert_narrow_ (type, expr)
908 tree type, expr;
909 {
910 register tree e = expr;
911 register enum tree_code code = TREE_CODE (type);
912
913 if (type == TREE_TYPE (e)
914 || TREE_CODE (e) == ERROR_MARK)
915 return e;
916 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
917 return fold (build1 (NOP_EXPR, type, e));
918 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
919 || code == ERROR_MARK)
920 return error_mark_node;
921 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
922 {
923 assert ("void value not ignored as it ought to be" == NULL);
924 return error_mark_node;
925 }
926 assert (code != VOID_TYPE);
927 if ((code != RECORD_TYPE)
928 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
929 assert ("converting COMPLEX to REAL" == NULL);
930 assert (code != ENUMERAL_TYPE);
931 if (code == INTEGER_TYPE)
932 {
933 assert (TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE);
934 assert (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)));
935 return fold (convert_to_integer (type, e));
936 }
937 if (code == POINTER_TYPE)
938 {
939 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
940 return fold (convert_to_pointer (type, e));
941 }
942 if (code == REAL_TYPE)
943 {
944 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
945 assert (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)));
946 return fold (convert_to_real (type, e));
947 }
948 if (code == COMPLEX_TYPE)
949 {
950 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
951 assert (TYPE_PRECISION (TREE_TYPE (type)) <= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
952 return fold (convert_to_complex (type, e));
953 }
954 if (code == RECORD_TYPE)
955 {
956 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
957 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
958 <= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
959 return fold (ffecom_convert_to_complex_ (type, e));
960 }
961
962 assert ("conversion to non-scalar type requested" == NULL);
963 return error_mark_node;
964 }
965 #endif
966
967 /* Like gcc's convert(), but crashes if narrowing might happen. */
968
969 #if FFECOM_targetCURRENT == FFECOM_targetGCC
970 static tree
971 ffecom_convert_widen_ (type, expr)
972 tree type, expr;
973 {
974 register tree e = expr;
975 register enum tree_code code = TREE_CODE (type);
976
977 if (type == TREE_TYPE (e)
978 || TREE_CODE (e) == ERROR_MARK)
979 return e;
980 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
981 return fold (build1 (NOP_EXPR, type, e));
982 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
983 || code == ERROR_MARK)
984 return error_mark_node;
985 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
986 {
987 assert ("void value not ignored as it ought to be" == NULL);
988 return error_mark_node;
989 }
990 assert (code != VOID_TYPE);
991 if ((code != RECORD_TYPE)
992 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
993 assert ("narrowing COMPLEX to REAL" == NULL);
994 assert (code != ENUMERAL_TYPE);
995 if (code == INTEGER_TYPE)
996 {
997 assert (TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE);
998 assert (TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)));
999 return fold (convert_to_integer (type, e));
1000 }
1001 if (code == POINTER_TYPE)
1002 {
1003 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1004 return fold (convert_to_pointer (type, e));
1005 }
1006 if (code == REAL_TYPE)
1007 {
1008 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1009 assert (TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)));
1010 return fold (convert_to_real (type, e));
1011 }
1012 if (code == COMPLEX_TYPE)
1013 {
1014 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1015 assert (TYPE_PRECISION (TREE_TYPE (type)) >= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1016 return fold (convert_to_complex (type, e));
1017 }
1018 if (code == RECORD_TYPE)
1019 {
1020 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
1021 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1022 >= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
1023 return fold (ffecom_convert_to_complex_ (type, e));
1024 }
1025
1026 assert ("conversion to non-scalar type requested" == NULL);
1027 return error_mark_node;
1028 }
1029 #endif
1030
1031 /* Handles making a COMPLEX type, either the standard
1032 (but buggy?) gbe way, or the safer (but less elegant?)
1033 f2c way. */
1034
1035 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1036 static tree
1037 ffecom_make_complex_type_ (tree subtype)
1038 {
1039 tree type;
1040 tree realfield;
1041 tree imagfield;
1042
1043 if (ffe_is_emulate_complex ())
1044 {
1045 type = make_node (RECORD_TYPE);
1046 realfield = ffecom_decl_field (type, NULL_TREE, "r", subtype);
1047 imagfield = ffecom_decl_field (type, realfield, "i", subtype);
1048 TYPE_FIELDS (type) = realfield;
1049 layout_type (type);
1050 }
1051 else
1052 {
1053 type = make_node (COMPLEX_TYPE);
1054 TREE_TYPE (type) = subtype;
1055 layout_type (type);
1056 }
1057
1058 return type;
1059 }
1060 #endif
1061
1062 /* Chooses either the gbe or the f2c way to build a
1063 complex constant. */
1064
1065 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1066 static tree
1067 ffecom_build_complex_constant_ (tree type, tree realpart, tree imagpart)
1068 {
1069 tree bothparts;
1070
1071 if (ffe_is_emulate_complex ())
1072 {
1073 bothparts = build_tree_list (TYPE_FIELDS (type), realpart);
1074 TREE_CHAIN (bothparts) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), imagpart);
1075 bothparts = build (CONSTRUCTOR, type, NULL_TREE, bothparts);
1076 }
1077 else
1078 {
1079 bothparts = build_complex (type, realpart, imagpart);
1080 }
1081
1082 return bothparts;
1083 }
1084 #endif
1085
1086 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1087 static tree
1088 ffecom_arglist_expr_ (char *c, ffebld expr)
1089 {
1090 tree list;
1091 tree *plist = &list;
1092 tree trail = NULL_TREE; /* Append char length args here. */
1093 tree *ptrail = &trail;
1094 tree length;
1095 ffebld exprh;
1096 tree item;
1097 bool ptr = FALSE;
1098 tree wanted = NULL_TREE;
1099 static char zed[] = "0";
1100
1101 if (c == NULL)
1102 c = &zed[0];
1103
1104 while (expr != NULL)
1105 {
1106 if (*c != '\0')
1107 {
1108 ptr = FALSE;
1109 if (*c == '&')
1110 {
1111 ptr = TRUE;
1112 ++c;
1113 }
1114 switch (*(c++))
1115 {
1116 case '\0':
1117 ptr = TRUE;
1118 wanted = NULL_TREE;
1119 break;
1120
1121 case 'a':
1122 assert (ptr);
1123 wanted = NULL_TREE;
1124 break;
1125
1126 case 'c':
1127 wanted = ffecom_f2c_complex_type_node;
1128 break;
1129
1130 case 'd':
1131 wanted = ffecom_f2c_doublereal_type_node;
1132 break;
1133
1134 case 'e':
1135 wanted = ffecom_f2c_doublecomplex_type_node;
1136 break;
1137
1138 case 'f':
1139 wanted = ffecom_f2c_real_type_node;
1140 break;
1141
1142 case 'i':
1143 wanted = ffecom_f2c_integer_type_node;
1144 break;
1145
1146 case 'j':
1147 wanted = ffecom_f2c_longint_type_node;
1148 break;
1149
1150 default:
1151 assert ("bad argstring code" == NULL);
1152 wanted = NULL_TREE;
1153 break;
1154 }
1155 }
1156
1157 exprh = ffebld_head (expr);
1158 if (exprh == NULL)
1159 wanted = NULL_TREE;
1160
1161 if ((wanted == NULL_TREE)
1162 || (ptr
1163 && (TYPE_MODE
1164 (ffecom_tree_type[ffeinfo_basictype (ffebld_info (exprh))]
1165 [ffeinfo_kindtype (ffebld_info (exprh))])
1166 == TYPE_MODE (wanted))))
1167 *plist
1168 = build_tree_list (NULL_TREE,
1169 ffecom_arg_ptr_to_expr (exprh,
1170 &length));
1171 else
1172 {
1173 item = ffecom_arg_expr (exprh, &length);
1174 item = ffecom_convert_widen_ (wanted, item);
1175 if (ptr)
1176 {
1177 item = ffecom_1 (ADDR_EXPR,
1178 build_pointer_type (TREE_TYPE (item)),
1179 item);
1180 }
1181 *plist
1182 = build_tree_list (NULL_TREE,
1183 item);
1184 }
1185
1186 plist = &TREE_CHAIN (*plist);
1187 expr = ffebld_trail (expr);
1188 if (length != NULL_TREE)
1189 {
1190 *ptrail = build_tree_list (NULL_TREE, length);
1191 ptrail = &TREE_CHAIN (*ptrail);
1192 }
1193 }
1194
1195 /* We've run out of args in the call; if the implementation expects
1196 more, supply null pointers for them, which the implementation can
1197 check to see if an arg was omitted. */
1198
1199 while (*c != '\0' && *c != '0')
1200 {
1201 if (*c == '&')
1202 ++c;
1203 else
1204 assert ("missing arg to run-time routine!" == NULL);
1205
1206 switch (*(c++))
1207 {
1208 case '\0':
1209 case 'a':
1210 case 'c':
1211 case 'd':
1212 case 'e':
1213 case 'f':
1214 case 'i':
1215 case 'j':
1216 break;
1217
1218 default:
1219 assert ("bad arg string code" == NULL);
1220 break;
1221 }
1222 *plist
1223 = build_tree_list (NULL_TREE,
1224 null_pointer_node);
1225 plist = &TREE_CHAIN (*plist);
1226 }
1227
1228 *plist = trail;
1229
1230 return list;
1231 }
1232 #endif
1233
1234 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1235 static tree
1236 ffecom_widest_expr_type_ (ffebld list)
1237 {
1238 ffebld item;
1239 ffebld widest = NULL;
1240 ffetype type;
1241 ffetype widest_type = NULL;
1242 tree t;
1243
1244 for (; list != NULL; list = ffebld_trail (list))
1245 {
1246 item = ffebld_head (list);
1247 if (item == NULL)
1248 continue;
1249 if ((widest != NULL)
1250 && (ffeinfo_basictype (ffebld_info (item))
1251 != ffeinfo_basictype (ffebld_info (widest))))
1252 continue;
1253 type = ffeinfo_type (ffeinfo_basictype (ffebld_info (item)),
1254 ffeinfo_kindtype (ffebld_info (item)));
1255 if ((widest == FFEINFO_kindtypeNONE)
1256 || (ffetype_size (type)
1257 > ffetype_size (widest_type)))
1258 {
1259 widest = item;
1260 widest_type = type;
1261 }
1262 }
1263
1264 assert (widest != NULL);
1265 t = ffecom_tree_type[ffeinfo_basictype (ffebld_info (widest))]
1266 [ffeinfo_kindtype (ffebld_info (widest))];
1267 assert (t != NULL_TREE);
1268 return t;
1269 }
1270 #endif
1271
1272 /* Check whether dest and source might overlap. ffebld versions of these
1273 might or might not be passed, will be NULL if not.
1274
1275 The test is really whether source_tree is modifiable and, if modified,
1276 might overlap destination such that the value(s) in the destination might
1277 change before it is finally modified. dest_* are the canonized
1278 destination itself. */
1279
1280 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1281 static bool
1282 ffecom_overlap_ (tree dest_decl, tree dest_offset, tree dest_size,
1283 tree source_tree, ffebld source UNUSED,
1284 bool scalar_arg)
1285 {
1286 tree source_decl;
1287 tree source_offset;
1288 tree source_size;
1289 tree t;
1290
1291 if (source_tree == NULL_TREE)
1292 return FALSE;
1293
1294 switch (TREE_CODE (source_tree))
1295 {
1296 case ERROR_MARK:
1297 case IDENTIFIER_NODE:
1298 case INTEGER_CST:
1299 case REAL_CST:
1300 case COMPLEX_CST:
1301 case STRING_CST:
1302 case CONST_DECL:
1303 case VAR_DECL:
1304 case RESULT_DECL:
1305 case FIELD_DECL:
1306 case MINUS_EXPR:
1307 case MULT_EXPR:
1308 case TRUNC_DIV_EXPR:
1309 case CEIL_DIV_EXPR:
1310 case FLOOR_DIV_EXPR:
1311 case ROUND_DIV_EXPR:
1312 case TRUNC_MOD_EXPR:
1313 case CEIL_MOD_EXPR:
1314 case FLOOR_MOD_EXPR:
1315 case ROUND_MOD_EXPR:
1316 case RDIV_EXPR:
1317 case EXACT_DIV_EXPR:
1318 case FIX_TRUNC_EXPR:
1319 case FIX_CEIL_EXPR:
1320 case FIX_FLOOR_EXPR:
1321 case FIX_ROUND_EXPR:
1322 case FLOAT_EXPR:
1323 case EXPON_EXPR:
1324 case NEGATE_EXPR:
1325 case MIN_EXPR:
1326 case MAX_EXPR:
1327 case ABS_EXPR:
1328 case FFS_EXPR:
1329 case LSHIFT_EXPR:
1330 case RSHIFT_EXPR:
1331 case LROTATE_EXPR:
1332 case RROTATE_EXPR:
1333 case BIT_IOR_EXPR:
1334 case BIT_XOR_EXPR:
1335 case BIT_AND_EXPR:
1336 case BIT_ANDTC_EXPR:
1337 case BIT_NOT_EXPR:
1338 case TRUTH_ANDIF_EXPR:
1339 case TRUTH_ORIF_EXPR:
1340 case TRUTH_AND_EXPR:
1341 case TRUTH_OR_EXPR:
1342 case TRUTH_XOR_EXPR:
1343 case TRUTH_NOT_EXPR:
1344 case LT_EXPR:
1345 case LE_EXPR:
1346 case GT_EXPR:
1347 case GE_EXPR:
1348 case EQ_EXPR:
1349 case NE_EXPR:
1350 case COMPLEX_EXPR:
1351 case CONJ_EXPR:
1352 case REALPART_EXPR:
1353 case IMAGPART_EXPR:
1354 case LABEL_EXPR:
1355 case COMPONENT_REF:
1356 return FALSE;
1357
1358 case COMPOUND_EXPR:
1359 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1360 TREE_OPERAND (source_tree, 1), NULL,
1361 scalar_arg);
1362
1363 case MODIFY_EXPR:
1364 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1365 TREE_OPERAND (source_tree, 0), NULL,
1366 scalar_arg);
1367
1368 case CONVERT_EXPR:
1369 case NOP_EXPR:
1370 case NON_LVALUE_EXPR:
1371 case PLUS_EXPR:
1372 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1373 return TRUE;
1374
1375 ffecom_tree_canonize_ptr_ (&source_decl, &source_offset,
1376 source_tree);
1377 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1378 break;
1379
1380 case COND_EXPR:
1381 return
1382 ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1383 TREE_OPERAND (source_tree, 1), NULL,
1384 scalar_arg)
1385 || ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1386 TREE_OPERAND (source_tree, 2), NULL,
1387 scalar_arg);
1388
1389
1390 case ADDR_EXPR:
1391 ffecom_tree_canonize_ref_ (&source_decl, &source_offset,
1392 &source_size,
1393 TREE_OPERAND (source_tree, 0));
1394 break;
1395
1396 case PARM_DECL:
1397 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1398 return TRUE;
1399
1400 source_decl = source_tree;
1401 source_offset = size_zero_node;
1402 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1403 break;
1404
1405 case SAVE_EXPR:
1406 case REFERENCE_EXPR:
1407 case PREDECREMENT_EXPR:
1408 case PREINCREMENT_EXPR:
1409 case POSTDECREMENT_EXPR:
1410 case POSTINCREMENT_EXPR:
1411 case INDIRECT_REF:
1412 case ARRAY_REF:
1413 case CALL_EXPR:
1414 default:
1415 return TRUE;
1416 }
1417
1418 /* Come here when source_decl, source_offset, and source_size filled
1419 in appropriately. */
1420
1421 if (source_decl == NULL_TREE)
1422 return FALSE; /* No decl involved, so no overlap. */
1423
1424 if (source_decl != dest_decl)
1425 return FALSE; /* Different decl, no overlap. */
1426
1427 if (TREE_CODE (dest_size) == ERROR_MARK)
1428 return TRUE; /* Assignment into entire assumed-size
1429 array? Shouldn't happen.... */
1430
1431 t = ffecom_2 (LE_EXPR, integer_type_node,
1432 ffecom_2 (PLUS_EXPR, TREE_TYPE (dest_offset),
1433 dest_offset,
1434 convert (TREE_TYPE (dest_offset),
1435 dest_size)),
1436 convert (TREE_TYPE (dest_offset),
1437 source_offset));
1438
1439 if (integer_onep (t))
1440 return FALSE; /* Destination precedes source. */
1441
1442 if (!scalar_arg
1443 || (source_size == NULL_TREE)
1444 || (TREE_CODE (source_size) == ERROR_MARK)
1445 || integer_zerop (source_size))
1446 return TRUE; /* No way to tell if dest follows source. */
1447
1448 t = ffecom_2 (LE_EXPR, integer_type_node,
1449 ffecom_2 (PLUS_EXPR, TREE_TYPE (source_offset),
1450 source_offset,
1451 convert (TREE_TYPE (source_offset),
1452 source_size)),
1453 convert (TREE_TYPE (source_offset),
1454 dest_offset));
1455
1456 if (integer_onep (t))
1457 return FALSE; /* Destination follows source. */
1458
1459 return TRUE; /* Destination and source overlap. */
1460 }
1461 #endif
1462
1463 /* Check whether dest might overlap any of a list of arguments or is
1464 in a COMMON area the callee might know about (and thus modify). */
1465
1466 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1467 static bool
1468 ffecom_args_overlapping_ (tree dest_tree, ffebld dest UNUSED,
1469 tree args, tree callee_commons,
1470 bool scalar_args)
1471 {
1472 tree arg;
1473 tree dest_decl;
1474 tree dest_offset;
1475 tree dest_size;
1476
1477 ffecom_tree_canonize_ref_ (&dest_decl, &dest_offset, &dest_size,
1478 dest_tree);
1479
1480 if (dest_decl == NULL_TREE)
1481 return FALSE; /* Seems unlikely! */
1482
1483 /* If the decl cannot be determined reliably, or if its in COMMON
1484 and the callee isn't known to not futz with COMMON via other
1485 means, overlap might happen. */
1486
1487 if ((TREE_CODE (dest_decl) == ERROR_MARK)
1488 || ((callee_commons != NULL_TREE)
1489 && TREE_PUBLIC (dest_decl)))
1490 return TRUE;
1491
1492 for (; args != NULL_TREE; args = TREE_CHAIN (args))
1493 {
1494 if (((arg = TREE_VALUE (args)) != NULL_TREE)
1495 && ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1496 arg, NULL, scalar_args))
1497 return TRUE;
1498 }
1499
1500 return FALSE;
1501 }
1502 #endif
1503
1504 /* Build a string for a variable name as used by NAMELIST. This means that
1505 if we're using the f2c library, we build an uppercase string, since
1506 f2c does this. */
1507
1508 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1509 static tree
1510 ffecom_build_f2c_string_ (int i, char *s)
1511 {
1512 if (!ffe_is_f2c_library ())
1513 return build_string (i, s);
1514
1515 {
1516 char *tmp;
1517 char *p;
1518 char *q;
1519 char space[34];
1520 tree t;
1521
1522 if (((size_t) i) > ARRAY_SIZE (space))
1523 tmp = malloc_new_ks (malloc_pool_image (), "f2c_string", i);
1524 else
1525 tmp = &space[0];
1526
1527 for (p = s, q = tmp; *p != '\0'; ++p, ++q)
1528 *q = ffesrc_toupper (*p);
1529 *q = '\0';
1530
1531 t = build_string (i, tmp);
1532
1533 if (((size_t) i) > ARRAY_SIZE (space))
1534 malloc_kill_ks (malloc_pool_image (), tmp, i);
1535
1536 return t;
1537 }
1538 }
1539
1540 #endif
1541 /* Returns CALL_EXPR or equivalent with given type (pass NULL_TREE for
1542 type to just get whatever the function returns), handling the
1543 f2c value-returning convention, if required, by prepending
1544 to the arglist a pointer to a temporary to receive the return value. */
1545
1546 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1547 static tree
1548 ffecom_call_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1549 tree type, tree args, tree dest_tree,
1550 ffebld dest, bool *dest_used, tree callee_commons,
1551 bool scalar_args)
1552 {
1553 tree item;
1554 tree tempvar;
1555
1556 if (dest_used != NULL)
1557 *dest_used = FALSE;
1558
1559 if (is_f2c_complex)
1560 {
1561 if ((dest_used == NULL)
1562 || (dest == NULL)
1563 || (ffeinfo_basictype (ffebld_info (dest))
1564 != FFEINFO_basictypeCOMPLEX)
1565 || (ffeinfo_kindtype (ffebld_info (dest)) != kt)
1566 || ((type != NULL_TREE) && (TREE_TYPE (dest_tree) != type))
1567 || ffecom_args_overlapping_ (dest_tree, dest, args,
1568 callee_commons,
1569 scalar_args))
1570 {
1571 tempvar = ffecom_push_tempvar (ffecom_tree_type
1572 [FFEINFO_basictypeCOMPLEX][kt],
1573 FFETARGET_charactersizeNONE,
1574 -1, TRUE);
1575 }
1576 else
1577 {
1578 *dest_used = TRUE;
1579 tempvar = dest_tree;
1580 type = NULL_TREE;
1581 }
1582
1583 item
1584 = build_tree_list (NULL_TREE,
1585 ffecom_1 (ADDR_EXPR,
1586 build_pointer_type (TREE_TYPE (tempvar)),
1587 tempvar));
1588 TREE_CHAIN (item) = args;
1589
1590 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1591 item, NULL_TREE);
1592
1593 if (tempvar != dest_tree)
1594 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item, tempvar);
1595 }
1596 else
1597 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1598 args, NULL_TREE);
1599
1600 if ((type != NULL_TREE) && (TREE_TYPE (item) != type))
1601 item = ffecom_convert_narrow_ (type, item);
1602
1603 return item;
1604 }
1605 #endif
1606
1607 /* Given two arguments, transform them and make a call to the given
1608 function via ffecom_call_. */
1609
1610 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1611 static tree
1612 ffecom_call_binop_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1613 tree type, ffebld left, ffebld right,
1614 tree dest_tree, ffebld dest, bool *dest_used,
1615 tree callee_commons, bool scalar_args)
1616 {
1617 tree left_tree;
1618 tree right_tree;
1619 tree left_length;
1620 tree right_length;
1621
1622 ffecom_push_calltemps ();
1623 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
1624 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
1625 ffecom_pop_calltemps ();
1626
1627 left_tree = build_tree_list (NULL_TREE, left_tree);
1628 right_tree = build_tree_list (NULL_TREE, right_tree);
1629 TREE_CHAIN (left_tree) = right_tree;
1630
1631 if (left_length != NULL_TREE)
1632 {
1633 left_length = build_tree_list (NULL_TREE, left_length);
1634 TREE_CHAIN (right_tree) = left_length;
1635 }
1636
1637 if (right_length != NULL_TREE)
1638 {
1639 right_length = build_tree_list (NULL_TREE, right_length);
1640 if (left_length != NULL_TREE)
1641 TREE_CHAIN (left_length) = right_length;
1642 else
1643 TREE_CHAIN (right_tree) = right_length;
1644 }
1645
1646 return ffecom_call_ (fn, kt, is_f2c_complex, type, left_tree,
1647 dest_tree, dest, dest_used, callee_commons,
1648 scalar_args);
1649 }
1650 #endif
1651
1652 /* ffecom_char_args_x_ -- Return ptr/length args for char subexpression
1653
1654 tree ptr_arg;
1655 tree length_arg;
1656 ffebld expr;
1657 bool with_null;
1658 ffecom_char_args_x_(&ptr_arg,&length_arg,expr,with_null);
1659
1660 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
1661 subexpressions by constructing the appropriate trees for the ptr-to-
1662 character-text and length-of-character-text arguments in a calling
1663 sequence.
1664
1665 Note that if with_null is TRUE, and the expression is an opCONTER,
1666 a null byte is appended to the string. */
1667
1668 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1669 static void
1670 ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
1671 {
1672 tree item;
1673 tree high;
1674 ffetargetCharacter1 val;
1675 ffetargetCharacterSize newlen;
1676
1677 switch (ffebld_op (expr))
1678 {
1679 case FFEBLD_opCONTER:
1680 val = ffebld_constant_character1 (ffebld_conter (expr));
1681 newlen = ffetarget_length_character1 (val);
1682 if (with_null)
1683 {
1684 if (newlen != 0)
1685 ++newlen; /* begin FFETARGET-NULL-KLUDGE. */
1686 }
1687 *length = build_int_2 (newlen, 0);
1688 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
1689 high = build_int_2 (newlen, 0);
1690 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
1691 item = build_string (newlen, /* end FFETARGET-NULL-KLUDGE. */
1692 ffetarget_text_character1 (val));
1693 TREE_TYPE (item)
1694 = build_type_variant
1695 (build_array_type
1696 (char_type_node,
1697 build_range_type
1698 (ffecom_f2c_ftnlen_type_node,
1699 ffecom_f2c_ftnlen_one_node,
1700 high)),
1701 1, 0);
1702 TREE_CONSTANT (item) = 1;
1703 TREE_STATIC (item) = 1;
1704 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
1705 item);
1706 break;
1707
1708 case FFEBLD_opSYMTER:
1709 {
1710 ffesymbol s = ffebld_symter (expr);
1711
1712 item = ffesymbol_hook (s).decl_tree;
1713 if (item == NULL_TREE)
1714 {
1715 s = ffecom_sym_transform_ (s);
1716 item = ffesymbol_hook (s).decl_tree;
1717 }
1718 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
1719 {
1720 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
1721 *length = ffesymbol_hook (s).length_tree;
1722 else
1723 {
1724 *length = build_int_2 (ffesymbol_size (s), 0);
1725 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
1726 }
1727 }
1728 else if (item == error_mark_node)
1729 *length = error_mark_node;
1730 else /* FFEINFO_kindFUNCTION: */
1731 *length = NULL_TREE;
1732 if (!ffesymbol_hook (s).addr
1733 && (item != error_mark_node))
1734 item = ffecom_1 (ADDR_EXPR,
1735 build_pointer_type (TREE_TYPE (item)),
1736 item);
1737 }
1738 break;
1739
1740 case FFEBLD_opARRAYREF:
1741 {
1742 ffebld dims[FFECOM_dimensionsMAX];
1743 tree array;
1744 int i;
1745
1746 ffecom_push_calltemps ();
1747 ffecom_char_args_ (&item, length, ffebld_left (expr));
1748 ffecom_pop_calltemps ();
1749
1750 if (item == error_mark_node || *length == error_mark_node)
1751 {
1752 item = *length = error_mark_node;
1753 break;
1754 }
1755
1756 /* Build up ARRAY_REFs in reverse order (since we're column major
1757 here in Fortran land). */
1758
1759 for (i = 0, expr = ffebld_right (expr);
1760 expr != NULL;
1761 expr = ffebld_trail (expr))
1762 dims[i++] = ffebld_head (expr);
1763
1764 for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
1765 i >= 0;
1766 --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
1767 {
1768 item = ffecom_2 (PLUS_EXPR, build_pointer_type (TREE_TYPE (array)),
1769 item,
1770 size_binop (MULT_EXPR,
1771 size_in_bytes (TREE_TYPE (array)),
1772 size_binop (MINUS_EXPR,
1773 ffecom_expr (dims[i]),
1774 TYPE_MIN_VALUE (TYPE_DOMAIN (array)))));
1775 }
1776 }
1777 break;
1778
1779 case FFEBLD_opSUBSTR:
1780 {
1781 ffebld start;
1782 ffebld end;
1783 ffebld thing = ffebld_right (expr);
1784 tree start_tree;
1785 tree end_tree;
1786
1787 assert (ffebld_op (thing) == FFEBLD_opITEM);
1788 start = ffebld_head (thing);
1789 thing = ffebld_trail (thing);
1790 assert (ffebld_trail (thing) == NULL);
1791 end = ffebld_head (thing);
1792
1793 ffecom_push_calltemps ();
1794 ffecom_char_args_ (&item, length, ffebld_left (expr));
1795 ffecom_pop_calltemps ();
1796
1797 if (item == error_mark_node || *length == error_mark_node)
1798 {
1799 item = *length = error_mark_node;
1800 break;
1801 }
1802
1803 if (start == NULL)
1804 {
1805 if (end == NULL)
1806 ;
1807 else
1808 {
1809 end_tree = convert (ffecom_f2c_ftnlen_type_node,
1810 ffecom_expr (end));
1811
1812 if (end_tree == error_mark_node)
1813 {
1814 item = *length = error_mark_node;
1815 break;
1816 }
1817
1818 *length = end_tree;
1819 }
1820 }
1821 else
1822 {
1823 start_tree = convert (ffecom_f2c_ftnlen_type_node,
1824 ffecom_expr (start));
1825
1826 if (start_tree == error_mark_node)
1827 {
1828 item = *length = error_mark_node;
1829 break;
1830 }
1831
1832 start_tree = ffecom_save_tree (start_tree);
1833
1834 item = ffecom_2 (PLUS_EXPR, TREE_TYPE (item),
1835 item,
1836 ffecom_2 (MINUS_EXPR,
1837 TREE_TYPE (start_tree),
1838 start_tree,
1839 ffecom_f2c_ftnlen_one_node));
1840
1841 if (end == NULL)
1842 {
1843 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
1844 ffecom_f2c_ftnlen_one_node,
1845 ffecom_2 (MINUS_EXPR,
1846 ffecom_f2c_ftnlen_type_node,
1847 *length,
1848 start_tree));
1849 }
1850 else
1851 {
1852 end_tree = convert (ffecom_f2c_ftnlen_type_node,
1853 ffecom_expr (end));
1854
1855 if (end_tree == error_mark_node)
1856 {
1857 item = *length = error_mark_node;
1858 break;
1859 }
1860
1861 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
1862 ffecom_f2c_ftnlen_one_node,
1863 ffecom_2 (MINUS_EXPR,
1864 ffecom_f2c_ftnlen_type_node,
1865 end_tree, start_tree));
1866 }
1867 }
1868 }
1869 break;
1870
1871 case FFEBLD_opFUNCREF:
1872 {
1873 ffesymbol s = ffebld_symter (ffebld_left (expr));
1874 tree tempvar;
1875 tree args;
1876 ffetargetCharacterSize size = ffeinfo_size (ffebld_info (expr));
1877 ffecomGfrt ix;
1878
1879 if (size == FFETARGET_charactersizeNONE)
1880 size = 24; /* ~~~~ Kludge alert! This should someday be fixed. */
1881
1882 *length = build_int_2 (size, 0);
1883 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
1884
1885 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
1886 == FFEINFO_whereINTRINSIC)
1887 {
1888 if (size == 1)
1889 { /* Invocation of an intrinsic returning CHARACTER*1. */
1890 item = ffecom_expr_intrinsic_ (expr, NULL_TREE,
1891 NULL, NULL);
1892 break;
1893 }
1894 ix = ffeintrin_gfrt_direct (ffebld_symter_implementation (ffebld_left (expr)));
1895 assert (ix != FFECOM_gfrt);
1896 item = ffecom_gfrt_tree_ (ix);
1897 }
1898 else
1899 {
1900 ix = FFECOM_gfrt;
1901 item = ffesymbol_hook (s).decl_tree;
1902 if (item == NULL_TREE)
1903 {
1904 s = ffecom_sym_transform_ (s);
1905 item = ffesymbol_hook (s).decl_tree;
1906 }
1907 if (item == error_mark_node)
1908 {
1909 item = *length = error_mark_node;
1910 break;
1911 }
1912
1913 if (!ffesymbol_hook (s).addr)
1914 item = ffecom_1_fn (item);
1915 }
1916
1917 assert (ffecom_pending_calls_ != 0);
1918 tempvar = ffecom_push_tempvar (char_type_node, size, -1, TRUE);
1919 tempvar = ffecom_1 (ADDR_EXPR,
1920 build_pointer_type (TREE_TYPE (tempvar)),
1921 tempvar);
1922
1923 ffecom_push_calltemps ();
1924
1925 args = build_tree_list (NULL_TREE, tempvar);
1926
1927 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT) /* Sfunc args by value. */
1928 TREE_CHAIN (args) = ffecom_list_expr (ffebld_right (expr));
1929 else
1930 {
1931 TREE_CHAIN (args) = build_tree_list (NULL_TREE, *length);
1932 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
1933 {
1934 TREE_CHAIN (TREE_CHAIN (args))
1935 = ffecom_arglist_expr_ (ffecom_gfrt_args_ (ix),
1936 ffebld_right (expr));
1937 }
1938 else
1939 {
1940 TREE_CHAIN (TREE_CHAIN (args))
1941 = ffecom_list_ptr_to_expr (ffebld_right (expr));
1942 }
1943 }
1944
1945 item = ffecom_3s (CALL_EXPR,
1946 TREE_TYPE (TREE_TYPE (TREE_TYPE (item))),
1947 item, args, NULL_TREE);
1948 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item,
1949 tempvar);
1950
1951 ffecom_pop_calltemps ();
1952 }
1953 break;
1954
1955 case FFEBLD_opCONVERT:
1956
1957 ffecom_push_calltemps ();
1958 ffecom_char_args_ (&item, length, ffebld_left (expr));
1959 ffecom_pop_calltemps ();
1960
1961 if (item == error_mark_node || *length == error_mark_node)
1962 {
1963 item = *length = error_mark_node;
1964 break;
1965 }
1966
1967 if ((ffebld_size_known (ffebld_left (expr))
1968 == FFETARGET_charactersizeNONE)
1969 || (ffebld_size_known (ffebld_left (expr)) < (ffebld_size (expr))))
1970 { /* Possible blank-padding needed, copy into
1971 temporary. */
1972 tree tempvar;
1973 tree args;
1974 tree newlen;
1975
1976 assert (ffecom_pending_calls_ != 0);
1977 tempvar = ffecom_push_tempvar (char_type_node,
1978 ffebld_size (expr), -1, TRUE);
1979 tempvar = ffecom_1 (ADDR_EXPR,
1980 build_pointer_type (TREE_TYPE (tempvar)),
1981 tempvar);
1982
1983 newlen = build_int_2 (ffebld_size (expr), 0);
1984 TREE_TYPE (newlen) = ffecom_f2c_ftnlen_type_node;
1985
1986 args = build_tree_list (NULL_TREE, tempvar);
1987 TREE_CHAIN (args) = build_tree_list (NULL_TREE, item);
1988 TREE_CHAIN (TREE_CHAIN (args)) = build_tree_list (NULL_TREE, newlen);
1989 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (args)))
1990 = build_tree_list (NULL_TREE, *length);
1991
1992 item = ffecom_call_gfrt (FFECOM_gfrtCOPY, args);
1993 TREE_SIDE_EFFECTS (item) = 1;
1994 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), fold (item),
1995 tempvar);
1996 *length = newlen;
1997 }
1998 else
1999 { /* Just truncate the length. */
2000 *length = build_int_2 (ffebld_size (expr), 0);
2001 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2002 }
2003 break;
2004
2005 default:
2006 assert ("bad op for single char arg expr" == NULL);
2007 item = NULL_TREE;
2008 break;
2009 }
2010
2011 *xitem = item;
2012 }
2013 #endif
2014
2015 /* Check the size of the type to be sure it doesn't overflow the
2016 "portable" capacities of the compiler back end. `dummy' types
2017 can generally overflow the normal sizes as long as the computations
2018 themselves don't overflow. A particular target of the back end
2019 must still enforce its size requirements, though, and the back
2020 end takes care of this in stor-layout.c. */
2021
2022 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2023 static tree
2024 ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy)
2025 {
2026 if (TREE_CODE (type) == ERROR_MARK)
2027 return type;
2028
2029 if (TYPE_SIZE (type) == NULL_TREE)
2030 return type;
2031
2032 if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
2033 return type;
2034
2035 if ((tree_int_cst_sgn (TYPE_SIZE (type)) < 0)
2036 || (!dummy && (TREE_INT_CST_HIGH (TYPE_SIZE (type)) != 0))
2037 || TREE_OVERFLOW (TYPE_SIZE (type)))
2038 {
2039 ffebad_start (FFEBAD_ARRAY_LARGE);
2040 ffebad_string (ffesymbol_text (s));
2041 ffebad_here (0, ffesymbol_where_line (s), ffesymbol_where_column (s));
2042 ffebad_finish ();
2043
2044 return error_mark_node;
2045 }
2046
2047 return type;
2048 }
2049 #endif
2050
2051 /* Builds a length argument (PARM_DECL). Also wraps type in an array type
2052 where the dimension info is (1:size) where <size> is ffesymbol_size(s) if
2053 known, length_arg if not known (FFETARGET_charactersizeNONE). */
2054
2055 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2056 static tree
2057 ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s)
2058 {
2059 ffetargetCharacterSize sz = ffesymbol_size (s);
2060 tree highval;
2061 tree tlen;
2062 tree type = *xtype;
2063
2064 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
2065 tlen = NULL_TREE; /* A statement function, no length passed. */
2066 else
2067 {
2068 if (ffesymbol_where (s) == FFEINFO_whereDUMMY)
2069 tlen = ffecom_get_invented_identifier ("__g77_length_%s",
2070 ffesymbol_text (s), 0);
2071 else
2072 tlen = ffecom_get_invented_identifier ("__g77_%s",
2073 "length", 0);
2074 tlen = build_decl (PARM_DECL, tlen, ffecom_f2c_ftnlen_type_node);
2075 #if BUILT_FOR_270
2076 DECL_ARTIFICIAL (tlen) = 1;
2077 #endif
2078 }
2079
2080 if (sz == FFETARGET_charactersizeNONE)
2081 {
2082 assert (tlen != NULL_TREE);
2083 highval = tlen;
2084 }
2085 else
2086 {
2087 highval = build_int_2 (sz, 0);
2088 TREE_TYPE (highval) = ffecom_f2c_ftnlen_type_node;
2089 }
2090
2091 type = build_array_type (type,
2092 build_range_type (ffecom_f2c_ftnlen_type_node,
2093 ffecom_f2c_ftnlen_one_node,
2094 highval));
2095
2096 *xtype = type;
2097 return tlen;
2098 }
2099
2100 #endif
2101 /* ffecom_concat_list_gather_ -- Gather list of concatenated string exprs
2102
2103 ffecomConcatList_ catlist;
2104 ffebld expr; // expr of CHARACTER basictype.
2105 ffetargetCharacterSize max; // max chars to gather or _...NONE if no max
2106 catlist = ffecom_concat_list_gather_(catlist,expr,max);
2107
2108 Scans expr for character subexpressions, updates and returns catlist
2109 accordingly. */
2110
2111 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2112 static ffecomConcatList_
2113 ffecom_concat_list_gather_ (ffecomConcatList_ catlist, ffebld expr,
2114 ffetargetCharacterSize max)
2115 {
2116 ffetargetCharacterSize sz;
2117
2118 recurse: /* :::::::::::::::::::: */
2119
2120 if (expr == NULL)
2121 return catlist;
2122
2123 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen >= max))
2124 return catlist; /* Don't append any more items. */
2125
2126 switch (ffebld_op (expr))
2127 {
2128 case FFEBLD_opCONTER:
2129 case FFEBLD_opSYMTER:
2130 case FFEBLD_opARRAYREF:
2131 case FFEBLD_opFUNCREF:
2132 case FFEBLD_opSUBSTR:
2133 case FFEBLD_opCONVERT: /* Callers should strip this off beforehand
2134 if they don't need to preserve it. */
2135 if (catlist.count == catlist.max)
2136 { /* Make a (larger) list. */
2137 ffebld *newx;
2138 int newmax;
2139
2140 newmax = (catlist.max == 0) ? 8 : catlist.max * 2;
2141 newx = malloc_new_ks (malloc_pool_image (), "catlist",
2142 newmax * sizeof (newx[0]));
2143 if (catlist.max != 0)
2144 {
2145 memcpy (newx, catlist.exprs, catlist.max * sizeof (newx[0]));
2146 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2147 catlist.max * sizeof (newx[0]));
2148 }
2149 catlist.max = newmax;
2150 catlist.exprs = newx;
2151 }
2152 if ((sz = ffebld_size_known (expr)) != FFETARGET_charactersizeNONE)
2153 catlist.minlen += sz;
2154 else
2155 ++catlist.minlen; /* Not true for F90; can be 0 length. */
2156 if ((sz = ffebld_size_max (expr)) == FFETARGET_charactersizeNONE)
2157 catlist.maxlen = sz;
2158 else
2159 catlist.maxlen += sz;
2160 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen > max))
2161 { /* This item overlaps (or is beyond) the end
2162 of the destination. */
2163 switch (ffebld_op (expr))
2164 {
2165 case FFEBLD_opCONTER:
2166 case FFEBLD_opSYMTER:
2167 case FFEBLD_opARRAYREF:
2168 case FFEBLD_opFUNCREF:
2169 case FFEBLD_opSUBSTR:
2170 break; /* ~~Do useful truncations here. */
2171
2172 default:
2173 assert ("op changed or inconsistent switches!" == NULL);
2174 break;
2175 }
2176 }
2177 catlist.exprs[catlist.count++] = expr;
2178 return catlist;
2179
2180 case FFEBLD_opPAREN:
2181 expr = ffebld_left (expr);
2182 goto recurse; /* :::::::::::::::::::: */
2183
2184 case FFEBLD_opCONCATENATE:
2185 catlist = ffecom_concat_list_gather_ (catlist, ffebld_left (expr), max);
2186 expr = ffebld_right (expr);
2187 goto recurse; /* :::::::::::::::::::: */
2188
2189 #if 0 /* Breaks passing small actual arg to larger
2190 dummy arg of sfunc */
2191 case FFEBLD_opCONVERT:
2192 expr = ffebld_left (expr);
2193 {
2194 ffetargetCharacterSize cmax;
2195
2196 cmax = catlist.len + ffebld_size_known (expr);
2197
2198 if ((max == FFETARGET_charactersizeNONE) || (max > cmax))
2199 max = cmax;
2200 }
2201 goto recurse; /* :::::::::::::::::::: */
2202 #endif
2203
2204 case FFEBLD_opANY:
2205 return catlist;
2206
2207 default:
2208 assert ("bad op in _gather_" == NULL);
2209 return catlist;
2210 }
2211 }
2212
2213 #endif
2214 /* ffecom_concat_list_kill_ -- Kill list of concatenated string exprs
2215
2216 ffecomConcatList_ catlist;
2217 ffecom_concat_list_kill_(catlist);
2218
2219 Anything allocated within the list info is deallocated. */
2220
2221 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2222 static void
2223 ffecom_concat_list_kill_ (ffecomConcatList_ catlist)
2224 {
2225 if (catlist.max != 0)
2226 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2227 catlist.max * sizeof (catlist.exprs[0]));
2228 }
2229
2230 #endif
2231 /* ffecom_concat_list_new_ -- Make list of concatenated string exprs
2232
2233 ffecomConcatList_ catlist;
2234 ffebld expr; // Root expr of CHARACTER basictype.
2235 ffetargetCharacterSize max; // max chars to gather or _...NONE if no max
2236 catlist = ffecom_concat_list_new_(expr,max);
2237
2238 Returns a flattened list of concatenated subexpressions given a
2239 tree of such expressions. */
2240
2241 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2242 static ffecomConcatList_
2243 ffecom_concat_list_new_ (ffebld expr, ffetargetCharacterSize max)
2244 {
2245 ffecomConcatList_ catlist;
2246
2247 catlist.maxlen = catlist.minlen = catlist.max = catlist.count = 0;
2248 return ffecom_concat_list_gather_ (catlist, expr, max);
2249 }
2250
2251 #endif
2252
2253 /* Provide some kind of useful info on member of aggregate area,
2254 since current g77/gcc technology does not provide debug info
2255 on these members. */
2256
2257 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2258 static void
2259 ffecom_debug_kludge_ (tree aggr, char *aggr_type, ffesymbol member,
2260 tree member_type UNUSED, ffetargetOffset offset)
2261 {
2262 tree value;
2263 tree decl;
2264 int len;
2265 char *buff;
2266 char space[120];
2267 #if 0
2268 tree type_id;
2269
2270 for (type_id = member_type;
2271 TREE_CODE (type_id) != IDENTIFIER_NODE;
2272 )
2273 {
2274 switch (TREE_CODE (type_id))
2275 {
2276 case INTEGER_TYPE:
2277 case REAL_TYPE:
2278 type_id = TYPE_NAME (type_id);
2279 break;
2280
2281 case ARRAY_TYPE:
2282 case COMPLEX_TYPE:
2283 type_id = TREE_TYPE (type_id);
2284 break;
2285
2286 default:
2287 assert ("no IDENTIFIER_NODE for type!" == NULL);
2288 type_id = error_mark_node;
2289 break;
2290 }
2291 }
2292 #endif
2293
2294 if (ffecom_transform_only_dummies_
2295 || !ffe_is_debug_kludge ())
2296 return; /* Can't do this yet, maybe later. */
2297
2298 len = 60
2299 + strlen (aggr_type)
2300 + IDENTIFIER_LENGTH (DECL_NAME (aggr));
2301 #if 0
2302 + IDENTIFIER_LENGTH (type_id);
2303 #endif
2304
2305 if (((size_t) len) >= ARRAY_SIZE (space))
2306 buff = malloc_new_ks (malloc_pool_image (), "debug_kludge", len + 1);
2307 else
2308 buff = &space[0];
2309
2310 sprintf (&buff[0], "At (%s) `%s' plus %ld bytes",
2311 aggr_type,
2312 IDENTIFIER_POINTER (DECL_NAME (aggr)),
2313 (long int) offset);
2314
2315 value = build_string (len, buff);
2316 TREE_TYPE (value)
2317 = build_type_variant (build_array_type (char_type_node,
2318 build_range_type
2319 (integer_type_node,
2320 integer_one_node,
2321 build_int_2 (strlen (buff), 0))),
2322 1, 0);
2323 decl = build_decl (VAR_DECL,
2324 ffecom_get_identifier_ (ffesymbol_text (member)),
2325 TREE_TYPE (value));
2326 TREE_CONSTANT (decl) = 1;
2327 TREE_STATIC (decl) = 1;
2328 DECL_INITIAL (decl) = error_mark_node;
2329 DECL_IN_SYSTEM_HEADER (decl) = 1; /* Don't let -Wunused complain. */
2330 decl = start_decl (decl, FALSE);
2331 finish_decl (decl, value, FALSE);
2332
2333 if (buff != &space[0])
2334 malloc_kill_ks (malloc_pool_image (), buff, len + 1);
2335 }
2336 #endif
2337
2338 /* ffecom_do_entry_ -- Do compilation of a particular entrypoint
2339
2340 ffesymbol fn; // the SUBROUTINE, FUNCTION, or ENTRY symbol itself
2341 int i; // entry# for this entrypoint (used by master fn)
2342 ffecom_do_entrypoint_(s,i);
2343
2344 Makes a public entry point that calls our private master fn (already
2345 compiled). */
2346
2347 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2348 static void
2349 ffecom_do_entry_ (ffesymbol fn, int entrynum)
2350 {
2351 ffebld item;
2352 tree type; /* Type of function. */
2353 tree multi_retval; /* Var holding return value (union). */
2354 tree result; /* Var holding result. */
2355 ffeinfoBasictype bt;
2356 ffeinfoKindtype kt;
2357 ffeglobal g;
2358 ffeglobalType gt;
2359 bool charfunc; /* All entry points return same type
2360 CHARACTER. */
2361 bool cmplxfunc; /* Use f2c way of returning COMPLEX. */
2362 bool multi; /* Master fn has multiple return types. */
2363 bool altreturning = FALSE; /* This entry point has alternate returns. */
2364 int yes;
2365
2366 /* c-parse.y indeed does call suspend_momentary and not only ignores the
2367 return value, but also never calls resume_momentary, when starting an
2368 outer function (see "fndef:", "setspecs:", and so on). So g77 does the
2369 same thing. It shouldn't be a problem since start_function calls
2370 temporary_allocation, but it might be necessary. If it causes a problem
2371 here, then maybe there's a bug lurking in gcc. NOTE: This identical
2372 comment appears twice in thist file. */
2373
2374 suspend_momentary ();
2375
2376 ffecom_doing_entry_ = TRUE; /* Don't bother with array dimensions. */
2377
2378 switch (ffecom_primary_entry_kind_)
2379 {
2380 case FFEINFO_kindFUNCTION:
2381
2382 /* Determine actual return type for function. */
2383
2384 gt = FFEGLOBAL_typeFUNC;
2385 bt = ffesymbol_basictype (fn);
2386 kt = ffesymbol_kindtype (fn);
2387 if (bt == FFEINFO_basictypeNONE)
2388 {
2389 ffeimplic_establish_symbol (fn);
2390 if (ffesymbol_funcresult (fn) != NULL)
2391 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
2392 bt = ffesymbol_basictype (fn);
2393 kt = ffesymbol_kindtype (fn);
2394 }
2395
2396 if (bt == FFEINFO_basictypeCHARACTER)
2397 charfunc = TRUE, cmplxfunc = FALSE;
2398 else if ((bt == FFEINFO_basictypeCOMPLEX)
2399 && ffesymbol_is_f2c (fn))
2400 charfunc = FALSE, cmplxfunc = TRUE;
2401 else
2402 charfunc = cmplxfunc = FALSE;
2403
2404 if (charfunc)
2405 type = ffecom_tree_fun_type_void;
2406 else if (ffesymbol_is_f2c (fn))
2407 type = ffecom_tree_fun_type[bt][kt];
2408 else
2409 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
2410
2411 if ((type == NULL_TREE)
2412 || (TREE_TYPE (type) == NULL_TREE))
2413 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
2414
2415 multi = (ffecom_master_bt_ == FFEINFO_basictypeNONE);
2416 break;
2417
2418 case FFEINFO_kindSUBROUTINE:
2419 gt = FFEGLOBAL_typeSUBR;
2420 bt = FFEINFO_basictypeNONE;
2421 kt = FFEINFO_kindtypeNONE;
2422 if (ffecom_is_altreturning_)
2423 { /* Am _I_ altreturning? */
2424 for (item = ffesymbol_dummyargs (fn);
2425 item != NULL;
2426 item = ffebld_trail (item))
2427 {
2428 if (ffebld_op (ffebld_head (item)) == FFEBLD_opSTAR)
2429 {
2430 altreturning = TRUE;
2431 break;
2432 }
2433 }
2434 if (altreturning)
2435 type = ffecom_tree_subr_type;
2436 else
2437 type = ffecom_tree_fun_type_void;
2438 }
2439 else
2440 type = ffecom_tree_fun_type_void;
2441 charfunc = FALSE;
2442 cmplxfunc = FALSE;
2443 multi = FALSE;
2444 break;
2445
2446 default:
2447 assert ("say what??" == NULL);
2448 /* Fall through. */
2449 case FFEINFO_kindANY:
2450 gt = FFEGLOBAL_typeANY;
2451 bt = FFEINFO_basictypeNONE;
2452 kt = FFEINFO_kindtypeNONE;
2453 type = error_mark_node;
2454 charfunc = FALSE;
2455 cmplxfunc = FALSE;
2456 multi = FALSE;
2457 break;
2458 }
2459
2460 /* build_decl uses the current lineno and input_filename to set the decl
2461 source info. So, I've putzed with ffestd and ffeste code to update that
2462 source info to point to the appropriate statement just before calling
2463 ffecom_do_entrypoint (which calls this fn). */
2464
2465 start_function (ffecom_get_external_identifier_ (fn),
2466 type,
2467 0, /* nested/inline */
2468 1); /* TREE_PUBLIC */
2469
2470 if (((g = ffesymbol_global (fn)) != NULL)
2471 && ((ffeglobal_type (g) == gt)
2472 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
2473 {
2474 ffeglobal_set_hook (g, current_function_decl);
2475 }
2476
2477 /* Reset args in master arg list so they get retransitioned. */
2478
2479 for (item = ffecom_master_arglist_;
2480 item != NULL;
2481 item = ffebld_trail (item))
2482 {
2483 ffebld arg;
2484 ffesymbol s;
2485
2486 arg = ffebld_head (item);
2487 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2488 continue; /* Alternate return or some such thing. */
2489 s = ffebld_symter (arg);
2490 ffesymbol_hook (s).decl_tree = NULL_TREE;
2491 ffesymbol_hook (s).length_tree = NULL_TREE;
2492 }
2493
2494 /* Build dummy arg list for this entry point. */
2495
2496 yes = suspend_momentary ();
2497
2498 if (charfunc || cmplxfunc)
2499 { /* Prepend arg for where result goes. */
2500 tree type;
2501 tree length;
2502
2503 if (charfunc)
2504 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
2505 else
2506 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
2507
2508 result = ffecom_get_invented_identifier ("__g77_%s",
2509 "result", 0);
2510
2511 /* Make length arg _and_ enhance type info for CHAR arg itself. */
2512
2513 if (charfunc)
2514 length = ffecom_char_enhance_arg_ (&type, fn);
2515 else
2516 length = NULL_TREE; /* Not ref'd if !charfunc. */
2517
2518 type = build_pointer_type (type);
2519 result = build_decl (PARM_DECL, result, type);
2520
2521 push_parm_decl (result);
2522 ffecom_func_result_ = result;
2523
2524 if (charfunc)
2525 {
2526 push_parm_decl (length);
2527 ffecom_func_length_ = length;
2528 }
2529 }
2530 else
2531 result = DECL_RESULT (current_function_decl);
2532
2533 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (fn), FALSE);
2534
2535 resume_momentary (yes);
2536
2537 store_parm_decls (0);
2538
2539 ffecom_start_compstmt_ ();
2540
2541 /* Make local var to hold return type for multi-type master fn. */
2542
2543 if (multi)
2544 {
2545 yes = suspend_momentary ();
2546
2547 multi_retval = ffecom_get_invented_identifier ("__g77_%s",
2548 "multi_retval", 0);
2549 multi_retval = build_decl (VAR_DECL, multi_retval,
2550 ffecom_multi_type_node_);
2551 multi_retval = start_decl (multi_retval, FALSE);
2552 finish_decl (multi_retval, NULL_TREE, FALSE);
2553
2554 resume_momentary (yes);
2555 }
2556 else
2557 multi_retval = NULL_TREE; /* Not actually ref'd if !multi. */
2558
2559 /* Here we emit the actual code for the entry point. */
2560
2561 {
2562 ffebld list;
2563 ffebld arg;
2564 ffesymbol s;
2565 tree arglist = NULL_TREE;
2566 tree *plist = &arglist;
2567 tree prepend;
2568 tree call;
2569 tree actarg;
2570 tree master_fn;
2571
2572 /* Prepare actual arg list based on master arg list. */
2573
2574 for (list = ffecom_master_arglist_;
2575 list != NULL;
2576 list = ffebld_trail (list))
2577 {
2578 arg = ffebld_head (list);
2579 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2580 continue;
2581 s = ffebld_symter (arg);
2582 if (ffesymbol_hook (s).decl_tree == NULL_TREE)
2583 actarg = null_pointer_node; /* We don't have this arg. */
2584 else
2585 actarg = ffesymbol_hook (s).decl_tree;
2586 *plist = build_tree_list (NULL_TREE, actarg);
2587 plist = &TREE_CHAIN (*plist);
2588 }
2589
2590 /* This code appends the length arguments for character
2591 variables/arrays. */
2592
2593 for (list = ffecom_master_arglist_;
2594 list != NULL;
2595 list = ffebld_trail (list))
2596 {
2597 arg = ffebld_head (list);
2598 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2599 continue;
2600 s = ffebld_symter (arg);
2601 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
2602 continue; /* Only looking for CHARACTER arguments. */
2603 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
2604 continue; /* Only looking for variables and arrays. */
2605 if (ffesymbol_hook (s).length_tree == NULL_TREE)
2606 actarg = ffecom_f2c_ftnlen_zero_node; /* We don't have this arg. */
2607 else
2608 actarg = ffesymbol_hook (s).length_tree;
2609 *plist = build_tree_list (NULL_TREE, actarg);
2610 plist = &TREE_CHAIN (*plist);
2611 }
2612
2613 /* Prepend character-value return info to actual arg list. */
2614
2615 if (charfunc)
2616 {
2617 prepend = build_tree_list (NULL_TREE, ffecom_func_result_);
2618 TREE_CHAIN (prepend)
2619 = build_tree_list (NULL_TREE, ffecom_func_length_);
2620 TREE_CHAIN (TREE_CHAIN (prepend)) = arglist;
2621 arglist = prepend;
2622 }
2623
2624 /* Prepend multi-type return value to actual arg list. */
2625
2626 if (multi)
2627 {
2628 prepend
2629 = build_tree_list (NULL_TREE,
2630 ffecom_1 (ADDR_EXPR,
2631 build_pointer_type (TREE_TYPE (multi_retval)),
2632 multi_retval));
2633 TREE_CHAIN (prepend) = arglist;
2634 arglist = prepend;
2635 }
2636
2637 /* Prepend my entry-point number to the actual arg list. */
2638
2639 prepend = build_tree_list (NULL_TREE, build_int_2 (entrynum, 0));
2640 TREE_CHAIN (prepend) = arglist;
2641 arglist = prepend;
2642
2643 /* Build the call to the master function. */
2644
2645 master_fn = ffecom_1_fn (ffecom_previous_function_decl_);
2646 call = ffecom_3s (CALL_EXPR,
2647 TREE_TYPE (TREE_TYPE (TREE_TYPE (master_fn))),
2648 master_fn, arglist, NULL_TREE);
2649
2650 /* Decide whether the master function is a function or subroutine, and
2651 handle the return value for my entry point. */
2652
2653 if (charfunc || ((ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
2654 && !altreturning))
2655 {
2656 expand_expr_stmt (call);
2657 expand_null_return ();
2658 }
2659 else if (multi && cmplxfunc)
2660 {
2661 expand_expr_stmt (call);
2662 result
2663 = ffecom_1 (INDIRECT_REF,
2664 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
2665 result);
2666 result = ffecom_modify (NULL_TREE, result,
2667 ffecom_2 (COMPONENT_REF, TREE_TYPE (result),
2668 multi_retval,
2669 ffecom_multi_fields_[bt][kt]));
2670 expand_expr_stmt (result);
2671 expand_null_return ();
2672 }
2673 else if (multi)
2674 {
2675 expand_expr_stmt (call);
2676 result
2677 = ffecom_modify (NULL_TREE, result,
2678 convert (TREE_TYPE (result),
2679 ffecom_2 (COMPONENT_REF,
2680 ffecom_tree_type[bt][kt],
2681 multi_retval,
2682 ffecom_multi_fields_[bt][kt])));
2683 expand_return (result);
2684 }
2685 else if (cmplxfunc)
2686 {
2687 result
2688 = ffecom_1 (INDIRECT_REF,
2689 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
2690 result);
2691 result = ffecom_modify (NULL_TREE, result, call);
2692 expand_expr_stmt (result);
2693 expand_null_return ();
2694 }
2695 else
2696 {
2697 result = ffecom_modify (NULL_TREE,
2698 result,
2699 convert (TREE_TYPE (result),
2700 call));
2701 expand_return (result);
2702 }
2703
2704 clear_momentary ();
2705 }
2706
2707 ffecom_end_compstmt_ ();
2708
2709 finish_function (0);
2710
2711 ffecom_doing_entry_ = FALSE;
2712 }
2713
2714 #endif
2715 /* Transform expr into gcc tree with possible destination
2716
2717 Recursive descent on expr while making corresponding tree nodes and
2718 attaching type info and such. If destination supplied and compatible
2719 with temporary that would be made in certain cases, temporary isn't
2720 made, destination used instead, and dest_used flag set TRUE.
2721
2722 If TREE_TYPE is non-null, it overrides the type that the expression
2723 would normally be computed in. This is most useful for array indices
2724 which should be done in sizetype for efficiency. */
2725
2726 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2727 static tree
2728 ffecom_expr_ (ffebld expr, tree tree_type_x, tree dest_tree,
2729 ffebld dest, bool *dest_used,
2730 bool assignp)
2731 {
2732 tree item;
2733 tree list;
2734 tree args;
2735 ffeinfoBasictype bt;
2736 ffeinfoKindtype kt;
2737 tree t;
2738 tree dt; /* decl_tree for an ffesymbol. */
2739 tree tree_type;
2740 tree left, right;
2741 ffesymbol s;
2742 enum tree_code code;
2743
2744 assert (expr != NULL);
2745
2746 if (dest_used != NULL)
2747 *dest_used = FALSE;
2748
2749 bt = ffeinfo_basictype (ffebld_info (expr));
2750 kt = ffeinfo_kindtype (ffebld_info (expr));
2751 tree_type = ffecom_tree_type[bt][kt];
2752
2753 switch (ffebld_op (expr))
2754 {
2755 case FFEBLD_opACCTER:
2756 {
2757 ffebitCount i;
2758 ffebit bits = ffebld_accter_bits (expr);
2759 ffetargetOffset source_offset = 0;
2760 size_t size;
2761 tree purpose;
2762
2763 size = ffetype_size (ffeinfo_type (bt, kt));
2764
2765 list = item = NULL;
2766 for (;;)
2767 {
2768 ffebldConstantUnion cu;
2769 ffebitCount length;
2770 bool value;
2771 ffebldConstantArray ca = ffebld_accter (expr);
2772
2773 ffebit_test (bits, source_offset, &value, &length);
2774 if (length == 0)
2775 break;
2776
2777 if (value)
2778 {
2779 for (i = 0; i < length; ++i)
2780 {
2781 cu = ffebld_constantarray_get (ca, bt, kt,
2782 source_offset + i);
2783
2784 t = ffecom_constantunion (&cu, bt, kt, tree_type);
2785
2786 if (i == 0)
2787 purpose = build_int_2 (source_offset, 0);
2788 else
2789 purpose = NULL_TREE;
2790
2791 if (list == NULL_TREE)
2792 list = item = build_tree_list (purpose, t);
2793 else
2794 {
2795 TREE_CHAIN (item) = build_tree_list (purpose, t);
2796 item = TREE_CHAIN (item);
2797 }
2798 }
2799 }
2800 source_offset += length;
2801 }
2802 }
2803
2804 item = build_int_2 (ffebld_accter_size (expr), 0);
2805 ffebit_kill (ffebld_accter_bits (expr));
2806 TREE_TYPE (item) = ffecom_integer_type_node;
2807 item
2808 = build_array_type
2809 (tree_type,
2810 build_range_type (ffecom_integer_type_node,
2811 ffecom_integer_zero_node,
2812 item));
2813 list = build (CONSTRUCTOR, item, NULL_TREE, list);
2814 TREE_CONSTANT (list) = 1;
2815 TREE_STATIC (list) = 1;
2816 return list;
2817
2818 case FFEBLD_opARRTER:
2819 {
2820 ffetargetOffset i;
2821
2822 list = item = NULL_TREE;
2823 for (i = 0; i < ffebld_arrter_size (expr); ++i)
2824 {
2825 ffebldConstantUnion cu
2826 = ffebld_constantarray_get (ffebld_arrter (expr), bt, kt, i);
2827
2828 t = ffecom_constantunion (&cu, bt, kt, tree_type);
2829
2830 if (list == NULL_TREE)
2831 list = item = build_tree_list (NULL_TREE, t);
2832 else
2833 {
2834 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
2835 item = TREE_CHAIN (item);
2836 }
2837 }
2838 }
2839
2840 item = build_int_2 (ffebld_arrter_size (expr), 0);
2841 TREE_TYPE (item) = ffecom_integer_type_node;
2842 item
2843 = build_array_type
2844 (tree_type,
2845 build_range_type (ffecom_integer_type_node,
2846 ffecom_integer_one_node,
2847 item));
2848 list = build (CONSTRUCTOR, item, NULL_TREE, list);
2849 TREE_CONSTANT (list) = 1;
2850 TREE_STATIC (list) = 1;
2851 return list;
2852
2853 case FFEBLD_opCONTER:
2854 item
2855 = ffecom_constantunion (&ffebld_constant_union (ffebld_conter (expr)),
2856 bt, kt, tree_type);
2857 return item;
2858
2859 case FFEBLD_opSYMTER:
2860 if ((ffebld_symter_generic (expr) != FFEINTRIN_genNONE)
2861 || (ffebld_symter_specific (expr) != FFEINTRIN_specNONE))
2862 return ffecom_ptr_to_expr (expr); /* Same as %REF(intrinsic). */
2863 s = ffebld_symter (expr);
2864 t = ffesymbol_hook (s).decl_tree;
2865
2866 if (assignp)
2867 { /* ASSIGN'ed-label expr. */
2868 if (ffe_is_ugly_assign ())
2869 {
2870 /* User explicitly wants ASSIGN'ed variables to be at the same
2871 memory address as the variables when used in non-ASSIGN
2872 contexts. That can make old, arcane, non-standard code
2873 work, but don't try to do it when a pointer wouldn't fit
2874 in the normal variable (take other approach, and warn,
2875 instead). */
2876
2877 if (t == NULL_TREE)
2878 {
2879 s = ffecom_sym_transform_ (s);
2880 t = ffesymbol_hook (s).decl_tree;
2881 assert (t != NULL_TREE);
2882 }
2883
2884 if (t == error_mark_node)
2885 return t;
2886
2887 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (t)))
2888 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
2889 {
2890 if (ffesymbol_hook (s).addr)
2891 t = ffecom_1 (INDIRECT_REF,
2892 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
2893 return t;
2894 }
2895
2896 if (ffesymbol_hook (s).assign_tree == NULL_TREE)
2897 {
2898 ffebad_start_msg ("ASSIGN'ed label cannot fit into `%A' at %0 -- using wider sibling",
2899 FFEBAD_severityWARNING);
2900 ffebad_string (ffesymbol_text (s));
2901 ffebad_here (0, ffesymbol_where_line (s),
2902 ffesymbol_where_column (s));
2903 ffebad_finish ();
2904 }
2905 }
2906
2907 /* Don't use the normal variable's tree for ASSIGN, though mark
2908 it as in the system header (housekeeping). Use an explicit,
2909 specially created sibling that is known to be wide enough
2910 to hold pointers to labels. */
2911
2912 if (t != NULL_TREE
2913 && TREE_CODE (t) == VAR_DECL)
2914 DECL_IN_SYSTEM_HEADER (t) = 1; /* Don't let -Wunused complain. */
2915
2916 t = ffesymbol_hook (s).assign_tree;
2917 if (t == NULL_TREE)
2918 {
2919 s = ffecom_sym_transform_assign_ (s);
2920 t = ffesymbol_hook (s).assign_tree;
2921 assert (t != NULL_TREE);
2922 }
2923 }
2924 else
2925 {
2926 if (t == NULL_TREE)
2927 {
2928 s = ffecom_sym_transform_ (s);
2929 t = ffesymbol_hook (s).decl_tree;
2930 assert (t != NULL_TREE);
2931 }
2932 if (ffesymbol_hook (s).addr)
2933 t = ffecom_1 (INDIRECT_REF,
2934 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
2935 }
2936 return t;
2937
2938 case FFEBLD_opARRAYREF:
2939 {
2940 ffebld dims[FFECOM_dimensionsMAX];
2941 #if FFECOM_FASTER_ARRAY_REFS
2942 tree array;
2943 #endif
2944 int i;
2945
2946 #if FFECOM_FASTER_ARRAY_REFS
2947 t = ffecom_ptr_to_expr (ffebld_left (expr));
2948 #else
2949 t = ffecom_expr (ffebld_left (expr));
2950 #endif
2951 if (t == error_mark_node)
2952 return t;
2953
2954 if ((ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereFLEETING)
2955 && !mark_addressable (t))
2956 return error_mark_node; /* Make sure non-const ref is to
2957 non-reg. */
2958
2959 /* Build up ARRAY_REFs in reverse order (since we're column major
2960 here in Fortran land). */
2961
2962 for (i = 0, expr = ffebld_right (expr);
2963 expr != NULL;
2964 expr = ffebld_trail (expr))
2965 dims[i++] = ffebld_head (expr);
2966
2967 #if FFECOM_FASTER_ARRAY_REFS
2968 for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t)));
2969 i >= 0;
2970 --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
2971 t = ffecom_2 (PLUS_EXPR,
2972 build_pointer_type (TREE_TYPE (array)),
2973 t,
2974 size_binop (MULT_EXPR,
2975 size_in_bytes (TREE_TYPE (array)),
2976 size_binop (MINUS_EXPR,
2977 ffecom_expr (dims[i]),
2978 TYPE_MIN_VALUE (TYPE_DOMAIN (array)))));
2979 t = ffecom_1 (INDIRECT_REF,
2980 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))),
2981 t);
2982 #else
2983 while (i > 0)
2984 t = ffecom_2 (ARRAY_REF,
2985 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))),
2986 t,
2987 ffecom_expr_ (dims[--i], sizetype, NULL, NULL,
2988 NULL, FALSE));
2989 #endif
2990
2991 return t;
2992 }
2993
2994 case FFEBLD_opUPLUS:
2995 left = ffecom_expr_ (ffebld_left (expr), tree_type_x, NULL, NULL,
2996 NULL, FALSE);
2997 return ffecom_1 (NOP_EXPR, tree_type, left);
2998
2999 case FFEBLD_opPAREN: /* ~~~Make sure Fortran rules respected here */
3000 left = ffecom_expr_ (ffebld_left (expr), tree_type_x, NULL, NULL,
3001 NULL, FALSE);
3002 return ffecom_1 (NOP_EXPR, tree_type, left);
3003
3004 case FFEBLD_opUMINUS:
3005 left = ffecom_expr_ (ffebld_left (expr), tree_type_x, NULL, NULL,
3006 NULL, FALSE);
3007 if (tree_type_x)
3008 {
3009 tree_type = tree_type_x;
3010 left = convert (tree_type, left);
3011 }
3012 return ffecom_1 (NEGATE_EXPR, tree_type, left);
3013
3014 case FFEBLD_opADD:
3015 left = ffecom_expr_ (ffebld_left (expr), tree_type_x, NULL, NULL,
3016 NULL, FALSE);
3017 right = ffecom_expr_ (ffebld_right (expr), tree_type_x, NULL, NULL,
3018 NULL, FALSE);
3019 if (tree_type_x)
3020 {
3021 tree_type = tree_type_x;
3022 left = convert (tree_type, left);
3023 right = convert (tree_type, right);
3024 }
3025 return ffecom_2 (PLUS_EXPR, tree_type, left, right);
3026
3027 case FFEBLD_opSUBTRACT:
3028 left = ffecom_expr_ (ffebld_left (expr), tree_type_x, NULL, NULL,
3029 NULL, FALSE);
3030 right = ffecom_expr_ (ffebld_right (expr), tree_type_x, NULL, NULL,
3031 NULL, FALSE);
3032 if (tree_type_x)
3033 {
3034 tree_type = tree_type_x;
3035 left = convert (tree_type, left);
3036 right = convert (tree_type, right);
3037 }
3038 return ffecom_2 (MINUS_EXPR, tree_type, left, right);
3039
3040 case FFEBLD_opMULTIPLY:
3041 left = ffecom_expr_ (ffebld_left (expr), tree_type_x, NULL, NULL,
3042 NULL, FALSE);
3043 right = ffecom_expr_ (ffebld_right (expr), tree_type_x, NULL, NULL,
3044 NULL, FALSE);
3045 if (tree_type_x)
3046 {
3047 tree_type = tree_type_x;
3048 left = convert (tree_type, left);
3049 right = convert (tree_type, right);
3050 }
3051 return ffecom_2 (MULT_EXPR, tree_type, left, right);
3052
3053 case FFEBLD_opDIVIDE:
3054 left = ffecom_expr_ (ffebld_left (expr), tree_type_x, NULL, NULL,
3055 NULL, FALSE);
3056 right = ffecom_expr_ (ffebld_right (expr), tree_type_x, NULL, NULL,
3057 NULL, FALSE);
3058 if (tree_type_x)
3059 {
3060 tree_type = tree_type_x;
3061 left = convert (tree_type, left);
3062 right = convert (tree_type, right);
3063 }
3064 return ffecom_tree_divide_ (tree_type, left, right,
3065 dest_tree, dest, dest_used);
3066
3067 case FFEBLD_opPOWER:
3068 {
3069 ffebld left = ffebld_left (expr);
3070 ffebld right = ffebld_right (expr);
3071 ffecomGfrt code;
3072 ffeinfoKindtype rtkt;
3073
3074 switch (ffeinfo_basictype (ffebld_info (right)))
3075 {
3076 case FFEINFO_basictypeINTEGER:
3077 if (1 || optimize)
3078 {
3079 item = ffecom_expr_power_integer_ (left, right);
3080 if (item != NULL_TREE)
3081 return item;
3082 }
3083
3084 rtkt = FFEINFO_kindtypeINTEGER1;
3085 switch (ffeinfo_basictype (ffebld_info (left)))
3086 {
3087 case FFEINFO_basictypeINTEGER:
3088 if ((ffeinfo_kindtype (ffebld_info (left))
3089 == FFEINFO_kindtypeINTEGER4)
3090 || (ffeinfo_kindtype (ffebld_info (right))
3091 == FFEINFO_kindtypeINTEGER4))
3092 {
3093 code = FFECOM_gfrtPOW_QQ;
3094 rtkt = FFEINFO_kindtypeINTEGER4;
3095 }
3096 else
3097 code = FFECOM_gfrtPOW_II;
3098 break;
3099
3100 case FFEINFO_basictypeREAL:
3101 if (ffeinfo_kindtype (ffebld_info (left))
3102 == FFEINFO_kindtypeREAL1)
3103 code = FFECOM_gfrtPOW_RI;
3104 else
3105 code = FFECOM_gfrtPOW_DI;
3106 break;
3107
3108 case FFEINFO_basictypeCOMPLEX:
3109 if (ffeinfo_kindtype (ffebld_info (left))
3110 == FFEINFO_kindtypeREAL1)
3111 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
3112 else
3113 code = FFECOM_gfrtPOW_ZI; /* Overlapping result okay. */
3114 break;
3115
3116 default:
3117 assert ("bad pow_*i" == NULL);
3118 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
3119 break;
3120 }
3121 if (ffeinfo_kindtype (ffebld_info (left)) != rtkt)
3122 left = ffeexpr_convert (left, NULL, NULL,
3123 FFEINFO_basictypeINTEGER,
3124 rtkt, 0,
3125 FFETARGET_charactersizeNONE,
3126 FFEEXPR_contextLET);
3127 if (ffeinfo_kindtype (ffebld_info (right)) != rtkt)
3128 right = ffeexpr_convert (right, NULL, NULL,
3129 FFEINFO_basictypeINTEGER,
3130 rtkt, 0,
3131 FFETARGET_charactersizeNONE,
3132 FFEEXPR_contextLET);
3133 break;
3134
3135 case FFEINFO_basictypeREAL:
3136 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3137 left = ffeexpr_convert (left, NULL, NULL, FFEINFO_basictypeREAL,
3138 FFEINFO_kindtypeREALDOUBLE, 0,
3139 FFETARGET_charactersizeNONE,
3140 FFEEXPR_contextLET);
3141 if (ffeinfo_kindtype (ffebld_info (right))
3142 == FFEINFO_kindtypeREAL1)
3143 right = ffeexpr_convert (right, NULL, NULL,
3144 FFEINFO_basictypeREAL,
3145 FFEINFO_kindtypeREALDOUBLE, 0,
3146 FFETARGET_charactersizeNONE,
3147 FFEEXPR_contextLET);
3148 code = FFECOM_gfrtPOW_DD;
3149 break;
3150
3151 case FFEINFO_basictypeCOMPLEX:
3152 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3153 left = ffeexpr_convert (left, NULL, NULL,
3154 FFEINFO_basictypeCOMPLEX,
3155 FFEINFO_kindtypeREALDOUBLE, 0,
3156 FFETARGET_charactersizeNONE,
3157 FFEEXPR_contextLET);
3158 if (ffeinfo_kindtype (ffebld_info (right))
3159 == FFEINFO_kindtypeREAL1)
3160 right = ffeexpr_convert (right, NULL, NULL,
3161 FFEINFO_basictypeCOMPLEX,
3162 FFEINFO_kindtypeREALDOUBLE, 0,
3163 FFETARGET_charactersizeNONE,
3164 FFEEXPR_contextLET);
3165 code = FFECOM_gfrtPOW_ZZ; /* Overlapping result okay. */
3166 break;
3167
3168 default:
3169 assert ("bad pow_x*" == NULL);
3170 code = FFECOM_gfrtPOW_II;
3171 break;
3172 }
3173 return ffecom_call_binop_ (ffecom_gfrt_tree_ (code),
3174 ffecom_gfrt_kindtype (code),
3175 (ffe_is_f2c_library ()
3176 && ffecom_gfrt_complex_[code]),
3177 tree_type, left, right,
3178 dest_tree, dest, dest_used,
3179 NULL_TREE, FALSE);
3180 }
3181
3182 case FFEBLD_opNOT:
3183 switch (bt)
3184 {
3185 case FFEINFO_basictypeLOGICAL:
3186 item = ffecom_truth_value_invert (ffecom_expr (ffebld_left (expr)));
3187 return convert (tree_type, item);
3188
3189 case FFEINFO_basictypeINTEGER:
3190 return ffecom_1 (BIT_NOT_EXPR, tree_type,
3191 ffecom_expr (ffebld_left (expr)));
3192
3193 default:
3194 assert ("NOT bad basictype" == NULL);
3195 /* Fall through. */
3196 case FFEINFO_basictypeANY:
3197 return error_mark_node;
3198 }
3199 break;
3200
3201 case FFEBLD_opFUNCREF:
3202 assert (ffeinfo_basictype (ffebld_info (expr))
3203 != FFEINFO_basictypeCHARACTER);
3204 /* Fall through. */
3205 case FFEBLD_opSUBRREF:
3206 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
3207 == FFEINFO_whereINTRINSIC)
3208 { /* Invocation of an intrinsic. */
3209 item = ffecom_expr_intrinsic_ (expr, dest_tree, dest,
3210 dest_used);
3211 return item;
3212 }
3213 s = ffebld_symter (ffebld_left (expr));
3214 dt = ffesymbol_hook (s).decl_tree;
3215 if (dt == NULL_TREE)
3216 {
3217 s = ffecom_sym_transform_ (s);
3218 dt = ffesymbol_hook (s).decl_tree;
3219 }
3220 if (dt == error_mark_node)
3221 return dt;
3222
3223 if (ffesymbol_hook (s).addr)
3224 item = dt;
3225 else
3226 item = ffecom_1_fn (dt);
3227
3228 ffecom_push_calltemps ();
3229 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
3230 args = ffecom_list_expr (ffebld_right (expr));
3231 else
3232 args = ffecom_list_ptr_to_expr (ffebld_right (expr));
3233 ffecom_pop_calltemps ();
3234
3235 item = ffecom_call_ (item, kt,
3236 ffesymbol_is_f2c (s)
3237 && (bt == FFEINFO_basictypeCOMPLEX)
3238 && (ffesymbol_where (s)
3239 != FFEINFO_whereCONSTANT),
3240 tree_type,
3241 args,
3242 dest_tree, dest, dest_used,
3243 error_mark_node, FALSE);
3244 TREE_SIDE_EFFECTS (item) = 1;
3245 return item;
3246
3247 case FFEBLD_opAND:
3248 switch (bt)
3249 {
3250 case FFEINFO_basictypeLOGICAL:
3251 item
3252 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3253 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3254 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3255 return convert (tree_type, item);
3256
3257 case FFEINFO_basictypeINTEGER:
3258 return ffecom_2 (BIT_AND_EXPR, tree_type,
3259 ffecom_expr (ffebld_left (expr)),
3260 ffecom_expr (ffebld_right (expr)));
3261
3262 default:
3263 assert ("AND bad basictype" == NULL);
3264 /* Fall through. */
3265 case FFEINFO_basictypeANY:
3266 return error_mark_node;
3267 }
3268 break;
3269
3270 case FFEBLD_opOR:
3271 switch (bt)
3272 {
3273 case FFEINFO_basictypeLOGICAL:
3274 item
3275 = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
3276 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3277 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3278 return convert (tree_type, item);
3279
3280 case FFEINFO_basictypeINTEGER:
3281 return ffecom_2 (BIT_IOR_EXPR, tree_type,
3282 ffecom_expr (ffebld_left (expr)),
3283 ffecom_expr (ffebld_right (expr)));
3284
3285 default:
3286 assert ("OR bad basictype" == NULL);
3287 /* Fall through. */
3288 case FFEINFO_basictypeANY:
3289 return error_mark_node;
3290 }
3291 break;
3292
3293 case FFEBLD_opXOR:
3294 case FFEBLD_opNEQV:
3295 switch (bt)
3296 {
3297 case FFEINFO_basictypeLOGICAL:
3298 item
3299 = ffecom_2 (NE_EXPR, integer_type_node,
3300 ffecom_expr (ffebld_left (expr)),
3301 ffecom_expr (ffebld_right (expr)));
3302 return convert (tree_type, ffecom_truth_value (item));
3303
3304 case FFEINFO_basictypeINTEGER:
3305 return ffecom_2 (BIT_XOR_EXPR, tree_type,
3306 ffecom_expr (ffebld_left (expr)),
3307 ffecom_expr (ffebld_right (expr)));
3308
3309 default:
3310 assert ("XOR/NEQV bad basictype" == NULL);
3311 /* Fall through. */
3312 case FFEINFO_basictypeANY:
3313 return error_mark_node;
3314 }
3315 break;
3316
3317 case FFEBLD_opEQV:
3318 switch (bt)
3319 {
3320 case FFEINFO_basictypeLOGICAL:
3321 item
3322 = ffecom_2 (EQ_EXPR, integer_type_node,
3323 ffecom_expr (ffebld_left (expr)),
3324 ffecom_expr (ffebld_right (expr)));
3325 return convert (tree_type, ffecom_truth_value (item));
3326
3327 case FFEINFO_basictypeINTEGER:
3328 return
3329 ffecom_1 (BIT_NOT_EXPR, tree_type,
3330 ffecom_2 (BIT_XOR_EXPR, tree_type,
3331 ffecom_expr (ffebld_left (expr)),
3332 ffecom_expr (ffebld_right (expr))));
3333
3334 default:
3335 assert ("EQV bad basictype" == NULL);
3336 /* Fall through. */
3337 case FFEINFO_basictypeANY:
3338 return error_mark_node;
3339 }
3340 break;
3341
3342 case FFEBLD_opCONVERT:
3343 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opANY)
3344 return error_mark_node;
3345
3346 switch (bt)
3347 {
3348 case FFEINFO_basictypeLOGICAL:
3349 case FFEINFO_basictypeINTEGER:
3350 case FFEINFO_basictypeREAL:
3351 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3352
3353 case FFEINFO_basictypeCOMPLEX:
3354 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3355 {
3356 case FFEINFO_basictypeINTEGER:
3357 case FFEINFO_basictypeLOGICAL:
3358 case FFEINFO_basictypeREAL:
3359 item = ffecom_expr (ffebld_left (expr));
3360 if (item == error_mark_node)
3361 return error_mark_node;
3362 /* convert() takes care of converting to the subtype first,
3363 at least in gcc-2.7.2. */
3364 item = convert (tree_type, item);
3365 return item;
3366
3367 case FFEINFO_basictypeCOMPLEX:
3368 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3369
3370 default:
3371 assert ("CONVERT COMPLEX bad basictype" == NULL);
3372 /* Fall through. */
3373 case FFEINFO_basictypeANY:
3374 return error_mark_node;
3375 }
3376 break;
3377
3378 default:
3379 assert ("CONVERT bad basictype" == NULL);
3380 /* Fall through. */
3381 case FFEINFO_basictypeANY:
3382 return error_mark_node;
3383 }
3384 break;
3385
3386 case FFEBLD_opLT:
3387 code = LT_EXPR;
3388 goto relational; /* :::::::::::::::::::: */
3389
3390 case FFEBLD_opLE:
3391 code = LE_EXPR;
3392 goto relational; /* :::::::::::::::::::: */
3393
3394 case FFEBLD_opEQ:
3395 code = EQ_EXPR;
3396 goto relational; /* :::::::::::::::::::: */
3397
3398 case FFEBLD_opNE:
3399 code = NE_EXPR;
3400 goto relational; /* :::::::::::::::::::: */
3401
3402 case FFEBLD_opGT:
3403 code = GT_EXPR;
3404 goto relational; /* :::::::::::::::::::: */
3405
3406 case FFEBLD_opGE:
3407 code = GE_EXPR;
3408
3409 relational: /* :::::::::::::::::::: */
3410 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3411 {
3412 case FFEINFO_basictypeLOGICAL:
3413 case FFEINFO_basictypeINTEGER:
3414 case FFEINFO_basictypeREAL:
3415 item = ffecom_2 (code, integer_type_node,
3416 ffecom_expr (ffebld_left (expr)),
3417 ffecom_expr (ffebld_right (expr)));
3418 return convert (tree_type, item);
3419
3420 case FFEINFO_basictypeCOMPLEX:
3421 assert (code == EQ_EXPR || code == NE_EXPR);
3422 {
3423 tree real_type;
3424 tree arg1 = ffecom_expr (ffebld_left (expr));
3425 tree arg2 = ffecom_expr (ffebld_right (expr));
3426
3427 if (arg1 == error_mark_node || arg2 == error_mark_node)
3428 return error_mark_node;
3429
3430 arg1 = ffecom_save_tree (arg1);
3431 arg2 = ffecom_save_tree (arg2);
3432
3433 if (TREE_CODE (TREE_TYPE (arg1)) == COMPLEX_TYPE)
3434 {
3435 real_type = TREE_TYPE (TREE_TYPE (arg1));
3436 assert (real_type == TREE_TYPE (TREE_TYPE (arg2)));
3437 }
3438 else
3439 {
3440 real_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg1)));
3441 assert (real_type == TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg2))));
3442 }
3443
3444 item
3445 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3446 ffecom_2 (EQ_EXPR, integer_type_node,
3447 ffecom_1 (REALPART_EXPR, real_type, arg1),
3448 ffecom_1 (REALPART_EXPR, real_type, arg2)),
3449 ffecom_2 (EQ_EXPR, integer_type_node,
3450 ffecom_1 (IMAGPART_EXPR, real_type, arg1),
3451 ffecom_1 (IMAGPART_EXPR, real_type,
3452 arg2)));
3453 if (code == EQ_EXPR)
3454 item = ffecom_truth_value (item);
3455 else
3456 item = ffecom_truth_value_invert (item);
3457 return convert (tree_type, item);
3458 }
3459
3460 case FFEINFO_basictypeCHARACTER:
3461 ffecom_push_calltemps (); /* Even though we might not call. */
3462
3463 {
3464 ffebld left = ffebld_left (expr);
3465 ffebld right = ffebld_right (expr);
3466 tree left_tree;
3467 tree right_tree;
3468 tree left_length;
3469 tree right_length;
3470
3471 /* f2c run-time functions do the implicit blank-padding for us,
3472 so we don't usually have to implement blank-padding ourselves.
3473 (The exception is when we pass an argument to a separately
3474 compiled statement function -- if we know the arg is not the
3475 same length as the dummy, we must truncate or extend it. If
3476 we "inline" statement functions, that necessity goes away as
3477 well.)
3478
3479 Strip off the CONVERT operators that blank-pad. (Truncation by
3480 CONVERT shouldn't happen here, but it can happen in
3481 assignments.) */
3482
3483 while (ffebld_op (left) == FFEBLD_opCONVERT)
3484 left = ffebld_left (left);
3485 while (ffebld_op (right) == FFEBLD_opCONVERT)
3486 right = ffebld_left (right);
3487
3488 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
3489 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
3490
3491 if (left_tree == error_mark_node || left_length == error_mark_node
3492 || right_tree == error_mark_node
3493 || right_length == error_mark_node)
3494 {
3495 ffecom_pop_calltemps ();
3496 return error_mark_node;
3497 }
3498
3499 if ((ffebld_size_known (left) == 1)
3500 && (ffebld_size_known (right) == 1))
3501 {
3502 left_tree
3503 = ffecom_1 (INDIRECT_REF,
3504 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3505 left_tree);
3506 right_tree
3507 = ffecom_1 (INDIRECT_REF,
3508 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3509 right_tree);
3510
3511 item
3512 = ffecom_2 (code, integer_type_node,
3513 ffecom_2 (ARRAY_REF,
3514 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3515 left_tree,
3516 integer_one_node),
3517 ffecom_2 (ARRAY_REF,
3518 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3519 right_tree,
3520 integer_one_node));
3521 }
3522 else
3523 {
3524 item = build_tree_list (NULL_TREE, left_tree);
3525 TREE_CHAIN (item) = build_tree_list (NULL_TREE, right_tree);
3526 TREE_CHAIN (TREE_CHAIN (item)) = build_tree_list (NULL_TREE,
3527 left_length);
3528 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
3529 = build_tree_list (NULL_TREE, right_length);
3530 item = ffecom_call_gfrt (FFECOM_gfrtCMP, item);
3531 item = ffecom_2 (code, integer_type_node,
3532 item,
3533 convert (TREE_TYPE (item),
3534 integer_zero_node));
3535 }
3536 item = convert (tree_type, item);
3537 }
3538
3539 ffecom_pop_calltemps ();
3540 return item;
3541
3542 default:
3543 assert ("relational bad basictype" == NULL);
3544 /* Fall through. */
3545 case FFEINFO_basictypeANY:
3546 return error_mark_node;
3547 }
3548 break;
3549
3550 case FFEBLD_opPERCENT_LOC:
3551 item = ffecom_arg_ptr_to_expr (ffebld_left (expr), &list);
3552 return convert (tree_type, item);
3553
3554 case FFEBLD_opITEM:
3555 case FFEBLD_opSTAR:
3556 case FFEBLD_opBOUNDS:
3557 case FFEBLD_opREPEAT:
3558 case FFEBLD_opLABTER:
3559 case FFEBLD_opLABTOK:
3560 case FFEBLD_opIMPDO:
3561 case FFEBLD_opCONCATENATE:
3562 case FFEBLD_opSUBSTR:
3563 default:
3564 assert ("bad op" == NULL);
3565 /* Fall through. */
3566 case FFEBLD_opANY:
3567 return error_mark_node;
3568 }
3569
3570 #if 1
3571 assert ("didn't think anything got here anymore!!" == NULL);
3572 #else
3573 switch (ffebld_arity (expr))
3574 {
3575 case 2:
3576 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3577 TREE_OPERAND (item, 1) = ffecom_expr (ffebld_right (expr));
3578 if (TREE_OPERAND (item, 0) == error_mark_node
3579 || TREE_OPERAND (item, 1) == error_mark_node)
3580 return error_mark_node;
3581 break;
3582
3583 case 1:
3584 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3585 if (TREE_OPERAND (item, 0) == error_mark_node)
3586 return error_mark_node;
3587 break;
3588
3589 default:
3590 break;
3591 }
3592
3593 return fold (item);
3594 #endif
3595 }
3596
3597 #endif
3598 /* Returns the tree that does the intrinsic invocation.
3599
3600 Note: this function applies only to intrinsics returning
3601 CHARACTER*1 or non-CHARACTER results, and to intrinsic
3602 subroutines. */
3603
3604 #if FFECOM_targetCURRENT == FFECOM_targetGCC
3605 static tree
3606 ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
3607 ffebld dest, bool *dest_used)
3608 {
3609 tree expr_tree;
3610 tree saved_expr1; /* For those who need it. */
3611 tree saved_expr2; /* For those who need it. */
3612 ffeinfoBasictype bt;
3613 ffeinfoKindtype kt;
3614 tree tree_type;
3615 tree arg1_type;
3616 tree real_type; /* REAL type corresponding to COMPLEX. */
3617 tree tempvar;
3618 ffebld list = ffebld_right (expr); /* List of (some) args. */
3619 ffebld arg1; /* For handy reference. */
3620 ffebld arg2;
3621 ffebld arg3;
3622 ffeintrinImp codegen_imp;
3623 ffecomGfrt gfrt;
3624
3625 assert (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER);
3626
3627 if (dest_used != NULL)
3628 *dest_used = FALSE;
3629
3630 bt = ffeinfo_basictype (ffebld_info (expr));
3631 kt = ffeinfo_kindtype (ffebld_info (expr));
3632 tree_type = ffecom_tree_type[bt][kt];
3633
3634 if (list != NULL)
3635 {
3636 arg1 = ffebld_head (list);
3637 if (arg1 != NULL && ffebld_op (arg1) == FFEBLD_opANY)
3638 return error_mark_node;
3639 if ((list = ffebld_trail (list)) != NULL)
3640 {
3641 arg2 = ffebld_head (list);
3642 if (arg2 != NULL && ffebld_op (arg2) == FFEBLD_opANY)
3643 return error_mark_node;
3644 if ((list = ffebld_trail (list)) != NULL)
3645 {
3646 arg3 = ffebld_head (list);
3647 if (arg3 != NULL && ffebld_op (arg3) == FFEBLD_opANY)
3648 return error_mark_node;
3649 }
3650 else
3651 arg3 = NULL;
3652 }
3653 else
3654 arg2 = arg3 = NULL;
3655 }
3656 else
3657 arg1 = arg2 = arg3 = NULL;
3658
3659 /* <list> ends up at the opITEM of the 3rd arg, or NULL if there are < 3
3660 args. This is used by the MAX/MIN expansions. */
3661
3662 if (arg1 != NULL)
3663 arg1_type = ffecom_tree_type
3664 [ffeinfo_basictype (ffebld_info (arg1))]
3665 [ffeinfo_kindtype (ffebld_info (arg1))];
3666 else
3667 arg1_type = NULL_TREE; /* Really not needed, but might catch bugs
3668 here. */
3669
3670 /* There are several ways for each of the cases in the following switch
3671 statements to exit (from simplest to use to most complicated):
3672
3673 break; (when expr_tree == NULL)
3674
3675 A standard call is made to the specific intrinsic just as if it had been
3676 passed in as a dummy procedure and called as any old procedure. This
3677 method can produce slower code but in some cases it's the easiest way for
3678 now. However, if a (presumably faster) direct call is available,
3679 that is used, so this is the easiest way in many more cases now.
3680
3681 gfrt = FFECOM_gfrtWHATEVER;
3682 break;
3683
3684 gfrt contains the gfrt index of a library function to call, passing the
3685 argument(s) by value rather than by reference. Used when a more
3686 careful choice of library function is needed than that provided
3687 by the vanilla `break;'.
3688
3689 return expr_tree;
3690
3691 The expr_tree has been completely set up and is ready to be returned
3692 as is. No further actions are taken. Use this when the tree is not
3693 in the simple form for one of the arity_n labels. */
3694
3695 /* For info on how the switch statement cases were written, see the files
3696 enclosed in comments below the switch statement. */
3697
3698 codegen_imp = ffebld_symter_implementation (ffebld_left (expr));
3699 gfrt = ffeintrin_gfrt_direct (codegen_imp);
3700 if (gfrt == FFECOM_gfrt)
3701 gfrt = ffeintrin_gfrt_indirect (codegen_imp);
3702
3703 switch (codegen_imp)
3704 {
3705 case FFEINTRIN_impABS:
3706 case FFEINTRIN_impCABS:
3707 case FFEINTRIN_impCDABS:
3708 case FFEINTRIN_impDABS:
3709 case FFEINTRIN_impIABS:
3710 if (ffeinfo_basictype (ffebld_info (arg1))
3711 == FFEINFO_basictypeCOMPLEX)
3712 {
3713 if (kt == FFEINFO_kindtypeREAL1)
3714 gfrt = FFECOM_gfrtCABS;
3715 else if (kt == FFEINFO_kindtypeREAL2)
3716 gfrt = FFECOM_gfrtCDABS;
3717 break;
3718 }
3719 return ffecom_1 (ABS_EXPR, tree_type,
3720 convert (tree_type, ffecom_expr (arg1)));
3721
3722 case FFEINTRIN_impACOS:
3723 case FFEINTRIN_impDACOS:
3724 break;
3725
3726 case FFEINTRIN_impAIMAG:
3727 case FFEINTRIN_impDIMAG:
3728 case FFEINTRIN_impIMAGPART:
3729 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
3730 arg1_type = TREE_TYPE (arg1_type);
3731 else
3732 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
3733
3734 return
3735 convert (tree_type,
3736 ffecom_1 (IMAGPART_EXPR, arg1_type,
3737 ffecom_expr (arg1)));
3738
3739 case FFEINTRIN_impAINT:
3740 case FFEINTRIN_impDINT:
3741 #if 0 /* ~~ someday implement FIX_TRUNC_EXPR
3742 yielding same type as arg */
3743 return ffecom_1 (FIX_TRUNC_EXPR, tree_type, ffecom_expr (arg1));
3744 #else /* in the meantime, must use floor to avoid range problems with ints */
3745 /* r__1 = r1 >= 0 ? floor(r1) : -floor(-r1); */
3746 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
3747 return
3748 convert (tree_type,
3749 ffecom_3 (COND_EXPR, double_type_node,
3750 ffecom_truth_value
3751 (ffecom_2 (GE_EXPR, integer_type_node,
3752 saved_expr1,
3753 convert (arg1_type,
3754 ffecom_float_zero_))),
3755 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
3756 build_tree_list (NULL_TREE,
3757 convert (double_type_node,
3758 saved_expr1))),
3759 ffecom_1 (NEGATE_EXPR, double_type_node,
3760 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
3761 build_tree_list (NULL_TREE,
3762 convert (double_type_node,
3763 ffecom_1 (NEGATE_EXPR,
3764 arg1_type,
3765 saved_expr1))))
3766 ))
3767 );
3768 #endif
3769
3770 case FFEINTRIN_impANINT:
3771 case FFEINTRIN_impDNINT:
3772 #if 0 /* This way of doing it won't handle real
3773 numbers of large magnitudes. */
3774 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
3775 expr_tree = convert (tree_type,
3776 convert (integer_type_node,
3777 ffecom_3 (COND_EXPR, tree_type,
3778 ffecom_truth_value
3779 (ffecom_2 (GE_EXPR,
3780 integer_type_node,
3781 saved_expr1,
3782 ffecom_float_zero_)),
3783 ffecom_2 (PLUS_EXPR,
3784 tree_type,
3785 saved_expr1,
3786 ffecom_float_half_),
3787 ffecom_2 (MINUS_EXPR,
3788 tree_type,
3789 saved_expr1,
3790 ffecom_float_half_))));
3791 return expr_tree;
3792 #else /* So we instead call floor. */
3793 /* r__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1) */
3794 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
3795 return
3796 convert (tree_type,
3797 ffecom_3 (COND_EXPR, double_type_node,
3798 ffecom_truth_value
3799 (ffecom_2 (GE_EXPR, integer_type_node,
3800 saved_expr1,
3801 convert (arg1_type,
3802 ffecom_float_zero_))),
3803 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
3804 build_tree_list (NULL_TREE,
3805 convert (double_type_node,
3806 ffecom_2 (PLUS_EXPR,
3807 arg1_type,
3808 saved_expr1,
3809 convert (arg1_type,
3810 ffecom_float_half_))))),
3811 ffecom_1 (NEGATE_EXPR, double_type_node,
3812 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
3813 build_tree_list (NULL_TREE,
3814 convert (double_type_node,
3815 ffecom_2 (MINUS_EXPR,
3816 arg1_type,
3817 convert (arg1_type,
3818 ffecom_float_half_),
3819 saved_expr1)))))
3820 )
3821 );
3822 #endif
3823
3824 case FFEINTRIN_impASIN:
3825 case FFEINTRIN_impDASIN:
3826 case FFEINTRIN_impATAN:
3827 case FFEINTRIN_impDATAN:
3828 case FFEINTRIN_impATAN2:
3829 case FFEINTRIN_impDATAN2:
3830 break;
3831
3832 case FFEINTRIN_impCHAR:
3833 case FFEINTRIN_impACHAR:
3834 assert (ffecom_pending_calls_ != 0);
3835 tempvar = ffecom_push_tempvar (char_type_node,
3836 1, -1, TRUE);
3837 {
3838 tree tmv = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (tempvar)));
3839
3840 expr_tree = ffecom_modify (tmv,
3841 ffecom_2 (ARRAY_REF, tmv, tempvar,
3842 integer_one_node),
3843 convert (tmv, ffecom_expr (arg1)));
3844 }
3845 expr_tree = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar),
3846 expr_tree,
3847 tempvar);
3848 expr_tree = ffecom_1 (ADDR_EXPR,
3849 build_pointer_type (TREE_TYPE (expr_tree)),
3850 expr_tree);
3851 return expr_tree;
3852
3853 case FFEINTRIN_impCMPLX:
3854 case FFEINTRIN_impDCMPLX:
3855 if (arg2 == NULL)
3856 return
3857 convert (tree_type, ffecom_expr (arg1));
3858
3859 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
3860 return
3861 ffecom_2 (COMPLEX_EXPR, tree_type,
3862 convert (real_type, ffecom_expr (arg1)),
3863 convert (real_type,
3864 ffecom_expr (arg2)));
3865
3866 case FFEINTRIN_impCOMPLEX:
3867 return
3868 ffecom_2 (COMPLEX_EXPR, tree_type,
3869 ffecom_expr (arg1),
3870 ffecom_expr (arg2));
3871
3872 case FFEINTRIN_impCONJG:
3873 case FFEINTRIN_impDCONJG:
3874 {
3875 tree arg1_tree;
3876
3877 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
3878 arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
3879 return
3880 ffecom_2 (COMPLEX_EXPR, tree_type,
3881 ffecom_1 (REALPART_EXPR, real_type, arg1_tree),
3882 ffecom_1 (NEGATE_EXPR, real_type,
3883 ffecom_1 (IMAGPART_EXPR, real_type, arg1_tree)));
3884 }
3885
3886 case FFEINTRIN_impCOS:
3887 case FFEINTRIN_impCCOS:
3888 case FFEINTRIN_impCDCOS:
3889 case FFEINTRIN_impDCOS:
3890 if (bt == FFEINFO_basictypeCOMPLEX)
3891 {
3892 if (kt == FFEINFO_kindtypeREAL1)
3893 gfrt = FFECOM_gfrtCCOS; /* Overlapping result okay. */
3894 else if (kt == FFEINFO_kindtypeREAL2)
3895 gfrt = FFECOM_gfrtCDCOS; /* Overlapping result okay. */
3896 }
3897 break;
3898
3899 case FFEINTRIN_impCOSH:
3900 case FFEINTRIN_impDCOSH:
3901 break;
3902
3903 case FFEINTRIN_impDBLE:
3904 case FFEINTRIN_impDFLOAT:
3905 case FFEINTRIN_impDREAL:
3906 case FFEINTRIN_impFLOAT:
3907 case FFEINTRIN_impIDINT:
3908 case FFEINTRIN_impIFIX:
3909 case FFEINTRIN_impINT2:
3910 case FFEINTRIN_impINT8:
3911 case FFEINTRIN_impINT:
3912 case FFEINTRIN_impLONG:
3913 case FFEINTRIN_impREAL:
3914 case FFEINTRIN_impSHORT:
3915 case FFEINTRIN_impSNGL:
3916 return convert (tree_type, ffecom_expr (arg1));
3917
3918 case FFEINTRIN_impDIM:
3919 case FFEINTRIN_impDDIM:
3920 case FFEINTRIN_impIDIM:
3921 saved_expr1 = ffecom_save_tree (convert (tree_type,
3922 ffecom_expr (arg1)));
3923 saved_expr2 = ffecom_save_tree (convert (tree_type,
3924 ffecom_expr (arg2)));
3925 return
3926 ffecom_3 (COND_EXPR, tree_type,
3927 ffecom_truth_value
3928 (ffecom_2 (GT_EXPR, integer_type_node,
3929 saved_expr1,
3930 saved_expr2)),
3931 ffecom_2 (MINUS_EXPR, tree_type,
3932 saved_expr1,
3933 saved_expr2),
3934 convert (tree_type, ffecom_float_zero_));
3935
3936 case FFEINTRIN_impDPROD:
3937 return
3938 ffecom_2 (MULT_EXPR, tree_type,
3939 convert (tree_type, ffecom_expr (arg1)),
3940 convert (tree_type, ffecom_expr (arg2)));
3941
3942 case FFEINTRIN_impEXP:
3943 case FFEINTRIN_impCDEXP:
3944 case FFEINTRIN_impCEXP:
3945 case FFEINTRIN_impDEXP:
3946 if (bt == FFEINFO_basictypeCOMPLEX)
3947 {
3948 if (kt == FFEINFO_kindtypeREAL1)
3949 gfrt = FFECOM_gfrtCEXP; /* Overlapping result okay. */
3950 else if (kt == FFEINFO_kindtypeREAL2)
3951 gfrt = FFECOM_gfrtCDEXP; /* Overlapping result okay. */
3952 }
3953 break;
3954
3955 case FFEINTRIN_impICHAR:
3956 case FFEINTRIN_impIACHAR:
3957 #if 0 /* The simple approach. */
3958 ffecom_char_args_ (&expr_tree, &saved_expr1 /* Ignored */ , arg1);
3959 expr_tree
3960 = ffecom_1 (INDIRECT_REF,
3961 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
3962 expr_tree);
3963 expr_tree
3964 = ffecom_2 (ARRAY_REF,
3965 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
3966 expr_tree,
3967 integer_one_node);
3968 return convert (tree_type, expr_tree);
3969 #else /* The more interesting (and more optimal) approach. */
3970 expr_tree = ffecom_intrinsic_ichar_ (tree_type, arg1, &saved_expr1);
3971 expr_tree = ffecom_3 (COND_EXPR, tree_type,
3972 saved_expr1,
3973 expr_tree,
3974 convert (tree_type, integer_zero_node));
3975 return expr_tree;
3976 #endif
3977
3978 case FFEINTRIN_impINDEX:
3979 break;
3980
3981 case FFEINTRIN_impLEN:
3982 #if 0
3983 break; /* The simple approach. */
3984 #else
3985 return ffecom_intrinsic_len_ (arg1); /* The more optimal approach. */
3986 #endif
3987
3988 case FFEINTRIN_impLGE:
3989 case FFEINTRIN_impLGT:
3990 case FFEINTRIN_impLLE:
3991 case FFEINTRIN_impLLT:
3992 break;
3993
3994 case FFEINTRIN_impLOG:
3995 case FFEINTRIN_impALOG:
3996 case FFEINTRIN_impCDLOG:
3997 case FFEINTRIN_impCLOG:
3998 case FFEINTRIN_impDLOG:
3999 if (bt == FFEINFO_basictypeCOMPLEX)
4000 {
4001 if (kt == FFEINFO_kindtypeREAL1)
4002 gfrt = FFECOM_gfrtCLOG; /* Overlapping result okay. */
4003 else if (kt == FFEINFO_kindtypeREAL2)
4004 gfrt = FFECOM_gfrtCDLOG; /* Overlapping result okay. */
4005 }
4006 break;
4007
4008 case FFEINTRIN_impLOG10:
4009 case FFEINTRIN_impALOG10:
4010 case FFEINTRIN_impDLOG10:
4011 if (gfrt != FFECOM_gfrt)
4012 break; /* Already picked one, stick with it. */
4013
4014 if (kt == FFEINFO_kindtypeREAL1)
4015 gfrt = FFECOM_gfrtALOG10;
4016 else if (kt == FFEINFO_kindtypeREAL2)
4017 gfrt = FFECOM_gfrtDLOG10;
4018 break;
4019
4020 case FFEINTRIN_impMAX:
4021 case FFEINTRIN_impAMAX0:
4022 case FFEINTRIN_impAMAX1:
4023 case FFEINTRIN_impDMAX1:
4024 case FFEINTRIN_impMAX0:
4025 case FFEINTRIN_impMAX1:
4026 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4027 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4028 else
4029 arg1_type = tree_type;
4030 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4031 convert (arg1_type, ffecom_expr (arg1)),
4032 convert (arg1_type, ffecom_expr (arg2)));
4033 for (; list != NULL; list = ffebld_trail (list))
4034 {
4035 if ((ffebld_head (list) == NULL)
4036 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4037 continue;
4038 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4039 expr_tree,
4040 convert (arg1_type,
4041 ffecom_expr (ffebld_head (list))));
4042 }
4043 return convert (tree_type, expr_tree);
4044
4045 case FFEINTRIN_impMIN:
4046 case FFEINTRIN_impAMIN0:
4047 case FFEINTRIN_impAMIN1:
4048 case FFEINTRIN_impDMIN1:
4049 case FFEINTRIN_impMIN0:
4050 case FFEINTRIN_impMIN1:
4051 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4052 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4053 else
4054 arg1_type = tree_type;
4055 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4056 convert (arg1_type, ffecom_expr (arg1)),
4057 convert (arg1_type, ffecom_expr (arg2)));
4058 for (; list != NULL; list = ffebld_trail (list))
4059 {
4060 if ((ffebld_head (list) == NULL)
4061 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4062 continue;
4063 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4064 expr_tree,
4065 convert (arg1_type,
4066 ffecom_expr (ffebld_head (list))));
4067 }
4068 return convert (tree_type, expr_tree);
4069
4070 case FFEINTRIN_impMOD:
4071 case FFEINTRIN_impAMOD:
4072 case FFEINTRIN_impDMOD:
4073 if (bt != FFEINFO_basictypeREAL)
4074 return ffecom_2 (TRUNC_MOD_EXPR, tree_type,
4075 convert (tree_type, ffecom_expr (arg1)),
4076 convert (tree_type, ffecom_expr (arg2)));
4077
4078 if (kt == FFEINFO_kindtypeREAL1)
4079 gfrt = FFECOM_gfrtAMOD;
4080 else if (kt == FFEINFO_kindtypeREAL2)
4081 gfrt = FFECOM_gfrtDMOD;
4082 break;
4083
4084 case FFEINTRIN_impNINT:
4085 case FFEINTRIN_impIDNINT:
4086 #if 0 /* ~~ ideally FIX_ROUND_EXPR would be
4087 implemented, but it ain't yet */
4088 return ffecom_1 (FIX_ROUND_EXPR, tree_type, ffecom_expr (arg1));
4089 #else
4090 /* i__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1); */
4091 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4092 return
4093 convert (ffecom_integer_type_node,
4094 ffecom_3 (COND_EXPR, arg1_type,
4095 ffecom_truth_value
4096 (ffecom_2 (GE_EXPR, integer_type_node,
4097 saved_expr1,
4098 convert (arg1_type,
4099 ffecom_float_zero_))),
4100 ffecom_2 (PLUS_EXPR, arg1_type,
4101 saved_expr1,
4102 convert (arg1_type,
4103 ffecom_float_half_)),
4104 ffecom_2 (MINUS_EXPR, arg1_type,
4105 saved_expr1,
4106 convert (arg1_type,
4107 ffecom_float_half_))));
4108 #endif
4109
4110 case FFEINTRIN_impSIGN:
4111 case FFEINTRIN_impDSIGN:
4112 case FFEINTRIN_impISIGN:
4113 {
4114 tree arg2_tree = ffecom_expr (arg2);
4115
4116 saved_expr1
4117 = ffecom_save_tree
4118 (ffecom_1 (ABS_EXPR, tree_type,
4119 convert (tree_type,
4120 ffecom_expr (arg1))));
4121 expr_tree
4122 = ffecom_3 (COND_EXPR, tree_type,
4123 ffecom_truth_value
4124 (ffecom_2 (GE_EXPR, integer_type_node,
4125 arg2_tree,
4126 convert (TREE_TYPE (arg2_tree),
4127 integer_zero_node))),
4128 saved_expr1,
4129 ffecom_1 (NEGATE_EXPR, tree_type, saved_expr1));
4130 /* Make sure SAVE_EXPRs get referenced early enough. */
4131 expr_tree
4132 = ffecom_2 (COMPOUND_EXPR, tree_type,
4133 convert (void_type_node, saved_expr1),
4134 expr_tree);
4135 }
4136 return expr_tree;
4137
4138 case FFEINTRIN_impSIN:
4139 case FFEINTRIN_impCDSIN:
4140 case FFEINTRIN_impCSIN:
4141 case FFEINTRIN_impDSIN:
4142 if (bt == FFEINFO_basictypeCOMPLEX)
4143 {
4144 if (kt == FFEINFO_kindtypeREAL1)
4145 gfrt = FFECOM_gfrtCSIN; /* Overlapping result okay. */
4146 else if (kt == FFEINFO_kindtypeREAL2)
4147 gfrt = FFECOM_gfrtCDSIN; /* Overlapping result okay. */
4148 }
4149 break;
4150
4151 case FFEINTRIN_impSINH:
4152 case FFEINTRIN_impDSINH:
4153 break;
4154
4155 case FFEINTRIN_impSQRT:
4156 case FFEINTRIN_impCDSQRT:
4157 case FFEINTRIN_impCSQRT:
4158 case FFEINTRIN_impDSQRT:
4159 if (bt == FFEINFO_basictypeCOMPLEX)
4160 {
4161 if (kt == FFEINFO_kindtypeREAL1)
4162 gfrt = FFECOM_gfrtCSQRT; /* Overlapping result okay. */
4163 else if (kt == FFEINFO_kindtypeREAL2)
4164 gfrt = FFECOM_gfrtCDSQRT; /* Overlapping result okay. */
4165 }
4166 break;
4167
4168 case FFEINTRIN_impTAN:
4169 case FFEINTRIN_impDTAN:
4170 case FFEINTRIN_impTANH:
4171 case FFEINTRIN_impDTANH:
4172 break;
4173
4174 case FFEINTRIN_impREALPART:
4175 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4176 arg1_type = TREE_TYPE (arg1_type);
4177 else
4178 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4179
4180 return
4181 convert (tree_type,
4182 ffecom_1 (REALPART_EXPR, arg1_type,
4183 ffecom_expr (arg1)));
4184
4185 case FFEINTRIN_impIAND:
4186 case FFEINTRIN_impAND:
4187 return ffecom_2 (BIT_AND_EXPR, tree_type,
4188 convert (tree_type,
4189 ffecom_expr (arg1)),
4190 convert (tree_type,
4191 ffecom_expr (arg2)));
4192
4193 case FFEINTRIN_impIOR:
4194 case FFEINTRIN_impOR:
4195 return ffecom_2 (BIT_IOR_EXPR, tree_type,
4196 convert (tree_type,
4197 ffecom_expr (arg1)),
4198 convert (tree_type,
4199 ffecom_expr (arg2)));
4200
4201 case FFEINTRIN_impIEOR:
4202 case FFEINTRIN_impXOR:
4203 return ffecom_2 (BIT_XOR_EXPR, tree_type,
4204 convert (tree_type,
4205 ffecom_expr (arg1)),
4206 convert (tree_type,
4207 ffecom_expr (arg2)));
4208
4209 case FFEINTRIN_impLSHIFT:
4210 return ffecom_2 (LSHIFT_EXPR, tree_type,
4211 ffecom_expr (arg1),
4212 convert (integer_type_node,
4213 ffecom_expr (arg2)));
4214
4215 case FFEINTRIN_impRSHIFT:
4216 return ffecom_2 (RSHIFT_EXPR, tree_type,
4217 ffecom_expr (arg1),
4218 convert (integer_type_node,
4219 ffecom_expr (arg2)));
4220
4221 case FFEINTRIN_impNOT:
4222 return ffecom_1 (BIT_NOT_EXPR, tree_type, ffecom_expr (arg1));
4223
4224 case FFEINTRIN_impBIT_SIZE:
4225 return convert (tree_type, TYPE_SIZE (arg1_type));
4226
4227 case FFEINTRIN_impBTEST:
4228 {
4229 ffetargetLogical1 true;
4230 ffetargetLogical1 false;
4231 tree true_tree;
4232 tree false_tree;
4233
4234 ffetarget_logical1 (&true, TRUE);
4235 ffetarget_logical1 (&false, FALSE);
4236 if (true == 1)
4237 true_tree = convert (tree_type, integer_one_node);
4238 else
4239 true_tree = convert (tree_type, build_int_2 (true, 0));
4240 if (false == 0)
4241 false_tree = convert (tree_type, integer_zero_node);
4242 else
4243 false_tree = convert (tree_type, build_int_2 (false, 0));
4244
4245 return
4246 ffecom_3 (COND_EXPR, tree_type,
4247 ffecom_truth_value
4248 (ffecom_2 (EQ_EXPR, integer_type_node,
4249 ffecom_2 (BIT_AND_EXPR, arg1_type,
4250 ffecom_expr (arg1),
4251 ffecom_2 (LSHIFT_EXPR, arg1_type,
4252 convert (arg1_type,
4253 integer_one_node),
4254 convert (integer_type_node,
4255 ffecom_expr (arg2)))),
4256 convert (arg1_type,
4257 integer_zero_node))),
4258 false_tree,
4259 true_tree);
4260 }
4261
4262 case FFEINTRIN_impIBCLR:
4263 return
4264 ffecom_2 (BIT_AND_EXPR, tree_type,
4265 ffecom_expr (arg1),
4266 ffecom_1 (BIT_NOT_EXPR, tree_type,
4267 ffecom_2 (LSHIFT_EXPR, tree_type,
4268 convert (tree_type,
4269 integer_one_node),
4270 convert (integer_type_node,
4271 ffecom_expr (arg2)))));
4272
4273 case FFEINTRIN_impIBITS:
4274 {
4275 tree arg3_tree = ffecom_save_tree (convert (integer_type_node,
4276 ffecom_expr (arg3)));
4277 tree uns_type
4278 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4279
4280 expr_tree
4281 = ffecom_2 (BIT_AND_EXPR, tree_type,
4282 ffecom_2 (RSHIFT_EXPR, tree_type,
4283 ffecom_expr (arg1),
4284 convert (integer_type_node,
4285 ffecom_expr (arg2))),
4286 convert (tree_type,
4287 ffecom_2 (RSHIFT_EXPR, uns_type,
4288 ffecom_1 (BIT_NOT_EXPR,
4289 uns_type,
4290 convert (uns_type,
4291 integer_zero_node)),
4292 ffecom_2 (MINUS_EXPR,
4293 integer_type_node,
4294 TYPE_SIZE (uns_type),
4295 arg3_tree))));
4296 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4297 expr_tree
4298 = ffecom_3 (COND_EXPR, tree_type,
4299 ffecom_truth_value
4300 (ffecom_2 (NE_EXPR, integer_type_node,
4301 arg3_tree,
4302 integer_zero_node)),
4303 expr_tree,
4304 convert (tree_type, integer_zero_node));
4305 #endif
4306 }
4307 return expr_tree;
4308
4309 case FFEINTRIN_impIBSET:
4310 return
4311 ffecom_2 (BIT_IOR_EXPR, tree_type,
4312 ffecom_expr (arg1),
4313 ffecom_2 (LSHIFT_EXPR, tree_type,
4314 convert (tree_type, integer_one_node),
4315 convert (integer_type_node,
4316 ffecom_expr (arg2))));
4317
4318 case FFEINTRIN_impISHFT:
4319 {
4320 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4321 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4322 ffecom_expr (arg2)));
4323 tree uns_type
4324 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4325
4326 expr_tree
4327 = ffecom_3 (COND_EXPR, tree_type,
4328 ffecom_truth_value
4329 (ffecom_2 (GE_EXPR, integer_type_node,
4330 arg2_tree,
4331 integer_zero_node)),
4332 ffecom_2 (LSHIFT_EXPR, tree_type,
4333 arg1_tree,
4334 arg2_tree),
4335 convert (tree_type,
4336 ffecom_2 (RSHIFT_EXPR, uns_type,
4337 convert (uns_type, arg1_tree),
4338 ffecom_1 (NEGATE_EXPR,
4339 integer_type_node,
4340 arg2_tree))));
4341 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4342 expr_tree
4343 = ffecom_3 (COND_EXPR, tree_type,
4344 ffecom_truth_value
4345 (ffecom_2 (NE_EXPR, integer_type_node,
4346 arg2_tree,
4347 TYPE_SIZE (uns_type))),
4348 expr_tree,
4349 convert (tree_type, integer_zero_node));
4350 #endif
4351 /* Make sure SAVE_EXPRs get referenced early enough. */
4352 expr_tree
4353 = ffecom_2 (COMPOUND_EXPR, tree_type,
4354 convert (void_type_node, arg1_tree),
4355 ffecom_2 (COMPOUND_EXPR, tree_type,
4356 convert (void_type_node, arg2_tree),
4357 expr_tree));
4358 }
4359 return expr_tree;
4360
4361 case FFEINTRIN_impISHFTC:
4362 {
4363 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4364 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4365 ffecom_expr (arg2)));
4366 tree arg3_tree = (arg3 == NULL) ? TYPE_SIZE (tree_type)
4367 : ffecom_save_tree (convert (integer_type_node, ffecom_expr (arg3)));
4368 tree shift_neg;
4369 tree shift_pos;
4370 tree mask_arg1;
4371 tree masked_arg1;
4372 tree uns_type
4373 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4374
4375 mask_arg1
4376 = ffecom_2 (LSHIFT_EXPR, tree_type,
4377 ffecom_1 (BIT_NOT_EXPR, tree_type,
4378 convert (tree_type, integer_zero_node)),
4379 arg3_tree);
4380 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4381 mask_arg1
4382 = ffecom_3 (COND_EXPR, tree_type,
4383 ffecom_truth_value
4384 (ffecom_2 (NE_EXPR, integer_type_node,
4385 arg3_tree,
4386 TYPE_SIZE (uns_type))),
4387 mask_arg1,
4388 convert (tree_type, integer_zero_node));
4389 #endif
4390 mask_arg1 = ffecom_save_tree (mask_arg1);
4391 masked_arg1
4392 = ffecom_2 (BIT_AND_EXPR, tree_type,
4393 arg1_tree,
4394 ffecom_1 (BIT_NOT_EXPR, tree_type,
4395 mask_arg1));
4396 masked_arg1 = ffecom_save_tree (masked_arg1);
4397 shift_neg
4398 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4399 convert (tree_type,
4400 ffecom_2 (RSHIFT_EXPR, uns_type,
4401 convert (uns_type, masked_arg1),
4402 ffecom_1 (NEGATE_EXPR,
4403 integer_type_node,
4404 arg2_tree))),
4405 ffecom_2 (LSHIFT_EXPR, tree_type,
4406 arg1_tree,
4407 ffecom_2 (PLUS_EXPR, integer_type_node,
4408 arg2_tree,
4409 arg3_tree)));
4410 shift_pos
4411 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4412 ffecom_2 (LSHIFT_EXPR, tree_type,
4413 arg1_tree,
4414 arg2_tree),
4415 convert (tree_type,
4416 ffecom_2 (RSHIFT_EXPR, uns_type,
4417 convert (uns_type, masked_arg1),
4418 ffecom_2 (MINUS_EXPR,
4419 integer_type_node,
4420 arg3_tree,
4421 arg2_tree))));
4422 expr_tree
4423 = ffecom_3 (COND_EXPR, tree_type,
4424 ffecom_truth_value
4425 (ffecom_2 (LT_EXPR, integer_type_node,
4426 arg2_tree,
4427 integer_zero_node)),
4428 shift_neg,
4429 shift_pos);
4430 expr_tree
4431 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4432 ffecom_2 (BIT_AND_EXPR, tree_type,
4433 mask_arg1,
4434 arg1_tree),
4435 ffecom_2 (BIT_AND_EXPR, tree_type,
4436 ffecom_1 (BIT_NOT_EXPR, tree_type,
4437 mask_arg1),
4438 expr_tree));
4439 expr_tree
4440 = ffecom_3 (COND_EXPR, tree_type,
4441 ffecom_truth_value
4442 (ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
4443 ffecom_2 (EQ_EXPR, integer_type_node,
4444 ffecom_1 (ABS_EXPR,
4445 integer_type_node,
4446 arg2_tree),
4447 arg3_tree),
4448 ffecom_2 (EQ_EXPR, integer_type_node,
4449 arg2_tree,
4450 integer_zero_node))),
4451 arg1_tree,
4452 expr_tree);
4453 /* Make sure SAVE_EXPRs get referenced early enough. */
4454 expr_tree
4455 = ffecom_2 (COMPOUND_EXPR, tree_type,
4456 convert (void_type_node, arg1_tree),
4457 ffecom_2 (COMPOUND_EXPR, tree_type,
4458 convert (void_type_node, arg2_tree),
4459 ffecom_2 (COMPOUND_EXPR, tree_type,
4460 convert (void_type_node,
4461 mask_arg1),
4462 ffecom_2 (COMPOUND_EXPR, tree_type,
4463 convert (void_type_node,
4464 masked_arg1),
4465 expr_tree))));
4466 expr_tree
4467 = ffecom_2 (COMPOUND_EXPR, tree_type,
4468 convert (void_type_node,
4469 arg3_tree),
4470 expr_tree);
4471 }
4472 return expr_tree;
4473
4474 case FFEINTRIN_impLOC:
4475 {
4476 tree arg1_tree = ffecom_expr (arg1);
4477
4478 expr_tree
4479 = convert (tree_type,
4480 ffecom_1 (ADDR_EXPR,
4481 build_pointer_type (TREE_TYPE (arg1_tree)),
4482 arg1_tree));
4483 }
4484 return expr_tree;
4485
4486 case FFEINTRIN_impMVBITS:
4487 {
4488 tree arg1_tree;
4489 tree arg2_tree;
4490 tree arg3_tree;
4491 ffebld arg4 = ffebld_head (ffebld_trail (list));
4492 tree arg4_tree;
4493 tree arg4_type;
4494 ffebld arg5 = ffebld_head (ffebld_trail (ffebld_trail (list)));
4495 tree arg5_tree;
4496 tree prep_arg1;
4497 tree prep_arg4;
4498 tree arg5_plus_arg3;
4499
4500 ffecom_push_calltemps ();
4501
4502 arg2_tree = convert (integer_type_node,
4503 ffecom_expr (arg2));
4504 arg3_tree = ffecom_save_tree (convert (integer_type_node,
4505 ffecom_expr (arg3)));
4506 arg4_tree = ffecom_expr_rw (arg4);
4507 arg4_type = TREE_TYPE (arg4_tree);
4508
4509 arg1_tree = ffecom_save_tree (convert (arg4_type,
4510 ffecom_expr (arg1)));
4511
4512 arg5_tree = ffecom_save_tree (convert (integer_type_node,
4513 ffecom_expr (arg5)));
4514
4515 ffecom_pop_calltemps ();
4516
4517 prep_arg1
4518 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4519 ffecom_2 (BIT_AND_EXPR, arg4_type,
4520 ffecom_2 (RSHIFT_EXPR, arg4_type,
4521 arg1_tree,
4522 arg2_tree),
4523 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4524 ffecom_2 (LSHIFT_EXPR, arg4_type,
4525 ffecom_1 (BIT_NOT_EXPR,
4526 arg4_type,
4527 convert
4528 (arg4_type,
4529 integer_zero_node)),
4530 arg3_tree))),
4531 arg5_tree);
4532 arg5_plus_arg3
4533 = ffecom_save_tree (ffecom_2 (PLUS_EXPR, arg4_type,
4534 arg5_tree,
4535 arg3_tree));
4536 prep_arg4
4537 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4538 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4539 convert (arg4_type,
4540 integer_zero_node)),
4541 arg5_plus_arg3);
4542 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4543 prep_arg4
4544 = ffecom_3 (COND_EXPR, arg4_type,
4545 ffecom_truth_value
4546 (ffecom_2 (NE_EXPR, integer_type_node,
4547 arg5_plus_arg3,
4548 convert (TREE_TYPE (arg5_plus_arg3),
4549 TYPE_SIZE (arg4_type)))),
4550 prep_arg4,
4551 convert (arg4_type, integer_zero_node));
4552 #endif
4553 prep_arg4
4554 = ffecom_2 (BIT_AND_EXPR, arg4_type,
4555 arg4_tree,
4556 ffecom_2 (BIT_IOR_EXPR, arg4_type,
4557 prep_arg4,
4558 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4559 ffecom_2 (LSHIFT_EXPR, arg4_type,
4560 ffecom_1 (BIT_NOT_EXPR,
4561 arg4_type,
4562 convert
4563 (arg4_type,
4564 integer_zero_node)),
4565 arg5_tree))));
4566 prep_arg1
4567 = ffecom_2 (BIT_IOR_EXPR, arg4_type,
4568 prep_arg1,
4569 prep_arg4);
4570 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4571 prep_arg1
4572 = ffecom_3 (COND_EXPR, arg4_type,
4573 ffecom_truth_value
4574 (ffecom_2 (NE_EXPR, integer_type_node,
4575 arg3_tree,
4576 convert (TREE_TYPE (arg3_tree),
4577 integer_zero_node))),
4578 prep_arg1,
4579 arg4_tree);
4580 prep_arg1
4581 = ffecom_3 (COND_EXPR, arg4_type,
4582 ffecom_truth_value
4583 (ffecom_2 (NE_EXPR, integer_type_node,
4584 arg3_tree,
4585 convert (TREE_TYPE (arg3_tree),
4586 TYPE_SIZE (arg4_type)))),
4587 prep_arg1,
4588 arg1_tree);
4589 #endif
4590 expr_tree
4591 = ffecom_2s (MODIFY_EXPR, void_type_node,
4592 arg4_tree,
4593 prep_arg1);
4594 /* Make sure SAVE_EXPRs get referenced early enough. */
4595 expr_tree
4596 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4597 arg1_tree,
4598 ffecom_2 (COMPOUND_EXPR, void_type_node,
4599 arg3_tree,
4600 ffecom_2 (COMPOUND_EXPR, void_type_node,
4601 arg5_tree,
4602 ffecom_2 (COMPOUND_EXPR, void_type_node,
4603 arg5_plus_arg3,
4604 expr_tree))));
4605 expr_tree
4606 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4607 arg4_tree,
4608 expr_tree);
4609
4610 }
4611 return expr_tree;
4612
4613 case FFEINTRIN_impDERF:
4614 case FFEINTRIN_impERF:
4615 case FFEINTRIN_impDERFC:
4616 case FFEINTRIN_impERFC:
4617 break;
4618
4619 case FFEINTRIN_impIARGC:
4620 /* extern int xargc; i__1 = xargc - 1; */
4621 expr_tree = ffecom_2 (MINUS_EXPR, TREE_TYPE (ffecom_tree_xargc_),
4622 ffecom_tree_xargc_,
4623 convert (TREE_TYPE (ffecom_tree_xargc_),
4624 integer_one_node));
4625 return expr_tree;
4626
4627 case FFEINTRIN_impSIGNAL_func:
4628 case FFEINTRIN_impSIGNAL_subr:
4629 {
4630 tree arg1_tree;
4631 tree arg2_tree;
4632 tree arg3_tree;
4633
4634 ffecom_push_calltemps ();
4635
4636 arg1_tree = convert (ffecom_f2c_integer_type_node,
4637 ffecom_expr (arg1));
4638 arg1_tree = ffecom_1 (ADDR_EXPR,
4639 build_pointer_type (TREE_TYPE (arg1_tree)),
4640 arg1_tree);
4641
4642 /* Pass procedure as a pointer to it, anything else by value. */
4643 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4644 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4645 else
4646 arg2_tree = ffecom_ptr_to_expr (arg2);
4647 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4648 arg2_tree);
4649
4650 if (arg3 != NULL)
4651 arg3_tree = ffecom_expr_rw (arg3);
4652 else
4653 arg3_tree = NULL_TREE;
4654
4655 ffecom_pop_calltemps ();
4656
4657 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4658 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4659 TREE_CHAIN (arg1_tree) = arg2_tree;
4660
4661 expr_tree
4662 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4663 ffecom_gfrt_kindtype (gfrt),
4664 FALSE,
4665 ((codegen_imp == FFEINTRIN_impSIGNAL_subr) ?
4666 NULL_TREE :
4667 tree_type),
4668 arg1_tree,
4669 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
4670
4671 if (arg3_tree != NULL_TREE)
4672 expr_tree
4673 = ffecom_modify (NULL_TREE, arg3_tree,
4674 convert (TREE_TYPE (arg3_tree),
4675 expr_tree));
4676 }
4677 return expr_tree;
4678
4679 case FFEINTRIN_impALARM:
4680 {
4681 tree arg1_tree;
4682 tree arg2_tree;
4683 tree arg3_tree;
4684
4685 ffecom_push_calltemps ();
4686
4687 arg1_tree = convert (ffecom_f2c_integer_type_node,
4688 ffecom_expr (arg1));
4689 arg1_tree = ffecom_1 (ADDR_EXPR,
4690 build_pointer_type (TREE_TYPE (arg1_tree)),
4691 arg1_tree);
4692
4693 /* Pass procedure as a pointer to it, anything else by value. */
4694 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4695 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4696 else
4697 arg2_tree = ffecom_ptr_to_expr (arg2);
4698 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4699 arg2_tree);
4700
4701 if (arg3 != NULL)
4702 arg3_tree = ffecom_expr_rw (arg3);
4703 else
4704 arg3_tree = NULL_TREE;
4705
4706 ffecom_pop_calltemps ();
4707
4708 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4709 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4710 TREE_CHAIN (arg1_tree) = arg2_tree;
4711
4712 expr_tree
4713 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4714 ffecom_gfrt_kindtype (gfrt),
4715 FALSE,
4716 NULL_TREE,
4717 arg1_tree,
4718 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
4719
4720 if (arg3_tree != NULL_TREE)
4721 expr_tree
4722 = ffecom_modify (NULL_TREE, arg3_tree,
4723 convert (TREE_TYPE (arg3_tree),
4724 expr_tree));
4725 }
4726 return expr_tree;
4727
4728 case FFEINTRIN_impCHDIR_subr:
4729 case FFEINTRIN_impFDATE_subr:
4730 case FFEINTRIN_impFGET_subr:
4731 case FFEINTRIN_impFPUT_subr:
4732 case FFEINTRIN_impGETCWD_subr:
4733 case FFEINTRIN_impHOSTNM_subr:
4734 case FFEINTRIN_impSYSTEM_subr:
4735 case FFEINTRIN_impUNLINK_subr:
4736 {
4737 tree arg1_len = integer_zero_node;
4738 tree arg1_tree;
4739 tree arg2_tree;
4740
4741 ffecom_push_calltemps ();
4742
4743 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
4744
4745 if (arg2 != NULL)
4746 arg2_tree = ffecom_expr_rw (arg2);
4747 else
4748 arg2_tree = NULL_TREE;
4749
4750 ffecom_pop_calltemps ();
4751
4752 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4753 arg1_len = build_tree_list (NULL_TREE, arg1_len);
4754 TREE_CHAIN (arg1_tree) = arg1_len;
4755
4756 expr_tree
4757 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4758 ffecom_gfrt_kindtype (gfrt),
4759 FALSE,
4760 NULL_TREE,
4761 arg1_tree,
4762 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
4763
4764 if (arg2_tree != NULL_TREE)
4765 expr_tree
4766 = ffecom_modify (NULL_TREE, arg2_tree,
4767 convert (TREE_TYPE (arg2_tree),
4768 expr_tree));
4769 }
4770 return expr_tree;
4771
4772 case FFEINTRIN_impEXIT:
4773 if (arg1 != NULL)
4774 break;
4775
4776 expr_tree = build_tree_list (NULL_TREE,
4777 ffecom_1 (ADDR_EXPR,
4778 build_pointer_type
4779 (ffecom_integer_type_node),
4780 integer_zero_node));
4781
4782 return
4783 ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4784 ffecom_gfrt_kindtype (gfrt),
4785 FALSE,
4786 void_type_node,
4787 expr_tree,
4788 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
4789
4790 case FFEINTRIN_impFLUSH:
4791 if (arg1 == NULL)
4792 gfrt = FFECOM_gfrtFLUSH;
4793 else
4794 gfrt = FFECOM_gfrtFLUSH1;
4795 break;
4796
4797 case FFEINTRIN_impCHMOD_subr:
4798 case FFEINTRIN_impLINK_subr:
4799 case FFEINTRIN_impRENAME_subr:
4800 case FFEINTRIN_impSYMLNK_subr:
4801 {
4802 tree arg1_len = integer_zero_node;
4803 tree arg1_tree;
4804 tree arg2_len = integer_zero_node;
4805 tree arg2_tree;
4806 tree arg3_tree;
4807
4808 ffecom_push_calltemps ();
4809
4810 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
4811 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
4812 if (arg3 != NULL)
4813 arg3_tree = ffecom_expr_rw (arg3);
4814 else
4815 arg3_tree = NULL_TREE;
4816
4817 ffecom_pop_calltemps ();
4818
4819 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4820 arg1_len = build_tree_list (NULL_TREE, arg1_len);
4821 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4822 arg2_len = build_tree_list (NULL_TREE, arg2_len);
4823 TREE_CHAIN (arg1_tree) = arg2_tree;
4824 TREE_CHAIN (arg2_tree) = arg1_len;
4825 TREE_CHAIN (arg1_len) = arg2_len;
4826 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4827 ffecom_gfrt_kindtype (gfrt),
4828 FALSE,
4829 NULL_TREE,
4830 arg1_tree,
4831 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
4832 if (arg3_tree != NULL_TREE)
4833 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
4834 convert (TREE_TYPE (arg3_tree),
4835 expr_tree));
4836 }
4837 return expr_tree;
4838
4839 case FFEINTRIN_impLSTAT_subr:
4840 case FFEINTRIN_impSTAT_subr:
4841 {
4842 tree arg1_len = integer_zero_node;
4843 tree arg1_tree;
4844 tree arg2_tree;
4845 tree arg3_tree;
4846
4847 ffecom_push_calltemps ();
4848
4849 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
4850
4851 arg2_tree = ffecom_ptr_to_expr (arg2);
4852
4853 if (arg3 != NULL)
4854 arg3_tree = ffecom_expr_rw (arg3);
4855 else
4856 arg3_tree = NULL_TREE;
4857
4858 ffecom_pop_calltemps ();
4859
4860 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4861 arg1_len = build_tree_list (NULL_TREE, arg1_len);
4862 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4863 TREE_CHAIN (arg1_tree) = arg2_tree;
4864 TREE_CHAIN (arg2_tree) = arg1_len;
4865 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4866 ffecom_gfrt_kindtype (gfrt),
4867 FALSE,
4868 NULL_TREE,
4869 arg1_tree,
4870 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
4871 if (arg3_tree != NULL_TREE)
4872 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
4873 convert (TREE_TYPE (arg3_tree),
4874 expr_tree));
4875 }
4876 return expr_tree;
4877
4878 case FFEINTRIN_impFGETC_subr:
4879 case FFEINTRIN_impFPUTC_subr:
4880 {
4881 tree arg1_tree;
4882 tree arg2_tree;
4883 tree arg2_len = integer_zero_node;
4884 tree arg3_tree;
4885
4886 ffecom_push_calltemps ();
4887
4888 arg1_tree = convert (ffecom_f2c_integer_type_node,
4889 ffecom_expr (arg1));
4890 arg1_tree = ffecom_1 (ADDR_EXPR,
4891 build_pointer_type (TREE_TYPE (arg1_tree)),
4892 arg1_tree);
4893
4894 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
4895 arg3_tree = ffecom_expr_rw (arg3);
4896
4897 ffecom_pop_calltemps ();
4898
4899 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4900 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4901 arg2_len = build_tree_list (NULL_TREE, arg2_len);
4902 TREE_CHAIN (arg1_tree) = arg2_tree;
4903 TREE_CHAIN (arg2_tree) = arg2_len;
4904
4905 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4906 ffecom_gfrt_kindtype (gfrt),
4907 FALSE,
4908 NULL_TREE,
4909 arg1_tree,
4910 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
4911 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
4912 convert (TREE_TYPE (arg3_tree),
4913 expr_tree));
4914 }
4915 return expr_tree;
4916
4917 case FFEINTRIN_impFSTAT_subr:
4918 {
4919 tree arg1_tree;
4920 tree arg2_tree;
4921 tree arg3_tree;
4922
4923 ffecom_push_calltemps ();
4924
4925 arg1_tree = convert (ffecom_f2c_integer_type_node,
4926 ffecom_expr (arg1));
4927 arg1_tree = ffecom_1 (ADDR_EXPR,
4928 build_pointer_type (TREE_TYPE (arg1_tree)),
4929 arg1_tree);
4930
4931 arg2_tree = convert (ffecom_f2c_ptr_to_integer_type_node,
4932 ffecom_ptr_to_expr (arg2));
4933
4934 if (arg3 == NULL)
4935 arg3_tree = NULL_TREE;
4936 else
4937 arg3_tree = ffecom_expr_rw (arg3);
4938
4939 ffecom_pop_calltemps ();
4940
4941 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4942 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4943 TREE_CHAIN (arg1_tree) = arg2_tree;
4944 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4945 ffecom_gfrt_kindtype (gfrt),
4946 FALSE,
4947 NULL_TREE,
4948 arg1_tree,
4949 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
4950 if (arg3_tree != NULL_TREE) {
4951 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
4952 convert (TREE_TYPE (arg3_tree),
4953 expr_tree));
4954 }
4955 }
4956 return expr_tree;
4957
4958 case FFEINTRIN_impKILL_subr:
4959 {
4960 tree arg1_tree;
4961 tree arg2_tree;
4962 tree arg3_tree;
4963
4964 ffecom_push_calltemps ();
4965
4966 arg1_tree = convert (ffecom_f2c_integer_type_node,
4967 ffecom_expr (arg1));
4968 arg1_tree = ffecom_1 (ADDR_EXPR,
4969 build_pointer_type (TREE_TYPE (arg1_tree)),
4970 arg1_tree);
4971
4972 arg2_tree = convert (ffecom_f2c_integer_type_node,
4973 ffecom_expr (arg2));
4974 arg2_tree = ffecom_1 (ADDR_EXPR,
4975 build_pointer_type (TREE_TYPE (arg2_tree)),
4976 arg2_tree);
4977
4978 if (arg3 == NULL)
4979 arg3_tree = NULL_TREE;
4980 else
4981 arg3_tree = ffecom_expr_rw (arg3);
4982
4983 ffecom_pop_calltemps ();
4984
4985 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4986 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4987 TREE_CHAIN (arg1_tree) = arg2_tree;
4988 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4989 ffecom_gfrt_kindtype (gfrt),
4990 FALSE,
4991 NULL_TREE,
4992 arg1_tree,
4993 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
4994 if (arg3_tree != NULL_TREE) {
4995 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
4996 convert (TREE_TYPE (arg3_tree),
4997 expr_tree));
4998 }
4999 }
5000 return expr_tree;
5001
5002 case FFEINTRIN_impCTIME_subr:
5003 case FFEINTRIN_impTTYNAM_subr:
5004 {
5005 tree arg1_len = integer_zero_node;
5006 tree arg1_tree;
5007 tree arg2_tree;
5008
5009 ffecom_push_calltemps ();
5010
5011 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5012
5013 arg2_tree = convert (((gfrt == FFEINTRIN_impCTIME_subr) ?
5014 ffecom_f2c_longint_type_node :
5015 ffecom_f2c_integer_type_node),
5016 ffecom_expr (arg2));
5017 arg2_tree = ffecom_1 (ADDR_EXPR,
5018 build_pointer_type (TREE_TYPE (arg2_tree)),
5019 arg2_tree);
5020
5021 ffecom_pop_calltemps ();
5022
5023 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5024 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5025 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5026 TREE_CHAIN (arg1_len) = arg2_tree;
5027 TREE_CHAIN (arg1_tree) = arg1_len;
5028
5029 expr_tree
5030 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5031 ffecom_gfrt_kindtype (gfrt),
5032 FALSE,
5033 NULL_TREE,
5034 arg1_tree,
5035 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
5036 }
5037 return expr_tree;
5038
5039 case FFEINTRIN_impIRAND:
5040 case FFEINTRIN_impRAND:
5041 /* Arg defaults to 0 (normal random case) */
5042 {
5043 tree arg1_tree;
5044
5045 if (arg1 == NULL)
5046 arg1_tree = ffecom_integer_zero_node;
5047 else
5048 arg1_tree = ffecom_expr (arg1);
5049 arg1_tree = convert (ffecom_f2c_integer_type_node,
5050 arg1_tree);
5051 arg1_tree = ffecom_1 (ADDR_EXPR,
5052 build_pointer_type (TREE_TYPE (arg1_tree)),
5053 arg1_tree);
5054 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5055
5056 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5057 ffecom_gfrt_kindtype (gfrt),
5058 FALSE,
5059 ((codegen_imp == FFEINTRIN_impIRAND) ?
5060 ffecom_f2c_integer_type_node :
5061 ffecom_f2c_doublereal_type_node),
5062 arg1_tree,
5063 dest_tree, dest, dest_used,
5064 NULL_TREE, TRUE);
5065 }
5066 return expr_tree;
5067
5068 case FFEINTRIN_impFTELL_subr:
5069 case FFEINTRIN_impUMASK_subr:
5070 {
5071 tree arg1_tree;
5072 tree arg2_tree;
5073
5074 ffecom_push_calltemps ();
5075
5076 arg1_tree = convert (ffecom_f2c_integer_type_node,
5077 ffecom_expr (arg1));
5078 arg1_tree = ffecom_1 (ADDR_EXPR,
5079 build_pointer_type (TREE_TYPE (arg1_tree)),
5080 arg1_tree);
5081
5082 if (arg2 == NULL)
5083 arg2_tree = NULL_TREE;
5084 else
5085 arg2_tree = ffecom_expr_rw (arg2);
5086
5087 ffecom_pop_calltemps ();
5088
5089 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5090 ffecom_gfrt_kindtype (gfrt),
5091 FALSE,
5092 NULL_TREE,
5093 build_tree_list (NULL_TREE, arg1_tree),
5094 NULL_TREE, NULL, NULL, NULL_TREE,
5095 TRUE);
5096 if (arg2_tree != NULL_TREE) {
5097 expr_tree = ffecom_modify (NULL_TREE, arg2_tree,
5098 convert (TREE_TYPE (arg2_tree),
5099 expr_tree));
5100 }
5101 }
5102 return expr_tree;
5103
5104 case FFEINTRIN_impCPU_TIME:
5105 case FFEINTRIN_impSECOND_subr:
5106 {
5107 tree arg1_tree;
5108
5109 ffecom_push_calltemps ();
5110
5111 arg1_tree = ffecom_expr_rw (arg1);
5112
5113 ffecom_pop_calltemps ();
5114
5115 expr_tree
5116 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5117 ffecom_gfrt_kindtype (gfrt),
5118 FALSE,
5119 NULL_TREE,
5120 NULL_TREE,
5121 NULL_TREE, NULL, NULL, NULL_TREE, TRUE);
5122
5123 expr_tree
5124 = ffecom_modify (NULL_TREE, arg1_tree,
5125 convert (TREE_TYPE (arg1_tree),
5126 expr_tree));
5127 }
5128 return expr_tree;
5129
5130 case FFEINTRIN_impDTIME_subr:
5131 case FFEINTRIN_impETIME_subr:
5132 {
5133 tree arg1_tree;
5134 tree arg2_tree;
5135
5136 ffecom_push_calltemps ();
5137
5138 arg1_tree = ffecom_expr_rw (arg1);
5139
5140 arg2_tree = ffecom_ptr_to_expr (arg2);
5141
5142 ffecom_pop_calltemps ();
5143
5144 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5145 ffecom_gfrt_kindtype (gfrt),
5146 FALSE,
5147 NULL_TREE,
5148 build_tree_list (NULL_TREE, arg2_tree),
5149 NULL_TREE, NULL, NULL, NULL_TREE,
5150 TRUE);
5151 expr_tree = ffecom_modify (NULL_TREE, arg1_tree,
5152 convert (TREE_TYPE (arg1_tree),
5153 expr_tree));
5154 }
5155 return expr_tree;
5156
5157 /* Straightforward calls of libf2c routines: */
5158 case FFEINTRIN_impABORT:
5159 case FFEINTRIN_impACCESS:
5160 case FFEINTRIN_impBESJ0:
5161 case FFEINTRIN_impBESJ1:
5162 case FFEINTRIN_impBESJN:
5163 case FFEINTRIN_impBESY0:
5164 case FFEINTRIN_impBESY1:
5165 case FFEINTRIN_impBESYN:
5166 case FFEINTRIN_impCHDIR_func:
5167 case FFEINTRIN_impCHMOD_func:
5168 case FFEINTRIN_impDATE:
5169 case FFEINTRIN_impDBESJ0:
5170 case FFEINTRIN_impDBESJ1:
5171 case FFEINTRIN_impDBESJN:
5172 case FFEINTRIN_impDBESY0:
5173 case FFEINTRIN_impDBESY1:
5174 case FFEINTRIN_impDBESYN:
5175 case FFEINTRIN_impDTIME_func:
5176 case FFEINTRIN_impETIME_func:
5177 case FFEINTRIN_impFGETC_func:
5178 case FFEINTRIN_impFGET_func:
5179 case FFEINTRIN_impFNUM:
5180 case FFEINTRIN_impFPUTC_func:
5181 case FFEINTRIN_impFPUT_func:
5182 case FFEINTRIN_impFSEEK:
5183 case FFEINTRIN_impFSTAT_func:
5184 case FFEINTRIN_impFTELL_func:
5185 case FFEINTRIN_impGERROR:
5186 case FFEINTRIN_impGETARG:
5187 case FFEINTRIN_impGETCWD_func:
5188 case FFEINTRIN_impGETENV:
5189 case FFEINTRIN_impGETGID:
5190 case FFEINTRIN_impGETLOG:
5191 case FFEINTRIN_impGETPID:
5192 case FFEINTRIN_impGETUID:
5193 case FFEINTRIN_impGMTIME:
5194 case FFEINTRIN_impHOSTNM_func:
5195 case FFEINTRIN_impIDATE_unix:
5196 case FFEINTRIN_impIDATE_vxt:
5197 case FFEINTRIN_impIERRNO:
5198 case FFEINTRIN_impISATTY:
5199 case FFEINTRIN_impITIME:
5200 case FFEINTRIN_impKILL_func:
5201 case FFEINTRIN_impLINK_func:
5202 case FFEINTRIN_impLNBLNK:
5203 case FFEINTRIN_impLSTAT_func:
5204 case FFEINTRIN_impLTIME:
5205 case FFEINTRIN_impMCLOCK8:
5206 case FFEINTRIN_impMCLOCK:
5207 case FFEINTRIN_impPERROR:
5208 case FFEINTRIN_impRENAME_func:
5209 case FFEINTRIN_impSECNDS:
5210 case FFEINTRIN_impSECOND_func:
5211 case FFEINTRIN_impSLEEP:
5212 case FFEINTRIN_impSRAND:
5213 case FFEINTRIN_impSTAT_func:
5214 case FFEINTRIN_impSYMLNK_func:
5215 case FFEINTRIN_impSYSTEM_CLOCK:
5216 case FFEINTRIN_impSYSTEM_func:
5217 case FFEINTRIN_impTIME8:
5218 case FFEINTRIN_impTIME_unix:
5219 case FFEINTRIN_impTIME_vxt:
5220 case FFEINTRIN_impUMASK_func:
5221 case FFEINTRIN_impUNLINK_func:
5222 break;
5223
5224 case FFEINTRIN_impCTIME_func: /* CHARACTER functions not handled here. */
5225 case FFEINTRIN_impFDATE_func: /* CHARACTER functions not handled here. */
5226 case FFEINTRIN_impTTYNAM_func: /* CHARACTER functions not handled here. */
5227 case FFEINTRIN_impNONE:
5228 case FFEINTRIN_imp: /* Hush up gcc warning. */
5229 fprintf (stderr, "No %s implementation.\n",
5230 ffeintrin_name_implementation (ffebld_symter_implementation (ffebld_left (expr))));
5231 assert ("unimplemented intrinsic" == NULL);
5232 return error_mark_node;
5233 }
5234
5235 assert (gfrt != FFECOM_gfrt); /* Must have an implementation! */
5236
5237 ffecom_push_calltemps ();
5238 expr_tree = ffecom_arglist_expr_ (ffecom_gfrt_args_ (gfrt),
5239 ffebld_right (expr));
5240 ffecom_pop_calltemps ();
5241
5242 return ffecom_call_ (ffecom_gfrt_tree_ (gfrt), ffecom_gfrt_kindtype (gfrt),
5243 (ffe_is_f2c_library () && ffecom_gfrt_complex_[gfrt]),
5244 tree_type,
5245 expr_tree, dest_tree, dest, dest_used,
5246 NULL_TREE, TRUE);
5247
5248 /**INDENT* (Do not reformat this comment even with -fca option.)
5249 Data-gathering files: Given the source file listed below, compiled with
5250 f2c I obtained the output file listed after that, and from the output
5251 file I derived the above code.
5252
5253 -------- (begin input file to f2c)
5254 implicit none
5255 character*10 A1,A2
5256 complex C1,C2
5257 integer I1,I2
5258 real R1,R2
5259 double precision D1,D2
5260 C
5261 call getem(A1,A2,C1,C2,I1,I2,R1,R2,D1,D2)
5262 c /
5263 call fooI(I1/I2)
5264 call fooR(R1/I1)
5265 call fooD(D1/I1)
5266 call fooC(C1/I1)
5267 call fooR(R1/R2)
5268 call fooD(R1/D1)
5269 call fooD(D1/D2)
5270 call fooD(D1/R1)
5271 call fooC(C1/C2)
5272 call fooC(C1/R1)
5273 call fooZ(C1/D1)
5274 c **
5275 call fooI(I1**I2)
5276 call fooR(R1**I1)
5277 call fooD(D1**I1)
5278 call fooC(C1**I1)
5279 call fooR(R1**R2)
5280 call fooD(R1**D1)
5281 call fooD(D1**D2)
5282 call fooD(D1**R1)
5283 call fooC(C1**C2)
5284 call fooC(C1**R1)
5285 call fooZ(C1**D1)
5286 c FFEINTRIN_impABS
5287 call fooR(ABS(R1))
5288 c FFEINTRIN_impACOS
5289 call fooR(ACOS(R1))
5290 c FFEINTRIN_impAIMAG
5291 call fooR(AIMAG(C1))
5292 c FFEINTRIN_impAINT
5293 call fooR(AINT(R1))
5294 c FFEINTRIN_impALOG
5295 call fooR(ALOG(R1))
5296 c FFEINTRIN_impALOG10
5297 call fooR(ALOG10(R1))
5298 c FFEINTRIN_impAMAX0
5299 call fooR(AMAX0(I1,I2))
5300 c FFEINTRIN_impAMAX1
5301 call fooR(AMAX1(R1,R2))
5302 c FFEINTRIN_impAMIN0
5303 call fooR(AMIN0(I1,I2))
5304 c FFEINTRIN_impAMIN1
5305 call fooR(AMIN1(R1,R2))
5306 c FFEINTRIN_impAMOD
5307 call fooR(AMOD(R1,R2))
5308 c FFEINTRIN_impANINT
5309 call fooR(ANINT(R1))
5310 c FFEINTRIN_impASIN
5311 call fooR(ASIN(R1))
5312 c FFEINTRIN_impATAN
5313 call fooR(ATAN(R1))
5314 c FFEINTRIN_impATAN2
5315 call fooR(ATAN2(R1,R2))
5316 c FFEINTRIN_impCABS
5317 call fooR(CABS(C1))
5318 c FFEINTRIN_impCCOS
5319 call fooC(CCOS(C1))
5320 c FFEINTRIN_impCEXP
5321 call fooC(CEXP(C1))
5322 c FFEINTRIN_impCHAR
5323 call fooA(CHAR(I1))
5324 c FFEINTRIN_impCLOG
5325 call fooC(CLOG(C1))
5326 c FFEINTRIN_impCONJG
5327 call fooC(CONJG(C1))
5328 c FFEINTRIN_impCOS
5329 call fooR(COS(R1))
5330 c FFEINTRIN_impCOSH
5331 call fooR(COSH(R1))
5332 c FFEINTRIN_impCSIN
5333 call fooC(CSIN(C1))
5334 c FFEINTRIN_impCSQRT
5335 call fooC(CSQRT(C1))
5336 c FFEINTRIN_impDABS
5337 call fooD(DABS(D1))
5338 c FFEINTRIN_impDACOS
5339 call fooD(DACOS(D1))
5340 c FFEINTRIN_impDASIN
5341 call fooD(DASIN(D1))
5342 c FFEINTRIN_impDATAN
5343 call fooD(DATAN(D1))
5344 c FFEINTRIN_impDATAN2
5345 call fooD(DATAN2(D1,D2))
5346 c FFEINTRIN_impDCOS
5347 call fooD(DCOS(D1))
5348 c FFEINTRIN_impDCOSH
5349 call fooD(DCOSH(D1))
5350 c FFEINTRIN_impDDIM
5351 call fooD(DDIM(D1,D2))
5352 c FFEINTRIN_impDEXP
5353 call fooD(DEXP(D1))
5354 c FFEINTRIN_impDIM
5355 call fooR(DIM(R1,R2))
5356 c FFEINTRIN_impDINT
5357 call fooD(DINT(D1))
5358 c FFEINTRIN_impDLOG
5359 call fooD(DLOG(D1))
5360 c FFEINTRIN_impDLOG10
5361 call fooD(DLOG10(D1))
5362 c FFEINTRIN_impDMAX1
5363 call fooD(DMAX1(D1,D2))
5364 c FFEINTRIN_impDMIN1
5365 call fooD(DMIN1(D1,D2))
5366 c FFEINTRIN_impDMOD
5367 call fooD(DMOD(D1,D2))
5368 c FFEINTRIN_impDNINT
5369 call fooD(DNINT(D1))
5370 c FFEINTRIN_impDPROD
5371 call fooD(DPROD(R1,R2))
5372 c FFEINTRIN_impDSIGN
5373 call fooD(DSIGN(D1,D2))
5374 c FFEINTRIN_impDSIN
5375 call fooD(DSIN(D1))
5376 c FFEINTRIN_impDSINH
5377 call fooD(DSINH(D1))
5378 c FFEINTRIN_impDSQRT
5379 call fooD(DSQRT(D1))
5380 c FFEINTRIN_impDTAN
5381 call fooD(DTAN(D1))
5382 c FFEINTRIN_impDTANH
5383 call fooD(DTANH(D1))
5384 c FFEINTRIN_impEXP
5385 call fooR(EXP(R1))
5386 c FFEINTRIN_impIABS
5387 call fooI(IABS(I1))
5388 c FFEINTRIN_impICHAR
5389 call fooI(ICHAR(A1))
5390 c FFEINTRIN_impIDIM
5391 call fooI(IDIM(I1,I2))
5392 c FFEINTRIN_impIDNINT
5393 call fooI(IDNINT(D1))
5394 c FFEINTRIN_impINDEX
5395 call fooI(INDEX(A1,A2))
5396 c FFEINTRIN_impISIGN
5397 call fooI(ISIGN(I1,I2))
5398 c FFEINTRIN_impLEN
5399 call fooI(LEN(A1))
5400 c FFEINTRIN_impLGE
5401 call fooL(LGE(A1,A2))
5402 c FFEINTRIN_impLGT
5403 call fooL(LGT(A1,A2))
5404 c FFEINTRIN_impLLE
5405 call fooL(LLE(A1,A2))
5406 c FFEINTRIN_impLLT
5407 call fooL(LLT(A1,A2))
5408 c FFEINTRIN_impMAX0
5409 call fooI(MAX0(I1,I2))
5410 c FFEINTRIN_impMAX1
5411 call fooI(MAX1(R1,R2))
5412 c FFEINTRIN_impMIN0
5413 call fooI(MIN0(I1,I2))
5414 c FFEINTRIN_impMIN1
5415 call fooI(MIN1(R1,R2))
5416 c FFEINTRIN_impMOD
5417 call fooI(MOD(I1,I2))
5418 c FFEINTRIN_impNINT
5419 call fooI(NINT(R1))
5420 c FFEINTRIN_impSIGN
5421 call fooR(SIGN(R1,R2))
5422 c FFEINTRIN_impSIN
5423 call fooR(SIN(R1))
5424 c FFEINTRIN_impSINH
5425 call fooR(SINH(R1))
5426 c FFEINTRIN_impSQRT
5427 call fooR(SQRT(R1))
5428 c FFEINTRIN_impTAN
5429 call fooR(TAN(R1))
5430 c FFEINTRIN_impTANH
5431 call fooR(TANH(R1))
5432 c FFEINTRIN_imp_CMPLX_C
5433 call fooC(cmplx(C1,C2))
5434 c FFEINTRIN_imp_CMPLX_D
5435 call fooZ(cmplx(D1,D2))
5436 c FFEINTRIN_imp_CMPLX_I
5437 call fooC(cmplx(I1,I2))
5438 c FFEINTRIN_imp_CMPLX_R
5439 call fooC(cmplx(R1,R2))
5440 c FFEINTRIN_imp_DBLE_C
5441 call fooD(dble(C1))
5442 c FFEINTRIN_imp_DBLE_D
5443 call fooD(dble(D1))
5444 c FFEINTRIN_imp_DBLE_I
5445 call fooD(dble(I1))
5446 c FFEINTRIN_imp_DBLE_R
5447 call fooD(dble(R1))
5448 c FFEINTRIN_imp_INT_C
5449 call fooI(int(C1))
5450 c FFEINTRIN_imp_INT_D
5451 call fooI(int(D1))
5452 c FFEINTRIN_imp_INT_I
5453 call fooI(int(I1))
5454 c FFEINTRIN_imp_INT_R
5455 call fooI(int(R1))
5456 c FFEINTRIN_imp_REAL_C
5457 call fooR(real(C1))
5458 c FFEINTRIN_imp_REAL_D
5459 call fooR(real(D1))
5460 c FFEINTRIN_imp_REAL_I
5461 call fooR(real(I1))
5462 c FFEINTRIN_imp_REAL_R
5463 call fooR(real(R1))
5464 c
5465 c FFEINTRIN_imp_INT_D:
5466 c
5467 c FFEINTRIN_specIDINT
5468 call fooI(IDINT(D1))
5469 c
5470 c FFEINTRIN_imp_INT_R:
5471 c
5472 c FFEINTRIN_specIFIX
5473 call fooI(IFIX(R1))
5474 c FFEINTRIN_specINT
5475 call fooI(INT(R1))
5476 c
5477 c FFEINTRIN_imp_REAL_D:
5478 c
5479 c FFEINTRIN_specSNGL
5480 call fooR(SNGL(D1))
5481 c
5482 c FFEINTRIN_imp_REAL_I:
5483 c
5484 c FFEINTRIN_specFLOAT
5485 call fooR(FLOAT(I1))
5486 c FFEINTRIN_specREAL
5487 call fooR(REAL(I1))
5488 c
5489 end
5490 -------- (end input file to f2c)
5491
5492 -------- (begin output from providing above input file as input to:
5493 -------- `f2c | gcc -E -C - | sed -e "s:/[*]*://:g" -e "s:[*]*[/]://:g" \
5494 -------- -e "s:^#.*$::g"')
5495
5496 // -- translated by f2c (version 19950223).
5497 You must link the resulting object file with the libraries:
5498 -lf2c -lm (in that order)
5499 //
5500
5501
5502 // f2c.h -- Standard Fortran to C header file //
5503
5504 /// barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed."
5505
5506 - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) //
5507
5508
5509
5510
5511 // F2C_INTEGER will normally be `int' but would be `long' on 16-bit systems //
5512 // we assume short, float are OK //
5513 typedef long int // long int // integer;
5514 typedef char *address;
5515 typedef short int shortint;
5516 typedef float real;
5517 typedef double doublereal;
5518 typedef struct { real r, i; } complex;
5519 typedef struct { doublereal r, i; } doublecomplex;
5520 typedef long int // long int // logical;
5521 typedef short int shortlogical;
5522 typedef char logical1;
5523 typedef char integer1;
5524 // typedef long long longint; // // system-dependent //
5525
5526
5527
5528
5529 // Extern is for use with -E //
5530
5531
5532
5533
5534 // I/O stuff //
5535
5536
5537
5538
5539
5540
5541
5542
5543 typedef long int // int or long int // flag;
5544 typedef long int // int or long int // ftnlen;
5545 typedef long int // int or long int // ftnint;
5546
5547
5548 //external read, write//
5549 typedef struct
5550 { flag cierr;
5551 ftnint ciunit;
5552 flag ciend;
5553 char *cifmt;
5554 ftnint cirec;
5555 } cilist;
5556
5557 //internal read, write//
5558 typedef struct
5559 { flag icierr;
5560 char *iciunit;
5561 flag iciend;
5562 char *icifmt;
5563 ftnint icirlen;
5564 ftnint icirnum;
5565 } icilist;
5566
5567 //open//
5568 typedef struct
5569 { flag oerr;
5570 ftnint ounit;
5571 char *ofnm;
5572 ftnlen ofnmlen;
5573 char *osta;
5574 char *oacc;
5575 char *ofm;
5576 ftnint orl;
5577 char *oblnk;
5578 } olist;
5579
5580 //close//
5581 typedef struct
5582 { flag cerr;
5583 ftnint cunit;
5584 char *csta;
5585 } cllist;
5586
5587 //rewind, backspace, endfile//
5588 typedef struct
5589 { flag aerr;
5590 ftnint aunit;
5591 } alist;
5592
5593 // inquire //
5594 typedef struct
5595 { flag inerr;
5596 ftnint inunit;
5597 char *infile;
5598 ftnlen infilen;
5599 ftnint *inex; //parameters in standard's order//
5600 ftnint *inopen;
5601 ftnint *innum;
5602 ftnint *innamed;
5603 char *inname;
5604 ftnlen innamlen;
5605 char *inacc;
5606 ftnlen inacclen;
5607 char *inseq;
5608 ftnlen inseqlen;
5609 char *indir;
5610 ftnlen indirlen;
5611 char *infmt;
5612 ftnlen infmtlen;
5613 char *inform;
5614 ftnint informlen;
5615 char *inunf;
5616 ftnlen inunflen;
5617 ftnint *inrecl;
5618 ftnint *innrec;
5619 char *inblank;
5620 ftnlen inblanklen;
5621 } inlist;
5622
5623
5624
5625 union Multitype { // for multiple entry points //
5626 integer1 g;
5627 shortint h;
5628 integer i;
5629 // longint j; //
5630 real r;
5631 doublereal d;
5632 complex c;
5633 doublecomplex z;
5634 };
5635
5636 typedef union Multitype Multitype;
5637
5638 typedef long Long; // No longer used; formerly in Namelist //
5639
5640 struct Vardesc { // for Namelist //
5641 char *name;
5642 char *addr;
5643 ftnlen *dims;
5644 int type;
5645 };
5646 typedef struct Vardesc Vardesc;
5647
5648 struct Namelist {
5649 char *name;
5650 Vardesc **vars;
5651 int nvars;
5652 };
5653 typedef struct Namelist Namelist;
5654
5655
5656
5657
5658
5659
5660
5661
5662 // procedure parameter types for -A and -C++ //
5663
5664
5665
5666
5667 typedef int // Unknown procedure type // (*U_fp)();
5668 typedef shortint (*J_fp)();
5669 typedef integer (*I_fp)();
5670 typedef real (*R_fp)();
5671 typedef doublereal (*D_fp)(), (*E_fp)();
5672 typedef // Complex // void (*C_fp)();
5673 typedef // Double Complex // void (*Z_fp)();
5674 typedef logical (*L_fp)();
5675 typedef shortlogical (*K_fp)();
5676 typedef // Character // void (*H_fp)();
5677 typedef // Subroutine // int (*S_fp)();
5678
5679 // E_fp is for real functions when -R is not specified //
5680 typedef void C_f; // complex function //
5681 typedef void H_f; // character function //
5682 typedef void Z_f; // double complex function //
5683 typedef doublereal E_f; // real function with -R not specified //
5684
5685 // undef any lower-case symbols that your C compiler predefines, e.g.: //
5686
5687
5688 // (No such symbols should be defined in a strict ANSI C compiler.
5689 We can avoid trouble with f2c-translated code by using
5690 gcc -ansi [-traditional].) //
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714 // Main program // MAIN__()
5715 {
5716 // System generated locals //
5717 integer i__1;
5718 real r__1, r__2;
5719 doublereal d__1, d__2;
5720 complex q__1;
5721 doublecomplex z__1, z__2, z__3;
5722 logical L__1;
5723 char ch__1[1];
5724
5725 // Builtin functions //
5726 void c_div();
5727 integer pow_ii();
5728 double pow_ri(), pow_di();
5729 void pow_ci();
5730 double pow_dd();
5731 void pow_zz();
5732 double acos(), r_imag(), r_int(), log(), r_lg10(), r_mod(), r_nint(),
5733 asin(), atan(), atan2(), c_abs();
5734 void c_cos(), c_exp(), c_log(), r_cnjg();
5735 double cos(), cosh();
5736 void c_sin(), c_sqrt();
5737 double d_dim(), exp(), r_dim(), d_int(), d_lg10(), d_mod(), d_nint(),
5738 d_sign(), sin(), sinh(), sqrt(), tan(), tanh();
5739 integer i_dim(), i_dnnt(), i_indx(), i_sign(), i_len();
5740 logical l_ge(), l_gt(), l_le(), l_lt();
5741 integer i_nint();
5742 double r_sign();
5743
5744 // Local variables //
5745 extern // Subroutine // int fooa_(), fooc_(), food_(), fooi_(), foor_(),
5746 fool_(), fooz_(), getem_();
5747 static char a1[10], a2[10];
5748 static complex c1, c2;
5749 static doublereal d1, d2;
5750 static integer i1, i2;
5751 static real r1, r2;
5752
5753
5754 getem_(a1, a2, &c1, &c2, &i1, &i2, &r1, &r2, &d1, &d2, 10L, 10L);
5755 // / //
5756 i__1 = i1 / i2;
5757 fooi_(&i__1);
5758 r__1 = r1 / i1;
5759 foor_(&r__1);
5760 d__1 = d1 / i1;
5761 food_(&d__1);
5762 d__1 = (doublereal) i1;
5763 q__1.r = c1.r / d__1, q__1.i = c1.i / d__1;
5764 fooc_(&q__1);
5765 r__1 = r1 / r2;
5766 foor_(&r__1);
5767 d__1 = r1 / d1;
5768 food_(&d__1);
5769 d__1 = d1 / d2;
5770 food_(&d__1);
5771 d__1 = d1 / r1;
5772 food_(&d__1);
5773 c_div(&q__1, &c1, &c2);
5774 fooc_(&q__1);
5775 q__1.r = c1.r / r1, q__1.i = c1.i / r1;
5776 fooc_(&q__1);
5777 z__1.r = c1.r / d1, z__1.i = c1.i / d1;
5778 fooz_(&z__1);
5779 // ** //
5780 i__1 = pow_ii(&i1, &i2);
5781 fooi_(&i__1);
5782 r__1 = pow_ri(&r1, &i1);
5783 foor_(&r__1);
5784 d__1 = pow_di(&d1, &i1);
5785 food_(&d__1);
5786 pow_ci(&q__1, &c1, &i1);
5787 fooc_(&q__1);
5788 d__1 = (doublereal) r1;
5789 d__2 = (doublereal) r2;
5790 r__1 = pow_dd(&d__1, &d__2);
5791 foor_(&r__1);
5792 d__2 = (doublereal) r1;
5793 d__1 = pow_dd(&d__2, &d1);
5794 food_(&d__1);
5795 d__1 = pow_dd(&d1, &d2);
5796 food_(&d__1);
5797 d__2 = (doublereal) r1;
5798 d__1 = pow_dd(&d1, &d__2);
5799 food_(&d__1);
5800 z__2.r = c1.r, z__2.i = c1.i;
5801 z__3.r = c2.r, z__3.i = c2.i;
5802 pow_zz(&z__1, &z__2, &z__3);
5803 q__1.r = z__1.r, q__1.i = z__1.i;
5804 fooc_(&q__1);
5805 z__2.r = c1.r, z__2.i = c1.i;
5806 z__3.r = r1, z__3.i = 0.;
5807 pow_zz(&z__1, &z__2, &z__3);
5808 q__1.r = z__1.r, q__1.i = z__1.i;
5809 fooc_(&q__1);
5810 z__2.r = c1.r, z__2.i = c1.i;
5811 z__3.r = d1, z__3.i = 0.;
5812 pow_zz(&z__1, &z__2, &z__3);
5813 fooz_(&z__1);
5814 // FFEINTRIN_impABS //
5815 r__1 = (doublereal)(( r1 ) >= 0 ? ( r1 ) : -( r1 )) ;
5816 foor_(&r__1);
5817 // FFEINTRIN_impACOS //
5818 r__1 = acos(r1);
5819 foor_(&r__1);
5820 // FFEINTRIN_impAIMAG //
5821 r__1 = r_imag(&c1);
5822 foor_(&r__1);
5823 // FFEINTRIN_impAINT //
5824 r__1 = r_int(&r1);
5825 foor_(&r__1);
5826 // FFEINTRIN_impALOG //
5827 r__1 = log(r1);
5828 foor_(&r__1);
5829 // FFEINTRIN_impALOG10 //
5830 r__1 = r_lg10(&r1);
5831 foor_(&r__1);
5832 // FFEINTRIN_impAMAX0 //
5833 r__1 = (real) (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
5834 foor_(&r__1);
5835 // FFEINTRIN_impAMAX1 //
5836 r__1 = (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
5837 foor_(&r__1);
5838 // FFEINTRIN_impAMIN0 //
5839 r__1 = (real) (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
5840 foor_(&r__1);
5841 // FFEINTRIN_impAMIN1 //
5842 r__1 = (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
5843 foor_(&r__1);
5844 // FFEINTRIN_impAMOD //
5845 r__1 = r_mod(&r1, &r2);
5846 foor_(&r__1);
5847 // FFEINTRIN_impANINT //
5848 r__1 = r_nint(&r1);
5849 foor_(&r__1);
5850 // FFEINTRIN_impASIN //
5851 r__1 = asin(r1);
5852 foor_(&r__1);
5853 // FFEINTRIN_impATAN //
5854 r__1 = atan(r1);
5855 foor_(&r__1);
5856 // FFEINTRIN_impATAN2 //
5857 r__1 = atan2(r1, r2);
5858 foor_(&r__1);
5859 // FFEINTRIN_impCABS //
5860 r__1 = c_abs(&c1);
5861 foor_(&r__1);
5862 // FFEINTRIN_impCCOS //
5863 c_cos(&q__1, &c1);
5864 fooc_(&q__1);
5865 // FFEINTRIN_impCEXP //
5866 c_exp(&q__1, &c1);
5867 fooc_(&q__1);
5868 // FFEINTRIN_impCHAR //
5869 *(unsigned char *)&ch__1[0] = i1;
5870 fooa_(ch__1, 1L);
5871 // FFEINTRIN_impCLOG //
5872 c_log(&q__1, &c1);
5873 fooc_(&q__1);
5874 // FFEINTRIN_impCONJG //
5875 r_cnjg(&q__1, &c1);
5876 fooc_(&q__1);
5877 // FFEINTRIN_impCOS //
5878 r__1 = cos(r1);
5879 foor_(&r__1);
5880 // FFEINTRIN_impCOSH //
5881 r__1 = cosh(r1);
5882 foor_(&r__1);
5883 // FFEINTRIN_impCSIN //
5884 c_sin(&q__1, &c1);
5885 fooc_(&q__1);
5886 // FFEINTRIN_impCSQRT //
5887 c_sqrt(&q__1, &c1);
5888 fooc_(&q__1);
5889 // FFEINTRIN_impDABS //
5890 d__1 = (( d1 ) >= 0 ? ( d1 ) : -( d1 )) ;
5891 food_(&d__1);
5892 // FFEINTRIN_impDACOS //
5893 d__1 = acos(d1);
5894 food_(&d__1);
5895 // FFEINTRIN_impDASIN //
5896 d__1 = asin(d1);
5897 food_(&d__1);
5898 // FFEINTRIN_impDATAN //
5899 d__1 = atan(d1);
5900 food_(&d__1);
5901 // FFEINTRIN_impDATAN2 //
5902 d__1 = atan2(d1, d2);
5903 food_(&d__1);
5904 // FFEINTRIN_impDCOS //
5905 d__1 = cos(d1);
5906 food_(&d__1);
5907 // FFEINTRIN_impDCOSH //
5908 d__1 = cosh(d1);
5909 food_(&d__1);
5910 // FFEINTRIN_impDDIM //
5911 d__1 = d_dim(&d1, &d2);
5912 food_(&d__1);
5913 // FFEINTRIN_impDEXP //
5914 d__1 = exp(d1);
5915 food_(&d__1);
5916 // FFEINTRIN_impDIM //
5917 r__1 = r_dim(&r1, &r2);
5918 foor_(&r__1);
5919 // FFEINTRIN_impDINT //
5920 d__1 = d_int(&d1);
5921 food_(&d__1);
5922 // FFEINTRIN_impDLOG //
5923 d__1 = log(d1);
5924 food_(&d__1);
5925 // FFEINTRIN_impDLOG10 //
5926 d__1 = d_lg10(&d1);
5927 food_(&d__1);
5928 // FFEINTRIN_impDMAX1 //
5929 d__1 = (( d1 ) >= ( d2 ) ? ( d1 ) : ( d2 )) ;
5930 food_(&d__1);
5931 // FFEINTRIN_impDMIN1 //
5932 d__1 = (( d1 ) <= ( d2 ) ? ( d1 ) : ( d2 )) ;
5933 food_(&d__1);
5934 // FFEINTRIN_impDMOD //
5935 d__1 = d_mod(&d1, &d2);
5936 food_(&d__1);
5937 // FFEINTRIN_impDNINT //
5938 d__1 = d_nint(&d1);
5939 food_(&d__1);
5940 // FFEINTRIN_impDPROD //
5941 d__1 = (doublereal) r1 * r2;
5942 food_(&d__1);
5943 // FFEINTRIN_impDSIGN //
5944 d__1 = d_sign(&d1, &d2);
5945 food_(&d__1);
5946 // FFEINTRIN_impDSIN //
5947 d__1 = sin(d1);
5948 food_(&d__1);
5949 // FFEINTRIN_impDSINH //
5950 d__1 = sinh(d1);
5951 food_(&d__1);
5952 // FFEINTRIN_impDSQRT //
5953 d__1 = sqrt(d1);
5954 food_(&d__1);
5955 // FFEINTRIN_impDTAN //
5956 d__1 = tan(d1);
5957 food_(&d__1);
5958 // FFEINTRIN_impDTANH //
5959 d__1 = tanh(d1);
5960 food_(&d__1);
5961 // FFEINTRIN_impEXP //
5962 r__1 = exp(r1);
5963 foor_(&r__1);
5964 // FFEINTRIN_impIABS //
5965 i__1 = (( i1 ) >= 0 ? ( i1 ) : -( i1 )) ;
5966 fooi_(&i__1);
5967 // FFEINTRIN_impICHAR //
5968 i__1 = *(unsigned char *)a1;
5969 fooi_(&i__1);
5970 // FFEINTRIN_impIDIM //
5971 i__1 = i_dim(&i1, &i2);
5972 fooi_(&i__1);
5973 // FFEINTRIN_impIDNINT //
5974 i__1 = i_dnnt(&d1);
5975 fooi_(&i__1);
5976 // FFEINTRIN_impINDEX //
5977 i__1 = i_indx(a1, a2, 10L, 10L);
5978 fooi_(&i__1);
5979 // FFEINTRIN_impISIGN //
5980 i__1 = i_sign(&i1, &i2);
5981 fooi_(&i__1);
5982 // FFEINTRIN_impLEN //
5983 i__1 = i_len(a1, 10L);
5984 fooi_(&i__1);
5985 // FFEINTRIN_impLGE //
5986 L__1 = l_ge(a1, a2, 10L, 10L);
5987 fool_(&L__1);
5988 // FFEINTRIN_impLGT //
5989 L__1 = l_gt(a1, a2, 10L, 10L);
5990 fool_(&L__1);
5991 // FFEINTRIN_impLLE //
5992 L__1 = l_le(a1, a2, 10L, 10L);
5993 fool_(&L__1);
5994 // FFEINTRIN_impLLT //
5995 L__1 = l_lt(a1, a2, 10L, 10L);
5996 fool_(&L__1);
5997 // FFEINTRIN_impMAX0 //
5998 i__1 = (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
5999 fooi_(&i__1);
6000 // FFEINTRIN_impMAX1 //
6001 i__1 = (integer) (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
6002 fooi_(&i__1);
6003 // FFEINTRIN_impMIN0 //
6004 i__1 = (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
6005 fooi_(&i__1);
6006 // FFEINTRIN_impMIN1 //
6007 i__1 = (integer) (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
6008 fooi_(&i__1);
6009 // FFEINTRIN_impMOD //
6010 i__1 = i1 % i2;
6011 fooi_(&i__1);
6012 // FFEINTRIN_impNINT //
6013 i__1 = i_nint(&r1);
6014 fooi_(&i__1);
6015 // FFEINTRIN_impSIGN //
6016 r__1 = r_sign(&r1, &r2);
6017 foor_(&r__1);
6018 // FFEINTRIN_impSIN //
6019 r__1 = sin(r1);
6020 foor_(&r__1);
6021 // FFEINTRIN_impSINH //
6022 r__1 = sinh(r1);
6023 foor_(&r__1);
6024 // FFEINTRIN_impSQRT //
6025 r__1 = sqrt(r1);
6026 foor_(&r__1);
6027 // FFEINTRIN_impTAN //
6028 r__1 = tan(r1);
6029 foor_(&r__1);
6030 // FFEINTRIN_impTANH //
6031 r__1 = tanh(r1);
6032 foor_(&r__1);
6033 // FFEINTRIN_imp_CMPLX_C //
6034 r__1 = c1.r;
6035 r__2 = c2.r;
6036 q__1.r = r__1, q__1.i = r__2;
6037 fooc_(&q__1);
6038 // FFEINTRIN_imp_CMPLX_D //
6039 z__1.r = d1, z__1.i = d2;
6040 fooz_(&z__1);
6041 // FFEINTRIN_imp_CMPLX_I //
6042 r__1 = (real) i1;
6043 r__2 = (real) i2;
6044 q__1.r = r__1, q__1.i = r__2;
6045 fooc_(&q__1);
6046 // FFEINTRIN_imp_CMPLX_R //
6047 q__1.r = r1, q__1.i = r2;
6048 fooc_(&q__1);
6049 // FFEINTRIN_imp_DBLE_C //
6050 d__1 = (doublereal) c1.r;
6051 food_(&d__1);
6052 // FFEINTRIN_imp_DBLE_D //
6053 d__1 = d1;
6054 food_(&d__1);
6055 // FFEINTRIN_imp_DBLE_I //
6056 d__1 = (doublereal) i1;
6057 food_(&d__1);
6058 // FFEINTRIN_imp_DBLE_R //
6059 d__1 = (doublereal) r1;
6060 food_(&d__1);
6061 // FFEINTRIN_imp_INT_C //
6062 i__1 = (integer) c1.r;
6063 fooi_(&i__1);
6064 // FFEINTRIN_imp_INT_D //
6065 i__1 = (integer) d1;
6066 fooi_(&i__1);
6067 // FFEINTRIN_imp_INT_I //
6068 i__1 = i1;
6069 fooi_(&i__1);
6070 // FFEINTRIN_imp_INT_R //
6071 i__1 = (integer) r1;
6072 fooi_(&i__1);
6073 // FFEINTRIN_imp_REAL_C //
6074 r__1 = c1.r;
6075 foor_(&r__1);
6076 // FFEINTRIN_imp_REAL_D //
6077 r__1 = (real) d1;
6078 foor_(&r__1);
6079 // FFEINTRIN_imp_REAL_I //
6080 r__1 = (real) i1;
6081 foor_(&r__1);
6082 // FFEINTRIN_imp_REAL_R //
6083 r__1 = r1;
6084 foor_(&r__1);
6085
6086 // FFEINTRIN_imp_INT_D: //
6087
6088 // FFEINTRIN_specIDINT //
6089 i__1 = (integer) d1;
6090 fooi_(&i__1);
6091
6092 // FFEINTRIN_imp_INT_R: //
6093
6094 // FFEINTRIN_specIFIX //
6095 i__1 = (integer) r1;
6096 fooi_(&i__1);
6097 // FFEINTRIN_specINT //
6098 i__1 = (integer) r1;
6099 fooi_(&i__1);
6100
6101 // FFEINTRIN_imp_REAL_D: //
6102
6103 // FFEINTRIN_specSNGL //
6104 r__1 = (real) d1;
6105 foor_(&r__1);
6106
6107 // FFEINTRIN_imp_REAL_I: //
6108
6109 // FFEINTRIN_specFLOAT //
6110 r__1 = (real) i1;
6111 foor_(&r__1);
6112 // FFEINTRIN_specREAL //
6113 r__1 = (real) i1;
6114 foor_(&r__1);
6115
6116 } // MAIN__ //
6117
6118 -------- (end output file from f2c)
6119
6120 */
6121 }
6122
6123 #endif
6124 /* For power (exponentiation) where right-hand operand is type INTEGER,
6125 generate in-line code to do it the fast way (which, if the operand
6126 is a constant, might just mean a series of multiplies). */
6127
6128 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6129 static tree
6130 ffecom_expr_power_integer_ (ffebld left, ffebld right)
6131 {
6132 tree l = ffecom_expr (left);
6133 tree r = ffecom_expr (right);
6134 tree ltype = TREE_TYPE (l);
6135 tree rtype = TREE_TYPE (r);
6136 tree result = NULL_TREE;
6137
6138 if (l == error_mark_node
6139 || r == error_mark_node)
6140 return error_mark_node;
6141
6142 if (TREE_CODE (r) == INTEGER_CST)
6143 {
6144 int sgn = tree_int_cst_sgn (r);
6145
6146 if (sgn == 0)
6147 return convert (ltype, integer_one_node);
6148
6149 if ((TREE_CODE (ltype) == INTEGER_TYPE)
6150 && (sgn < 0))
6151 {
6152 /* Reciprocal of integer is either 0, -1, or 1, so after
6153 calculating that (which we leave to the back end to do
6154 or not do optimally), don't bother with any multiplying. */
6155
6156 result = ffecom_tree_divide_ (ltype,
6157 convert (ltype, integer_one_node),
6158 l,
6159 NULL_TREE, NULL, NULL);
6160 r = ffecom_1 (NEGATE_EXPR,
6161 rtype,
6162 r);
6163 if ((TREE_INT_CST_LOW (r) & 1) == 0)
6164 result = ffecom_1 (ABS_EXPR, rtype,
6165 result);
6166 }
6167
6168 /* Generate appropriate series of multiplies, preceded
6169 by divide if the exponent is negative. */
6170
6171 l = save_expr (l);
6172
6173 if (sgn < 0)
6174 {
6175 l = ffecom_tree_divide_ (ltype,
6176 convert (ltype, integer_one_node),
6177 l,
6178 NULL_TREE, NULL, NULL);
6179 r = ffecom_1 (NEGATE_EXPR, rtype, r);
6180 assert (TREE_CODE (r) == INTEGER_CST);
6181
6182 if (tree_int_cst_sgn (r) < 0)
6183 { /* The "most negative" number. */
6184 r = ffecom_1 (NEGATE_EXPR, rtype,
6185 ffecom_2 (RSHIFT_EXPR, rtype,
6186 r,
6187 integer_one_node));
6188 l = save_expr (l);
6189 l = ffecom_2 (MULT_EXPR, ltype,
6190 l,
6191 l);
6192 }
6193 }
6194
6195 for (;;)
6196 {
6197 if (TREE_INT_CST_LOW (r) & 1)
6198 {
6199 if (result == NULL_TREE)
6200 result = l;
6201 else
6202 result = ffecom_2 (MULT_EXPR, ltype,
6203 result,
6204 l);
6205 }
6206
6207 r = ffecom_2 (RSHIFT_EXPR, rtype,
6208 r,
6209 integer_one_node);
6210 if (integer_zerop (r))
6211 break;
6212 assert (TREE_CODE (r) == INTEGER_CST);
6213
6214 l = save_expr (l);
6215 l = ffecom_2 (MULT_EXPR, ltype,
6216 l,
6217 l);
6218 }
6219 return result;
6220 }
6221
6222 /* Though rhs isn't a constant, in-line code cannot be expanded
6223 while transforming dummies
6224 because the back end cannot be easily convinced to generate
6225 stores (MODIFY_EXPR), handle temporaries, and so on before
6226 all the appropriate rtx's have been generated for things like
6227 dummy args referenced in rhs -- which doesn't happen until
6228 store_parm_decls() is called (expand_function_start, I believe,
6229 does the actual rtx-stuffing of PARM_DECLs).
6230
6231 So, in this case, let the caller generate the call to the
6232 run-time-library function to evaluate the power for us. */
6233
6234 if (ffecom_transform_only_dummies_)
6235 return NULL_TREE;
6236
6237 /* Right-hand operand not a constant, expand in-line code to figure
6238 out how to do the multiplies, &c.
6239
6240 The returned expression is expressed this way in GNU C, where l and
6241 r are the "inputs":
6242
6243 ({ typeof (r) rtmp = r;
6244 typeof (l) ltmp = l;
6245 typeof (l) result;
6246
6247 if (rtmp == 0)
6248 result = 1;
6249 else
6250 {
6251 if ((basetypeof (l) == basetypeof (int))
6252 && (rtmp < 0))
6253 {
6254 result = ((typeof (l)) 1) / ltmp;
6255 if ((ltmp < 0) && (((-rtmp) & 1) == 0))
6256 result = -result;
6257 }
6258 else
6259 {
6260 result = 1;
6261 if ((basetypeof (l) != basetypeof (int))
6262 && (rtmp < 0))
6263 {
6264 ltmp = ((typeof (l)) 1) / ltmp;
6265 rtmp = -rtmp;
6266 if (rtmp < 0)
6267 {
6268 rtmp = -(rtmp >> 1);
6269 ltmp *= ltmp;
6270 }
6271 }
6272 for (;;)
6273 {
6274 if (rtmp & 1)
6275 result *= ltmp;
6276 if ((rtmp >>= 1) == 0)
6277 break;
6278 ltmp *= ltmp;
6279 }
6280 }
6281 }
6282 result;
6283 })
6284
6285 Note that some of the above is compile-time collapsable, such as
6286 the first part of the if statements that checks the base type of
6287 l against int. The if statements are phrased that way to suggest
6288 an easy way to generate the if/else constructs here, knowing that
6289 the back end should (and probably does) eliminate the resulting
6290 dead code (either the int case or the non-int case), something
6291 it couldn't do without the redundant phrasing, requiring explicit
6292 dead-code elimination here, which would be kind of difficult to
6293 read. */
6294
6295 {
6296 tree rtmp;
6297 tree ltmp;
6298 tree basetypeof_l_is_int;
6299 tree se;
6300
6301 basetypeof_l_is_int
6302 = build_int_2 ((TREE_CODE (ltype) == INTEGER_TYPE), 0);
6303
6304 se = expand_start_stmt_expr ();
6305 ffecom_push_calltemps ();
6306
6307 rtmp = ffecom_push_tempvar (rtype, FFETARGET_charactersizeNONE, -1,
6308 TRUE);
6309 ltmp = ffecom_push_tempvar (ltype, FFETARGET_charactersizeNONE, -1,
6310 TRUE);
6311 result = ffecom_push_tempvar (ltype, FFETARGET_charactersizeNONE, -1,
6312 TRUE);
6313
6314 expand_expr_stmt (ffecom_modify (void_type_node,
6315 rtmp,
6316 r));
6317 expand_expr_stmt (ffecom_modify (void_type_node,
6318 ltmp,
6319 l));
6320 expand_start_cond (ffecom_truth_value
6321 (ffecom_2 (EQ_EXPR, integer_type_node,
6322 rtmp,
6323 convert (rtype, integer_zero_node))),
6324 0);
6325 expand_expr_stmt (ffecom_modify (void_type_node,
6326 result,
6327 convert (ltype, integer_one_node)));
6328 expand_start_else ();
6329 if (!integer_zerop (basetypeof_l_is_int))
6330 {
6331 expand_start_cond (ffecom_2 (LT_EXPR, integer_type_node,
6332 rtmp,
6333 convert (rtype,
6334 integer_zero_node)),
6335 0);
6336 expand_expr_stmt (ffecom_modify (void_type_node,
6337 result,
6338 ffecom_tree_divide_
6339 (ltype,
6340 convert (ltype, integer_one_node),
6341 ltmp,
6342 NULL_TREE, NULL, NULL)));
6343 expand_start_cond (ffecom_truth_value
6344 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
6345 ffecom_2 (LT_EXPR, integer_type_node,
6346 ltmp,
6347 convert (ltype,
6348 integer_zero_node)),
6349 ffecom_2 (EQ_EXPR, integer_type_node,
6350 ffecom_2 (BIT_AND_EXPR,
6351 rtype,
6352 ffecom_1 (NEGATE_EXPR,
6353 rtype,
6354 rtmp),
6355 convert (rtype,
6356 integer_one_node)),
6357 convert (rtype,
6358 integer_zero_node)))),
6359 0);
6360 expand_expr_stmt (ffecom_modify (void_type_node,
6361 result,
6362 ffecom_1 (NEGATE_EXPR,
6363 ltype,
6364 result)));
6365 expand_end_cond ();
6366 expand_start_else ();
6367 }
6368 expand_expr_stmt (ffecom_modify (void_type_node,
6369 result,
6370 convert (ltype, integer_one_node)));
6371 expand_start_cond (ffecom_truth_value
6372 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
6373 ffecom_truth_value_invert
6374 (basetypeof_l_is_int),
6375 ffecom_2 (LT_EXPR, integer_type_node,
6376 rtmp,
6377 convert (rtype,
6378 integer_zero_node)))),
6379 0);
6380 expand_expr_stmt (ffecom_modify (void_type_node,
6381 ltmp,
6382 ffecom_tree_divide_
6383 (ltype,
6384 convert (ltype, integer_one_node),
6385 ltmp,
6386 NULL_TREE, NULL, NULL)));
6387 expand_expr_stmt (ffecom_modify (void_type_node,
6388 rtmp,
6389 ffecom_1 (NEGATE_EXPR, rtype,
6390 rtmp)));
6391 expand_start_cond (ffecom_truth_value
6392 (ffecom_2 (LT_EXPR, integer_type_node,
6393 rtmp,
6394 convert (rtype, integer_zero_node))),
6395 0);
6396 expand_expr_stmt (ffecom_modify (void_type_node,
6397 rtmp,
6398 ffecom_1 (NEGATE_EXPR, rtype,
6399 ffecom_2 (RSHIFT_EXPR,
6400 rtype,
6401 rtmp,
6402 integer_one_node))));
6403 expand_expr_stmt (ffecom_modify (void_type_node,
6404 ltmp,
6405 ffecom_2 (MULT_EXPR, ltype,
6406 ltmp,
6407 ltmp)));
6408 expand_end_cond ();
6409 expand_end_cond ();
6410 expand_start_loop (1);
6411 expand_start_cond (ffecom_truth_value
6412 (ffecom_2 (BIT_AND_EXPR, rtype,
6413 rtmp,
6414 convert (rtype, integer_one_node))),
6415 0);
6416 expand_expr_stmt (ffecom_modify (void_type_node,
6417 result,
6418 ffecom_2 (MULT_EXPR, ltype,
6419 result,
6420 ltmp)));
6421 expand_end_cond ();
6422 expand_exit_loop_if_false (NULL,
6423 ffecom_truth_value
6424 (ffecom_modify (rtype,
6425 rtmp,
6426 ffecom_2 (RSHIFT_EXPR,
6427 rtype,
6428 rtmp,
6429 integer_one_node))));
6430 expand_expr_stmt (ffecom_modify (void_type_node,
6431 ltmp,
6432 ffecom_2 (MULT_EXPR, ltype,
6433 ltmp,
6434 ltmp)));
6435 expand_end_loop ();
6436 expand_end_cond ();
6437 if (!integer_zerop (basetypeof_l_is_int))
6438 expand_end_cond ();
6439 expand_expr_stmt (result);
6440
6441 ffecom_pop_calltemps ();
6442 result = expand_end_stmt_expr (se);
6443 TREE_SIDE_EFFECTS (result) = 1;
6444 }
6445
6446 return result;
6447 }
6448
6449 #endif
6450 /* ffecom_expr_transform_ -- Transform symbols in expr
6451
6452 ffebld expr; // FFE expression.
6453 ffecom_expr_transform_ (expr);
6454
6455 Recursive descent on expr while transforming any untransformed SYMTERs. */
6456
6457 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6458 static void
6459 ffecom_expr_transform_ (ffebld expr)
6460 {
6461 tree t;
6462 ffesymbol s;
6463
6464 tail_recurse: /* :::::::::::::::::::: */
6465
6466 if (expr == NULL)
6467 return;
6468
6469 switch (ffebld_op (expr))
6470 {
6471 case FFEBLD_opSYMTER:
6472 s = ffebld_symter (expr);
6473 t = ffesymbol_hook (s).decl_tree;
6474 if ((t == NULL_TREE)
6475 && ((ffesymbol_kind (s) != FFEINFO_kindNONE)
6476 || ((ffesymbol_where (s) != FFEINFO_whereNONE)
6477 && (ffesymbol_where (s) != FFEINFO_whereINTRINSIC))))
6478 {
6479 s = ffecom_sym_transform_ (s);
6480 t = ffesymbol_hook (s).decl_tree; /* Sfunc expr non-dummy,
6481 DIMENSION expr? */
6482 }
6483 break; /* Ok if (t == NULL) here. */
6484
6485 case FFEBLD_opITEM:
6486 ffecom_expr_transform_ (ffebld_head (expr));
6487 expr = ffebld_trail (expr);
6488 goto tail_recurse; /* :::::::::::::::::::: */
6489
6490 default:
6491 break;
6492 }
6493
6494 switch (ffebld_arity (expr))
6495 {
6496 case 2:
6497 ffecom_expr_transform_ (ffebld_left (expr));
6498 expr = ffebld_right (expr);
6499 goto tail_recurse; /* :::::::::::::::::::: */
6500
6501 case 1:
6502 expr = ffebld_left (expr);
6503 goto tail_recurse; /* :::::::::::::::::::: */
6504
6505 default:
6506 break;
6507 }
6508
6509 return;
6510 }
6511
6512 #endif
6513 /* Make a type based on info in live f2c.h file. */
6514
6515 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6516 static void
6517 ffecom_f2c_make_type_ (tree *type, int tcode, char *name)
6518 {
6519 switch (tcode)
6520 {
6521 case FFECOM_f2ccodeCHAR:
6522 *type = make_signed_type (CHAR_TYPE_SIZE);
6523 break;
6524
6525 case FFECOM_f2ccodeSHORT:
6526 *type = make_signed_type (SHORT_TYPE_SIZE);
6527 break;
6528
6529 case FFECOM_f2ccodeINT:
6530 *type = make_signed_type (INT_TYPE_SIZE);
6531 break;
6532
6533 case FFECOM_f2ccodeLONG:
6534 *type = make_signed_type (LONG_TYPE_SIZE);
6535 break;
6536
6537 case FFECOM_f2ccodeLONGLONG:
6538 *type = make_signed_type (LONG_LONG_TYPE_SIZE);
6539 break;
6540
6541 case FFECOM_f2ccodeCHARPTR:
6542 *type = build_pointer_type (DEFAULT_SIGNED_CHAR
6543 ? signed_char_type_node
6544 : unsigned_char_type_node);
6545 break;
6546
6547 case FFECOM_f2ccodeFLOAT:
6548 *type = make_node (REAL_TYPE);
6549 TYPE_PRECISION (*type) = FLOAT_TYPE_SIZE;
6550 layout_type (*type);
6551 break;
6552
6553 case FFECOM_f2ccodeDOUBLE:
6554 *type = make_node (REAL_TYPE);
6555 TYPE_PRECISION (*type) = DOUBLE_TYPE_SIZE;
6556 layout_type (*type);
6557 break;
6558
6559 case FFECOM_f2ccodeLONGDOUBLE:
6560 *type = make_node (REAL_TYPE);
6561 TYPE_PRECISION (*type) = LONG_DOUBLE_TYPE_SIZE;
6562 layout_type (*type);
6563 break;
6564
6565 case FFECOM_f2ccodeTWOREALS:
6566 *type = ffecom_make_complex_type_ (ffecom_f2c_real_type_node);
6567 break;
6568
6569 case FFECOM_f2ccodeTWODOUBLEREALS:
6570 *type = ffecom_make_complex_type_ (ffecom_f2c_doublereal_type_node);
6571 break;
6572
6573 default:
6574 assert ("unexpected FFECOM_f2ccodeXYZZY!" == NULL);
6575 *type = error_mark_node;
6576 return;
6577 }
6578
6579 pushdecl (build_decl (TYPE_DECL,
6580 ffecom_get_invented_identifier ("__g77_f2c_%s",
6581 name, 0),
6582 *type));
6583 }
6584
6585 #endif
6586 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6587 /* Set the f2c list-directed-I/O code for whatever (integral) type has the
6588 given size. */
6589
6590 static void
6591 ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
6592 int code)
6593 {
6594 int j;
6595 tree t;
6596
6597 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
6598 if (((t = ffecom_tree_type[bt][j]) != NULL_TREE)
6599 && (TREE_INT_CST_LOW (TYPE_SIZE (t)) == size))
6600 {
6601 assert (code != -1);
6602 ffecom_f2c_typecode_[bt][j] = code;
6603 code = -1;
6604 }
6605 }
6606
6607 #endif
6608 /* Finish up globals after doing all program units in file
6609
6610 Need to handle only uninitialized COMMON areas. */
6611
6612 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6613 static ffeglobal
6614 ffecom_finish_global_ (ffeglobal global)
6615 {
6616 tree cbtype;
6617 tree cbt;
6618 tree size;
6619
6620 if (ffeglobal_type (global) != FFEGLOBAL_typeCOMMON)
6621 return global;
6622
6623 if (ffeglobal_common_init (global))
6624 return global;
6625
6626 cbt = ffeglobal_hook (global);
6627 if ((cbt == NULL_TREE)
6628 || !ffeglobal_common_have_size (global))
6629 return global; /* No need to make common, never ref'd. */
6630
6631 suspend_momentary ();
6632
6633 DECL_EXTERNAL (cbt) = 0;
6634
6635 /* Give the array a size now. */
6636
6637 size = build_int_2 (ffeglobal_common_size (global), 0);
6638
6639 cbtype = TREE_TYPE (cbt);
6640 TYPE_DOMAIN (cbtype) = build_range_type (integer_type_node,
6641 integer_one_node,
6642 size);
6643 if (!TREE_TYPE (size))
6644 TREE_TYPE (size) = TYPE_DOMAIN (cbtype);
6645 layout_type (cbtype);
6646
6647 cbt = start_decl (cbt, FALSE);
6648 assert (cbt == ffeglobal_hook (global));
6649
6650 finish_decl (cbt, NULL_TREE, FALSE);
6651
6652 return global;
6653 }
6654
6655 #endif
6656 /* Finish up any untransformed symbols. */
6657
6658 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6659 static ffesymbol
6660 ffecom_finish_symbol_transform_ (ffesymbol s)
6661 {
6662 if ((s == NULL) || (TREE_CODE (current_function_decl) == ERROR_MARK))
6663 return s;
6664
6665 /* It's easy to know to transform an untransformed symbol, to make sure
6666 we put out debugging info for it. But COMMON variables, unlike
6667 EQUIVALENCE ones, aren't given declarations in addition to the
6668 tree expressions that specify offsets, because COMMON variables
6669 can be referenced in the outer scope where only dummy arguments
6670 (PARM_DECLs) should really be seen. To be safe, just don't do any
6671 VAR_DECLs for COMMON variables when we transform them for real
6672 use, and therefore we do all the VAR_DECL creating here. */
6673
6674 if ((ffesymbol_hook (s).decl_tree == NULL_TREE)
6675 && ((ffesymbol_kind (s) != FFEINFO_kindNONE)
6676 || ((ffesymbol_where (s) != FFEINFO_whereNONE)
6677 && (ffesymbol_where (s) != FFEINFO_whereINTRINSIC)))
6678 && (ffesymbol_where (s) != FFEINFO_whereDUMMY))
6679 /* Not transformed, and not CHARACTER*(*), and not a dummy
6680 argument, which can happen only if the entry point names
6681 it "rides in on" are all invalidated for other reasons. */
6682 s = ffecom_sym_transform_ (s);
6683
6684 if ((ffesymbol_where (s) == FFEINFO_whereCOMMON)
6685 && (ffesymbol_hook (s).decl_tree != error_mark_node))
6686 {
6687 #ifdef SOMEONE_GETS_DEBUG_SUPPORT_WORKING
6688 int yes = suspend_momentary ();
6689
6690 /* This isn't working, at least for dbxout. The .s file looks
6691 okay to me (burley), but in gdb 4.9 at least, the variables
6692 appear to reside somewhere outside of the common area, so
6693 it doesn't make sense to mislead anyone by generating the info
6694 on those variables until this is fixed. NOTE: Same problem
6695 with EQUIVALENCE, sadly...see similar #if later. */
6696 ffecom_member_phase2_ (ffesymbol_storage (ffesymbol_common (s)),
6697 ffesymbol_storage (s));
6698
6699 resume_momentary (yes);
6700 #endif
6701 }
6702
6703 return s;
6704 }
6705
6706 #endif
6707 /* Append underscore(s) to name before calling get_identifier. "us"
6708 is nonzero if the name already contains an underscore and thus
6709 needs two underscores appended. */
6710
6711 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6712 static tree
6713 ffecom_get_appended_identifier_ (char us, char *name)
6714 {
6715 int i;
6716 char *newname;
6717 tree id;
6718
6719 newname = xmalloc ((i = strlen (name)) + 1
6720 + ffe_is_underscoring ()
6721 + us);
6722 memcpy (newname, name, i);
6723 newname[i] = '_';
6724 newname[i + us] = '_';
6725 newname[i + 1 + us] = '\0';
6726 id = get_identifier (newname);
6727
6728 free (newname);
6729
6730 return id;
6731 }
6732
6733 #endif
6734 /* Decide whether to append underscore to name before calling
6735 get_identifier. */
6736
6737 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6738 static tree
6739 ffecom_get_external_identifier_ (ffesymbol s)
6740 {
6741 char us;
6742 char *name = ffesymbol_text (s);
6743
6744 /* If name is a built-in name, just return it as is. */
6745
6746 if (!ffe_is_underscoring ()
6747 || (strcmp (name, FFETARGET_nameBLANK_COMMON) == 0)
6748 #if FFETARGET_isENFORCED_MAIN_NAME
6749 || (strcmp (name, FFETARGET_nameENFORCED_NAME) == 0)
6750 #else
6751 || (strcmp (name, FFETARGET_nameUNNAMED_MAIN) == 0)
6752 #endif
6753 || (strcmp (name, FFETARGET_nameUNNAMED_BLOCK_DATA) == 0))
6754 return get_identifier (name);
6755
6756 us = ffe_is_second_underscore ()
6757 ? (strchr (name, '_') != NULL)
6758 : 0;
6759
6760 return ffecom_get_appended_identifier_ (us, name);
6761 }
6762
6763 #endif
6764 /* Decide whether to append underscore to internal name before calling
6765 get_identifier.
6766
6767 This is for non-external, top-function-context names only. Transform
6768 identifier so it doesn't conflict with the transformed result
6769 of using a _different_ external name. E.g. if "CALL FOO" is
6770 transformed into "FOO_();", then the variable in "FOO_ = 3"
6771 must be transformed into something that does not conflict, since
6772 these two things should be independent.
6773
6774 The transformation is as follows. If the name does not contain
6775 an underscore, there is no possible conflict, so just return.
6776 If the name does contain an underscore, then transform it just
6777 like we transform an external identifier. */
6778
6779 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6780 static tree
6781 ffecom_get_identifier_ (char *name)
6782 {
6783 /* If name does not contain an underscore, just return it as is. */
6784
6785 if (!ffe_is_underscoring ()
6786 || (strchr (name, '_') == NULL))
6787 return get_identifier (name);
6788
6789 return ffecom_get_appended_identifier_ (ffe_is_second_underscore (),
6790 name);
6791 }
6792
6793 #endif
6794 /* ffecom_gen_sfuncdef_ -- Generate definition of statement function
6795
6796 tree t;
6797 ffesymbol s; // kindFUNCTION, whereIMMEDIATE.
6798 t = ffecom_gen_sfuncdef_(s,ffesymbol_basictype(s),
6799 ffesymbol_kindtype(s));
6800
6801 Call after setting up containing function and getting trees for all
6802 other symbols. */
6803
6804 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6805 static tree
6806 ffecom_gen_sfuncdef_ (ffesymbol s, ffeinfoBasictype bt, ffeinfoKindtype kt)
6807 {
6808 ffebld expr = ffesymbol_sfexpr (s);
6809 tree type;
6810 tree func;
6811 tree result;
6812 bool charfunc = (bt == FFEINFO_basictypeCHARACTER);
6813 static bool recurse = FALSE;
6814 int yes;
6815 int old_lineno = lineno;
6816 char *old_input_filename = input_filename;
6817
6818 ffecom_nested_entry_ = s;
6819
6820 /* For now, we don't have a handy pointer to where the sfunc is actually
6821 defined, though that should be easy to add to an ffesymbol. (The
6822 token/where info available might well point to the place where the type
6823 of the sfunc is declared, especially if that precedes the place where
6824 the sfunc itself is defined, which is typically the case.) We should
6825 put out a null pointer rather than point somewhere wrong, but I want to
6826 see how it works at this point. */
6827
6828 input_filename = ffesymbol_where_filename (s);
6829 lineno = ffesymbol_where_filelinenum (s);
6830
6831 /* Pretransform the expression so any newly discovered things belong to the
6832 outer program unit, not to the statement function. */
6833
6834 ffecom_expr_transform_ (expr);
6835
6836 /* Make sure no recursive invocation of this fn (a specific case of failing
6837 to pretransform an sfunc's expression, i.e. where its expression
6838 references another untransformed sfunc) happens. */
6839
6840 assert (!recurse);
6841 recurse = TRUE;
6842
6843 yes = suspend_momentary ();
6844
6845 push_f_function_context ();
6846
6847 ffecom_push_calltemps ();
6848
6849 if (charfunc)
6850 type = void_type_node;
6851 else
6852 {
6853 type = ffecom_tree_type[bt][kt];
6854 if (type == NULL_TREE)
6855 type = integer_type_node; /* _sym_exec_transition reports
6856 error. */
6857 }
6858
6859 start_function (ffecom_get_identifier_ (ffesymbol_text (s)),
6860 build_function_type (type, NULL_TREE),
6861 1, /* nested/inline */
6862 0); /* TREE_PUBLIC */
6863
6864 /* We don't worry about COMPLEX return values here, because this is
6865 entirely internal to our code, and gcc has the ability to return COMPLEX
6866 directly as a value. */
6867
6868 yes = suspend_momentary ();
6869
6870 if (charfunc)
6871 { /* Prepend arg for where result goes. */
6872 tree type;
6873
6874 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
6875
6876 result = ffecom_get_invented_identifier ("__g77_%s",
6877 "result", 0);
6878
6879 ffecom_char_enhance_arg_ (&type, s); /* Ignore returned length. */
6880
6881 type = build_pointer_type (type);
6882 result = build_decl (PARM_DECL, result, type);
6883
6884 push_parm_decl (result);
6885 }
6886 else
6887 result = NULL_TREE; /* Not ref'd if !charfunc. */
6888
6889 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (s), TRUE);
6890
6891 resume_momentary (yes);
6892
6893 store_parm_decls (0);
6894
6895 ffecom_start_compstmt_ ();
6896
6897 if (expr != NULL)
6898 {
6899 if (charfunc)
6900 {
6901 ffetargetCharacterSize sz = ffesymbol_size (s);
6902 tree result_length;
6903
6904 result_length = build_int_2 (sz, 0);
6905 TREE_TYPE (result_length) = ffecom_f2c_ftnlen_type_node;
6906
6907 ffecom_let_char_ (result, result_length, sz, expr);
6908 expand_null_return ();
6909 }
6910 else
6911 expand_return (ffecom_modify (NULL_TREE,
6912 DECL_RESULT (current_function_decl),
6913 ffecom_expr (expr)));
6914
6915 clear_momentary ();
6916 }
6917
6918 ffecom_end_compstmt_ ();
6919
6920 func = current_function_decl;
6921 finish_function (1);
6922
6923 ffecom_pop_calltemps ();
6924
6925 pop_f_function_context ();
6926
6927 resume_momentary (yes);
6928
6929 recurse = FALSE;
6930
6931 lineno = old_lineno;
6932 input_filename = old_input_filename;
6933
6934 ffecom_nested_entry_ = NULL;
6935
6936 return func;
6937 }
6938
6939 #endif
6940
6941 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6942 static char *
6943 ffecom_gfrt_args_ (ffecomGfrt ix)
6944 {
6945 return ffecom_gfrt_argstring_[ix];
6946 }
6947
6948 #endif
6949 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6950 static tree
6951 ffecom_gfrt_tree_ (ffecomGfrt ix)
6952 {
6953 if (ffecom_gfrt_[ix] == NULL_TREE)
6954 ffecom_make_gfrt_ (ix);
6955
6956 return ffecom_1 (ADDR_EXPR,
6957 build_pointer_type (TREE_TYPE (ffecom_gfrt_[ix])),
6958 ffecom_gfrt_[ix]);
6959 }
6960
6961 #endif
6962 /* Return initialize-to-zero expression for this VAR_DECL. */
6963
6964 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6965 static tree
6966 ffecom_init_zero_ (tree decl)
6967 {
6968 tree init;
6969 int incremental = TREE_STATIC (decl);
6970 tree type = TREE_TYPE (decl);
6971
6972 if (incremental)
6973 {
6974 int momentary = suspend_momentary ();
6975 push_obstacks_nochange ();
6976 if (TREE_PERMANENT (decl))
6977 end_temporary_allocation ();
6978 make_decl_rtl (decl, NULL, TREE_PUBLIC (decl) ? 1 : 0);
6979 assemble_variable (decl, TREE_PUBLIC (decl) ? 1 : 0, 0, 1);
6980 pop_obstacks ();
6981 resume_momentary (momentary);
6982 }
6983
6984 push_momentary ();
6985
6986 if ((TREE_CODE (type) != ARRAY_TYPE)
6987 && (TREE_CODE (type) != RECORD_TYPE)
6988 && (TREE_CODE (type) != UNION_TYPE)
6989 && !incremental)
6990 init = convert (type, integer_zero_node);
6991 else if (!incremental)
6992 {
6993 int momentary = suspend_momentary ();
6994
6995 init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
6996 TREE_CONSTANT (init) = 1;
6997 TREE_STATIC (init) = 1;
6998
6999 resume_momentary (momentary);
7000 }
7001 else
7002 {
7003 int momentary = suspend_momentary ();
7004
7005 assemble_zeros (int_size_in_bytes (type));
7006 init = error_mark_node;
7007
7008 resume_momentary (momentary);
7009 }
7010
7011 pop_momentary_nofree ();
7012
7013 return init;
7014 }
7015
7016 #endif
7017 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7018 static tree
7019 ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
7020 tree *maybe_tree)
7021 {
7022 tree expr_tree;
7023 tree length_tree;
7024
7025 switch (ffebld_op (arg))
7026 {
7027 case FFEBLD_opCONTER: /* For F90, check 0-length. */
7028 if (ffetarget_length_character1
7029 (ffebld_constant_character1
7030 (ffebld_conter (arg))) == 0)
7031 {
7032 *maybe_tree = integer_zero_node;
7033 return convert (tree_type, integer_zero_node);
7034 }
7035
7036 *maybe_tree = integer_one_node;
7037 expr_tree = build_int_2 (*ffetarget_text_character1
7038 (ffebld_constant_character1
7039 (ffebld_conter (arg))),
7040 0);
7041 TREE_TYPE (expr_tree) = tree_type;
7042 return expr_tree;
7043
7044 case FFEBLD_opSYMTER:
7045 case FFEBLD_opARRAYREF:
7046 case FFEBLD_opFUNCREF:
7047 case FFEBLD_opSUBSTR:
7048 ffecom_push_calltemps ();
7049 ffecom_char_args_ (&expr_tree, &length_tree, arg);
7050 ffecom_pop_calltemps ();
7051
7052 if ((expr_tree == error_mark_node)
7053 || (length_tree == error_mark_node))
7054 {
7055 *maybe_tree = error_mark_node;
7056 return error_mark_node;
7057 }
7058
7059 if (integer_zerop (length_tree))
7060 {
7061 *maybe_tree = integer_zero_node;
7062 return convert (tree_type, integer_zero_node);
7063 }
7064
7065 expr_tree
7066 = ffecom_1 (INDIRECT_REF,
7067 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
7068 expr_tree);
7069 expr_tree
7070 = ffecom_2 (ARRAY_REF,
7071 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
7072 expr_tree,
7073 integer_one_node);
7074 expr_tree = convert (tree_type, expr_tree);
7075
7076 if (TREE_CODE (length_tree) == INTEGER_CST)
7077 *maybe_tree = integer_one_node;
7078 else /* Must check length at run time. */
7079 *maybe_tree
7080 = ffecom_truth_value
7081 (ffecom_2 (GT_EXPR, integer_type_node,
7082 length_tree,
7083 ffecom_f2c_ftnlen_zero_node));
7084 return expr_tree;
7085
7086 case FFEBLD_opPAREN:
7087 case FFEBLD_opCONVERT:
7088 if (ffeinfo_size (ffebld_info (arg)) == 0)
7089 {
7090 *maybe_tree = integer_zero_node;
7091 return convert (tree_type, integer_zero_node);
7092 }
7093 return ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
7094 maybe_tree);
7095
7096 case FFEBLD_opCONCATENATE:
7097 {
7098 tree maybe_left;
7099 tree maybe_right;
7100 tree expr_left;
7101 tree expr_right;
7102
7103 expr_left = ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
7104 &maybe_left);
7105 expr_right = ffecom_intrinsic_ichar_ (tree_type, ffebld_right (arg),
7106 &maybe_right);
7107 *maybe_tree = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
7108 maybe_left,
7109 maybe_right);
7110 expr_tree = ffecom_3 (COND_EXPR, tree_type,
7111 maybe_left,
7112 expr_left,
7113 expr_right);
7114 return expr_tree;
7115 }
7116
7117 default:
7118 assert ("bad op in ICHAR" == NULL);
7119 return error_mark_node;
7120 }
7121 }
7122
7123 #endif
7124 /* ffecom_intrinsic_len_ -- Return length info for char arg (LEN())
7125
7126 tree length_arg;
7127 ffebld expr;
7128 length_arg = ffecom_intrinsic_len_ (expr);
7129
7130 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
7131 subexpressions by constructing the appropriate tree for the
7132 length-of-character-text argument in a calling sequence. */
7133
7134 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7135 static tree
7136 ffecom_intrinsic_len_ (ffebld expr)
7137 {
7138 ffetargetCharacter1 val;
7139 tree length;
7140
7141 switch (ffebld_op (expr))
7142 {
7143 case FFEBLD_opCONTER:
7144 val = ffebld_constant_character1 (ffebld_conter (expr));
7145 length = build_int_2 (ffetarget_length_character1 (val), 0);
7146 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
7147 break;
7148
7149 case FFEBLD_opSYMTER:
7150 {
7151 ffesymbol s = ffebld_symter (expr);
7152 tree item;
7153
7154 item = ffesymbol_hook (s).decl_tree;
7155 if (item == NULL_TREE)
7156 {
7157 s = ffecom_sym_transform_ (s);
7158 item = ffesymbol_hook (s).decl_tree;
7159 }
7160 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
7161 {
7162 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
7163 length = ffesymbol_hook (s).length_tree;
7164 else
7165 {
7166 length = build_int_2 (ffesymbol_size (s), 0);
7167 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
7168 }
7169 }
7170 else if (item == error_mark_node)
7171 length = error_mark_node;
7172 else /* FFEINFO_kindFUNCTION: */
7173 length = NULL_TREE;
7174 }
7175 break;
7176
7177 case FFEBLD_opARRAYREF:
7178 length = ffecom_intrinsic_len_ (ffebld_left (expr));
7179 break;
7180
7181 case FFEBLD_opSUBSTR:
7182 {
7183 ffebld start;
7184 ffebld end;
7185 ffebld thing = ffebld_right (expr);
7186 tree start_tree;
7187 tree end_tree;
7188
7189 assert (ffebld_op (thing) == FFEBLD_opITEM);
7190 start = ffebld_head (thing);
7191 thing = ffebld_trail (thing);
7192 assert (ffebld_trail (thing) == NULL);
7193 end = ffebld_head (thing);
7194
7195 length = ffecom_intrinsic_len_ (ffebld_left (expr));
7196
7197 if (length == error_mark_node)
7198 break;
7199
7200 if (start == NULL)
7201 {
7202 if (end == NULL)
7203 ;
7204 else
7205 {
7206 length = convert (ffecom_f2c_ftnlen_type_node,
7207 ffecom_expr (end));
7208 }
7209 }
7210 else
7211 {
7212 start_tree = convert (ffecom_f2c_ftnlen_type_node,
7213 ffecom_expr (start));
7214
7215 if (start_tree == error_mark_node)
7216 {
7217 length = error_mark_node;
7218 break;
7219 }
7220
7221 if (end == NULL)
7222 {
7223 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
7224 ffecom_f2c_ftnlen_one_node,
7225 ffecom_2 (MINUS_EXPR,
7226 ffecom_f2c_ftnlen_type_node,
7227 length,
7228 start_tree));
7229 }
7230 else
7231 {
7232 end_tree = convert (ffecom_f2c_ftnlen_type_node,
7233 ffecom_expr (end));
7234
7235 if (end_tree == error_mark_node)
7236 {
7237 length = error_mark_node;
7238 break;
7239 }
7240
7241 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
7242 ffecom_f2c_ftnlen_one_node,
7243 ffecom_2 (MINUS_EXPR,
7244 ffecom_f2c_ftnlen_type_node,
7245 end_tree, start_tree));
7246 }
7247 }
7248 }
7249 break;
7250
7251 case FFEBLD_opCONCATENATE:
7252 length
7253 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
7254 ffecom_intrinsic_len_ (ffebld_left (expr)),
7255 ffecom_intrinsic_len_ (ffebld_right (expr)));
7256 break;
7257
7258 case FFEBLD_opFUNCREF:
7259 case FFEBLD_opCONVERT:
7260 length = build_int_2 (ffebld_size (expr), 0);
7261 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
7262 break;
7263
7264 default:
7265 assert ("bad op for single char arg expr" == NULL);
7266 length = ffecom_f2c_ftnlen_zero_node;
7267 break;
7268 }
7269
7270 assert (length != NULL_TREE);
7271
7272 return length;
7273 }
7274
7275 #endif
7276 /* ffecom_let_char_ -- Do assignment stuff for character type
7277
7278 tree dest_tree; // destination (ADDR_EXPR)
7279 tree dest_length; // length (INT_CST/INDIRECT_REF(PARM_DECL))
7280 ffetargetCharacterSize dest_size; // length
7281 ffebld source; // source expression
7282 ffecom_let_char_(dest_tree,dest_length,dest_size,source);
7283
7284 Generates code to do the assignment. Used by ordinary assignment
7285 statement handler ffecom_let_stmt and by statement-function
7286 handler to generate code for a statement function. */
7287
7288 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7289 static void
7290 ffecom_let_char_ (tree dest_tree, tree dest_length,
7291 ffetargetCharacterSize dest_size, ffebld source)
7292 {
7293 ffecomConcatList_ catlist;
7294 tree source_length;
7295 tree source_tree;
7296 tree expr_tree;
7297
7298 if ((dest_tree == error_mark_node)
7299 || (dest_length == error_mark_node))
7300 return;
7301
7302 assert (dest_tree != NULL_TREE);
7303 assert (dest_length != NULL_TREE);
7304
7305 /* Source might be an opCONVERT, which just means it is a different size
7306 than the destination. Since the underlying implementation here handles
7307 that (directly or via the s_copy or s_cat run-time-library functions),
7308 we don't need the "convenience" of an opCONVERT that tells us to
7309 truncate or blank-pad, particularly since the resulting implementation
7310 would probably be slower than otherwise. */
7311
7312 while (ffebld_op (source) == FFEBLD_opCONVERT)
7313 source = ffebld_left (source);
7314
7315 catlist = ffecom_concat_list_new_ (source, dest_size);
7316 switch (ffecom_concat_list_count_ (catlist))
7317 {
7318 case 0: /* Shouldn't happen, but in case it does... */
7319 ffecom_concat_list_kill_ (catlist);
7320 source_tree = null_pointer_node;
7321 source_length = ffecom_f2c_ftnlen_zero_node;
7322 expr_tree = build_tree_list (NULL_TREE, dest_tree);
7323 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
7324 TREE_CHAIN (TREE_CHAIN (expr_tree))
7325 = build_tree_list (NULL_TREE, dest_length);
7326 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
7327 = build_tree_list (NULL_TREE, source_length);
7328
7329 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree);
7330 TREE_SIDE_EFFECTS (expr_tree) = 1;
7331
7332 expand_expr_stmt (expr_tree);
7333
7334 return;
7335
7336 case 1: /* The (fairly) easy case. */
7337 ffecom_char_args_ (&source_tree, &source_length,
7338 ffecom_concat_list_expr_ (catlist, 0));
7339 ffecom_concat_list_kill_ (catlist);
7340 assert (source_tree != NULL_TREE);
7341 assert (source_length != NULL_TREE);
7342
7343 if ((source_tree == error_mark_node)
7344 || (source_length == error_mark_node))
7345 return;
7346
7347 if (dest_size == 1)
7348 {
7349 dest_tree
7350 = ffecom_1 (INDIRECT_REF,
7351 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
7352 (dest_tree))),
7353 dest_tree);
7354 dest_tree
7355 = ffecom_2 (ARRAY_REF,
7356 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
7357 (dest_tree))),
7358 dest_tree,
7359 integer_one_node);
7360 source_tree
7361 = ffecom_1 (INDIRECT_REF,
7362 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
7363 (source_tree))),
7364 source_tree);
7365 source_tree
7366 = ffecom_2 (ARRAY_REF,
7367 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
7368 (source_tree))),
7369 source_tree,
7370 integer_one_node);
7371
7372 expr_tree = ffecom_modify (void_type_node, dest_tree, source_tree);
7373
7374 expand_expr_stmt (expr_tree);
7375
7376 return;
7377 }
7378
7379 expr_tree = build_tree_list (NULL_TREE, dest_tree);
7380 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
7381 TREE_CHAIN (TREE_CHAIN (expr_tree))
7382 = build_tree_list (NULL_TREE, dest_length);
7383 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
7384 = build_tree_list (NULL_TREE, source_length);
7385
7386 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree);
7387 TREE_SIDE_EFFECTS (expr_tree) = 1;
7388
7389 expand_expr_stmt (expr_tree);
7390
7391 return;
7392
7393 default: /* Must actually concatenate things. */
7394 break;
7395 }
7396
7397 /* Heavy-duty concatenation. */
7398
7399 {
7400 int count = ffecom_concat_list_count_ (catlist);
7401 int i;
7402 tree lengths;
7403 tree items;
7404 tree length_array;
7405 tree item_array;
7406 tree citem;
7407 tree clength;
7408
7409 length_array
7410 = lengths
7411 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
7412 FFETARGET_charactersizeNONE, count, TRUE);
7413 item_array = items = ffecom_push_tempvar (ffecom_f2c_address_type_node,
7414 FFETARGET_charactersizeNONE,
7415 count, TRUE);
7416
7417 for (i = 0; i < count; ++i)
7418 {
7419 ffecom_char_args_ (&citem, &clength,
7420 ffecom_concat_list_expr_ (catlist, i));
7421 if ((citem == error_mark_node)
7422 || (clength == error_mark_node))
7423 {
7424 ffecom_concat_list_kill_ (catlist);
7425 return;
7426 }
7427
7428 items
7429 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
7430 ffecom_modify (void_type_node,
7431 ffecom_2 (ARRAY_REF,
7432 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
7433 item_array,
7434 build_int_2 (i, 0)),
7435 citem),
7436 items);
7437 lengths
7438 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
7439 ffecom_modify (void_type_node,
7440 ffecom_2 (ARRAY_REF,
7441 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
7442 length_array,
7443 build_int_2 (i, 0)),
7444 clength),
7445 lengths);
7446 }
7447
7448 expr_tree = build_tree_list (NULL_TREE, dest_tree);
7449 TREE_CHAIN (expr_tree)
7450 = build_tree_list (NULL_TREE,
7451 ffecom_1 (ADDR_EXPR,
7452 build_pointer_type (TREE_TYPE (items)),
7453 items));
7454 TREE_CHAIN (TREE_CHAIN (expr_tree))
7455 = build_tree_list (NULL_TREE,
7456 ffecom_1 (ADDR_EXPR,
7457 build_pointer_type (TREE_TYPE (lengths)),
7458 lengths));
7459 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
7460 = build_tree_list
7461 (NULL_TREE,
7462 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
7463 convert (ffecom_f2c_ftnlen_type_node,
7464 build_int_2 (count, 0))));
7465 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree))))
7466 = build_tree_list (NULL_TREE, dest_length);
7467
7468 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCAT, expr_tree);
7469 TREE_SIDE_EFFECTS (expr_tree) = 1;
7470
7471 expand_expr_stmt (expr_tree);
7472 }
7473
7474 ffecom_concat_list_kill_ (catlist);
7475 }
7476
7477 #endif
7478 /* ffecom_make_gfrt_ -- Make initial info for run-time routine
7479
7480 ffecomGfrt ix;
7481 ffecom_make_gfrt_(ix);
7482
7483 Assumes gfrt_[ix] is NULL_TREE, and replaces it with the FUNCTION_DECL
7484 for the indicated run-time routine (ix). */
7485
7486 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7487 static void
7488 ffecom_make_gfrt_ (ffecomGfrt ix)
7489 {
7490 tree t;
7491 tree ttype;
7492
7493 push_obstacks_nochange ();
7494 end_temporary_allocation ();
7495
7496 switch (ffecom_gfrt_type_[ix])
7497 {
7498 case FFECOM_rttypeVOID_:
7499 ttype = void_type_node;
7500 break;
7501
7502 case FFECOM_rttypeVOIDSTAR_:
7503 ttype = TREE_TYPE (null_pointer_node); /* `void *'. */
7504 break;
7505
7506 case FFECOM_rttypeFTNINT_:
7507 ttype = ffecom_f2c_ftnint_type_node;
7508 break;
7509
7510 case FFECOM_rttypeINTEGER_:
7511 ttype = ffecom_f2c_integer_type_node;
7512 break;
7513
7514 case FFECOM_rttypeLONGINT_:
7515 ttype = ffecom_f2c_longint_type_node;
7516 break;
7517
7518 case FFECOM_rttypeLOGICAL_:
7519 ttype = ffecom_f2c_logical_type_node;
7520 break;
7521
7522 case FFECOM_rttypeREAL_F2C_:
7523 ttype = double_type_node;
7524 break;
7525
7526 case FFECOM_rttypeREAL_GNU_:
7527 ttype = float_type_node;
7528 break;
7529
7530 case FFECOM_rttypeCOMPLEX_F2C_:
7531 ttype = void_type_node;
7532 break;
7533
7534 case FFECOM_rttypeCOMPLEX_GNU_:
7535 ttype = ffecom_f2c_complex_type_node;
7536 break;
7537
7538 case FFECOM_rttypeDOUBLE_:
7539 ttype = double_type_node;
7540 break;
7541
7542 case FFECOM_rttypeDOUBLEREAL_:
7543 ttype = ffecom_f2c_doublereal_type_node;
7544 break;
7545
7546 case FFECOM_rttypeDBLCMPLX_F2C_:
7547 ttype = void_type_node;
7548 break;
7549
7550 case FFECOM_rttypeDBLCMPLX_GNU_:
7551 ttype = ffecom_f2c_doublecomplex_type_node;
7552 break;
7553
7554 case FFECOM_rttypeCHARACTER_:
7555 ttype = void_type_node;
7556 break;
7557
7558 default:
7559 ttype = NULL;
7560 assert ("bad rttype" == NULL);
7561 break;
7562 }
7563
7564 ttype = build_function_type (ttype, NULL_TREE);
7565 t = build_decl (FUNCTION_DECL,
7566 get_identifier (ffecom_gfrt_name_[ix]),
7567 ttype);
7568 DECL_EXTERNAL (t) = 1;
7569 TREE_PUBLIC (t) = 1;
7570 TREE_THIS_VOLATILE (t) = ffecom_gfrt_volatile_[ix] ? 1 : 0;
7571
7572 t = start_decl (t, TRUE);
7573
7574 finish_decl (t, NULL_TREE, TRUE);
7575
7576 resume_temporary_allocation ();
7577 pop_obstacks ();
7578
7579 ffecom_gfrt_[ix] = t;
7580 }
7581
7582 #endif
7583 /* Phase 1 pass over each member of a COMMON/EQUIVALENCE group. */
7584
7585 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7586 static void
7587 ffecom_member_phase1_ (ffestorag mst UNUSED, ffestorag st)
7588 {
7589 ffesymbol s = ffestorag_symbol (st);
7590
7591 if (ffesymbol_namelisted (s))
7592 ffecom_member_namelisted_ = TRUE;
7593 }
7594
7595 #endif
7596 /* Phase 2 pass over each member of a COMMON/EQUIVALENCE group. Declare
7597 the member so debugger will see it. Otherwise nobody should be
7598 referencing the member. */
7599
7600 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7601 #ifdef SOMEONE_GETS_DEBUG_SUPPORT_WORKING
7602 static void
7603 ffecom_member_phase2_ (ffestorag mst, ffestorag st)
7604 {
7605 ffesymbol s;
7606 tree t;
7607 tree mt;
7608 tree type;
7609
7610 if ((mst == NULL)
7611 || ((mt = ffestorag_hook (mst)) == NULL)
7612 || (mt == error_mark_node))
7613 return;
7614
7615 if ((st == NULL)
7616 || ((s = ffestorag_symbol (st)) == NULL))
7617 return;
7618
7619 type = ffecom_type_localvar_ (s,
7620 ffesymbol_basictype (s),
7621 ffesymbol_kindtype (s));
7622 if (type == error_mark_node)
7623 return;
7624
7625 t = build_decl (VAR_DECL,
7626 ffecom_get_identifier_ (ffesymbol_text (s)),
7627 type);
7628
7629 TREE_STATIC (t) = TREE_STATIC (mt);
7630 DECL_INITIAL (t) = NULL_TREE;
7631 TREE_ASM_WRITTEN (t) = 1;
7632
7633 DECL_RTL (t)
7634 = gen_rtx (MEM, TYPE_MODE (type),
7635 plus_constant (XEXP (DECL_RTL (mt), 0),
7636 ffestorag_modulo (mst)
7637 + ffestorag_offset (st)
7638 - ffestorag_offset (mst)));
7639
7640 t = start_decl (t, FALSE);
7641
7642 finish_decl (t, NULL_TREE, FALSE);
7643 }
7644
7645 #endif
7646 #endif
7647 /* ffecom_push_dummy_decls_ -- Transform dummy args, push parm decls in order
7648
7649 Ignores STAR (alternate-return) dummies. All other get exec-transitioned
7650 (which generates their trees) and then their trees get push_parm_decl'd.
7651
7652 The second arg is TRUE if the dummies are for a statement function, in
7653 which case lengths are not pushed for character arguments (since they are
7654 always known by both the caller and the callee, though the code allows
7655 for someday permitting CHAR*(*) stmtfunc dummies). */
7656
7657 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7658 static void
7659 ffecom_push_dummy_decls_ (ffebld dummy_list, bool stmtfunc)
7660 {
7661 ffebld dummy;
7662 ffebld dumlist;
7663 ffesymbol s;
7664 tree parm;
7665
7666 ffecom_transform_only_dummies_ = TRUE;
7667
7668 /* First push the parms corresponding to actual dummy "contents". */
7669
7670 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7671 {
7672 dummy = ffebld_head (dumlist);
7673 switch (ffebld_op (dummy))
7674 {
7675 case FFEBLD_opSTAR:
7676 case FFEBLD_opANY:
7677 continue; /* Forget alternate returns. */
7678
7679 default:
7680 break;
7681 }
7682 assert (ffebld_op (dummy) == FFEBLD_opSYMTER);
7683 s = ffebld_symter (dummy);
7684 parm = ffesymbol_hook (s).decl_tree;
7685 if (parm == NULL_TREE)
7686 {
7687 s = ffecom_sym_transform_ (s);
7688 parm = ffesymbol_hook (s).decl_tree;
7689 assert (parm != NULL_TREE);
7690 }
7691 if (parm != error_mark_node)
7692 push_parm_decl (parm);
7693 }
7694
7695 /* Then, for CHARACTER dummies, push the parms giving their lengths. */
7696
7697 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7698 {
7699 dummy = ffebld_head (dumlist);
7700 switch (ffebld_op (dummy))
7701 {
7702 case FFEBLD_opSTAR:
7703 case FFEBLD_opANY:
7704 continue; /* Forget alternate returns, they mean
7705 NOTHING! */
7706
7707 default:
7708 break;
7709 }
7710 s = ffebld_symter (dummy);
7711 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
7712 continue; /* Only looking for CHARACTER arguments. */
7713 if (stmtfunc && (ffesymbol_size (s) != FFETARGET_charactersizeNONE))
7714 continue; /* Stmtfunc arg with known size needs no
7715 length param. */
7716 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
7717 continue; /* Only looking for variables and arrays. */
7718 parm = ffesymbol_hook (s).length_tree;
7719 assert (parm != NULL_TREE);
7720 if (parm != error_mark_node)
7721 push_parm_decl (parm);
7722 }
7723
7724 ffecom_transform_only_dummies_ = FALSE;
7725 }
7726
7727 #endif
7728 /* ffecom_start_progunit_ -- Beginning of program unit
7729
7730 Does GNU back end stuff necessary to teach it about the start of its
7731 equivalent of a Fortran program unit. */
7732
7733 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7734 static void
7735 ffecom_start_progunit_ ()
7736 {
7737 ffesymbol fn = ffecom_primary_entry_;
7738 ffebld arglist;
7739 tree id; /* Identifier (name) of function. */
7740 tree type; /* Type of function. */
7741 tree result; /* Result of function. */
7742 ffeinfoBasictype bt;
7743 ffeinfoKindtype kt;
7744 ffeglobal g;
7745 ffeglobalType gt;
7746 ffeglobalType egt = FFEGLOBAL_type;
7747 bool charfunc;
7748 bool cmplxfunc;
7749 bool altentries = (ffecom_num_entrypoints_ != 0);
7750 bool multi
7751 = altentries
7752 && (ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
7753 && (ffecom_master_bt_ == FFEINFO_basictypeNONE);
7754 bool main_program = FALSE;
7755 int old_lineno = lineno;
7756 char *old_input_filename = input_filename;
7757 int yes;
7758
7759 assert (fn != NULL);
7760 assert (ffesymbol_hook (fn).decl_tree == NULL_TREE);
7761
7762 input_filename = ffesymbol_where_filename (fn);
7763 lineno = ffesymbol_where_filelinenum (fn);
7764
7765 /* c-parse.y indeed does call suspend_momentary and not only ignores the
7766 return value, but also never calls resume_momentary, when starting an
7767 outer function (see "fndef:", "setspecs:", and so on). So g77 does the
7768 same thing. It shouldn't be a problem since start_function calls
7769 temporary_allocation, but it might be necessary. If it causes a problem
7770 here, then maybe there's a bug lurking in gcc. NOTE: This identical
7771 comment appears twice in thist file. */
7772
7773 suspend_momentary ();
7774
7775 switch (ffecom_primary_entry_kind_)
7776 {
7777 case FFEINFO_kindPROGRAM:
7778 main_program = TRUE;
7779 gt = FFEGLOBAL_typeMAIN;
7780 bt = FFEINFO_basictypeNONE;
7781 kt = FFEINFO_kindtypeNONE;
7782 type = ffecom_tree_fun_type_void;
7783 charfunc = FALSE;
7784 cmplxfunc = FALSE;
7785 break;
7786
7787 case FFEINFO_kindBLOCKDATA:
7788 gt = FFEGLOBAL_typeBDATA;
7789 bt = FFEINFO_basictypeNONE;
7790 kt = FFEINFO_kindtypeNONE;
7791 type = ffecom_tree_fun_type_void;
7792 charfunc = FALSE;
7793 cmplxfunc = FALSE;
7794 break;
7795
7796 case FFEINFO_kindFUNCTION:
7797 gt = FFEGLOBAL_typeFUNC;
7798 egt = FFEGLOBAL_typeEXT;
7799 bt = ffesymbol_basictype (fn);
7800 kt = ffesymbol_kindtype (fn);
7801 if (bt == FFEINFO_basictypeNONE)
7802 {
7803 ffeimplic_establish_symbol (fn);
7804 if (ffesymbol_funcresult (fn) != NULL)
7805 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
7806 bt = ffesymbol_basictype (fn);
7807 kt = ffesymbol_kindtype (fn);
7808 }
7809
7810 if (multi)
7811 charfunc = cmplxfunc = FALSE;
7812 else if (bt == FFEINFO_basictypeCHARACTER)
7813 charfunc = TRUE, cmplxfunc = FALSE;
7814 else if ((bt == FFEINFO_basictypeCOMPLEX)
7815 && ffesymbol_is_f2c (fn)
7816 && !altentries)
7817 charfunc = FALSE, cmplxfunc = TRUE;
7818 else
7819 charfunc = cmplxfunc = FALSE;
7820
7821 if (multi || charfunc)
7822 type = ffecom_tree_fun_type_void;
7823 else if (ffesymbol_is_f2c (fn) && !altentries)
7824 type = ffecom_tree_fun_type[bt][kt];
7825 else
7826 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
7827
7828 if ((type == NULL_TREE)
7829 || (TREE_TYPE (type) == NULL_TREE))
7830 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
7831 break;
7832
7833 case FFEINFO_kindSUBROUTINE:
7834 gt = FFEGLOBAL_typeSUBR;
7835 egt = FFEGLOBAL_typeEXT;
7836 bt = FFEINFO_basictypeNONE;
7837 kt = FFEINFO_kindtypeNONE;
7838 if (ffecom_is_altreturning_)
7839 type = ffecom_tree_subr_type;
7840 else
7841 type = ffecom_tree_fun_type_void;
7842 charfunc = FALSE;
7843 cmplxfunc = FALSE;
7844 break;
7845
7846 default:
7847 assert ("say what??" == NULL);
7848 /* Fall through. */
7849 case FFEINFO_kindANY:
7850 gt = FFEGLOBAL_typeANY;
7851 bt = FFEINFO_basictypeNONE;
7852 kt = FFEINFO_kindtypeNONE;
7853 type = error_mark_node;
7854 charfunc = FALSE;
7855 cmplxfunc = FALSE;
7856 break;
7857 }
7858
7859 if (altentries)
7860 id = ffecom_get_invented_identifier ("__g77_masterfun_%s",
7861 ffesymbol_text (fn),
7862 0);
7863 #if FFETARGET_isENFORCED_MAIN
7864 else if (main_program)
7865 id = get_identifier (FFETARGET_nameENFORCED_MAIN_NAME);
7866 #endif
7867 else
7868 id = ffecom_get_external_identifier_ (fn);
7869
7870 start_function (id,
7871 type,
7872 0, /* nested/inline */
7873 !altentries); /* TREE_PUBLIC */
7874
7875 if (!altentries
7876 && ((g = ffesymbol_global (fn)) != NULL)
7877 && ((ffeglobal_type (g) == gt)
7878 || (ffeglobal_type (g) == egt)))
7879 {
7880 ffeglobal_set_hook (g, current_function_decl);
7881 }
7882
7883 yes = suspend_momentary ();
7884
7885 /* Arg handling needs exec-transitioned ffesymbols to work with. But
7886 exec-transitioning needs current_function_decl to be filled in. So we
7887 do these things in two phases. */
7888
7889 if (altentries)
7890 { /* 1st arg identifies which entrypoint. */
7891 ffecom_which_entrypoint_decl_
7892 = build_decl (PARM_DECL,
7893 ffecom_get_invented_identifier ("__g77_%s",
7894 "which_entrypoint",
7895 0),
7896 integer_type_node);
7897 push_parm_decl (ffecom_which_entrypoint_decl_);
7898 }
7899
7900 if (charfunc
7901 || cmplxfunc
7902 || multi)
7903 { /* Arg for result (return value). */
7904 tree type;
7905 tree length;
7906
7907 if (charfunc)
7908 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
7909 else if (cmplxfunc)
7910 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
7911 else
7912 type = ffecom_multi_type_node_;
7913
7914 result = ffecom_get_invented_identifier ("__g77_%s",
7915 "result", 0);
7916
7917 /* Make length arg _and_ enhance type info for CHAR arg itself. */
7918
7919 if (charfunc)
7920 length = ffecom_char_enhance_arg_ (&type, fn);
7921 else
7922 length = NULL_TREE; /* Not ref'd if !charfunc. */
7923
7924 type = build_pointer_type (type);
7925 result = build_decl (PARM_DECL, result, type);
7926
7927 push_parm_decl (result);
7928 if (multi)
7929 ffecom_multi_retval_ = result;
7930 else
7931 ffecom_func_result_ = result;
7932
7933 if (charfunc)
7934 {
7935 push_parm_decl (length);
7936 ffecom_func_length_ = length;
7937 }
7938 }
7939
7940 if (ffecom_primary_entry_is_proc_)
7941 {
7942 if (altentries)
7943 arglist = ffecom_master_arglist_;
7944 else
7945 arglist = ffesymbol_dummyargs (fn);
7946 ffecom_push_dummy_decls_ (arglist, FALSE);
7947 }
7948
7949 resume_momentary (yes);
7950
7951 if (TREE_CODE (current_function_decl) != ERROR_MARK)
7952 store_parm_decls (main_program ? 1 : 0);
7953
7954 ffecom_start_compstmt_ ();
7955
7956 lineno = old_lineno;
7957 input_filename = old_input_filename;
7958
7959 /* This handles any symbols still untransformed, in case -g specified.
7960 This used to be done in ffecom_finish_progunit, but it turns out to
7961 be necessary to do it here so that statement functions are
7962 expanded before code. But don't bother for BLOCK DATA. */
7963
7964 if (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
7965 ffesymbol_drive (ffecom_finish_symbol_transform_);
7966 }
7967
7968 #endif
7969 /* ffecom_sym_transform_ -- Transform FFE sym into backend sym
7970
7971 ffesymbol s;
7972 ffecom_sym_transform_(s);
7973
7974 The ffesymbol_hook info for s is updated with appropriate backend info
7975 on the symbol. */
7976
7977 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7978 static ffesymbol
7979 ffecom_sym_transform_ (ffesymbol s)
7980 {
7981 tree t; /* Transformed thingy. */
7982 tree tlen; /* Length if CHAR*(*). */
7983 bool addr; /* Is t the address of the thingy? */
7984 ffeinfoBasictype bt;
7985 ffeinfoKindtype kt;
7986 ffeglobal g;
7987 int yes;
7988 int old_lineno = lineno;
7989 char *old_input_filename = input_filename;
7990
7991 if (ffesymbol_sfdummyparent (s) == NULL)
7992 {
7993 input_filename = ffesymbol_where_filename (s);
7994 lineno = ffesymbol_where_filelinenum (s);
7995 }
7996 else
7997 {
7998 ffesymbol sf = ffesymbol_sfdummyparent (s);
7999
8000 input_filename = ffesymbol_where_filename (sf);
8001 lineno = ffesymbol_where_filelinenum (sf);
8002 }
8003
8004 bt = ffeinfo_basictype (ffebld_info (s));
8005 kt = ffeinfo_kindtype (ffebld_info (s));
8006
8007 t = NULL_TREE;
8008 tlen = NULL_TREE;
8009 addr = FALSE;
8010
8011 switch (ffesymbol_kind (s))
8012 {
8013 case FFEINFO_kindNONE:
8014 switch (ffesymbol_where (s))
8015 {
8016 case FFEINFO_whereDUMMY: /* Subroutine or function. */
8017 assert (ffecom_transform_only_dummies_);
8018
8019 /* Before 0.4, this could be ENTITY/DUMMY, but see
8020 ffestu_sym_end_transition -- no longer true (in particular, if
8021 it could be an ENTITY, it _will_ be made one, so that
8022 possibility won't come through here). So we never make length
8023 arg for CHARACTER type. */
8024
8025 t = build_decl (PARM_DECL,
8026 ffecom_get_identifier_ (ffesymbol_text (s)),
8027 ffecom_tree_ptr_to_subr_type);
8028 #if BUILT_FOR_270
8029 DECL_ARTIFICIAL (t) = 1;
8030 #endif
8031 addr = TRUE;
8032 break;
8033
8034 case FFEINFO_whereGLOBAL: /* Subroutine or function. */
8035 assert (!ffecom_transform_only_dummies_);
8036
8037 if (((g = ffesymbol_global (s)) != NULL)
8038 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8039 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8040 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8041 && (ffeglobal_hook (g) != NULL_TREE)
8042 && ffe_is_globals ())
8043 {
8044 t = ffeglobal_hook (g);
8045 break;
8046 }
8047
8048 push_obstacks_nochange ();
8049 end_temporary_allocation ();
8050
8051 t = build_decl (FUNCTION_DECL,
8052 ffecom_get_external_identifier_ (s),
8053 ffecom_tree_subr_type); /* Assume subr. */
8054 DECL_EXTERNAL (t) = 1;
8055 TREE_PUBLIC (t) = 1;
8056
8057 t = start_decl (t, FALSE);
8058 finish_decl (t, NULL_TREE, FALSE);
8059
8060 if ((g != NULL)
8061 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8062 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8063 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8064 ffeglobal_set_hook (g, t);
8065
8066 resume_temporary_allocation ();
8067 pop_obstacks ();
8068
8069 break;
8070
8071 default:
8072 assert ("NONE where unexpected" == NULL);
8073 /* Fall through. */
8074 case FFEINFO_whereANY:
8075 break;
8076 }
8077 break;
8078
8079 case FFEINFO_kindENTITY:
8080 switch (ffeinfo_where (ffesymbol_info (s)))
8081 {
8082
8083 case FFEINFO_whereCONSTANT: /* ~~debugging info needed? */
8084 assert (!ffecom_transform_only_dummies_);
8085 t = error_mark_node; /* Shouldn't ever see this in expr. */
8086 break;
8087
8088 case FFEINFO_whereLOCAL:
8089 assert (!ffecom_transform_only_dummies_);
8090
8091 {
8092 ffestorag st = ffesymbol_storage (s);
8093 tree type;
8094
8095 if ((st != NULL)
8096 && (ffestorag_size (st) == 0))
8097 {
8098 t = error_mark_node;
8099 break;
8100 }
8101
8102 yes = suspend_momentary ();
8103 type = ffecom_type_localvar_ (s, bt, kt);
8104 resume_momentary (yes);
8105
8106 if (type == error_mark_node)
8107 {
8108 t = error_mark_node;
8109 break;
8110 }
8111
8112 if ((st != NULL)
8113 && (ffestorag_parent (st) != NULL))
8114 { /* Child of EQUIVALENCE parent. */
8115 ffestorag est;
8116 tree et;
8117 int yes;
8118 ffetargetOffset offset;
8119
8120 est = ffestorag_parent (st);
8121 ffecom_transform_equiv_ (est);
8122
8123 et = ffestorag_hook (est);
8124 assert (et != NULL_TREE);
8125
8126 if (! TREE_STATIC (et))
8127 put_var_into_stack (et);
8128
8129 yes = suspend_momentary ();
8130
8131 offset = ffestorag_modulo (est)
8132 + ffestorag_offset (ffesymbol_storage (s))
8133 - ffestorag_offset (est);
8134
8135 ffecom_debug_kludge_ (et, "EQUIVALENCE", s, type, offset);
8136
8137 /* (t_type *) (((char *) &et) + offset) */
8138
8139 t = convert (string_type_node, /* (char *) */
8140 ffecom_1 (ADDR_EXPR,
8141 build_pointer_type (TREE_TYPE (et)),
8142 et));
8143 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
8144 t,
8145 build_int_2 (offset, 0));
8146 t = convert (build_pointer_type (type),
8147 t);
8148
8149 addr = TRUE;
8150
8151 resume_momentary (yes);
8152 }
8153 else
8154 {
8155 tree initexpr;
8156 bool init = ffesymbol_is_init (s);
8157
8158 yes = suspend_momentary ();
8159
8160 t = build_decl (VAR_DECL,
8161 ffecom_get_identifier_ (ffesymbol_text (s)),
8162 type);
8163
8164 if (init
8165 || ffesymbol_namelisted (s)
8166 #ifdef FFECOM_sizeMAXSTACKITEM
8167 || ((st != NULL)
8168 && (ffestorag_size (st) > FFECOM_sizeMAXSTACKITEM))
8169 #endif
8170 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8171 && (ffecom_primary_entry_kind_
8172 != FFEINFO_kindBLOCKDATA)
8173 && (ffesymbol_is_save (s) || ffe_is_saveall ())))
8174 TREE_STATIC (t) = !ffesymbol_attr (s, FFESYMBOL_attrADJUSTABLE);
8175 else
8176 TREE_STATIC (t) = 0; /* No need to make static. */
8177
8178 if (init || ffe_is_init_local_zero ())
8179 DECL_INITIAL (t) = error_mark_node;
8180
8181 /* Keep -Wunused from complaining about var if it
8182 is used as sfunc arg or DATA implied-DO. */
8183 if (ffesymbol_attrs (s) & FFESYMBOL_attrsSFARG)
8184 DECL_IN_SYSTEM_HEADER (t) = 1;
8185
8186 t = start_decl (t, FALSE);
8187
8188 if (init)
8189 {
8190 if (ffesymbol_init (s) != NULL)
8191 initexpr = ffecom_expr (ffesymbol_init (s));
8192 else
8193 initexpr = ffecom_init_zero_ (t);
8194 }
8195 else if (ffe_is_init_local_zero ())
8196 initexpr = ffecom_init_zero_ (t);
8197 else
8198 initexpr = NULL_TREE; /* Not ref'd if !init. */
8199
8200 finish_decl (t, initexpr, FALSE);
8201
8202 if ((st != NULL) && (DECL_SIZE (t) != error_mark_node))
8203 {
8204 tree size_tree;
8205
8206 size_tree = size_binop (CEIL_DIV_EXPR,
8207 DECL_SIZE (t),
8208 size_int (BITS_PER_UNIT));
8209 assert (TREE_INT_CST_HIGH (size_tree) == 0);
8210 assert (TREE_INT_CST_LOW (size_tree) == ffestorag_size (st));
8211 }
8212
8213 resume_momentary (yes);
8214 }
8215 }
8216 break;
8217
8218 case FFEINFO_whereRESULT:
8219 assert (!ffecom_transform_only_dummies_);
8220
8221 if (bt == FFEINFO_basictypeCHARACTER)
8222 { /* Result is already in list of dummies, use
8223 it (& length). */
8224 t = ffecom_func_result_;
8225 tlen = ffecom_func_length_;
8226 addr = TRUE;
8227 break;
8228 }
8229 if ((ffecom_num_entrypoints_ == 0)
8230 && (bt == FFEINFO_basictypeCOMPLEX)
8231 && (ffesymbol_is_f2c (ffecom_primary_entry_)))
8232 { /* Result is already in list of dummies, use
8233 it. */
8234 t = ffecom_func_result_;
8235 addr = TRUE;
8236 break;
8237 }
8238 if (ffecom_func_result_ != NULL_TREE)
8239 {
8240 t = ffecom_func_result_;
8241 break;
8242 }
8243 if ((ffecom_num_entrypoints_ != 0)
8244 && (ffecom_master_bt_ == FFEINFO_basictypeNONE))
8245 {
8246 yes = suspend_momentary ();
8247
8248 assert (ffecom_multi_retval_ != NULL_TREE);
8249 t = ffecom_1 (INDIRECT_REF, ffecom_multi_type_node_,
8250 ffecom_multi_retval_);
8251 t = ffecom_2 (COMPONENT_REF, ffecom_tree_type[bt][kt],
8252 t, ffecom_multi_fields_[bt][kt]);
8253
8254 resume_momentary (yes);
8255 break;
8256 }
8257
8258 yes = suspend_momentary ();
8259
8260 t = build_decl (VAR_DECL,
8261 ffecom_get_identifier_ (ffesymbol_text (s)),
8262 ffecom_tree_type[bt][kt]);
8263 TREE_STATIC (t) = 0; /* Put result on stack. */
8264 t = start_decl (t, FALSE);
8265 finish_decl (t, NULL_TREE, FALSE);
8266
8267 ffecom_func_result_ = t;
8268
8269 resume_momentary (yes);
8270 break;
8271
8272 case FFEINFO_whereDUMMY:
8273 {
8274 tree type;
8275 ffebld dl;
8276 ffebld dim;
8277 tree low;
8278 tree high;
8279 tree old_sizes;
8280 bool adjustable = FALSE; /* Conditionally adjustable? */
8281
8282 type = ffecom_tree_type[bt][kt];
8283 if (ffesymbol_sfdummyparent (s) != NULL)
8284 {
8285 if (current_function_decl == ffecom_outer_function_decl_)
8286 { /* Exec transition before sfunc
8287 context; get it later. */
8288 break;
8289 }
8290 t = ffecom_get_identifier_ (ffesymbol_text
8291 (ffesymbol_sfdummyparent (s)));
8292 }
8293 else
8294 t = ffecom_get_identifier_ (ffesymbol_text (s));
8295
8296 assert (ffecom_transform_only_dummies_);
8297
8298 old_sizes = get_pending_sizes ();
8299 put_pending_sizes (old_sizes);
8300
8301 if (bt == FFEINFO_basictypeCHARACTER)
8302 tlen = ffecom_char_enhance_arg_ (&type, s);
8303 type = ffecom_check_size_overflow_ (s, type, TRUE);
8304
8305 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
8306 {
8307 if (type == error_mark_node)
8308 break;
8309
8310 dim = ffebld_head (dl);
8311 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
8312 if ((ffebld_left (dim) == NULL) || ffecom_doing_entry_)
8313 low = ffecom_integer_one_node;
8314 else
8315 low = ffecom_expr (ffebld_left (dim));
8316 assert (ffebld_right (dim) != NULL);
8317 if ((ffebld_op (ffebld_right (dim)) == FFEBLD_opSTAR)
8318 || ffecom_doing_entry_)
8319 {
8320 /* Used to just do high=low. But for ffecom_tree_
8321 canonize_ref_, it probably is important to correctly
8322 assess the size. E.g. given COMPLEX C(*),CFUNC and
8323 C(2)=CFUNC(C), overlap can happen, while it can't
8324 for, say, C(1)=CFUNC(C(2)). */
8325 /* Even more recently used to set to INT_MAX, but that
8326 broke when some overflow checking went into the back
8327 end. Now we just leave the upper bound unspecified. */
8328 high = NULL;
8329 }
8330 else
8331 high = ffecom_expr (ffebld_right (dim));
8332
8333 /* Determine whether array is conditionally adjustable,
8334 to decide whether back-end magic is needed.
8335
8336 Normally the front end uses the back-end function
8337 variable_size to wrap SAVE_EXPR's around expressions
8338 affecting the size/shape of an array so that the
8339 size/shape info doesn't change during execution
8340 of the compiled code even though variables and
8341 functions referenced in those expressions might.
8342
8343 variable_size also makes sure those saved expressions
8344 get evaluated immediately upon entry to the
8345 compiled procedure -- the front end normally doesn't
8346 have to worry about that.
8347
8348 However, there is a problem with this that affects
8349 g77's implementation of entry points, and that is
8350 that it is _not_ true that each invocation of the
8351 compiled procedure is permitted to evaluate
8352 array size/shape info -- because it is possible
8353 that, for some invocations, that info is invalid (in
8354 which case it is "promised" -- i.e. a violation of
8355 the Fortran standard -- that the compiled code
8356 won't reference the array or its size/shape
8357 during that particular invocation).
8358
8359 To phrase this in C terms, consider this gcc function:
8360
8361 void foo (int *n, float (*a)[*n])
8362 {
8363 // a is "pointer to array ...", fyi.
8364 }
8365
8366 Suppose that, for some invocations, it is permitted
8367 for a caller of foo to do this:
8368
8369 foo (NULL, NULL);
8370
8371 Now the _written_ code for foo can take such a call
8372 into account by either testing explicitly for whether
8373 (a == NULL) || (n == NULL) -- presumably it is
8374 not permitted to reference *a in various fashions
8375 if (n == NULL) I suppose -- or it can avoid it by
8376 looking at other info (other arguments, static/global
8377 data, etc.).
8378
8379 However, this won't work in gcc 2.5.8 because it'll
8380 automatically emit the code to save the "*n"
8381 expression, which'll yield a NULL dereference for
8382 the "foo (NULL, NULL)" call, something the code
8383 for foo cannot prevent.
8384
8385 g77 definitely needs to avoid executing such
8386 code anytime the pointer to the adjustable array
8387 is NULL, because even if its bounds expressions
8388 don't have any references to possible "absent"
8389 variables like "*n" -- say all variable references
8390 are to COMMON variables, i.e. global (though in C,
8391 local static could actually make sense) -- the
8392 expressions could yield other run-time problems
8393 for allowably "dead" values in those variables.
8394
8395 For example, let's consider a more complicated
8396 version of foo:
8397
8398 extern int i;
8399 extern int j;
8400
8401 void foo (float (*a)[i/j])
8402 {
8403 ...
8404 }
8405
8406 The above is (essentially) quite valid for Fortran
8407 but, again, for a call like "foo (NULL);", it is
8408 permitted for i and j to be undefined when the
8409 call is made. If j happened to be zero, for
8410 example, emitting the code to evaluate "i/j"
8411 could result in a run-time error.
8412
8413 Offhand, though I don't have my F77 or F90
8414 standards handy, it might even be valid for a
8415 bounds expression to contain a function reference,
8416 in which case I doubt it is permitted for an
8417 implementation to invoke that function in the
8418 Fortran case involved here (invocation of an
8419 alternate ENTRY point that doesn't have the adjustable
8420 array as one of its arguments).
8421
8422 So, the code that the compiler would normally emit
8423 to preevaluate the size/shape info for an
8424 adjustable array _must not_ be executed at run time
8425 in certain cases. Specifically, for Fortran,
8426 the case is when the pointer to the adjustable
8427 array == NULL. (For gnu-ish C, it might be nice
8428 for the source code itself to specify an expression
8429 that, if TRUE, inhibits execution of the code. Or
8430 reverse the sense for elegance.)
8431
8432 (Note that g77 could use a different test than NULL,
8433 actually, since it happens to always pass an
8434 integer to the called function that specifies which
8435 entry point is being invoked. Hmm, this might
8436 solve the next problem.)
8437
8438 One way a user could, I suppose, write "foo" so
8439 it works is to insert COND_EXPR's for the
8440 size/shape info so the dangerous stuff isn't
8441 actually done, as in:
8442
8443 void foo (int *n, float (*a)[(a == NULL) ? 0 : *n])
8444 {
8445 ...
8446 }
8447
8448 The next problem is that the front end needs to
8449 be able to tell the back end about the array's
8450 decl _before_ it tells it about the conditional
8451 expression to inhibit evaluation of size/shape info,
8452 as shown above.
8453
8454 To solve this, the front end needs to be able
8455 to give the back end the expression to inhibit
8456 generation of the preevaluation code _after_
8457 it makes the decl for the adjustable array.
8458
8459 Until then, the above example using the COND_EXPR
8460 doesn't pass muster with gcc because the "(a == NULL)"
8461 part has a reference to "a", which is still
8462 undefined at that point.
8463
8464 g77 will therefore use a different mechanism in the
8465 meantime. */
8466
8467 if (!adjustable
8468 && ((TREE_CODE (low) != INTEGER_CST)
8469 || (high && TREE_CODE (high) != INTEGER_CST)))
8470 adjustable = TRUE;
8471
8472 #if 0 /* Old approach -- see below. */
8473 if (TREE_CODE (low) != INTEGER_CST)
8474 low = ffecom_3 (COND_EXPR, integer_type_node,
8475 ffecom_adjarray_passed_ (s),
8476 low,
8477 ffecom_integer_zero_node);
8478
8479 if (high && TREE_CODE (high) != INTEGER_CST)
8480 high = ffecom_3 (COND_EXPR, integer_type_node,
8481 ffecom_adjarray_passed_ (s),
8482 high,
8483 ffecom_integer_zero_node);
8484 #endif
8485
8486 /* ~~~gcc/stor-layout.c/layout_type should do this,
8487 probably. Fixes 950302-1.f. */
8488
8489 if (TREE_CODE (low) != INTEGER_CST)
8490 low = variable_size (low);
8491
8492 /* ~~~similarly, this fixes dumb0.f. The C front end
8493 does this, which is why dumb0.c would work. */
8494
8495 if (high && TREE_CODE (high) != INTEGER_CST)
8496 high = variable_size (high);
8497
8498 type
8499 = build_array_type
8500 (type,
8501 build_range_type (ffecom_integer_type_node,
8502 low, high));
8503 type = ffecom_check_size_overflow_ (s, type, TRUE);
8504 }
8505
8506 if (type == error_mark_node)
8507 {
8508 t = error_mark_node;
8509 break;
8510 }
8511
8512 if ((ffesymbol_sfdummyparent (s) == NULL)
8513 || (ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER))
8514 {
8515 type = build_pointer_type (type);
8516 addr = TRUE;
8517 }
8518
8519 t = build_decl (PARM_DECL, t, type);
8520 #if BUILT_FOR_270
8521 DECL_ARTIFICIAL (t) = 1;
8522 #endif
8523
8524 /* If this arg is present in every entry point's list of
8525 dummy args, then we're done. */
8526
8527 if (ffesymbol_numentries (s)
8528 == (ffecom_num_entrypoints_ + 1))
8529 break;
8530
8531 #if 1
8532
8533 /* If variable_size in stor-layout has been called during
8534 the above, then get_pending_sizes should have the
8535 yet-to-be-evaluated saved expressions pending.
8536 Make the whole lot of them get emitted, conditionally
8537 on whether the array decl ("t" above) is not NULL. */
8538
8539 {
8540 tree sizes = get_pending_sizes ();
8541 tree tem;
8542
8543 for (tem = sizes;
8544 tem != old_sizes;
8545 tem = TREE_CHAIN (tem))
8546 {
8547 tree temv = TREE_VALUE (tem);
8548
8549 if (sizes == tem)
8550 sizes = temv;
8551 else
8552 sizes
8553 = ffecom_2 (COMPOUND_EXPR,
8554 TREE_TYPE (sizes),
8555 temv,
8556 sizes);
8557 }
8558
8559 if (sizes != tem)
8560 {
8561 sizes
8562 = ffecom_3 (COND_EXPR,
8563 TREE_TYPE (sizes),
8564 ffecom_2 (NE_EXPR,
8565 integer_type_node,
8566 t,
8567 null_pointer_node),
8568 sizes,
8569 convert (TREE_TYPE (sizes),
8570 integer_zero_node));
8571 sizes = ffecom_save_tree (sizes);
8572
8573 sizes
8574 = tree_cons (NULL_TREE, sizes, tem);
8575 }
8576
8577 if (sizes)
8578 put_pending_sizes (sizes);
8579 }
8580
8581 #else
8582 #if 0
8583 if (adjustable
8584 && (ffesymbol_numentries (s)
8585 != ffecom_num_entrypoints_ + 1))
8586 DECL_SOMETHING (t)
8587 = ffecom_2 (NE_EXPR, integer_type_node,
8588 t,
8589 null_pointer_node);
8590 #else
8591 #if 0
8592 if (adjustable
8593 && (ffesymbol_numentries (s)
8594 != ffecom_num_entrypoints_ + 1))
8595 {
8596 ffebad_start (FFEBAD_MISSING_ADJARRAY_UNSUPPORTED);
8597 ffebad_here (0, ffesymbol_where_line (s),
8598 ffesymbol_where_column (s));
8599 ffebad_string (ffesymbol_text (s));
8600 ffebad_finish ();
8601 }
8602 #endif
8603 #endif
8604 #endif
8605 }
8606 break;
8607
8608 case FFEINFO_whereCOMMON:
8609 {
8610 ffesymbol cs;
8611 ffeglobal cg;
8612 tree ct;
8613 ffestorag st = ffesymbol_storage (s);
8614 tree type;
8615 int yes;
8616
8617 cs = ffesymbol_common (s); /* The COMMON area itself. */
8618 if (st != NULL) /* Else not laid out. */
8619 {
8620 ffecom_transform_common_ (cs);
8621 st = ffesymbol_storage (s);
8622 }
8623
8624 yes = suspend_momentary ();
8625
8626 type = ffecom_type_localvar_ (s, bt, kt);
8627
8628 cg = ffesymbol_global (cs); /* The global COMMON info. */
8629 if ((cg == NULL)
8630 || (ffeglobal_type (cg) != FFEGLOBAL_typeCOMMON))
8631 ct = NULL_TREE;
8632 else
8633 ct = ffeglobal_hook (cg); /* The common area's tree. */
8634
8635 if ((ct == NULL_TREE)
8636 || (st == NULL)
8637 || (type == error_mark_node))
8638 t = error_mark_node;
8639 else
8640 {
8641 ffetargetOffset offset;
8642 ffestorag cst;
8643
8644 cst = ffestorag_parent (st);
8645 assert (cst == ffesymbol_storage (cs));
8646
8647 offset = ffestorag_modulo (cst)
8648 + ffestorag_offset (st)
8649 - ffestorag_offset (cst);
8650
8651 ffecom_debug_kludge_ (ct, "COMMON", s, type, offset);
8652
8653 /* (t_type *) (((char *) &ct) + offset) */
8654
8655 t = convert (string_type_node, /* (char *) */
8656 ffecom_1 (ADDR_EXPR,
8657 build_pointer_type (TREE_TYPE (ct)),
8658 ct));
8659 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
8660 t,
8661 build_int_2 (offset, 0));
8662 t = convert (build_pointer_type (type),
8663 t);
8664
8665 addr = TRUE;
8666 }
8667
8668 resume_momentary (yes);
8669 }
8670 break;
8671
8672 case FFEINFO_whereIMMEDIATE:
8673 case FFEINFO_whereGLOBAL:
8674 case FFEINFO_whereFLEETING:
8675 case FFEINFO_whereFLEETING_CADDR:
8676 case FFEINFO_whereFLEETING_IADDR:
8677 case FFEINFO_whereINTRINSIC:
8678 case FFEINFO_whereCONSTANT_SUBOBJECT:
8679 default:
8680 assert ("ENTITY where unheard of" == NULL);
8681 /* Fall through. */
8682 case FFEINFO_whereANY:
8683 t = error_mark_node;
8684 break;
8685 }
8686 break;
8687
8688 case FFEINFO_kindFUNCTION:
8689 switch (ffeinfo_where (ffesymbol_info (s)))
8690 {
8691 case FFEINFO_whereLOCAL: /* Me. */
8692 assert (!ffecom_transform_only_dummies_);
8693 t = current_function_decl;
8694 break;
8695
8696 case FFEINFO_whereGLOBAL:
8697 assert (!ffecom_transform_only_dummies_);
8698
8699 if (((g = ffesymbol_global (s)) != NULL)
8700 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8701 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8702 && (ffeglobal_hook (g) != NULL_TREE)
8703 && ffe_is_globals ())
8704 {
8705 t = ffeglobal_hook (g);
8706 break;
8707 }
8708
8709 push_obstacks_nochange ();
8710 end_temporary_allocation ();
8711
8712 if (ffesymbol_is_f2c (s)
8713 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8714 t = ffecom_tree_fun_type[bt][kt];
8715 else
8716 t = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
8717
8718 t = build_decl (FUNCTION_DECL,
8719 ffecom_get_external_identifier_ (s),
8720 t);
8721 DECL_EXTERNAL (t) = 1;
8722 TREE_PUBLIC (t) = 1;
8723
8724 t = start_decl (t, FALSE);
8725 finish_decl (t, NULL_TREE, FALSE);
8726
8727 if ((g != NULL)
8728 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8729 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8730 ffeglobal_set_hook (g, t);
8731
8732 resume_temporary_allocation ();
8733 pop_obstacks ();
8734
8735 break;
8736
8737 case FFEINFO_whereDUMMY:
8738 assert (ffecom_transform_only_dummies_);
8739
8740 if (ffesymbol_is_f2c (s)
8741 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8742 t = ffecom_tree_ptr_to_fun_type[bt][kt];
8743 else
8744 t = build_pointer_type
8745 (build_function_type (ffecom_tree_type[bt][kt], NULL_TREE));
8746
8747 t = build_decl (PARM_DECL,
8748 ffecom_get_identifier_ (ffesymbol_text (s)),
8749 t);
8750 #if BUILT_FOR_270
8751 DECL_ARTIFICIAL (t) = 1;
8752 #endif
8753 addr = TRUE;
8754 break;
8755
8756 case FFEINFO_whereCONSTANT: /* Statement function. */
8757 assert (!ffecom_transform_only_dummies_);
8758 t = ffecom_gen_sfuncdef_ (s, bt, kt);
8759 break;
8760
8761 case FFEINFO_whereINTRINSIC:
8762 assert (!ffecom_transform_only_dummies_);
8763 break; /* Let actual references generate their
8764 decls. */
8765
8766 default:
8767 assert ("FUNCTION where unheard of" == NULL);
8768 /* Fall through. */
8769 case FFEINFO_whereANY:
8770 t = error_mark_node;
8771 break;
8772 }
8773 break;
8774
8775 case FFEINFO_kindSUBROUTINE:
8776 switch (ffeinfo_where (ffesymbol_info (s)))
8777 {
8778 case FFEINFO_whereLOCAL: /* Me. */
8779 assert (!ffecom_transform_only_dummies_);
8780 t = current_function_decl;
8781 break;
8782
8783 case FFEINFO_whereGLOBAL:
8784 assert (!ffecom_transform_only_dummies_);
8785
8786 if (((g = ffesymbol_global (s)) != NULL)
8787 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8788 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8789 && (ffeglobal_hook (g) != NULL_TREE)
8790 && ffe_is_globals ())
8791 {
8792 t = ffeglobal_hook (g);
8793 break;
8794 }
8795
8796 push_obstacks_nochange ();
8797 end_temporary_allocation ();
8798
8799 t = build_decl (FUNCTION_DECL,
8800 ffecom_get_external_identifier_ (s),
8801 ffecom_tree_subr_type);
8802 DECL_EXTERNAL (t) = 1;
8803 TREE_PUBLIC (t) = 1;
8804
8805 t = start_decl (t, FALSE);
8806 finish_decl (t, NULL_TREE, FALSE);
8807
8808 if ((g != NULL)
8809 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8810 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8811 ffeglobal_set_hook (g, t);
8812
8813 resume_temporary_allocation ();
8814 pop_obstacks ();
8815
8816 break;
8817
8818 case FFEINFO_whereDUMMY:
8819 assert (ffecom_transform_only_dummies_);
8820
8821 t = build_decl (PARM_DECL,
8822 ffecom_get_identifier_ (ffesymbol_text (s)),
8823 ffecom_tree_ptr_to_subr_type);
8824 #if BUILT_FOR_270
8825 DECL_ARTIFICIAL (t) = 1;
8826 #endif
8827 addr = TRUE;
8828 break;
8829
8830 case FFEINFO_whereINTRINSIC:
8831 assert (!ffecom_transform_only_dummies_);
8832 break; /* Let actual references generate their
8833 decls. */
8834
8835 default:
8836 assert ("SUBROUTINE where unheard of" == NULL);
8837 /* Fall through. */
8838 case FFEINFO_whereANY:
8839 t = error_mark_node;
8840 break;
8841 }
8842 break;
8843
8844 case FFEINFO_kindPROGRAM:
8845 switch (ffeinfo_where (ffesymbol_info (s)))
8846 {
8847 case FFEINFO_whereLOCAL: /* Me. */
8848 assert (!ffecom_transform_only_dummies_);
8849 t = current_function_decl;
8850 break;
8851
8852 case FFEINFO_whereCOMMON:
8853 case FFEINFO_whereDUMMY:
8854 case FFEINFO_whereGLOBAL:
8855 case FFEINFO_whereRESULT:
8856 case FFEINFO_whereFLEETING:
8857 case FFEINFO_whereFLEETING_CADDR:
8858 case FFEINFO_whereFLEETING_IADDR:
8859 case FFEINFO_whereIMMEDIATE:
8860 case FFEINFO_whereINTRINSIC:
8861 case FFEINFO_whereCONSTANT:
8862 case FFEINFO_whereCONSTANT_SUBOBJECT:
8863 default:
8864 assert ("PROGRAM where unheard of" == NULL);
8865 /* Fall through. */
8866 case FFEINFO_whereANY:
8867 t = error_mark_node;
8868 break;
8869 }
8870 break;
8871
8872 case FFEINFO_kindBLOCKDATA:
8873 switch (ffeinfo_where (ffesymbol_info (s)))
8874 {
8875 case FFEINFO_whereLOCAL: /* Me. */
8876 assert (!ffecom_transform_only_dummies_);
8877 t = current_function_decl;
8878 break;
8879
8880 case FFEINFO_whereGLOBAL:
8881 assert (!ffecom_transform_only_dummies_);
8882
8883 push_obstacks_nochange ();
8884 end_temporary_allocation ();
8885
8886 t = build_decl (FUNCTION_DECL,
8887 ffecom_get_external_identifier_ (s),
8888 ffecom_tree_blockdata_type);
8889 DECL_EXTERNAL (t) = 1;
8890 TREE_PUBLIC (t) = 1;
8891
8892 t = start_decl (t, FALSE);
8893 finish_decl (t, NULL_TREE, FALSE);
8894
8895 resume_temporary_allocation ();
8896 pop_obstacks ();
8897
8898 break;
8899
8900 case FFEINFO_whereCOMMON:
8901 case FFEINFO_whereDUMMY:
8902 case FFEINFO_whereRESULT:
8903 case FFEINFO_whereFLEETING:
8904 case FFEINFO_whereFLEETING_CADDR:
8905 case FFEINFO_whereFLEETING_IADDR:
8906 case FFEINFO_whereIMMEDIATE:
8907 case FFEINFO_whereINTRINSIC:
8908 case FFEINFO_whereCONSTANT:
8909 case FFEINFO_whereCONSTANT_SUBOBJECT:
8910 default:
8911 assert ("BLOCKDATA where unheard of" == NULL);
8912 /* Fall through. */
8913 case FFEINFO_whereANY:
8914 t = error_mark_node;
8915 break;
8916 }
8917 break;
8918
8919 case FFEINFO_kindCOMMON:
8920 switch (ffeinfo_where (ffesymbol_info (s)))
8921 {
8922 case FFEINFO_whereLOCAL:
8923 assert (!ffecom_transform_only_dummies_);
8924 ffecom_transform_common_ (s);
8925 break;
8926
8927 case FFEINFO_whereNONE:
8928 case FFEINFO_whereCOMMON:
8929 case FFEINFO_whereDUMMY:
8930 case FFEINFO_whereGLOBAL:
8931 case FFEINFO_whereRESULT:
8932 case FFEINFO_whereFLEETING:
8933 case FFEINFO_whereFLEETING_CADDR:
8934 case FFEINFO_whereFLEETING_IADDR:
8935 case FFEINFO_whereIMMEDIATE:
8936 case FFEINFO_whereINTRINSIC:
8937 case FFEINFO_whereCONSTANT:
8938 case FFEINFO_whereCONSTANT_SUBOBJECT:
8939 default:
8940 assert ("COMMON where unheard of" == NULL);
8941 /* Fall through. */
8942 case FFEINFO_whereANY:
8943 t = error_mark_node;
8944 break;
8945 }
8946 break;
8947
8948 case FFEINFO_kindCONSTRUCT:
8949 switch (ffeinfo_where (ffesymbol_info (s)))
8950 {
8951 case FFEINFO_whereLOCAL:
8952 assert (!ffecom_transform_only_dummies_);
8953 break;
8954
8955 case FFEINFO_whereNONE:
8956 case FFEINFO_whereCOMMON:
8957 case FFEINFO_whereDUMMY:
8958 case FFEINFO_whereGLOBAL:
8959 case FFEINFO_whereRESULT:
8960 case FFEINFO_whereFLEETING:
8961 case FFEINFO_whereFLEETING_CADDR:
8962 case FFEINFO_whereFLEETING_IADDR:
8963 case FFEINFO_whereIMMEDIATE:
8964 case FFEINFO_whereINTRINSIC:
8965 case FFEINFO_whereCONSTANT:
8966 case FFEINFO_whereCONSTANT_SUBOBJECT:
8967 default:
8968 assert ("CONSTRUCT where unheard of" == NULL);
8969 /* Fall through. */
8970 case FFEINFO_whereANY:
8971 t = error_mark_node;
8972 break;
8973 }
8974 break;
8975
8976 case FFEINFO_kindNAMELIST:
8977 switch (ffeinfo_where (ffesymbol_info (s)))
8978 {
8979 case FFEINFO_whereLOCAL:
8980 assert (!ffecom_transform_only_dummies_);
8981 t = ffecom_transform_namelist_ (s);
8982 break;
8983
8984 case FFEINFO_whereNONE:
8985 case FFEINFO_whereCOMMON:
8986 case FFEINFO_whereDUMMY:
8987 case FFEINFO_whereGLOBAL:
8988 case FFEINFO_whereRESULT:
8989 case FFEINFO_whereFLEETING:
8990 case FFEINFO_whereFLEETING_CADDR:
8991 case FFEINFO_whereFLEETING_IADDR:
8992 case FFEINFO_whereIMMEDIATE:
8993 case FFEINFO_whereINTRINSIC:
8994 case FFEINFO_whereCONSTANT:
8995 case FFEINFO_whereCONSTANT_SUBOBJECT:
8996 default:
8997 assert ("NAMELIST where unheard of" == NULL);
8998 /* Fall through. */
8999 case FFEINFO_whereANY:
9000 t = error_mark_node;
9001 break;
9002 }
9003 break;
9004
9005 default:
9006 assert ("kind unheard of" == NULL);
9007 /* Fall through. */
9008 case FFEINFO_kindANY:
9009 t = error_mark_node;
9010 break;
9011 }
9012
9013 ffesymbol_hook (s).decl_tree = t;
9014 ffesymbol_hook (s).length_tree = tlen;
9015 ffesymbol_hook (s).addr = addr;
9016
9017 lineno = old_lineno;
9018 input_filename = old_input_filename;
9019
9020 return s;
9021 }
9022
9023 #endif
9024 /* Transform into ASSIGNable symbol.
9025
9026 Symbol has already been transformed, but for whatever reason, the
9027 resulting decl_tree has been deemed not usable for an ASSIGN target.
9028 (E.g. it isn't wide enough to hold a pointer.) So, here we invent
9029 another local symbol of type void * and stuff that in the assign_tree
9030 argument. The F77/F90 standards allow this implementation. */
9031
9032 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9033 static ffesymbol
9034 ffecom_sym_transform_assign_ (ffesymbol s)
9035 {
9036 tree t; /* Transformed thingy. */
9037 int yes;
9038 int old_lineno = lineno;
9039 char *old_input_filename = input_filename;
9040
9041 if (ffesymbol_sfdummyparent (s) == NULL)
9042 {
9043 input_filename = ffesymbol_where_filename (s);
9044 lineno = ffesymbol_where_filelinenum (s);
9045 }
9046 else
9047 {
9048 ffesymbol sf = ffesymbol_sfdummyparent (s);
9049
9050 input_filename = ffesymbol_where_filename (sf);
9051 lineno = ffesymbol_where_filelinenum (sf);
9052 }
9053
9054 assert (!ffecom_transform_only_dummies_);
9055
9056 yes = suspend_momentary ();
9057
9058 t = build_decl (VAR_DECL,
9059 ffecom_get_invented_identifier ("__g77_ASSIGN_%s",
9060 ffesymbol_text (s),
9061 0),
9062 TREE_TYPE (null_pointer_node));
9063
9064 switch (ffesymbol_where (s))
9065 {
9066 case FFEINFO_whereLOCAL:
9067 /* Unlike for regular vars, SAVE status is easy to determine for
9068 ASSIGNed vars, since there's no initialization, there's no
9069 effective storage association (so "SAVE J" does not apply to
9070 K even given "EQUIVALENCE (J,K)"), there's no size issue
9071 to worry about, etc. */
9072 if ((ffesymbol_is_save (s) || ffe_is_saveall ())
9073 && (ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
9074 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA))
9075 TREE_STATIC (t) = 1; /* SAVEd in proc, make static. */
9076 else
9077 TREE_STATIC (t) = 0; /* No need to make static. */
9078 break;
9079
9080 case FFEINFO_whereCOMMON:
9081 TREE_STATIC (t) = 1; /* Assume COMMONs always SAVEd. */
9082 break;
9083
9084 case FFEINFO_whereDUMMY:
9085 /* Note that twinning a DUMMY means the caller won't see
9086 the ASSIGNed value. But both F77 and F90 allow implementations
9087 to do this, i.e. disallow Fortran code that would try and
9088 take advantage of actually putting a label into a variable
9089 via a dummy argument (or any other storage association, for
9090 that matter). */
9091 TREE_STATIC (t) = 0;
9092 break;
9093
9094 default:
9095 TREE_STATIC (t) = 0;
9096 break;
9097 }
9098
9099 t = start_decl (t, FALSE);
9100 finish_decl (t, NULL_TREE, FALSE);
9101
9102 resume_momentary (yes);
9103
9104 ffesymbol_hook (s).assign_tree = t;
9105
9106 lineno = old_lineno;
9107 input_filename = old_input_filename;
9108
9109 return s;
9110 }
9111
9112 #endif
9113 /* Implement COMMON area in back end.
9114
9115 Because COMMON-based variables can be referenced in the dimension
9116 expressions of dummy (adjustable) arrays, and because dummies
9117 (in the gcc back end) need to be put in the outer binding level
9118 of a function (which has two binding levels, the outer holding
9119 the dummies and the inner holding the other vars), special care
9120 must be taken to handle COMMON areas.
9121
9122 The current strategy is basically to always tell the back end about
9123 the COMMON area as a top-level external reference to just a block
9124 of storage of the master type of that area (e.g. integer, real,
9125 character, whatever -- not a structure). As a distinct action,
9126 if initial values are provided, tell the back end about the area
9127 as a top-level non-external (initialized) area and remember not to
9128 allow further initialization or expansion of the area. Meanwhile,
9129 if no initialization happens at all, tell the back end about
9130 the largest size we've seen declared so the space does get reserved.
9131 (This function doesn't handle all that stuff, but it does some
9132 of the important things.)
9133
9134 Meanwhile, for COMMON variables themselves, just keep creating
9135 references like *((float *) (&common_area + offset)) each time
9136 we reference the variable. In other words, don't make a VAR_DECL
9137 or any kind of component reference (like we used to do before 0.4),
9138 though we might do that as well just for debugging purposes (and
9139 stuff the rtl with the appropriate offset expression). */
9140
9141 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9142 static void
9143 ffecom_transform_common_ (ffesymbol s)
9144 {
9145 ffestorag st = ffesymbol_storage (s);
9146 ffeglobal g = ffesymbol_global (s);
9147 tree cbt;
9148 tree cbtype;
9149 tree init;
9150 bool is_init = ffestorag_is_init (st);
9151
9152 assert (st != NULL);
9153
9154 if ((g == NULL)
9155 || (ffeglobal_type (g) != FFEGLOBAL_typeCOMMON))
9156 return;
9157
9158 /* First update the size of the area in global terms. */
9159
9160 ffeglobal_size_common (s, ffestorag_size (st));
9161
9162 if (!ffeglobal_common_init (g))
9163 is_init = FALSE; /* No explicit init, don't let erroneous joins init. */
9164
9165 cbt = ffeglobal_hook (g);
9166
9167 /* If we already have declared this common block for a previous program
9168 unit, and either we already initialized it or we don't have new
9169 initialization for it, just return what we have without changing it. */
9170
9171 if ((cbt != NULL_TREE)
9172 && (!is_init
9173 || !DECL_EXTERNAL (cbt)))
9174 return;
9175
9176 /* Process inits. */
9177
9178 if (is_init)
9179 {
9180 if (ffestorag_init (st) != NULL)
9181 {
9182 init = ffecom_expr (ffestorag_init (st));
9183 if (init == error_mark_node)
9184 { /* Hopefully the back end complained! */
9185 init = NULL_TREE;
9186 if (cbt != NULL_TREE)
9187 return;
9188 }
9189 }
9190 else
9191 init = error_mark_node;
9192 }
9193 else
9194 init = NULL_TREE;
9195
9196 push_obstacks_nochange ();
9197 end_temporary_allocation ();
9198
9199 /* cbtype must be permanently allocated! */
9200
9201 if (init)
9202 cbtype = build_array_type (char_type_node,
9203 build_range_type (integer_type_node,
9204 integer_one_node,
9205 build_int_2
9206 (ffeglobal_common_size (g),
9207 0)));
9208 else
9209 cbtype = build_array_type (char_type_node, NULL_TREE);
9210
9211 if (cbt == NULL_TREE)
9212 {
9213 cbt
9214 = build_decl (VAR_DECL,
9215 ffecom_get_external_identifier_ (s),
9216 cbtype);
9217 TREE_STATIC (cbt) = 1;
9218 TREE_PUBLIC (cbt) = 1;
9219 }
9220 else
9221 {
9222 assert (is_init);
9223 TREE_TYPE (cbt) = cbtype;
9224 }
9225 DECL_EXTERNAL (cbt) = init ? 0 : 1;
9226 DECL_INITIAL (cbt) = init ? error_mark_node : NULL_TREE;
9227
9228 cbt = start_decl (cbt, TRUE);
9229 if (ffeglobal_hook (g) != NULL)
9230 assert (cbt == ffeglobal_hook (g));
9231
9232 assert (!init || !DECL_EXTERNAL (cbt));
9233
9234 /* Make sure that any type can live in COMMON and be referenced
9235 without getting a bus error. We could pick the most restrictive
9236 alignment of all entities actually placed in the COMMON, but
9237 this seems easy enough. */
9238
9239 DECL_ALIGN (cbt) = BIGGEST_ALIGNMENT;
9240
9241 if (is_init && (ffestorag_init (st) == NULL))
9242 init = ffecom_init_zero_ (cbt);
9243
9244 finish_decl (cbt, init, TRUE);
9245
9246 if (is_init)
9247 ffestorag_set_init (st, ffebld_new_any ());
9248
9249 if (init)
9250 {
9251 tree size_tree;
9252
9253 assert (DECL_SIZE (cbt) != NULL_TREE);
9254 assert (TREE_CODE (DECL_SIZE (cbt)) == INTEGER_CST);
9255 size_tree = size_binop (CEIL_DIV_EXPR,
9256 DECL_SIZE (cbt),
9257 size_int (BITS_PER_UNIT));
9258 assert (TREE_INT_CST_HIGH (size_tree) == 0);
9259 assert (TREE_INT_CST_LOW (size_tree) == ffeglobal_common_size (g));
9260 }
9261
9262 ffeglobal_set_hook (g, cbt);
9263
9264 ffestorag_set_hook (st, cbt);
9265
9266 resume_temporary_allocation ();
9267 pop_obstacks ();
9268 }
9269
9270 #endif
9271 /* Make master area for local EQUIVALENCE. */
9272
9273 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9274 static void
9275 ffecom_transform_equiv_ (ffestorag eqst)
9276 {
9277 tree eqt;
9278 tree eqtype;
9279 tree init;
9280 tree high;
9281 bool is_init = ffestorag_is_init (eqst);
9282 int yes;
9283
9284 assert (eqst != NULL);
9285
9286 eqt = ffestorag_hook (eqst);
9287
9288 if (eqt != NULL_TREE)
9289 return;
9290
9291 /* Process inits. */
9292
9293 if (is_init)
9294 {
9295 if (ffestorag_init (eqst) != NULL)
9296 {
9297 init = ffecom_expr (ffestorag_init (eqst));
9298 if (init == error_mark_node)
9299 init = NULL_TREE; /* Hopefully the back end complained! */
9300 }
9301 else
9302 init = error_mark_node;
9303 }
9304 else if (ffe_is_init_local_zero ())
9305 init = error_mark_node;
9306 else
9307 init = NULL_TREE;
9308
9309 ffecom_member_namelisted_ = FALSE;
9310 ffestorag_drive (ffestorag_list_equivs (eqst),
9311 &ffecom_member_phase1_,
9312 eqst);
9313
9314 yes = suspend_momentary ();
9315
9316 high = build_int_2 (ffestorag_size (eqst), 0);
9317 TREE_TYPE (high) = ffecom_integer_type_node;
9318
9319 eqtype = build_array_type (char_type_node,
9320 build_range_type (ffecom_integer_type_node,
9321 ffecom_integer_one_node,
9322 high));
9323
9324 eqt = build_decl (VAR_DECL,
9325 ffecom_get_invented_identifier ("__g77_equiv_%s",
9326 ffesymbol_text
9327 (ffestorag_symbol
9328 (eqst)),
9329 0),
9330 eqtype);
9331 DECL_EXTERNAL (eqt) = 0;
9332 if (is_init
9333 || ffecom_member_namelisted_
9334 #ifdef FFECOM_sizeMAXSTACKITEM
9335 || (ffestorag_size (eqst) > FFECOM_sizeMAXSTACKITEM)
9336 #endif
9337 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
9338 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
9339 && (ffestorag_is_save (eqst) || ffe_is_saveall ())))
9340 TREE_STATIC (eqt) = 1;
9341 else
9342 TREE_STATIC (eqt) = 0;
9343 TREE_PUBLIC (eqt) = 0;
9344 DECL_CONTEXT (eqt) = current_function_decl;
9345 if (init)
9346 DECL_INITIAL (eqt) = error_mark_node;
9347 else
9348 DECL_INITIAL (eqt) = NULL_TREE;
9349
9350 eqt = start_decl (eqt, FALSE);
9351
9352 /* Make sure this shows up as a debug symbol, which is not normally
9353 the case for invented identifiers. */
9354
9355 DECL_IGNORED_P (eqt) = 0;
9356
9357 /* Make sure that any type can live in EQUIVALENCE and be referenced
9358 without getting a bus error. We could pick the most restrictive
9359 alignment of all entities actually placed in the EQUIVALENCE, but
9360 this seems easy enough. */
9361
9362 DECL_ALIGN (eqt) = BIGGEST_ALIGNMENT;
9363
9364 if ((!is_init && ffe_is_init_local_zero ())
9365 || (is_init && (ffestorag_init (eqst) == NULL)))
9366 init = ffecom_init_zero_ (eqt);
9367
9368 finish_decl (eqt, init, FALSE);
9369
9370 if (is_init)
9371 ffestorag_set_init (eqst, ffebld_new_any ());
9372
9373 {
9374 tree size_tree;
9375
9376 size_tree = size_binop (CEIL_DIV_EXPR,
9377 DECL_SIZE (eqt),
9378 size_int (BITS_PER_UNIT));
9379 assert (TREE_INT_CST_HIGH (size_tree) == 0);
9380 assert (TREE_INT_CST_LOW (size_tree) == ffestorag_size (eqst));
9381 }
9382
9383 ffestorag_set_hook (eqst, eqt);
9384
9385 #ifdef SOMEONE_GETS_DEBUG_SUPPORT_WORKING
9386 ffestorag_drive (ffestorag_list_equivs (eqst),
9387 &ffecom_member_phase2_,
9388 eqst);
9389 #endif
9390
9391 resume_momentary (yes);
9392 }
9393
9394 #endif
9395 /* Implement NAMELIST in back end. See f2c/format.c for more info. */
9396
9397 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9398 static tree
9399 ffecom_transform_namelist_ (ffesymbol s)
9400 {
9401 tree nmlt;
9402 tree nmltype = ffecom_type_namelist_ ();
9403 tree nmlinits;
9404 tree nameinit;
9405 tree varsinit;
9406 tree nvarsinit;
9407 tree field;
9408 tree high;
9409 int yes;
9410 int i;
9411 static int mynumber = 0;
9412
9413 yes = suspend_momentary ();
9414
9415 nmlt = build_decl (VAR_DECL,
9416 ffecom_get_invented_identifier ("__g77_namelist_%d",
9417 NULL, mynumber++),
9418 nmltype);
9419 TREE_STATIC (nmlt) = 1;
9420 DECL_INITIAL (nmlt) = error_mark_node;
9421
9422 nmlt = start_decl (nmlt, FALSE);
9423
9424 /* Process inits. */
9425
9426 i = strlen (ffesymbol_text (s));
9427
9428 high = build_int_2 (i, 0);
9429 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
9430
9431 nameinit = ffecom_build_f2c_string_ (i + 1,
9432 ffesymbol_text (s));
9433 TREE_TYPE (nameinit)
9434 = build_type_variant
9435 (build_array_type
9436 (char_type_node,
9437 build_range_type (ffecom_f2c_ftnlen_type_node,
9438 ffecom_f2c_ftnlen_one_node,
9439 high)),
9440 1, 0);
9441 TREE_CONSTANT (nameinit) = 1;
9442 TREE_STATIC (nameinit) = 1;
9443 nameinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (nameinit)),
9444 nameinit);
9445
9446 varsinit = ffecom_vardesc_array_ (s);
9447 varsinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (varsinit)),
9448 varsinit);
9449 TREE_CONSTANT (varsinit) = 1;
9450 TREE_STATIC (varsinit) = 1;
9451
9452 {
9453 ffebld b;
9454
9455 for (i = 0, b = ffesymbol_namelist (s); b != NULL; b = ffebld_trail (b))
9456 ++i;
9457 }
9458 nvarsinit = build_int_2 (i, 0);
9459 TREE_TYPE (nvarsinit) = integer_type_node;
9460 TREE_CONSTANT (nvarsinit) = 1;
9461 TREE_STATIC (nvarsinit) = 1;
9462
9463 nmlinits = build_tree_list ((field = TYPE_FIELDS (nmltype)), nameinit);
9464 TREE_CHAIN (nmlinits) = build_tree_list ((field = TREE_CHAIN (field)),
9465 varsinit);
9466 TREE_CHAIN (TREE_CHAIN (nmlinits))
9467 = build_tree_list ((field = TREE_CHAIN (field)), nvarsinit);
9468
9469 nmlinits = build (CONSTRUCTOR, nmltype, NULL_TREE, nmlinits);
9470 TREE_CONSTANT (nmlinits) = 1;
9471 TREE_STATIC (nmlinits) = 1;
9472
9473 finish_decl (nmlt, nmlinits, FALSE);
9474
9475 nmlt = ffecom_1 (ADDR_EXPR, build_pointer_type (nmltype), nmlt);
9476
9477 resume_momentary (yes);
9478
9479 return nmlt;
9480 }
9481
9482 #endif
9483
9484 /* A subroutine of ffecom_tree_canonize_ref_. The incoming tree is
9485 analyzed on the assumption it is calculating a pointer to be
9486 indirected through. It must return the proper decl and offset,
9487 taking into account different units of measurements for offsets. */
9488
9489 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9490 static void
9491 ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
9492 tree t)
9493 {
9494 switch (TREE_CODE (t))
9495 {
9496 case NOP_EXPR:
9497 case CONVERT_EXPR:
9498 case NON_LVALUE_EXPR:
9499 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
9500 break;
9501
9502 case PLUS_EXPR:
9503 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
9504 if ((*decl == NULL_TREE)
9505 || (*decl == error_mark_node))
9506 break;
9507
9508 if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST)
9509 {
9510 /* An offset into COMMON. */
9511 *offset = size_binop (PLUS_EXPR,
9512 *offset,
9513 TREE_OPERAND (t, 1));
9514 /* Convert offset (presumably in bytes) into canonical units
9515 (presumably bits). */
9516 *offset = size_binop (MULT_EXPR,
9517 TYPE_SIZE (TREE_TYPE (TREE_TYPE (t))),
9518 *offset);
9519 break;
9520 }
9521 /* Not a COMMON reference, so an unrecognized pattern. */
9522 *decl = error_mark_node;
9523 break;
9524
9525 case PARM_DECL:
9526 *decl = t;
9527 *offset = bitsize_int (0L, 0L);
9528 break;
9529
9530 case ADDR_EXPR:
9531 if (TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL)
9532 {
9533 /* A reference to COMMON. */
9534 *decl = TREE_OPERAND (t, 0);
9535 *offset = bitsize_int (0L, 0L);
9536 break;
9537 }
9538 /* Fall through. */
9539 default:
9540 /* Not a COMMON reference, so an unrecognized pattern. */
9541 *decl = error_mark_node;
9542 break;
9543 }
9544 }
9545 #endif
9546
9547 /* Given a tree that is possibly intended for use as an lvalue, return
9548 information representing a canonical view of that tree as a decl, an
9549 offset into that decl, and a size for the lvalue.
9550
9551 If there's no applicable decl, NULL_TREE is returned for the decl,
9552 and the other fields are left undefined.
9553
9554 If the tree doesn't fit the recognizable forms, an ERROR_MARK node
9555 is returned for the decl, and the other fields are left undefined.
9556
9557 Otherwise, the decl returned currently is either a VAR_DECL or a
9558 PARM_DECL.
9559
9560 The offset returned is always valid, but of course not necessarily
9561 a constant, and not necessarily converted into the appropriate
9562 type, leaving that up to the caller (so as to avoid that overhead
9563 if the decls being looked at are different anyway).
9564
9565 If the size cannot be determined (e.g. an adjustable array),
9566 an ERROR_MARK node is returned for the size. Otherwise, the
9567 size returned is valid, not necessarily a constant, and not
9568 necessarily converted into the appropriate type as with the
9569 offset.
9570
9571 Note that the offset and size expressions are expressed in the
9572 base storage units (usually bits) rather than in the units of
9573 the type of the decl, because two decls with different types
9574 might overlap but with apparently non-overlapping array offsets,
9575 whereas converting the array offsets to consistant offsets will
9576 reveal the overlap. */
9577
9578 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9579 static void
9580 ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
9581 tree *size, tree t)
9582 {
9583 /* The default path is to report a nonexistant decl. */
9584 *decl = NULL_TREE;
9585
9586 if (t == NULL_TREE)
9587 return;
9588
9589 switch (TREE_CODE (t))
9590 {
9591 case ERROR_MARK:
9592 case IDENTIFIER_NODE:
9593 case INTEGER_CST:
9594 case REAL_CST:
9595 case COMPLEX_CST:
9596 case STRING_CST:
9597 case CONST_DECL:
9598 case PLUS_EXPR:
9599 case MINUS_EXPR:
9600 case MULT_EXPR:
9601 case TRUNC_DIV_EXPR:
9602 case CEIL_DIV_EXPR:
9603 case FLOOR_DIV_EXPR:
9604 case ROUND_DIV_EXPR:
9605 case TRUNC_MOD_EXPR:
9606 case CEIL_MOD_EXPR:
9607 case FLOOR_MOD_EXPR:
9608 case ROUND_MOD_EXPR:
9609 case RDIV_EXPR:
9610 case EXACT_DIV_EXPR:
9611 case FIX_TRUNC_EXPR:
9612 case FIX_CEIL_EXPR:
9613 case FIX_FLOOR_EXPR:
9614 case FIX_ROUND_EXPR:
9615 case FLOAT_EXPR:
9616 case EXPON_EXPR:
9617 case NEGATE_EXPR:
9618 case MIN_EXPR:
9619 case MAX_EXPR:
9620 case ABS_EXPR:
9621 case FFS_EXPR:
9622 case LSHIFT_EXPR:
9623 case RSHIFT_EXPR:
9624 case LROTATE_EXPR:
9625 case RROTATE_EXPR:
9626 case BIT_IOR_EXPR:
9627 case BIT_XOR_EXPR:
9628 case BIT_AND_EXPR:
9629 case BIT_ANDTC_EXPR:
9630 case BIT_NOT_EXPR:
9631 case TRUTH_ANDIF_EXPR:
9632 case TRUTH_ORIF_EXPR:
9633 case TRUTH_AND_EXPR:
9634 case TRUTH_OR_EXPR:
9635 case TRUTH_XOR_EXPR:
9636 case TRUTH_NOT_EXPR:
9637 case LT_EXPR:
9638 case LE_EXPR:
9639 case GT_EXPR:
9640 case GE_EXPR:
9641 case EQ_EXPR:
9642 case NE_EXPR:
9643 case COMPLEX_EXPR:
9644 case CONJ_EXPR:
9645 case REALPART_EXPR:
9646 case IMAGPART_EXPR:
9647 case LABEL_EXPR:
9648 case COMPONENT_REF:
9649 case COMPOUND_EXPR:
9650 case ADDR_EXPR:
9651 return;
9652
9653 case VAR_DECL:
9654 case PARM_DECL:
9655 *decl = t;
9656 *offset = bitsize_int (0L, 0L);
9657 *size = TYPE_SIZE (TREE_TYPE (t));
9658 return;
9659
9660 case ARRAY_REF:
9661 {
9662 tree array = TREE_OPERAND (t, 0);
9663 tree element = TREE_OPERAND (t, 1);
9664 tree init_offset;
9665
9666 if ((array == NULL_TREE)
9667 || (element == NULL_TREE))
9668 {
9669 *decl = error_mark_node;
9670 return;
9671 }
9672
9673 ffecom_tree_canonize_ref_ (decl, &init_offset, size,
9674 array);
9675 if ((*decl == NULL_TREE)
9676 || (*decl == error_mark_node))
9677 return;
9678
9679 *offset = size_binop (MULT_EXPR,
9680 TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))),
9681 size_binop (MINUS_EXPR,
9682 element,
9683 TYPE_MIN_VALUE
9684 (TYPE_DOMAIN
9685 (TREE_TYPE (array)))));
9686
9687 *offset = size_binop (PLUS_EXPR,
9688 init_offset,
9689 *offset);
9690
9691 *size = TYPE_SIZE (TREE_TYPE (t));
9692 return;
9693 }
9694
9695 case INDIRECT_REF:
9696
9697 /* Most of this code is to handle references to COMMON. And so
9698 far that is useful only for calling library functions, since
9699 external (user) functions might reference common areas. But
9700 even calling an external function, it's worthwhile to decode
9701 COMMON references because if not storing into COMMON, we don't
9702 want COMMON-based arguments to gratuitously force use of a
9703 temporary. */
9704
9705 *size = TYPE_SIZE (TREE_TYPE (t));
9706
9707 ffecom_tree_canonize_ptr_ (decl, offset,
9708 TREE_OPERAND (t, 0));
9709
9710 return;
9711
9712 case CONVERT_EXPR:
9713 case NOP_EXPR:
9714 case MODIFY_EXPR:
9715 case NON_LVALUE_EXPR:
9716 case RESULT_DECL:
9717 case FIELD_DECL:
9718 case COND_EXPR: /* More cases than we can handle. */
9719 case SAVE_EXPR:
9720 case REFERENCE_EXPR:
9721 case PREDECREMENT_EXPR:
9722 case PREINCREMENT_EXPR:
9723 case POSTDECREMENT_EXPR:
9724 case POSTINCREMENT_EXPR:
9725 case CALL_EXPR:
9726 default:
9727 *decl = error_mark_node;
9728 return;
9729 }
9730 }
9731 #endif
9732
9733 /* Do divide operation appropriate to type of operands. */
9734
9735 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9736 static tree
9737 ffecom_tree_divide_ (tree tree_type, tree left, tree right,
9738 tree dest_tree, ffebld dest, bool *dest_used)
9739 {
9740 if ((left == error_mark_node)
9741 || (right == error_mark_node))
9742 return error_mark_node;
9743
9744 switch (TREE_CODE (tree_type))
9745 {
9746 case INTEGER_TYPE:
9747 return ffecom_2 (TRUNC_DIV_EXPR, tree_type,
9748 left,
9749 right);
9750
9751 case COMPLEX_TYPE:
9752 {
9753 ffecomGfrt ix;
9754
9755 if (TREE_TYPE (tree_type)
9756 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9757 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9758 else
9759 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
9760
9761 left = ffecom_1 (ADDR_EXPR,
9762 build_pointer_type (TREE_TYPE (left)),
9763 left);
9764 left = build_tree_list (NULL_TREE, left);
9765 right = ffecom_1 (ADDR_EXPR,
9766 build_pointer_type (TREE_TYPE (right)),
9767 right);
9768 right = build_tree_list (NULL_TREE, right);
9769 TREE_CHAIN (left) = right;
9770
9771 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9772 ffecom_gfrt_kindtype (ix),
9773 ffe_is_f2c_library (),
9774 tree_type,
9775 left,
9776 dest_tree, dest, dest_used,
9777 NULL_TREE, TRUE);
9778 }
9779 break;
9780
9781 case RECORD_TYPE:
9782 {
9783 ffecomGfrt ix;
9784
9785 if (TREE_TYPE (TYPE_FIELDS (tree_type))
9786 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9787 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9788 else
9789 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
9790
9791 left = ffecom_1 (ADDR_EXPR,
9792 build_pointer_type (TREE_TYPE (left)),
9793 left);
9794 left = build_tree_list (NULL_TREE, left);
9795 right = ffecom_1 (ADDR_EXPR,
9796 build_pointer_type (TREE_TYPE (right)),
9797 right);
9798 right = build_tree_list (NULL_TREE, right);
9799 TREE_CHAIN (left) = right;
9800
9801 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9802 ffecom_gfrt_kindtype (ix),
9803 ffe_is_f2c_library (),
9804 tree_type,
9805 left,
9806 dest_tree, dest, dest_used,
9807 NULL_TREE, TRUE);
9808 }
9809 break;
9810
9811 default:
9812 return ffecom_2 (RDIV_EXPR, tree_type,
9813 left,
9814 right);
9815 }
9816 }
9817
9818 #endif
9819 /* ffecom_type_localvar_ -- Build type info for non-dummy variable
9820
9821 tree type;
9822 ffesymbol s; // the variable's symbol
9823 ffeinfoBasictype bt; // it's basictype
9824 ffeinfoKindtype kt; // it's kindtype
9825
9826 type = ffecom_type_localvar_(s,bt,kt);
9827
9828 Handles static arrays, CHARACTER type, etc. */
9829
9830 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9831 static tree
9832 ffecom_type_localvar_ (ffesymbol s, ffeinfoBasictype bt,
9833 ffeinfoKindtype kt)
9834 {
9835 tree type;
9836 ffebld dl;
9837 ffebld dim;
9838 tree lowt;
9839 tree hight;
9840
9841 type = ffecom_tree_type[bt][kt];
9842 if (bt == FFEINFO_basictypeCHARACTER)
9843 {
9844 hight = build_int_2 (ffesymbol_size (s), 0);
9845 TREE_TYPE (hight) = ffecom_f2c_ftnlen_type_node;
9846
9847 type
9848 = build_array_type
9849 (type,
9850 build_range_type (ffecom_f2c_ftnlen_type_node,
9851 ffecom_f2c_ftnlen_one_node,
9852 hight));
9853 type = ffecom_check_size_overflow_ (s, type, FALSE);
9854 }
9855
9856 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
9857 {
9858 if (type == error_mark_node)
9859 break;
9860
9861 dim = ffebld_head (dl);
9862 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
9863
9864 if (ffebld_left (dim) == NULL)
9865 lowt = integer_one_node;
9866 else
9867 lowt = ffecom_expr (ffebld_left (dim));
9868
9869 if (TREE_CODE (lowt) != INTEGER_CST)
9870 lowt = variable_size (lowt);
9871
9872 assert (ffebld_right (dim) != NULL);
9873 hight = ffecom_expr (ffebld_right (dim));
9874
9875 if (TREE_CODE (hight) != INTEGER_CST)
9876 hight = variable_size (hight);
9877
9878 type = build_array_type (type,
9879 build_range_type (ffecom_integer_type_node,
9880 lowt, hight));
9881 type = ffecom_check_size_overflow_ (s, type, FALSE);
9882 }
9883
9884 return type;
9885 }
9886
9887 #endif
9888 /* Build Namelist type. */
9889
9890 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9891 static tree
9892 ffecom_type_namelist_ ()
9893 {
9894 static tree type = NULL_TREE;
9895
9896 if (type == NULL_TREE)
9897 {
9898 static tree namefield, varsfield, nvarsfield;
9899 tree vardesctype;
9900
9901 vardesctype = ffecom_type_vardesc_ ();
9902
9903 push_obstacks_nochange ();
9904 end_temporary_allocation ();
9905
9906 type = make_node (RECORD_TYPE);
9907
9908 vardesctype = build_pointer_type (build_pointer_type (vardesctype));
9909
9910 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9911 string_type_node);
9912 varsfield = ffecom_decl_field (type, namefield, "vars", vardesctype);
9913 nvarsfield = ffecom_decl_field (type, varsfield, "nvars",
9914 integer_type_node);
9915
9916 TYPE_FIELDS (type) = namefield;
9917 layout_type (type);
9918
9919 resume_temporary_allocation ();
9920 pop_obstacks ();
9921 }
9922
9923 return type;
9924 }
9925
9926 #endif
9927
9928 /* Make a copy of a type, assuming caller has switched to the permanent
9929 obstacks and that the type is for an aggregate (array) initializer. */
9930
9931 #if FFECOM_targetCURRENT == FFECOM_targetGCC && 0 /* Not used now. */
9932 static tree
9933 ffecom_type_permanent_copy_ (tree t)
9934 {
9935 tree domain;
9936 tree max;
9937
9938 assert (TREE_TYPE (t) != NULL_TREE);
9939
9940 domain = TYPE_DOMAIN (t);
9941
9942 assert (TREE_CODE (t) == ARRAY_TYPE);
9943 assert (TREE_PERMANENT (TREE_TYPE (t)));
9944 assert (TREE_PERMANENT (TREE_TYPE (domain)));
9945 assert (TREE_PERMANENT (TYPE_MIN_VALUE (domain)));
9946
9947 max = TYPE_MAX_VALUE (domain);
9948 if (!TREE_PERMANENT (max))
9949 {
9950 assert (TREE_CODE (max) == INTEGER_CST);
9951
9952 max = build_int_2 (TREE_INT_CST_LOW (max), TREE_INT_CST_HIGH (max));
9953 TREE_TYPE (max) = TREE_TYPE (TYPE_MIN_VALUE (domain));
9954 }
9955
9956 return build_array_type (TREE_TYPE (t),
9957 build_range_type (TREE_TYPE (domain),
9958 TYPE_MIN_VALUE (domain),
9959 max));
9960 }
9961 #endif
9962
9963 /* Build Vardesc type. */
9964
9965 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9966 static tree
9967 ffecom_type_vardesc_ ()
9968 {
9969 static tree type = NULL_TREE;
9970 static tree namefield, addrfield, dimsfield, typefield;
9971
9972 if (type == NULL_TREE)
9973 {
9974 push_obstacks_nochange ();
9975 end_temporary_allocation ();
9976
9977 type = make_node (RECORD_TYPE);
9978
9979 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9980 string_type_node);
9981 addrfield = ffecom_decl_field (type, namefield, "addr",
9982 string_type_node);
9983 dimsfield = ffecom_decl_field (type, addrfield, "dims",
9984 ffecom_f2c_ptr_to_ftnlen_type_node);
9985 typefield = ffecom_decl_field (type, dimsfield, "type",
9986 integer_type_node);
9987
9988 TYPE_FIELDS (type) = namefield;
9989 layout_type (type);
9990
9991 resume_temporary_allocation ();
9992 pop_obstacks ();
9993 }
9994
9995 return type;
9996 }
9997
9998 #endif
9999
10000 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10001 static tree
10002 ffecom_vardesc_ (ffebld expr)
10003 {
10004 ffesymbol s;
10005
10006 assert (ffebld_op (expr) == FFEBLD_opSYMTER);
10007 s = ffebld_symter (expr);
10008
10009 if (ffesymbol_hook (s).vardesc_tree == NULL_TREE)
10010 {
10011 int i;
10012 tree vardesctype = ffecom_type_vardesc_ ();
10013 tree var;
10014 tree nameinit;
10015 tree dimsinit;
10016 tree addrinit;
10017 tree typeinit;
10018 tree field;
10019 tree varinits;
10020 int yes;
10021 static int mynumber = 0;
10022
10023 yes = suspend_momentary ();
10024
10025 var = build_decl (VAR_DECL,
10026 ffecom_get_invented_identifier ("__g77_vardesc_%d",
10027 NULL, mynumber++),
10028 vardesctype);
10029 TREE_STATIC (var) = 1;
10030 DECL_INITIAL (var) = error_mark_node;
10031
10032 var = start_decl (var, FALSE);
10033
10034 /* Process inits. */
10035
10036 nameinit = ffecom_build_f2c_string_ ((i = strlen (ffesymbol_text (s)))
10037 + 1,
10038 ffesymbol_text (s));
10039 TREE_TYPE (nameinit)
10040 = build_type_variant
10041 (build_array_type
10042 (char_type_node,
10043 build_range_type (integer_type_node,
10044 integer_one_node,
10045 build_int_2 (i, 0))),
10046 1, 0);
10047 TREE_CONSTANT (nameinit) = 1;
10048 TREE_STATIC (nameinit) = 1;
10049 nameinit = ffecom_1 (ADDR_EXPR,
10050 build_pointer_type (TREE_TYPE (nameinit)),
10051 nameinit);
10052
10053 addrinit = ffecom_arg_ptr_to_expr (expr, &typeinit);
10054
10055 dimsinit = ffecom_vardesc_dims_ (s);
10056
10057 if (typeinit == NULL_TREE)
10058 {
10059 ffeinfoBasictype bt = ffesymbol_basictype (s);
10060 ffeinfoKindtype kt = ffesymbol_kindtype (s);
10061 int tc = ffecom_f2c_typecode (bt, kt);
10062
10063 assert (tc != -1);
10064 typeinit = build_int_2 (tc, (tc < 0) ? -1 : 0);
10065 }
10066 else
10067 typeinit = ffecom_1 (NEGATE_EXPR, TREE_TYPE (typeinit), typeinit);
10068
10069 varinits = build_tree_list ((field = TYPE_FIELDS (vardesctype)),
10070 nameinit);
10071 TREE_CHAIN (varinits) = build_tree_list ((field = TREE_CHAIN (field)),
10072 addrinit);
10073 TREE_CHAIN (TREE_CHAIN (varinits))
10074 = build_tree_list ((field = TREE_CHAIN (field)), dimsinit);
10075 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (varinits)))
10076 = build_tree_list ((field = TREE_CHAIN (field)), typeinit);
10077
10078 varinits = build (CONSTRUCTOR, vardesctype, NULL_TREE, varinits);
10079 TREE_CONSTANT (varinits) = 1;
10080 TREE_STATIC (varinits) = 1;
10081
10082 finish_decl (var, varinits, FALSE);
10083
10084 var = ffecom_1 (ADDR_EXPR, build_pointer_type (vardesctype), var);
10085
10086 resume_momentary (yes);
10087
10088 ffesymbol_hook (s).vardesc_tree = var;
10089 }
10090
10091 return ffesymbol_hook (s).vardesc_tree;
10092 }
10093
10094 #endif
10095 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10096 static tree
10097 ffecom_vardesc_array_ (ffesymbol s)
10098 {
10099 ffebld b;
10100 tree list;
10101 tree item = NULL_TREE;
10102 tree var;
10103 int i;
10104 int yes;
10105 static int mynumber = 0;
10106
10107 for (i = 0, list = NULL_TREE, b = ffesymbol_namelist (s);
10108 b != NULL;
10109 b = ffebld_trail (b), ++i)
10110 {
10111 tree t;
10112
10113 t = ffecom_vardesc_ (ffebld_head (b));
10114
10115 if (list == NULL_TREE)
10116 list = item = build_tree_list (NULL_TREE, t);
10117 else
10118 {
10119 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
10120 item = TREE_CHAIN (item);
10121 }
10122 }
10123
10124 yes = suspend_momentary ();
10125
10126 item = build_array_type (build_pointer_type (ffecom_type_vardesc_ ()),
10127 build_range_type (integer_type_node,
10128 integer_one_node,
10129 build_int_2 (i, 0)));
10130 list = build (CONSTRUCTOR, item, NULL_TREE, list);
10131 TREE_CONSTANT (list) = 1;
10132 TREE_STATIC (list) = 1;
10133
10134 var = ffecom_get_invented_identifier ("__g77_vardesc_array_%d", NULL,
10135 mynumber++);
10136 var = build_decl (VAR_DECL, var, item);
10137 TREE_STATIC (var) = 1;
10138 DECL_INITIAL (var) = error_mark_node;
10139 var = start_decl (var, FALSE);
10140 finish_decl (var, list, FALSE);
10141
10142 resume_momentary (yes);
10143
10144 return var;
10145 }
10146
10147 #endif
10148 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10149 static tree
10150 ffecom_vardesc_dims_ (ffesymbol s)
10151 {
10152 if (ffesymbol_dims (s) == NULL)
10153 return convert (ffecom_f2c_ptr_to_ftnlen_type_node,
10154 integer_zero_node);
10155
10156 {
10157 ffebld b;
10158 ffebld e;
10159 tree list;
10160 tree backlist;
10161 tree item = NULL_TREE;
10162 tree var;
10163 int yes;
10164 tree numdim;
10165 tree numelem;
10166 tree baseoff = NULL_TREE;
10167 static int mynumber = 0;
10168
10169 numdim = build_int_2 ((int) ffesymbol_rank (s), 0);
10170 TREE_TYPE (numdim) = ffecom_f2c_ftnlen_type_node;
10171
10172 numelem = ffecom_expr (ffesymbol_arraysize (s));
10173 TREE_TYPE (numelem) = ffecom_f2c_ftnlen_type_node;
10174
10175 list = NULL_TREE;
10176 backlist = NULL_TREE;
10177 for (b = ffesymbol_dims (s), e = ffesymbol_extents (s);
10178 b != NULL;
10179 b = ffebld_trail (b), e = ffebld_trail (e))
10180 {
10181 tree t;
10182 tree low;
10183 tree back;
10184
10185 if (ffebld_trail (b) == NULL)
10186 t = NULL_TREE;
10187 else
10188 {
10189 t = convert (ffecom_f2c_ftnlen_type_node,
10190 ffecom_expr (ffebld_head (e)));
10191
10192 if (list == NULL_TREE)
10193 list = item = build_tree_list (NULL_TREE, t);
10194 else
10195 {
10196 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
10197 item = TREE_CHAIN (item);
10198 }
10199 }
10200
10201 if (ffebld_left (ffebld_head (b)) == NULL)
10202 low = ffecom_integer_one_node;
10203 else
10204 low = ffecom_expr (ffebld_left (ffebld_head (b)));
10205 low = convert (ffecom_f2c_ftnlen_type_node, low);
10206
10207 back = build_tree_list (low, t);
10208 TREE_CHAIN (back) = backlist;
10209 backlist = back;
10210 }
10211
10212 for (item = backlist; item != NULL_TREE; item = TREE_CHAIN (item))
10213 {
10214 if (TREE_VALUE (item) == NULL_TREE)
10215 baseoff = TREE_PURPOSE (item);
10216 else
10217 baseoff = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
10218 TREE_PURPOSE (item),
10219 ffecom_2 (MULT_EXPR,
10220 ffecom_f2c_ftnlen_type_node,
10221 TREE_VALUE (item),
10222 baseoff));
10223 }
10224
10225 /* backlist now dead, along with all TREE_PURPOSEs on it. */
10226
10227 baseoff = build_tree_list (NULL_TREE, baseoff);
10228 TREE_CHAIN (baseoff) = list;
10229
10230 numelem = build_tree_list (NULL_TREE, numelem);
10231 TREE_CHAIN (numelem) = baseoff;
10232
10233 numdim = build_tree_list (NULL_TREE, numdim);
10234 TREE_CHAIN (numdim) = numelem;
10235
10236 yes = suspend_momentary ();
10237
10238 item = build_array_type (ffecom_f2c_ftnlen_type_node,
10239 build_range_type (integer_type_node,
10240 integer_zero_node,
10241 build_int_2
10242 ((int) ffesymbol_rank (s)
10243 + 2, 0)));
10244 list = build (CONSTRUCTOR, item, NULL_TREE, numdim);
10245 TREE_CONSTANT (list) = 1;
10246 TREE_STATIC (list) = 1;
10247
10248 var = ffecom_get_invented_identifier ("__g77_dims_%d", NULL,
10249 mynumber++);
10250 var = build_decl (VAR_DECL, var, item);
10251 TREE_STATIC (var) = 1;
10252 DECL_INITIAL (var) = error_mark_node;
10253 var = start_decl (var, FALSE);
10254 finish_decl (var, list, FALSE);
10255
10256 var = ffecom_1 (ADDR_EXPR, build_pointer_type (item), var);
10257
10258 resume_momentary (yes);
10259
10260 return var;
10261 }
10262 }
10263
10264 #endif
10265 /* Essentially does a "fold (build1 (code, type, node))" while checking
10266 for certain housekeeping things.
10267
10268 NOTE: for building an ADDR_EXPR around a FUNCTION_DECL, use
10269 ffecom_1_fn instead. */
10270
10271 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10272 tree
10273 ffecom_1 (enum tree_code code, tree type, tree node)
10274 {
10275 tree item;
10276
10277 if ((node == error_mark_node)
10278 || (type == error_mark_node))
10279 return error_mark_node;
10280
10281 if (code == ADDR_EXPR)
10282 {
10283 if (!mark_addressable (node))
10284 assert ("can't mark_addressable this node!" == NULL);
10285 }
10286
10287 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
10288 {
10289 tree realtype;
10290
10291 case REALPART_EXPR:
10292 item = build (COMPONENT_REF, type, node, TYPE_FIELDS (TREE_TYPE (node)));
10293 break;
10294
10295 case IMAGPART_EXPR:
10296 item = build (COMPONENT_REF, type, node, TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (node))));
10297 break;
10298
10299
10300 case NEGATE_EXPR:
10301 if (TREE_CODE (type) != RECORD_TYPE)
10302 {
10303 item = build1 (code, type, node);
10304 break;
10305 }
10306 node = ffecom_stabilize_aggregate_ (node);
10307 realtype = TREE_TYPE (TYPE_FIELDS (type));
10308 item =
10309 ffecom_2 (COMPLEX_EXPR, type,
10310 ffecom_1 (NEGATE_EXPR, realtype,
10311 ffecom_1 (REALPART_EXPR, realtype,
10312 node)),
10313 ffecom_1 (NEGATE_EXPR, realtype,
10314 ffecom_1 (IMAGPART_EXPR, realtype,
10315 node)));
10316 break;
10317
10318 default:
10319 item = build1 (code, type, node);
10320 break;
10321 }
10322
10323 if (TREE_SIDE_EFFECTS (node))
10324 TREE_SIDE_EFFECTS (item) = 1;
10325 if ((code == ADDR_EXPR) && staticp (node))
10326 TREE_CONSTANT (item) = 1;
10327 return fold (item);
10328 }
10329 #endif
10330
10331 /* Like ffecom_1 (ADDR_EXPR, TREE_TYPE (node), node), except
10332 handles TREE_CODE (node) == FUNCTION_DECL. In particular,
10333 does not set TREE_ADDRESSABLE (because calling an inline
10334 function does not mean the function needs to be separately
10335 compiled). */
10336
10337 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10338 tree
10339 ffecom_1_fn (tree node)
10340 {
10341 tree item;
10342 tree type;
10343
10344 if (node == error_mark_node)
10345 return error_mark_node;
10346
10347 type = build_type_variant (TREE_TYPE (node),
10348 TREE_READONLY (node),
10349 TREE_THIS_VOLATILE (node));
10350 item = build1 (ADDR_EXPR,
10351 build_pointer_type (type), node);
10352 if (TREE_SIDE_EFFECTS (node))
10353 TREE_SIDE_EFFECTS (item) = 1;
10354 if (staticp (node))
10355 TREE_CONSTANT (item) = 1;
10356 return fold (item);
10357 }
10358 #endif
10359
10360 /* Essentially does a "fold (build (code, type, node1, node2))" while
10361 checking for certain housekeeping things. */
10362
10363 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10364 tree
10365 ffecom_2 (enum tree_code code, tree type, tree node1,
10366 tree node2)
10367 {
10368 tree item;
10369
10370 if ((node1 == error_mark_node)
10371 || (node2 == error_mark_node)
10372 || (type == error_mark_node))
10373 return error_mark_node;
10374
10375 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
10376 {
10377 tree a, b, c, d, realtype;
10378
10379 case CONJ_EXPR:
10380 assert ("no CONJ_EXPR support yet" == NULL);
10381 return error_mark_node;
10382
10383 case COMPLEX_EXPR:
10384 item = build_tree_list (TYPE_FIELDS (type), node1);
10385 TREE_CHAIN (item) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), node2);
10386 item = build (CONSTRUCTOR, type, NULL_TREE, item);
10387 break;
10388
10389 case PLUS_EXPR:
10390 if (TREE_CODE (type) != RECORD_TYPE)
10391 {
10392 item = build (code, type, node1, node2);
10393 break;
10394 }
10395 node1 = ffecom_stabilize_aggregate_ (node1);
10396 node2 = ffecom_stabilize_aggregate_ (node2);
10397 realtype = TREE_TYPE (TYPE_FIELDS (type));
10398 item =
10399 ffecom_2 (COMPLEX_EXPR, type,
10400 ffecom_2 (PLUS_EXPR, realtype,
10401 ffecom_1 (REALPART_EXPR, realtype,
10402 node1),
10403 ffecom_1 (REALPART_EXPR, realtype,
10404 node2)),
10405 ffecom_2 (PLUS_EXPR, realtype,
10406 ffecom_1 (IMAGPART_EXPR, realtype,
10407 node1),
10408 ffecom_1 (IMAGPART_EXPR, realtype,
10409 node2)));
10410 break;
10411
10412 case MINUS_EXPR:
10413 if (TREE_CODE (type) != RECORD_TYPE)
10414 {
10415 item = build (code, type, node1, node2);
10416 break;
10417 }
10418 node1 = ffecom_stabilize_aggregate_ (node1);
10419 node2 = ffecom_stabilize_aggregate_ (node2);
10420 realtype = TREE_TYPE (TYPE_FIELDS (type));
10421 item =
10422 ffecom_2 (COMPLEX_EXPR, type,
10423 ffecom_2 (MINUS_EXPR, realtype,
10424 ffecom_1 (REALPART_EXPR, realtype,
10425 node1),
10426 ffecom_1 (REALPART_EXPR, realtype,
10427 node2)),
10428 ffecom_2 (MINUS_EXPR, realtype,
10429 ffecom_1 (IMAGPART_EXPR, realtype,
10430 node1),
10431 ffecom_1 (IMAGPART_EXPR, realtype,
10432 node2)));
10433 break;
10434
10435 case MULT_EXPR:
10436 if (TREE_CODE (type) != RECORD_TYPE)
10437 {
10438 item = build (code, type, node1, node2);
10439 break;
10440 }
10441 node1 = ffecom_stabilize_aggregate_ (node1);
10442 node2 = ffecom_stabilize_aggregate_ (node2);
10443 realtype = TREE_TYPE (TYPE_FIELDS (type));
10444 a = save_expr (ffecom_1 (REALPART_EXPR, realtype,
10445 node1));
10446 b = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
10447 node1));
10448 c = save_expr (ffecom_1 (REALPART_EXPR, realtype,
10449 node2));
10450 d = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
10451 node2));
10452 item =
10453 ffecom_2 (COMPLEX_EXPR, type,
10454 ffecom_2 (MINUS_EXPR, realtype,
10455 ffecom_2 (MULT_EXPR, realtype,
10456 a,
10457 c),
10458 ffecom_2 (MULT_EXPR, realtype,
10459 b,
10460 d)),
10461 ffecom_2 (PLUS_EXPR, realtype,
10462 ffecom_2 (MULT_EXPR, realtype,
10463 a,
10464 d),
10465 ffecom_2 (MULT_EXPR, realtype,
10466 c,
10467 b)));
10468 break;
10469
10470 case EQ_EXPR:
10471 if ((TREE_CODE (node1) != RECORD_TYPE)
10472 && (TREE_CODE (node2) != RECORD_TYPE))
10473 {
10474 item = build (code, type, node1, node2);
10475 break;
10476 }
10477 assert (TREE_CODE (node1) == RECORD_TYPE);
10478 assert (TREE_CODE (node2) == RECORD_TYPE);
10479 node1 = ffecom_stabilize_aggregate_ (node1);
10480 node2 = ffecom_stabilize_aggregate_ (node2);
10481 realtype = TREE_TYPE (TYPE_FIELDS (type));
10482 item =
10483 ffecom_2 (TRUTH_ANDIF_EXPR, type,
10484 ffecom_2 (code, type,
10485 ffecom_1 (REALPART_EXPR, realtype,
10486 node1),
10487 ffecom_1 (REALPART_EXPR, realtype,
10488 node2)),
10489 ffecom_2 (code, type,
10490 ffecom_1 (IMAGPART_EXPR, realtype,
10491 node1),
10492 ffecom_1 (IMAGPART_EXPR, realtype,
10493 node2)));
10494 break;
10495
10496 case NE_EXPR:
10497 if ((TREE_CODE (node1) != RECORD_TYPE)
10498 && (TREE_CODE (node2) != RECORD_TYPE))
10499 {
10500 item = build (code, type, node1, node2);
10501 break;
10502 }
10503 assert (TREE_CODE (node1) == RECORD_TYPE);
10504 assert (TREE_CODE (node2) == RECORD_TYPE);
10505 node1 = ffecom_stabilize_aggregate_ (node1);
10506 node2 = ffecom_stabilize_aggregate_ (node2);
10507 realtype = TREE_TYPE (TYPE_FIELDS (type));
10508 item =
10509 ffecom_2 (TRUTH_ORIF_EXPR, type,
10510 ffecom_2 (code, type,
10511 ffecom_1 (REALPART_EXPR, realtype,
10512 node1),
10513 ffecom_1 (REALPART_EXPR, realtype,
10514 node2)),
10515 ffecom_2 (code, type,
10516 ffecom_1 (IMAGPART_EXPR, realtype,
10517 node1),
10518 ffecom_1 (IMAGPART_EXPR, realtype,
10519 node2)));
10520 break;
10521
10522 default:
10523 item = build (code, type, node1, node2);
10524 break;
10525 }
10526
10527 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2))
10528 TREE_SIDE_EFFECTS (item) = 1;
10529 return fold (item);
10530 }
10531
10532 #endif
10533 /* ffecom_2pass_advise_entrypoint -- Advise that there's this entrypoint
10534
10535 ffesymbol s; // the ENTRY point itself
10536 if (ffecom_2pass_advise_entrypoint(s))
10537 // the ENTRY point has been accepted
10538
10539 Does whatever compiler needs to do when it learns about the entrypoint,
10540 like determine the return type of the master function, count the
10541 number of entrypoints, etc. Returns FALSE if the return type is
10542 not compatible with the return type(s) of other entrypoint(s).
10543
10544 NOTE: for every call to this fn that returns TRUE, _do_entrypoint must
10545 later (after _finish_progunit) be called with the same entrypoint(s)
10546 as passed to this fn for which TRUE was returned.
10547
10548 03-Jan-92 JCB 2.0
10549 Return FALSE if the return type conflicts with previous entrypoints. */
10550
10551 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10552 bool
10553 ffecom_2pass_advise_entrypoint (ffesymbol entry)
10554 {
10555 ffebld list; /* opITEM. */
10556 ffebld mlist; /* opITEM. */
10557 ffebld plist; /* opITEM. */
10558 ffebld arg; /* ffebld_head(opITEM). */
10559 ffebld item; /* opITEM. */
10560 ffesymbol s; /* ffebld_symter(arg). */
10561 ffeinfoBasictype bt = ffesymbol_basictype (entry);
10562 ffeinfoKindtype kt = ffesymbol_kindtype (entry);
10563 ffetargetCharacterSize size = ffesymbol_size (entry);
10564 bool ok;
10565
10566 if (ffecom_num_entrypoints_ == 0)
10567 { /* First entrypoint, make list of main
10568 arglist's dummies. */
10569 assert (ffecom_primary_entry_ != NULL);
10570
10571 ffecom_master_bt_ = ffesymbol_basictype (ffecom_primary_entry_);
10572 ffecom_master_kt_ = ffesymbol_kindtype (ffecom_primary_entry_);
10573 ffecom_master_size_ = ffesymbol_size (ffecom_primary_entry_);
10574
10575 for (plist = NULL, list = ffesymbol_dummyargs (ffecom_primary_entry_);
10576 list != NULL;
10577 list = ffebld_trail (list))
10578 {
10579 arg = ffebld_head (list);
10580 if (ffebld_op (arg) != FFEBLD_opSYMTER)
10581 continue; /* Alternate return or some such thing. */
10582 item = ffebld_new_item (arg, NULL);
10583 if (plist == NULL)
10584 ffecom_master_arglist_ = item;
10585 else
10586 ffebld_set_trail (plist, item);
10587 plist = item;
10588 }
10589 }
10590
10591 /* If necessary, scan entry arglist for alternate returns. Do this scan
10592 apparently redundantly (it's done below to UNIONize the arglists) so
10593 that we don't complain about RETURN 1 if an offending ENTRY is the only
10594 one with an alternate return. */
10595
10596 if (!ffecom_is_altreturning_)
10597 {
10598 for (list = ffesymbol_dummyargs (entry);
10599 list != NULL;
10600 list = ffebld_trail (list))
10601 {
10602 arg = ffebld_head (list);
10603 if (ffebld_op (arg) == FFEBLD_opSTAR)
10604 {
10605 ffecom_is_altreturning_ = TRUE;
10606 break;
10607 }
10608 }
10609 }
10610
10611 /* Now check type compatibility. */
10612
10613 switch (ffecom_master_bt_)
10614 {
10615 case FFEINFO_basictypeNONE:
10616 ok = (bt != FFEINFO_basictypeCHARACTER);
10617 break;
10618
10619 case FFEINFO_basictypeCHARACTER:
10620 ok
10621 = (bt == FFEINFO_basictypeCHARACTER)
10622 && (kt == ffecom_master_kt_)
10623 && (size == ffecom_master_size_);
10624 break;
10625
10626 case FFEINFO_basictypeANY:
10627 return FALSE; /* Just don't bother. */
10628
10629 default:
10630 if (bt == FFEINFO_basictypeCHARACTER)
10631 {
10632 ok = FALSE;
10633 break;
10634 }
10635 ok = TRUE;
10636 if ((bt != ffecom_master_bt_) || (kt != ffecom_master_kt_))
10637 {
10638 ffecom_master_bt_ = FFEINFO_basictypeNONE;
10639 ffecom_master_kt_ = FFEINFO_kindtypeNONE;
10640 }
10641 break;
10642 }
10643
10644 if (!ok)
10645 {
10646 ffebad_start (FFEBAD_ENTRY_CONFLICTS);
10647 ffest_ffebad_here_current_stmt (0);
10648 ffebad_finish ();
10649 return FALSE; /* Can't handle entrypoint. */
10650 }
10651
10652 /* Entrypoint type compatible with previous types. */
10653
10654 ++ffecom_num_entrypoints_;
10655
10656 /* Master-arg-list = UNION(Master-arg-list,entry-arg-list). */
10657
10658 for (list = ffesymbol_dummyargs (entry);
10659 list != NULL;
10660 list = ffebld_trail (list))
10661 {
10662 arg = ffebld_head (list);
10663 if (ffebld_op (arg) != FFEBLD_opSYMTER)
10664 continue; /* Alternate return or some such thing. */
10665 s = ffebld_symter (arg);
10666 for (plist = NULL, mlist = ffecom_master_arglist_;
10667 mlist != NULL;
10668 plist = mlist, mlist = ffebld_trail (mlist))
10669 { /* plist points to previous item for easy
10670 appending of arg. */
10671 if (ffebld_symter (ffebld_head (mlist)) == s)
10672 break; /* Already have this arg in the master list. */
10673 }
10674 if (mlist != NULL)
10675 continue; /* Already have this arg in the master list. */
10676
10677 /* Append this arg to the master list. */
10678
10679 item = ffebld_new_item (arg, NULL);
10680 if (plist == NULL)
10681 ffecom_master_arglist_ = item;
10682 else
10683 ffebld_set_trail (plist, item);
10684 }
10685
10686 return TRUE;
10687 }
10688
10689 #endif
10690 /* ffecom_2pass_do_entrypoint -- Do compilation of entrypoint
10691
10692 ffesymbol s; // the ENTRY point itself
10693 ffecom_2pass_do_entrypoint(s);
10694
10695 Does whatever compiler needs to do to make the entrypoint actually
10696 happen. Must be called for each entrypoint after
10697 ffecom_finish_progunit is called. */
10698
10699 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10700 void
10701 ffecom_2pass_do_entrypoint (ffesymbol entry)
10702 {
10703 static int mfn_num = 0;
10704 static int ent_num;
10705
10706 if (mfn_num != ffecom_num_fns_)
10707 { /* First entrypoint for this program unit. */
10708 ent_num = 1;
10709 mfn_num = ffecom_num_fns_;
10710 ffecom_do_entry_ (ffecom_primary_entry_, 0);
10711 }
10712 else
10713 ++ent_num;
10714
10715 --ffecom_num_entrypoints_;
10716
10717 ffecom_do_entry_ (entry, ent_num);
10718 }
10719
10720 #endif
10721
10722 /* Essentially does a "fold (build (code, type, node1, node2))" while
10723 checking for certain housekeeping things. Always sets
10724 TREE_SIDE_EFFECTS. */
10725
10726 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10727 tree
10728 ffecom_2s (enum tree_code code, tree type, tree node1,
10729 tree node2)
10730 {
10731 tree item;
10732
10733 if ((node1 == error_mark_node)
10734 || (node2 == error_mark_node)
10735 || (type == error_mark_node))
10736 return error_mark_node;
10737
10738 item = build (code, type, node1, node2);
10739 TREE_SIDE_EFFECTS (item) = 1;
10740 return fold (item);
10741 }
10742
10743 #endif
10744 /* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10745 checking for certain housekeeping things. */
10746
10747 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10748 tree
10749 ffecom_3 (enum tree_code code, tree type, tree node1,
10750 tree node2, tree node3)
10751 {
10752 tree item;
10753
10754 if ((node1 == error_mark_node)
10755 || (node2 == error_mark_node)
10756 || (node3 == error_mark_node)
10757 || (type == error_mark_node))
10758 return error_mark_node;
10759
10760 item = build (code, type, node1, node2, node3);
10761 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2)
10762 || (node3 != NULL_TREE && TREE_SIDE_EFFECTS (node3)))
10763 TREE_SIDE_EFFECTS (item) = 1;
10764 return fold (item);
10765 }
10766
10767 #endif
10768 /* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10769 checking for certain housekeeping things. Always sets
10770 TREE_SIDE_EFFECTS. */
10771
10772 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10773 tree
10774 ffecom_3s (enum tree_code code, tree type, tree node1,
10775 tree node2, tree node3)
10776 {
10777 tree item;
10778
10779 if ((node1 == error_mark_node)
10780 || (node2 == error_mark_node)
10781 || (node3 == error_mark_node)
10782 || (type == error_mark_node))
10783 return error_mark_node;
10784
10785 item = build (code, type, node1, node2, node3);
10786 TREE_SIDE_EFFECTS (item) = 1;
10787 return fold (item);
10788 }
10789
10790 #endif
10791 /* ffecom_arg_expr -- Transform argument expr into gcc tree
10792
10793 See use by ffecom_list_expr.
10794
10795 If expression is NULL, returns an integer zero tree. If it is not
10796 a CHARACTER expression, returns whatever ffecom_expr
10797 returns and sets the length return value to NULL_TREE. Otherwise
10798 generates code to evaluate the character expression, returns the proper
10799 pointer to the result, but does NOT set the length return value to a tree
10800 that specifies the length of the result. (In other words, the length
10801 variable is always set to NULL_TREE, because a length is never passed.)
10802
10803 21-Dec-91 JCB 1.1
10804 Don't set returned length, since nobody needs it (yet; someday if
10805 we allow CHARACTER*(*) dummies to statement functions, we'll need
10806 it). */
10807
10808 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10809 tree
10810 ffecom_arg_expr (ffebld expr, tree *length)
10811 {
10812 tree ign;
10813
10814 *length = NULL_TREE;
10815
10816 if (expr == NULL)
10817 return integer_zero_node;
10818
10819 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10820 return ffecom_expr (expr);
10821
10822 return ffecom_arg_ptr_to_expr (expr, &ign);
10823 }
10824
10825 #endif
10826 /* ffecom_arg_ptr_to_expr -- Transform argument expr into gcc tree
10827
10828 See use by ffecom_list_ptr_to_expr.
10829
10830 If expression is NULL, returns an integer zero tree. If it is not
10831 a CHARACTER expression, returns whatever ffecom_ptr_to_expr
10832 returns and sets the length return value to NULL_TREE. Otherwise
10833 generates code to evaluate the character expression, returns the proper
10834 pointer to the result, AND sets the length return value to a tree that
10835 specifies the length of the result.
10836
10837 If the length argument is NULL, this is a slightly special
10838 case of building a FORMAT expression, that is, an expression that
10839 will be used at run time without regard to length. For the current
10840 implementation, which uses the libf2c library, this means it is nice
10841 to append a null byte to the end of the expression, where feasible,
10842 to make sure any diagnostic about the FORMAT string terminates at
10843 some useful point.
10844
10845 For now, treat %REF(char-expr) as the same as char-expr with a NULL
10846 length argument. This might even be seen as a feature, if a null
10847 byte can always be appended. */
10848
10849 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10850 tree
10851 ffecom_arg_ptr_to_expr (ffebld expr, tree *length)
10852 {
10853 tree item;
10854 tree ign_length;
10855 ffecomConcatList_ catlist;
10856
10857 if (length != NULL)
10858 *length = NULL_TREE;
10859
10860 if (expr == NULL)
10861 return integer_zero_node;
10862
10863 switch (ffebld_op (expr))
10864 {
10865 case FFEBLD_opPERCENT_VAL:
10866 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10867 return ffecom_expr (ffebld_left (expr));
10868 {
10869 tree temp_exp;
10870 tree temp_length;
10871
10872 temp_exp = ffecom_arg_ptr_to_expr (ffebld_left (expr), &temp_length);
10873 return ffecom_1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (temp_exp)),
10874 temp_exp);
10875 }
10876
10877 case FFEBLD_opPERCENT_REF:
10878 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10879 return ffecom_ptr_to_expr (ffebld_left (expr));
10880 if (length != NULL)
10881 {
10882 ign_length = NULL_TREE;
10883 length = &ign_length;
10884 }
10885 expr = ffebld_left (expr);
10886 break;
10887
10888 case FFEBLD_opPERCENT_DESCR:
10889 switch (ffeinfo_basictype (ffebld_info (expr)))
10890 {
10891 #ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10892 case FFEINFO_basictypeHOLLERITH:
10893 #endif
10894 case FFEINFO_basictypeCHARACTER:
10895 break; /* Passed by descriptor anyway. */
10896
10897 default:
10898 item = ffecom_ptr_to_expr (expr);
10899 if (item != error_mark_node)
10900 *length = TYPE_SIZE (TREE_TYPE (TREE_TYPE (item)));
10901 break;
10902 }
10903 break;
10904
10905 default:
10906 break;
10907 }
10908
10909 #ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10910 if ((ffeinfo_basictype (ffebld_info (expr)) == FFEINFO_basictypeHOLLERITH)
10911 && (length != NULL))
10912 { /* Pass Hollerith by descriptor. */
10913 ffetargetHollerith h;
10914
10915 assert (ffebld_op (expr) == FFEBLD_opCONTER);
10916 h = ffebld_cu_val_hollerith (ffebld_constant_union
10917 (ffebld_conter (expr)));
10918 *length
10919 = build_int_2 (h.length, 0);
10920 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10921 }
10922 #endif
10923
10924 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10925 return ffecom_ptr_to_expr (expr);
10926
10927 assert (ffeinfo_kindtype (ffebld_info (expr))
10928 == FFEINFO_kindtypeCHARACTER1);
10929
10930 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
10931 switch (ffecom_concat_list_count_ (catlist))
10932 {
10933 case 0: /* Shouldn't happen, but in case it does... */
10934 if (length != NULL)
10935 {
10936 *length = ffecom_f2c_ftnlen_zero_node;
10937 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10938 }
10939 ffecom_concat_list_kill_ (catlist);
10940 return null_pointer_node;
10941
10942 case 1: /* The (fairly) easy case. */
10943 if (length == NULL)
10944 ffecom_char_args_with_null_ (&item, &ign_length,
10945 ffecom_concat_list_expr_ (catlist, 0));
10946 else
10947 ffecom_char_args_ (&item, length,
10948 ffecom_concat_list_expr_ (catlist, 0));
10949 ffecom_concat_list_kill_ (catlist);
10950 assert (item != NULL_TREE);
10951 return item;
10952
10953 default: /* Must actually concatenate things. */
10954 break;
10955 }
10956
10957 {
10958 int count = ffecom_concat_list_count_ (catlist);
10959 int i;
10960 tree lengths;
10961 tree items;
10962 tree length_array;
10963 tree item_array;
10964 tree citem;
10965 tree clength;
10966 tree temporary;
10967 tree num;
10968 tree known_length;
10969 ffetargetCharacterSize sz;
10970
10971 length_array
10972 = lengths
10973 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
10974 FFETARGET_charactersizeNONE, count, TRUE);
10975 item_array
10976 = items
10977 = ffecom_push_tempvar (ffecom_f2c_address_type_node,
10978 FFETARGET_charactersizeNONE, count, TRUE);
10979
10980 known_length = ffecom_f2c_ftnlen_zero_node;
10981
10982 for (i = 0; i < count; ++i)
10983 {
10984 if ((i == count)
10985 && (length == NULL))
10986 ffecom_char_args_with_null_ (&citem, &clength,
10987 ffecom_concat_list_expr_ (catlist, i));
10988 else
10989 ffecom_char_args_ (&citem, &clength,
10990 ffecom_concat_list_expr_ (catlist, i));
10991 if ((citem == error_mark_node)
10992 || (clength == error_mark_node))
10993 {
10994 ffecom_concat_list_kill_ (catlist);
10995 *length = error_mark_node;
10996 return error_mark_node;
10997 }
10998
10999 items
11000 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
11001 ffecom_modify (void_type_node,
11002 ffecom_2 (ARRAY_REF,
11003 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
11004 item_array,
11005 build_int_2 (i, 0)),
11006 citem),
11007 items);
11008 clength = ffecom_save_tree (clength);
11009 if (length != NULL)
11010 known_length
11011 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
11012 known_length,
11013 clength);
11014 lengths
11015 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
11016 ffecom_modify (void_type_node,
11017 ffecom_2 (ARRAY_REF,
11018 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
11019 length_array,
11020 build_int_2 (i, 0)),
11021 clength),
11022 lengths);
11023 }
11024
11025 sz = ffecom_concat_list_maxlen_ (catlist);
11026 assert (sz != FFETARGET_charactersizeNONE);
11027
11028 temporary = ffecom_push_tempvar (char_type_node,
11029 sz, -1, TRUE);
11030 temporary = ffecom_1 (ADDR_EXPR,
11031 build_pointer_type (TREE_TYPE (temporary)),
11032 temporary);
11033
11034 item = build_tree_list (NULL_TREE, temporary);
11035 TREE_CHAIN (item)
11036 = build_tree_list (NULL_TREE,
11037 ffecom_1 (ADDR_EXPR,
11038 build_pointer_type (TREE_TYPE (items)),
11039 items));
11040 TREE_CHAIN (TREE_CHAIN (item))
11041 = build_tree_list (NULL_TREE,
11042 ffecom_1 (ADDR_EXPR,
11043 build_pointer_type (TREE_TYPE (lengths)),
11044 lengths));
11045 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
11046 = build_tree_list
11047 (NULL_TREE,
11048 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
11049 convert (ffecom_f2c_ftnlen_type_node,
11050 build_int_2 (count, 0))));
11051 num = build_int_2 (sz, 0);
11052 TREE_TYPE (num) = ffecom_f2c_ftnlen_type_node;
11053 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item))))
11054 = build_tree_list (NULL_TREE, num);
11055
11056 item = ffecom_call_gfrt (FFECOM_gfrtCAT, item);
11057 TREE_SIDE_EFFECTS (item) = 1;
11058 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (temporary),
11059 item,
11060 temporary);
11061
11062 if (length != NULL)
11063 *length = known_length;
11064 }
11065
11066 ffecom_concat_list_kill_ (catlist);
11067 assert (item != NULL_TREE);
11068 return item;
11069 }
11070
11071 #endif
11072 /* ffecom_call_gfrt -- Generate call to run-time function
11073
11074 tree expr;
11075 expr = ffecom_call_gfrt(FFECOM_gfrtSTOPNIL,NULL_TREE);
11076
11077 The first arg is the GNU Fortran Run-Time function index, the second
11078 arg is the list of arguments to pass to it. Returned is the expression
11079 (WITHOUT TREE_SIDE_EFFECTS set!) that makes the call and returns the
11080 result (which may be void). */
11081
11082 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11083 tree
11084 ffecom_call_gfrt (ffecomGfrt ix, tree args)
11085 {
11086 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
11087 ffecom_gfrt_kindtype (ix),
11088 ffe_is_f2c_library () && ffecom_gfrt_complex_[ix],
11089 NULL_TREE, args, NULL_TREE, NULL,
11090 NULL, NULL_TREE, TRUE);
11091 }
11092 #endif
11093
11094 /* ffecom_constantunion -- Transform constant-union to tree
11095
11096 ffebldConstantUnion cu; // the constant to transform
11097 ffeinfoBasictype bt; // its basic type
11098 ffeinfoKindtype kt; // its kind type
11099 tree tree_type; // ffecom_tree_type[bt][kt]
11100 ffecom_constantunion(&cu,bt,kt,tree_type); */
11101
11102 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11103 tree
11104 ffecom_constantunion (ffebldConstantUnion *cu, ffeinfoBasictype bt,
11105 ffeinfoKindtype kt, tree tree_type)
11106 {
11107 tree item;
11108
11109 switch (bt)
11110 {
11111 case FFEINFO_basictypeINTEGER:
11112 {
11113 int val;
11114
11115 switch (kt)
11116 {
11117 #if FFETARGET_okINTEGER1
11118 case FFEINFO_kindtypeINTEGER1:
11119 val = ffebld_cu_val_integer1 (*cu);
11120 break;
11121 #endif
11122
11123 #if FFETARGET_okINTEGER2
11124 case FFEINFO_kindtypeINTEGER2:
11125 val = ffebld_cu_val_integer2 (*cu);
11126 break;
11127 #endif
11128
11129 #if FFETARGET_okINTEGER3
11130 case FFEINFO_kindtypeINTEGER3:
11131 val = ffebld_cu_val_integer3 (*cu);
11132 break;
11133 #endif
11134
11135 #if FFETARGET_okINTEGER4
11136 case FFEINFO_kindtypeINTEGER4:
11137 val = ffebld_cu_val_integer4 (*cu);
11138 break;
11139 #endif
11140
11141 default:
11142 assert ("bad INTEGER constant kind type" == NULL);
11143 /* Fall through. */
11144 case FFEINFO_kindtypeANY:
11145 return error_mark_node;
11146 }
11147 item = build_int_2 (val, (val < 0) ? -1 : 0);
11148 TREE_TYPE (item) = tree_type;
11149 }
11150 break;
11151
11152 case FFEINFO_basictypeLOGICAL:
11153 {
11154 int val;
11155
11156 switch (kt)
11157 {
11158 #if FFETARGET_okLOGICAL1
11159 case FFEINFO_kindtypeLOGICAL1:
11160 val = ffebld_cu_val_logical1 (*cu);
11161 break;
11162 #endif
11163
11164 #if FFETARGET_okLOGICAL2
11165 case FFEINFO_kindtypeLOGICAL2:
11166 val = ffebld_cu_val_logical2 (*cu);
11167 break;
11168 #endif
11169
11170 #if FFETARGET_okLOGICAL3
11171 case FFEINFO_kindtypeLOGICAL3:
11172 val = ffebld_cu_val_logical3 (*cu);
11173 break;
11174 #endif
11175
11176 #if FFETARGET_okLOGICAL4
11177 case FFEINFO_kindtypeLOGICAL4:
11178 val = ffebld_cu_val_logical4 (*cu);
11179 break;
11180 #endif
11181
11182 default:
11183 assert ("bad LOGICAL constant kind type" == NULL);
11184 /* Fall through. */
11185 case FFEINFO_kindtypeANY:
11186 return error_mark_node;
11187 }
11188 item = build_int_2 (val, (val < 0) ? -1 : 0);
11189 TREE_TYPE (item) = tree_type;
11190 }
11191 break;
11192
11193 case FFEINFO_basictypeREAL:
11194 {
11195 REAL_VALUE_TYPE val;
11196
11197 switch (kt)
11198 {
11199 #if FFETARGET_okREAL1
11200 case FFEINFO_kindtypeREAL1:
11201 val = ffetarget_value_real1 (ffebld_cu_val_real1 (*cu));
11202 break;
11203 #endif
11204
11205 #if FFETARGET_okREAL2
11206 case FFEINFO_kindtypeREAL2:
11207 val = ffetarget_value_real2 (ffebld_cu_val_real2 (*cu));
11208 break;
11209 #endif
11210
11211 #if FFETARGET_okREAL3
11212 case FFEINFO_kindtypeREAL3:
11213 val = ffetarget_value_real3 (ffebld_cu_val_real3 (*cu));
11214 break;
11215 #endif
11216
11217 #if FFETARGET_okREAL4
11218 case FFEINFO_kindtypeREAL4:
11219 val = ffetarget_value_real4 (ffebld_cu_val_real4 (*cu));
11220 break;
11221 #endif
11222
11223 default:
11224 assert ("bad REAL constant kind type" == NULL);
11225 /* Fall through. */
11226 case FFEINFO_kindtypeANY:
11227 return error_mark_node;
11228 }
11229 item = build_real (tree_type, val);
11230 }
11231 break;
11232
11233 case FFEINFO_basictypeCOMPLEX:
11234 {
11235 REAL_VALUE_TYPE real;
11236 REAL_VALUE_TYPE imag;
11237 tree el_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
11238
11239 switch (kt)
11240 {
11241 #if FFETARGET_okCOMPLEX1
11242 case FFEINFO_kindtypeREAL1:
11243 real = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).real);
11244 imag = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).imaginary);
11245 break;
11246 #endif
11247
11248 #if FFETARGET_okCOMPLEX2
11249 case FFEINFO_kindtypeREAL2:
11250 real = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).real);
11251 imag = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).imaginary);
11252 break;
11253 #endif
11254
11255 #if FFETARGET_okCOMPLEX3
11256 case FFEINFO_kindtypeREAL3:
11257 real = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).real);
11258 imag = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).imaginary);
11259 break;
11260 #endif
11261
11262 #if FFETARGET_okCOMPLEX4
11263 case FFEINFO_kindtypeREAL4:
11264 real = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).real);
11265 imag = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).imaginary);
11266 break;
11267 #endif
11268
11269 default:
11270 assert ("bad REAL constant kind type" == NULL);
11271 /* Fall through. */
11272 case FFEINFO_kindtypeANY:
11273 return error_mark_node;
11274 }
11275 item = ffecom_build_complex_constant_ (tree_type,
11276 build_real (el_type, real),
11277 build_real (el_type, imag));
11278 }
11279 break;
11280
11281 case FFEINFO_basictypeCHARACTER:
11282 { /* Happens only in DATA and similar contexts. */
11283 ffetargetCharacter1 val;
11284
11285 switch (kt)
11286 {
11287 #if FFETARGET_okCHARACTER1
11288 case FFEINFO_kindtypeLOGICAL1:
11289 val = ffebld_cu_val_character1 (*cu);
11290 break;
11291 #endif
11292
11293 default:
11294 assert ("bad CHARACTER constant kind type" == NULL);
11295 /* Fall through. */
11296 case FFEINFO_kindtypeANY:
11297 return error_mark_node;
11298 }
11299 item = build_string (ffetarget_length_character1 (val),
11300 ffetarget_text_character1 (val));
11301 TREE_TYPE (item)
11302 = build_type_variant (build_array_type (char_type_node,
11303 build_range_type
11304 (integer_type_node,
11305 integer_one_node,
11306 build_int_2
11307 (ffetarget_length_character1
11308 (val), 0))),
11309 1, 0);
11310 }
11311 break;
11312
11313 case FFEINFO_basictypeHOLLERITH:
11314 {
11315 ffetargetHollerith h;
11316
11317 h = ffebld_cu_val_hollerith (*cu);
11318
11319 /* If not at least as wide as default INTEGER, widen it. */
11320 if (h.length >= FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE)
11321 item = build_string (h.length, h.text);
11322 else
11323 {
11324 char str[FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE];
11325
11326 memcpy (str, h.text, h.length);
11327 memset (&str[h.length], ' ',
11328 FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE
11329 - h.length);
11330 item = build_string (FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE,
11331 str);
11332 }
11333 TREE_TYPE (item)
11334 = build_type_variant (build_array_type (char_type_node,
11335 build_range_type
11336 (integer_type_node,
11337 integer_one_node,
11338 build_int_2
11339 (h.length, 0))),
11340 1, 0);
11341 }
11342 break;
11343
11344 case FFEINFO_basictypeTYPELESS:
11345 {
11346 ffetargetInteger1 ival;
11347 ffetargetTypeless tless;
11348 ffebad error;
11349
11350 tless = ffebld_cu_val_typeless (*cu);
11351 error = ffetarget_convert_integer1_typeless (&ival, tless);
11352 assert (error == FFEBAD);
11353
11354 item = build_int_2 ((int) ival, 0);
11355 }
11356 break;
11357
11358 default:
11359 assert ("not yet on constant type" == NULL);
11360 /* Fall through. */
11361 case FFEINFO_basictypeANY:
11362 return error_mark_node;
11363 }
11364
11365 TREE_CONSTANT (item) = 1;
11366
11367 return item;
11368 }
11369
11370 #endif
11371
11372 /* Handy way to make a field in a struct/union. */
11373
11374 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11375 tree
11376 ffecom_decl_field (tree context, tree prevfield,
11377 char *name, tree type)
11378 {
11379 tree field;
11380
11381 field = build_decl (FIELD_DECL, get_identifier (name), type);
11382 DECL_CONTEXT (field) = context;
11383 DECL_FRAME_SIZE (field) = 0;
11384 if (prevfield != NULL_TREE)
11385 TREE_CHAIN (prevfield) = field;
11386
11387 return field;
11388 }
11389
11390 #endif
11391
11392 void
11393 ffecom_close_include (FILE *f)
11394 {
11395 #if FFECOM_GCC_INCLUDE
11396 ffecom_close_include_ (f);
11397 #endif
11398 }
11399
11400 int
11401 ffecom_decode_include_option (char *spec)
11402 {
11403 #if FFECOM_GCC_INCLUDE
11404 return ffecom_decode_include_option_ (spec);
11405 #else
11406 return 1;
11407 #endif
11408 }
11409
11410 /* ffecom_end_transition -- Perform end transition on all symbols
11411
11412 ffecom_end_transition();
11413
11414 Calls ffecom_sym_end_transition for each global and local symbol. */
11415
11416 void
11417 ffecom_end_transition ()
11418 {
11419 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11420 ffebld item;
11421 #endif
11422
11423 if (ffe_is_ffedebug ())
11424 fprintf (dmpout, "; end_stmt_transition\n");
11425
11426 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11427 ffecom_list_blockdata_ = NULL;
11428 ffecom_list_common_ = NULL;
11429 #endif
11430
11431 ffesymbol_drive (ffecom_sym_end_transition);
11432 if (ffe_is_ffedebug ())
11433 {
11434 ffestorag_report ();
11435 ffesymbol_report_all ();
11436 }
11437
11438 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11439 ffecom_start_progunit_ ();
11440
11441 for (item = ffecom_list_blockdata_;
11442 item != NULL;
11443 item = ffebld_trail (item))
11444 {
11445 ffebld callee;
11446 ffesymbol s;
11447 tree dt;
11448 tree t;
11449 tree var;
11450 int yes;
11451 static int number = 0;
11452
11453 callee = ffebld_head (item);
11454 s = ffebld_symter (callee);
11455 t = ffesymbol_hook (s).decl_tree;
11456 if (t == NULL_TREE)
11457 {
11458 s = ffecom_sym_transform_ (s);
11459 t = ffesymbol_hook (s).decl_tree;
11460 }
11461
11462 yes = suspend_momentary ();
11463
11464 dt = build_pointer_type (TREE_TYPE (t));
11465
11466 var = build_decl (VAR_DECL,
11467 ffecom_get_invented_identifier ("__g77_forceload_%d",
11468 NULL, number++),
11469 dt);
11470 DECL_EXTERNAL (var) = 0;
11471 TREE_STATIC (var) = 1;
11472 TREE_PUBLIC (var) = 0;
11473 DECL_INITIAL (var) = error_mark_node;
11474 TREE_USED (var) = 1;
11475
11476 var = start_decl (var, FALSE);
11477
11478 t = ffecom_1 (ADDR_EXPR, dt, t);
11479
11480 finish_decl (var, t, FALSE);
11481
11482 resume_momentary (yes);
11483 }
11484
11485 /* This handles any COMMON areas that weren't referenced but have, for
11486 example, important initial data. */
11487
11488 for (item = ffecom_list_common_;
11489 item != NULL;
11490 item = ffebld_trail (item))
11491 ffecom_transform_common_ (ffebld_symter (ffebld_head (item)));
11492
11493 ffecom_list_common_ = NULL;
11494 #endif
11495 }
11496
11497 /* ffecom_exec_transition -- Perform exec transition on all symbols
11498
11499 ffecom_exec_transition();
11500
11501 Calls ffecom_sym_exec_transition for each global and local symbol.
11502 Make sure error updating not inhibited. */
11503
11504 void
11505 ffecom_exec_transition ()
11506 {
11507 bool inhibited;
11508
11509 if (ffe_is_ffedebug ())
11510 fprintf (dmpout, "; exec_stmt_transition\n");
11511
11512 inhibited = ffebad_inhibit ();
11513 ffebad_set_inhibit (FALSE);
11514
11515 ffesymbol_drive (ffecom_sym_exec_transition); /* Don't retract! */
11516 ffeequiv_exec_transition (); /* Handle all pending EQUIVALENCEs. */
11517 if (ffe_is_ffedebug ())
11518 {
11519 ffestorag_report ();
11520 ffesymbol_report_all ();
11521 }
11522
11523 if (inhibited)
11524 ffebad_set_inhibit (TRUE);
11525 }
11526
11527 /* ffecom_expand_let_stmt -- Compile let (assignment) statement
11528
11529 ffebld dest;
11530 ffebld source;
11531 ffecom_expand_let_stmt(dest,source);
11532
11533 Convert dest and source using ffecom_expr, then join them
11534 with an ASSIGN op and pass the whole thing to expand_expr_stmt. */
11535
11536 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11537 void
11538 ffecom_expand_let_stmt (ffebld dest, ffebld source)
11539 {
11540 tree dest_tree;
11541 tree dest_length;
11542 tree source_tree;
11543 tree expr_tree;
11544
11545 if (ffeinfo_basictype (ffebld_info (dest)) != FFEINFO_basictypeCHARACTER)
11546 {
11547 bool dest_used;
11548
11549 dest_tree = ffecom_expr_rw (dest);
11550 if (dest_tree == error_mark_node)
11551 return;
11552
11553 if ((TREE_CODE (dest_tree) != VAR_DECL)
11554 || TREE_ADDRESSABLE (dest_tree))
11555 source_tree = ffecom_expr_ (source, NULL_TREE, dest_tree, dest,
11556 &dest_used, FALSE);
11557 else
11558 {
11559 source_tree = ffecom_expr (source);
11560 dest_used = FALSE;
11561 }
11562 if (source_tree == error_mark_node)
11563 return;
11564
11565 if (dest_used)
11566 expr_tree = source_tree;
11567 else
11568 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11569 dest_tree,
11570 source_tree);
11571
11572 expand_expr_stmt (expr_tree);
11573 return;
11574 }
11575
11576 ffecom_push_calltemps ();
11577 ffecom_char_args_ (&dest_tree, &dest_length, dest);
11578 ffecom_let_char_ (dest_tree, dest_length, ffebld_size_known (dest),
11579 source);
11580 ffecom_pop_calltemps ();
11581 }
11582
11583 #endif
11584 /* ffecom_expr -- Transform expr into gcc tree
11585
11586 tree t;
11587 ffebld expr; // FFE expression.
11588 tree = ffecom_expr(expr);
11589
11590 Recursive descent on expr while making corresponding tree nodes and
11591 attaching type info and such. */
11592
11593 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11594 tree
11595 ffecom_expr (ffebld expr)
11596 {
11597 return ffecom_expr_ (expr, NULL_TREE, NULL_TREE, NULL, NULL,
11598 FALSE);
11599 }
11600
11601 #endif
11602 /* Like ffecom_expr, but return tree usable for assigned GOTO or FORMAT. */
11603
11604 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11605 tree
11606 ffecom_expr_assign (ffebld expr)
11607 {
11608 return ffecom_expr_ (expr, NULL_TREE, NULL_TREE, NULL, NULL,
11609 TRUE);
11610 }
11611
11612 #endif
11613 /* Like ffecom_expr_rw, but return tree usable for ASSIGN. */
11614
11615 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11616 tree
11617 ffecom_expr_assign_w (ffebld expr)
11618 {
11619 return ffecom_expr_ (expr, NULL_TREE, NULL_TREE, NULL, NULL,
11620 TRUE);
11621 }
11622
11623 #endif
11624 /* Transform expr for use as into read/write tree and stabilize the
11625 reference. Not for use on CHARACTER expressions.
11626
11627 Recursive descent on expr while making corresponding tree nodes and
11628 attaching type info and such. */
11629
11630 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11631 tree
11632 ffecom_expr_rw (ffebld expr)
11633 {
11634 assert (expr != NULL);
11635
11636 return stabilize_reference (ffecom_expr (expr));
11637 }
11638
11639 #endif
11640 /* Do global stuff. */
11641
11642 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11643 void
11644 ffecom_finish_compile ()
11645 {
11646 assert (ffecom_outer_function_decl_ == NULL_TREE);
11647 assert (current_function_decl == NULL_TREE);
11648
11649 ffeglobal_drive (ffecom_finish_global_);
11650 }
11651
11652 #endif
11653 /* Public entry point for front end to access finish_decl. */
11654
11655 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11656 void
11657 ffecom_finish_decl (tree decl, tree init, bool is_top_level)
11658 {
11659 assert (!is_top_level);
11660 finish_decl (decl, init, FALSE);
11661 }
11662
11663 #endif
11664 /* Finish a program unit. */
11665
11666 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11667 void
11668 ffecom_finish_progunit ()
11669 {
11670 ffecom_end_compstmt_ ();
11671
11672 ffecom_previous_function_decl_ = current_function_decl;
11673 ffecom_which_entrypoint_decl_ = NULL_TREE;
11674
11675 finish_function (0);
11676 }
11677
11678 #endif
11679 /* Wrapper for get_identifier. pattern is like "...%s...", text is
11680 inserted into final name in place of "%s", or if text is NULL,
11681 pattern is like "...%d..." and text form of number is inserted
11682 in place of "%d". */
11683
11684 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11685 tree
11686 ffecom_get_invented_identifier (char *pattern, char *text, int number)
11687 {
11688 tree decl;
11689 char *nam;
11690 mallocSize lenlen;
11691 char space[66];
11692
11693 if (text == NULL)
11694 lenlen = strlen (pattern) + 20;
11695 else
11696 lenlen = strlen (pattern) + strlen (text) - 1;
11697 if (lenlen > ARRAY_SIZE (space))
11698 nam = malloc_new_ks (malloc_pool_image (), pattern, lenlen);
11699 else
11700 nam = &space[0];
11701 if (text == NULL)
11702 sprintf (&nam[0], pattern, number);
11703 else
11704 sprintf (&nam[0], pattern, text);
11705 decl = get_identifier (nam);
11706 if (lenlen > ARRAY_SIZE (space))
11707 malloc_kill_ks (malloc_pool_image (), nam, lenlen);
11708
11709 IDENTIFIER_INVENTED (decl) = 1;
11710
11711 return decl;
11712 }
11713
11714 ffeinfoBasictype
11715 ffecom_gfrt_basictype (ffecomGfrt gfrt)
11716 {
11717 assert (gfrt < FFECOM_gfrt);
11718
11719 switch (ffecom_gfrt_type_[gfrt])
11720 {
11721 case FFECOM_rttypeVOID_:
11722 case FFECOM_rttypeVOIDSTAR_:
11723 return FFEINFO_basictypeNONE;
11724
11725 case FFECOM_rttypeFTNINT_:
11726 return FFEINFO_basictypeINTEGER;
11727
11728 case FFECOM_rttypeINTEGER_:
11729 return FFEINFO_basictypeINTEGER;
11730
11731 case FFECOM_rttypeLONGINT_:
11732 return FFEINFO_basictypeINTEGER;
11733
11734 case FFECOM_rttypeLOGICAL_:
11735 return FFEINFO_basictypeLOGICAL;
11736
11737 case FFECOM_rttypeREAL_F2C_:
11738 case FFECOM_rttypeREAL_GNU_:
11739 return FFEINFO_basictypeREAL;
11740
11741 case FFECOM_rttypeCOMPLEX_F2C_:
11742 case FFECOM_rttypeCOMPLEX_GNU_:
11743 return FFEINFO_basictypeCOMPLEX;
11744
11745 case FFECOM_rttypeDOUBLE_:
11746 case FFECOM_rttypeDOUBLEREAL_:
11747 return FFEINFO_basictypeREAL;
11748
11749 case FFECOM_rttypeDBLCMPLX_F2C_:
11750 case FFECOM_rttypeDBLCMPLX_GNU_:
11751 return FFEINFO_basictypeCOMPLEX;
11752
11753 case FFECOM_rttypeCHARACTER_:
11754 return FFEINFO_basictypeCHARACTER;
11755
11756 default:
11757 return FFEINFO_basictypeANY;
11758 }
11759 }
11760
11761 ffeinfoKindtype
11762 ffecom_gfrt_kindtype (ffecomGfrt gfrt)
11763 {
11764 assert (gfrt < FFECOM_gfrt);
11765
11766 switch (ffecom_gfrt_type_[gfrt])
11767 {
11768 case FFECOM_rttypeVOID_:
11769 case FFECOM_rttypeVOIDSTAR_:
11770 return FFEINFO_kindtypeNONE;
11771
11772 case FFECOM_rttypeFTNINT_:
11773 return FFEINFO_kindtypeINTEGER1;
11774
11775 case FFECOM_rttypeINTEGER_:
11776 return FFEINFO_kindtypeINTEGER1;
11777
11778 case FFECOM_rttypeLONGINT_:
11779 return FFEINFO_kindtypeINTEGER4;
11780
11781 case FFECOM_rttypeLOGICAL_:
11782 return FFEINFO_kindtypeLOGICAL1;
11783
11784 case FFECOM_rttypeREAL_F2C_:
11785 case FFECOM_rttypeREAL_GNU_:
11786 return FFEINFO_kindtypeREAL1;
11787
11788 case FFECOM_rttypeCOMPLEX_F2C_:
11789 case FFECOM_rttypeCOMPLEX_GNU_:
11790 return FFEINFO_kindtypeREAL1;
11791
11792 case FFECOM_rttypeDOUBLE_:
11793 case FFECOM_rttypeDOUBLEREAL_:
11794 return FFEINFO_kindtypeREAL2;
11795
11796 case FFECOM_rttypeDBLCMPLX_F2C_:
11797 case FFECOM_rttypeDBLCMPLX_GNU_:
11798 return FFEINFO_kindtypeREAL2;
11799
11800 case FFECOM_rttypeCHARACTER_:
11801 return FFEINFO_kindtypeCHARACTER1;
11802
11803 default:
11804 return FFEINFO_kindtypeANY;
11805 }
11806 }
11807
11808 void
11809 ffecom_init_0 ()
11810 {
11811 tree endlink;
11812 int i;
11813 int j;
11814 tree t;
11815 tree field;
11816 ffetype type;
11817 ffetype base_type;
11818
11819 /* This block of code comes from the now-obsolete cktyps.c. It checks
11820 whether the compiler environment is buggy in known ways, some of which
11821 would, if not explicitly checked here, result in subtle bugs in g77. */
11822
11823 if (ffe_is_do_internal_checks ())
11824 {
11825 static char names[][12]
11826 =
11827 {"bar", "bletch", "foo", "foobar"};
11828 char *name;
11829 unsigned long ul;
11830 double fl;
11831
11832 name = bsearch ("foo", &names[0], ARRAY_SIZE (names), sizeof (names[0]),
11833 (int (*)()) strcmp);
11834 if (name != (char *) &names[2])
11835 {
11836 assert ("bsearch doesn't work, #define FFEPROJ_BSEARCH 0 in proj.h"
11837 == NULL);
11838 abort ();
11839 }
11840
11841 ul = strtoul ("123456789", NULL, 10);
11842 if (ul != 123456789L)
11843 {
11844 assert ("strtoul doesn't have enough range, #define FFEPROJ_STRTOUL 0\
11845 in proj.h" == NULL);
11846 abort ();
11847 }
11848
11849 fl = atof ("56.789");
11850 if ((fl < 56.788) || (fl > 56.79))
11851 {
11852 assert ("atof not type double, fix your #include <stdio.h>"
11853 == NULL);
11854 abort ();
11855 }
11856 }
11857
11858 #if FFECOM_GCC_INCLUDE
11859 ffecom_initialize_char_syntax_ ();
11860 #endif
11861
11862 ffecom_outer_function_decl_ = NULL_TREE;
11863 current_function_decl = NULL_TREE;
11864 named_labels = NULL_TREE;
11865 current_binding_level = NULL_BINDING_LEVEL;
11866 free_binding_level = NULL_BINDING_LEVEL;
11867 pushlevel (0); /* make the binding_level structure for
11868 global names */
11869 global_binding_level = current_binding_level;
11870
11871 /* Define `int' and `char' first so that dbx will output them first. */
11872
11873 integer_type_node = make_signed_type (INT_TYPE_SIZE);
11874 pushdecl (build_decl (TYPE_DECL, get_identifier ("int"),
11875 integer_type_node));
11876
11877 char_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
11878 pushdecl (build_decl (TYPE_DECL, get_identifier ("char"),
11879 char_type_node));
11880
11881 long_integer_type_node = make_signed_type (LONG_TYPE_SIZE);
11882 pushdecl (build_decl (TYPE_DECL, get_identifier ("long int"),
11883 long_integer_type_node));
11884
11885 unsigned_type_node = make_unsigned_type (INT_TYPE_SIZE);
11886 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned int"),
11887 unsigned_type_node));
11888
11889 long_unsigned_type_node = make_unsigned_type (LONG_TYPE_SIZE);
11890 pushdecl (build_decl (TYPE_DECL, get_identifier ("long unsigned int"),
11891 long_unsigned_type_node));
11892
11893 long_long_integer_type_node = make_signed_type (LONG_LONG_TYPE_SIZE);
11894 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long int"),
11895 long_long_integer_type_node));
11896
11897 long_long_unsigned_type_node = make_unsigned_type (LONG_LONG_TYPE_SIZE);
11898 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"),
11899 long_long_unsigned_type_node));
11900
11901 set_sizetype
11902 (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))));
11903
11904 error_mark_node = make_node (ERROR_MARK);
11905 TREE_TYPE (error_mark_node) = error_mark_node;
11906
11907 short_integer_type_node = make_signed_type (SHORT_TYPE_SIZE);
11908 pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"),
11909 short_integer_type_node));
11910
11911 short_unsigned_type_node = make_unsigned_type (SHORT_TYPE_SIZE);
11912 pushdecl (build_decl (TYPE_DECL, get_identifier ("short unsigned int"),
11913 short_unsigned_type_node));
11914
11915 /* Define both `signed char' and `unsigned char'. */
11916 signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE);
11917 pushdecl (build_decl (TYPE_DECL, get_identifier ("signed char"),
11918 signed_char_type_node));
11919
11920 unsigned_char_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
11921 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned char"),
11922 unsigned_char_type_node));
11923
11924 float_type_node = make_node (REAL_TYPE);
11925 TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE;
11926 layout_type (float_type_node);
11927 pushdecl (build_decl (TYPE_DECL, get_identifier ("float"),
11928 float_type_node));
11929
11930 double_type_node = make_node (REAL_TYPE);
11931 TYPE_PRECISION (double_type_node) = DOUBLE_TYPE_SIZE;
11932 layout_type (double_type_node);
11933 pushdecl (build_decl (TYPE_DECL, get_identifier ("double"),
11934 double_type_node));
11935
11936 long_double_type_node = make_node (REAL_TYPE);
11937 TYPE_PRECISION (long_double_type_node) = LONG_DOUBLE_TYPE_SIZE;
11938 layout_type (long_double_type_node);
11939 pushdecl (build_decl (TYPE_DECL, get_identifier ("long double"),
11940 long_double_type_node));
11941
11942 complex_integer_type_node = ffecom_make_complex_type_ (integer_type_node);
11943 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"),
11944 complex_integer_type_node));
11945
11946 complex_float_type_node = ffecom_make_complex_type_ (float_type_node);
11947 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"),
11948 complex_float_type_node));
11949
11950 complex_double_type_node = ffecom_make_complex_type_ (double_type_node);
11951 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"),
11952 complex_double_type_node));
11953
11954 complex_long_double_type_node = ffecom_make_complex_type_ (long_double_type_node);
11955 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"),
11956 complex_long_double_type_node));
11957
11958 integer_zero_node = build_int_2 (0, 0);
11959 TREE_TYPE (integer_zero_node) = integer_type_node;
11960 integer_one_node = build_int_2 (1, 0);
11961 TREE_TYPE (integer_one_node) = integer_type_node;
11962
11963 size_zero_node = build_int_2 (0, 0);
11964 TREE_TYPE (size_zero_node) = sizetype;
11965 size_one_node = build_int_2 (1, 0);
11966 TREE_TYPE (size_one_node) = sizetype;
11967
11968 void_type_node = make_node (VOID_TYPE);
11969 pushdecl (build_decl (TYPE_DECL, get_identifier ("void"),
11970 void_type_node));
11971 layout_type (void_type_node); /* Uses integer_zero_node */
11972 /* We are not going to have real types in C with less than byte alignment,
11973 so we might as well not have any types that claim to have it. */
11974 TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
11975
11976 null_pointer_node = build_int_2 (0, 0);
11977 TREE_TYPE (null_pointer_node) = build_pointer_type (void_type_node);
11978 layout_type (TREE_TYPE (null_pointer_node));
11979
11980 string_type_node = build_pointer_type (char_type_node);
11981
11982 ffecom_tree_fun_type_void
11983 = build_function_type (void_type_node, NULL_TREE);
11984
11985 ffecom_tree_ptr_to_fun_type_void
11986 = build_pointer_type (ffecom_tree_fun_type_void);
11987
11988 endlink = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
11989
11990 float_ftype_float
11991 = build_function_type (float_type_node,
11992 tree_cons (NULL_TREE, float_type_node, endlink));
11993
11994 double_ftype_double
11995 = build_function_type (double_type_node,
11996 tree_cons (NULL_TREE, double_type_node, endlink));
11997
11998 ldouble_ftype_ldouble
11999 = build_function_type (long_double_type_node,
12000 tree_cons (NULL_TREE, long_double_type_node,
12001 endlink));
12002
12003 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
12004 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
12005 {
12006 ffecom_tree_type[i][j] = NULL_TREE;
12007 ffecom_tree_fun_type[i][j] = NULL_TREE;
12008 ffecom_tree_ptr_to_fun_type[i][j] = NULL_TREE;
12009 ffecom_f2c_typecode_[i][j] = -1;
12010 }
12011
12012 /* Set up standard g77 types. Note that INTEGER and LOGICAL are set
12013 to size FLOAT_TYPE_SIZE because they have to be the same size as
12014 REAL, which also is FLOAT_TYPE_SIZE, according to the standard.
12015 Compiler options and other such stuff that change the ways these
12016 types are set should not affect this particular setup. */
12017
12018 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1]
12019 = t = make_signed_type (FLOAT_TYPE_SIZE);
12020 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer"),
12021 t));
12022 type = ffetype_new ();
12023 base_type = type;
12024 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER1,
12025 type);
12026 ffetype_set_ams (type,
12027 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12028 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12029 ffetype_set_star (base_type,
12030 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12031 type);
12032 ffetype_set_kind (base_type, 1, type);
12033 assert (ffetype_size (type) == sizeof (ffetargetInteger1));
12034
12035 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER1]
12036 = t = make_unsigned_type (FLOAT_TYPE_SIZE); /* HOLLERITH means unsigned. */
12037 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned"),
12038 t));
12039
12040 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER2]
12041 = t = make_signed_type (CHAR_TYPE_SIZE);
12042 pushdecl (build_decl (TYPE_DECL, get_identifier ("byte"),
12043 t));
12044 type = ffetype_new ();
12045 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER2,
12046 type);
12047 ffetype_set_ams (type,
12048 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12049 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12050 ffetype_set_star (base_type,
12051 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12052 type);
12053 ffetype_set_kind (base_type, 3, type);
12054 assert (ffetype_size (type) == sizeof (ffetargetInteger2));
12055
12056 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER2]
12057 = t = make_unsigned_type (CHAR_TYPE_SIZE);
12058 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned byte"),
12059 t));
12060
12061 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER3]
12062 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
12063 pushdecl (build_decl (TYPE_DECL, get_identifier ("word"),
12064 t));
12065 type = ffetype_new ();
12066 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER3,
12067 type);
12068 ffetype_set_ams (type,
12069 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12070 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12071 ffetype_set_star (base_type,
12072 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12073 type);
12074 ffetype_set_kind (base_type, 6, type);
12075 assert (ffetype_size (type) == sizeof (ffetargetInteger3));
12076
12077 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER3]
12078 = t = make_unsigned_type (CHAR_TYPE_SIZE * 2);
12079 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned word"),
12080 t));
12081
12082 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER4]
12083 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
12084 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer4"),
12085 t));
12086 type = ffetype_new ();
12087 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER4,
12088 type);
12089 ffetype_set_ams (type,
12090 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12091 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12092 ffetype_set_star (base_type,
12093 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12094 type);
12095 ffetype_set_kind (base_type, 2, type);
12096 assert (ffetype_size (type) == sizeof (ffetargetInteger4));
12097
12098 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER4]
12099 = t = make_unsigned_type (FLOAT_TYPE_SIZE * 2);
12100 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned4"),
12101 t));
12102
12103 #if 0
12104 if (ffe_is_do_internal_checks ()
12105 && LONG_TYPE_SIZE != FLOAT_TYPE_SIZE
12106 && LONG_TYPE_SIZE != CHAR_TYPE_SIZE
12107 && LONG_TYPE_SIZE != SHORT_TYPE_SIZE
12108 && LONG_TYPE_SIZE != LONG_LONG_TYPE_SIZE)
12109 {
12110 fprintf (stderr, "Sorry, no g77 support for LONG_TYPE_SIZE (%d bits) yet.\n",
12111 LONG_TYPE_SIZE);
12112 }
12113 #endif
12114
12115 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL1]
12116 = t = make_signed_type (FLOAT_TYPE_SIZE);
12117 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical"),
12118 t));
12119 type = ffetype_new ();
12120 base_type = type;
12121 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL1,
12122 type);
12123 ffetype_set_ams (type,
12124 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12125 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12126 ffetype_set_star (base_type,
12127 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12128 type);
12129 ffetype_set_kind (base_type, 1, type);
12130 assert (ffetype_size (type) == sizeof (ffetargetLogical1));
12131
12132 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL2]
12133 = t = make_signed_type (CHAR_TYPE_SIZE);
12134 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical2"),
12135 t));
12136 type = ffetype_new ();
12137 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL2,
12138 type);
12139 ffetype_set_ams (type,
12140 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12141 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12142 ffetype_set_star (base_type,
12143 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12144 type);
12145 ffetype_set_kind (base_type, 3, type);
12146 assert (ffetype_size (type) == sizeof (ffetargetLogical2));
12147
12148 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL3]
12149 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
12150 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical3"),
12151 t));
12152 type = ffetype_new ();
12153 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL3,
12154 type);
12155 ffetype_set_ams (type,
12156 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12157 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12158 ffetype_set_star (base_type,
12159 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12160 type);
12161 ffetype_set_kind (base_type, 6, type);
12162 assert (ffetype_size (type) == sizeof (ffetargetLogical3));
12163
12164 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL4]
12165 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
12166 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical4"),
12167 t));
12168 type = ffetype_new ();
12169 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL4,
12170 type);
12171 ffetype_set_ams (type,
12172 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12173 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12174 ffetype_set_star (base_type,
12175 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12176 type);
12177 ffetype_set_kind (base_type, 2, type);
12178 assert (ffetype_size (type) == sizeof (ffetargetLogical4));
12179
12180 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
12181 = t = make_node (REAL_TYPE);
12182 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE;
12183 pushdecl (build_decl (TYPE_DECL, get_identifier ("real"),
12184 t));
12185 layout_type (t);
12186 type = ffetype_new ();
12187 base_type = type;
12188 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREAL1,
12189 type);
12190 ffetype_set_ams (type,
12191 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12192 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12193 ffetype_set_star (base_type,
12194 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12195 type);
12196 ffetype_set_kind (base_type, 1, type);
12197 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
12198 = FFETARGET_f2cTYREAL;
12199 assert (ffetype_size (type) == sizeof (ffetargetReal1));
12200
12201 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREALDOUBLE]
12202 = t = make_node (REAL_TYPE);
12203 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE * 2; /* Always twice REAL. */
12204 pushdecl (build_decl (TYPE_DECL, get_identifier ("double precision"),
12205 t));
12206 layout_type (t);
12207 type = ffetype_new ();
12208 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREALDOUBLE,
12209 type);
12210 ffetype_set_ams (type,
12211 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12212 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12213 ffetype_set_star (base_type,
12214 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12215 type);
12216 ffetype_set_kind (base_type, 2, type);
12217 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]
12218 = FFETARGET_f2cTYDREAL;
12219 assert (ffetype_size (type) == sizeof (ffetargetReal2));
12220
12221 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
12222 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]);
12223 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex"),
12224 t));
12225 type = ffetype_new ();
12226 base_type = type;
12227 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREAL1,
12228 type);
12229 ffetype_set_ams (type,
12230 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12231 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12232 ffetype_set_star (base_type,
12233 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12234 type);
12235 ffetype_set_kind (base_type, 1, type);
12236 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
12237 = FFETARGET_f2cTYCOMPLEX;
12238 assert (ffetype_size (type) == sizeof (ffetargetComplex1));
12239
12240 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREALDOUBLE]
12241 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]);
12242 pushdecl (build_decl (TYPE_DECL, get_identifier ("double complex"),
12243 t));
12244 type = ffetype_new ();
12245 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREALDOUBLE,
12246 type);
12247 ffetype_set_ams (type,
12248 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12249 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12250 ffetype_set_star (base_type,
12251 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
12252 type);
12253 ffetype_set_kind (base_type, 2,
12254 type);
12255 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL2]
12256 = FFETARGET_f2cTYDCOMPLEX;
12257 assert (ffetype_size (type) == sizeof (ffetargetComplex2));
12258
12259 /* Make function and ptr-to-function types for non-CHARACTER types. */
12260
12261 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
12262 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
12263 {
12264 if ((t = ffecom_tree_type[i][j]) != NULL_TREE)
12265 {
12266 if (i == FFEINFO_basictypeINTEGER)
12267 {
12268 /* Figure out the smallest INTEGER type that can hold
12269 a pointer on this machine. */
12270 if (GET_MODE_SIZE (TYPE_MODE (t))
12271 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
12272 {
12273 if ((ffecom_pointer_kind_ == FFEINFO_kindtypeNONE)
12274 || (GET_MODE_SIZE (TYPE_MODE (ffecom_tree_type[i][ffecom_pointer_kind_]))
12275 > GET_MODE_SIZE (TYPE_MODE (t))))
12276 ffecom_pointer_kind_ = j;
12277 }
12278 }
12279 else if (i == FFEINFO_basictypeCOMPLEX)
12280 t = void_type_node;
12281 /* For f2c compatibility, REAL functions are really
12282 implemented as DOUBLE PRECISION. */
12283 else if ((i == FFEINFO_basictypeREAL)
12284 && (j == FFEINFO_kindtypeREAL1))
12285 t = ffecom_tree_type
12286 [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2];
12287
12288 t = ffecom_tree_fun_type[i][j] = build_function_type (t,
12289 NULL_TREE);
12290 ffecom_tree_ptr_to_fun_type[i][j] = build_pointer_type (t);
12291 }
12292 }
12293
12294 /* Set up pointer types. */
12295
12296 if (ffecom_pointer_kind_ == FFEINFO_basictypeNONE)
12297 fatal ("no INTEGER type can hold a pointer on this configuration");
12298 else if (0 && ffe_is_do_internal_checks ())
12299 fprintf (stderr, "Pointer type kt=%d\n", ffecom_pointer_kind_);
12300 type = ffetype_new ();
12301 ffetype_set_kind (ffeinfo_type (FFEINFO_basictypeINTEGER,
12302 FFEINFO_kindtypeINTEGERDEFAULT),
12303 7, type);
12304
12305 if (ffe_is_ugly_assign ())
12306 ffecom_label_kind_ = ffecom_pointer_kind_; /* Require ASSIGN etc to this. */
12307 else
12308 ffecom_label_kind_ = FFEINFO_kindtypeINTEGERDEFAULT;
12309 if (0 && ffe_is_do_internal_checks ())
12310 fprintf (stderr, "Label type kt=%d\n", ffecom_label_kind_);
12311
12312 ffecom_integer_type_node
12313 = ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1];
12314 ffecom_integer_zero_node = convert (ffecom_integer_type_node,
12315 integer_zero_node);
12316 ffecom_integer_one_node = convert (ffecom_integer_type_node,
12317 integer_one_node);
12318
12319 /* Yes, the "FLOAT_TYPE_SIZE" references below are intentional.
12320 Turns out that by TYLONG, runtime/libI77/lio.h really means
12321 "whatever size an ftnint is". For consistency and sanity,
12322 com.h and runtime/f2c.h.in agree that flag, ftnint, and ftlen
12323 all are INTEGER, which we also make out of whatever back-end
12324 integer type is FLOAT_TYPE_SIZE bits wide. This change, from
12325 LONG_TYPE_SIZE, for TYLONG and TYLOGICAL, was necessary to
12326 accommodate machines like the Alpha. Note that this suggests
12327 f2c and libf2c are missing a distinction perhaps needed on
12328 some machines between "int" and "long int". -- burley 0.5.5 950215 */
12329
12330 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, FLOAT_TYPE_SIZE,
12331 FFETARGET_f2cTYLONG);
12332 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, SHORT_TYPE_SIZE,
12333 FFETARGET_f2cTYSHORT);
12334 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, CHAR_TYPE_SIZE,
12335 FFETARGET_f2cTYINT1);
12336 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, LONG_LONG_TYPE_SIZE,
12337 FFETARGET_f2cTYQUAD);
12338 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, FLOAT_TYPE_SIZE,
12339 FFETARGET_f2cTYLOGICAL);
12340 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, SHORT_TYPE_SIZE,
12341 FFETARGET_f2cTYLOGICAL2);
12342 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, CHAR_TYPE_SIZE,
12343 FFETARGET_f2cTYLOGICAL1);
12344 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, LONG_LONG_TYPE_SIZE,
12345 FFETARGET_f2cTYQUAD /* ~~~ */);
12346
12347 /* CHARACTER stuff is all special-cased, so it is not handled in the above
12348 loop. CHARACTER items are built as arrays of unsigned char. */
12349
12350 ffecom_tree_type[FFEINFO_basictypeCHARACTER]
12351 [FFEINFO_kindtypeCHARACTER1] = t = char_type_node;
12352 type = ffetype_new ();
12353 base_type = type;
12354 ffeinfo_set_type (FFEINFO_basictypeCHARACTER,
12355 FFEINFO_kindtypeCHARACTER1,
12356 type);
12357 ffetype_set_ams (type,
12358 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12359 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12360 ffetype_set_kind (base_type, 1, type);
12361 assert (ffetype_size (type)
12362 == sizeof (((ffetargetCharacter1) { 0, NULL }).text[0]));
12363
12364 ffecom_tree_fun_type[FFEINFO_basictypeCHARACTER]
12365 [FFEINFO_kindtypeCHARACTER1] = ffecom_tree_fun_type_void;
12366 ffecom_tree_ptr_to_fun_type[FFEINFO_basictypeCHARACTER]
12367 [FFEINFO_kindtypeCHARACTER1]
12368 = ffecom_tree_ptr_to_fun_type_void;
12369 ffecom_f2c_typecode_[FFEINFO_basictypeCHARACTER][FFEINFO_kindtypeCHARACTER1]
12370 = FFETARGET_f2cTYCHAR;
12371
12372 ffecom_f2c_typecode_[FFEINFO_basictypeANY][FFEINFO_kindtypeANY]
12373 = 0;
12374
12375 /* Make multi-return-value type and fields. */
12376
12377 ffecom_multi_type_node_ = make_node (UNION_TYPE);
12378
12379 field = NULL_TREE;
12380
12381 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
12382 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
12383 {
12384 char name[30];
12385
12386 if (ffecom_tree_type[i][j] == NULL_TREE)
12387 continue; /* Not supported. */
12388 sprintf (&name[0], "bt_%s_kt_%s",
12389 ffeinfo_basictype_string ((ffeinfoBasictype) i),
12390 ffeinfo_kindtype_string ((ffeinfoKindtype) j));
12391 ffecom_multi_fields_[i][j] = build_decl (FIELD_DECL,
12392 get_identifier (name),
12393 ffecom_tree_type[i][j]);
12394 DECL_CONTEXT (ffecom_multi_fields_[i][j])
12395 = ffecom_multi_type_node_;
12396 DECL_FRAME_SIZE (ffecom_multi_fields_[i][j]) = 0;
12397 TREE_CHAIN (ffecom_multi_fields_[i][j]) = field;
12398 field = ffecom_multi_fields_[i][j];
12399 }
12400
12401 TYPE_FIELDS (ffecom_multi_type_node_) = field;
12402 layout_type (ffecom_multi_type_node_);
12403
12404 /* Subroutines usually return integer because they might have alternate
12405 returns. */
12406
12407 ffecom_tree_subr_type
12408 = build_function_type (integer_type_node, NULL_TREE);
12409 ffecom_tree_ptr_to_subr_type
12410 = build_pointer_type (ffecom_tree_subr_type);
12411 ffecom_tree_blockdata_type
12412 = build_function_type (void_type_node, NULL_TREE);
12413
12414 builtin_function ("__builtin_sqrtf", float_ftype_float,
12415 BUILT_IN_FSQRT, "sqrtf");
12416 builtin_function ("__builtin_fsqrt", double_ftype_double,
12417 BUILT_IN_FSQRT, "sqrt");
12418 builtin_function ("__builtin_sqrtl", ldouble_ftype_ldouble,
12419 BUILT_IN_FSQRT, "sqrtl");
12420 builtin_function ("__builtin_sinf", float_ftype_float,
12421 BUILT_IN_SIN, "sinf");
12422 builtin_function ("__builtin_sin", double_ftype_double,
12423 BUILT_IN_SIN, "sin");
12424 builtin_function ("__builtin_sinl", ldouble_ftype_ldouble,
12425 BUILT_IN_SIN, "sinl");
12426 builtin_function ("__builtin_cosf", float_ftype_float,
12427 BUILT_IN_COS, "cosf");
12428 builtin_function ("__builtin_cos", double_ftype_double,
12429 BUILT_IN_COS, "cos");
12430 builtin_function ("__builtin_cosl", ldouble_ftype_ldouble,
12431 BUILT_IN_COS, "cosl");
12432
12433 #if BUILT_FOR_270
12434 pedantic_lvalues = FALSE;
12435 #endif
12436
12437 ffecom_f2c_make_type_ (&ffecom_f2c_integer_type_node,
12438 FFECOM_f2cINTEGER,
12439 "integer");
12440 ffecom_f2c_make_type_ (&ffecom_f2c_address_type_node,
12441 FFECOM_f2cADDRESS,
12442 "address");
12443 ffecom_f2c_make_type_ (&ffecom_f2c_real_type_node,
12444 FFECOM_f2cREAL,
12445 "real");
12446 ffecom_f2c_make_type_ (&ffecom_f2c_doublereal_type_node,
12447 FFECOM_f2cDOUBLEREAL,
12448 "doublereal");
12449 ffecom_f2c_make_type_ (&ffecom_f2c_complex_type_node,
12450 FFECOM_f2cCOMPLEX,
12451 "complex");
12452 ffecom_f2c_make_type_ (&ffecom_f2c_doublecomplex_type_node,
12453 FFECOM_f2cDOUBLECOMPLEX,
12454 "doublecomplex");
12455 ffecom_f2c_make_type_ (&ffecom_f2c_longint_type_node,
12456 FFECOM_f2cLONGINT,
12457 "longint");
12458 ffecom_f2c_make_type_ (&ffecom_f2c_logical_type_node,
12459 FFECOM_f2cLOGICAL,
12460 "logical");
12461 ffecom_f2c_make_type_ (&ffecom_f2c_flag_type_node,
12462 FFECOM_f2cFLAG,
12463 "flag");
12464 ffecom_f2c_make_type_ (&ffecom_f2c_ftnlen_type_node,
12465 FFECOM_f2cFTNLEN,
12466 "ftnlen");
12467 ffecom_f2c_make_type_ (&ffecom_f2c_ftnint_type_node,
12468 FFECOM_f2cFTNINT,
12469 "ftnint");
12470
12471 ffecom_f2c_ftnlen_zero_node
12472 = convert (ffecom_f2c_ftnlen_type_node, integer_zero_node);
12473
12474 ffecom_f2c_ftnlen_one_node
12475 = convert (ffecom_f2c_ftnlen_type_node, integer_one_node);
12476
12477 ffecom_f2c_ftnlen_two_node = build_int_2 (2, 0);
12478 TREE_TYPE (ffecom_f2c_ftnlen_two_node) = ffecom_integer_type_node;
12479
12480 ffecom_f2c_ptr_to_ftnlen_type_node
12481 = build_pointer_type (ffecom_f2c_ftnlen_type_node);
12482
12483 ffecom_f2c_ptr_to_ftnint_type_node
12484 = build_pointer_type (ffecom_f2c_ftnint_type_node);
12485
12486 ffecom_f2c_ptr_to_integer_type_node
12487 = build_pointer_type (ffecom_f2c_integer_type_node);
12488
12489 ffecom_f2c_ptr_to_real_type_node
12490 = build_pointer_type (ffecom_f2c_real_type_node);
12491
12492 ffecom_float_zero_ = build_real (float_type_node, dconst0);
12493 ffecom_double_zero_ = build_real (double_type_node, dconst0);
12494 {
12495 REAL_VALUE_TYPE point_5;
12496
12497 #ifdef REAL_ARITHMETIC
12498 REAL_ARITHMETIC (point_5, RDIV_EXPR, dconst1, dconst2);
12499 #else
12500 point_5 = .5;
12501 #endif
12502 ffecom_float_half_ = build_real (float_type_node, point_5);
12503 ffecom_double_half_ = build_real (double_type_node, point_5);
12504 }
12505
12506 /* Do "extern int xargc;". */
12507
12508 ffecom_tree_xargc_ = build_decl (VAR_DECL,
12509 get_identifier ("xargc"),
12510 integer_type_node);
12511 DECL_EXTERNAL (ffecom_tree_xargc_) = 1;
12512 TREE_STATIC (ffecom_tree_xargc_) = 1;
12513 TREE_PUBLIC (ffecom_tree_xargc_) = 1;
12514 ffecom_tree_xargc_ = start_decl (ffecom_tree_xargc_, FALSE);
12515 finish_decl (ffecom_tree_xargc_, NULL_TREE, FALSE);
12516
12517 #if 0 /* This is being fixed, and seems to be working now. */
12518 if ((FLOAT_TYPE_SIZE != 32)
12519 || (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))) != 32))
12520 {
12521 warning ("configuration: REAL, INTEGER, and LOGICAL are %d bits wide,",
12522 (int) FLOAT_TYPE_SIZE);
12523 warning ("and pointers are %d bits wide, but g77 doesn't yet work",
12524 (int) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))));
12525 warning ("properly unless they all are 32 bits wide.");
12526 warning ("Please keep this in mind before you report bugs. g77 should");
12527 warning ("support non-32-bit machines better as of version 0.6.");
12528 }
12529 #endif
12530
12531 #if 0 /* Code in ste.c that would crash has been commented out. */
12532 if (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
12533 < TYPE_PRECISION (string_type_node))
12534 /* I/O will probably crash. */
12535 warning ("configuration: char * holds %d bits, but ftnlen only %d",
12536 TYPE_PRECISION (string_type_node),
12537 TYPE_PRECISION (ffecom_f2c_ftnlen_type_node));
12538 #endif
12539
12540 #if 0 /* ASSIGN-related stuff has been changed to accommodate this. */
12541 if (TYPE_PRECISION (ffecom_integer_type_node)
12542 < TYPE_PRECISION (string_type_node))
12543 /* ASSIGN 10 TO I will crash. */
12544 warning ("configuration: char * holds %d bits, but INTEGER only %d --\n\
12545 ASSIGN statement might fail",
12546 TYPE_PRECISION (string_type_node),
12547 TYPE_PRECISION (ffecom_integer_type_node));
12548 #endif
12549 }
12550
12551 #endif
12552 /* ffecom_init_2 -- Initialize
12553
12554 ffecom_init_2(); */
12555
12556 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12557 void
12558 ffecom_init_2 ()
12559 {
12560 assert (ffecom_outer_function_decl_ == NULL_TREE);
12561 assert (current_function_decl == NULL_TREE);
12562 assert (ffecom_which_entrypoint_decl_ == NULL_TREE);
12563
12564 ffecom_master_arglist_ = NULL;
12565 ++ffecom_num_fns_;
12566 ffecom_latest_temp_ = NULL;
12567 ffecom_primary_entry_ = NULL;
12568 ffecom_is_altreturning_ = FALSE;
12569 ffecom_func_result_ = NULL_TREE;
12570 ffecom_multi_retval_ = NULL_TREE;
12571 }
12572
12573 #endif
12574 /* ffecom_list_expr -- Transform list of exprs into gcc tree
12575
12576 tree t;
12577 ffebld expr; // FFE opITEM list.
12578 tree = ffecom_list_expr(expr);
12579
12580 List of actual args is transformed into corresponding gcc backend list. */
12581
12582 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12583 tree
12584 ffecom_list_expr (ffebld expr)
12585 {
12586 tree list;
12587 tree *plist = &list;
12588 tree trail = NULL_TREE; /* Append char length args here. */
12589 tree *ptrail = &trail;
12590 tree length;
12591
12592 while (expr != NULL)
12593 {
12594 *plist
12595 = build_tree_list (NULL_TREE, ffecom_arg_expr (ffebld_head (expr),
12596 &length));
12597 plist = &TREE_CHAIN (*plist);
12598 expr = ffebld_trail (expr);
12599 if (length != NULL_TREE)
12600 {
12601 *ptrail = build_tree_list (NULL_TREE, length);
12602 ptrail = &TREE_CHAIN (*ptrail);
12603 }
12604 }
12605
12606 *plist = trail;
12607
12608 return list;
12609 }
12610
12611 #endif
12612 /* ffecom_list_ptr_to_expr -- Transform list of exprs into gcc tree
12613
12614 tree t;
12615 ffebld expr; // FFE opITEM list.
12616 tree = ffecom_list_ptr_to_expr(expr);
12617
12618 List of actual args is transformed into corresponding gcc backend list for
12619 use in calling an external procedure (vs. a statement function). */
12620
12621 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12622 tree
12623 ffecom_list_ptr_to_expr (ffebld expr)
12624 {
12625 tree list;
12626 tree *plist = &list;
12627 tree trail = NULL_TREE; /* Append char length args here. */
12628 tree *ptrail = &trail;
12629 tree length;
12630
12631 while (expr != NULL)
12632 {
12633 *plist
12634 = build_tree_list (NULL_TREE,
12635 ffecom_arg_ptr_to_expr (ffebld_head (expr),
12636 &length));
12637 plist = &TREE_CHAIN (*plist);
12638 expr = ffebld_trail (expr);
12639 if (length != NULL_TREE)
12640 {
12641 *ptrail = build_tree_list (NULL_TREE, length);
12642 ptrail = &TREE_CHAIN (*ptrail);
12643 }
12644 }
12645
12646 *plist = trail;
12647
12648 return list;
12649 }
12650
12651 #endif
12652 /* Obtain gcc's LABEL_DECL tree for label. */
12653
12654 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12655 tree
12656 ffecom_lookup_label (ffelab label)
12657 {
12658 tree glabel;
12659
12660 if (ffelab_hook (label) == NULL_TREE)
12661 {
12662 char labelname[16];
12663
12664 switch (ffelab_type (label))
12665 {
12666 case FFELAB_typeLOOPEND:
12667 case FFELAB_typeNOTLOOP:
12668 case FFELAB_typeENDIF:
12669 sprintf (labelname, "%" ffelabValue_f "u", ffelab_value (label));
12670 glabel = build_decl (LABEL_DECL, get_identifier (labelname),
12671 void_type_node);
12672 DECL_CONTEXT (glabel) = current_function_decl;
12673 DECL_MODE (glabel) = VOIDmode;
12674 break;
12675
12676 case FFELAB_typeFORMAT:
12677 push_obstacks_nochange ();
12678 end_temporary_allocation ();
12679
12680 glabel = build_decl (VAR_DECL,
12681 ffecom_get_invented_identifier
12682 ("__g77_format_%d", NULL,
12683 (int) ffelab_value (label)),
12684 build_type_variant (build_array_type
12685 (char_type_node,
12686 NULL_TREE),
12687 1, 0));
12688 TREE_CONSTANT (glabel) = 1;
12689 TREE_STATIC (glabel) = 1;
12690 DECL_CONTEXT (glabel) = 0;
12691 DECL_INITIAL (glabel) = NULL;
12692 make_decl_rtl (glabel, NULL, 0);
12693 expand_decl (glabel);
12694
12695 resume_temporary_allocation ();
12696 pop_obstacks ();
12697
12698 break;
12699
12700 case FFELAB_typeANY:
12701 glabel = error_mark_node;
12702 break;
12703
12704 default:
12705 assert ("bad label type" == NULL);
12706 glabel = NULL;
12707 break;
12708 }
12709 ffelab_set_hook (label, glabel);
12710 }
12711 else
12712 {
12713 glabel = ffelab_hook (label);
12714 }
12715
12716 return glabel;
12717 }
12718
12719 #endif
12720 /* Stabilizes the arguments. Don't use this if the lhs and rhs come from
12721 a single source specification (as in the fourth argument of MVBITS).
12722 If the type is NULL_TREE, the type of lhs is used to make the type of
12723 the MODIFY_EXPR. */
12724
12725 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12726 tree
12727 ffecom_modify (tree newtype, tree lhs,
12728 tree rhs)
12729 {
12730 if (lhs == error_mark_node || rhs == error_mark_node)
12731 return error_mark_node;
12732
12733 if (newtype == NULL_TREE)
12734 newtype = TREE_TYPE (lhs);
12735
12736 if (TREE_SIDE_EFFECTS (lhs))
12737 lhs = stabilize_reference (lhs);
12738
12739 return ffecom_2s (MODIFY_EXPR, newtype, lhs, rhs);
12740 }
12741
12742 #endif
12743
12744 /* Register source file name. */
12745
12746 void
12747 ffecom_file (char *name)
12748 {
12749 #if FFECOM_GCC_INCLUDE
12750 ffecom_file_ (name);
12751 #endif
12752 }
12753
12754 /* ffecom_notify_init_storage -- An aggregate storage is now fully init'ed
12755
12756 ffestorag st;
12757 ffecom_notify_init_storage(st);
12758
12759 Gets called when all possible units in an aggregate storage area (a LOCAL
12760 with equivalences or a COMMON) have been initialized. The initialization
12761 info either is in ffestorag_init or, if that is NULL,
12762 ffestorag_accretion:
12763
12764 ffestorag_init may contain an opCONTER or opARRTER. opCONTER may occur
12765 even for an array if the array is one element in length!
12766
12767 ffestorag_accretion will contain an opACCTER. It is much like an
12768 opARRTER except it has an ffebit object in it instead of just a size.
12769 The back end can use the info in the ffebit object, if it wants, to
12770 reduce the amount of actual initialization, but in any case it should
12771 kill the ffebit object when done. Also, set accretion to NULL but
12772 init to a non-NULL value.
12773
12774 After performing initialization, DO NOT set init to NULL, because that'll
12775 tell the front end it is ok for more initialization to happen. Instead,
12776 set init to an opANY expression or some such thing that you can use to
12777 tell that you've already initialized the object.
12778
12779 27-Oct-91 JCB 1.1
12780 Support two-pass FFE. */
12781
12782 void
12783 ffecom_notify_init_storage (ffestorag st)
12784 {
12785 ffebld init; /* The initialization expression. */
12786 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12787 ffetargetOffset size; /* The size of the entity. */
12788 #endif
12789
12790 if (ffestorag_init (st) == NULL)
12791 {
12792 init = ffestorag_accretion (st);
12793 assert (init != NULL);
12794 ffestorag_set_accretion (st, NULL);
12795 ffestorag_set_accretes (st, 0);
12796
12797 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12798 /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12799 size = ffebld_accter_size (init);
12800 ffebit_kill (ffebld_accter_bits (init));
12801 ffebld_set_op (init, FFEBLD_opARRTER);
12802 ffebld_set_arrter (init, ffebld_accter (init));
12803 ffebld_arrter_set_size (init, size);
12804 #endif
12805
12806 #if FFECOM_TWOPASS
12807 ffestorag_set_init (st, init);
12808 #endif
12809 }
12810 #if FFECOM_ONEPASS
12811 else
12812 init = ffestorag_init (st);
12813 #endif
12814
12815 #if FFECOM_ONEPASS /* Process the inits, wipe 'em out. */
12816 ffestorag_set_init (st, ffebld_new_any ());
12817
12818 if (ffebld_op (init) == FFEBLD_opANY)
12819 return; /* Oh, we already did this! */
12820
12821 #if FFECOM_targetCURRENT == FFECOM_targetFFE
12822 {
12823 ffesymbol s;
12824
12825 if (ffestorag_symbol (st) != NULL)
12826 s = ffestorag_symbol (st);
12827 else
12828 s = ffestorag_typesymbol (st);
12829
12830 fprintf (dmpout, "= initialize_storage \"%s\" ",
12831 (s != NULL) ? ffesymbol_text (s) : "(unnamed)");
12832 ffebld_dump (init);
12833 fputc ('\n', dmpout);
12834 }
12835 #endif
12836
12837 #endif /* if FFECOM_ONEPASS */
12838 }
12839
12840 /* ffecom_notify_init_symbol -- A symbol is now fully init'ed
12841
12842 ffesymbol s;
12843 ffecom_notify_init_symbol(s);
12844
12845 Gets called when all possible units in a symbol (not placed in COMMON
12846 or involved in EQUIVALENCE, unless it as yet has no ffestorag object)
12847 have been initialized. The initialization info either is in
12848 ffesymbol_init or, if that is NULL, ffesymbol_accretion:
12849
12850 ffesymbol_init may contain an opCONTER or opARRTER. opCONTER may occur
12851 even for an array if the array is one element in length!
12852
12853 ffesymbol_accretion will contain an opACCTER. It is much like an
12854 opARRTER except it has an ffebit object in it instead of just a size.
12855 The back end can use the info in the ffebit object, if it wants, to
12856 reduce the amount of actual initialization, but in any case it should
12857 kill the ffebit object when done. Also, set accretion to NULL but
12858 init to a non-NULL value.
12859
12860 After performing initialization, DO NOT set init to NULL, because that'll
12861 tell the front end it is ok for more initialization to happen. Instead,
12862 set init to an opANY expression or some such thing that you can use to
12863 tell that you've already initialized the object.
12864
12865 27-Oct-91 JCB 1.1
12866 Support two-pass FFE. */
12867
12868 void
12869 ffecom_notify_init_symbol (ffesymbol s)
12870 {
12871 ffebld init; /* The initialization expression. */
12872 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12873 ffetargetOffset size; /* The size of the entity. */
12874 #endif
12875
12876 if (ffesymbol_storage (s) == NULL)
12877 return; /* Do nothing until COMMON/EQUIVALENCE
12878 possibilities checked. */
12879
12880 if ((ffesymbol_init (s) == NULL)
12881 && ((init = ffesymbol_accretion (s)) != NULL))
12882 {
12883 ffesymbol_set_accretion (s, NULL);
12884 ffesymbol_set_accretes (s, 0);
12885
12886 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12887 /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12888 size = ffebld_accter_size (init);
12889 ffebit_kill (ffebld_accter_bits (init));
12890 ffebld_set_op (init, FFEBLD_opARRTER);
12891 ffebld_set_arrter (init, ffebld_accter (init));
12892 ffebld_arrter_set_size (init, size);
12893 #endif
12894
12895 #if FFECOM_TWOPASS
12896 ffesymbol_set_init (s, init);
12897 #endif
12898 }
12899 #if FFECOM_ONEPASS
12900 else
12901 init = ffesymbol_init (s);
12902 #endif
12903
12904 #if FFECOM_ONEPASS
12905 ffesymbol_set_init (s, ffebld_new_any ());
12906
12907 if (ffebld_op (init) == FFEBLD_opANY)
12908 return; /* Oh, we already did this! */
12909
12910 #if FFECOM_targetCURRENT == FFECOM_targetFFE
12911 fprintf (dmpout, "= initialize_symbol \"%s\" ", ffesymbol_text (s));
12912 ffebld_dump (init);
12913 fputc ('\n', dmpout);
12914 #endif
12915
12916 #endif /* if FFECOM_ONEPASS */
12917 }
12918
12919 /* ffecom_notify_primary_entry -- Learn which is the primary entry point
12920
12921 ffesymbol s;
12922 ffecom_notify_primary_entry(s);
12923
12924 Gets called when implicit or explicit PROGRAM statement seen or when
12925 FUNCTION, SUBROUTINE, or BLOCK DATA statement seen, with the primary
12926 global symbol that serves as the entry point. */
12927
12928 void
12929 ffecom_notify_primary_entry (ffesymbol s)
12930 {
12931 ffecom_primary_entry_ = s;
12932 ffecom_primary_entry_kind_ = ffesymbol_kind (s);
12933
12934 if ((ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
12935 || (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE))
12936 ffecom_primary_entry_is_proc_ = TRUE;
12937 else
12938 ffecom_primary_entry_is_proc_ = FALSE;
12939
12940 if (!ffe_is_silent ())
12941 {
12942 if (ffecom_primary_entry_kind_ == FFEINFO_kindPROGRAM)
12943 fprintf (stderr, "%s:\n", ffesymbol_text (s));
12944 else
12945 fprintf (stderr, " %s:\n", ffesymbol_text (s));
12946 }
12947
12948 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12949 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
12950 {
12951 ffebld list;
12952 ffebld arg;
12953
12954 for (list = ffesymbol_dummyargs (s);
12955 list != NULL;
12956 list = ffebld_trail (list))
12957 {
12958 arg = ffebld_head (list);
12959 if (ffebld_op (arg) == FFEBLD_opSTAR)
12960 {
12961 ffecom_is_altreturning_ = TRUE;
12962 break;
12963 }
12964 }
12965 }
12966 #endif
12967 }
12968
12969 FILE *
12970 ffecom_open_include (char *name, ffewhereLine l, ffewhereColumn c)
12971 {
12972 #if FFECOM_GCC_INCLUDE
12973 return ffecom_open_include_ (name, l, c);
12974 #else
12975 return fopen (name, "r");
12976 #endif
12977 }
12978
12979 /* Clean up after making automatically popped call-arg temps.
12980
12981 Call this in pairs with push_calltemps around calls to
12982 ffecom_arg_ptr_to_expr if the latter might use temporaries.
12983 Any temporaries made within the outermost sequence of
12984 push_calltemps and pop_calltemps, that are marked as "auto-pop"
12985 meaning they won't be explicitly popped (freed), are popped
12986 at this point so they can be reused later.
12987
12988 NOTE: when called by ffecom_gen_sfuncdef_, ffecom_pending_calls_
12989 should come in == 1, and all of the in-use auto-pop temps
12990 should have DECL_CONTEXT (temp->t) == current_function_decl.
12991 Moreover, these temps should _never_ be re-used in future
12992 calls to ffecom_push_tempvar -- since current_function_decl will
12993 never be the same again.
12994
12995 SO, it could be a minor win in terms of compile time to just
12996 strip these temps off the list. That is, if the above assumptions
12997 are correct, just remove from the list of temps any temp
12998 that is both in-use and has DECL_CONTEXT (temp->t)
12999 == current_function_decl, when called from ffecom_gen_sfuncdef_. */
13000
13001 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13002 void
13003 ffecom_pop_calltemps ()
13004 {
13005 ffecomTemp_ temp;
13006
13007 assert (ffecom_pending_calls_ > 0);
13008
13009 if (--ffecom_pending_calls_ == 0)
13010 for (temp = ffecom_latest_temp_; temp != NULL; temp = temp->next)
13011 if (temp->auto_pop)
13012 temp->in_use = FALSE;
13013 }
13014
13015 #endif
13016 /* Mark latest temp with given tree as no longer in use. */
13017
13018 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13019 void
13020 ffecom_pop_tempvar (tree t)
13021 {
13022 ffecomTemp_ temp;
13023
13024 for (temp = ffecom_latest_temp_; temp != NULL; temp = temp->next)
13025 if (temp->in_use && (temp->t == t))
13026 {
13027 assert (!temp->auto_pop);
13028 temp->in_use = FALSE;
13029 return;
13030 }
13031 else
13032 assert (temp->t != t);
13033
13034 assert ("couldn't ffecom_pop_tempvar!" != NULL);
13035 }
13036
13037 #endif
13038 /* ffecom_ptr_to_expr -- Transform expr into gcc tree with & in front
13039
13040 tree t;
13041 ffebld expr; // FFE expression.
13042 tree = ffecom_ptr_to_expr(expr);
13043
13044 Like ffecom_expr, but sticks address-of in front of most things. */
13045
13046 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13047 tree
13048 ffecom_ptr_to_expr (ffebld expr)
13049 {
13050 tree item;
13051 ffeinfoBasictype bt;
13052 ffeinfoKindtype kt;
13053 ffesymbol s;
13054
13055 assert (expr != NULL);
13056
13057 switch (ffebld_op (expr))
13058 {
13059 case FFEBLD_opSYMTER:
13060 s = ffebld_symter (expr);
13061 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
13062 {
13063 ffecomGfrt ix;
13064
13065 ix = ffeintrin_gfrt_indirect (ffebld_symter_implementation (expr));
13066 assert (ix != FFECOM_gfrt);
13067 if ((item = ffecom_gfrt_[ix]) == NULL_TREE)
13068 {
13069 ffecom_make_gfrt_ (ix);
13070 item = ffecom_gfrt_[ix];
13071 }
13072 }
13073 else
13074 {
13075 item = ffesymbol_hook (s).decl_tree;
13076 if (item == NULL_TREE)
13077 {
13078 s = ffecom_sym_transform_ (s);
13079 item = ffesymbol_hook (s).decl_tree;
13080 }
13081 }
13082 assert (item != NULL);
13083 if (item == error_mark_node)
13084 return item;
13085 if (!ffesymbol_hook (s).addr)
13086 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
13087 item);
13088 return item;
13089
13090 case FFEBLD_opARRAYREF:
13091 {
13092 ffebld dims[FFECOM_dimensionsMAX];
13093 tree array;
13094 int i;
13095
13096 item = ffecom_ptr_to_expr (ffebld_left (expr));
13097
13098 if (item == error_mark_node)
13099 return item;
13100
13101 if ((ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereFLEETING)
13102 && !mark_addressable (item))
13103 return error_mark_node; /* Make sure non-const ref is to
13104 non-reg. */
13105
13106 /* Build up ARRAY_REFs in reverse order (since we're column major
13107 here in Fortran land). */
13108
13109 for (i = 0, expr = ffebld_right (expr);
13110 expr != NULL;
13111 expr = ffebld_trail (expr))
13112 dims[i++] = ffebld_head (expr);
13113
13114 for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
13115 i >= 0;
13116 --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
13117 {
13118 /* The initial subtraction should happen in the original type so
13119 that (possible) negative values are handled appropriately. */
13120 item
13121 = ffecom_2 (PLUS_EXPR,
13122 build_pointer_type (TREE_TYPE (array)),
13123 item,
13124 size_binop (MULT_EXPR,
13125 size_in_bytes (TREE_TYPE (array)),
13126 convert (sizetype,
13127 fold (build (MINUS_EXPR,
13128 TREE_TYPE (TYPE_MIN_VALUE (TYPE_DOMAIN (array))),
13129 ffecom_expr (dims[i]),
13130 TYPE_MIN_VALUE (TYPE_DOMAIN (array)))))));
13131 }
13132 }
13133 return item;
13134
13135 case FFEBLD_opCONTER:
13136
13137 bt = ffeinfo_basictype (ffebld_info (expr));
13138 kt = ffeinfo_kindtype (ffebld_info (expr));
13139
13140 item = ffecom_constantunion (&ffebld_constant_union
13141 (ffebld_conter (expr)), bt, kt,
13142 ffecom_tree_type[bt][kt]);
13143 if (item == error_mark_node)
13144 return error_mark_node;
13145 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
13146 item);
13147 return item;
13148
13149 case FFEBLD_opANY:
13150 return error_mark_node;
13151
13152 default:
13153 assert (ffecom_pending_calls_ > 0);
13154
13155 bt = ffeinfo_basictype (ffebld_info (expr));
13156 kt = ffeinfo_kindtype (ffebld_info (expr));
13157
13158 item = ffecom_expr (expr);
13159 if (item == error_mark_node)
13160 return error_mark_node;
13161
13162 /* The back end currently optimizes a bit too zealously for us, in that
13163 we fail JCB001 if the following block of code is omitted. It checks
13164 to see if the transformed expression is a symbol or array reference,
13165 and encloses it in a SAVE_EXPR if that is the case. */
13166
13167 STRIP_NOPS (item);
13168 if ((TREE_CODE (item) == VAR_DECL)
13169 || (TREE_CODE (item) == PARM_DECL)
13170 || (TREE_CODE (item) == RESULT_DECL)
13171 || (TREE_CODE (item) == INDIRECT_REF)
13172 || (TREE_CODE (item) == ARRAY_REF)
13173 || (TREE_CODE (item) == COMPONENT_REF)
13174 #ifdef OFFSET_REF
13175 || (TREE_CODE (item) == OFFSET_REF)
13176 #endif
13177 || (TREE_CODE (item) == BUFFER_REF)
13178 || (TREE_CODE (item) == REALPART_EXPR)
13179 || (TREE_CODE (item) == IMAGPART_EXPR))
13180 {
13181 item = ffecom_save_tree (item);
13182 }
13183
13184 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
13185 item);
13186 return item;
13187 }
13188
13189 assert ("fall-through error" == NULL);
13190 return error_mark_node;
13191 }
13192
13193 #endif
13194 /* Prepare to make call-arg temps.
13195
13196 Call this in pairs with pop_calltemps around calls to
13197 ffecom_arg_ptr_to_expr if the latter might use temporaries. */
13198
13199 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13200 void
13201 ffecom_push_calltemps ()
13202 {
13203 ffecom_pending_calls_++;
13204 }
13205
13206 #endif
13207 /* Obtain a temp var with given data type.
13208
13209 Returns a VAR_DECL tree of a currently (that is, at the current
13210 statement being compiled) not in use and having the given data type,
13211 making a new one if necessary. size is FFETARGET_charactersizeNONE
13212 for a non-CHARACTER type or >= 0 for a CHARACTER type. elements is
13213 -1 for a scalar or > 0 for an array of type. auto_pop is TRUE if
13214 ffecom_pop_tempvar won't be called, meaning temp will be freed
13215 when #pending calls goes to zero. */
13216
13217 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13218 tree
13219 ffecom_push_tempvar (tree type, ffetargetCharacterSize size, int elements,
13220 bool auto_pop)
13221 {
13222 ffecomTemp_ temp;
13223 int yes;
13224 tree t;
13225 static int mynumber;
13226
13227 assert (!auto_pop || (ffecom_pending_calls_ > 0));
13228
13229 if (type == error_mark_node)
13230 return error_mark_node;
13231
13232 for (temp = ffecom_latest_temp_; temp != NULL; temp = temp->next)
13233 {
13234 if (temp->in_use
13235 || (temp->type != type)
13236 || (temp->size != size)
13237 || (temp->elements != elements)
13238 || (DECL_CONTEXT (temp->t) != current_function_decl))
13239 continue;
13240
13241 temp->in_use = TRUE;
13242 temp->auto_pop = auto_pop;
13243 return temp->t;
13244 }
13245
13246 /* Create a new temp. */
13247
13248 yes = suspend_momentary ();
13249
13250 if (size != FFETARGET_charactersizeNONE)
13251 type = build_array_type (type,
13252 build_range_type (ffecom_f2c_ftnlen_type_node,
13253 ffecom_f2c_ftnlen_one_node,
13254 build_int_2 (size, 0)));
13255 if (elements != -1)
13256 type = build_array_type (type,
13257 build_range_type (integer_type_node,
13258 integer_zero_node,
13259 build_int_2 (elements - 1,
13260 0)));
13261 t = build_decl (VAR_DECL,
13262 ffecom_get_invented_identifier ("__g77_expr_%d", NULL,
13263 mynumber++),
13264 type);
13265 { /* ~~~~ kludge alert here!!! else temp gets reused outside
13266 a compound-statement sequence.... */
13267 extern tree sequence_rtl_expr;
13268 tree back_end_bug = sequence_rtl_expr;
13269
13270 sequence_rtl_expr = NULL_TREE;
13271
13272 t = start_decl (t, FALSE);
13273 finish_decl (t, NULL_TREE, FALSE);
13274
13275 sequence_rtl_expr = back_end_bug;
13276 }
13277
13278 resume_momentary (yes);
13279
13280 temp = malloc_new_kp (ffe_pool_program_unit (), "ffecomTemp_",
13281 sizeof (*temp));
13282
13283 temp->next = ffecom_latest_temp_;
13284 temp->type = type;
13285 temp->t = t;
13286 temp->size = size;
13287 temp->elements = elements;
13288 temp->in_use = TRUE;
13289 temp->auto_pop = auto_pop;
13290
13291 ffecom_latest_temp_ = temp;
13292
13293 return t;
13294 }
13295
13296 #endif
13297 /* ffecom_return_expr -- Returns return-value expr given alt return expr
13298
13299 tree rtn; // NULL_TREE means use expand_null_return()
13300 ffebld expr; // NULL if no alt return expr to RETURN stmt
13301 rtn = ffecom_return_expr(expr);
13302
13303 Based on the program unit type and other info (like return function
13304 type, return master function type when alternate ENTRY points,
13305 whether subroutine has any alternate RETURN points, etc), returns the
13306 appropriate expression to be returned to the caller, or NULL_TREE
13307 meaning no return value or the caller expects it to be returned somewhere
13308 else (which is handled by other parts of this module). */
13309
13310 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13311 tree
13312 ffecom_return_expr (ffebld expr)
13313 {
13314 tree rtn;
13315
13316 switch (ffecom_primary_entry_kind_)
13317 {
13318 case FFEINFO_kindPROGRAM:
13319 case FFEINFO_kindBLOCKDATA:
13320 rtn = NULL_TREE;
13321 break;
13322
13323 case FFEINFO_kindSUBROUTINE:
13324 if (!ffecom_is_altreturning_)
13325 rtn = NULL_TREE; /* No alt returns, never an expr. */
13326 else if (expr == NULL)
13327 rtn = integer_zero_node;
13328 else
13329 rtn = ffecom_expr (expr);
13330 break;
13331
13332 case FFEINFO_kindFUNCTION:
13333 if ((ffecom_multi_retval_ != NULL_TREE)
13334 || (ffesymbol_basictype (ffecom_primary_entry_)
13335 == FFEINFO_basictypeCHARACTER)
13336 || ((ffesymbol_basictype (ffecom_primary_entry_)
13337 == FFEINFO_basictypeCOMPLEX)
13338 && (ffecom_num_entrypoints_ == 0)
13339 && ffesymbol_is_f2c (ffecom_primary_entry_)))
13340 { /* Value is returned by direct assignment
13341 into (implicit) dummy. */
13342 rtn = NULL_TREE;
13343 break;
13344 }
13345 rtn = ffecom_func_result_;
13346 #if 0
13347 /* Spurious error if RETURN happens before first reference! So elide
13348 this code. In particular, for debugging registry, rtn should always
13349 be non-null after all, but TREE_USED won't be set until we encounter
13350 a reference in the code. Perfectly okay (but weird) code that,
13351 e.g., has "GOTO 20;10 RETURN;20 RTN=0;GOTO 10", would result in
13352 this diagnostic for no reason. Have people use -O -Wuninitialized
13353 and leave it to the back end to find obviously weird cases. */
13354
13355 /* Used to "assert(rtn != NULL_TREE);" here, but it's kind of a valid
13356 situation; if the return value has never been referenced, it won't
13357 have a tree under 2pass mode. */
13358 if ((rtn == NULL_TREE)
13359 || !TREE_USED (rtn))
13360 {
13361 ffebad_start (FFEBAD_RETURN_VALUE_UNSET);
13362 ffebad_here (0, ffesymbol_where_line (ffecom_primary_entry_),
13363 ffesymbol_where_column (ffecom_primary_entry_));
13364 ffebad_string (ffesymbol_text (ffesymbol_funcresult
13365 (ffecom_primary_entry_)));
13366 ffebad_finish ();
13367 }
13368 #endif
13369 break;
13370
13371 default:
13372 assert ("bad unit kind" == NULL);
13373 case FFEINFO_kindANY:
13374 rtn = error_mark_node;
13375 break;
13376 }
13377
13378 return rtn;
13379 }
13380
13381 #endif
13382 /* Do save_expr only if tree is not error_mark_node. */
13383
13384 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13385 tree
13386 ffecom_save_tree (tree t)
13387 {
13388 return save_expr (t);
13389 }
13390 #endif
13391
13392 /* Public entry point for front end to access start_decl. */
13393
13394 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13395 tree
13396 ffecom_start_decl (tree decl, bool is_initialized)
13397 {
13398 DECL_INITIAL (decl) = is_initialized ? error_mark_node : NULL_TREE;
13399 return start_decl (decl, FALSE);
13400 }
13401
13402 #endif
13403 /* ffecom_sym_commit -- Symbol's state being committed to reality
13404
13405 ffesymbol s;
13406 ffecom_sym_commit(s);
13407
13408 Does whatever the backend needs when a symbol is committed after having
13409 been backtrackable for a period of time. */
13410
13411 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13412 void
13413 ffecom_sym_commit (ffesymbol s UNUSED)
13414 {
13415 assert (!ffesymbol_retractable ());
13416 }
13417
13418 #endif
13419 /* ffecom_sym_end_transition -- Perform end transition on all symbols
13420
13421 ffecom_sym_end_transition();
13422
13423 Does backend-specific stuff and also calls ffest_sym_end_transition
13424 to do the necessary FFE stuff.
13425
13426 Backtracking is never enabled when this fn is called, so don't worry
13427 about it. */
13428
13429 ffesymbol
13430 ffecom_sym_end_transition (ffesymbol s)
13431 {
13432 ffestorag st;
13433
13434 assert (!ffesymbol_retractable ());
13435
13436 s = ffest_sym_end_transition (s);
13437
13438 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13439 if ((ffesymbol_kind (s) == FFEINFO_kindBLOCKDATA)
13440 && (ffesymbol_where (s) == FFEINFO_whereGLOBAL))
13441 {
13442 ffecom_list_blockdata_
13443 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13444 FFEINTRIN_specNONE,
13445 FFEINTRIN_impNONE),
13446 ffecom_list_blockdata_);
13447 }
13448 #endif
13449
13450 /* This is where we finally notice that a symbol has partial initialization
13451 and finalize it. */
13452
13453 if (ffesymbol_accretion (s) != NULL)
13454 {
13455 assert (ffesymbol_init (s) == NULL);
13456 ffecom_notify_init_symbol (s);
13457 }
13458 else if (((st = ffesymbol_storage (s)) != NULL)
13459 && ((st = ffestorag_parent (st)) != NULL)
13460 && (ffestorag_accretion (st) != NULL))
13461 {
13462 assert (ffestorag_init (st) == NULL);
13463 ffecom_notify_init_storage (st);
13464 }
13465
13466 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13467 if ((ffesymbol_kind (s) == FFEINFO_kindCOMMON)
13468 && (ffesymbol_where (s) == FFEINFO_whereLOCAL)
13469 && (ffesymbol_storage (s) != NULL))
13470 {
13471 ffecom_list_common_
13472 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13473 FFEINTRIN_specNONE,
13474 FFEINTRIN_impNONE),
13475 ffecom_list_common_);
13476 }
13477 #endif
13478
13479 return s;
13480 }
13481
13482 /* ffecom_sym_exec_transition -- Perform exec transition on all symbols
13483
13484 ffecom_sym_exec_transition();
13485
13486 Does backend-specific stuff and also calls ffest_sym_exec_transition
13487 to do the necessary FFE stuff.
13488
13489 See the long-winded description in ffecom_sym_learned for info
13490 on handling the situation where backtracking is inhibited. */
13491
13492 ffesymbol
13493 ffecom_sym_exec_transition (ffesymbol s)
13494 {
13495 s = ffest_sym_exec_transition (s);
13496
13497 return s;
13498 }
13499
13500 /* ffecom_sym_learned -- Initial or more info gained on symbol after exec
13501
13502 ffesymbol s;
13503 s = ffecom_sym_learned(s);
13504
13505 Called when a new symbol is seen after the exec transition or when more
13506 info (perhaps) is gained for an UNCERTAIN symbol. The symbol state when
13507 it arrives here is that all its latest info is updated already, so its
13508 state may be UNCERTAIN or UNDERSTOOD, it might already have the hook
13509 field filled in if its gone through here or exec_transition first, and
13510 so on.
13511
13512 The backend probably wants to check ffesymbol_retractable() to see if
13513 backtracking is in effect. If so, the FFE's changes to the symbol may
13514 be retracted (undone) or committed (ratified), at which time the
13515 appropriate ffecom_sym_retract or _commit function will be called
13516 for that function.
13517
13518 If the backend has its own backtracking mechanism, great, use it so that
13519 committal is a simple operation. Though it doesn't make much difference,
13520 I suppose: the reason for tentative symbol evolution in the FFE is to
13521 enable error detection in weird incorrect statements early and to disable
13522 incorrect error detection on a correct statement. The backend is not
13523 likely to introduce any information that'll get involved in these
13524 considerations, so it is probably just fine that the implementation
13525 model for this fn and for _exec_transition is to not do anything
13526 (besides the required FFE stuff) if ffesymbol_retractable() returns TRUE
13527 and instead wait until ffecom_sym_commit is called (which it never
13528 will be as long as we're using ambiguity-detecting statement analysis in
13529 the FFE, which we are initially to shake out the code, but don't depend
13530 on this), otherwise go ahead and do whatever is needed.
13531
13532 In essence, then, when this fn and _exec_transition get called while
13533 backtracking is enabled, a general mechanism would be to flag which (or
13534 both) of these were called (and in what order? neat question as to what
13535 might happen that I'm too lame to think through right now) and then when
13536 _commit is called reproduce the original calling sequence, if any, for
13537 the two fns (at which point backtracking will, of course, be disabled). */
13538
13539 ffesymbol
13540 ffecom_sym_learned (ffesymbol s)
13541 {
13542 ffestorag_exec_layout (s);
13543
13544 return s;
13545 }
13546
13547 /* ffecom_sym_retract -- Symbol's state being retracted from reality
13548
13549 ffesymbol s;
13550 ffecom_sym_retract(s);
13551
13552 Does whatever the backend needs when a symbol is retracted after having
13553 been backtrackable for a period of time. */
13554
13555 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13556 void
13557 ffecom_sym_retract (ffesymbol s UNUSED)
13558 {
13559 assert (!ffesymbol_retractable ());
13560
13561 #if 0 /* GCC doesn't commit any backtrackable sins,
13562 so nothing needed here. */
13563 switch (ffesymbol_hook (s).state)
13564 {
13565 case 0: /* nothing happened yet. */
13566 break;
13567
13568 case 1: /* exec transition happened. */
13569 break;
13570
13571 case 2: /* learned happened. */
13572 break;
13573
13574 case 3: /* learned then exec. */
13575 break;
13576
13577 case 4: /* exec then learned. */
13578 break;
13579
13580 default:
13581 assert ("bad hook state" == NULL);
13582 break;
13583 }
13584 #endif
13585 }
13586
13587 #endif
13588 /* Create temporary gcc label. */
13589
13590 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13591 tree
13592 ffecom_temp_label ()
13593 {
13594 tree glabel;
13595 static int mynumber = 0;
13596
13597 glabel = build_decl (LABEL_DECL,
13598 ffecom_get_invented_identifier ("__g77_label_%d",
13599 NULL,
13600 mynumber++),
13601 void_type_node);
13602 DECL_CONTEXT (glabel) = current_function_decl;
13603 DECL_MODE (glabel) = VOIDmode;
13604
13605 return glabel;
13606 }
13607
13608 #endif
13609 /* Return an expression that is usable as an arg in a conditional context
13610 (IF, DO WHILE, .NOT., and so on).
13611
13612 Use the one provided for the back end as of >2.6.0. */
13613
13614 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13615 tree
13616 ffecom_truth_value (tree expr)
13617 {
13618 return truthvalue_conversion (expr);
13619 }
13620
13621 #endif
13622 /* Return the inversion of a truth value (the inversion of what
13623 ffecom_truth_value builds).
13624
13625 Apparently invert_truthvalue, which is properly in the back end, is
13626 enough for now, so just use it. */
13627
13628 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13629 tree
13630 ffecom_truth_value_invert (tree expr)
13631 {
13632 return invert_truthvalue (ffecom_truth_value (expr));
13633 }
13634
13635 #endif
13636 /* Return PARM_DECL for arg#1 of master fn containing alternate ENTRY points
13637
13638 If the PARM_DECL already exists, return it, else create it. It's an
13639 integer_type_node argument for the master function that implements a
13640 subroutine or function with more than one entrypoint and is bound at
13641 run time with the entrypoint number (0 for SUBROUTINE/FUNCTION, 1 for
13642 first ENTRY statement, and so on). */
13643
13644 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13645 tree
13646 ffecom_which_entrypoint_decl ()
13647 {
13648 assert (ffecom_which_entrypoint_decl_ != NULL_TREE);
13649
13650 return ffecom_which_entrypoint_decl_;
13651 }
13652
13653 #endif
13654 \f
13655 /* The following sections consists of private and public functions
13656 that have the same names and perform roughly the same functions
13657 as counterparts in the C front end. Changes in the C front end
13658 might affect how things should be done here. Only functions
13659 needed by the back end should be public here; the rest should
13660 be private (static in the C sense). Functions needed by other
13661 g77 front-end modules should be accessed by them via public
13662 ffecom_* names, which should themselves call private versions
13663 in this section so the private versions are easy to recognize
13664 when upgrading to a new gcc and finding interesting changes
13665 in the front end.
13666
13667 Functions named after rule "foo:" in c-parse.y are named
13668 "bison_rule_foo_" so they are easy to find. */
13669
13670 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13671
13672 static void
13673 bison_rule_compstmt_ ()
13674 {
13675 emit_line_note (input_filename, lineno);
13676 expand_end_bindings (getdecls (), 1, 1);
13677 poplevel (1, 1, 0);
13678 pop_momentary ();
13679 }
13680
13681 static void
13682 bison_rule_pushlevel_ ()
13683 {
13684 emit_line_note (input_filename, lineno);
13685 pushlevel (0);
13686 clear_last_expr ();
13687 push_momentary ();
13688 expand_start_bindings (0);
13689 }
13690
13691 /* Return a definition for a builtin function named NAME and whose data type
13692 is TYPE. TYPE should be a function type with argument types.
13693 FUNCTION_CODE tells later passes how to compile calls to this function.
13694 See tree.h for its possible values.
13695
13696 If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
13697 the name to be called if we can't opencode the function. */
13698
13699 static tree
13700 builtin_function (char *name, tree type,
13701 enum built_in_function function_code, char *library_name)
13702 {
13703 tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
13704 DECL_EXTERNAL (decl) = 1;
13705 TREE_PUBLIC (decl) = 1;
13706 if (library_name)
13707 DECL_ASSEMBLER_NAME (decl) = get_identifier (library_name);
13708 make_decl_rtl (decl, NULL_PTR, 1);
13709 pushdecl (decl);
13710 if (function_code != NOT_BUILT_IN)
13711 {
13712 DECL_BUILT_IN (decl) = 1;
13713 DECL_FUNCTION_CODE (decl) = function_code;
13714 }
13715
13716 return decl;
13717 }
13718
13719 /* Handle when a new declaration NEWDECL
13720 has the same name as an old one OLDDECL
13721 in the same binding contour.
13722 Prints an error message if appropriate.
13723
13724 If safely possible, alter OLDDECL to look like NEWDECL, and return 1.
13725 Otherwise, return 0. */
13726
13727 static int
13728 duplicate_decls (tree newdecl, tree olddecl)
13729 {
13730 int types_match = 1;
13731 int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
13732 && DECL_INITIAL (newdecl) != 0);
13733 tree oldtype = TREE_TYPE (olddecl);
13734 tree newtype = TREE_TYPE (newdecl);
13735
13736 if (olddecl == newdecl)
13737 return 1;
13738
13739 if (TREE_CODE (newtype) == ERROR_MARK
13740 || TREE_CODE (oldtype) == ERROR_MARK)
13741 types_match = 0;
13742
13743 /* New decl is completely inconsistent with the old one =>
13744 tell caller to replace the old one.
13745 This is always an error except in the case of shadowing a builtin. */
13746 if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
13747 return 0;
13748
13749 /* For real parm decl following a forward decl,
13750 return 1 so old decl will be reused. */
13751 if (types_match && TREE_CODE (newdecl) == PARM_DECL
13752 && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
13753 return 1;
13754
13755 /* The new declaration is the same kind of object as the old one.
13756 The declarations may partially match. Print warnings if they don't
13757 match enough. Ultimately, copy most of the information from the new
13758 decl to the old one, and keep using the old one. */
13759
13760 if (TREE_CODE (olddecl) == FUNCTION_DECL
13761 && DECL_BUILT_IN (olddecl))
13762 {
13763 /* A function declaration for a built-in function. */
13764 if (!TREE_PUBLIC (newdecl))
13765 return 0;
13766 else if (!types_match)
13767 {
13768 /* Accept the return type of the new declaration if same modes. */
13769 tree oldreturntype = TREE_TYPE (TREE_TYPE (olddecl));
13770 tree newreturntype = TREE_TYPE (TREE_TYPE (newdecl));
13771
13772 /* Make sure we put the new type in the same obstack as the old ones.
13773 If the old types are not both in the same obstack, use the
13774 permanent one. */
13775 if (TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (newtype))
13776 push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
13777 else
13778 {
13779 push_obstacks_nochange ();
13780 end_temporary_allocation ();
13781 }
13782
13783 if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
13784 {
13785 /* Function types may be shared, so we can't just modify
13786 the return type of olddecl's function type. */
13787 tree newtype
13788 = build_function_type (newreturntype,
13789 TYPE_ARG_TYPES (TREE_TYPE (olddecl)));
13790
13791 types_match = 1;
13792 if (types_match)
13793 TREE_TYPE (olddecl) = newtype;
13794 }
13795
13796 pop_obstacks ();
13797 }
13798 if (!types_match)
13799 return 0;
13800 }
13801 else if (TREE_CODE (olddecl) == FUNCTION_DECL
13802 && DECL_SOURCE_LINE (olddecl) == 0)
13803 {
13804 /* A function declaration for a predeclared function
13805 that isn't actually built in. */
13806 if (!TREE_PUBLIC (newdecl))
13807 return 0;
13808 else if (!types_match)
13809 {
13810 /* If the types don't match, preserve volatility indication.
13811 Later on, we will discard everything else about the
13812 default declaration. */
13813 TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
13814 }
13815 }
13816
13817 /* Copy all the DECL_... slots specified in the new decl
13818 except for any that we copy here from the old type.
13819
13820 Past this point, we don't change OLDTYPE and NEWTYPE
13821 even if we change the types of NEWDECL and OLDDECL. */
13822
13823 if (types_match)
13824 {
13825 /* Make sure we put the new type in the same obstack as the old ones.
13826 If the old types are not both in the same obstack, use the permanent
13827 one. */
13828 if (TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (newtype))
13829 push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
13830 else
13831 {
13832 push_obstacks_nochange ();
13833 end_temporary_allocation ();
13834 }
13835
13836 /* Merge the data types specified in the two decls. */
13837 if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
13838 TREE_TYPE (newdecl)
13839 = TREE_TYPE (olddecl)
13840 = TREE_TYPE (newdecl);
13841
13842 /* Lay the type out, unless already done. */
13843 if (oldtype != TREE_TYPE (newdecl))
13844 {
13845 if (TREE_TYPE (newdecl) != error_mark_node)
13846 layout_type (TREE_TYPE (newdecl));
13847 if (TREE_CODE (newdecl) != FUNCTION_DECL
13848 && TREE_CODE (newdecl) != TYPE_DECL
13849 && TREE_CODE (newdecl) != CONST_DECL)
13850 layout_decl (newdecl, 0);
13851 }
13852 else
13853 {
13854 /* Since the type is OLDDECL's, make OLDDECL's size go with. */
13855 DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
13856 if (TREE_CODE (olddecl) != FUNCTION_DECL)
13857 if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
13858 DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
13859 }
13860
13861 /* Keep the old rtl since we can safely use it. */
13862 DECL_RTL (newdecl) = DECL_RTL (olddecl);
13863
13864 /* Merge the type qualifiers. */
13865 if (DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl)
13866 && !TREE_THIS_VOLATILE (newdecl))
13867 TREE_THIS_VOLATILE (olddecl) = 0;
13868 if (TREE_READONLY (newdecl))
13869 TREE_READONLY (olddecl) = 1;
13870 if (TREE_THIS_VOLATILE (newdecl))
13871 {
13872 TREE_THIS_VOLATILE (olddecl) = 1;
13873 if (TREE_CODE (newdecl) == VAR_DECL)
13874 make_var_volatile (newdecl);
13875 }
13876
13877 /* Keep source location of definition rather than declaration.
13878 Likewise, keep decl at outer scope. */
13879 if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
13880 || (DECL_CONTEXT (newdecl) != 0 && DECL_CONTEXT (olddecl) == 0))
13881 {
13882 DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
13883 DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl);
13884
13885 if (DECL_CONTEXT (olddecl) == 0
13886 && TREE_CODE (newdecl) != FUNCTION_DECL)
13887 DECL_CONTEXT (newdecl) = 0;
13888 }
13889
13890 /* Merge the unused-warning information. */
13891 if (DECL_IN_SYSTEM_HEADER (olddecl))
13892 DECL_IN_SYSTEM_HEADER (newdecl) = 1;
13893 else if (DECL_IN_SYSTEM_HEADER (newdecl))
13894 DECL_IN_SYSTEM_HEADER (olddecl) = 1;
13895
13896 /* Merge the initialization information. */
13897 if (DECL_INITIAL (newdecl) == 0)
13898 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
13899
13900 /* Merge the section attribute.
13901 We want to issue an error if the sections conflict but that must be
13902 done later in decl_attributes since we are called before attributes
13903 are assigned. */
13904 if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
13905 DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
13906
13907 #if BUILT_FOR_270
13908 if (TREE_CODE (newdecl) == FUNCTION_DECL)
13909 {
13910 DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
13911 DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
13912 }
13913 #endif
13914
13915 pop_obstacks ();
13916 }
13917 /* If cannot merge, then use the new type and qualifiers,
13918 and don't preserve the old rtl. */
13919 else
13920 {
13921 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
13922 TREE_READONLY (olddecl) = TREE_READONLY (newdecl);
13923 TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl);
13924 TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl);
13925 }
13926
13927 /* Merge the storage class information. */
13928 /* For functions, static overrides non-static. */
13929 if (TREE_CODE (newdecl) == FUNCTION_DECL)
13930 {
13931 TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
13932 /* This is since we don't automatically
13933 copy the attributes of NEWDECL into OLDDECL. */
13934 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
13935 /* If this clears `static', clear it in the identifier too. */
13936 if (! TREE_PUBLIC (olddecl))
13937 TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
13938 }
13939 if (DECL_EXTERNAL (newdecl))
13940 {
13941 TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
13942 DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
13943 /* An extern decl does not override previous storage class. */
13944 TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
13945 }
13946 else
13947 {
13948 TREE_STATIC (olddecl) = TREE_STATIC (newdecl);
13949 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
13950 }
13951
13952 /* If either decl says `inline', this fn is inline,
13953 unless its definition was passed already. */
13954 if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
13955 DECL_INLINE (olddecl) = 1;
13956 DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
13957
13958 /* Get rid of any built-in function if new arg types don't match it
13959 or if we have a function definition. */
13960 if (TREE_CODE (newdecl) == FUNCTION_DECL
13961 && DECL_BUILT_IN (olddecl)
13962 && (!types_match || new_is_definition))
13963 {
13964 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
13965 DECL_BUILT_IN (olddecl) = 0;
13966 }
13967
13968 /* If redeclaring a builtin function, and not a definition,
13969 it stays built in.
13970 Also preserve various other info from the definition. */
13971 if (TREE_CODE (newdecl) == FUNCTION_DECL && !new_is_definition)
13972 {
13973 if (DECL_BUILT_IN (olddecl))
13974 {
13975 DECL_BUILT_IN (newdecl) = 1;
13976 DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
13977 }
13978 else
13979 DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl);
13980
13981 DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
13982 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
13983 DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
13984 DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
13985 }
13986
13987 /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
13988 But preserve olddecl's DECL_UID. */
13989 {
13990 register unsigned olddecl_uid = DECL_UID (olddecl);
13991
13992 memcpy ((char *) olddecl + sizeof (struct tree_common),
13993 (char *) newdecl + sizeof (struct tree_common),
13994 sizeof (struct tree_decl) - sizeof (struct tree_common));
13995 DECL_UID (olddecl) = olddecl_uid;
13996 }
13997
13998 return 1;
13999 }
14000
14001 /* Finish processing of a declaration;
14002 install its initial value.
14003 If the length of an array type is not known before,
14004 it must be determined now, from the initial value, or it is an error. */
14005
14006 static void
14007 finish_decl (tree decl, tree init, bool is_top_level)
14008 {
14009 register tree type = TREE_TYPE (decl);
14010 int was_incomplete = (DECL_SIZE (decl) == 0);
14011 int temporary = allocation_temporary_p ();
14012 bool at_top_level = (current_binding_level == global_binding_level);
14013 bool top_level = is_top_level || at_top_level;
14014
14015 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
14016 level anyway. */
14017 assert (!is_top_level || !at_top_level);
14018
14019 if (TREE_CODE (decl) == PARM_DECL)
14020 assert (init == NULL_TREE);
14021 /* Remember that PARM_DECL doesn't have a DECL_INITIAL field per se -- it
14022 overlaps DECL_ARG_TYPE. */
14023 else if (init == NULL_TREE)
14024 assert (DECL_INITIAL (decl) == NULL_TREE);
14025 else
14026 assert (DECL_INITIAL (decl) == error_mark_node);
14027
14028 if (init != NULL_TREE)
14029 {
14030 if (TREE_CODE (decl) != TYPE_DECL)
14031 DECL_INITIAL (decl) = init;
14032 else
14033 {
14034 /* typedef foo = bar; store the type of bar as the type of foo. */
14035 TREE_TYPE (decl) = TREE_TYPE (init);
14036 DECL_INITIAL (decl) = init = 0;
14037 }
14038 }
14039
14040 /* Pop back to the obstack that is current for this binding level. This is
14041 because MAXINDEX, rtl, etc. to be made below must go in the permanent
14042 obstack. But don't discard the temporary data yet. */
14043 pop_obstacks ();
14044
14045 /* Deduce size of array from initialization, if not already known */
14046
14047 if (TREE_CODE (type) == ARRAY_TYPE
14048 && TYPE_DOMAIN (type) == 0
14049 && TREE_CODE (decl) != TYPE_DECL)
14050 {
14051 assert (top_level);
14052 assert (was_incomplete);
14053
14054 layout_decl (decl, 0);
14055 }
14056
14057 if (TREE_CODE (decl) == VAR_DECL)
14058 {
14059 if (DECL_SIZE (decl) == NULL_TREE
14060 && TYPE_SIZE (TREE_TYPE (decl)) != NULL_TREE)
14061 layout_decl (decl, 0);
14062
14063 if (DECL_SIZE (decl) == NULL_TREE
14064 && (TREE_STATIC (decl)
14065 ?
14066 /* A static variable with an incomplete type is an error if it is
14067 initialized. Also if it is not file scope. Otherwise, let it
14068 through, but if it is not `extern' then it may cause an error
14069 message later. */
14070 (DECL_INITIAL (decl) != 0 || DECL_CONTEXT (decl) != 0)
14071 :
14072 /* An automatic variable with an incomplete type is an error. */
14073 !DECL_EXTERNAL (decl)))
14074 {
14075 assert ("storage size not known" == NULL);
14076 abort ();
14077 }
14078
14079 if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
14080 && (DECL_SIZE (decl) != 0)
14081 && (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST))
14082 {
14083 assert ("storage size not constant" == NULL);
14084 abort ();
14085 }
14086 }
14087
14088 /* Output the assembler code and/or RTL code for variables and functions,
14089 unless the type is an undefined structure or union. If not, it will get
14090 done when the type is completed. */
14091
14092 if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
14093 {
14094 rest_of_decl_compilation (decl, NULL,
14095 DECL_CONTEXT (decl) == 0,
14096 0);
14097
14098 if (DECL_CONTEXT (decl) != 0)
14099 {
14100 /* Recompute the RTL of a local array now if it used to be an
14101 incomplete type. */
14102 if (was_incomplete
14103 && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
14104 {
14105 /* If we used it already as memory, it must stay in memory. */
14106 TREE_ADDRESSABLE (decl) = TREE_USED (decl);
14107 /* If it's still incomplete now, no init will save it. */
14108 if (DECL_SIZE (decl) == 0)
14109 DECL_INITIAL (decl) = 0;
14110 expand_decl (decl);
14111 }
14112 /* Compute and store the initial value. */
14113 if (TREE_CODE (decl) != FUNCTION_DECL)
14114 expand_decl_init (decl);
14115 }
14116 }
14117 else if (TREE_CODE (decl) == TYPE_DECL)
14118 {
14119 rest_of_decl_compilation (decl, NULL_PTR,
14120 DECL_CONTEXT (decl) == 0,
14121 0);
14122 }
14123
14124 /* This test used to include TREE_PERMANENT, however, we have the same
14125 problem with initializers at the function level. Such initializers get
14126 saved until the end of the function on the momentary_obstack. */
14127 if (!(TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))
14128 && temporary
14129 /* DECL_INITIAL is not defined in PARM_DECLs, since it shares space with
14130 DECL_ARG_TYPE. */
14131 && TREE_CODE (decl) != PARM_DECL)
14132 {
14133 /* We need to remember that this array HAD an initialization, but
14134 discard the actual temporary nodes, since we can't have a permanent
14135 node keep pointing to them. */
14136 /* We make an exception for inline functions, since it's normal for a
14137 local extern redeclaration of an inline function to have a copy of
14138 the top-level decl's DECL_INLINE. */
14139 if ((DECL_INITIAL (decl) != 0)
14140 && (DECL_INITIAL (decl) != error_mark_node))
14141 {
14142 /* If this is a const variable, then preserve the
14143 initializer instead of discarding it so that we can optimize
14144 references to it. */
14145 /* This test used to include TREE_STATIC, but this won't be set
14146 for function level initializers. */
14147 if (TREE_READONLY (decl))
14148 {
14149 preserve_initializer ();
14150 /* Hack? Set the permanent bit for something that is
14151 permanent, but not on the permenent obstack, so as to
14152 convince output_constant_def to make its rtl on the
14153 permanent obstack. */
14154 TREE_PERMANENT (DECL_INITIAL (decl)) = 1;
14155
14156 /* The initializer and DECL must have the same (or equivalent
14157 types), but if the initializer is a STRING_CST, its type
14158 might not be on the right obstack, so copy the type
14159 of DECL. */
14160 TREE_TYPE (DECL_INITIAL (decl)) = type;
14161 }
14162 else
14163 DECL_INITIAL (decl) = error_mark_node;
14164 }
14165 }
14166
14167 /* If requested, warn about definitions of large data objects. */
14168
14169 if (warn_larger_than
14170 && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
14171 && !DECL_EXTERNAL (decl))
14172 {
14173 register tree decl_size = DECL_SIZE (decl);
14174
14175 if (decl_size && TREE_CODE (decl_size) == INTEGER_CST)
14176 {
14177 unsigned units = TREE_INT_CST_LOW (decl_size) / BITS_PER_UNIT;
14178
14179 if (units > larger_than_size)
14180 warning_with_decl (decl, "size of `%s' is %u bytes", units);
14181 }
14182 }
14183
14184 /* If we have gone back from temporary to permanent allocation, actually
14185 free the temporary space that we no longer need. */
14186 if (temporary && !allocation_temporary_p ())
14187 permanent_allocation (0);
14188
14189 /* At the end of a declaration, throw away any variable type sizes of types
14190 defined inside that declaration. There is no use computing them in the
14191 following function definition. */
14192 if (current_binding_level == global_binding_level)
14193 get_pending_sizes ();
14194 }
14195
14196 /* Finish up a function declaration and compile that function
14197 all the way to assembler language output. The free the storage
14198 for the function definition.
14199
14200 This is called after parsing the body of the function definition.
14201
14202 NESTED is nonzero if the function being finished is nested in another. */
14203
14204 static void
14205 finish_function (int nested)
14206 {
14207 register tree fndecl = current_function_decl;
14208
14209 assert (fndecl != NULL_TREE);
14210 if (TREE_CODE (fndecl) != ERROR_MARK)
14211 {
14212 if (nested)
14213 assert (DECL_CONTEXT (fndecl) != NULL_TREE);
14214 else
14215 assert (DECL_CONTEXT (fndecl) == NULL_TREE);
14216 }
14217
14218 /* TREE_READONLY (fndecl) = 1;
14219 This caused &foo to be of type ptr-to-const-function
14220 which then got a warning when stored in a ptr-to-function variable. */
14221
14222 poplevel (1, 0, 1);
14223
14224 if (TREE_CODE (fndecl) != ERROR_MARK)
14225 {
14226 BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
14227
14228 /* Must mark the RESULT_DECL as being in this function. */
14229
14230 DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
14231
14232 /* Obey `register' declarations if `setjmp' is called in this fn. */
14233 /* Generate rtl for function exit. */
14234 expand_function_end (input_filename, lineno, 0);
14235
14236 /* So we can tell if jump_optimize sets it to 1. */
14237 can_reach_end = 0;
14238
14239 /* Run the optimizers and output the assembler code for this function. */
14240 rest_of_compilation (fndecl);
14241 }
14242
14243 /* Free all the tree nodes making up this function. */
14244 /* Switch back to allocating nodes permanently until we start another
14245 function. */
14246 if (!nested)
14247 permanent_allocation (1);
14248
14249 if (DECL_SAVED_INSNS (fndecl) == 0 && !nested && (TREE_CODE (fndecl) != ERROR_MARK))
14250 {
14251 /* Stop pointing to the local nodes about to be freed. */
14252 /* But DECL_INITIAL must remain nonzero so we know this was an actual
14253 function definition. */
14254 /* For a nested function, this is done in pop_f_function_context. */
14255 /* If rest_of_compilation set this to 0, leave it 0. */
14256 if (DECL_INITIAL (fndecl) != 0)
14257 DECL_INITIAL (fndecl) = error_mark_node;
14258 DECL_ARGUMENTS (fndecl) = 0;
14259 }
14260
14261 if (!nested)
14262 {
14263 /* Let the error reporting routines know that we're outside a function.
14264 For a nested function, this value is used in pop_c_function_context
14265 and then reset via pop_function_context. */
14266 ffecom_outer_function_decl_ = current_function_decl = NULL;
14267 }
14268 }
14269
14270 /* Plug-in replacement for identifying the name of a decl and, for a
14271 function, what we call it in diagnostics. For now, "program unit"
14272 should suffice, since it's a bit of a hassle to figure out which
14273 of several kinds of things it is. Note that it could conceivably
14274 be a statement function, which probably isn't really a program unit
14275 per se, but if that comes up, it should be easy to check (being a
14276 nested function and all). */
14277
14278 static char *
14279 lang_printable_name (tree decl, int v)
14280 {
14281 /* Just to keep GCC quiet about the unused variable.
14282 In theory, differing values of V should produce different
14283 output. */
14284 switch (v)
14285 {
14286 default:
14287 if (TREE_CODE (decl) == ERROR_MARK)
14288 return "erroneous code";
14289 return IDENTIFIER_POINTER (DECL_NAME (decl));
14290 }
14291 }
14292
14293 /* g77's function to print out name of current function that caused
14294 an error. */
14295
14296 #if BUILT_FOR_270
14297 void
14298 lang_print_error_function (file)
14299 char *file;
14300 {
14301 static ffeglobal last_g = NULL;
14302 static ffesymbol last_s = NULL;
14303 ffeglobal g;
14304 ffesymbol s;
14305 char *kind;
14306
14307 if ((ffecom_primary_entry_ == NULL)
14308 || (ffesymbol_global (ffecom_primary_entry_) == NULL))
14309 {
14310 g = NULL;
14311 s = NULL;
14312 kind = NULL;
14313 }
14314 else
14315 {
14316 g = ffesymbol_global (ffecom_primary_entry_);
14317 if (ffecom_nested_entry_ == NULL)
14318 {
14319 s = ffecom_primary_entry_;
14320 switch (ffesymbol_kind (s))
14321 {
14322 case FFEINFO_kindFUNCTION:
14323 kind = "function";
14324 break;
14325
14326 case FFEINFO_kindSUBROUTINE:
14327 kind = "subroutine";
14328 break;
14329
14330 case FFEINFO_kindPROGRAM:
14331 kind = "program";
14332 break;
14333
14334 case FFEINFO_kindBLOCKDATA:
14335 kind = "block-data";
14336 break;
14337
14338 default:
14339 kind = ffeinfo_kind_message (ffesymbol_kind (s));
14340 break;
14341 }
14342 }
14343 else
14344 {
14345 s = ffecom_nested_entry_;
14346 kind = "statement function";
14347 }
14348 }
14349
14350 if ((last_g != g) || (last_s != s))
14351 {
14352 if (file)
14353 fprintf (stderr, "%s: ", file);
14354
14355 if (s == NULL)
14356 fprintf (stderr, "Outside of any program unit:\n");
14357 else
14358 {
14359 char *name = ffesymbol_text (s);
14360
14361 fprintf (stderr, "In %s `%s':\n", kind, name);
14362 }
14363
14364 last_g = g;
14365 last_s = s;
14366 }
14367 }
14368 #endif
14369
14370 /* Similar to `lookup_name' but look only at current binding level. */
14371
14372 static tree
14373 lookup_name_current_level (tree name)
14374 {
14375 register tree t;
14376
14377 if (current_binding_level == global_binding_level)
14378 return IDENTIFIER_GLOBAL_VALUE (name);
14379
14380 if (IDENTIFIER_LOCAL_VALUE (name) == 0)
14381 return 0;
14382
14383 for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
14384 if (DECL_NAME (t) == name)
14385 break;
14386
14387 return t;
14388 }
14389
14390 /* Create a new `struct binding_level'. */
14391
14392 static struct binding_level *
14393 make_binding_level ()
14394 {
14395 /* NOSTRICT */
14396 return (struct binding_level *) xmalloc (sizeof (struct binding_level));
14397 }
14398
14399 /* Save and restore the variables in this file and elsewhere
14400 that keep track of the progress of compilation of the current function.
14401 Used for nested functions. */
14402
14403 struct f_function
14404 {
14405 struct f_function *next;
14406 tree named_labels;
14407 tree shadowed_labels;
14408 struct binding_level *binding_level;
14409 };
14410
14411 struct f_function *f_function_chain;
14412
14413 /* Restore the variables used during compilation of a C function. */
14414
14415 static void
14416 pop_f_function_context ()
14417 {
14418 struct f_function *p = f_function_chain;
14419 tree link;
14420
14421 /* Bring back all the labels that were shadowed. */
14422 for (link = shadowed_labels; link; link = TREE_CHAIN (link))
14423 if (DECL_NAME (TREE_VALUE (link)) != 0)
14424 IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)))
14425 = TREE_VALUE (link);
14426
14427 if (DECL_SAVED_INSNS (current_function_decl) == 0)
14428 {
14429 /* Stop pointing to the local nodes about to be freed. */
14430 /* But DECL_INITIAL must remain nonzero so we know this was an actual
14431 function definition. */
14432 DECL_INITIAL (current_function_decl) = error_mark_node;
14433 DECL_ARGUMENTS (current_function_decl) = 0;
14434 }
14435
14436 pop_function_context ();
14437
14438 f_function_chain = p->next;
14439
14440 named_labels = p->named_labels;
14441 shadowed_labels = p->shadowed_labels;
14442 current_binding_level = p->binding_level;
14443
14444 free (p);
14445 }
14446
14447 /* Save and reinitialize the variables
14448 used during compilation of a C function. */
14449
14450 static void
14451 push_f_function_context ()
14452 {
14453 struct f_function *p
14454 = (struct f_function *) xmalloc (sizeof (struct f_function));
14455
14456 push_function_context ();
14457
14458 p->next = f_function_chain;
14459 f_function_chain = p;
14460
14461 p->named_labels = named_labels;
14462 p->shadowed_labels = shadowed_labels;
14463 p->binding_level = current_binding_level;
14464 }
14465
14466 static void
14467 push_parm_decl (tree parm)
14468 {
14469 int old_immediate_size_expand = immediate_size_expand;
14470
14471 /* Don't try computing parm sizes now -- wait till fn is called. */
14472
14473 immediate_size_expand = 0;
14474
14475 push_obstacks_nochange ();
14476
14477 /* Fill in arg stuff. */
14478
14479 DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
14480 DECL_ARG_TYPE_AS_WRITTEN (parm) = TREE_TYPE (parm);
14481 TREE_READONLY (parm) = 1; /* All implementation args are read-only. */
14482
14483 parm = pushdecl (parm);
14484
14485 immediate_size_expand = old_immediate_size_expand;
14486
14487 finish_decl (parm, NULL_TREE, FALSE);
14488 }
14489
14490 /* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, if appropriate. */
14491
14492 static tree
14493 pushdecl_top_level (x)
14494 tree x;
14495 {
14496 register tree t;
14497 register struct binding_level *b = current_binding_level;
14498 register tree f = current_function_decl;
14499
14500 current_binding_level = global_binding_level;
14501 current_function_decl = NULL_TREE;
14502 t = pushdecl (x);
14503 current_binding_level = b;
14504 current_function_decl = f;
14505 return t;
14506 }
14507
14508 /* Store the list of declarations of the current level.
14509 This is done for the parameter declarations of a function being defined,
14510 after they are modified in the light of any missing parameters. */
14511
14512 static tree
14513 storedecls (decls)
14514 tree decls;
14515 {
14516 return current_binding_level->names = decls;
14517 }
14518
14519 /* Store the parameter declarations into the current function declaration.
14520 This is called after parsing the parameter declarations, before
14521 digesting the body of the function.
14522
14523 For an old-style definition, modify the function's type
14524 to specify at least the number of arguments. */
14525
14526 static void
14527 store_parm_decls (int is_main_program UNUSED)
14528 {
14529 register tree fndecl = current_function_decl;
14530
14531 /* This is a chain of PARM_DECLs from old-style parm declarations. */
14532 DECL_ARGUMENTS (fndecl) = storedecls (nreverse (getdecls ()));
14533
14534 /* Initialize the RTL code for the function. */
14535
14536 init_function_start (fndecl, input_filename, lineno);
14537
14538 /* Set up parameters and prepare for return, for the function. */
14539
14540 expand_function_start (fndecl, 0);
14541 }
14542
14543 static tree
14544 start_decl (tree decl, bool is_top_level)
14545 {
14546 register tree tem;
14547 bool at_top_level = (current_binding_level == global_binding_level);
14548 bool top_level = is_top_level || at_top_level;
14549
14550 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
14551 level anyway. */
14552 assert (!is_top_level || !at_top_level);
14553
14554 /* The corresponding pop_obstacks is in finish_decl. */
14555 push_obstacks_nochange ();
14556
14557 if (DECL_INITIAL (decl) != NULL_TREE)
14558 {
14559 assert (DECL_INITIAL (decl) == error_mark_node);
14560 assert (!DECL_EXTERNAL (decl));
14561 }
14562 else if (top_level)
14563 assert ((TREE_STATIC (decl) == 1) || DECL_EXTERNAL (decl) == 1);
14564
14565 /* For Fortran, we by default put things in .common when possible. */
14566 DECL_COMMON (decl) = 1;
14567
14568 /* Add this decl to the current binding level. TEM may equal DECL or it may
14569 be a previous decl of the same name. */
14570 if (is_top_level)
14571 tem = pushdecl_top_level (decl);
14572 else
14573 tem = pushdecl (decl);
14574
14575 /* For a local variable, define the RTL now. */
14576 if (!top_level
14577 /* But not if this is a duplicate decl and we preserved the rtl from the
14578 previous one (which may or may not happen). */
14579 && DECL_RTL (tem) == 0)
14580 {
14581 if (TYPE_SIZE (TREE_TYPE (tem)) != 0)
14582 expand_decl (tem);
14583 else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
14584 && DECL_INITIAL (tem) != 0)
14585 expand_decl (tem);
14586 }
14587
14588 if (DECL_INITIAL (tem) != NULL_TREE)
14589 {
14590 /* When parsing and digesting the initializer, use temporary storage.
14591 Do this even if we will ignore the value. */
14592 if (at_top_level)
14593 temporary_allocation ();
14594 }
14595
14596 return tem;
14597 }
14598
14599 /* Create the FUNCTION_DECL for a function definition.
14600 DECLSPECS and DECLARATOR are the parts of the declaration;
14601 they describe the function's name and the type it returns,
14602 but twisted together in a fashion that parallels the syntax of C.
14603
14604 This function creates a binding context for the function body
14605 as well as setting up the FUNCTION_DECL in current_function_decl.
14606
14607 Returns 1 on success. If the DECLARATOR is not suitable for a function
14608 (it defines a datum instead), we return 0, which tells
14609 yyparse to report a parse error.
14610
14611 NESTED is nonzero for a function nested within another function. */
14612
14613 static void
14614 start_function (tree name, tree type, int nested, int public)
14615 {
14616 tree decl1;
14617 tree restype;
14618 int old_immediate_size_expand = immediate_size_expand;
14619
14620 named_labels = 0;
14621 shadowed_labels = 0;
14622
14623 /* Don't expand any sizes in the return type of the function. */
14624 immediate_size_expand = 0;
14625
14626 if (nested)
14627 {
14628 assert (!public);
14629 assert (current_function_decl != NULL_TREE);
14630 assert (DECL_CONTEXT (current_function_decl) == NULL_TREE);
14631 }
14632 else
14633 {
14634 assert (current_function_decl == NULL_TREE);
14635 }
14636
14637 if (TREE_CODE (type) == ERROR_MARK)
14638 decl1 = current_function_decl = error_mark_node;
14639 else
14640 {
14641 decl1 = build_decl (FUNCTION_DECL,
14642 name,
14643 type);
14644 TREE_PUBLIC (decl1) = public ? 1 : 0;
14645 if (nested)
14646 DECL_INLINE (decl1) = 1;
14647 TREE_STATIC (decl1) = 1;
14648 DECL_EXTERNAL (decl1) = 0;
14649
14650 announce_function (decl1);
14651
14652 /* Make the init_value nonzero so pushdecl knows this is not tentative.
14653 error_mark_node is replaced below (in poplevel) with the BLOCK. */
14654 DECL_INITIAL (decl1) = error_mark_node;
14655
14656 /* Record the decl so that the function name is defined. If we already have
14657 a decl for this name, and it is a FUNCTION_DECL, use the old decl. */
14658
14659 current_function_decl = pushdecl (decl1);
14660 }
14661
14662 if (!nested)
14663 ffecom_outer_function_decl_ = current_function_decl;
14664
14665 pushlevel (0);
14666
14667 if (TREE_CODE (current_function_decl) != ERROR_MARK)
14668 {
14669 make_function_rtl (current_function_decl);
14670
14671 restype = TREE_TYPE (TREE_TYPE (current_function_decl));
14672 DECL_RESULT (current_function_decl)
14673 = build_decl (RESULT_DECL, NULL_TREE, restype);
14674 }
14675
14676 if (!nested)
14677 /* Allocate further tree nodes temporarily during compilation of this
14678 function only. */
14679 temporary_allocation ();
14680
14681 if (!nested && (TREE_CODE (current_function_decl) != ERROR_MARK))
14682 TREE_ADDRESSABLE (current_function_decl) = 1;
14683
14684 immediate_size_expand = old_immediate_size_expand;
14685 }
14686 \f
14687 /* Here are the public functions the GNU back end needs. */
14688
14689 /* This is used by the `assert' macro. It is provided in libgcc.a,
14690 which `cc' doesn't know how to link. Note that the C++ front-end
14691 no longer actually uses the `assert' macro (instead, it calls
14692 my_friendly_assert). But all of the back-end files still need this. */
14693 void
14694 __eprintf (string, expression, line, filename)
14695 #ifdef __STDC__
14696 const char *string;
14697 const char *expression;
14698 unsigned line;
14699 const char *filename;
14700 #else
14701 char *string;
14702 char *expression;
14703 unsigned line;
14704 char *filename;
14705 #endif
14706 {
14707 fprintf (stderr, string, expression, line, filename);
14708 fflush (stderr);
14709 abort ();
14710 }
14711
14712 tree
14713 convert (type, expr)
14714 tree type, expr;
14715 {
14716 register tree e = expr;
14717 register enum tree_code code = TREE_CODE (type);
14718
14719 if (type == TREE_TYPE (e)
14720 || TREE_CODE (e) == ERROR_MARK)
14721 return e;
14722 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
14723 return fold (build1 (NOP_EXPR, type, e));
14724 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
14725 || code == ERROR_MARK)
14726 return error_mark_node;
14727 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
14728 {
14729 assert ("void value not ignored as it ought to be" == NULL);
14730 return error_mark_node;
14731 }
14732 if (code == VOID_TYPE)
14733 return build1 (CONVERT_EXPR, type, e);
14734 if ((code != RECORD_TYPE)
14735 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
14736 e = ffecom_1 (REALPART_EXPR, TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e))),
14737 e);
14738 if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
14739 return fold (convert_to_integer (type, e));
14740 if (code == POINTER_TYPE)
14741 return fold (convert_to_pointer (type, e));
14742 if (code == REAL_TYPE)
14743 return fold (convert_to_real (type, e));
14744 if (code == COMPLEX_TYPE)
14745 return fold (convert_to_complex (type, e));
14746 if (code == RECORD_TYPE)
14747 return fold (ffecom_convert_to_complex_ (type, e));
14748
14749 assert ("conversion to non-scalar type requested" == NULL);
14750 return error_mark_node;
14751 }
14752
14753 /* integrate_decl_tree calls this function, but since we don't use the
14754 DECL_LANG_SPECIFIC field, this is a no-op. */
14755
14756 void
14757 copy_lang_decl (node)
14758 tree node UNUSED;
14759 {
14760 }
14761
14762 /* Return the list of declarations of the current level.
14763 Note that this list is in reverse order unless/until
14764 you nreverse it; and when you do nreverse it, you must
14765 store the result back using `storedecls' or you will lose. */
14766
14767 tree
14768 getdecls ()
14769 {
14770 return current_binding_level->names;
14771 }
14772
14773 /* Nonzero if we are currently in the global binding level. */
14774
14775 int
14776 global_bindings_p ()
14777 {
14778 return current_binding_level == global_binding_level;
14779 }
14780
14781 /* Insert BLOCK at the end of the list of subblocks of the
14782 current binding level. This is used when a BIND_EXPR is expanded,
14783 to handle the BLOCK node inside the BIND_EXPR. */
14784
14785 void
14786 incomplete_type_error (value, type)
14787 tree value UNUSED;
14788 tree type;
14789 {
14790 if (TREE_CODE (type) == ERROR_MARK)
14791 return;
14792
14793 assert ("incomplete type?!?" == NULL);
14794 }
14795
14796 void
14797 init_decl_processing ()
14798 {
14799 malloc_init ();
14800 ffe_init_0 ();
14801 }
14802
14803 void
14804 init_lex ()
14805 {
14806 #if BUILT_FOR_270
14807 extern void (*print_error_function) (char *);
14808 #endif
14809
14810 /* Make identifier nodes long enough for the language-specific slots. */
14811 set_identifier_size (sizeof (struct lang_identifier));
14812 decl_printable_name = lang_printable_name;
14813 #if BUILT_FOR_270
14814 print_error_function = lang_print_error_function;
14815 #endif
14816 }
14817
14818 void
14819 insert_block (block)
14820 tree block;
14821 {
14822 TREE_USED (block) = 1;
14823 current_binding_level->blocks
14824 = chainon (current_binding_level->blocks, block);
14825 }
14826
14827 int
14828 lang_decode_option (p)
14829 char *p;
14830 {
14831 return ffe_decode_option (p);
14832 }
14833
14834 void
14835 lang_finish ()
14836 {
14837 ffe_terminate_0 ();
14838
14839 if (ffe_is_ffedebug ())
14840 malloc_pool_display (malloc_pool_image ());
14841 }
14842
14843 char *
14844 lang_identify ()
14845 {
14846 return "f77";
14847 }
14848
14849 void
14850 lang_init ()
14851 {
14852 extern FILE *finput; /* Don't pollute com.h with this. */
14853
14854 /* If the file is output from cpp, it should contain a first line
14855 `# 1 "real-filename"', and the current design of gcc (toplev.c
14856 in particular and the way it sets up information relied on by
14857 INCLUDE) requires that we read this now, and store the
14858 "real-filename" info in master_input_filename. Ask the lexer
14859 to try doing this. */
14860 ffelex_hash_kludge (finput);
14861 }
14862
14863 int
14864 mark_addressable (exp)
14865 tree exp;
14866 {
14867 register tree x = exp;
14868 while (1)
14869 switch (TREE_CODE (x))
14870 {
14871 case ADDR_EXPR:
14872 case COMPONENT_REF:
14873 case ARRAY_REF:
14874 x = TREE_OPERAND (x, 0);
14875 break;
14876
14877 case CONSTRUCTOR:
14878 TREE_ADDRESSABLE (x) = 1;
14879 return 1;
14880
14881 case VAR_DECL:
14882 case CONST_DECL:
14883 case PARM_DECL:
14884 case RESULT_DECL:
14885 if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)
14886 && DECL_NONLOCAL (x))
14887 {
14888 if (TREE_PUBLIC (x))
14889 {
14890 assert ("address of global register var requested" == NULL);
14891 return 0;
14892 }
14893 assert ("address of register variable requested" == NULL);
14894 }
14895 else if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x))
14896 {
14897 if (TREE_PUBLIC (x))
14898 {
14899 assert ("address of global register var requested" == NULL);
14900 return 0;
14901 }
14902 assert ("address of register var requested" == NULL);
14903 }
14904 put_var_into_stack (x);
14905
14906 /* drops in */
14907 case FUNCTION_DECL:
14908 TREE_ADDRESSABLE (x) = 1;
14909 #if 0 /* poplevel deals with this now. */
14910 if (DECL_CONTEXT (x) == 0)
14911 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
14912 #endif
14913
14914 default:
14915 return 1;
14916 }
14917 }
14918
14919 /* If DECL has a cleanup, build and return that cleanup here.
14920 This is a callback called by expand_expr. */
14921
14922 tree
14923 maybe_build_cleanup (decl)
14924 tree decl UNUSED;
14925 {
14926 /* There are no cleanups in Fortran. */
14927 return NULL_TREE;
14928 }
14929
14930 /* Exit a binding level.
14931 Pop the level off, and restore the state of the identifier-decl mappings
14932 that were in effect when this level was entered.
14933
14934 If KEEP is nonzero, this level had explicit declarations, so
14935 and create a "block" (a BLOCK node) for the level
14936 to record its declarations and subblocks for symbol table output.
14937
14938 If FUNCTIONBODY is nonzero, this level is the body of a function,
14939 so create a block as if KEEP were set and also clear out all
14940 label names.
14941
14942 If REVERSE is nonzero, reverse the order of decls before putting
14943 them into the BLOCK. */
14944
14945 tree
14946 poplevel (keep, reverse, functionbody)
14947 int keep;
14948 int reverse;
14949 int functionbody;
14950 {
14951 register tree link;
14952 /* The chain of decls was accumulated in reverse order. Put it into forward
14953 order, just for cleanliness. */
14954 tree decls;
14955 tree subblocks = current_binding_level->blocks;
14956 tree block = 0;
14957 tree decl;
14958 int block_previously_created;
14959
14960 /* Get the decls in the order they were written. Usually
14961 current_binding_level->names is in reverse order. But parameter decls
14962 were previously put in forward order. */
14963
14964 if (reverse)
14965 current_binding_level->names
14966 = decls = nreverse (current_binding_level->names);
14967 else
14968 decls = current_binding_level->names;
14969
14970 /* Output any nested inline functions within this block if they weren't
14971 already output. */
14972
14973 for (decl = decls; decl; decl = TREE_CHAIN (decl))
14974 if (TREE_CODE (decl) == FUNCTION_DECL
14975 && !TREE_ASM_WRITTEN (decl)
14976 && DECL_INITIAL (decl) != 0
14977 && TREE_ADDRESSABLE (decl))
14978 {
14979 /* If this decl was copied from a file-scope decl on account of a
14980 block-scope extern decl, propagate TREE_ADDRESSABLE to the
14981 file-scope decl. */
14982 if (DECL_ABSTRACT_ORIGIN (decl) != 0)
14983 TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
14984 else
14985 {
14986 push_function_context ();
14987 output_inline_function (decl);
14988 pop_function_context ();
14989 }
14990 }
14991
14992 /* If there were any declarations or structure tags in that level, or if
14993 this level is a function body, create a BLOCK to record them for the
14994 life of this function. */
14995
14996 block = 0;
14997 block_previously_created = (current_binding_level->this_block != 0);
14998 if (block_previously_created)
14999 block = current_binding_level->this_block;
15000 else if (keep || functionbody)
15001 block = make_node (BLOCK);
15002 if (block != 0)
15003 {
15004 BLOCK_VARS (block) = decls;
15005 BLOCK_SUBBLOCKS (block) = subblocks;
15006 remember_end_note (block);
15007 }
15008
15009 /* In each subblock, record that this is its superior. */
15010
15011 for (link = subblocks; link; link = TREE_CHAIN (link))
15012 BLOCK_SUPERCONTEXT (link) = block;
15013
15014 /* Clear out the meanings of the local variables of this level. */
15015
15016 for (link = decls; link; link = TREE_CHAIN (link))
15017 {
15018 if (DECL_NAME (link) != 0)
15019 {
15020 /* If the ident. was used or addressed via a local extern decl,
15021 don't forget that fact. */
15022 if (DECL_EXTERNAL (link))
15023 {
15024 if (TREE_USED (link))
15025 TREE_USED (DECL_NAME (link)) = 1;
15026 if (TREE_ADDRESSABLE (link))
15027 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
15028 }
15029 IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0;
15030 }
15031 }
15032
15033 /* If the level being exited is the top level of a function, check over all
15034 the labels, and clear out the current (function local) meanings of their
15035 names. */
15036
15037 if (functionbody)
15038 {
15039 /* If this is the top level block of a function, the vars are the
15040 function's parameters. Don't leave them in the BLOCK because they
15041 are found in the FUNCTION_DECL instead. */
15042
15043 BLOCK_VARS (block) = 0;
15044 }
15045
15046 /* Pop the current level, and free the structure for reuse. */
15047
15048 {
15049 register struct binding_level *level = current_binding_level;
15050 current_binding_level = current_binding_level->level_chain;
15051
15052 level->level_chain = free_binding_level;
15053 free_binding_level = level;
15054 }
15055
15056 /* Dispose of the block that we just made inside some higher level. */
15057 if (functionbody)
15058 DECL_INITIAL (current_function_decl) = block;
15059 else if (block)
15060 {
15061 if (!block_previously_created)
15062 current_binding_level->blocks
15063 = chainon (current_binding_level->blocks, block);
15064 }
15065 /* If we did not make a block for the level just exited, any blocks made
15066 for inner levels (since they cannot be recorded as subblocks in that
15067 level) must be carried forward so they will later become subblocks of
15068 something else. */
15069 else if (subblocks)
15070 current_binding_level->blocks
15071 = chainon (current_binding_level->blocks, subblocks);
15072
15073 /* Set the TYPE_CONTEXTs for all of the tagged types belonging to this
15074 binding contour so that they point to the appropriate construct, i.e.
15075 either to the current FUNCTION_DECL node, or else to the BLOCK node we
15076 just constructed.
15077
15078 Note that for tagged types whose scope is just the formal parameter list
15079 for some function type specification, we can't properly set their
15080 TYPE_CONTEXTs here, because we don't have a pointer to the appropriate
15081 FUNCTION_TYPE node readily available to us. For those cases, the
15082 TYPE_CONTEXTs of the relevant tagged type nodes get set in
15083 `grokdeclarator' as soon as we have created the FUNCTION_TYPE node which
15084 will represent the "scope" for these "parameter list local" tagged
15085 types. */
15086
15087 if (block)
15088 TREE_USED (block) = 1;
15089 return block;
15090 }
15091
15092 void
15093 print_lang_decl (file, node, indent)
15094 FILE *file UNUSED;
15095 tree node UNUSED;
15096 int indent UNUSED;
15097 {
15098 }
15099
15100 void
15101 print_lang_identifier (file, node, indent)
15102 FILE *file;
15103 tree node;
15104 int indent;
15105 {
15106 print_node (file, "global", IDENTIFIER_GLOBAL_VALUE (node), indent + 4);
15107 print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4);
15108 }
15109
15110 void
15111 print_lang_statistics ()
15112 {
15113 }
15114
15115 void
15116 print_lang_type (file, node, indent)
15117 FILE *file UNUSED;
15118 tree node UNUSED;
15119 int indent UNUSED;
15120 {
15121 }
15122
15123 /* Record a decl-node X as belonging to the current lexical scope.
15124 Check for errors (such as an incompatible declaration for the same
15125 name already seen in the same scope).
15126
15127 Returns either X or an old decl for the same name.
15128 If an old decl is returned, it may have been smashed
15129 to agree with what X says. */
15130
15131 tree
15132 pushdecl (x)
15133 tree x;
15134 {
15135 register tree t;
15136 register tree name = DECL_NAME (x);
15137 register struct binding_level *b = current_binding_level;
15138
15139 if ((TREE_CODE (x) == FUNCTION_DECL)
15140 && (DECL_INITIAL (x) == 0)
15141 && DECL_EXTERNAL (x))
15142 DECL_CONTEXT (x) = NULL_TREE;
15143 else
15144 DECL_CONTEXT (x) = current_function_decl;
15145
15146 if (name)
15147 {
15148 if (IDENTIFIER_INVENTED (name))
15149 {
15150 #if BUILT_FOR_270
15151 DECL_ARTIFICIAL (x) = 1;
15152 #endif
15153 DECL_IN_SYSTEM_HEADER (x) = 1;
15154 DECL_IGNORED_P (x) = 1;
15155 TREE_USED (x) = 1;
15156 if (TREE_CODE (x) == TYPE_DECL)
15157 TYPE_DECL_SUPPRESS_DEBUG (x) = 1;
15158 }
15159
15160 t = lookup_name_current_level (name);
15161
15162 assert ((t == NULL_TREE) || (DECL_CONTEXT (x) == NULL_TREE));
15163
15164 /* Don't push non-parms onto list for parms until we understand
15165 why we're doing this and whether it works. */
15166
15167 assert ((b == global_binding_level)
15168 || !ffecom_transform_only_dummies_
15169 || TREE_CODE (x) == PARM_DECL);
15170
15171 if ((t != NULL_TREE) && duplicate_decls (x, t))
15172 return t;
15173
15174 /* If we are processing a typedef statement, generate a whole new
15175 ..._TYPE node (which will be just an variant of the existing
15176 ..._TYPE node with identical properties) and then install the
15177 TYPE_DECL node generated to represent the typedef name as the
15178 TYPE_NAME of this brand new (duplicate) ..._TYPE node.
15179
15180 The whole point here is to end up with a situation where each and every
15181 ..._TYPE node the compiler creates will be uniquely associated with
15182 AT MOST one node representing a typedef name. This way, even though
15183 the compiler substitutes corresponding ..._TYPE nodes for TYPE_DECL
15184 (i.e. "typedef name") nodes very early on, later parts of the
15185 compiler can always do the reverse translation and get back the
15186 corresponding typedef name. For example, given:
15187
15188 typedef struct S MY_TYPE; MY_TYPE object;
15189
15190 Later parts of the compiler might only know that `object' was of type
15191 `struct S' if if were not for code just below. With this code
15192 however, later parts of the compiler see something like:
15193
15194 struct S' == struct S typedef struct S' MY_TYPE; struct S' object;
15195
15196 And they can then deduce (from the node for type struct S') that the
15197 original object declaration was:
15198
15199 MY_TYPE object;
15200
15201 Being able to do this is important for proper support of protoize, and
15202 also for generating precise symbolic debugging information which
15203 takes full account of the programmer's (typedef) vocabulary.
15204
15205 Obviously, we don't want to generate a duplicate ..._TYPE node if the
15206 TYPE_DECL node that we are now processing really represents a
15207 standard built-in type.
15208
15209 Since all standard types are effectively declared at line zero in the
15210 source file, we can easily check to see if we are working on a
15211 standard type by checking the current value of lineno. */
15212
15213 if (TREE_CODE (x) == TYPE_DECL)
15214 {
15215 if (DECL_SOURCE_LINE (x) == 0)
15216 {
15217 if (TYPE_NAME (TREE_TYPE (x)) == 0)
15218 TYPE_NAME (TREE_TYPE (x)) = x;
15219 }
15220 else if (TREE_TYPE (x) != error_mark_node)
15221 {
15222 tree tt = TREE_TYPE (x);
15223
15224 tt = build_type_copy (tt);
15225 TYPE_NAME (tt) = x;
15226 TREE_TYPE (x) = tt;
15227 }
15228 }
15229
15230 /* This name is new in its binding level. Install the new declaration
15231 and return it. */
15232 if (b == global_binding_level)
15233 IDENTIFIER_GLOBAL_VALUE (name) = x;
15234 else
15235 IDENTIFIER_LOCAL_VALUE (name) = x;
15236 }
15237
15238 /* Put decls on list in reverse order. We will reverse them later if
15239 necessary. */
15240 TREE_CHAIN (x) = b->names;
15241 b->names = x;
15242
15243 return x;
15244 }
15245
15246 /* Enter a new binding level.
15247 If TAG_TRANSPARENT is nonzero, do so only for the name space of variables,
15248 not for that of tags. */
15249
15250 void
15251 pushlevel (tag_transparent)
15252 int tag_transparent;
15253 {
15254 register struct binding_level *newlevel = NULL_BINDING_LEVEL;
15255
15256 assert (!tag_transparent);
15257
15258 /* Reuse or create a struct for this binding level. */
15259
15260 if (free_binding_level)
15261 {
15262 newlevel = free_binding_level;
15263 free_binding_level = free_binding_level->level_chain;
15264 }
15265 else
15266 {
15267 newlevel = make_binding_level ();
15268 }
15269
15270 /* Add this level to the front of the chain (stack) of levels that are
15271 active. */
15272
15273 *newlevel = clear_binding_level;
15274 newlevel->level_chain = current_binding_level;
15275 current_binding_level = newlevel;
15276 }
15277
15278 /* Set the BLOCK node for the innermost scope
15279 (the one we are currently in). */
15280
15281 void
15282 set_block (block)
15283 register tree block;
15284 {
15285 current_binding_level->this_block = block;
15286 }
15287
15288 /* ~~tree.h SHOULD declare this, because toplev.c references it. */
15289
15290 /* Can't 'yydebug' a front end not generated by yacc/bison! */
15291
15292 void
15293 set_yydebug (value)
15294 int value;
15295 {
15296 if (value)
15297 fprintf (stderr, "warning: no yacc/bison-generated output to debug!\n");
15298 }
15299
15300 tree
15301 signed_or_unsigned_type (unsignedp, type)
15302 int unsignedp;
15303 tree type;
15304 {
15305 tree type2;
15306
15307 if (! INTEGRAL_TYPE_P (type))
15308 return type;
15309 if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
15310 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15311 if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
15312 return unsignedp ? unsigned_type_node : integer_type_node;
15313 if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node))
15314 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15315 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node))
15316 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15317 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node))
15318 return (unsignedp ? long_long_unsigned_type_node
15319 : long_long_integer_type_node);
15320
15321 type2 = type_for_size (TYPE_PRECISION (type), unsignedp);
15322 if (type2 == NULL_TREE)
15323 return type;
15324
15325 return type2;
15326 }
15327
15328 tree
15329 signed_type (type)
15330 tree type;
15331 {
15332 tree type1 = TYPE_MAIN_VARIANT (type);
15333 ffeinfoKindtype kt;
15334 tree type2;
15335
15336 if (type1 == unsigned_char_type_node || type1 == char_type_node)
15337 return signed_char_type_node;
15338 if (type1 == unsigned_type_node)
15339 return integer_type_node;
15340 if (type1 == short_unsigned_type_node)
15341 return short_integer_type_node;
15342 if (type1 == long_unsigned_type_node)
15343 return long_integer_type_node;
15344 if (type1 == long_long_unsigned_type_node)
15345 return long_long_integer_type_node;
15346 #if 0 /* gcc/c-* files only */
15347 if (type1 == unsigned_intDI_type_node)
15348 return intDI_type_node;
15349 if (type1 == unsigned_intSI_type_node)
15350 return intSI_type_node;
15351 if (type1 == unsigned_intHI_type_node)
15352 return intHI_type_node;
15353 if (type1 == unsigned_intQI_type_node)
15354 return intQI_type_node;
15355 #endif
15356
15357 type2 = type_for_size (TYPE_PRECISION (type1), 0);
15358 if (type2 != NULL_TREE)
15359 return type2;
15360
15361 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15362 {
15363 type2 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
15364
15365 if (type1 == type2)
15366 return ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15367 }
15368
15369 return type;
15370 }
15371
15372 /* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
15373 or validate its data type for an `if' or `while' statement or ?..: exp.
15374
15375 This preparation consists of taking the ordinary
15376 representation of an expression expr and producing a valid tree
15377 boolean expression describing whether expr is nonzero. We could
15378 simply always do build_binary_op (NE_EXPR, expr, integer_zero_node, 1),
15379 but we optimize comparisons, &&, ||, and !.
15380
15381 The resulting type should always be `integer_type_node'. */
15382
15383 tree
15384 truthvalue_conversion (expr)
15385 tree expr;
15386 {
15387 if (TREE_CODE (expr) == ERROR_MARK)
15388 return expr;
15389
15390 #if 0 /* This appears to be wrong for C++. */
15391 /* These really should return error_mark_node after 2.4 is stable.
15392 But not all callers handle ERROR_MARK properly. */
15393 switch (TREE_CODE (TREE_TYPE (expr)))
15394 {
15395 case RECORD_TYPE:
15396 error ("struct type value used where scalar is required");
15397 return integer_zero_node;
15398
15399 case UNION_TYPE:
15400 error ("union type value used where scalar is required");
15401 return integer_zero_node;
15402
15403 case ARRAY_TYPE:
15404 error ("array type value used where scalar is required");
15405 return integer_zero_node;
15406
15407 default:
15408 break;
15409 }
15410 #endif /* 0 */
15411
15412 switch (TREE_CODE (expr))
15413 {
15414 /* It is simpler and generates better code to have only TRUTH_*_EXPR
15415 or comparison expressions as truth values at this level. */
15416 #if 0
15417 case COMPONENT_REF:
15418 /* A one-bit unsigned bit-field is already acceptable. */
15419 if (1 == TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (expr, 1)))
15420 && TREE_UNSIGNED (TREE_OPERAND (expr, 1)))
15421 return expr;
15422 break;
15423 #endif
15424
15425 case EQ_EXPR:
15426 /* It is simpler and generates better code to have only TRUTH_*_EXPR
15427 or comparison expressions as truth values at this level. */
15428 #if 0
15429 if (integer_zerop (TREE_OPERAND (expr, 1)))
15430 return build_unary_op (TRUTH_NOT_EXPR, TREE_OPERAND (expr, 0), 0);
15431 #endif
15432 case NE_EXPR: case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
15433 case TRUTH_ANDIF_EXPR:
15434 case TRUTH_ORIF_EXPR:
15435 case TRUTH_AND_EXPR:
15436 case TRUTH_OR_EXPR:
15437 case TRUTH_XOR_EXPR:
15438 TREE_TYPE (expr) = integer_type_node;
15439 return expr;
15440
15441 case ERROR_MARK:
15442 return expr;
15443
15444 case INTEGER_CST:
15445 return integer_zerop (expr) ? integer_zero_node : integer_one_node;
15446
15447 case REAL_CST:
15448 return real_zerop (expr) ? integer_zero_node : integer_one_node;
15449
15450 case ADDR_EXPR:
15451 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0)))
15452 return build (COMPOUND_EXPR, integer_type_node,
15453 TREE_OPERAND (expr, 0), integer_one_node);
15454 else
15455 return integer_one_node;
15456
15457 case COMPLEX_EXPR:
15458 return ffecom_2 ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
15459 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15460 integer_type_node,
15461 truthvalue_conversion (TREE_OPERAND (expr, 0)),
15462 truthvalue_conversion (TREE_OPERAND (expr, 1)));
15463
15464 case NEGATE_EXPR:
15465 case ABS_EXPR:
15466 case FLOAT_EXPR:
15467 case FFS_EXPR:
15468 /* These don't change whether an object is non-zero or zero. */
15469 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15470
15471 case LROTATE_EXPR:
15472 case RROTATE_EXPR:
15473 /* These don't change whether an object is zero or non-zero, but
15474 we can't ignore them if their second arg has side-effects. */
15475 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
15476 return build (COMPOUND_EXPR, integer_type_node, TREE_OPERAND (expr, 1),
15477 truthvalue_conversion (TREE_OPERAND (expr, 0)));
15478 else
15479 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15480
15481 case COND_EXPR:
15482 /* Distribute the conversion into the arms of a COND_EXPR. */
15483 return fold (build (COND_EXPR, integer_type_node, TREE_OPERAND (expr, 0),
15484 truthvalue_conversion (TREE_OPERAND (expr, 1)),
15485 truthvalue_conversion (TREE_OPERAND (expr, 2))));
15486
15487 case CONVERT_EXPR:
15488 /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
15489 since that affects how `default_conversion' will behave. */
15490 if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE
15491 || TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
15492 break;
15493 /* fall through... */
15494 case NOP_EXPR:
15495 /* If this is widening the argument, we can ignore it. */
15496 if (TYPE_PRECISION (TREE_TYPE (expr))
15497 >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
15498 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15499 break;
15500
15501 case MINUS_EXPR:
15502 /* With IEEE arithmetic, x - x may not equal 0, so we can't optimize
15503 this case. */
15504 if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
15505 && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE)
15506 break;
15507 /* fall through... */
15508 case BIT_XOR_EXPR:
15509 /* This and MINUS_EXPR can be changed into a comparison of the
15510 two objects. */
15511 if (TREE_TYPE (TREE_OPERAND (expr, 0))
15512 == TREE_TYPE (TREE_OPERAND (expr, 1)))
15513 return ffecom_2 (NE_EXPR, integer_type_node,
15514 TREE_OPERAND (expr, 0),
15515 TREE_OPERAND (expr, 1));
15516 return ffecom_2 (NE_EXPR, integer_type_node,
15517 TREE_OPERAND (expr, 0),
15518 fold (build1 (NOP_EXPR,
15519 TREE_TYPE (TREE_OPERAND (expr, 0)),
15520 TREE_OPERAND (expr, 1))));
15521
15522 case BIT_AND_EXPR:
15523 if (integer_onep (TREE_OPERAND (expr, 1)))
15524 return expr;
15525 break;
15526
15527 case MODIFY_EXPR:
15528 #if 0 /* No such thing in Fortran. */
15529 if (warn_parentheses && C_EXP_ORIGINAL_CODE (expr) == MODIFY_EXPR)
15530 warning ("suggest parentheses around assignment used as truth value");
15531 #endif
15532 break;
15533
15534 default:
15535 break;
15536 }
15537
15538 if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
15539 return (ffecom_2
15540 ((TREE_SIDE_EFFECTS (expr)
15541 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15542 integer_type_node,
15543 truthvalue_conversion (ffecom_1 (REALPART_EXPR,
15544 TREE_TYPE (TREE_TYPE (expr)),
15545 expr)),
15546 truthvalue_conversion (ffecom_1 (IMAGPART_EXPR,
15547 TREE_TYPE (TREE_TYPE (expr)),
15548 expr))));
15549
15550 return ffecom_2 (NE_EXPR, integer_type_node,
15551 expr,
15552 convert (TREE_TYPE (expr), integer_zero_node));
15553 }
15554
15555 tree
15556 type_for_mode (mode, unsignedp)
15557 enum machine_mode mode;
15558 int unsignedp;
15559 {
15560 int i;
15561 int j;
15562 tree t;
15563
15564 if (mode == TYPE_MODE (integer_type_node))
15565 return unsignedp ? unsigned_type_node : integer_type_node;
15566
15567 if (mode == TYPE_MODE (signed_char_type_node))
15568 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15569
15570 if (mode == TYPE_MODE (short_integer_type_node))
15571 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15572
15573 if (mode == TYPE_MODE (long_integer_type_node))
15574 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15575
15576 if (mode == TYPE_MODE (long_long_integer_type_node))
15577 return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
15578
15579 if (mode == TYPE_MODE (float_type_node))
15580 return float_type_node;
15581
15582 if (mode == TYPE_MODE (double_type_node))
15583 return double_type_node;
15584
15585 if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
15586 return build_pointer_type (char_type_node);
15587
15588 if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
15589 return build_pointer_type (integer_type_node);
15590
15591 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
15592 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
15593 {
15594 if (((t = ffecom_tree_type[i][j]) != NULL_TREE)
15595 && (mode == TYPE_MODE (t)))
15596 {
15597 if ((i == FFEINFO_basictypeINTEGER) && unsignedp)
15598 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][j];
15599 else
15600 return t;
15601 }
15602 }
15603
15604 return 0;
15605 }
15606
15607 tree
15608 type_for_size (bits, unsignedp)
15609 unsigned bits;
15610 int unsignedp;
15611 {
15612 ffeinfoKindtype kt;
15613 tree type_node;
15614
15615 if (bits == TYPE_PRECISION (integer_type_node))
15616 return unsignedp ? unsigned_type_node : integer_type_node;
15617
15618 if (bits == TYPE_PRECISION (signed_char_type_node))
15619 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15620
15621 if (bits == TYPE_PRECISION (short_integer_type_node))
15622 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15623
15624 if (bits == TYPE_PRECISION (long_integer_type_node))
15625 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15626
15627 if (bits == TYPE_PRECISION (long_long_integer_type_node))
15628 return (unsignedp ? long_long_unsigned_type_node
15629 : long_long_integer_type_node);
15630
15631 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15632 {
15633 type_node = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15634
15635 if ((type_node != NULL_TREE) && (bits == TYPE_PRECISION (type_node)))
15636 return unsignedp ? ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt]
15637 : type_node;
15638 }
15639
15640 return 0;
15641 }
15642
15643 tree
15644 unsigned_type (type)
15645 tree type;
15646 {
15647 tree type1 = TYPE_MAIN_VARIANT (type);
15648 ffeinfoKindtype kt;
15649 tree type2;
15650
15651 if (type1 == signed_char_type_node || type1 == char_type_node)
15652 return unsigned_char_type_node;
15653 if (type1 == integer_type_node)
15654 return unsigned_type_node;
15655 if (type1 == short_integer_type_node)
15656 return short_unsigned_type_node;
15657 if (type1 == long_integer_type_node)
15658 return long_unsigned_type_node;
15659 if (type1 == long_long_integer_type_node)
15660 return long_long_unsigned_type_node;
15661 #if 0 /* gcc/c-* files only */
15662 if (type1 == intDI_type_node)
15663 return unsigned_intDI_type_node;
15664 if (type1 == intSI_type_node)
15665 return unsigned_intSI_type_node;
15666 if (type1 == intHI_type_node)
15667 return unsigned_intHI_type_node;
15668 if (type1 == intQI_type_node)
15669 return unsigned_intQI_type_node;
15670 #endif
15671
15672 type2 = type_for_size (TYPE_PRECISION (type1), 1);
15673 if (type2 != NULL_TREE)
15674 return type2;
15675
15676 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15677 {
15678 type2 = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15679
15680 if (type1 == type2)
15681 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
15682 }
15683
15684 return type;
15685 }
15686
15687 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
15688 \f
15689 #if FFECOM_GCC_INCLUDE
15690
15691 /* From gcc/cccp.c, the code to handle -I. */
15692
15693 /* Skip leading "./" from a directory name.
15694 This may yield the empty string, which represents the current directory. */
15695
15696 static char *
15697 skip_redundant_dir_prefix (char *dir)
15698 {
15699 while (dir[0] == '.' && dir[1] == '/')
15700 for (dir += 2; *dir == '/'; dir++)
15701 continue;
15702 if (dir[0] == '.' && !dir[1])
15703 dir++;
15704 return dir;
15705 }
15706
15707 /* The file_name_map structure holds a mapping of file names for a
15708 particular directory. This mapping is read from the file named
15709 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
15710 map filenames on a file system with severe filename restrictions,
15711 such as DOS. The format of the file name map file is just a series
15712 of lines with two tokens on each line. The first token is the name
15713 to map, and the second token is the actual name to use. */
15714
15715 struct file_name_map
15716 {
15717 struct file_name_map *map_next;
15718 char *map_from;
15719 char *map_to;
15720 };
15721
15722 #define FILE_NAME_MAP_FILE "header.gcc"
15723
15724 /* Current maximum length of directory names in the search path
15725 for include files. (Altered as we get more of them.) */
15726
15727 static int max_include_len = 0;
15728
15729 struct file_name_list
15730 {
15731 struct file_name_list *next;
15732 char *fname;
15733 /* Mapping of file names for this directory. */
15734 struct file_name_map *name_map;
15735 /* Non-zero if name_map is valid. */
15736 int got_name_map;
15737 };
15738
15739 static struct file_name_list *include = NULL; /* First dir to search */
15740 static struct file_name_list *last_include = NULL; /* Last in chain */
15741
15742 /* I/O buffer structure.
15743 The `fname' field is nonzero for source files and #include files
15744 and for the dummy text used for -D and -U.
15745 It is zero for rescanning results of macro expansion
15746 and for expanding macro arguments. */
15747 #define INPUT_STACK_MAX 400
15748 static struct file_buf {
15749 char *fname;
15750 /* Filename specified with #line command. */
15751 char *nominal_fname;
15752 /* Record where in the search path this file was found.
15753 For #include_next. */
15754 struct file_name_list *dir;
15755 ffewhereLine line;
15756 ffewhereColumn column;
15757 } instack[INPUT_STACK_MAX];
15758
15759 static int last_error_tick = 0; /* Incremented each time we print it. */
15760 static int input_file_stack_tick = 0; /* Incremented when status changes. */
15761
15762 /* Current nesting level of input sources.
15763 `instack[indepth]' is the level currently being read. */
15764 static int indepth = -1;
15765
15766 typedef struct file_buf FILE_BUF;
15767
15768 typedef unsigned char U_CHAR;
15769
15770 /* table to tell if char can be part of a C identifier. */
15771 U_CHAR is_idchar[256];
15772 /* table to tell if char can be first char of a c identifier. */
15773 U_CHAR is_idstart[256];
15774 /* table to tell if c is horizontal space. */
15775 U_CHAR is_hor_space[256];
15776 /* table to tell if c is horizontal or vertical space. */
15777 static U_CHAR is_space[256];
15778
15779 #define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
15780 #define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*p]) p++; } while (0)
15781
15782 /* Nonzero means -I- has been seen,
15783 so don't look for #include "foo" the source-file directory. */
15784 static int ignore_srcdir;
15785
15786 #ifndef INCLUDE_LEN_FUDGE
15787 #define INCLUDE_LEN_FUDGE 0
15788 #endif
15789
15790 static void append_include_chain (struct file_name_list *first,
15791 struct file_name_list *last);
15792 static FILE *open_include_file (char *filename,
15793 struct file_name_list *searchptr);
15794 static void print_containing_files (ffebadSeverity sev);
15795 static char *skip_redundant_dir_prefix (char *);
15796 static char *read_filename_string (int ch, FILE *f);
15797 static struct file_name_map *read_name_map (char *dirname);
15798 static char *savestring (char *input);
15799
15800 /* Append a chain of `struct file_name_list's
15801 to the end of the main include chain.
15802 FIRST is the beginning of the chain to append, and LAST is the end. */
15803
15804 static void
15805 append_include_chain (first, last)
15806 struct file_name_list *first, *last;
15807 {
15808 struct file_name_list *dir;
15809
15810 if (!first || !last)
15811 return;
15812
15813 if (include == 0)
15814 include = first;
15815 else
15816 last_include->next = first;
15817
15818 for (dir = first; ; dir = dir->next) {
15819 int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE;
15820 if (len > max_include_len)
15821 max_include_len = len;
15822 if (dir == last)
15823 break;
15824 }
15825
15826 last->next = NULL;
15827 last_include = last;
15828 }
15829
15830 /* Try to open include file FILENAME. SEARCHPTR is the directory
15831 being tried from the include file search path. This function maps
15832 filenames on file systems based on information read by
15833 read_name_map. */
15834
15835 static FILE *
15836 open_include_file (filename, searchptr)
15837 char *filename;
15838 struct file_name_list *searchptr;
15839 {
15840 register struct file_name_map *map;
15841 register char *from;
15842 char *p, *dir;
15843
15844 if (searchptr && ! searchptr->got_name_map)
15845 {
15846 searchptr->name_map = read_name_map (searchptr->fname
15847 ? searchptr->fname : ".");
15848 searchptr->got_name_map = 1;
15849 }
15850
15851 /* First check the mapping for the directory we are using. */
15852 if (searchptr && searchptr->name_map)
15853 {
15854 from = filename;
15855 if (searchptr->fname)
15856 from += strlen (searchptr->fname) + 1;
15857 for (map = searchptr->name_map; map; map = map->map_next)
15858 {
15859 if (! strcmp (map->map_from, from))
15860 {
15861 /* Found a match. */
15862 return fopen (map->map_to, "r");
15863 }
15864 }
15865 }
15866
15867 /* Try to find a mapping file for the particular directory we are
15868 looking in. Thus #include <sys/types.h> will look up sys/types.h
15869 in /usr/include/header.gcc and look up types.h in
15870 /usr/include/sys/header.gcc. */
15871 p = rindex (filename, '/');
15872 #ifdef DIR_SEPARATOR
15873 if (! p) p = rindex (filename, DIR_SEPARATOR);
15874 else {
15875 char *tmp = rindex (filename, DIR_SEPARATOR);
15876 if (tmp != NULL && tmp > p) p = tmp;
15877 }
15878 #endif
15879 if (! p)
15880 p = filename;
15881 if (searchptr
15882 && searchptr->fname
15883 && strlen (searchptr->fname) == (size_t) (p - filename)
15884 && ! strncmp (searchptr->fname, filename, (int) (p - filename)))
15885 {
15886 /* FILENAME is in SEARCHPTR, which we've already checked. */
15887 return fopen (filename, "r");
15888 }
15889
15890 if (p == filename)
15891 {
15892 from = filename;
15893 map = read_name_map (".");
15894 }
15895 else
15896 {
15897 dir = (char *) xmalloc (p - filename + 1);
15898 memcpy (dir, filename, p - filename);
15899 dir[p - filename] = '\0';
15900 from = p + 1;
15901 map = read_name_map (dir);
15902 free (dir);
15903 }
15904 for (; map; map = map->map_next)
15905 if (! strcmp (map->map_from, from))
15906 return fopen (map->map_to, "r");
15907
15908 return fopen (filename, "r");
15909 }
15910
15911 /* Print the file names and line numbers of the #include
15912 commands which led to the current file. */
15913
15914 static void
15915 print_containing_files (ffebadSeverity sev)
15916 {
15917 FILE_BUF *ip = NULL;
15918 int i;
15919 int first = 1;
15920 char *str1;
15921 char *str2;
15922
15923 /* If stack of files hasn't changed since we last printed
15924 this info, don't repeat it. */
15925 if (last_error_tick == input_file_stack_tick)
15926 return;
15927
15928 for (i = indepth; i >= 0; i--)
15929 if (instack[i].fname != NULL) {
15930 ip = &instack[i];
15931 break;
15932 }
15933
15934 /* Give up if we don't find a source file. */
15935 if (ip == NULL)
15936 return;
15937
15938 /* Find the other, outer source files. */
15939 for (i--; i >= 0; i--)
15940 if (instack[i].fname != NULL)
15941 {
15942 ip = &instack[i];
15943 if (first)
15944 {
15945 first = 0;
15946 str1 = "In file included";
15947 }
15948 else
15949 {
15950 str1 = "... ...";
15951 }
15952
15953 if (i == 1)
15954 str2 = ":";
15955 else
15956 str2 = "";
15957
15958 ffebad_start_msg ("%A from %B at %0%C", sev);
15959 ffebad_here (0, ip->line, ip->column);
15960 ffebad_string (str1);
15961 ffebad_string (ip->nominal_fname);
15962 ffebad_string (str2);
15963 ffebad_finish ();
15964 }
15965
15966 /* Record we have printed the status as of this time. */
15967 last_error_tick = input_file_stack_tick;
15968 }
15969
15970 /* Read a space delimited string of unlimited length from a stdio
15971 file. */
15972
15973 static char *
15974 read_filename_string (ch, f)
15975 int ch;
15976 FILE *f;
15977 {
15978 char *alloc, *set;
15979 int len;
15980
15981 len = 20;
15982 set = alloc = xmalloc (len + 1);
15983 if (! is_space[ch])
15984 {
15985 *set++ = ch;
15986 while ((ch = getc (f)) != EOF && ! is_space[ch])
15987 {
15988 if (set - alloc == len)
15989 {
15990 len *= 2;
15991 alloc = xrealloc (alloc, len + 1);
15992 set = alloc + len / 2;
15993 }
15994 *set++ = ch;
15995 }
15996 }
15997 *set = '\0';
15998 ungetc (ch, f);
15999 return alloc;
16000 }
16001
16002 /* Read the file name map file for DIRNAME. */
16003
16004 static struct file_name_map *
16005 read_name_map (dirname)
16006 char *dirname;
16007 {
16008 /* This structure holds a linked list of file name maps, one per
16009 directory. */
16010 struct file_name_map_list
16011 {
16012 struct file_name_map_list *map_list_next;
16013 char *map_list_name;
16014 struct file_name_map *map_list_map;
16015 };
16016 static struct file_name_map_list *map_list;
16017 register struct file_name_map_list *map_list_ptr;
16018 char *name;
16019 FILE *f;
16020 size_t dirlen;
16021 int separator_needed;
16022
16023 dirname = skip_redundant_dir_prefix (dirname);
16024
16025 for (map_list_ptr = map_list; map_list_ptr;
16026 map_list_ptr = map_list_ptr->map_list_next)
16027 if (! strcmp (map_list_ptr->map_list_name, dirname))
16028 return map_list_ptr->map_list_map;
16029
16030 map_list_ptr = ((struct file_name_map_list *)
16031 xmalloc (sizeof (struct file_name_map_list)));
16032 map_list_ptr->map_list_name = savestring (dirname);
16033 map_list_ptr->map_list_map = NULL;
16034
16035 dirlen = strlen (dirname);
16036 separator_needed = dirlen != 0 && dirname[dirlen - 1] != '/';
16037 name = (char *) xmalloc (dirlen + strlen (FILE_NAME_MAP_FILE) + 2);
16038 strcpy (name, dirname);
16039 name[dirlen] = '/';
16040 strcpy (name + dirlen + separator_needed, FILE_NAME_MAP_FILE);
16041 f = fopen (name, "r");
16042 free (name);
16043 if (!f)
16044 map_list_ptr->map_list_map = NULL;
16045 else
16046 {
16047 int ch;
16048
16049 while ((ch = getc (f)) != EOF)
16050 {
16051 char *from, *to;
16052 struct file_name_map *ptr;
16053
16054 if (is_space[ch])
16055 continue;
16056 from = read_filename_string (ch, f);
16057 while ((ch = getc (f)) != EOF && is_hor_space[ch])
16058 ;
16059 to = read_filename_string (ch, f);
16060
16061 ptr = ((struct file_name_map *)
16062 xmalloc (sizeof (struct file_name_map)));
16063 ptr->map_from = from;
16064
16065 /* Make the real filename absolute. */
16066 if (*to == '/')
16067 ptr->map_to = to;
16068 else
16069 {
16070 ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
16071 strcpy (ptr->map_to, dirname);
16072 ptr->map_to[dirlen] = '/';
16073 strcpy (ptr->map_to + dirlen + separator_needed, to);
16074 free (to);
16075 }
16076
16077 ptr->map_next = map_list_ptr->map_list_map;
16078 map_list_ptr->map_list_map = ptr;
16079
16080 while ((ch = getc (f)) != '\n')
16081 if (ch == EOF)
16082 break;
16083 }
16084 fclose (f);
16085 }
16086
16087 map_list_ptr->map_list_next = map_list;
16088 map_list = map_list_ptr;
16089
16090 return map_list_ptr->map_list_map;
16091 }
16092
16093 static char *
16094 savestring (input)
16095 char *input;
16096 {
16097 unsigned size = strlen (input);
16098 char *output = xmalloc (size + 1);
16099 strcpy (output, input);
16100 return output;
16101 }
16102
16103 static void
16104 ffecom_file_ (char *name)
16105 {
16106 FILE_BUF *fp;
16107
16108 /* Do partial setup of input buffer for the sake of generating
16109 early #line directives (when -g is in effect). */
16110
16111 fp = &instack[++indepth];
16112 memset ((char *) fp, 0, sizeof (FILE_BUF));
16113 if (name == NULL)
16114 name = "";
16115 fp->nominal_fname = fp->fname = name;
16116 }
16117
16118 /* Initialize syntactic classifications of characters. */
16119
16120 static void
16121 ffecom_initialize_char_syntax_ ()
16122 {
16123 register int i;
16124
16125 /*
16126 * Set up is_idchar and is_idstart tables. These should be
16127 * faster than saying (is_alpha (c) || c == '_'), etc.
16128 * Set up these things before calling any routines tthat
16129 * refer to them.
16130 */
16131 for (i = 'a'; i <= 'z'; i++) {
16132 is_idchar[i - 'a' + 'A'] = 1;
16133 is_idchar[i] = 1;
16134 is_idstart[i - 'a' + 'A'] = 1;
16135 is_idstart[i] = 1;
16136 }
16137 for (i = '0'; i <= '9'; i++)
16138 is_idchar[i] = 1;
16139 is_idchar['_'] = 1;
16140 is_idstart['_'] = 1;
16141
16142 /* horizontal space table */
16143 is_hor_space[' '] = 1;
16144 is_hor_space['\t'] = 1;
16145 is_hor_space['\v'] = 1;
16146 is_hor_space['\f'] = 1;
16147 is_hor_space['\r'] = 1;
16148
16149 is_space[' '] = 1;
16150 is_space['\t'] = 1;
16151 is_space['\v'] = 1;
16152 is_space['\f'] = 1;
16153 is_space['\n'] = 1;
16154 is_space['\r'] = 1;
16155 }
16156
16157 static void
16158 ffecom_close_include_ (FILE *f)
16159 {
16160 fclose (f);
16161
16162 indepth--;
16163 input_file_stack_tick++;
16164
16165 ffewhere_line_kill (instack[indepth].line);
16166 ffewhere_column_kill (instack[indepth].column);
16167 }
16168
16169 static int
16170 ffecom_decode_include_option_ (char *spec)
16171 {
16172 struct file_name_list *dirtmp;
16173
16174 if (! ignore_srcdir && !strcmp (spec, "-"))
16175 ignore_srcdir = 1;
16176 else
16177 {
16178 dirtmp = (struct file_name_list *)
16179 xmalloc (sizeof (struct file_name_list));
16180 dirtmp->next = 0; /* New one goes on the end */
16181 if (spec[0] != 0)
16182 dirtmp->fname = spec;
16183 else
16184 fatal ("Directory name must immediately follow -I option with no intervening spaces, as in `-Idir', not `-I dir'");
16185 dirtmp->got_name_map = 0;
16186 append_include_chain (dirtmp, dirtmp);
16187 }
16188 return 1;
16189 }
16190
16191 /* Open INCLUDEd file. */
16192
16193 static FILE *
16194 ffecom_open_include_ (char *name, ffewhereLine l, ffewhereColumn c)
16195 {
16196 char *fbeg = name;
16197 size_t flen = strlen (fbeg);
16198 struct file_name_list *search_start = include; /* Chain of dirs to search */
16199 struct file_name_list dsp[1]; /* First in chain, if #include "..." */
16200 struct file_name_list *searchptr = 0;
16201 char *fname; /* Dynamically allocated fname buffer */
16202 FILE *f;
16203 FILE_BUF *fp;
16204
16205 if (flen == 0)
16206 return NULL;
16207
16208 dsp[0].fname = NULL;
16209
16210 /* If -I- was specified, don't search current dir, only spec'd ones. */
16211 if (!ignore_srcdir)
16212 {
16213 for (fp = &instack[indepth]; fp >= instack; fp--)
16214 {
16215 int n;
16216 char *ep;
16217 char *nam;
16218
16219 if ((nam = fp->nominal_fname) != NULL)
16220 {
16221 /* Found a named file. Figure out dir of the file,
16222 and put it in front of the search list. */
16223 dsp[0].next = search_start;
16224 search_start = dsp;
16225 #ifndef VMS
16226 ep = rindex (nam, '/');
16227 #ifdef DIR_SEPARATOR
16228 if (ep == NULL) ep = rindex (nam, DIR_SEPARATOR);
16229 else {
16230 char *tmp = rindex (nam, DIR_SEPARATOR);
16231 if (tmp != NULL && tmp > ep) ep = tmp;
16232 }
16233 #endif
16234 #else /* VMS */
16235 ep = rindex (nam, ']');
16236 if (ep == NULL) ep = rindex (nam, '>');
16237 if (ep == NULL) ep = rindex (nam, ':');
16238 if (ep != NULL) ep++;
16239 #endif /* VMS */
16240 if (ep != NULL)
16241 {
16242 n = ep - nam;
16243 dsp[0].fname = (char *) xmalloc (n + 1);
16244 strncpy (dsp[0].fname, nam, n);
16245 dsp[0].fname[n] = '\0';
16246 if (n + INCLUDE_LEN_FUDGE > max_include_len)
16247 max_include_len = n + INCLUDE_LEN_FUDGE;
16248 }
16249 else
16250 dsp[0].fname = NULL; /* Current directory */
16251 dsp[0].got_name_map = 0;
16252 break;
16253 }
16254 }
16255 }
16256
16257 /* Allocate this permanently, because it gets stored in the definitions
16258 of macros. */
16259 fname = xmalloc (max_include_len + flen + 4);
16260 /* + 2 above for slash and terminating null. */
16261 /* + 2 added for '.h' on VMS (to support '#include filename') (NOT USED
16262 for g77 yet). */
16263
16264 /* If specified file name is absolute, just open it. */
16265
16266 if (*fbeg == '/'
16267 #ifdef DIR_SEPARATOR
16268 || *fbeg == DIR_SEPARATOR
16269 #endif
16270 )
16271 {
16272 strncpy (fname, (char *) fbeg, flen);
16273 fname[flen] = 0;
16274 f = open_include_file (fname, NULL_PTR);
16275 }
16276 else
16277 {
16278 f = NULL;
16279
16280 /* Search directory path, trying to open the file.
16281 Copy each filename tried into FNAME. */
16282
16283 for (searchptr = search_start; searchptr; searchptr = searchptr->next)
16284 {
16285 if (searchptr->fname)
16286 {
16287 /* The empty string in a search path is ignored.
16288 This makes it possible to turn off entirely
16289 a standard piece of the list. */
16290 if (searchptr->fname[0] == 0)
16291 continue;
16292 strcpy (fname, skip_redundant_dir_prefix (searchptr->fname));
16293 if (fname[0] && fname[strlen (fname) - 1] != '/')
16294 strcat (fname, "/");
16295 fname[strlen (fname) + flen] = 0;
16296 }
16297 else
16298 fname[0] = 0;
16299
16300 strncat (fname, fbeg, flen);
16301 #ifdef VMS
16302 /* Change this 1/2 Unix 1/2 VMS file specification into a
16303 full VMS file specification */
16304 if (searchptr->fname && (searchptr->fname[0] != 0))
16305 {
16306 /* Fix up the filename */
16307 hack_vms_include_specification (fname);
16308 }
16309 else
16310 {
16311 /* This is a normal VMS filespec, so use it unchanged. */
16312 strncpy (fname, (char *) fbeg, flen);
16313 fname[flen] = 0;
16314 #if 0 /* Not for g77. */
16315 /* if it's '#include filename', add the missing .h */
16316 if (index (fname, '.') == NULL)
16317 strcat (fname, ".h");
16318 #endif
16319 }
16320 #endif /* VMS */
16321 f = open_include_file (fname, searchptr);
16322 #ifdef EACCES
16323 if (f == NULL && errno == EACCES)
16324 {
16325 print_containing_files (FFEBAD_severityWARNING);
16326 ffebad_start_msg ("At %0, INCLUDE file %A exists, but is not readable",
16327 FFEBAD_severityWARNING);
16328 ffebad_string (fname);
16329 ffebad_here (0, l, c);
16330 ffebad_finish ();
16331 }
16332 #endif
16333 if (f != NULL)
16334 break;
16335 }
16336 }
16337
16338 if (f == NULL)
16339 {
16340 /* A file that was not found. */
16341
16342 strncpy (fname, (char *) fbeg, flen);
16343 fname[flen] = 0;
16344 print_containing_files (ffebad_severity (FFEBAD_OPEN_INCLUDE));
16345 ffebad_start (FFEBAD_OPEN_INCLUDE);
16346 ffebad_here (0, l, c);
16347 ffebad_string (fname);
16348 ffebad_finish ();
16349 }
16350
16351 if (dsp[0].fname != NULL)
16352 free (dsp[0].fname);
16353
16354 if (f == NULL)
16355 return NULL;
16356
16357 if (indepth >= (INPUT_STACK_MAX - 1))
16358 {
16359 print_containing_files (FFEBAD_severityFATAL);
16360 ffebad_start_msg ("At %0, INCLUDE nesting too deep",
16361 FFEBAD_severityFATAL);
16362 ffebad_string (fname);
16363 ffebad_here (0, l, c);
16364 ffebad_finish ();
16365 return NULL;
16366 }
16367
16368 instack[indepth].line = ffewhere_line_use (l);
16369 instack[indepth].column = ffewhere_column_use (c);
16370
16371 fp = &instack[indepth + 1];
16372 memset ((char *) fp, 0, sizeof (FILE_BUF));
16373 fp->nominal_fname = fp->fname = fname;
16374 fp->dir = searchptr;
16375
16376 indepth++;
16377 input_file_stack_tick++;
16378
16379 return f;
16380 }
16381 #endif /* FFECOM_GCC_INCLUDE */