]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/f/com.c
Makefile.in: Update to use common.opt and lang_opt_files.
[thirdparty/gcc.git] / gcc / f / com.c
1 /* com.c -- Implementation File (module.c template V1.0)
2 Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
3 Free Software Foundation, Inc.
4 Contributed by James Craig Burley.
5
6 This file is part of GNU Fortran.
7
8 GNU Fortran is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 GNU Fortran is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GNU Fortran; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
21 02111-1307, USA.
22
23 Related Modules:
24 None
25
26 Description:
27 Contains compiler-specific functions.
28
29 Modifications:
30 */
31
32 /* Understanding this module means understanding the interface between
33 the g77 front end and the gcc back end (or, perhaps, some other
34 back end). In here are the functions called by the front end proper
35 to notify whatever back end is in place about certain things, and
36 also the back-end-specific functions. It's a bear to deal with, so
37 lately I've been trying to simplify things, especially with regard
38 to the gcc-back-end-specific stuff.
39
40 Building expressions generally seems quite easy, but building decls
41 has been challenging and is undergoing revision. gcc has several
42 kinds of decls:
43
44 TYPE_DECL -- a type (int, float, struct, function, etc.)
45 CONST_DECL -- a constant of some type other than function
46 LABEL_DECL -- a variable or a constant?
47 PARM_DECL -- an argument to a function (a variable that is a dummy)
48 RESULT_DECL -- the return value of a function (a variable)
49 VAR_DECL -- other variable (can hold a ptr-to-function, struct, int, etc.)
50 FUNCTION_DECL -- a function (either the actual function or an extern ref)
51 FIELD_DECL -- a field in a struct or union (goes into types)
52
53 g77 has a set of functions that somewhat parallels the gcc front end
54 when it comes to building decls:
55
56 Internal Function (one we define, not just declare as extern):
57 if (is_nested) push_f_function_context ();
58 start_function (get_identifier ("function_name"), function_type,
59 is_nested, is_public);
60 // for each arg, build PARM_DECL and call push_parm_decl (decl) with it;
61 store_parm_decls (is_main_program);
62 ffecom_start_compstmt ();
63 // for stmts and decls inside function, do appropriate things;
64 ffecom_end_compstmt ();
65 finish_function (is_nested);
66 if (is_nested) pop_f_function_context ();
67
68 Everything Else:
69 tree d;
70 tree init;
71 // fill in external, public, static, &c for decl, and
72 // set DECL_INITIAL to error_mark_node if going to initialize
73 // set is_top_level TRUE only if not at top level and decl
74 // must go in top level (i.e. not within current function decl context)
75 d = start_decl (decl, is_top_level);
76 init = ...; // if have initializer
77 finish_decl (d, init, is_top_level);
78
79 */
80
81 /* Include files. */
82
83 #include "proj.h"
84 #include "flags.h"
85 #include "real.h"
86 #include "rtl.h"
87 #include "toplev.h"
88 #include "tree.h"
89 #include "output.h" /* Must follow tree.h so TREE_CODE is defined! */
90 #include "convert.h"
91 #include "ggc.h"
92 #include "diagnostic.h"
93 #include "intl.h"
94 #include "langhooks.h"
95 #include "langhooks-def.h"
96 #include "debug.h"
97
98 /* VMS-specific definitions */
99 #ifdef VMS
100 #include <descrip.h>
101 #define O_RDONLY 0 /* Open arg for Read/Only */
102 #define O_WRONLY 1 /* Open arg for Write/Only */
103 #define read(fd,buf,size) VMS_read (fd,buf,size)
104 #define write(fd,buf,size) VMS_write (fd,buf,size)
105 #define open(fname,mode,prot) VMS_open (fname,mode,prot)
106 #define fopen(fname,mode) VMS_fopen (fname,mode)
107 #define freopen(fname,mode,ofile) VMS_freopen (fname,mode,ofile)
108 #define strncat(dst,src,cnt) VMS_strncat (dst,src,cnt)
109 #define fstat(fd,stbuf) VMS_fstat (fd,stbuf)
110 static int VMS_fstat (), VMS_stat ();
111 static char * VMS_strncat ();
112 static int VMS_read ();
113 static int VMS_write ();
114 static int VMS_open ();
115 static FILE * VMS_fopen ();
116 static FILE * VMS_freopen ();
117 static void hack_vms_include_specification ();
118 typedef struct { unsigned :16, :16, :16; } vms_ino_t;
119 #define ino_t vms_ino_t
120 #define INCLUDE_LEN_FUDGE 10 /* leave room for VMS syntax conversion */
121 #endif /* VMS */
122
123 #define FFECOM_DETERMINE_TYPES 1 /* for com.h */
124 #include "com.h"
125 #include "bad.h"
126 #include "bld.h"
127 #include "equiv.h"
128 #include "expr.h"
129 #include "implic.h"
130 #include "info.h"
131 #include "malloc.h"
132 #include "src.h"
133 #include "st.h"
134 #include "storag.h"
135 #include "symbol.h"
136 #include "target.h"
137 #include "top.h"
138 #include "type.h"
139
140 /* Externals defined here. */
141
142 /* Stream for reading from the input file. */
143 FILE *finput;
144
145 /* These definitions parallel those in c-decl.c so that code from that
146 module can be used pretty much as is. Much of these defs aren't
147 otherwise used, i.e. by g77 code per se, except some of them are used
148 to build some of them that are. The ones that are global (i.e. not
149 "static") are those that ste.c and such might use (directly
150 or by using com macros that reference them in their definitions). */
151
152 tree string_type_node;
153
154 /* The rest of these are inventions for g77, though there might be
155 similar things in the C front end. As they are found, these
156 inventions should be renamed to be canonical. Note that only
157 the ones currently required to be global are so. */
158
159 static GTY(()) tree ffecom_tree_fun_type_void;
160
161 tree ffecom_integer_type_node; /* Abbrev for _tree_type[blah][blah]. */
162 tree ffecom_integer_zero_node; /* Like *_*_* with g77's integer type. */
163 tree ffecom_integer_one_node; /* " */
164 tree ffecom_tree_type[FFEINFO_basictype][FFEINFO_kindtype];
165
166 /* _fun_type things are the f2c-specific versions. For -fno-f2c,
167 just use build_function_type and build_pointer_type on the
168 appropriate _tree_type array element. */
169
170 static GTY(()) tree ffecom_tree_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
171 static GTY(()) tree
172 ffecom_tree_ptr_to_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
173 static GTY(()) tree ffecom_tree_subr_type;
174 static GTY(()) tree ffecom_tree_ptr_to_subr_type;
175 static GTY(()) tree ffecom_tree_blockdata_type;
176
177 static GTY(()) tree ffecom_tree_xargc_;
178
179 ffecomSymbol ffecom_symbol_null_
180 =
181 {
182 NULL_TREE,
183 NULL_TREE,
184 NULL_TREE,
185 NULL_TREE,
186 false
187 };
188 ffeinfoKindtype ffecom_pointer_kind_ = FFEINFO_basictypeNONE;
189 ffeinfoKindtype ffecom_label_kind_ = FFEINFO_basictypeNONE;
190
191 int ffecom_f2c_typecode_[FFEINFO_basictype][FFEINFO_kindtype];
192 tree ffecom_f2c_integer_type_node;
193 static GTY(()) tree ffecom_f2c_ptr_to_integer_type_node;
194 tree ffecom_f2c_address_type_node;
195 tree ffecom_f2c_real_type_node;
196 static GTY(()) tree ffecom_f2c_ptr_to_real_type_node;
197 tree ffecom_f2c_doublereal_type_node;
198 tree ffecom_f2c_complex_type_node;
199 tree ffecom_f2c_doublecomplex_type_node;
200 tree ffecom_f2c_longint_type_node;
201 tree ffecom_f2c_logical_type_node;
202 tree ffecom_f2c_flag_type_node;
203 tree ffecom_f2c_ftnlen_type_node;
204 tree ffecom_f2c_ftnlen_zero_node;
205 tree ffecom_f2c_ftnlen_one_node;
206 tree ffecom_f2c_ftnlen_two_node;
207 tree ffecom_f2c_ptr_to_ftnlen_type_node;
208 tree ffecom_f2c_ftnint_type_node;
209 tree ffecom_f2c_ptr_to_ftnint_type_node;
210
211 /* Simple definitions and enumerations. */
212
213 #ifndef FFECOM_sizeMAXSTACKITEM
214 #define FFECOM_sizeMAXSTACKITEM 32*1024 /* Keep user-declared things
215 larger than this # bytes
216 off stack if possible. */
217 #endif
218
219 /* For systems that have large enough stacks, they should define
220 this to 0, and here, for ease of use later on, we just undefine
221 it if it is 0. */
222
223 #if FFECOM_sizeMAXSTACKITEM == 0
224 #undef FFECOM_sizeMAXSTACKITEM
225 #endif
226
227 typedef enum
228 {
229 FFECOM_rttypeVOID_,
230 FFECOM_rttypeVOIDSTAR_, /* C's `void *' type. */
231 FFECOM_rttypeFTNINT_, /* f2c's `ftnint' type. */
232 FFECOM_rttypeINTEGER_, /* f2c's `integer' type. */
233 FFECOM_rttypeLONGINT_, /* f2c's `longint' type. */
234 FFECOM_rttypeLOGICAL_, /* f2c's `logical' type. */
235 FFECOM_rttypeREAL_F2C_, /* f2c's `real' returned as `double'. */
236 FFECOM_rttypeREAL_GNU_, /* `real' returned as such. */
237 FFECOM_rttypeCOMPLEX_F2C_, /* f2c's `complex' returned via 1st arg. */
238 FFECOM_rttypeCOMPLEX_GNU_, /* f2c's `complex' returned directly. */
239 FFECOM_rttypeDOUBLE_, /* C's `double' type. */
240 FFECOM_rttypeDOUBLEREAL_, /* f2c's `doublereal' type. */
241 FFECOM_rttypeDBLCMPLX_F2C_, /* f2c's `doublecomplex' returned via 1st arg. */
242 FFECOM_rttypeDBLCMPLX_GNU_, /* f2c's `doublecomplex' returned directly. */
243 FFECOM_rttypeCHARACTER_, /* f2c `char *'/`ftnlen' pair. */
244 FFECOM_rttype_
245 } ffecomRttype_;
246
247 /* Internal typedefs. */
248
249 typedef struct _ffecom_concat_list_ ffecomConcatList_;
250
251 /* Private include files. */
252
253
254 /* Internal structure definitions. */
255
256 struct _ffecom_concat_list_
257 {
258 ffebld *exprs;
259 int count;
260 int max;
261 ffetargetCharacterSize minlen;
262 ffetargetCharacterSize maxlen;
263 };
264
265 /* Static functions (internal). */
266
267 static tree ffe_type_for_mode PARAMS ((enum machine_mode, int));
268 static tree ffe_type_for_size PARAMS ((unsigned int, int));
269 static tree ffe_unsigned_type PARAMS ((tree));
270 static tree ffe_signed_type PARAMS ((tree));
271 static tree ffe_signed_or_unsigned_type PARAMS ((int, tree));
272 static bool ffe_mark_addressable PARAMS ((tree));
273 static tree ffe_truthvalue_conversion PARAMS ((tree));
274 static void ffecom_init_decl_processing PARAMS ((void));
275 static tree ffecom_arglist_expr_ (const char *argstring, ffebld args);
276 static tree ffecom_widest_expr_type_ (ffebld list);
277 static bool ffecom_overlap_ (tree dest_decl, tree dest_offset,
278 tree dest_size, tree source_tree,
279 ffebld source, bool scalar_arg);
280 static bool ffecom_args_overlapping_ (tree dest_tree, ffebld dest,
281 tree args, tree callee_commons,
282 bool scalar_args);
283 static tree ffecom_build_f2c_string_ (int i, const char *s);
284 static tree ffecom_call_ (tree fn, ffeinfoKindtype kt,
285 bool is_f2c_complex, tree type,
286 tree args, tree dest_tree,
287 ffebld dest, bool *dest_used,
288 tree callee_commons, bool scalar_args, tree hook);
289 static tree ffecom_call_binop_ (tree fn, ffeinfoKindtype kt,
290 bool is_f2c_complex, tree type,
291 ffebld left, ffebld right,
292 tree dest_tree, ffebld dest,
293 bool *dest_used, tree callee_commons,
294 bool scalar_args, bool ref, tree hook);
295 static void ffecom_char_args_x_ (tree *xitem, tree *length,
296 ffebld expr, bool with_null);
297 static tree ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy);
298 static tree ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s);
299 static ffecomConcatList_
300 ffecom_concat_list_gather_ (ffecomConcatList_ catlist,
301 ffebld expr,
302 ffetargetCharacterSize max);
303 static void ffecom_concat_list_kill_ (ffecomConcatList_ catlist);
304 static ffecomConcatList_ ffecom_concat_list_new_ (ffebld expr,
305 ffetargetCharacterSize max);
306 static void ffecom_debug_kludge_ (tree aggr, const char *aggr_type,
307 ffesymbol member, tree member_type,
308 ffetargetOffset offset);
309 static void ffecom_do_entry_ (ffesymbol fn, int entrynum);
310 static tree ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
311 bool *dest_used, bool assignp, bool widenp);
312 static tree ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
313 ffebld dest, bool *dest_used);
314 static tree ffecom_expr_power_integer_ (ffebld expr);
315 static void ffecom_expr_transform_ (ffebld expr);
316 static void ffecom_f2c_make_type_ (tree *type, int tcode, const char *name);
317 static void ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
318 int code);
319 static ffeglobal ffecom_finish_global_ (ffeglobal global);
320 static ffesymbol ffecom_finish_symbol_transform_ (ffesymbol s);
321 static tree ffecom_get_appended_identifier_ (char us, const char *text);
322 static tree ffecom_get_external_identifier_ (ffesymbol s);
323 static tree ffecom_get_identifier_ (const char *text);
324 static tree ffecom_gen_sfuncdef_ (ffesymbol s,
325 ffeinfoBasictype bt,
326 ffeinfoKindtype kt);
327 static const char *ffecom_gfrt_args_ (ffecomGfrt ix);
328 static tree ffecom_gfrt_tree_ (ffecomGfrt ix);
329 static tree ffecom_init_zero_ (tree decl);
330 static tree ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
331 tree *maybe_tree);
332 static tree ffecom_intrinsic_len_ (ffebld expr);
333 static void ffecom_let_char_ (tree dest_tree,
334 tree dest_length,
335 ffetargetCharacterSize dest_size,
336 ffebld source);
337 static void ffecom_make_gfrt_ (ffecomGfrt ix);
338 static void ffecom_member_phase1_ (ffestorag mst, ffestorag st);
339 static void ffecom_member_phase2_ (ffestorag mst, ffestorag st);
340 static void ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size,
341 ffebld source);
342 static void ffecom_push_dummy_decls_ (ffebld dumlist,
343 bool stmtfunc);
344 static void ffecom_start_progunit_ (void);
345 static ffesymbol ffecom_sym_transform_ (ffesymbol s);
346 static ffesymbol ffecom_sym_transform_assign_ (ffesymbol s);
347 static void ffecom_transform_common_ (ffesymbol s);
348 static void ffecom_transform_equiv_ (ffestorag st);
349 static tree ffecom_transform_namelist_ (ffesymbol s);
350 static void ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
351 tree t);
352 static void ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
353 tree *size, tree tree);
354 static tree ffecom_tree_divide_ (tree tree_type, tree left, tree right,
355 tree dest_tree, ffebld dest,
356 bool *dest_used, tree hook);
357 static tree ffecom_type_localvar_ (ffesymbol s,
358 ffeinfoBasictype bt,
359 ffeinfoKindtype kt);
360 static tree ffecom_type_namelist_ (void);
361 static tree ffecom_type_vardesc_ (void);
362 static tree ffecom_vardesc_ (ffebld expr);
363 static tree ffecom_vardesc_array_ (ffesymbol s);
364 static tree ffecom_vardesc_dims_ (ffesymbol s);
365 static tree ffecom_convert_narrow_ (tree type, tree expr);
366 static tree ffecom_convert_widen_ (tree type, tree expr);
367
368 /* These are static functions that parallel those found in the C front
369 end and thus have the same names. */
370
371 static tree bison_rule_compstmt_ (void);
372 static void bison_rule_pushlevel_ (void);
373 static void delete_block (tree block);
374 static int duplicate_decls (tree newdecl, tree olddecl);
375 static void finish_decl (tree decl, tree init, bool is_top_level);
376 static void finish_function (int nested);
377 static const char *ffe_printable_name (tree decl, int v);
378 static void ffe_print_error_function (diagnostic_context *, const char *);
379 static tree lookup_name_current_level (tree name);
380 static struct f_binding_level *make_binding_level (void);
381 static void pop_f_function_context (void);
382 static void push_f_function_context (void);
383 static void push_parm_decl (tree parm);
384 static tree pushdecl_top_level (tree decl);
385 static int kept_level_p (void);
386 static tree storedecls (tree decls);
387 static void store_parm_decls (int is_main_program);
388 static tree start_decl (tree decl, bool is_top_level);
389 static void start_function (tree name, tree type, int nested, int public);
390 static void ffecom_file_ (const char *name);
391 static void ffecom_close_include_ (FILE *f);
392 static FILE *ffecom_open_include_ (char *name, ffewhereLine l,
393 ffewhereColumn c);
394
395 /* Static objects accessed by functions in this module. */
396
397 static ffesymbol ffecom_primary_entry_ = NULL;
398 static ffesymbol ffecom_nested_entry_ = NULL;
399 static ffeinfoKind ffecom_primary_entry_kind_;
400 static bool ffecom_primary_entry_is_proc_;
401 static GTY(()) tree ffecom_outer_function_decl_;
402 static GTY(()) tree ffecom_previous_function_decl_;
403 static GTY(()) tree ffecom_which_entrypoint_decl_;
404 static GTY(()) tree ffecom_float_zero_;
405 static GTY(()) tree ffecom_float_half_;
406 static GTY(()) tree ffecom_double_zero_;
407 static GTY(()) tree ffecom_double_half_;
408 static GTY(()) tree ffecom_func_result_;/* For functions. */
409 static GTY(()) tree ffecom_func_length_;/* For CHARACTER fns. */
410 static ffebld ffecom_list_blockdata_;
411 static ffebld ffecom_list_common_;
412 static ffebld ffecom_master_arglist_;
413 static ffeinfoBasictype ffecom_master_bt_;
414 static ffeinfoKindtype ffecom_master_kt_;
415 static ffetargetCharacterSize ffecom_master_size_;
416 static int ffecom_num_fns_ = 0;
417 static int ffecom_num_entrypoints_ = 0;
418 static bool ffecom_is_altreturning_ = FALSE;
419 static GTY(()) tree ffecom_multi_type_node_;
420 static GTY(()) tree ffecom_multi_retval_;
421 static GTY(()) tree
422 ffecom_multi_fields_[FFEINFO_basictype][FFEINFO_kindtype];
423 static bool ffecom_member_namelisted_; /* _member_phase1_ namelisted? */
424 static bool ffecom_doing_entry_ = FALSE;
425 static bool ffecom_transform_only_dummies_ = FALSE;
426 static int ffecom_typesize_pointer_;
427 static int ffecom_typesize_integer1_;
428
429 /* Holds pointer-to-function expressions. */
430
431 static GTY(()) tree ffecom_gfrt_[FFECOM_gfrt];
432
433 /* Holds the external names of the functions. */
434
435 static const char *const ffecom_gfrt_name_[FFECOM_gfrt]
436 =
437 {
438 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) NAME,
439 #include "com-rt.def"
440 #undef DEFGFRT
441 };
442
443 /* Whether the function returns. */
444
445 static const bool ffecom_gfrt_volatile_[FFECOM_gfrt]
446 =
447 {
448 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) VOLATILE,
449 #include "com-rt.def"
450 #undef DEFGFRT
451 };
452
453 /* Whether the function returns type complex. */
454
455 static const bool ffecom_gfrt_complex_[FFECOM_gfrt]
456 =
457 {
458 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) COMPLEX,
459 #include "com-rt.def"
460 #undef DEFGFRT
461 };
462
463 /* Whether the function is const
464 (i.e., has no side effects and only depends on its arguments). */
465
466 static const bool ffecom_gfrt_const_[FFECOM_gfrt]
467 =
468 {
469 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) CONST,
470 #include "com-rt.def"
471 #undef DEFGFRT
472 };
473
474 /* Type code for the function return value. */
475
476 static const ffecomRttype_ ffecom_gfrt_type_[FFECOM_gfrt]
477 =
478 {
479 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) TYPE,
480 #include "com-rt.def"
481 #undef DEFGFRT
482 };
483
484 /* String of codes for the function's arguments. */
485
486 static const char *const ffecom_gfrt_argstring_[FFECOM_gfrt]
487 =
488 {
489 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) ARGS,
490 #include "com-rt.def"
491 #undef DEFGFRT
492 };
493
494 /* Internal macros. */
495
496 /* We let tm.h override the types used here, to handle trivial differences
497 such as the choice of unsigned int or long unsigned int for size_t.
498 When machines start needing nontrivial differences in the size type,
499 it would be best to do something here to figure out automatically
500 from other information what type to use. */
501
502 #ifndef SIZE_TYPE
503 #define SIZE_TYPE "long unsigned int"
504 #endif
505
506 #define ffecom_concat_list_count_(catlist) ((catlist).count)
507 #define ffecom_concat_list_expr_(catlist,i) ((catlist).exprs[(i)])
508 #define ffecom_concat_list_maxlen_(catlist) ((catlist).maxlen)
509 #define ffecom_concat_list_minlen_(catlist) ((catlist).minlen)
510
511 #define ffecom_char_args_(i,l,e) ffecom_char_args_x_((i),(l),(e),FALSE)
512 #define ffecom_char_args_with_null_(i,l,e) ffecom_char_args_x_((i),(l),(e),TRUE)
513
514 /* For each binding contour we allocate a binding_level structure
515 * which records the names defined in that contour.
516 * Contours include:
517 * 0) the global one
518 * 1) one for each function definition,
519 * where internal declarations of the parameters appear.
520 *
521 * The current meaning of a name can be found by searching the levels from
522 * the current one out to the global one.
523 */
524
525 /* Note that the information in the `names' component of the global contour
526 is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
527
528 struct f_binding_level GTY(())
529 {
530 /* A chain of _DECL nodes for all variables, constants, functions,
531 and typedef types. These are in the reverse of the order supplied.
532 */
533 tree names;
534
535 /* For each level (except not the global one),
536 a chain of BLOCK nodes for all the levels
537 that were entered and exited one level down. */
538 tree blocks;
539
540 /* The BLOCK node for this level, if one has been preallocated.
541 If 0, the BLOCK is allocated (if needed) when the level is popped. */
542 tree this_block;
543
544 /* The binding level which this one is contained in (inherits from). */
545 struct f_binding_level *level_chain;
546
547 /* 0: no ffecom_prepare_* functions called at this level yet;
548 1: ffecom_prepare* functions called, except not ffecom_prepare_end;
549 2: ffecom_prepare_end called. */
550 int prep_state;
551 };
552
553 #define NULL_BINDING_LEVEL (struct f_binding_level *) NULL
554
555 /* The binding level currently in effect. */
556
557 static GTY(()) struct f_binding_level *current_binding_level;
558
559 /* A chain of binding_level structures awaiting reuse. */
560
561 static GTY((deletable (""))) struct f_binding_level *free_binding_level;
562
563 /* The outermost binding level, for names of file scope.
564 This is created when the compiler is started and exists
565 through the entire run. */
566
567 static struct f_binding_level *global_binding_level;
568
569 /* Binding level structures are initialized by copying this one. */
570
571 static const struct f_binding_level clear_binding_level
572 =
573 {NULL, NULL, NULL, NULL_BINDING_LEVEL, 0};
574
575 /* Language-dependent contents of an identifier. */
576
577 struct lang_identifier GTY(())
578 {
579 struct tree_identifier common;
580 tree global_value;
581 tree local_value;
582 tree label_value;
583 bool invented;
584 };
585
586 /* Macros for access to language-specific slots in an identifier. */
587 /* Each of these slots contains a DECL node or null. */
588
589 /* This represents the value which the identifier has in the
590 file-scope namespace. */
591 #define IDENTIFIER_GLOBAL_VALUE(NODE) \
592 (((struct lang_identifier *)(NODE))->global_value)
593 /* This represents the value which the identifier has in the current
594 scope. */
595 #define IDENTIFIER_LOCAL_VALUE(NODE) \
596 (((struct lang_identifier *)(NODE))->local_value)
597 /* This represents the value which the identifier has as a label in
598 the current label scope. */
599 #define IDENTIFIER_LABEL_VALUE(NODE) \
600 (((struct lang_identifier *)(NODE))->label_value)
601 /* This is nonzero if the identifier was "made up" by g77 code. */
602 #define IDENTIFIER_INVENTED(NODE) \
603 (((struct lang_identifier *)(NODE))->invented)
604
605 /* The resulting tree type. */
606 union lang_tree_node
607 GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
608 chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
609 {
610 union tree_node GTY ((tag ("0"),
611 desc ("tree_node_structure (&%h)")))
612 generic;
613 struct lang_identifier GTY ((tag ("1"))) identifier;
614 };
615
616 /* Fortran doesn't use either of these. */
617 struct lang_decl GTY(())
618 {
619 };
620 struct lang_type GTY(())
621 {
622 };
623
624 /* In identifiers, C uses the following fields in a special way:
625 TREE_PUBLIC to record that there was a previous local extern decl.
626 TREE_USED to record that such a decl was used.
627 TREE_ADDRESSABLE to record that the address of such a decl was used. */
628
629 /* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
630 that have names. Here so we can clear out their names' definitions
631 at the end of the function. */
632
633 static GTY(()) tree named_labels;
634
635 /* A list of LABEL_DECLs from outer contexts that are currently shadowed. */
636
637 static GTY(()) tree shadowed_labels;
638 \f
639 /* Return the subscript expression, modified to do range-checking.
640
641 `array' is the array to be checked against.
642 `element' is the subscript expression to check.
643 `dim' is the dimension number (starting at 0).
644 `total_dims' is the total number of dimensions (0 for CHARACTER substring).
645 */
646
647 static tree
648 ffecom_subscript_check_ (tree array, tree element, int dim, int total_dims,
649 const char *array_name)
650 {
651 tree low = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
652 tree high = TYPE_MAX_VALUE (TYPE_DOMAIN (array));
653 tree cond;
654 tree die;
655 tree args;
656
657 if (element == error_mark_node)
658 return element;
659
660 if (TREE_TYPE (low) != TREE_TYPE (element))
661 {
662 if (TYPE_PRECISION (TREE_TYPE (low))
663 > TYPE_PRECISION (TREE_TYPE (element)))
664 element = convert (TREE_TYPE (low), element);
665 else
666 {
667 low = convert (TREE_TYPE (element), low);
668 if (high)
669 high = convert (TREE_TYPE (element), high);
670 }
671 }
672
673 element = ffecom_save_tree (element);
674 if (total_dims == 0)
675 {
676 /* Special handling for substring range checks. Fortran allows the
677 end subscript < begin subscript, which means that expressions like
678 string(1:0) are valid (and yield a null string). In view of this,
679 enforce two simpler conditions:
680 1) element<=high for end-substring;
681 2) element>=low for start-substring.
682 Run-time character movement will enforce remaining conditions.
683
684 More complicated checks would be better, but present structure only
685 provides one index element at a time, so it is not possible to
686 enforce a check of both i and j in string(i:j). If it were, the
687 complete set of rules would read,
688 if ( ((j<i) && ((low<=i<=high) || (low<=j<=high))) ||
689 ((low<=i<=high) && (low<=j<=high)) )
690 ok ;
691 else
692 range error ;
693 */
694 if (dim)
695 cond = ffecom_2 (LE_EXPR, integer_type_node, element, high);
696 else
697 cond = ffecom_2 (LE_EXPR, integer_type_node, low, element);
698 }
699 else
700 {
701 /* Array reference substring range checking. */
702
703 cond = ffecom_2 (LE_EXPR, integer_type_node,
704 low,
705 element);
706 if (high)
707 {
708 cond = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
709 cond,
710 ffecom_2 (LE_EXPR, integer_type_node,
711 element,
712 high));
713 }
714 }
715
716 {
717 int len;
718 char *proc;
719 char *var;
720 tree arg3;
721 tree arg2;
722 tree arg1;
723 tree arg4;
724
725 switch (total_dims)
726 {
727 case 0:
728 var = concat (array_name, "[", (dim ? "end" : "start"),
729 "-substring]", NULL);
730 len = strlen (var) + 1;
731 arg1 = build_string (len, var);
732 free (var);
733 break;
734
735 case 1:
736 len = strlen (array_name) + 1;
737 arg1 = build_string (len, array_name);
738 break;
739
740 default:
741 var = xmalloc (strlen (array_name) + 40);
742 sprintf (var, "%s[subscript-%d-of-%d]",
743 array_name,
744 dim + 1, total_dims);
745 len = strlen (var) + 1;
746 arg1 = build_string (len, var);
747 free (var);
748 break;
749 }
750
751 TREE_TYPE (arg1)
752 = build_type_variant (build_array_type (char_type_node,
753 build_range_type
754 (integer_type_node,
755 integer_one_node,
756 build_int_2 (len, 0))),
757 1, 0);
758 TREE_CONSTANT (arg1) = 1;
759 TREE_STATIC (arg1) = 1;
760 arg1 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg1)),
761 arg1);
762
763 /* s_rnge adds one to the element to print it, so bias against
764 that -- want to print a faithful *subscript* value. */
765 arg2 = convert (ffecom_f2c_ftnint_type_node,
766 ffecom_2 (MINUS_EXPR,
767 TREE_TYPE (element),
768 element,
769 convert (TREE_TYPE (element),
770 integer_one_node)));
771
772 proc = concat (input_filename, "/",
773 IDENTIFIER_POINTER (DECL_NAME (current_function_decl)),
774 NULL);
775 len = strlen (proc) + 1;
776 arg3 = build_string (len, proc);
777
778 free (proc);
779
780 TREE_TYPE (arg3)
781 = build_type_variant (build_array_type (char_type_node,
782 build_range_type
783 (integer_type_node,
784 integer_one_node,
785 build_int_2 (len, 0))),
786 1, 0);
787 TREE_CONSTANT (arg3) = 1;
788 TREE_STATIC (arg3) = 1;
789 arg3 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg3)),
790 arg3);
791
792 arg4 = convert (ffecom_f2c_ftnint_type_node,
793 build_int_2 (input_line, 0));
794
795 arg1 = build_tree_list (NULL_TREE, arg1);
796 arg2 = build_tree_list (NULL_TREE, arg2);
797 arg3 = build_tree_list (NULL_TREE, arg3);
798 arg4 = build_tree_list (NULL_TREE, arg4);
799 TREE_CHAIN (arg3) = arg4;
800 TREE_CHAIN (arg2) = arg3;
801 TREE_CHAIN (arg1) = arg2;
802
803 args = arg1;
804 }
805 die = ffecom_call_gfrt (FFECOM_gfrtRANGE,
806 args, NULL_TREE);
807 TREE_SIDE_EFFECTS (die) = 1;
808 die = convert (void_type_node, die);
809
810 element = ffecom_3 (COND_EXPR,
811 TREE_TYPE (element),
812 cond,
813 element,
814 die);
815
816 return element;
817 }
818
819 /* Return the computed element of an array reference.
820
821 `item' is NULL_TREE, or the transformed pointer to the array.
822 `expr' is the original opARRAYREF expression, which is transformed
823 if `item' is NULL_TREE.
824 `want_ptr' is nonzero if a pointer to the element, instead of
825 the element itself, is to be returned. */
826
827 static tree
828 ffecom_arrayref_ (tree item, ffebld expr, int want_ptr)
829 {
830 ffebld dims[FFECOM_dimensionsMAX];
831 int i;
832 int total_dims;
833 int flatten = ffe_is_flatten_arrays ();
834 int need_ptr;
835 tree array;
836 tree element;
837 tree tree_type;
838 tree tree_type_x;
839 const char *array_name;
840 ffetype type;
841 ffebld list;
842
843 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER)
844 array_name = ffesymbol_text (ffebld_symter (ffebld_left (expr)));
845 else
846 array_name = "[expr?]";
847
848 /* Build up ARRAY_REFs in reverse order (since we're column major
849 here in Fortran land). */
850
851 for (i = 0, list = ffebld_right (expr);
852 list != NULL;
853 ++i, list = ffebld_trail (list))
854 {
855 dims[i] = ffebld_head (list);
856 type = ffeinfo_type (ffebld_basictype (dims[i]),
857 ffebld_kindtype (dims[i]));
858 if (! flatten
859 && ffecom_typesize_pointer_ > ffecom_typesize_integer1_
860 && ffetype_size (type) > ffecom_typesize_integer1_)
861 /* E.g. ARRAY(INDEX), given INTEGER*8 INDEX, on a system with 64-bit
862 pointers and 32-bit integers. Do the full 64-bit pointer
863 arithmetic, for codes using arrays for nonstandard heap-like
864 work. */
865 flatten = 1;
866 }
867
868 total_dims = i;
869
870 need_ptr = want_ptr || flatten;
871
872 if (! item)
873 {
874 if (need_ptr)
875 item = ffecom_ptr_to_expr (ffebld_left (expr));
876 else
877 item = ffecom_expr (ffebld_left (expr));
878
879 if (item == error_mark_node)
880 return item;
881
882 if (ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereFLEETING
883 && ! ffe_mark_addressable (item))
884 return error_mark_node;
885 }
886
887 if (item == error_mark_node)
888 return item;
889
890 if (need_ptr)
891 {
892 tree min;
893
894 for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
895 i >= 0;
896 --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
897 {
898 min = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
899 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
900 if (flag_bounds_check)
901 element = ffecom_subscript_check_ (array, element, i, total_dims,
902 array_name);
903 if (element == error_mark_node)
904 return element;
905
906 /* Widen integral arithmetic as desired while preserving
907 signedness. */
908 tree_type = TREE_TYPE (element);
909 tree_type_x = tree_type;
910 if (tree_type
911 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
912 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
913 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
914
915 if (TREE_TYPE (min) != tree_type_x)
916 min = convert (tree_type_x, min);
917 if (TREE_TYPE (element) != tree_type_x)
918 element = convert (tree_type_x, element);
919
920 item = ffecom_2 (PLUS_EXPR,
921 build_pointer_type (TREE_TYPE (array)),
922 item,
923 size_binop (MULT_EXPR,
924 size_in_bytes (TREE_TYPE (array)),
925 convert (sizetype,
926 fold (build (MINUS_EXPR,
927 tree_type_x,
928 element, min)))));
929 }
930 if (! want_ptr)
931 {
932 item = ffecom_1 (INDIRECT_REF,
933 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
934 item);
935 }
936 }
937 else
938 {
939 for (--i;
940 i >= 0;
941 --i)
942 {
943 array = TYPE_MAIN_VARIANT (TREE_TYPE (item));
944
945 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
946 if (flag_bounds_check)
947 element = ffecom_subscript_check_ (array, element, i, total_dims,
948 array_name);
949 if (element == error_mark_node)
950 return element;
951
952 /* Widen integral arithmetic as desired while preserving
953 signedness. */
954 tree_type = TREE_TYPE (element);
955 tree_type_x = tree_type;
956 if (tree_type
957 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
958 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
959 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
960
961 element = convert (tree_type_x, element);
962
963 item = ffecom_2 (ARRAY_REF,
964 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
965 item,
966 element);
967 }
968 }
969
970 return item;
971 }
972
973 /* This is like gcc's stabilize_reference -- in fact, most of the code
974 comes from that -- but it handles the situation where the reference
975 is going to have its subparts picked at, and it shouldn't change
976 (or trigger extra invocations of functions in the subtrees) due to
977 this. save_expr is a bit overzealous, because we don't need the
978 entire thing calculated and saved like a temp. So, for DECLs, no
979 change is needed, because these are stable aggregates, and ARRAY_REF
980 and such might well be stable too, but for things like calculations,
981 we do need to calculate a snapshot of a value before picking at it. */
982
983 static tree
984 ffecom_stabilize_aggregate_ (tree ref)
985 {
986 tree result;
987 enum tree_code code = TREE_CODE (ref);
988
989 switch (code)
990 {
991 case VAR_DECL:
992 case PARM_DECL:
993 case RESULT_DECL:
994 /* No action is needed in this case. */
995 return ref;
996
997 case NOP_EXPR:
998 case CONVERT_EXPR:
999 case FLOAT_EXPR:
1000 case FIX_TRUNC_EXPR:
1001 case FIX_FLOOR_EXPR:
1002 case FIX_ROUND_EXPR:
1003 case FIX_CEIL_EXPR:
1004 result = build_nt (code, stabilize_reference (TREE_OPERAND (ref, 0)));
1005 break;
1006
1007 case INDIRECT_REF:
1008 result = build_nt (INDIRECT_REF,
1009 stabilize_reference_1 (TREE_OPERAND (ref, 0)));
1010 break;
1011
1012 case COMPONENT_REF:
1013 result = build_nt (COMPONENT_REF,
1014 stabilize_reference (TREE_OPERAND (ref, 0)),
1015 TREE_OPERAND (ref, 1));
1016 break;
1017
1018 case BIT_FIELD_REF:
1019 result = build_nt (BIT_FIELD_REF,
1020 stabilize_reference (TREE_OPERAND (ref, 0)),
1021 stabilize_reference_1 (TREE_OPERAND (ref, 1)),
1022 stabilize_reference_1 (TREE_OPERAND (ref, 2)));
1023 break;
1024
1025 case ARRAY_REF:
1026 result = build_nt (ARRAY_REF,
1027 stabilize_reference (TREE_OPERAND (ref, 0)),
1028 stabilize_reference_1 (TREE_OPERAND (ref, 1)));
1029 break;
1030
1031 case COMPOUND_EXPR:
1032 result = build_nt (COMPOUND_EXPR,
1033 stabilize_reference_1 (TREE_OPERAND (ref, 0)),
1034 stabilize_reference (TREE_OPERAND (ref, 1)));
1035 break;
1036
1037 case RTL_EXPR:
1038 abort ();
1039
1040
1041 default:
1042 return save_expr (ref);
1043
1044 case ERROR_MARK:
1045 return error_mark_node;
1046 }
1047
1048 TREE_TYPE (result) = TREE_TYPE (ref);
1049 TREE_READONLY (result) = TREE_READONLY (ref);
1050 TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (ref);
1051 TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (ref);
1052
1053 return result;
1054 }
1055
1056 /* A rip-off of gcc's convert.c convert_to_complex function,
1057 reworked to handle complex implemented as C structures
1058 (RECORD_TYPE with two fields, real and imaginary `r' and `i'). */
1059
1060 static tree
1061 ffecom_convert_to_complex_ (tree type, tree expr)
1062 {
1063 register enum tree_code form = TREE_CODE (TREE_TYPE (expr));
1064 tree subtype;
1065
1066 assert (TREE_CODE (type) == RECORD_TYPE);
1067
1068 subtype = TREE_TYPE (TYPE_FIELDS (type));
1069
1070 if (form == REAL_TYPE || form == INTEGER_TYPE || form == ENUMERAL_TYPE)
1071 {
1072 expr = convert (subtype, expr);
1073 return ffecom_2 (COMPLEX_EXPR, type, expr,
1074 convert (subtype, integer_zero_node));
1075 }
1076
1077 if (form == RECORD_TYPE)
1078 {
1079 tree elt_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr)));
1080 if (TYPE_MAIN_VARIANT (elt_type) == TYPE_MAIN_VARIANT (subtype))
1081 return expr;
1082 else
1083 {
1084 expr = save_expr (expr);
1085 return ffecom_2 (COMPLEX_EXPR,
1086 type,
1087 convert (subtype,
1088 ffecom_1 (REALPART_EXPR,
1089 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1090 expr)),
1091 convert (subtype,
1092 ffecom_1 (IMAGPART_EXPR,
1093 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1094 expr)));
1095 }
1096 }
1097
1098 if (form == POINTER_TYPE || form == REFERENCE_TYPE)
1099 error ("pointer value used where a complex was expected");
1100 else
1101 error ("aggregate value used where a complex was expected");
1102
1103 return ffecom_2 (COMPLEX_EXPR, type,
1104 convert (subtype, integer_zero_node),
1105 convert (subtype, integer_zero_node));
1106 }
1107
1108 /* Like gcc's convert(), but crashes if widening might happen. */
1109
1110 static tree
1111 ffecom_convert_narrow_ (tree type, tree expr)
1112 {
1113 register tree e = expr;
1114 register enum tree_code code = TREE_CODE (type);
1115
1116 if (type == TREE_TYPE (e)
1117 || TREE_CODE (e) == ERROR_MARK)
1118 return e;
1119 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1120 return fold (build1 (NOP_EXPR, type, e));
1121 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1122 || code == ERROR_MARK)
1123 return error_mark_node;
1124 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1125 {
1126 assert ("void value not ignored as it ought to be" == NULL);
1127 return error_mark_node;
1128 }
1129 assert (code != VOID_TYPE);
1130 if ((code != RECORD_TYPE)
1131 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1132 assert ("converting COMPLEX to REAL" == NULL);
1133 assert (code != ENUMERAL_TYPE);
1134 if (code == INTEGER_TYPE)
1135 {
1136 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1137 && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)))
1138 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1139 && (TYPE_PRECISION (type)
1140 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
1141 return fold (convert_to_integer (type, e));
1142 }
1143 if (code == POINTER_TYPE)
1144 {
1145 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1146 return fold (convert_to_pointer (type, e));
1147 }
1148 if (code == REAL_TYPE)
1149 {
1150 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1151 assert (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)));
1152 return fold (convert_to_real (type, e));
1153 }
1154 if (code == COMPLEX_TYPE)
1155 {
1156 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1157 assert (TYPE_PRECISION (TREE_TYPE (type)) <= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1158 return fold (convert_to_complex (type, e));
1159 }
1160 if (code == RECORD_TYPE)
1161 {
1162 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
1163 /* Check that at least the first field name agrees. */
1164 assert (DECL_NAME (TYPE_FIELDS (type))
1165 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
1166 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1167 <= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
1168 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1169 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1170 return e;
1171 return fold (ffecom_convert_to_complex_ (type, e));
1172 }
1173
1174 assert ("conversion to non-scalar type requested" == NULL);
1175 return error_mark_node;
1176 }
1177
1178 /* Like gcc's convert(), but crashes if narrowing might happen. */
1179
1180 static tree
1181 ffecom_convert_widen_ (tree type, tree expr)
1182 {
1183 register tree e = expr;
1184 register enum tree_code code = TREE_CODE (type);
1185
1186 if (type == TREE_TYPE (e)
1187 || TREE_CODE (e) == ERROR_MARK)
1188 return e;
1189 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1190 return fold (build1 (NOP_EXPR, type, e));
1191 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1192 || code == ERROR_MARK)
1193 return error_mark_node;
1194 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1195 {
1196 assert ("void value not ignored as it ought to be" == NULL);
1197 return error_mark_node;
1198 }
1199 assert (code != VOID_TYPE);
1200 if ((code != RECORD_TYPE)
1201 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1202 assert ("narrowing COMPLEX to REAL" == NULL);
1203 assert (code != ENUMERAL_TYPE);
1204 if (code == INTEGER_TYPE)
1205 {
1206 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1207 && TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)))
1208 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1209 && (TYPE_PRECISION (type)
1210 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
1211 return fold (convert_to_integer (type, e));
1212 }
1213 if (code == POINTER_TYPE)
1214 {
1215 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1216 return fold (convert_to_pointer (type, e));
1217 }
1218 if (code == REAL_TYPE)
1219 {
1220 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1221 assert (TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)));
1222 return fold (convert_to_real (type, e));
1223 }
1224 if (code == COMPLEX_TYPE)
1225 {
1226 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1227 assert (TYPE_PRECISION (TREE_TYPE (type)) >= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1228 return fold (convert_to_complex (type, e));
1229 }
1230 if (code == RECORD_TYPE)
1231 {
1232 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
1233 /* Check that at least the first field name agrees. */
1234 assert (DECL_NAME (TYPE_FIELDS (type))
1235 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
1236 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1237 >= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
1238 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1239 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1240 return e;
1241 return fold (ffecom_convert_to_complex_ (type, e));
1242 }
1243
1244 assert ("conversion to non-scalar type requested" == NULL);
1245 return error_mark_node;
1246 }
1247
1248 /* Handles making a COMPLEX type, either the standard
1249 (but buggy?) gbe way, or the safer (but less elegant?)
1250 f2c way. */
1251
1252 static tree
1253 ffecom_make_complex_type_ (tree subtype)
1254 {
1255 tree type;
1256 tree realfield;
1257 tree imagfield;
1258
1259 if (ffe_is_emulate_complex ())
1260 {
1261 type = make_node (RECORD_TYPE);
1262 realfield = ffecom_decl_field (type, NULL_TREE, "r", subtype);
1263 imagfield = ffecom_decl_field (type, realfield, "i", subtype);
1264 TYPE_FIELDS (type) = realfield;
1265 layout_type (type);
1266 }
1267 else
1268 {
1269 type = make_node (COMPLEX_TYPE);
1270 TREE_TYPE (type) = subtype;
1271 layout_type (type);
1272 }
1273
1274 return type;
1275 }
1276
1277 /* Chooses either the gbe or the f2c way to build a
1278 complex constant. */
1279
1280 static tree
1281 ffecom_build_complex_constant_ (tree type, tree realpart, tree imagpart)
1282 {
1283 tree bothparts;
1284
1285 if (ffe_is_emulate_complex ())
1286 {
1287 bothparts = build_tree_list (TYPE_FIELDS (type), realpart);
1288 TREE_CHAIN (bothparts) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), imagpart);
1289 bothparts = build_constructor (type, bothparts);
1290 }
1291 else
1292 {
1293 bothparts = build_complex (type, realpart, imagpart);
1294 }
1295
1296 return bothparts;
1297 }
1298
1299 static tree
1300 ffecom_arglist_expr_ (const char *c, ffebld expr)
1301 {
1302 tree list;
1303 tree *plist = &list;
1304 tree trail = NULL_TREE; /* Append char length args here. */
1305 tree *ptrail = &trail;
1306 tree length;
1307 ffebld exprh;
1308 tree item;
1309 bool ptr = FALSE;
1310 tree wanted = NULL_TREE;
1311 static const char zed[] = "0";
1312
1313 if (c == NULL)
1314 c = &zed[0];
1315
1316 while (expr != NULL)
1317 {
1318 if (*c != '\0')
1319 {
1320 ptr = FALSE;
1321 if (*c == '&')
1322 {
1323 ptr = TRUE;
1324 ++c;
1325 }
1326 switch (*(c++))
1327 {
1328 case '\0':
1329 ptr = TRUE;
1330 wanted = NULL_TREE;
1331 break;
1332
1333 case 'a':
1334 assert (ptr);
1335 wanted = NULL_TREE;
1336 break;
1337
1338 case 'c':
1339 wanted = ffecom_f2c_complex_type_node;
1340 break;
1341
1342 case 'd':
1343 wanted = ffecom_f2c_doublereal_type_node;
1344 break;
1345
1346 case 'e':
1347 wanted = ffecom_f2c_doublecomplex_type_node;
1348 break;
1349
1350 case 'f':
1351 wanted = ffecom_f2c_real_type_node;
1352 break;
1353
1354 case 'i':
1355 wanted = ffecom_f2c_integer_type_node;
1356 break;
1357
1358 case 'j':
1359 wanted = ffecom_f2c_longint_type_node;
1360 break;
1361
1362 default:
1363 assert ("bad argstring code" == NULL);
1364 wanted = NULL_TREE;
1365 break;
1366 }
1367 }
1368
1369 exprh = ffebld_head (expr);
1370 if (exprh == NULL)
1371 wanted = NULL_TREE;
1372
1373 if ((wanted == NULL_TREE)
1374 || (ptr
1375 && (TYPE_MODE
1376 (ffecom_tree_type[ffeinfo_basictype (ffebld_info (exprh))]
1377 [ffeinfo_kindtype (ffebld_info (exprh))])
1378 == TYPE_MODE (wanted))))
1379 *plist
1380 = build_tree_list (NULL_TREE,
1381 ffecom_arg_ptr_to_expr (exprh,
1382 &length));
1383 else
1384 {
1385 item = ffecom_arg_expr (exprh, &length);
1386 item = ffecom_convert_widen_ (wanted, item);
1387 if (ptr)
1388 {
1389 item = ffecom_1 (ADDR_EXPR,
1390 build_pointer_type (TREE_TYPE (item)),
1391 item);
1392 }
1393 *plist
1394 = build_tree_list (NULL_TREE,
1395 item);
1396 }
1397
1398 plist = &TREE_CHAIN (*plist);
1399 expr = ffebld_trail (expr);
1400 if (length != NULL_TREE)
1401 {
1402 *ptrail = build_tree_list (NULL_TREE, length);
1403 ptrail = &TREE_CHAIN (*ptrail);
1404 }
1405 }
1406
1407 /* We've run out of args in the call; if the implementation expects
1408 more, supply null pointers for them, which the implementation can
1409 check to see if an arg was omitted. */
1410
1411 while (*c != '\0' && *c != '0')
1412 {
1413 if (*c == '&')
1414 ++c;
1415 else
1416 assert ("missing arg to run-time routine!" == NULL);
1417
1418 switch (*(c++))
1419 {
1420 case '\0':
1421 case 'a':
1422 case 'c':
1423 case 'd':
1424 case 'e':
1425 case 'f':
1426 case 'i':
1427 case 'j':
1428 break;
1429
1430 default:
1431 assert ("bad arg string code" == NULL);
1432 break;
1433 }
1434 *plist
1435 = build_tree_list (NULL_TREE,
1436 null_pointer_node);
1437 plist = &TREE_CHAIN (*plist);
1438 }
1439
1440 *plist = trail;
1441
1442 return list;
1443 }
1444
1445 static tree
1446 ffecom_widest_expr_type_ (ffebld list)
1447 {
1448 ffebld item;
1449 ffebld widest = NULL;
1450 ffetype type;
1451 ffetype widest_type = NULL;
1452 tree t;
1453
1454 for (; list != NULL; list = ffebld_trail (list))
1455 {
1456 item = ffebld_head (list);
1457 if (item == NULL)
1458 continue;
1459 if ((widest != NULL)
1460 && (ffeinfo_basictype (ffebld_info (item))
1461 != ffeinfo_basictype (ffebld_info (widest))))
1462 continue;
1463 type = ffeinfo_type (ffeinfo_basictype (ffebld_info (item)),
1464 ffeinfo_kindtype (ffebld_info (item)));
1465 if ((widest == FFEINFO_kindtypeNONE)
1466 || (ffetype_size (type)
1467 > ffetype_size (widest_type)))
1468 {
1469 widest = item;
1470 widest_type = type;
1471 }
1472 }
1473
1474 assert (widest != NULL);
1475 t = ffecom_tree_type[ffeinfo_basictype (ffebld_info (widest))]
1476 [ffeinfo_kindtype (ffebld_info (widest))];
1477 assert (t != NULL_TREE);
1478 return t;
1479 }
1480
1481 /* Check whether a partial overlap between two expressions is possible.
1482
1483 Can *starting* to write a portion of expr1 change the value
1484 computed (perhaps already, *partially*) by expr2?
1485
1486 Currently, this is a concern only for a COMPLEX expr1. But if it
1487 isn't in COMMON or local EQUIVALENCE, since we don't support
1488 aliasing of arguments, it isn't a concern. */
1489
1490 static bool
1491 ffecom_possible_partial_overlap_ (ffebld expr1, ffebld expr2 ATTRIBUTE_UNUSED)
1492 {
1493 ffesymbol sym;
1494 ffestorag st;
1495
1496 switch (ffebld_op (expr1))
1497 {
1498 case FFEBLD_opSYMTER:
1499 sym = ffebld_symter (expr1);
1500 break;
1501
1502 case FFEBLD_opARRAYREF:
1503 if (ffebld_op (ffebld_left (expr1)) != FFEBLD_opSYMTER)
1504 return FALSE;
1505 sym = ffebld_symter (ffebld_left (expr1));
1506 break;
1507
1508 default:
1509 return FALSE;
1510 }
1511
1512 if (ffesymbol_where (sym) != FFEINFO_whereCOMMON
1513 && (ffesymbol_where (sym) != FFEINFO_whereLOCAL
1514 || ! (st = ffesymbol_storage (sym))
1515 || ! ffestorag_parent (st)))
1516 return FALSE;
1517
1518 /* It's in COMMON or local EQUIVALENCE. */
1519
1520 return TRUE;
1521 }
1522
1523 /* Check whether dest and source might overlap. ffebld versions of these
1524 might or might not be passed, will be NULL if not.
1525
1526 The test is really whether source_tree is modifiable and, if modified,
1527 might overlap destination such that the value(s) in the destination might
1528 change before it is finally modified. dest_* are the canonized
1529 destination itself. */
1530
1531 static bool
1532 ffecom_overlap_ (tree dest_decl, tree dest_offset, tree dest_size,
1533 tree source_tree, ffebld source UNUSED,
1534 bool scalar_arg)
1535 {
1536 tree source_decl;
1537 tree source_offset;
1538 tree source_size;
1539 tree t;
1540
1541 if (source_tree == NULL_TREE)
1542 return FALSE;
1543
1544 switch (TREE_CODE (source_tree))
1545 {
1546 case ERROR_MARK:
1547 case IDENTIFIER_NODE:
1548 case INTEGER_CST:
1549 case REAL_CST:
1550 case COMPLEX_CST:
1551 case STRING_CST:
1552 case CONST_DECL:
1553 case VAR_DECL:
1554 case RESULT_DECL:
1555 case FIELD_DECL:
1556 case MINUS_EXPR:
1557 case MULT_EXPR:
1558 case TRUNC_DIV_EXPR:
1559 case CEIL_DIV_EXPR:
1560 case FLOOR_DIV_EXPR:
1561 case ROUND_DIV_EXPR:
1562 case TRUNC_MOD_EXPR:
1563 case CEIL_MOD_EXPR:
1564 case FLOOR_MOD_EXPR:
1565 case ROUND_MOD_EXPR:
1566 case RDIV_EXPR:
1567 case EXACT_DIV_EXPR:
1568 case FIX_TRUNC_EXPR:
1569 case FIX_CEIL_EXPR:
1570 case FIX_FLOOR_EXPR:
1571 case FIX_ROUND_EXPR:
1572 case FLOAT_EXPR:
1573 case NEGATE_EXPR:
1574 case MIN_EXPR:
1575 case MAX_EXPR:
1576 case ABS_EXPR:
1577 case FFS_EXPR:
1578 case LSHIFT_EXPR:
1579 case RSHIFT_EXPR:
1580 case LROTATE_EXPR:
1581 case RROTATE_EXPR:
1582 case BIT_IOR_EXPR:
1583 case BIT_XOR_EXPR:
1584 case BIT_AND_EXPR:
1585 case BIT_ANDTC_EXPR:
1586 case BIT_NOT_EXPR:
1587 case TRUTH_ANDIF_EXPR:
1588 case TRUTH_ORIF_EXPR:
1589 case TRUTH_AND_EXPR:
1590 case TRUTH_OR_EXPR:
1591 case TRUTH_XOR_EXPR:
1592 case TRUTH_NOT_EXPR:
1593 case LT_EXPR:
1594 case LE_EXPR:
1595 case GT_EXPR:
1596 case GE_EXPR:
1597 case EQ_EXPR:
1598 case NE_EXPR:
1599 case COMPLEX_EXPR:
1600 case CONJ_EXPR:
1601 case REALPART_EXPR:
1602 case IMAGPART_EXPR:
1603 case LABEL_EXPR:
1604 case COMPONENT_REF:
1605 return FALSE;
1606
1607 case COMPOUND_EXPR:
1608 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1609 TREE_OPERAND (source_tree, 1), NULL,
1610 scalar_arg);
1611
1612 case MODIFY_EXPR:
1613 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1614 TREE_OPERAND (source_tree, 0), NULL,
1615 scalar_arg);
1616
1617 case CONVERT_EXPR:
1618 case NOP_EXPR:
1619 case NON_LVALUE_EXPR:
1620 case PLUS_EXPR:
1621 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1622 return TRUE;
1623
1624 ffecom_tree_canonize_ptr_ (&source_decl, &source_offset,
1625 source_tree);
1626 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1627 break;
1628
1629 case COND_EXPR:
1630 return
1631 ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1632 TREE_OPERAND (source_tree, 1), NULL,
1633 scalar_arg)
1634 || ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1635 TREE_OPERAND (source_tree, 2), NULL,
1636 scalar_arg);
1637
1638
1639 case ADDR_EXPR:
1640 ffecom_tree_canonize_ref_ (&source_decl, &source_offset,
1641 &source_size,
1642 TREE_OPERAND (source_tree, 0));
1643 break;
1644
1645 case PARM_DECL:
1646 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1647 return TRUE;
1648
1649 source_decl = source_tree;
1650 source_offset = bitsize_zero_node;
1651 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1652 break;
1653
1654 case SAVE_EXPR:
1655 case REFERENCE_EXPR:
1656 case PREDECREMENT_EXPR:
1657 case PREINCREMENT_EXPR:
1658 case POSTDECREMENT_EXPR:
1659 case POSTINCREMENT_EXPR:
1660 case INDIRECT_REF:
1661 case ARRAY_REF:
1662 case CALL_EXPR:
1663 default:
1664 return TRUE;
1665 }
1666
1667 /* Come here when source_decl, source_offset, and source_size filled
1668 in appropriately. */
1669
1670 if (source_decl == NULL_TREE)
1671 return FALSE; /* No decl involved, so no overlap. */
1672
1673 if (source_decl != dest_decl)
1674 return FALSE; /* Different decl, no overlap. */
1675
1676 if (TREE_CODE (dest_size) == ERROR_MARK)
1677 return TRUE; /* Assignment into entire assumed-size
1678 array? Shouldn't happen.... */
1679
1680 t = ffecom_2 (LE_EXPR, integer_type_node,
1681 ffecom_2 (PLUS_EXPR, TREE_TYPE (dest_offset),
1682 dest_offset,
1683 convert (TREE_TYPE (dest_offset),
1684 dest_size)),
1685 convert (TREE_TYPE (dest_offset),
1686 source_offset));
1687
1688 if (integer_onep (t))
1689 return FALSE; /* Destination precedes source. */
1690
1691 if (!scalar_arg
1692 || (source_size == NULL_TREE)
1693 || (TREE_CODE (source_size) == ERROR_MARK)
1694 || integer_zerop (source_size))
1695 return TRUE; /* No way to tell if dest follows source. */
1696
1697 t = ffecom_2 (LE_EXPR, integer_type_node,
1698 ffecom_2 (PLUS_EXPR, TREE_TYPE (source_offset),
1699 source_offset,
1700 convert (TREE_TYPE (source_offset),
1701 source_size)),
1702 convert (TREE_TYPE (source_offset),
1703 dest_offset));
1704
1705 if (integer_onep (t))
1706 return FALSE; /* Destination follows source. */
1707
1708 return TRUE; /* Destination and source overlap. */
1709 }
1710
1711 /* Check whether dest might overlap any of a list of arguments or is
1712 in a COMMON area the callee might know about (and thus modify). */
1713
1714 static bool
1715 ffecom_args_overlapping_ (tree dest_tree, ffebld dest UNUSED,
1716 tree args, tree callee_commons,
1717 bool scalar_args)
1718 {
1719 tree arg;
1720 tree dest_decl;
1721 tree dest_offset;
1722 tree dest_size;
1723
1724 ffecom_tree_canonize_ref_ (&dest_decl, &dest_offset, &dest_size,
1725 dest_tree);
1726
1727 if (dest_decl == NULL_TREE)
1728 return FALSE; /* Seems unlikely! */
1729
1730 /* If the decl cannot be determined reliably, or if its in COMMON
1731 and the callee isn't known to not futz with COMMON via other
1732 means, overlap might happen. */
1733
1734 if ((TREE_CODE (dest_decl) == ERROR_MARK)
1735 || ((callee_commons != NULL_TREE)
1736 && TREE_PUBLIC (dest_decl)))
1737 return TRUE;
1738
1739 for (; args != NULL_TREE; args = TREE_CHAIN (args))
1740 {
1741 if (((arg = TREE_VALUE (args)) != NULL_TREE)
1742 && ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1743 arg, NULL, scalar_args))
1744 return TRUE;
1745 }
1746
1747 return FALSE;
1748 }
1749
1750 /* Build a string for a variable name as used by NAMELIST. This means that
1751 if we're using the f2c library, we build an uppercase string, since
1752 f2c does this. */
1753
1754 static tree
1755 ffecom_build_f2c_string_ (int i, const char *s)
1756 {
1757 if (!ffe_is_f2c_library ())
1758 return build_string (i, s);
1759
1760 {
1761 char *tmp;
1762 const char *p;
1763 char *q;
1764 char space[34];
1765 tree t;
1766
1767 if (((size_t) i) > ARRAY_SIZE (space))
1768 tmp = malloc_new_ks (malloc_pool_image (), "f2c_string", i);
1769 else
1770 tmp = &space[0];
1771
1772 for (p = s, q = tmp; *p != '\0'; ++p, ++q)
1773 *q = TOUPPER (*p);
1774 *q = '\0';
1775
1776 t = build_string (i, tmp);
1777
1778 if (((size_t) i) > ARRAY_SIZE (space))
1779 malloc_kill_ks (malloc_pool_image (), tmp, i);
1780
1781 return t;
1782 }
1783 }
1784
1785 /* Returns CALL_EXPR or equivalent with given type (pass NULL_TREE for
1786 type to just get whatever the function returns), handling the
1787 f2c value-returning convention, if required, by prepending
1788 to the arglist a pointer to a temporary to receive the return value. */
1789
1790 static tree
1791 ffecom_call_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1792 tree type, tree args, tree dest_tree,
1793 ffebld dest, bool *dest_used, tree callee_commons,
1794 bool scalar_args, tree hook)
1795 {
1796 tree item;
1797 tree tempvar;
1798
1799 if (dest_used != NULL)
1800 *dest_used = FALSE;
1801
1802 if (is_f2c_complex)
1803 {
1804 if ((dest_used == NULL)
1805 || (dest == NULL)
1806 || (ffeinfo_basictype (ffebld_info (dest))
1807 != FFEINFO_basictypeCOMPLEX)
1808 || (ffeinfo_kindtype (ffebld_info (dest)) != kt)
1809 || ((type != NULL_TREE) && (TREE_TYPE (dest_tree) != type))
1810 || ffecom_args_overlapping_ (dest_tree, dest, args,
1811 callee_commons,
1812 scalar_args))
1813 {
1814 tempvar = hook;
1815 assert (tempvar);
1816 }
1817 else
1818 {
1819 *dest_used = TRUE;
1820 tempvar = dest_tree;
1821 type = NULL_TREE;
1822 }
1823
1824 item
1825 = build_tree_list (NULL_TREE,
1826 ffecom_1 (ADDR_EXPR,
1827 build_pointer_type (TREE_TYPE (tempvar)),
1828 tempvar));
1829 TREE_CHAIN (item) = args;
1830
1831 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1832 item, NULL_TREE);
1833
1834 if (tempvar != dest_tree)
1835 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item, tempvar);
1836 }
1837 else
1838 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1839 args, NULL_TREE);
1840
1841 if ((type != NULL_TREE) && (TREE_TYPE (item) != type))
1842 item = ffecom_convert_narrow_ (type, item);
1843
1844 return item;
1845 }
1846
1847 /* Given two arguments, transform them and make a call to the given
1848 function via ffecom_call_. */
1849
1850 static tree
1851 ffecom_call_binop_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1852 tree type, ffebld left, ffebld right,
1853 tree dest_tree, ffebld dest, bool *dest_used,
1854 tree callee_commons, bool scalar_args, bool ref, tree hook)
1855 {
1856 tree left_tree;
1857 tree right_tree;
1858 tree left_length;
1859 tree right_length;
1860
1861 if (ref)
1862 {
1863 /* Pass arguments by reference. */
1864 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
1865 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
1866 }
1867 else
1868 {
1869 /* Pass arguments by value. */
1870 left_tree = ffecom_arg_expr (left, &left_length);
1871 right_tree = ffecom_arg_expr (right, &right_length);
1872 }
1873
1874
1875 left_tree = build_tree_list (NULL_TREE, left_tree);
1876 right_tree = build_tree_list (NULL_TREE, right_tree);
1877 TREE_CHAIN (left_tree) = right_tree;
1878
1879 if (left_length != NULL_TREE)
1880 {
1881 left_length = build_tree_list (NULL_TREE, left_length);
1882 TREE_CHAIN (right_tree) = left_length;
1883 }
1884
1885 if (right_length != NULL_TREE)
1886 {
1887 right_length = build_tree_list (NULL_TREE, right_length);
1888 if (left_length != NULL_TREE)
1889 TREE_CHAIN (left_length) = right_length;
1890 else
1891 TREE_CHAIN (right_tree) = right_length;
1892 }
1893
1894 return ffecom_call_ (fn, kt, is_f2c_complex, type, left_tree,
1895 dest_tree, dest, dest_used, callee_commons,
1896 scalar_args, hook);
1897 }
1898
1899 /* Return ptr/length args for char subexpression
1900
1901 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
1902 subexpressions by constructing the appropriate trees for the ptr-to-
1903 character-text and length-of-character-text arguments in a calling
1904 sequence.
1905
1906 Note that if with_null is TRUE, and the expression is an opCONTER,
1907 a null byte is appended to the string. */
1908
1909 static void
1910 ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
1911 {
1912 tree item;
1913 tree high;
1914 ffetargetCharacter1 val;
1915 ffetargetCharacterSize newlen;
1916
1917 switch (ffebld_op (expr))
1918 {
1919 case FFEBLD_opCONTER:
1920 val = ffebld_constant_character1 (ffebld_conter (expr));
1921 newlen = ffetarget_length_character1 (val);
1922 if (with_null)
1923 {
1924 /* Begin FFETARGET-NULL-KLUDGE. */
1925 if (newlen != 0)
1926 ++newlen;
1927 }
1928 *length = build_int_2 (newlen, 0);
1929 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
1930 high = build_int_2 (newlen, 0);
1931 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
1932 item = build_string (newlen,
1933 ffetarget_text_character1 (val));
1934 /* End FFETARGET-NULL-KLUDGE. */
1935 TREE_TYPE (item)
1936 = build_type_variant
1937 (build_array_type
1938 (char_type_node,
1939 build_range_type
1940 (ffecom_f2c_ftnlen_type_node,
1941 ffecom_f2c_ftnlen_one_node,
1942 high)),
1943 1, 0);
1944 TREE_CONSTANT (item) = 1;
1945 TREE_STATIC (item) = 1;
1946 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
1947 item);
1948 break;
1949
1950 case FFEBLD_opSYMTER:
1951 {
1952 ffesymbol s = ffebld_symter (expr);
1953
1954 item = ffesymbol_hook (s).decl_tree;
1955 if (item == NULL_TREE)
1956 {
1957 s = ffecom_sym_transform_ (s);
1958 item = ffesymbol_hook (s).decl_tree;
1959 }
1960 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
1961 {
1962 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
1963 *length = ffesymbol_hook (s).length_tree;
1964 else
1965 {
1966 *length = build_int_2 (ffesymbol_size (s), 0);
1967 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
1968 }
1969 }
1970 else if (item == error_mark_node)
1971 *length = error_mark_node;
1972 else
1973 /* FFEINFO_kindFUNCTION. */
1974 *length = NULL_TREE;
1975 if (!ffesymbol_hook (s).addr
1976 && (item != error_mark_node))
1977 item = ffecom_1 (ADDR_EXPR,
1978 build_pointer_type (TREE_TYPE (item)),
1979 item);
1980 }
1981 break;
1982
1983 case FFEBLD_opARRAYREF:
1984 {
1985 ffecom_char_args_ (&item, length, ffebld_left (expr));
1986
1987 if (item == error_mark_node || *length == error_mark_node)
1988 {
1989 item = *length = error_mark_node;
1990 break;
1991 }
1992
1993 item = ffecom_arrayref_ (item, expr, 1);
1994 }
1995 break;
1996
1997 case FFEBLD_opSUBSTR:
1998 {
1999 ffebld start;
2000 ffebld end;
2001 ffebld thing = ffebld_right (expr);
2002 tree start_tree;
2003 tree end_tree;
2004 const char *char_name;
2005 ffebld left_symter;
2006 tree array;
2007
2008 assert (ffebld_op (thing) == FFEBLD_opITEM);
2009 start = ffebld_head (thing);
2010 thing = ffebld_trail (thing);
2011 assert (ffebld_trail (thing) == NULL);
2012 end = ffebld_head (thing);
2013
2014 /* Determine name for pretty-printing range-check errors. */
2015 for (left_symter = ffebld_left (expr);
2016 left_symter && ffebld_op (left_symter) == FFEBLD_opARRAYREF;
2017 left_symter = ffebld_left (left_symter))
2018 ;
2019 if (ffebld_op (left_symter) == FFEBLD_opSYMTER)
2020 char_name = ffesymbol_text (ffebld_symter (left_symter));
2021 else
2022 char_name = "[expr?]";
2023
2024 ffecom_char_args_ (&item, length, ffebld_left (expr));
2025
2026 if (item == error_mark_node || *length == error_mark_node)
2027 {
2028 item = *length = error_mark_node;
2029 break;
2030 }
2031
2032 array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
2033
2034 /* ~~~~Handle INTEGER*8 start/end, a la FFEBLD_opARRAYREF. */
2035
2036 if (start == NULL)
2037 {
2038 if (end == NULL)
2039 ;
2040 else
2041 {
2042 end_tree = ffecom_expr (end);
2043 if (flag_bounds_check)
2044 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2045 char_name);
2046 end_tree = convert (ffecom_f2c_ftnlen_type_node,
2047 end_tree);
2048
2049 if (end_tree == error_mark_node)
2050 {
2051 item = *length = error_mark_node;
2052 break;
2053 }
2054
2055 *length = end_tree;
2056 }
2057 }
2058 else
2059 {
2060 start_tree = ffecom_expr (start);
2061 if (flag_bounds_check)
2062 start_tree = ffecom_subscript_check_ (array, start_tree, 0, 0,
2063 char_name);
2064 start_tree = convert (ffecom_f2c_ftnlen_type_node,
2065 start_tree);
2066
2067 if (start_tree == error_mark_node)
2068 {
2069 item = *length = error_mark_node;
2070 break;
2071 }
2072
2073 start_tree = ffecom_save_tree (start_tree);
2074
2075 item = ffecom_2 (PLUS_EXPR, TREE_TYPE (item),
2076 item,
2077 ffecom_2 (MINUS_EXPR,
2078 TREE_TYPE (start_tree),
2079 start_tree,
2080 ffecom_f2c_ftnlen_one_node));
2081
2082 if (end == NULL)
2083 {
2084 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2085 ffecom_f2c_ftnlen_one_node,
2086 ffecom_2 (MINUS_EXPR,
2087 ffecom_f2c_ftnlen_type_node,
2088 *length,
2089 start_tree));
2090 }
2091 else
2092 {
2093 end_tree = ffecom_expr (end);
2094 if (flag_bounds_check)
2095 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2096 char_name);
2097 end_tree = convert (ffecom_f2c_ftnlen_type_node,
2098 end_tree);
2099
2100 if (end_tree == error_mark_node)
2101 {
2102 item = *length = error_mark_node;
2103 break;
2104 }
2105
2106 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2107 ffecom_f2c_ftnlen_one_node,
2108 ffecom_2 (MINUS_EXPR,
2109 ffecom_f2c_ftnlen_type_node,
2110 end_tree, start_tree));
2111 }
2112 }
2113 }
2114 break;
2115
2116 case FFEBLD_opFUNCREF:
2117 {
2118 ffesymbol s = ffebld_symter (ffebld_left (expr));
2119 tree tempvar;
2120 tree args;
2121 ffetargetCharacterSize size = ffeinfo_size (ffebld_info (expr));
2122 ffecomGfrt ix;
2123
2124 if (size == FFETARGET_charactersizeNONE)
2125 /* ~~Kludge alert! This should someday be fixed. */
2126 size = 24;
2127
2128 *length = build_int_2 (size, 0);
2129 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2130
2131 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
2132 == FFEINFO_whereINTRINSIC)
2133 {
2134 if (size == 1)
2135 {
2136 /* Invocation of an intrinsic returning CHARACTER*1. */
2137 item = ffecom_expr_intrinsic_ (expr, NULL_TREE,
2138 NULL, NULL);
2139 break;
2140 }
2141 ix = ffeintrin_gfrt_direct (ffebld_symter_implementation (ffebld_left (expr)));
2142 assert (ix != FFECOM_gfrt);
2143 item = ffecom_gfrt_tree_ (ix);
2144 }
2145 else
2146 {
2147 ix = FFECOM_gfrt;
2148 item = ffesymbol_hook (s).decl_tree;
2149 if (item == NULL_TREE)
2150 {
2151 s = ffecom_sym_transform_ (s);
2152 item = ffesymbol_hook (s).decl_tree;
2153 }
2154 if (item == error_mark_node)
2155 {
2156 item = *length = error_mark_node;
2157 break;
2158 }
2159
2160 if (!ffesymbol_hook (s).addr)
2161 item = ffecom_1_fn (item);
2162 }
2163 tempvar = ffebld_nonter_hook (expr);
2164 assert (tempvar);
2165 tempvar = ffecom_1 (ADDR_EXPR,
2166 build_pointer_type (TREE_TYPE (tempvar)),
2167 tempvar);
2168
2169 args = build_tree_list (NULL_TREE, tempvar);
2170
2171 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT) /* Sfunc args by value. */
2172 TREE_CHAIN (args) = ffecom_list_expr (ffebld_right (expr));
2173 else
2174 {
2175 TREE_CHAIN (args) = build_tree_list (NULL_TREE, *length);
2176 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
2177 {
2178 TREE_CHAIN (TREE_CHAIN (args))
2179 = ffecom_arglist_expr_ (ffecom_gfrt_args_ (ix),
2180 ffebld_right (expr));
2181 }
2182 else
2183 {
2184 TREE_CHAIN (TREE_CHAIN (args))
2185 = ffecom_list_ptr_to_expr (ffebld_right (expr));
2186 }
2187 }
2188
2189 item = ffecom_3s (CALL_EXPR,
2190 TREE_TYPE (TREE_TYPE (TREE_TYPE (item))),
2191 item, args, NULL_TREE);
2192 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item,
2193 tempvar);
2194 }
2195 break;
2196
2197 case FFEBLD_opCONVERT:
2198
2199 ffecom_char_args_ (&item, length, ffebld_left (expr));
2200
2201 if (item == error_mark_node || *length == error_mark_node)
2202 {
2203 item = *length = error_mark_node;
2204 break;
2205 }
2206
2207 if ((ffebld_size_known (ffebld_left (expr))
2208 == FFETARGET_charactersizeNONE)
2209 || (ffebld_size_known (ffebld_left (expr)) < (ffebld_size (expr))))
2210 { /* Possible blank-padding needed, copy into
2211 temporary. */
2212 tree tempvar;
2213 tree args;
2214 tree newlen;
2215
2216 tempvar = ffebld_nonter_hook (expr);
2217 assert (tempvar);
2218 tempvar = ffecom_1 (ADDR_EXPR,
2219 build_pointer_type (TREE_TYPE (tempvar)),
2220 tempvar);
2221
2222 newlen = build_int_2 (ffebld_size (expr), 0);
2223 TREE_TYPE (newlen) = ffecom_f2c_ftnlen_type_node;
2224
2225 args = build_tree_list (NULL_TREE, tempvar);
2226 TREE_CHAIN (args) = build_tree_list (NULL_TREE, item);
2227 TREE_CHAIN (TREE_CHAIN (args)) = build_tree_list (NULL_TREE, newlen);
2228 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (args)))
2229 = build_tree_list (NULL_TREE, *length);
2230
2231 item = ffecom_call_gfrt (FFECOM_gfrtCOPY, args, NULL_TREE);
2232 TREE_SIDE_EFFECTS (item) = 1;
2233 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), fold (item),
2234 tempvar);
2235 *length = newlen;
2236 }
2237 else
2238 { /* Just truncate the length. */
2239 *length = build_int_2 (ffebld_size (expr), 0);
2240 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2241 }
2242 break;
2243
2244 default:
2245 assert ("bad op for single char arg expr" == NULL);
2246 item = NULL_TREE;
2247 break;
2248 }
2249
2250 *xitem = item;
2251 }
2252
2253 /* Check the size of the type to be sure it doesn't overflow the
2254 "portable" capacities of the compiler back end. `dummy' types
2255 can generally overflow the normal sizes as long as the computations
2256 themselves don't overflow. A particular target of the back end
2257 must still enforce its size requirements, though, and the back
2258 end takes care of this in stor-layout.c. */
2259
2260 static tree
2261 ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy)
2262 {
2263 if (TREE_CODE (type) == ERROR_MARK)
2264 return type;
2265
2266 if (TYPE_SIZE (type) == NULL_TREE)
2267 return type;
2268
2269 if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
2270 return type;
2271
2272 /* An array is too large if size is negative or the type_size overflows
2273 or its "upper half" is larger than 3 (which would make the signed
2274 byte size and offset computations overflow). */
2275
2276 if ((tree_int_cst_sgn (TYPE_SIZE (type)) < 0)
2277 || (!dummy && (TREE_INT_CST_HIGH (TYPE_SIZE (type)) > 3
2278 || TREE_OVERFLOW (TYPE_SIZE (type)))))
2279 {
2280 ffebad_start (FFEBAD_ARRAY_LARGE);
2281 ffebad_string (ffesymbol_text (s));
2282 ffebad_here (0, ffesymbol_where_line (s), ffesymbol_where_column (s));
2283 ffebad_finish ();
2284
2285 return error_mark_node;
2286 }
2287
2288 return type;
2289 }
2290
2291 /* Builds a length argument (PARM_DECL). Also wraps type in an array type
2292 where the dimension info is (1:size) where <size> is ffesymbol_size(s) if
2293 known, length_arg if not known (FFETARGET_charactersizeNONE). */
2294
2295 static tree
2296 ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s)
2297 {
2298 ffetargetCharacterSize sz = ffesymbol_size (s);
2299 tree highval;
2300 tree tlen;
2301 tree type = *xtype;
2302
2303 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
2304 tlen = NULL_TREE; /* A statement function, no length passed. */
2305 else
2306 {
2307 if (ffesymbol_where (s) == FFEINFO_whereDUMMY)
2308 tlen = ffecom_get_invented_identifier ("__g77_length_%s",
2309 ffesymbol_text (s));
2310 else
2311 tlen = ffecom_get_invented_identifier ("__g77_%s", "length");
2312 tlen = build_decl (PARM_DECL, tlen, ffecom_f2c_ftnlen_type_node);
2313 DECL_ARTIFICIAL (tlen) = 1;
2314 }
2315
2316 if (sz == FFETARGET_charactersizeNONE)
2317 {
2318 assert (tlen != NULL_TREE);
2319 highval = variable_size (tlen);
2320 }
2321 else
2322 {
2323 highval = build_int_2 (sz, 0);
2324 TREE_TYPE (highval) = ffecom_f2c_ftnlen_type_node;
2325 }
2326
2327 type = build_array_type (type,
2328 build_range_type (ffecom_f2c_ftnlen_type_node,
2329 ffecom_f2c_ftnlen_one_node,
2330 highval));
2331
2332 *xtype = type;
2333 return tlen;
2334 }
2335
2336 /* ffecom_concat_list_gather_ -- Gather list of concatenated string exprs
2337
2338 ffecomConcatList_ catlist;
2339 ffebld expr; // expr of CHARACTER basictype.
2340 ffetargetCharacterSize max; // max chars to gather or _...NONE if no max
2341 catlist = ffecom_concat_list_gather_(catlist,expr,max);
2342
2343 Scans expr for character subexpressions, updates and returns catlist
2344 accordingly. */
2345
2346 static ffecomConcatList_
2347 ffecom_concat_list_gather_ (ffecomConcatList_ catlist, ffebld expr,
2348 ffetargetCharacterSize max)
2349 {
2350 ffetargetCharacterSize sz;
2351
2352 recurse:
2353
2354 if (expr == NULL)
2355 return catlist;
2356
2357 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen >= max))
2358 return catlist; /* Don't append any more items. */
2359
2360 switch (ffebld_op (expr))
2361 {
2362 case FFEBLD_opCONTER:
2363 case FFEBLD_opSYMTER:
2364 case FFEBLD_opARRAYREF:
2365 case FFEBLD_opFUNCREF:
2366 case FFEBLD_opSUBSTR:
2367 case FFEBLD_opCONVERT: /* Callers should strip this off beforehand
2368 if they don't need to preserve it. */
2369 if (catlist.count == catlist.max)
2370 { /* Make a (larger) list. */
2371 ffebld *newx;
2372 int newmax;
2373
2374 newmax = (catlist.max == 0) ? 8 : catlist.max * 2;
2375 newx = malloc_new_ks (malloc_pool_image (), "catlist",
2376 newmax * sizeof (newx[0]));
2377 if (catlist.max != 0)
2378 {
2379 memcpy (newx, catlist.exprs, catlist.max * sizeof (newx[0]));
2380 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2381 catlist.max * sizeof (newx[0]));
2382 }
2383 catlist.max = newmax;
2384 catlist.exprs = newx;
2385 }
2386 if ((sz = ffebld_size_known (expr)) != FFETARGET_charactersizeNONE)
2387 catlist.minlen += sz;
2388 else
2389 ++catlist.minlen; /* Not true for F90; can be 0 length. */
2390 if ((sz = ffebld_size_max (expr)) == FFETARGET_charactersizeNONE)
2391 catlist.maxlen = sz;
2392 else
2393 catlist.maxlen += sz;
2394 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen > max))
2395 { /* This item overlaps (or is beyond) the end
2396 of the destination. */
2397 switch (ffebld_op (expr))
2398 {
2399 case FFEBLD_opCONTER:
2400 case FFEBLD_opSYMTER:
2401 case FFEBLD_opARRAYREF:
2402 case FFEBLD_opFUNCREF:
2403 case FFEBLD_opSUBSTR:
2404 /* ~~Do useful truncations here. */
2405 break;
2406
2407 default:
2408 assert ("op changed or inconsistent switches!" == NULL);
2409 break;
2410 }
2411 }
2412 catlist.exprs[catlist.count++] = expr;
2413 return catlist;
2414
2415 case FFEBLD_opPAREN:
2416 expr = ffebld_left (expr);
2417 goto recurse; /* :::::::::::::::::::: */
2418
2419 case FFEBLD_opCONCATENATE:
2420 catlist = ffecom_concat_list_gather_ (catlist, ffebld_left (expr), max);
2421 expr = ffebld_right (expr);
2422 goto recurse; /* :::::::::::::::::::: */
2423
2424 #if 0 /* Breaks passing small actual arg to larger
2425 dummy arg of sfunc */
2426 case FFEBLD_opCONVERT:
2427 expr = ffebld_left (expr);
2428 {
2429 ffetargetCharacterSize cmax;
2430
2431 cmax = catlist.len + ffebld_size_known (expr);
2432
2433 if ((max == FFETARGET_charactersizeNONE) || (max > cmax))
2434 max = cmax;
2435 }
2436 goto recurse; /* :::::::::::::::::::: */
2437 #endif
2438
2439 case FFEBLD_opANY:
2440 return catlist;
2441
2442 default:
2443 assert ("bad op in _gather_" == NULL);
2444 return catlist;
2445 }
2446 }
2447
2448 /* ffecom_concat_list_kill_ -- Kill list of concatenated string exprs
2449
2450 ffecomConcatList_ catlist;
2451 ffecom_concat_list_kill_(catlist);
2452
2453 Anything allocated within the list info is deallocated. */
2454
2455 static void
2456 ffecom_concat_list_kill_ (ffecomConcatList_ catlist)
2457 {
2458 if (catlist.max != 0)
2459 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2460 catlist.max * sizeof (catlist.exprs[0]));
2461 }
2462
2463 /* Make list of concatenated string exprs.
2464
2465 Returns a flattened list of concatenated subexpressions given a
2466 tree of such expressions. */
2467
2468 static ffecomConcatList_
2469 ffecom_concat_list_new_ (ffebld expr, ffetargetCharacterSize max)
2470 {
2471 ffecomConcatList_ catlist;
2472
2473 catlist.maxlen = catlist.minlen = catlist.max = catlist.count = 0;
2474 return ffecom_concat_list_gather_ (catlist, expr, max);
2475 }
2476
2477 /* Provide some kind of useful info on member of aggregate area,
2478 since current g77/gcc technology does not provide debug info
2479 on these members. */
2480
2481 static void
2482 ffecom_debug_kludge_ (tree aggr, const char *aggr_type, ffesymbol member,
2483 tree member_type UNUSED, ffetargetOffset offset)
2484 {
2485 tree value;
2486 tree decl;
2487 int len;
2488 char *buff;
2489 char space[120];
2490 #if 0
2491 tree type_id;
2492
2493 for (type_id = member_type;
2494 TREE_CODE (type_id) != IDENTIFIER_NODE;
2495 )
2496 {
2497 switch (TREE_CODE (type_id))
2498 {
2499 case INTEGER_TYPE:
2500 case REAL_TYPE:
2501 type_id = TYPE_NAME (type_id);
2502 break;
2503
2504 case ARRAY_TYPE:
2505 case COMPLEX_TYPE:
2506 type_id = TREE_TYPE (type_id);
2507 break;
2508
2509 default:
2510 assert ("no IDENTIFIER_NODE for type!" == NULL);
2511 type_id = error_mark_node;
2512 break;
2513 }
2514 }
2515 #endif
2516
2517 if (ffecom_transform_only_dummies_
2518 || !ffe_is_debug_kludge ())
2519 return; /* Can't do this yet, maybe later. */
2520
2521 len = 60
2522 + strlen (aggr_type)
2523 + IDENTIFIER_LENGTH (DECL_NAME (aggr));
2524 #if 0
2525 + IDENTIFIER_LENGTH (type_id);
2526 #endif
2527
2528 if (((size_t) len) >= ARRAY_SIZE (space))
2529 buff = malloc_new_ks (malloc_pool_image (), "debug_kludge", len + 1);
2530 else
2531 buff = &space[0];
2532
2533 sprintf (&buff[0], "At (%s) `%s' plus %ld bytes",
2534 aggr_type,
2535 IDENTIFIER_POINTER (DECL_NAME (aggr)),
2536 (long int) offset);
2537
2538 value = build_string (len, buff);
2539 TREE_TYPE (value)
2540 = build_type_variant (build_array_type (char_type_node,
2541 build_range_type
2542 (integer_type_node,
2543 integer_one_node,
2544 build_int_2 (strlen (buff), 0))),
2545 1, 0);
2546 decl = build_decl (VAR_DECL,
2547 ffecom_get_identifier_ (ffesymbol_text (member)),
2548 TREE_TYPE (value));
2549 TREE_CONSTANT (decl) = 1;
2550 TREE_STATIC (decl) = 1;
2551 DECL_INITIAL (decl) = error_mark_node;
2552 DECL_IN_SYSTEM_HEADER (decl) = 1; /* Don't let -Wunused complain. */
2553 decl = start_decl (decl, FALSE);
2554 finish_decl (decl, value, FALSE);
2555
2556 if (buff != &space[0])
2557 malloc_kill_ks (malloc_pool_image (), buff, len + 1);
2558 }
2559
2560 /* ffecom_do_entry_ -- Do compilation of a particular entrypoint
2561
2562 ffesymbol fn; // the SUBROUTINE, FUNCTION, or ENTRY symbol itself
2563 int i; // entry# for this entrypoint (used by master fn)
2564 ffecom_do_entrypoint_(s,i);
2565
2566 Makes a public entry point that calls our private master fn (already
2567 compiled). */
2568
2569 static void
2570 ffecom_do_entry_ (ffesymbol fn, int entrynum)
2571 {
2572 ffebld item;
2573 tree type; /* Type of function. */
2574 tree multi_retval; /* Var holding return value (union). */
2575 tree result; /* Var holding result. */
2576 ffeinfoBasictype bt;
2577 ffeinfoKindtype kt;
2578 ffeglobal g;
2579 ffeglobalType gt;
2580 bool charfunc; /* All entry points return same type
2581 CHARACTER. */
2582 bool cmplxfunc; /* Use f2c way of returning COMPLEX. */
2583 bool multi; /* Master fn has multiple return types. */
2584 bool altreturning = FALSE; /* This entry point has alternate
2585 returns. */
2586 location_t old_loc = input_location;
2587
2588 input_filename = ffesymbol_where_filename (fn);
2589 input_line = ffesymbol_where_filelinenum (fn);
2590
2591 ffecom_doing_entry_ = TRUE; /* Don't bother with array dimensions. */
2592
2593 switch (ffecom_primary_entry_kind_)
2594 {
2595 case FFEINFO_kindFUNCTION:
2596
2597 /* Determine actual return type for function. */
2598
2599 gt = FFEGLOBAL_typeFUNC;
2600 bt = ffesymbol_basictype (fn);
2601 kt = ffesymbol_kindtype (fn);
2602 if (bt == FFEINFO_basictypeNONE)
2603 {
2604 ffeimplic_establish_symbol (fn);
2605 if (ffesymbol_funcresult (fn) != NULL)
2606 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
2607 bt = ffesymbol_basictype (fn);
2608 kt = ffesymbol_kindtype (fn);
2609 }
2610
2611 if (bt == FFEINFO_basictypeCHARACTER)
2612 charfunc = TRUE, cmplxfunc = FALSE;
2613 else if ((bt == FFEINFO_basictypeCOMPLEX)
2614 && ffesymbol_is_f2c (fn))
2615 charfunc = FALSE, cmplxfunc = TRUE;
2616 else
2617 charfunc = cmplxfunc = FALSE;
2618
2619 if (charfunc)
2620 type = ffecom_tree_fun_type_void;
2621 else if (ffesymbol_is_f2c (fn))
2622 type = ffecom_tree_fun_type[bt][kt];
2623 else
2624 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
2625
2626 if ((type == NULL_TREE)
2627 || (TREE_TYPE (type) == NULL_TREE))
2628 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
2629
2630 multi = (ffecom_master_bt_ == FFEINFO_basictypeNONE);
2631 break;
2632
2633 case FFEINFO_kindSUBROUTINE:
2634 gt = FFEGLOBAL_typeSUBR;
2635 bt = FFEINFO_basictypeNONE;
2636 kt = FFEINFO_kindtypeNONE;
2637 if (ffecom_is_altreturning_)
2638 { /* Am _I_ altreturning? */
2639 for (item = ffesymbol_dummyargs (fn);
2640 item != NULL;
2641 item = ffebld_trail (item))
2642 {
2643 if (ffebld_op (ffebld_head (item)) == FFEBLD_opSTAR)
2644 {
2645 altreturning = TRUE;
2646 break;
2647 }
2648 }
2649 if (altreturning)
2650 type = ffecom_tree_subr_type;
2651 else
2652 type = ffecom_tree_fun_type_void;
2653 }
2654 else
2655 type = ffecom_tree_fun_type_void;
2656 charfunc = FALSE;
2657 cmplxfunc = FALSE;
2658 multi = FALSE;
2659 break;
2660
2661 default:
2662 assert ("say what??" == NULL);
2663 /* Fall through. */
2664 case FFEINFO_kindANY:
2665 gt = FFEGLOBAL_typeANY;
2666 bt = FFEINFO_basictypeNONE;
2667 kt = FFEINFO_kindtypeNONE;
2668 type = error_mark_node;
2669 charfunc = FALSE;
2670 cmplxfunc = FALSE;
2671 multi = FALSE;
2672 break;
2673 }
2674
2675 /* build_decl uses the current lineno and input_filename to set the decl
2676 source info. So, I've putzed with ffestd and ffeste code to update that
2677 source info to point to the appropriate statement just before calling
2678 ffecom_do_entrypoint (which calls this fn). */
2679
2680 start_function (ffecom_get_external_identifier_ (fn),
2681 type,
2682 0, /* nested/inline */
2683 1); /* TREE_PUBLIC */
2684
2685 if (((g = ffesymbol_global (fn)) != NULL)
2686 && ((ffeglobal_type (g) == gt)
2687 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
2688 {
2689 ffeglobal_set_hook (g, current_function_decl);
2690 }
2691
2692 /* Reset args in master arg list so they get retransitioned. */
2693
2694 for (item = ffecom_master_arglist_;
2695 item != NULL;
2696 item = ffebld_trail (item))
2697 {
2698 ffebld arg;
2699 ffesymbol s;
2700
2701 arg = ffebld_head (item);
2702 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2703 continue; /* Alternate return or some such thing. */
2704 s = ffebld_symter (arg);
2705 ffesymbol_hook (s).decl_tree = NULL_TREE;
2706 ffesymbol_hook (s).length_tree = NULL_TREE;
2707 }
2708
2709 /* Build dummy arg list for this entry point. */
2710
2711 if (charfunc || cmplxfunc)
2712 { /* Prepend arg for where result goes. */
2713 tree type;
2714 tree length;
2715
2716 if (charfunc)
2717 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
2718 else
2719 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
2720
2721 result = ffecom_get_invented_identifier ("__g77_%s", "result");
2722
2723 /* Make length arg _and_ enhance type info for CHAR arg itself. */
2724
2725 if (charfunc)
2726 length = ffecom_char_enhance_arg_ (&type, fn);
2727 else
2728 length = NULL_TREE; /* Not ref'd if !charfunc. */
2729
2730 type = build_pointer_type (type);
2731 result = build_decl (PARM_DECL, result, type);
2732
2733 push_parm_decl (result);
2734 ffecom_func_result_ = result;
2735
2736 if (charfunc)
2737 {
2738 push_parm_decl (length);
2739 ffecom_func_length_ = length;
2740 }
2741 }
2742 else
2743 result = DECL_RESULT (current_function_decl);
2744
2745 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (fn), FALSE);
2746
2747 store_parm_decls (0);
2748
2749 ffecom_start_compstmt ();
2750 /* Disallow temp vars at this level. */
2751 current_binding_level->prep_state = 2;
2752
2753 /* Make local var to hold return type for multi-type master fn. */
2754
2755 if (multi)
2756 {
2757 multi_retval = ffecom_get_invented_identifier ("__g77_%s",
2758 "multi_retval");
2759 multi_retval = build_decl (VAR_DECL, multi_retval,
2760 ffecom_multi_type_node_);
2761 multi_retval = start_decl (multi_retval, FALSE);
2762 finish_decl (multi_retval, NULL_TREE, FALSE);
2763 }
2764 else
2765 multi_retval = NULL_TREE; /* Not actually ref'd if !multi. */
2766
2767 /* Here we emit the actual code for the entry point. */
2768
2769 {
2770 ffebld list;
2771 ffebld arg;
2772 ffesymbol s;
2773 tree arglist = NULL_TREE;
2774 tree *plist = &arglist;
2775 tree prepend;
2776 tree call;
2777 tree actarg;
2778 tree master_fn;
2779
2780 /* Prepare actual arg list based on master arg list. */
2781
2782 for (list = ffecom_master_arglist_;
2783 list != NULL;
2784 list = ffebld_trail (list))
2785 {
2786 arg = ffebld_head (list);
2787 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2788 continue;
2789 s = ffebld_symter (arg);
2790 if (ffesymbol_hook (s).decl_tree == NULL_TREE
2791 || ffesymbol_hook (s).decl_tree == error_mark_node)
2792 actarg = null_pointer_node; /* We don't have this arg. */
2793 else
2794 actarg = ffesymbol_hook (s).decl_tree;
2795 *plist = build_tree_list (NULL_TREE, actarg);
2796 plist = &TREE_CHAIN (*plist);
2797 }
2798
2799 /* This code appends the length arguments for character
2800 variables/arrays. */
2801
2802 for (list = ffecom_master_arglist_;
2803 list != NULL;
2804 list = ffebld_trail (list))
2805 {
2806 arg = ffebld_head (list);
2807 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2808 continue;
2809 s = ffebld_symter (arg);
2810 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
2811 continue; /* Only looking for CHARACTER arguments. */
2812 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
2813 continue; /* Only looking for variables and arrays. */
2814 if (ffesymbol_hook (s).length_tree == NULL_TREE
2815 || ffesymbol_hook (s).length_tree == error_mark_node)
2816 actarg = ffecom_f2c_ftnlen_zero_node; /* We don't have this arg. */
2817 else
2818 actarg = ffesymbol_hook (s).length_tree;
2819 *plist = build_tree_list (NULL_TREE, actarg);
2820 plist = &TREE_CHAIN (*plist);
2821 }
2822
2823 /* Prepend character-value return info to actual arg list. */
2824
2825 if (charfunc)
2826 {
2827 prepend = build_tree_list (NULL_TREE, ffecom_func_result_);
2828 TREE_CHAIN (prepend)
2829 = build_tree_list (NULL_TREE, ffecom_func_length_);
2830 TREE_CHAIN (TREE_CHAIN (prepend)) = arglist;
2831 arglist = prepend;
2832 }
2833
2834 /* Prepend multi-type return value to actual arg list. */
2835
2836 if (multi)
2837 {
2838 prepend
2839 = build_tree_list (NULL_TREE,
2840 ffecom_1 (ADDR_EXPR,
2841 build_pointer_type (TREE_TYPE (multi_retval)),
2842 multi_retval));
2843 TREE_CHAIN (prepend) = arglist;
2844 arglist = prepend;
2845 }
2846
2847 /* Prepend my entry-point number to the actual arg list. */
2848
2849 prepend = build_tree_list (NULL_TREE, build_int_2 (entrynum, 0));
2850 TREE_CHAIN (prepend) = arglist;
2851 arglist = prepend;
2852
2853 /* Build the call to the master function. */
2854
2855 master_fn = ffecom_1_fn (ffecom_previous_function_decl_);
2856 call = ffecom_3s (CALL_EXPR,
2857 TREE_TYPE (TREE_TYPE (TREE_TYPE (master_fn))),
2858 master_fn, arglist, NULL_TREE);
2859
2860 /* Decide whether the master function is a function or subroutine, and
2861 handle the return value for my entry point. */
2862
2863 if (charfunc || ((ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
2864 && !altreturning))
2865 {
2866 expand_expr_stmt (call);
2867 expand_null_return ();
2868 }
2869 else if (multi && cmplxfunc)
2870 {
2871 expand_expr_stmt (call);
2872 result
2873 = ffecom_1 (INDIRECT_REF,
2874 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
2875 result);
2876 result = ffecom_modify (NULL_TREE, result,
2877 ffecom_2 (COMPONENT_REF, TREE_TYPE (result),
2878 multi_retval,
2879 ffecom_multi_fields_[bt][kt]));
2880 expand_expr_stmt (result);
2881 expand_null_return ();
2882 }
2883 else if (multi)
2884 {
2885 expand_expr_stmt (call);
2886 result
2887 = ffecom_modify (NULL_TREE, result,
2888 convert (TREE_TYPE (result),
2889 ffecom_2 (COMPONENT_REF,
2890 ffecom_tree_type[bt][kt],
2891 multi_retval,
2892 ffecom_multi_fields_[bt][kt])));
2893 expand_return (result);
2894 }
2895 else if (cmplxfunc)
2896 {
2897 result
2898 = ffecom_1 (INDIRECT_REF,
2899 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
2900 result);
2901 result = ffecom_modify (NULL_TREE, result, call);
2902 expand_expr_stmt (result);
2903 expand_null_return ();
2904 }
2905 else
2906 {
2907 result = ffecom_modify (NULL_TREE,
2908 result,
2909 convert (TREE_TYPE (result),
2910 call));
2911 expand_return (result);
2912 }
2913 }
2914
2915 ffecom_end_compstmt ();
2916
2917 finish_function (0);
2918
2919 input_location = old_loc;
2920
2921 ffecom_doing_entry_ = FALSE;
2922 }
2923
2924 /* Transform expr into gcc tree with possible destination
2925
2926 Recursive descent on expr while making corresponding tree nodes and
2927 attaching type info and such. If destination supplied and compatible
2928 with temporary that would be made in certain cases, temporary isn't
2929 made, destination used instead, and dest_used flag set TRUE. */
2930
2931 static tree
2932 ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
2933 bool *dest_used, bool assignp, bool widenp)
2934 {
2935 tree item;
2936 tree list;
2937 tree args;
2938 ffeinfoBasictype bt;
2939 ffeinfoKindtype kt;
2940 tree t;
2941 tree dt; /* decl_tree for an ffesymbol. */
2942 tree tree_type, tree_type_x;
2943 tree left, right;
2944 ffesymbol s;
2945 enum tree_code code;
2946
2947 assert (expr != NULL);
2948
2949 if (dest_used != NULL)
2950 *dest_used = FALSE;
2951
2952 bt = ffeinfo_basictype (ffebld_info (expr));
2953 kt = ffeinfo_kindtype (ffebld_info (expr));
2954 tree_type = ffecom_tree_type[bt][kt];
2955
2956 /* Widen integral arithmetic as desired while preserving signedness. */
2957 tree_type_x = NULL_TREE;
2958 if (widenp && tree_type
2959 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
2960 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
2961 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
2962
2963 switch (ffebld_op (expr))
2964 {
2965 case FFEBLD_opACCTER:
2966 {
2967 ffebitCount i;
2968 ffebit bits = ffebld_accter_bits (expr);
2969 ffetargetOffset source_offset = 0;
2970 ffetargetOffset dest_offset = ffebld_accter_pad (expr);
2971 tree purpose;
2972
2973 assert (dest_offset == 0
2974 || (bt == FFEINFO_basictypeCHARACTER
2975 && kt == FFEINFO_kindtypeCHARACTER1));
2976
2977 list = item = NULL;
2978 for (;;)
2979 {
2980 ffebldConstantUnion cu;
2981 ffebitCount length;
2982 bool value;
2983 ffebldConstantArray ca = ffebld_accter (expr);
2984
2985 ffebit_test (bits, source_offset, &value, &length);
2986 if (length == 0)
2987 break;
2988
2989 if (value)
2990 {
2991 for (i = 0; i < length; ++i)
2992 {
2993 cu = ffebld_constantarray_get (ca, bt, kt,
2994 source_offset + i);
2995
2996 t = ffecom_constantunion (&cu, bt, kt, tree_type);
2997
2998 if (i == 0
2999 && dest_offset != 0)
3000 purpose = build_int_2 (dest_offset, 0);
3001 else
3002 purpose = NULL_TREE;
3003
3004 if (list == NULL_TREE)
3005 list = item = build_tree_list (purpose, t);
3006 else
3007 {
3008 TREE_CHAIN (item) = build_tree_list (purpose, t);
3009 item = TREE_CHAIN (item);
3010 }
3011 }
3012 }
3013 source_offset += length;
3014 dest_offset += length;
3015 }
3016 }
3017
3018 item = build_int_2 ((ffebld_accter_size (expr)
3019 + ffebld_accter_pad (expr)) - 1, 0);
3020 ffebit_kill (ffebld_accter_bits (expr));
3021 TREE_TYPE (item) = ffecom_integer_type_node;
3022 item
3023 = build_array_type
3024 (tree_type,
3025 build_range_type (ffecom_integer_type_node,
3026 ffecom_integer_zero_node,
3027 item));
3028 list = build_constructor (item, list);
3029 TREE_CONSTANT (list) = 1;
3030 TREE_STATIC (list) = 1;
3031 return list;
3032
3033 case FFEBLD_opARRTER:
3034 {
3035 ffetargetOffset i;
3036
3037 list = NULL_TREE;
3038 if (ffebld_arrter_pad (expr) == 0)
3039 item = NULL_TREE;
3040 else
3041 {
3042 assert (bt == FFEINFO_basictypeCHARACTER
3043 && kt == FFEINFO_kindtypeCHARACTER1);
3044
3045 /* Becomes PURPOSE first time through loop. */
3046 item = build_int_2 (ffebld_arrter_pad (expr), 0);
3047 }
3048
3049 for (i = 0; i < ffebld_arrter_size (expr); ++i)
3050 {
3051 ffebldConstantUnion cu
3052 = ffebld_constantarray_get (ffebld_arrter (expr), bt, kt, i);
3053
3054 t = ffecom_constantunion (&cu, bt, kt, tree_type);
3055
3056 if (list == NULL_TREE)
3057 /* Assume item is PURPOSE first time through loop. */
3058 list = item = build_tree_list (item, t);
3059 else
3060 {
3061 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
3062 item = TREE_CHAIN (item);
3063 }
3064 }
3065 }
3066
3067 item = build_int_2 ((ffebld_arrter_size (expr)
3068 + ffebld_arrter_pad (expr)) - 1, 0);
3069 TREE_TYPE (item) = ffecom_integer_type_node;
3070 item
3071 = build_array_type
3072 (tree_type,
3073 build_range_type (ffecom_integer_type_node,
3074 ffecom_integer_zero_node,
3075 item));
3076 list = build_constructor (item, list);
3077 TREE_CONSTANT (list) = 1;
3078 TREE_STATIC (list) = 1;
3079 return list;
3080
3081 case FFEBLD_opCONTER:
3082 assert (ffebld_conter_pad (expr) == 0);
3083 item
3084 = ffecom_constantunion (&ffebld_constant_union (ffebld_conter (expr)),
3085 bt, kt, tree_type);
3086 return item;
3087
3088 case FFEBLD_opSYMTER:
3089 if ((ffebld_symter_generic (expr) != FFEINTRIN_genNONE)
3090 || (ffebld_symter_specific (expr) != FFEINTRIN_specNONE))
3091 return ffecom_ptr_to_expr (expr); /* Same as %REF(intrinsic). */
3092 s = ffebld_symter (expr);
3093 t = ffesymbol_hook (s).decl_tree;
3094
3095 if (assignp)
3096 { /* ASSIGN'ed-label expr. */
3097 if (ffe_is_ugly_assign ())
3098 {
3099 /* User explicitly wants ASSIGN'ed variables to be at the same
3100 memory address as the variables when used in non-ASSIGN
3101 contexts. That can make old, arcane, non-standard code
3102 work, but don't try to do it when a pointer wouldn't fit
3103 in the normal variable (take other approach, and warn,
3104 instead). */
3105
3106 if (t == NULL_TREE)
3107 {
3108 s = ffecom_sym_transform_ (s);
3109 t = ffesymbol_hook (s).decl_tree;
3110 assert (t != NULL_TREE);
3111 }
3112
3113 if (t == error_mark_node)
3114 return t;
3115
3116 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (t)))
3117 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
3118 {
3119 if (ffesymbol_hook (s).addr)
3120 t = ffecom_1 (INDIRECT_REF,
3121 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3122 return t;
3123 }
3124
3125 if (ffesymbol_hook (s).assign_tree == NULL_TREE)
3126 {
3127 /* xgettext:no-c-format */
3128 ffebad_start_msg ("ASSIGN'ed label cannot fit into `%A' at %0 -- using wider sibling",
3129 FFEBAD_severityWARNING);
3130 ffebad_string (ffesymbol_text (s));
3131 ffebad_here (0, ffesymbol_where_line (s),
3132 ffesymbol_where_column (s));
3133 ffebad_finish ();
3134 }
3135 }
3136
3137 /* Don't use the normal variable's tree for ASSIGN, though mark
3138 it as in the system header (housekeeping). Use an explicit,
3139 specially created sibling that is known to be wide enough
3140 to hold pointers to labels. */
3141
3142 if (t != NULL_TREE
3143 && TREE_CODE (t) == VAR_DECL)
3144 DECL_IN_SYSTEM_HEADER (t) = 1; /* Don't let -Wunused complain. */
3145
3146 t = ffesymbol_hook (s).assign_tree;
3147 if (t == NULL_TREE)
3148 {
3149 s = ffecom_sym_transform_assign_ (s);
3150 t = ffesymbol_hook (s).assign_tree;
3151 assert (t != NULL_TREE);
3152 }
3153 }
3154 else
3155 {
3156 if (t == NULL_TREE)
3157 {
3158 s = ffecom_sym_transform_ (s);
3159 t = ffesymbol_hook (s).decl_tree;
3160 assert (t != NULL_TREE);
3161 }
3162 if (ffesymbol_hook (s).addr)
3163 t = ffecom_1 (INDIRECT_REF,
3164 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3165 }
3166 return t;
3167
3168 case FFEBLD_opARRAYREF:
3169 return ffecom_arrayref_ (NULL_TREE, expr, 0);
3170
3171 case FFEBLD_opUPLUS:
3172 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3173 return ffecom_1 (NOP_EXPR, tree_type, left);
3174
3175 case FFEBLD_opPAREN:
3176 /* ~~~Make sure Fortran rules respected here */
3177 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3178 return ffecom_1 (NOP_EXPR, tree_type, left);
3179
3180 case FFEBLD_opUMINUS:
3181 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3182 if (tree_type_x)
3183 {
3184 tree_type = tree_type_x;
3185 left = convert (tree_type, left);
3186 }
3187 return ffecom_1 (NEGATE_EXPR, tree_type, left);
3188
3189 case FFEBLD_opADD:
3190 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3191 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3192 if (tree_type_x)
3193 {
3194 tree_type = tree_type_x;
3195 left = convert (tree_type, left);
3196 right = convert (tree_type, right);
3197 }
3198 return ffecom_2 (PLUS_EXPR, tree_type, left, right);
3199
3200 case FFEBLD_opSUBTRACT:
3201 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3202 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3203 if (tree_type_x)
3204 {
3205 tree_type = tree_type_x;
3206 left = convert (tree_type, left);
3207 right = convert (tree_type, right);
3208 }
3209 return ffecom_2 (MINUS_EXPR, tree_type, left, right);
3210
3211 case FFEBLD_opMULTIPLY:
3212 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3213 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3214 if (tree_type_x)
3215 {
3216 tree_type = tree_type_x;
3217 left = convert (tree_type, left);
3218 right = convert (tree_type, right);
3219 }
3220 return ffecom_2 (MULT_EXPR, tree_type, left, right);
3221
3222 case FFEBLD_opDIVIDE:
3223 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3224 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3225 if (tree_type_x)
3226 {
3227 tree_type = tree_type_x;
3228 left = convert (tree_type, left);
3229 right = convert (tree_type, right);
3230 }
3231 return ffecom_tree_divide_ (tree_type, left, right,
3232 dest_tree, dest, dest_used,
3233 ffebld_nonter_hook (expr));
3234
3235 case FFEBLD_opPOWER:
3236 {
3237 ffebld left = ffebld_left (expr);
3238 ffebld right = ffebld_right (expr);
3239 ffecomGfrt code;
3240 ffeinfoKindtype rtkt;
3241 ffeinfoKindtype ltkt;
3242 bool ref = TRUE;
3243
3244 switch (ffeinfo_basictype (ffebld_info (right)))
3245 {
3246
3247 case FFEINFO_basictypeINTEGER:
3248 if (1 || optimize)
3249 {
3250 item = ffecom_expr_power_integer_ (expr);
3251 if (item != NULL_TREE)
3252 return item;
3253 }
3254
3255 rtkt = FFEINFO_kindtypeINTEGER1;
3256 switch (ffeinfo_basictype (ffebld_info (left)))
3257 {
3258 case FFEINFO_basictypeINTEGER:
3259 if ((ffeinfo_kindtype (ffebld_info (left))
3260 == FFEINFO_kindtypeINTEGER4)
3261 || (ffeinfo_kindtype (ffebld_info (right))
3262 == FFEINFO_kindtypeINTEGER4))
3263 {
3264 code = FFECOM_gfrtPOW_QQ;
3265 ltkt = FFEINFO_kindtypeINTEGER4;
3266 rtkt = FFEINFO_kindtypeINTEGER4;
3267 }
3268 else
3269 {
3270 code = FFECOM_gfrtPOW_II;
3271 ltkt = FFEINFO_kindtypeINTEGER1;
3272 }
3273 break;
3274
3275 case FFEINFO_basictypeREAL:
3276 if (ffeinfo_kindtype (ffebld_info (left))
3277 == FFEINFO_kindtypeREAL1)
3278 {
3279 code = FFECOM_gfrtPOW_RI;
3280 ltkt = FFEINFO_kindtypeREAL1;
3281 }
3282 else
3283 {
3284 code = FFECOM_gfrtPOW_DI;
3285 ltkt = FFEINFO_kindtypeREAL2;
3286 }
3287 break;
3288
3289 case FFEINFO_basictypeCOMPLEX:
3290 if (ffeinfo_kindtype (ffebld_info (left))
3291 == FFEINFO_kindtypeREAL1)
3292 {
3293 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
3294 ltkt = FFEINFO_kindtypeREAL1;
3295 }
3296 else
3297 {
3298 code = FFECOM_gfrtPOW_ZI; /* Overlapping result okay. */
3299 ltkt = FFEINFO_kindtypeREAL2;
3300 }
3301 break;
3302
3303 default:
3304 assert ("bad pow_*i" == NULL);
3305 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
3306 ltkt = FFEINFO_kindtypeREAL1;
3307 break;
3308 }
3309 if (ffeinfo_kindtype (ffebld_info (left)) != ltkt)
3310 left = ffeexpr_convert (left, NULL, NULL,
3311 ffeinfo_basictype (ffebld_info (left)),
3312 ltkt, 0,
3313 FFETARGET_charactersizeNONE,
3314 FFEEXPR_contextLET);
3315 if (ffeinfo_kindtype (ffebld_info (right)) != rtkt)
3316 right = ffeexpr_convert (right, NULL, NULL,
3317 FFEINFO_basictypeINTEGER,
3318 rtkt, 0,
3319 FFETARGET_charactersizeNONE,
3320 FFEEXPR_contextLET);
3321 break;
3322
3323 case FFEINFO_basictypeREAL:
3324 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3325 left = ffeexpr_convert (left, NULL, NULL, FFEINFO_basictypeREAL,
3326 FFEINFO_kindtypeREALDOUBLE, 0,
3327 FFETARGET_charactersizeNONE,
3328 FFEEXPR_contextLET);
3329 if (ffeinfo_kindtype (ffebld_info (right))
3330 == FFEINFO_kindtypeREAL1)
3331 right = ffeexpr_convert (right, NULL, NULL,
3332 FFEINFO_basictypeREAL,
3333 FFEINFO_kindtypeREALDOUBLE, 0,
3334 FFETARGET_charactersizeNONE,
3335 FFEEXPR_contextLET);
3336 /* We used to call FFECOM_gfrtPOW_DD here,
3337 which passes arguments by reference. */
3338 code = FFECOM_gfrtL_POW;
3339 /* Pass arguments by value. */
3340 ref = FALSE;
3341 break;
3342
3343 case FFEINFO_basictypeCOMPLEX:
3344 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3345 left = ffeexpr_convert (left, NULL, NULL,
3346 FFEINFO_basictypeCOMPLEX,
3347 FFEINFO_kindtypeREALDOUBLE, 0,
3348 FFETARGET_charactersizeNONE,
3349 FFEEXPR_contextLET);
3350 if (ffeinfo_kindtype (ffebld_info (right))
3351 == FFEINFO_kindtypeREAL1)
3352 right = ffeexpr_convert (right, NULL, NULL,
3353 FFEINFO_basictypeCOMPLEX,
3354 FFEINFO_kindtypeREALDOUBLE, 0,
3355 FFETARGET_charactersizeNONE,
3356 FFEEXPR_contextLET);
3357 code = FFECOM_gfrtPOW_ZZ; /* Overlapping result okay. */
3358 ref = TRUE; /* Pass arguments by reference. */
3359 break;
3360
3361 default:
3362 assert ("bad pow_x*" == NULL);
3363 code = FFECOM_gfrtPOW_II;
3364 break;
3365 }
3366 return ffecom_call_binop_ (ffecom_gfrt_tree_ (code),
3367 ffecom_gfrt_kindtype (code),
3368 (ffe_is_f2c_library ()
3369 && ffecom_gfrt_complex_[code]),
3370 tree_type, left, right,
3371 dest_tree, dest, dest_used,
3372 NULL_TREE, FALSE, ref,
3373 ffebld_nonter_hook (expr));
3374 }
3375
3376 case FFEBLD_opNOT:
3377 switch (bt)
3378 {
3379 case FFEINFO_basictypeLOGICAL:
3380 item = ffecom_truth_value_invert (ffecom_expr (ffebld_left (expr)));
3381 return convert (tree_type, item);
3382
3383 case FFEINFO_basictypeINTEGER:
3384 return ffecom_1 (BIT_NOT_EXPR, tree_type,
3385 ffecom_expr (ffebld_left (expr)));
3386
3387 default:
3388 assert ("NOT bad basictype" == NULL);
3389 /* Fall through. */
3390 case FFEINFO_basictypeANY:
3391 return error_mark_node;
3392 }
3393 break;
3394
3395 case FFEBLD_opFUNCREF:
3396 assert (ffeinfo_basictype (ffebld_info (expr))
3397 != FFEINFO_basictypeCHARACTER);
3398 /* Fall through. */
3399 case FFEBLD_opSUBRREF:
3400 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
3401 == FFEINFO_whereINTRINSIC)
3402 { /* Invocation of an intrinsic. */
3403 item = ffecom_expr_intrinsic_ (expr, dest_tree, dest,
3404 dest_used);
3405 return item;
3406 }
3407 s = ffebld_symter (ffebld_left (expr));
3408 dt = ffesymbol_hook (s).decl_tree;
3409 if (dt == NULL_TREE)
3410 {
3411 s = ffecom_sym_transform_ (s);
3412 dt = ffesymbol_hook (s).decl_tree;
3413 }
3414 if (dt == error_mark_node)
3415 return dt;
3416
3417 if (ffesymbol_hook (s).addr)
3418 item = dt;
3419 else
3420 item = ffecom_1_fn (dt);
3421
3422 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
3423 args = ffecom_list_expr (ffebld_right (expr));
3424 else
3425 args = ffecom_list_ptr_to_expr (ffebld_right (expr));
3426
3427 if (args == error_mark_node)
3428 return error_mark_node;
3429
3430 item = ffecom_call_ (item, kt,
3431 ffesymbol_is_f2c (s)
3432 && (bt == FFEINFO_basictypeCOMPLEX)
3433 && (ffesymbol_where (s)
3434 != FFEINFO_whereCONSTANT),
3435 tree_type,
3436 args,
3437 dest_tree, dest, dest_used,
3438 error_mark_node, FALSE,
3439 ffebld_nonter_hook (expr));
3440 TREE_SIDE_EFFECTS (item) = 1;
3441 return item;
3442
3443 case FFEBLD_opAND:
3444 switch (bt)
3445 {
3446 case FFEINFO_basictypeLOGICAL:
3447 item
3448 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3449 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3450 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3451 return convert (tree_type, item);
3452
3453 case FFEINFO_basictypeINTEGER:
3454 return ffecom_2 (BIT_AND_EXPR, tree_type,
3455 ffecom_expr (ffebld_left (expr)),
3456 ffecom_expr (ffebld_right (expr)));
3457
3458 default:
3459 assert ("AND bad basictype" == NULL);
3460 /* Fall through. */
3461 case FFEINFO_basictypeANY:
3462 return error_mark_node;
3463 }
3464 break;
3465
3466 case FFEBLD_opOR:
3467 switch (bt)
3468 {
3469 case FFEINFO_basictypeLOGICAL:
3470 item
3471 = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
3472 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3473 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3474 return convert (tree_type, item);
3475
3476 case FFEINFO_basictypeINTEGER:
3477 return ffecom_2 (BIT_IOR_EXPR, tree_type,
3478 ffecom_expr (ffebld_left (expr)),
3479 ffecom_expr (ffebld_right (expr)));
3480
3481 default:
3482 assert ("OR bad basictype" == NULL);
3483 /* Fall through. */
3484 case FFEINFO_basictypeANY:
3485 return error_mark_node;
3486 }
3487 break;
3488
3489 case FFEBLD_opXOR:
3490 case FFEBLD_opNEQV:
3491 switch (bt)
3492 {
3493 case FFEINFO_basictypeLOGICAL:
3494 item
3495 = ffecom_2 (NE_EXPR, integer_type_node,
3496 ffecom_expr (ffebld_left (expr)),
3497 ffecom_expr (ffebld_right (expr)));
3498 return convert (tree_type, ffecom_truth_value (item));
3499
3500 case FFEINFO_basictypeINTEGER:
3501 return ffecom_2 (BIT_XOR_EXPR, tree_type,
3502 ffecom_expr (ffebld_left (expr)),
3503 ffecom_expr (ffebld_right (expr)));
3504
3505 default:
3506 assert ("XOR/NEQV bad basictype" == NULL);
3507 /* Fall through. */
3508 case FFEINFO_basictypeANY:
3509 return error_mark_node;
3510 }
3511 break;
3512
3513 case FFEBLD_opEQV:
3514 switch (bt)
3515 {
3516 case FFEINFO_basictypeLOGICAL:
3517 item
3518 = ffecom_2 (EQ_EXPR, integer_type_node,
3519 ffecom_expr (ffebld_left (expr)),
3520 ffecom_expr (ffebld_right (expr)));
3521 return convert (tree_type, ffecom_truth_value (item));
3522
3523 case FFEINFO_basictypeINTEGER:
3524 return
3525 ffecom_1 (BIT_NOT_EXPR, tree_type,
3526 ffecom_2 (BIT_XOR_EXPR, tree_type,
3527 ffecom_expr (ffebld_left (expr)),
3528 ffecom_expr (ffebld_right (expr))));
3529
3530 default:
3531 assert ("EQV bad basictype" == NULL);
3532 /* Fall through. */
3533 case FFEINFO_basictypeANY:
3534 return error_mark_node;
3535 }
3536 break;
3537
3538 case FFEBLD_opCONVERT:
3539 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opANY)
3540 return error_mark_node;
3541
3542 switch (bt)
3543 {
3544 case FFEINFO_basictypeLOGICAL:
3545 case FFEINFO_basictypeINTEGER:
3546 case FFEINFO_basictypeREAL:
3547 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3548
3549 case FFEINFO_basictypeCOMPLEX:
3550 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3551 {
3552 case FFEINFO_basictypeINTEGER:
3553 case FFEINFO_basictypeLOGICAL:
3554 case FFEINFO_basictypeREAL:
3555 item = ffecom_expr (ffebld_left (expr));
3556 if (item == error_mark_node)
3557 return error_mark_node;
3558 /* convert() takes care of converting to the subtype first,
3559 at least in gcc-2.7.2. */
3560 item = convert (tree_type, item);
3561 return item;
3562
3563 case FFEINFO_basictypeCOMPLEX:
3564 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3565
3566 default:
3567 assert ("CONVERT COMPLEX bad basictype" == NULL);
3568 /* Fall through. */
3569 case FFEINFO_basictypeANY:
3570 return error_mark_node;
3571 }
3572 break;
3573
3574 default:
3575 assert ("CONVERT bad basictype" == NULL);
3576 /* Fall through. */
3577 case FFEINFO_basictypeANY:
3578 return error_mark_node;
3579 }
3580 break;
3581
3582 case FFEBLD_opLT:
3583 code = LT_EXPR;
3584 goto relational; /* :::::::::::::::::::: */
3585
3586 case FFEBLD_opLE:
3587 code = LE_EXPR;
3588 goto relational; /* :::::::::::::::::::: */
3589
3590 case FFEBLD_opEQ:
3591 code = EQ_EXPR;
3592 goto relational; /* :::::::::::::::::::: */
3593
3594 case FFEBLD_opNE:
3595 code = NE_EXPR;
3596 goto relational; /* :::::::::::::::::::: */
3597
3598 case FFEBLD_opGT:
3599 code = GT_EXPR;
3600 goto relational; /* :::::::::::::::::::: */
3601
3602 case FFEBLD_opGE:
3603 code = GE_EXPR;
3604
3605 relational: /* :::::::::::::::::::: */
3606 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3607 {
3608 case FFEINFO_basictypeLOGICAL:
3609 case FFEINFO_basictypeINTEGER:
3610 case FFEINFO_basictypeREAL:
3611 item = ffecom_2 (code, integer_type_node,
3612 ffecom_expr (ffebld_left (expr)),
3613 ffecom_expr (ffebld_right (expr)));
3614 return convert (tree_type, item);
3615
3616 case FFEINFO_basictypeCOMPLEX:
3617 assert (code == EQ_EXPR || code == NE_EXPR);
3618 {
3619 tree real_type;
3620 tree arg1 = ffecom_expr (ffebld_left (expr));
3621 tree arg2 = ffecom_expr (ffebld_right (expr));
3622
3623 if (arg1 == error_mark_node || arg2 == error_mark_node)
3624 return error_mark_node;
3625
3626 arg1 = ffecom_save_tree (arg1);
3627 arg2 = ffecom_save_tree (arg2);
3628
3629 if (TREE_CODE (TREE_TYPE (arg1)) == COMPLEX_TYPE)
3630 {
3631 real_type = TREE_TYPE (TREE_TYPE (arg1));
3632 assert (real_type == TREE_TYPE (TREE_TYPE (arg2)));
3633 }
3634 else
3635 {
3636 real_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg1)));
3637 assert (real_type == TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg2))));
3638 }
3639
3640 item
3641 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3642 ffecom_2 (EQ_EXPR, integer_type_node,
3643 ffecom_1 (REALPART_EXPR, real_type, arg1),
3644 ffecom_1 (REALPART_EXPR, real_type, arg2)),
3645 ffecom_2 (EQ_EXPR, integer_type_node,
3646 ffecom_1 (IMAGPART_EXPR, real_type, arg1),
3647 ffecom_1 (IMAGPART_EXPR, real_type,
3648 arg2)));
3649 if (code == EQ_EXPR)
3650 item = ffecom_truth_value (item);
3651 else
3652 item = ffecom_truth_value_invert (item);
3653 return convert (tree_type, item);
3654 }
3655
3656 case FFEINFO_basictypeCHARACTER:
3657 {
3658 ffebld left = ffebld_left (expr);
3659 ffebld right = ffebld_right (expr);
3660 tree left_tree;
3661 tree right_tree;
3662 tree left_length;
3663 tree right_length;
3664
3665 /* f2c run-time functions do the implicit blank-padding for us,
3666 so we don't usually have to implement blank-padding ourselves.
3667 (The exception is when we pass an argument to a separately
3668 compiled statement function -- if we know the arg is not the
3669 same length as the dummy, we must truncate or extend it. If
3670 we "inline" statement functions, that necessity goes away as
3671 well.)
3672
3673 Strip off the CONVERT operators that blank-pad. (Truncation by
3674 CONVERT shouldn't happen here, but it can happen in
3675 assignments.) */
3676
3677 while (ffebld_op (left) == FFEBLD_opCONVERT)
3678 left = ffebld_left (left);
3679 while (ffebld_op (right) == FFEBLD_opCONVERT)
3680 right = ffebld_left (right);
3681
3682 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
3683 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
3684
3685 if (left_tree == error_mark_node || left_length == error_mark_node
3686 || right_tree == error_mark_node
3687 || right_length == error_mark_node)
3688 return error_mark_node;
3689
3690 if ((ffebld_size_known (left) == 1)
3691 && (ffebld_size_known (right) == 1))
3692 {
3693 left_tree
3694 = ffecom_1 (INDIRECT_REF,
3695 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3696 left_tree);
3697 right_tree
3698 = ffecom_1 (INDIRECT_REF,
3699 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3700 right_tree);
3701
3702 item
3703 = ffecom_2 (code, integer_type_node,
3704 ffecom_2 (ARRAY_REF,
3705 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3706 left_tree,
3707 integer_one_node),
3708 ffecom_2 (ARRAY_REF,
3709 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3710 right_tree,
3711 integer_one_node));
3712 }
3713 else
3714 {
3715 item = build_tree_list (NULL_TREE, left_tree);
3716 TREE_CHAIN (item) = build_tree_list (NULL_TREE, right_tree);
3717 TREE_CHAIN (TREE_CHAIN (item)) = build_tree_list (NULL_TREE,
3718 left_length);
3719 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
3720 = build_tree_list (NULL_TREE, right_length);
3721 item = ffecom_call_gfrt (FFECOM_gfrtCMP, item, NULL_TREE);
3722 item = ffecom_2 (code, integer_type_node,
3723 item,
3724 convert (TREE_TYPE (item),
3725 integer_zero_node));
3726 }
3727 item = convert (tree_type, item);
3728 }
3729
3730 return item;
3731
3732 default:
3733 assert ("relational bad basictype" == NULL);
3734 /* Fall through. */
3735 case FFEINFO_basictypeANY:
3736 return error_mark_node;
3737 }
3738 break;
3739
3740 case FFEBLD_opPERCENT_LOC:
3741 item = ffecom_arg_ptr_to_expr (ffebld_left (expr), &list);
3742 return convert (tree_type, item);
3743
3744 case FFEBLD_opPERCENT_VAL:
3745 item = ffecom_arg_expr (ffebld_left (expr), &list);
3746 return convert (tree_type, item);
3747
3748 case FFEBLD_opITEM:
3749 case FFEBLD_opSTAR:
3750 case FFEBLD_opBOUNDS:
3751 case FFEBLD_opREPEAT:
3752 case FFEBLD_opLABTER:
3753 case FFEBLD_opLABTOK:
3754 case FFEBLD_opIMPDO:
3755 case FFEBLD_opCONCATENATE:
3756 case FFEBLD_opSUBSTR:
3757 default:
3758 assert ("bad op" == NULL);
3759 /* Fall through. */
3760 case FFEBLD_opANY:
3761 return error_mark_node;
3762 }
3763
3764 #if 1
3765 assert ("didn't think anything got here anymore!!" == NULL);
3766 #else
3767 switch (ffebld_arity (expr))
3768 {
3769 case 2:
3770 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3771 TREE_OPERAND (item, 1) = ffecom_expr (ffebld_right (expr));
3772 if (TREE_OPERAND (item, 0) == error_mark_node
3773 || TREE_OPERAND (item, 1) == error_mark_node)
3774 return error_mark_node;
3775 break;
3776
3777 case 1:
3778 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3779 if (TREE_OPERAND (item, 0) == error_mark_node)
3780 return error_mark_node;
3781 break;
3782
3783 default:
3784 break;
3785 }
3786
3787 return fold (item);
3788 #endif
3789 }
3790
3791 /* Returns the tree that does the intrinsic invocation.
3792
3793 Note: this function applies only to intrinsics returning
3794 CHARACTER*1 or non-CHARACTER results, and to intrinsic
3795 subroutines. */
3796
3797 static tree
3798 ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
3799 ffebld dest, bool *dest_used)
3800 {
3801 tree expr_tree;
3802 tree saved_expr1; /* For those who need it. */
3803 tree saved_expr2; /* For those who need it. */
3804 ffeinfoBasictype bt;
3805 ffeinfoKindtype kt;
3806 tree tree_type;
3807 tree arg1_type;
3808 tree real_type; /* REAL type corresponding to COMPLEX. */
3809 tree tempvar;
3810 ffebld list = ffebld_right (expr); /* List of (some) args. */
3811 ffebld arg1; /* For handy reference. */
3812 ffebld arg2;
3813 ffebld arg3;
3814 ffeintrinImp codegen_imp;
3815 ffecomGfrt gfrt;
3816
3817 assert (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER);
3818
3819 if (dest_used != NULL)
3820 *dest_used = FALSE;
3821
3822 bt = ffeinfo_basictype (ffebld_info (expr));
3823 kt = ffeinfo_kindtype (ffebld_info (expr));
3824 tree_type = ffecom_tree_type[bt][kt];
3825
3826 if (list != NULL)
3827 {
3828 arg1 = ffebld_head (list);
3829 if (arg1 != NULL && ffebld_op (arg1) == FFEBLD_opANY)
3830 return error_mark_node;
3831 if ((list = ffebld_trail (list)) != NULL)
3832 {
3833 arg2 = ffebld_head (list);
3834 if (arg2 != NULL && ffebld_op (arg2) == FFEBLD_opANY)
3835 return error_mark_node;
3836 if ((list = ffebld_trail (list)) != NULL)
3837 {
3838 arg3 = ffebld_head (list);
3839 if (arg3 != NULL && ffebld_op (arg3) == FFEBLD_opANY)
3840 return error_mark_node;
3841 }
3842 else
3843 arg3 = NULL;
3844 }
3845 else
3846 arg2 = arg3 = NULL;
3847 }
3848 else
3849 arg1 = arg2 = arg3 = NULL;
3850
3851 /* <list> ends up at the opITEM of the 3rd arg, or NULL if there are < 3
3852 args. This is used by the MAX/MIN expansions. */
3853
3854 if (arg1 != NULL)
3855 arg1_type = ffecom_tree_type
3856 [ffeinfo_basictype (ffebld_info (arg1))]
3857 [ffeinfo_kindtype (ffebld_info (arg1))];
3858 else
3859 arg1_type = NULL_TREE; /* Really not needed, but might catch bugs
3860 here. */
3861
3862 /* There are several ways for each of the cases in the following switch
3863 statements to exit (from simplest to use to most complicated):
3864
3865 break; (when expr_tree == NULL)
3866
3867 A standard call is made to the specific intrinsic just as if it had been
3868 passed in as a dummy procedure and called as any old procedure. This
3869 method can produce slower code but in some cases it's the easiest way for
3870 now. However, if a (presumably faster) direct call is available,
3871 that is used, so this is the easiest way in many more cases now.
3872
3873 gfrt = FFECOM_gfrtWHATEVER;
3874 break;
3875
3876 gfrt contains the gfrt index of a library function to call, passing the
3877 argument(s) by value rather than by reference. Used when a more
3878 careful choice of library function is needed than that provided
3879 by the vanilla `break;'.
3880
3881 return expr_tree;
3882
3883 The expr_tree has been completely set up and is ready to be returned
3884 as is. No further actions are taken. Use this when the tree is not
3885 in the simple form for one of the arity_n labels. */
3886
3887 /* For info on how the switch statement cases were written, see the files
3888 enclosed in comments below the switch statement. */
3889
3890 codegen_imp = ffebld_symter_implementation (ffebld_left (expr));
3891 gfrt = ffeintrin_gfrt_direct (codegen_imp);
3892 if (gfrt == FFECOM_gfrt)
3893 gfrt = ffeintrin_gfrt_indirect (codegen_imp);
3894
3895 switch (codegen_imp)
3896 {
3897 case FFEINTRIN_impABS:
3898 case FFEINTRIN_impCABS:
3899 case FFEINTRIN_impCDABS:
3900 case FFEINTRIN_impDABS:
3901 case FFEINTRIN_impIABS:
3902 if (ffeinfo_basictype (ffebld_info (arg1))
3903 == FFEINFO_basictypeCOMPLEX)
3904 {
3905 if (kt == FFEINFO_kindtypeREAL1)
3906 gfrt = FFECOM_gfrtCABS;
3907 else if (kt == FFEINFO_kindtypeREAL2)
3908 gfrt = FFECOM_gfrtCDABS;
3909 break;
3910 }
3911 return ffecom_1 (ABS_EXPR, tree_type,
3912 convert (tree_type, ffecom_expr (arg1)));
3913
3914 case FFEINTRIN_impACOS:
3915 case FFEINTRIN_impDACOS:
3916 break;
3917
3918 case FFEINTRIN_impAIMAG:
3919 case FFEINTRIN_impDIMAG:
3920 case FFEINTRIN_impIMAGPART:
3921 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
3922 arg1_type = TREE_TYPE (arg1_type);
3923 else
3924 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
3925
3926 return
3927 convert (tree_type,
3928 ffecom_1 (IMAGPART_EXPR, arg1_type,
3929 ffecom_expr (arg1)));
3930
3931 case FFEINTRIN_impAINT:
3932 case FFEINTRIN_impDINT:
3933 #if 0
3934 /* ~~Someday implement FIX_TRUNC_EXPR yielding same type as arg. */
3935 return ffecom_1 (FIX_TRUNC_EXPR, tree_type, ffecom_expr (arg1));
3936 #else /* in the meantime, must use floor to avoid range problems with ints */
3937 /* r__1 = r1 >= 0 ? floor(r1) : -floor(-r1); */
3938 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
3939 return
3940 convert (tree_type,
3941 ffecom_3 (COND_EXPR, double_type_node,
3942 ffecom_truth_value
3943 (ffecom_2 (GE_EXPR, integer_type_node,
3944 saved_expr1,
3945 convert (arg1_type,
3946 ffecom_float_zero_))),
3947 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
3948 build_tree_list (NULL_TREE,
3949 convert (double_type_node,
3950 saved_expr1)),
3951 NULL_TREE),
3952 ffecom_1 (NEGATE_EXPR, double_type_node,
3953 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
3954 build_tree_list (NULL_TREE,
3955 convert (double_type_node,
3956 ffecom_1 (NEGATE_EXPR,
3957 arg1_type,
3958 saved_expr1))),
3959 NULL_TREE)
3960 ))
3961 );
3962 #endif
3963
3964 case FFEINTRIN_impANINT:
3965 case FFEINTRIN_impDNINT:
3966 #if 0 /* This way of doing it won't handle real
3967 numbers of large magnitudes. */
3968 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
3969 expr_tree = convert (tree_type,
3970 convert (integer_type_node,
3971 ffecom_3 (COND_EXPR, tree_type,
3972 ffecom_truth_value
3973 (ffecom_2 (GE_EXPR,
3974 integer_type_node,
3975 saved_expr1,
3976 ffecom_float_zero_)),
3977 ffecom_2 (PLUS_EXPR,
3978 tree_type,
3979 saved_expr1,
3980 ffecom_float_half_),
3981 ffecom_2 (MINUS_EXPR,
3982 tree_type,
3983 saved_expr1,
3984 ffecom_float_half_))));
3985 return expr_tree;
3986 #else /* So we instead call floor. */
3987 /* r__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1) */
3988 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
3989 return
3990 convert (tree_type,
3991 ffecom_3 (COND_EXPR, double_type_node,
3992 ffecom_truth_value
3993 (ffecom_2 (GE_EXPR, integer_type_node,
3994 saved_expr1,
3995 convert (arg1_type,
3996 ffecom_float_zero_))),
3997 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
3998 build_tree_list (NULL_TREE,
3999 convert (double_type_node,
4000 ffecom_2 (PLUS_EXPR,
4001 arg1_type,
4002 saved_expr1,
4003 convert (arg1_type,
4004 ffecom_float_half_)))),
4005 NULL_TREE),
4006 ffecom_1 (NEGATE_EXPR, double_type_node,
4007 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4008 build_tree_list (NULL_TREE,
4009 convert (double_type_node,
4010 ffecom_2 (MINUS_EXPR,
4011 arg1_type,
4012 convert (arg1_type,
4013 ffecom_float_half_),
4014 saved_expr1))),
4015 NULL_TREE))
4016 )
4017 );
4018 #endif
4019
4020 case FFEINTRIN_impASIN:
4021 case FFEINTRIN_impDASIN:
4022 case FFEINTRIN_impATAN:
4023 case FFEINTRIN_impDATAN:
4024 case FFEINTRIN_impATAN2:
4025 case FFEINTRIN_impDATAN2:
4026 break;
4027
4028 case FFEINTRIN_impCHAR:
4029 case FFEINTRIN_impACHAR:
4030 tempvar = ffebld_nonter_hook (expr);
4031 assert (tempvar);
4032 {
4033 tree tmv = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (tempvar)));
4034
4035 expr_tree = ffecom_modify (tmv,
4036 ffecom_2 (ARRAY_REF, tmv, tempvar,
4037 integer_one_node),
4038 convert (tmv, ffecom_expr (arg1)));
4039 }
4040 expr_tree = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar),
4041 expr_tree,
4042 tempvar);
4043 expr_tree = ffecom_1 (ADDR_EXPR,
4044 build_pointer_type (TREE_TYPE (expr_tree)),
4045 expr_tree);
4046 return expr_tree;
4047
4048 case FFEINTRIN_impCMPLX:
4049 case FFEINTRIN_impDCMPLX:
4050 if (arg2 == NULL)
4051 return
4052 convert (tree_type, ffecom_expr (arg1));
4053
4054 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4055 return
4056 ffecom_2 (COMPLEX_EXPR, tree_type,
4057 convert (real_type, ffecom_expr (arg1)),
4058 convert (real_type,
4059 ffecom_expr (arg2)));
4060
4061 case FFEINTRIN_impCOMPLEX:
4062 return
4063 ffecom_2 (COMPLEX_EXPR, tree_type,
4064 ffecom_expr (arg1),
4065 ffecom_expr (arg2));
4066
4067 case FFEINTRIN_impCONJG:
4068 case FFEINTRIN_impDCONJG:
4069 {
4070 tree arg1_tree;
4071
4072 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4073 arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4074 return
4075 ffecom_2 (COMPLEX_EXPR, tree_type,
4076 ffecom_1 (REALPART_EXPR, real_type, arg1_tree),
4077 ffecom_1 (NEGATE_EXPR, real_type,
4078 ffecom_1 (IMAGPART_EXPR, real_type, arg1_tree)));
4079 }
4080
4081 case FFEINTRIN_impCOS:
4082 case FFEINTRIN_impCCOS:
4083 case FFEINTRIN_impCDCOS:
4084 case FFEINTRIN_impDCOS:
4085 if (bt == FFEINFO_basictypeCOMPLEX)
4086 {
4087 if (kt == FFEINFO_kindtypeREAL1)
4088 gfrt = FFECOM_gfrtCCOS; /* Overlapping result okay. */
4089 else if (kt == FFEINFO_kindtypeREAL2)
4090 gfrt = FFECOM_gfrtCDCOS; /* Overlapping result okay. */
4091 }
4092 break;
4093
4094 case FFEINTRIN_impCOSH:
4095 case FFEINTRIN_impDCOSH:
4096 break;
4097
4098 case FFEINTRIN_impDBLE:
4099 case FFEINTRIN_impDFLOAT:
4100 case FFEINTRIN_impDREAL:
4101 case FFEINTRIN_impFLOAT:
4102 case FFEINTRIN_impIDINT:
4103 case FFEINTRIN_impIFIX:
4104 case FFEINTRIN_impINT2:
4105 case FFEINTRIN_impINT8:
4106 case FFEINTRIN_impINT:
4107 case FFEINTRIN_impLONG:
4108 case FFEINTRIN_impREAL:
4109 case FFEINTRIN_impSHORT:
4110 case FFEINTRIN_impSNGL:
4111 return convert (tree_type, ffecom_expr (arg1));
4112
4113 case FFEINTRIN_impDIM:
4114 case FFEINTRIN_impDDIM:
4115 case FFEINTRIN_impIDIM:
4116 saved_expr1 = ffecom_save_tree (convert (tree_type,
4117 ffecom_expr (arg1)));
4118 saved_expr2 = ffecom_save_tree (convert (tree_type,
4119 ffecom_expr (arg2)));
4120 return
4121 ffecom_3 (COND_EXPR, tree_type,
4122 ffecom_truth_value
4123 (ffecom_2 (GT_EXPR, integer_type_node,
4124 saved_expr1,
4125 saved_expr2)),
4126 ffecom_2 (MINUS_EXPR, tree_type,
4127 saved_expr1,
4128 saved_expr2),
4129 convert (tree_type, ffecom_float_zero_));
4130
4131 case FFEINTRIN_impDPROD:
4132 return
4133 ffecom_2 (MULT_EXPR, tree_type,
4134 convert (tree_type, ffecom_expr (arg1)),
4135 convert (tree_type, ffecom_expr (arg2)));
4136
4137 case FFEINTRIN_impEXP:
4138 case FFEINTRIN_impCDEXP:
4139 case FFEINTRIN_impCEXP:
4140 case FFEINTRIN_impDEXP:
4141 if (bt == FFEINFO_basictypeCOMPLEX)
4142 {
4143 if (kt == FFEINFO_kindtypeREAL1)
4144 gfrt = FFECOM_gfrtCEXP; /* Overlapping result okay. */
4145 else if (kt == FFEINFO_kindtypeREAL2)
4146 gfrt = FFECOM_gfrtCDEXP; /* Overlapping result okay. */
4147 }
4148 break;
4149
4150 case FFEINTRIN_impICHAR:
4151 case FFEINTRIN_impIACHAR:
4152 #if 0 /* The simple approach. */
4153 ffecom_char_args_ (&expr_tree, &saved_expr1 /* Ignored */ , arg1);
4154 expr_tree
4155 = ffecom_1 (INDIRECT_REF,
4156 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4157 expr_tree);
4158 expr_tree
4159 = ffecom_2 (ARRAY_REF,
4160 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4161 expr_tree,
4162 integer_one_node);
4163 return convert (tree_type, expr_tree);
4164 #else /* The more interesting (and more optimal) approach. */
4165 expr_tree = ffecom_intrinsic_ichar_ (tree_type, arg1, &saved_expr1);
4166 expr_tree = ffecom_3 (COND_EXPR, tree_type,
4167 saved_expr1,
4168 expr_tree,
4169 convert (tree_type, integer_zero_node));
4170 return expr_tree;
4171 #endif
4172
4173 case FFEINTRIN_impINDEX:
4174 break;
4175
4176 case FFEINTRIN_impLEN:
4177 #if 0
4178 break; /* The simple approach. */
4179 #else
4180 return ffecom_intrinsic_len_ (arg1); /* The more optimal approach. */
4181 #endif
4182
4183 case FFEINTRIN_impLGE:
4184 case FFEINTRIN_impLGT:
4185 case FFEINTRIN_impLLE:
4186 case FFEINTRIN_impLLT:
4187 break;
4188
4189 case FFEINTRIN_impLOG:
4190 case FFEINTRIN_impALOG:
4191 case FFEINTRIN_impCDLOG:
4192 case FFEINTRIN_impCLOG:
4193 case FFEINTRIN_impDLOG:
4194 if (bt == FFEINFO_basictypeCOMPLEX)
4195 {
4196 if (kt == FFEINFO_kindtypeREAL1)
4197 gfrt = FFECOM_gfrtCLOG; /* Overlapping result okay. */
4198 else if (kt == FFEINFO_kindtypeREAL2)
4199 gfrt = FFECOM_gfrtCDLOG; /* Overlapping result okay. */
4200 }
4201 break;
4202
4203 case FFEINTRIN_impLOG10:
4204 case FFEINTRIN_impALOG10:
4205 case FFEINTRIN_impDLOG10:
4206 if (gfrt != FFECOM_gfrt)
4207 break; /* Already picked one, stick with it. */
4208
4209 if (kt == FFEINFO_kindtypeREAL1)
4210 /* We used to call FFECOM_gfrtALOG10 here. */
4211 gfrt = FFECOM_gfrtL_LOG10;
4212 else if (kt == FFEINFO_kindtypeREAL2)
4213 /* We used to call FFECOM_gfrtDLOG10 here. */
4214 gfrt = FFECOM_gfrtL_LOG10;
4215 break;
4216
4217 case FFEINTRIN_impMAX:
4218 case FFEINTRIN_impAMAX0:
4219 case FFEINTRIN_impAMAX1:
4220 case FFEINTRIN_impDMAX1:
4221 case FFEINTRIN_impMAX0:
4222 case FFEINTRIN_impMAX1:
4223 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4224 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4225 else
4226 arg1_type = tree_type;
4227 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4228 convert (arg1_type, ffecom_expr (arg1)),
4229 convert (arg1_type, ffecom_expr (arg2)));
4230 for (; list != NULL; list = ffebld_trail (list))
4231 {
4232 if ((ffebld_head (list) == NULL)
4233 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4234 continue;
4235 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4236 expr_tree,
4237 convert (arg1_type,
4238 ffecom_expr (ffebld_head (list))));
4239 }
4240 return convert (tree_type, expr_tree);
4241
4242 case FFEINTRIN_impMIN:
4243 case FFEINTRIN_impAMIN0:
4244 case FFEINTRIN_impAMIN1:
4245 case FFEINTRIN_impDMIN1:
4246 case FFEINTRIN_impMIN0:
4247 case FFEINTRIN_impMIN1:
4248 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4249 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4250 else
4251 arg1_type = tree_type;
4252 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4253 convert (arg1_type, ffecom_expr (arg1)),
4254 convert (arg1_type, ffecom_expr (arg2)));
4255 for (; list != NULL; list = ffebld_trail (list))
4256 {
4257 if ((ffebld_head (list) == NULL)
4258 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4259 continue;
4260 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4261 expr_tree,
4262 convert (arg1_type,
4263 ffecom_expr (ffebld_head (list))));
4264 }
4265 return convert (tree_type, expr_tree);
4266
4267 case FFEINTRIN_impMOD:
4268 case FFEINTRIN_impAMOD:
4269 case FFEINTRIN_impDMOD:
4270 if (bt != FFEINFO_basictypeREAL)
4271 return ffecom_2 (TRUNC_MOD_EXPR, tree_type,
4272 convert (tree_type, ffecom_expr (arg1)),
4273 convert (tree_type, ffecom_expr (arg2)));
4274
4275 if (kt == FFEINFO_kindtypeREAL1)
4276 /* We used to call FFECOM_gfrtAMOD here. */
4277 gfrt = FFECOM_gfrtL_FMOD;
4278 else if (kt == FFEINFO_kindtypeREAL2)
4279 /* We used to call FFECOM_gfrtDMOD here. */
4280 gfrt = FFECOM_gfrtL_FMOD;
4281 break;
4282
4283 case FFEINTRIN_impNINT:
4284 case FFEINTRIN_impIDNINT:
4285 #if 0
4286 /* ~~Ideally FIX_ROUND_EXPR would be implemented, but it ain't yet. */
4287 return ffecom_1 (FIX_ROUND_EXPR, tree_type, ffecom_expr (arg1));
4288 #else
4289 /* i__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1); */
4290 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4291 return
4292 convert (ffecom_integer_type_node,
4293 ffecom_3 (COND_EXPR, arg1_type,
4294 ffecom_truth_value
4295 (ffecom_2 (GE_EXPR, integer_type_node,
4296 saved_expr1,
4297 convert (arg1_type,
4298 ffecom_float_zero_))),
4299 ffecom_2 (PLUS_EXPR, arg1_type,
4300 saved_expr1,
4301 convert (arg1_type,
4302 ffecom_float_half_)),
4303 ffecom_2 (MINUS_EXPR, arg1_type,
4304 saved_expr1,
4305 convert (arg1_type,
4306 ffecom_float_half_))));
4307 #endif
4308
4309 case FFEINTRIN_impSIGN:
4310 case FFEINTRIN_impDSIGN:
4311 case FFEINTRIN_impISIGN:
4312 {
4313 tree arg2_tree = ffecom_expr (arg2);
4314
4315 saved_expr1
4316 = ffecom_save_tree
4317 (ffecom_1 (ABS_EXPR, tree_type,
4318 convert (tree_type,
4319 ffecom_expr (arg1))));
4320 expr_tree
4321 = ffecom_3 (COND_EXPR, tree_type,
4322 ffecom_truth_value
4323 (ffecom_2 (GE_EXPR, integer_type_node,
4324 arg2_tree,
4325 convert (TREE_TYPE (arg2_tree),
4326 integer_zero_node))),
4327 saved_expr1,
4328 ffecom_1 (NEGATE_EXPR, tree_type, saved_expr1));
4329 /* Make sure SAVE_EXPRs get referenced early enough. */
4330 expr_tree
4331 = ffecom_2 (COMPOUND_EXPR, tree_type,
4332 convert (void_type_node, saved_expr1),
4333 expr_tree);
4334 }
4335 return expr_tree;
4336
4337 case FFEINTRIN_impSIN:
4338 case FFEINTRIN_impCDSIN:
4339 case FFEINTRIN_impCSIN:
4340 case FFEINTRIN_impDSIN:
4341 if (bt == FFEINFO_basictypeCOMPLEX)
4342 {
4343 if (kt == FFEINFO_kindtypeREAL1)
4344 gfrt = FFECOM_gfrtCSIN; /* Overlapping result okay. */
4345 else if (kt == FFEINFO_kindtypeREAL2)
4346 gfrt = FFECOM_gfrtCDSIN; /* Overlapping result okay. */
4347 }
4348 break;
4349
4350 case FFEINTRIN_impSINH:
4351 case FFEINTRIN_impDSINH:
4352 break;
4353
4354 case FFEINTRIN_impSQRT:
4355 case FFEINTRIN_impCDSQRT:
4356 case FFEINTRIN_impCSQRT:
4357 case FFEINTRIN_impDSQRT:
4358 if (bt == FFEINFO_basictypeCOMPLEX)
4359 {
4360 if (kt == FFEINFO_kindtypeREAL1)
4361 gfrt = FFECOM_gfrtCSQRT; /* Overlapping result okay. */
4362 else if (kt == FFEINFO_kindtypeREAL2)
4363 gfrt = FFECOM_gfrtCDSQRT; /* Overlapping result okay. */
4364 }
4365 break;
4366
4367 case FFEINTRIN_impTAN:
4368 case FFEINTRIN_impDTAN:
4369 case FFEINTRIN_impTANH:
4370 case FFEINTRIN_impDTANH:
4371 break;
4372
4373 case FFEINTRIN_impREALPART:
4374 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4375 arg1_type = TREE_TYPE (arg1_type);
4376 else
4377 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4378
4379 return
4380 convert (tree_type,
4381 ffecom_1 (REALPART_EXPR, arg1_type,
4382 ffecom_expr (arg1)));
4383
4384 case FFEINTRIN_impIAND:
4385 case FFEINTRIN_impAND:
4386 return ffecom_2 (BIT_AND_EXPR, tree_type,
4387 convert (tree_type,
4388 ffecom_expr (arg1)),
4389 convert (tree_type,
4390 ffecom_expr (arg2)));
4391
4392 case FFEINTRIN_impIOR:
4393 case FFEINTRIN_impOR:
4394 return ffecom_2 (BIT_IOR_EXPR, tree_type,
4395 convert (tree_type,
4396 ffecom_expr (arg1)),
4397 convert (tree_type,
4398 ffecom_expr (arg2)));
4399
4400 case FFEINTRIN_impIEOR:
4401 case FFEINTRIN_impXOR:
4402 return ffecom_2 (BIT_XOR_EXPR, tree_type,
4403 convert (tree_type,
4404 ffecom_expr (arg1)),
4405 convert (tree_type,
4406 ffecom_expr (arg2)));
4407
4408 case FFEINTRIN_impLSHIFT:
4409 return ffecom_2 (LSHIFT_EXPR, tree_type,
4410 ffecom_expr (arg1),
4411 convert (integer_type_node,
4412 ffecom_expr (arg2)));
4413
4414 case FFEINTRIN_impRSHIFT:
4415 return ffecom_2 (RSHIFT_EXPR, tree_type,
4416 ffecom_expr (arg1),
4417 convert (integer_type_node,
4418 ffecom_expr (arg2)));
4419
4420 case FFEINTRIN_impNOT:
4421 return ffecom_1 (BIT_NOT_EXPR, tree_type, ffecom_expr (arg1));
4422
4423 case FFEINTRIN_impBIT_SIZE:
4424 return convert (tree_type, TYPE_SIZE (arg1_type));
4425
4426 case FFEINTRIN_impBTEST:
4427 {
4428 ffetargetLogical1 target_true;
4429 ffetargetLogical1 target_false;
4430 tree true_tree;
4431 tree false_tree;
4432
4433 ffetarget_logical1 (&target_true, TRUE);
4434 ffetarget_logical1 (&target_false, FALSE);
4435 if (target_true == 1)
4436 true_tree = convert (tree_type, integer_one_node);
4437 else
4438 true_tree = convert (tree_type, build_int_2 (target_true, 0));
4439 if (target_false == 0)
4440 false_tree = convert (tree_type, integer_zero_node);
4441 else
4442 false_tree = convert (tree_type, build_int_2 (target_false, 0));
4443
4444 return
4445 ffecom_3 (COND_EXPR, tree_type,
4446 ffecom_truth_value
4447 (ffecom_2 (EQ_EXPR, integer_type_node,
4448 ffecom_2 (BIT_AND_EXPR, arg1_type,
4449 ffecom_expr (arg1),
4450 ffecom_2 (LSHIFT_EXPR, arg1_type,
4451 convert (arg1_type,
4452 integer_one_node),
4453 convert (integer_type_node,
4454 ffecom_expr (arg2)))),
4455 convert (arg1_type,
4456 integer_zero_node))),
4457 false_tree,
4458 true_tree);
4459 }
4460
4461 case FFEINTRIN_impIBCLR:
4462 return
4463 ffecom_2 (BIT_AND_EXPR, tree_type,
4464 ffecom_expr (arg1),
4465 ffecom_1 (BIT_NOT_EXPR, tree_type,
4466 ffecom_2 (LSHIFT_EXPR, tree_type,
4467 convert (tree_type,
4468 integer_one_node),
4469 convert (integer_type_node,
4470 ffecom_expr (arg2)))));
4471
4472 case FFEINTRIN_impIBITS:
4473 {
4474 tree arg3_tree = ffecom_save_tree (convert (integer_type_node,
4475 ffecom_expr (arg3)));
4476 tree uns_type
4477 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4478
4479 expr_tree
4480 = ffecom_2 (BIT_AND_EXPR, tree_type,
4481 ffecom_2 (RSHIFT_EXPR, tree_type,
4482 ffecom_expr (arg1),
4483 convert (integer_type_node,
4484 ffecom_expr (arg2))),
4485 convert (tree_type,
4486 ffecom_2 (RSHIFT_EXPR, uns_type,
4487 ffecom_1 (BIT_NOT_EXPR,
4488 uns_type,
4489 convert (uns_type,
4490 integer_zero_node)),
4491 ffecom_2 (MINUS_EXPR,
4492 integer_type_node,
4493 TYPE_SIZE (uns_type),
4494 arg3_tree))));
4495 /* Fix up, because the RSHIFT_EXPR above can't shift over TYPE_SIZE. */
4496 expr_tree
4497 = ffecom_3 (COND_EXPR, tree_type,
4498 ffecom_truth_value
4499 (ffecom_2 (NE_EXPR, integer_type_node,
4500 arg3_tree,
4501 integer_zero_node)),
4502 expr_tree,
4503 convert (tree_type, integer_zero_node));
4504 }
4505 return expr_tree;
4506
4507 case FFEINTRIN_impIBSET:
4508 return
4509 ffecom_2 (BIT_IOR_EXPR, tree_type,
4510 ffecom_expr (arg1),
4511 ffecom_2 (LSHIFT_EXPR, tree_type,
4512 convert (tree_type, integer_one_node),
4513 convert (integer_type_node,
4514 ffecom_expr (arg2))));
4515
4516 case FFEINTRIN_impISHFT:
4517 {
4518 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4519 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4520 ffecom_expr (arg2)));
4521 tree uns_type
4522 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4523
4524 expr_tree
4525 = ffecom_3 (COND_EXPR, tree_type,
4526 ffecom_truth_value
4527 (ffecom_2 (GE_EXPR, integer_type_node,
4528 arg2_tree,
4529 integer_zero_node)),
4530 ffecom_2 (LSHIFT_EXPR, tree_type,
4531 arg1_tree,
4532 arg2_tree),
4533 convert (tree_type,
4534 ffecom_2 (RSHIFT_EXPR, uns_type,
4535 convert (uns_type, arg1_tree),
4536 ffecom_1 (NEGATE_EXPR,
4537 integer_type_node,
4538 arg2_tree))));
4539 /* Fix up, because {L|R}SHIFT_EXPR don't go over TYPE_SIZE bounds. */
4540 expr_tree
4541 = ffecom_3 (COND_EXPR, tree_type,
4542 ffecom_truth_value
4543 (ffecom_2 (NE_EXPR, integer_type_node,
4544 ffecom_1 (ABS_EXPR,
4545 integer_type_node,
4546 arg2_tree),
4547 TYPE_SIZE (uns_type))),
4548 expr_tree,
4549 convert (tree_type, integer_zero_node));
4550 /* Make sure SAVE_EXPRs get referenced early enough. */
4551 expr_tree
4552 = ffecom_2 (COMPOUND_EXPR, tree_type,
4553 convert (void_type_node, arg1_tree),
4554 ffecom_2 (COMPOUND_EXPR, tree_type,
4555 convert (void_type_node, arg2_tree),
4556 expr_tree));
4557 }
4558 return expr_tree;
4559
4560 case FFEINTRIN_impISHFTC:
4561 {
4562 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4563 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4564 ffecom_expr (arg2)));
4565 tree arg3_tree = (arg3 == NULL) ? TYPE_SIZE (tree_type)
4566 : ffecom_save_tree (convert (integer_type_node, ffecom_expr (arg3)));
4567 tree shift_neg;
4568 tree shift_pos;
4569 tree mask_arg1;
4570 tree masked_arg1;
4571 tree uns_type
4572 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4573
4574 mask_arg1
4575 = ffecom_2 (LSHIFT_EXPR, tree_type,
4576 ffecom_1 (BIT_NOT_EXPR, tree_type,
4577 convert (tree_type, integer_zero_node)),
4578 arg3_tree);
4579 /* Fix up, because LSHIFT_EXPR above can't shift over TYPE_SIZE. */
4580 mask_arg1
4581 = ffecom_3 (COND_EXPR, tree_type,
4582 ffecom_truth_value
4583 (ffecom_2 (NE_EXPR, integer_type_node,
4584 arg3_tree,
4585 TYPE_SIZE (uns_type))),
4586 mask_arg1,
4587 convert (tree_type, integer_zero_node));
4588 mask_arg1 = ffecom_save_tree (mask_arg1);
4589 masked_arg1
4590 = ffecom_2 (BIT_AND_EXPR, tree_type,
4591 arg1_tree,
4592 ffecom_1 (BIT_NOT_EXPR, tree_type,
4593 mask_arg1));
4594 masked_arg1 = ffecom_save_tree (masked_arg1);
4595 shift_neg
4596 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4597 convert (tree_type,
4598 ffecom_2 (RSHIFT_EXPR, uns_type,
4599 convert (uns_type, masked_arg1),
4600 ffecom_1 (NEGATE_EXPR,
4601 integer_type_node,
4602 arg2_tree))),
4603 ffecom_2 (LSHIFT_EXPR, tree_type,
4604 arg1_tree,
4605 ffecom_2 (PLUS_EXPR, integer_type_node,
4606 arg2_tree,
4607 arg3_tree)));
4608 shift_pos
4609 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4610 ffecom_2 (LSHIFT_EXPR, tree_type,
4611 arg1_tree,
4612 arg2_tree),
4613 convert (tree_type,
4614 ffecom_2 (RSHIFT_EXPR, uns_type,
4615 convert (uns_type, masked_arg1),
4616 ffecom_2 (MINUS_EXPR,
4617 integer_type_node,
4618 arg3_tree,
4619 arg2_tree))));
4620 expr_tree
4621 = ffecom_3 (COND_EXPR, tree_type,
4622 ffecom_truth_value
4623 (ffecom_2 (LT_EXPR, integer_type_node,
4624 arg2_tree,
4625 integer_zero_node)),
4626 shift_neg,
4627 shift_pos);
4628 expr_tree
4629 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4630 ffecom_2 (BIT_AND_EXPR, tree_type,
4631 mask_arg1,
4632 arg1_tree),
4633 ffecom_2 (BIT_AND_EXPR, tree_type,
4634 ffecom_1 (BIT_NOT_EXPR, tree_type,
4635 mask_arg1),
4636 expr_tree));
4637 expr_tree
4638 = ffecom_3 (COND_EXPR, tree_type,
4639 ffecom_truth_value
4640 (ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
4641 ffecom_2 (EQ_EXPR, integer_type_node,
4642 ffecom_1 (ABS_EXPR,
4643 integer_type_node,
4644 arg2_tree),
4645 arg3_tree),
4646 ffecom_2 (EQ_EXPR, integer_type_node,
4647 arg2_tree,
4648 integer_zero_node))),
4649 arg1_tree,
4650 expr_tree);
4651 /* Make sure SAVE_EXPRs get referenced early enough. */
4652 expr_tree
4653 = ffecom_2 (COMPOUND_EXPR, tree_type,
4654 convert (void_type_node, arg1_tree),
4655 ffecom_2 (COMPOUND_EXPR, tree_type,
4656 convert (void_type_node, arg2_tree),
4657 ffecom_2 (COMPOUND_EXPR, tree_type,
4658 convert (void_type_node,
4659 mask_arg1),
4660 ffecom_2 (COMPOUND_EXPR, tree_type,
4661 convert (void_type_node,
4662 masked_arg1),
4663 expr_tree))));
4664 expr_tree
4665 = ffecom_2 (COMPOUND_EXPR, tree_type,
4666 convert (void_type_node,
4667 arg3_tree),
4668 expr_tree);
4669 }
4670 return expr_tree;
4671
4672 case FFEINTRIN_impLOC:
4673 {
4674 tree arg1_tree = ffecom_expr (arg1);
4675
4676 expr_tree
4677 = convert (tree_type,
4678 ffecom_1 (ADDR_EXPR,
4679 build_pointer_type (TREE_TYPE (arg1_tree)),
4680 arg1_tree));
4681 }
4682 return expr_tree;
4683
4684 case FFEINTRIN_impMVBITS:
4685 {
4686 tree arg1_tree;
4687 tree arg2_tree;
4688 tree arg3_tree;
4689 ffebld arg4 = ffebld_head (ffebld_trail (list));
4690 tree arg4_tree;
4691 tree arg4_type;
4692 ffebld arg5 = ffebld_head (ffebld_trail (ffebld_trail (list)));
4693 tree arg5_tree;
4694 tree prep_arg1;
4695 tree prep_arg4;
4696 tree arg5_plus_arg3;
4697
4698 arg2_tree = convert (integer_type_node,
4699 ffecom_expr (arg2));
4700 arg3_tree = ffecom_save_tree (convert (integer_type_node,
4701 ffecom_expr (arg3)));
4702 arg4_tree = ffecom_expr_rw (NULL_TREE, arg4);
4703 arg4_type = TREE_TYPE (arg4_tree);
4704
4705 arg1_tree = ffecom_save_tree (convert (arg4_type,
4706 ffecom_expr (arg1)));
4707
4708 arg5_tree = ffecom_save_tree (convert (integer_type_node,
4709 ffecom_expr (arg5)));
4710
4711 prep_arg1
4712 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4713 ffecom_2 (BIT_AND_EXPR, arg4_type,
4714 ffecom_2 (RSHIFT_EXPR, arg4_type,
4715 arg1_tree,
4716 arg2_tree),
4717 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4718 ffecom_2 (LSHIFT_EXPR, arg4_type,
4719 ffecom_1 (BIT_NOT_EXPR,
4720 arg4_type,
4721 convert
4722 (arg4_type,
4723 integer_zero_node)),
4724 arg3_tree))),
4725 arg5_tree);
4726 arg5_plus_arg3
4727 = ffecom_save_tree (ffecom_2 (PLUS_EXPR, arg4_type,
4728 arg5_tree,
4729 arg3_tree));
4730 prep_arg4
4731 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4732 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4733 convert (arg4_type,
4734 integer_zero_node)),
4735 arg5_plus_arg3);
4736 /* Fix up, because LSHIFT_EXPR above can't shift over TYPE_SIZE. */
4737 prep_arg4
4738 = ffecom_3 (COND_EXPR, arg4_type,
4739 ffecom_truth_value
4740 (ffecom_2 (NE_EXPR, integer_type_node,
4741 arg5_plus_arg3,
4742 convert (TREE_TYPE (arg5_plus_arg3),
4743 TYPE_SIZE (arg4_type)))),
4744 prep_arg4,
4745 convert (arg4_type, integer_zero_node));
4746 prep_arg4
4747 = ffecom_2 (BIT_AND_EXPR, arg4_type,
4748 arg4_tree,
4749 ffecom_2 (BIT_IOR_EXPR, arg4_type,
4750 prep_arg4,
4751 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4752 ffecom_2 (LSHIFT_EXPR, arg4_type,
4753 ffecom_1 (BIT_NOT_EXPR,
4754 arg4_type,
4755 convert
4756 (arg4_type,
4757 integer_zero_node)),
4758 arg5_tree))));
4759 prep_arg1
4760 = ffecom_2 (BIT_IOR_EXPR, arg4_type,
4761 prep_arg1,
4762 prep_arg4);
4763 /* Fix up (twice), because LSHIFT_EXPR above
4764 can't shift over TYPE_SIZE. */
4765 prep_arg1
4766 = ffecom_3 (COND_EXPR, arg4_type,
4767 ffecom_truth_value
4768 (ffecom_2 (NE_EXPR, integer_type_node,
4769 arg3_tree,
4770 convert (TREE_TYPE (arg3_tree),
4771 integer_zero_node))),
4772 prep_arg1,
4773 arg4_tree);
4774 prep_arg1
4775 = ffecom_3 (COND_EXPR, arg4_type,
4776 ffecom_truth_value
4777 (ffecom_2 (NE_EXPR, integer_type_node,
4778 arg3_tree,
4779 convert (TREE_TYPE (arg3_tree),
4780 TYPE_SIZE (arg4_type)))),
4781 prep_arg1,
4782 arg1_tree);
4783 expr_tree
4784 = ffecom_2s (MODIFY_EXPR, void_type_node,
4785 arg4_tree,
4786 prep_arg1);
4787 /* Make sure SAVE_EXPRs get referenced early enough. */
4788 expr_tree
4789 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4790 arg1_tree,
4791 ffecom_2 (COMPOUND_EXPR, void_type_node,
4792 arg3_tree,
4793 ffecom_2 (COMPOUND_EXPR, void_type_node,
4794 arg5_tree,
4795 ffecom_2 (COMPOUND_EXPR, void_type_node,
4796 arg5_plus_arg3,
4797 expr_tree))));
4798 expr_tree
4799 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4800 arg4_tree,
4801 expr_tree);
4802
4803 }
4804 return expr_tree;
4805
4806 case FFEINTRIN_impDERF:
4807 case FFEINTRIN_impERF:
4808 case FFEINTRIN_impDERFC:
4809 case FFEINTRIN_impERFC:
4810 break;
4811
4812 case FFEINTRIN_impIARGC:
4813 /* extern int xargc; i__1 = xargc - 1; */
4814 expr_tree = ffecom_2 (MINUS_EXPR, TREE_TYPE (ffecom_tree_xargc_),
4815 ffecom_tree_xargc_,
4816 convert (TREE_TYPE (ffecom_tree_xargc_),
4817 integer_one_node));
4818 return expr_tree;
4819
4820 case FFEINTRIN_impSIGNAL_func:
4821 case FFEINTRIN_impSIGNAL_subr:
4822 {
4823 tree arg1_tree;
4824 tree arg2_tree;
4825 tree arg3_tree;
4826
4827 arg1_tree = convert (ffecom_f2c_integer_type_node,
4828 ffecom_expr (arg1));
4829 arg1_tree = ffecom_1 (ADDR_EXPR,
4830 build_pointer_type (TREE_TYPE (arg1_tree)),
4831 arg1_tree);
4832
4833 /* Pass procedure as a pointer to it, anything else by value. */
4834 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4835 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4836 else
4837 arg2_tree = ffecom_ptr_to_expr (arg2);
4838 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4839 arg2_tree);
4840
4841 if (arg3 != NULL)
4842 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
4843 else
4844 arg3_tree = NULL_TREE;
4845
4846 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4847 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4848 TREE_CHAIN (arg1_tree) = arg2_tree;
4849
4850 expr_tree
4851 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4852 ffecom_gfrt_kindtype (gfrt),
4853 FALSE,
4854 ((codegen_imp == FFEINTRIN_impSIGNAL_subr) ?
4855 NULL_TREE :
4856 tree_type),
4857 arg1_tree,
4858 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4859 ffebld_nonter_hook (expr));
4860
4861 if (arg3_tree != NULL_TREE)
4862 expr_tree
4863 = ffecom_modify (NULL_TREE, arg3_tree,
4864 convert (TREE_TYPE (arg3_tree),
4865 expr_tree));
4866 }
4867 return expr_tree;
4868
4869 case FFEINTRIN_impALARM:
4870 {
4871 tree arg1_tree;
4872 tree arg2_tree;
4873 tree arg3_tree;
4874
4875 arg1_tree = convert (ffecom_f2c_integer_type_node,
4876 ffecom_expr (arg1));
4877 arg1_tree = ffecom_1 (ADDR_EXPR,
4878 build_pointer_type (TREE_TYPE (arg1_tree)),
4879 arg1_tree);
4880
4881 /* Pass procedure as a pointer to it, anything else by value. */
4882 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4883 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4884 else
4885 arg2_tree = ffecom_ptr_to_expr (arg2);
4886 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4887 arg2_tree);
4888
4889 if (arg3 != NULL)
4890 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
4891 else
4892 arg3_tree = NULL_TREE;
4893
4894 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4895 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4896 TREE_CHAIN (arg1_tree) = arg2_tree;
4897
4898 expr_tree
4899 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4900 ffecom_gfrt_kindtype (gfrt),
4901 FALSE,
4902 NULL_TREE,
4903 arg1_tree,
4904 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4905 ffebld_nonter_hook (expr));
4906
4907 if (arg3_tree != NULL_TREE)
4908 expr_tree
4909 = ffecom_modify (NULL_TREE, arg3_tree,
4910 convert (TREE_TYPE (arg3_tree),
4911 expr_tree));
4912 }
4913 return expr_tree;
4914
4915 case FFEINTRIN_impCHDIR_subr:
4916 case FFEINTRIN_impFDATE_subr:
4917 case FFEINTRIN_impFGET_subr:
4918 case FFEINTRIN_impFPUT_subr:
4919 case FFEINTRIN_impGETCWD_subr:
4920 case FFEINTRIN_impHOSTNM_subr:
4921 case FFEINTRIN_impSYSTEM_subr:
4922 case FFEINTRIN_impUNLINK_subr:
4923 {
4924 tree arg1_len = integer_zero_node;
4925 tree arg1_tree;
4926 tree arg2_tree;
4927
4928 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
4929
4930 if (arg2 != NULL)
4931 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
4932 else
4933 arg2_tree = NULL_TREE;
4934
4935 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4936 arg1_len = build_tree_list (NULL_TREE, arg1_len);
4937 TREE_CHAIN (arg1_tree) = arg1_len;
4938
4939 expr_tree
4940 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4941 ffecom_gfrt_kindtype (gfrt),
4942 FALSE,
4943 NULL_TREE,
4944 arg1_tree,
4945 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4946 ffebld_nonter_hook (expr));
4947
4948 if (arg2_tree != NULL_TREE)
4949 expr_tree
4950 = ffecom_modify (NULL_TREE, arg2_tree,
4951 convert (TREE_TYPE (arg2_tree),
4952 expr_tree));
4953 }
4954 return expr_tree;
4955
4956 case FFEINTRIN_impEXIT:
4957 if (arg1 != NULL)
4958 break;
4959
4960 expr_tree = build_tree_list (NULL_TREE,
4961 ffecom_1 (ADDR_EXPR,
4962 build_pointer_type
4963 (ffecom_integer_type_node),
4964 integer_zero_node));
4965
4966 return
4967 ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4968 ffecom_gfrt_kindtype (gfrt),
4969 FALSE,
4970 void_type_node,
4971 expr_tree,
4972 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4973 ffebld_nonter_hook (expr));
4974
4975 case FFEINTRIN_impFLUSH:
4976 if (arg1 == NULL)
4977 gfrt = FFECOM_gfrtFLUSH;
4978 else
4979 gfrt = FFECOM_gfrtFLUSH1;
4980 break;
4981
4982 case FFEINTRIN_impCHMOD_subr:
4983 case FFEINTRIN_impLINK_subr:
4984 case FFEINTRIN_impRENAME_subr:
4985 case FFEINTRIN_impSYMLNK_subr:
4986 {
4987 tree arg1_len = integer_zero_node;
4988 tree arg1_tree;
4989 tree arg2_len = integer_zero_node;
4990 tree arg2_tree;
4991 tree arg3_tree;
4992
4993 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
4994 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
4995 if (arg3 != NULL)
4996 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
4997 else
4998 arg3_tree = NULL_TREE;
4999
5000 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5001 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5002 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5003 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5004 TREE_CHAIN (arg1_tree) = arg2_tree;
5005 TREE_CHAIN (arg2_tree) = arg1_len;
5006 TREE_CHAIN (arg1_len) = arg2_len;
5007 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5008 ffecom_gfrt_kindtype (gfrt),
5009 FALSE,
5010 NULL_TREE,
5011 arg1_tree,
5012 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5013 ffebld_nonter_hook (expr));
5014 if (arg3_tree != NULL_TREE)
5015 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5016 convert (TREE_TYPE (arg3_tree),
5017 expr_tree));
5018 }
5019 return expr_tree;
5020
5021 case FFEINTRIN_impLSTAT_subr:
5022 case FFEINTRIN_impSTAT_subr:
5023 {
5024 tree arg1_len = integer_zero_node;
5025 tree arg1_tree;
5026 tree arg2_tree;
5027 tree arg3_tree;
5028
5029 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5030
5031 arg2_tree = ffecom_ptr_to_expr (arg2);
5032
5033 if (arg3 != NULL)
5034 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5035 else
5036 arg3_tree = NULL_TREE;
5037
5038 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5039 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5040 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5041 TREE_CHAIN (arg1_tree) = arg2_tree;
5042 TREE_CHAIN (arg2_tree) = arg1_len;
5043 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5044 ffecom_gfrt_kindtype (gfrt),
5045 FALSE,
5046 NULL_TREE,
5047 arg1_tree,
5048 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5049 ffebld_nonter_hook (expr));
5050 if (arg3_tree != NULL_TREE)
5051 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5052 convert (TREE_TYPE (arg3_tree),
5053 expr_tree));
5054 }
5055 return expr_tree;
5056
5057 case FFEINTRIN_impFGETC_subr:
5058 case FFEINTRIN_impFPUTC_subr:
5059 {
5060 tree arg1_tree;
5061 tree arg2_tree;
5062 tree arg2_len = integer_zero_node;
5063 tree arg3_tree;
5064
5065 arg1_tree = convert (ffecom_f2c_integer_type_node,
5066 ffecom_expr (arg1));
5067 arg1_tree = ffecom_1 (ADDR_EXPR,
5068 build_pointer_type (TREE_TYPE (arg1_tree)),
5069 arg1_tree);
5070
5071 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
5072 if (arg3 != NULL)
5073 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5074 else
5075 arg3_tree = NULL_TREE;
5076
5077 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5078 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5079 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5080 TREE_CHAIN (arg1_tree) = arg2_tree;
5081 TREE_CHAIN (arg2_tree) = arg2_len;
5082
5083 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5084 ffecom_gfrt_kindtype (gfrt),
5085 FALSE,
5086 NULL_TREE,
5087 arg1_tree,
5088 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5089 ffebld_nonter_hook (expr));
5090 if (arg3_tree != NULL_TREE)
5091 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5092 convert (TREE_TYPE (arg3_tree),
5093 expr_tree));
5094 }
5095 return expr_tree;
5096
5097 case FFEINTRIN_impFSTAT_subr:
5098 {
5099 tree arg1_tree;
5100 tree arg2_tree;
5101 tree arg3_tree;
5102
5103 arg1_tree = convert (ffecom_f2c_integer_type_node,
5104 ffecom_expr (arg1));
5105 arg1_tree = ffecom_1 (ADDR_EXPR,
5106 build_pointer_type (TREE_TYPE (arg1_tree)),
5107 arg1_tree);
5108
5109 arg2_tree = convert (ffecom_f2c_ptr_to_integer_type_node,
5110 ffecom_ptr_to_expr (arg2));
5111
5112 if (arg3 == NULL)
5113 arg3_tree = NULL_TREE;
5114 else
5115 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5116
5117 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5118 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5119 TREE_CHAIN (arg1_tree) = arg2_tree;
5120 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5121 ffecom_gfrt_kindtype (gfrt),
5122 FALSE,
5123 NULL_TREE,
5124 arg1_tree,
5125 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5126 ffebld_nonter_hook (expr));
5127 if (arg3_tree != NULL_TREE) {
5128 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5129 convert (TREE_TYPE (arg3_tree),
5130 expr_tree));
5131 }
5132 }
5133 return expr_tree;
5134
5135 case FFEINTRIN_impKILL_subr:
5136 {
5137 tree arg1_tree;
5138 tree arg2_tree;
5139 tree arg3_tree;
5140
5141 arg1_tree = convert (ffecom_f2c_integer_type_node,
5142 ffecom_expr (arg1));
5143 arg1_tree = ffecom_1 (ADDR_EXPR,
5144 build_pointer_type (TREE_TYPE (arg1_tree)),
5145 arg1_tree);
5146
5147 arg2_tree = convert (ffecom_f2c_integer_type_node,
5148 ffecom_expr (arg2));
5149 arg2_tree = ffecom_1 (ADDR_EXPR,
5150 build_pointer_type (TREE_TYPE (arg2_tree)),
5151 arg2_tree);
5152
5153 if (arg3 == NULL)
5154 arg3_tree = NULL_TREE;
5155 else
5156 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5157
5158 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5159 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5160 TREE_CHAIN (arg1_tree) = arg2_tree;
5161 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5162 ffecom_gfrt_kindtype (gfrt),
5163 FALSE,
5164 NULL_TREE,
5165 arg1_tree,
5166 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5167 ffebld_nonter_hook (expr));
5168 if (arg3_tree != NULL_TREE) {
5169 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5170 convert (TREE_TYPE (arg3_tree),
5171 expr_tree));
5172 }
5173 }
5174 return expr_tree;
5175
5176 case FFEINTRIN_impCTIME_subr:
5177 case FFEINTRIN_impTTYNAM_subr:
5178 {
5179 tree arg1_len = integer_zero_node;
5180 tree arg1_tree;
5181 tree arg2_tree;
5182
5183 arg1_tree = ffecom_arg_ptr_to_expr (arg2, &arg1_len);
5184
5185 arg2_tree = convert (((codegen_imp == FFEINTRIN_impCTIME_subr) ?
5186 ffecom_f2c_longint_type_node :
5187 ffecom_f2c_integer_type_node),
5188 ffecom_expr (arg1));
5189 arg2_tree = ffecom_1 (ADDR_EXPR,
5190 build_pointer_type (TREE_TYPE (arg2_tree)),
5191 arg2_tree);
5192
5193 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5194 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5195 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5196 TREE_CHAIN (arg1_len) = arg2_tree;
5197 TREE_CHAIN (arg1_tree) = arg1_len;
5198
5199 expr_tree
5200 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5201 ffecom_gfrt_kindtype (gfrt),
5202 FALSE,
5203 NULL_TREE,
5204 arg1_tree,
5205 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5206 ffebld_nonter_hook (expr));
5207 TREE_SIDE_EFFECTS (expr_tree) = 1;
5208 }
5209 return expr_tree;
5210
5211 case FFEINTRIN_impIRAND:
5212 case FFEINTRIN_impRAND:
5213 /* Arg defaults to 0 (normal random case) */
5214 {
5215 tree arg1_tree;
5216
5217 if (arg1 == NULL)
5218 arg1_tree = ffecom_integer_zero_node;
5219 else
5220 arg1_tree = ffecom_expr (arg1);
5221 arg1_tree = convert (ffecom_f2c_integer_type_node,
5222 arg1_tree);
5223 arg1_tree = ffecom_1 (ADDR_EXPR,
5224 build_pointer_type (TREE_TYPE (arg1_tree)),
5225 arg1_tree);
5226 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5227
5228 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5229 ffecom_gfrt_kindtype (gfrt),
5230 FALSE,
5231 ((codegen_imp == FFEINTRIN_impIRAND) ?
5232 ffecom_f2c_integer_type_node :
5233 ffecom_f2c_real_type_node),
5234 arg1_tree,
5235 dest_tree, dest, dest_used,
5236 NULL_TREE, TRUE,
5237 ffebld_nonter_hook (expr));
5238 }
5239 return expr_tree;
5240
5241 case FFEINTRIN_impFTELL_subr:
5242 case FFEINTRIN_impUMASK_subr:
5243 {
5244 tree arg1_tree;
5245 tree arg2_tree;
5246
5247 arg1_tree = convert (ffecom_f2c_integer_type_node,
5248 ffecom_expr (arg1));
5249 arg1_tree = ffecom_1 (ADDR_EXPR,
5250 build_pointer_type (TREE_TYPE (arg1_tree)),
5251 arg1_tree);
5252
5253 if (arg2 == NULL)
5254 arg2_tree = NULL_TREE;
5255 else
5256 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
5257
5258 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5259 ffecom_gfrt_kindtype (gfrt),
5260 FALSE,
5261 NULL_TREE,
5262 build_tree_list (NULL_TREE, arg1_tree),
5263 NULL_TREE, NULL, NULL, NULL_TREE,
5264 TRUE,
5265 ffebld_nonter_hook (expr));
5266 if (arg2_tree != NULL_TREE) {
5267 expr_tree = ffecom_modify (NULL_TREE, arg2_tree,
5268 convert (TREE_TYPE (arg2_tree),
5269 expr_tree));
5270 }
5271 }
5272 return expr_tree;
5273
5274 case FFEINTRIN_impCPU_TIME:
5275 case FFEINTRIN_impSECOND_subr:
5276 {
5277 tree arg1_tree;
5278
5279 arg1_tree = ffecom_expr_w (NULL_TREE, arg1);
5280
5281 expr_tree
5282 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5283 ffecom_gfrt_kindtype (gfrt),
5284 FALSE,
5285 NULL_TREE,
5286 NULL_TREE,
5287 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5288 ffebld_nonter_hook (expr));
5289
5290 expr_tree
5291 = ffecom_modify (NULL_TREE, arg1_tree,
5292 convert (TREE_TYPE (arg1_tree),
5293 expr_tree));
5294 }
5295 return expr_tree;
5296
5297 case FFEINTRIN_impDTIME_subr:
5298 case FFEINTRIN_impETIME_subr:
5299 {
5300 tree arg1_tree;
5301 tree result_tree;
5302
5303 result_tree = ffecom_expr_w (NULL_TREE, arg2);
5304
5305 arg1_tree = ffecom_ptr_to_expr (arg1);
5306
5307 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5308 ffecom_gfrt_kindtype (gfrt),
5309 FALSE,
5310 NULL_TREE,
5311 build_tree_list (NULL_TREE, arg1_tree),
5312 NULL_TREE, NULL, NULL, NULL_TREE,
5313 TRUE,
5314 ffebld_nonter_hook (expr));
5315 expr_tree = ffecom_modify (NULL_TREE, result_tree,
5316 convert (TREE_TYPE (result_tree),
5317 expr_tree));
5318 }
5319 return expr_tree;
5320
5321 /* Straightforward calls of libf2c routines: */
5322 case FFEINTRIN_impABORT:
5323 case FFEINTRIN_impACCESS:
5324 case FFEINTRIN_impBESJ0:
5325 case FFEINTRIN_impBESJ1:
5326 case FFEINTRIN_impBESJN:
5327 case FFEINTRIN_impBESY0:
5328 case FFEINTRIN_impBESY1:
5329 case FFEINTRIN_impBESYN:
5330 case FFEINTRIN_impCHDIR_func:
5331 case FFEINTRIN_impCHMOD_func:
5332 case FFEINTRIN_impDATE:
5333 case FFEINTRIN_impDATE_AND_TIME:
5334 case FFEINTRIN_impDBESJ0:
5335 case FFEINTRIN_impDBESJ1:
5336 case FFEINTRIN_impDBESJN:
5337 case FFEINTRIN_impDBESY0:
5338 case FFEINTRIN_impDBESY1:
5339 case FFEINTRIN_impDBESYN:
5340 case FFEINTRIN_impDTIME_func:
5341 case FFEINTRIN_impETIME_func:
5342 case FFEINTRIN_impFGETC_func:
5343 case FFEINTRIN_impFGET_func:
5344 case FFEINTRIN_impFNUM:
5345 case FFEINTRIN_impFPUTC_func:
5346 case FFEINTRIN_impFPUT_func:
5347 case FFEINTRIN_impFSEEK:
5348 case FFEINTRIN_impFSTAT_func:
5349 case FFEINTRIN_impFTELL_func:
5350 case FFEINTRIN_impGERROR:
5351 case FFEINTRIN_impGETARG:
5352 case FFEINTRIN_impGETCWD_func:
5353 case FFEINTRIN_impGETENV:
5354 case FFEINTRIN_impGETGID:
5355 case FFEINTRIN_impGETLOG:
5356 case FFEINTRIN_impGETPID:
5357 case FFEINTRIN_impGETUID:
5358 case FFEINTRIN_impGMTIME:
5359 case FFEINTRIN_impHOSTNM_func:
5360 case FFEINTRIN_impIDATE_unix:
5361 case FFEINTRIN_impIDATE_vxt:
5362 case FFEINTRIN_impIERRNO:
5363 case FFEINTRIN_impISATTY:
5364 case FFEINTRIN_impITIME:
5365 case FFEINTRIN_impKILL_func:
5366 case FFEINTRIN_impLINK_func:
5367 case FFEINTRIN_impLNBLNK:
5368 case FFEINTRIN_impLSTAT_func:
5369 case FFEINTRIN_impLTIME:
5370 case FFEINTRIN_impMCLOCK8:
5371 case FFEINTRIN_impMCLOCK:
5372 case FFEINTRIN_impPERROR:
5373 case FFEINTRIN_impRENAME_func:
5374 case FFEINTRIN_impSECNDS:
5375 case FFEINTRIN_impSECOND_func:
5376 case FFEINTRIN_impSLEEP:
5377 case FFEINTRIN_impSRAND:
5378 case FFEINTRIN_impSTAT_func:
5379 case FFEINTRIN_impSYMLNK_func:
5380 case FFEINTRIN_impSYSTEM_CLOCK:
5381 case FFEINTRIN_impSYSTEM_func:
5382 case FFEINTRIN_impTIME8:
5383 case FFEINTRIN_impTIME_unix:
5384 case FFEINTRIN_impTIME_vxt:
5385 case FFEINTRIN_impUMASK_func:
5386 case FFEINTRIN_impUNLINK_func:
5387 break;
5388
5389 case FFEINTRIN_impCTIME_func: /* CHARACTER functions not handled here. */
5390 case FFEINTRIN_impFDATE_func: /* CHARACTER functions not handled here. */
5391 case FFEINTRIN_impTTYNAM_func: /* CHARACTER functions not handled here. */
5392 case FFEINTRIN_impNONE:
5393 case FFEINTRIN_imp: /* Hush up gcc warning. */
5394 fprintf (stderr, "No %s implementation.\n",
5395 ffeintrin_name_implementation (ffebld_symter_implementation (ffebld_left (expr))));
5396 assert ("unimplemented intrinsic" == NULL);
5397 return error_mark_node;
5398 }
5399
5400 assert (gfrt != FFECOM_gfrt); /* Must have an implementation! */
5401
5402 expr_tree = ffecom_arglist_expr_ (ffecom_gfrt_args_ (gfrt),
5403 ffebld_right (expr));
5404
5405 return ffecom_call_ (ffecom_gfrt_tree_ (gfrt), ffecom_gfrt_kindtype (gfrt),
5406 (ffe_is_f2c_library () && ffecom_gfrt_complex_[gfrt]),
5407 tree_type,
5408 expr_tree, dest_tree, dest, dest_used,
5409 NULL_TREE, TRUE,
5410 ffebld_nonter_hook (expr));
5411
5412 /* See bottom of this file for f2c transforms used to determine
5413 many of the above implementations. The info seems to confuse
5414 Emacs's C mode indentation, which is why it's been moved to
5415 the bottom of this source file. */
5416 }
5417
5418 /* For power (exponentiation) where right-hand operand is type INTEGER,
5419 generate in-line code to do it the fast way (which, if the operand
5420 is a constant, might just mean a series of multiplies). */
5421
5422 static tree
5423 ffecom_expr_power_integer_ (ffebld expr)
5424 {
5425 tree l = ffecom_expr (ffebld_left (expr));
5426 tree r = ffecom_expr (ffebld_right (expr));
5427 tree ltype = TREE_TYPE (l);
5428 tree rtype = TREE_TYPE (r);
5429 tree result = NULL_TREE;
5430
5431 if (l == error_mark_node
5432 || r == error_mark_node)
5433 return error_mark_node;
5434
5435 if (TREE_CODE (r) == INTEGER_CST)
5436 {
5437 int sgn = tree_int_cst_sgn (r);
5438
5439 if (sgn == 0)
5440 return convert (ltype, integer_one_node);
5441
5442 if ((TREE_CODE (ltype) == INTEGER_TYPE)
5443 && (sgn < 0))
5444 {
5445 /* Reciprocal of integer is either 0, -1, or 1, so after
5446 calculating that (which we leave to the back end to do
5447 or not do optimally), don't bother with any multiplying. */
5448
5449 result = ffecom_tree_divide_ (ltype,
5450 convert (ltype, integer_one_node),
5451 l,
5452 NULL_TREE, NULL, NULL, NULL_TREE);
5453 r = ffecom_1 (NEGATE_EXPR,
5454 rtype,
5455 r);
5456 if ((TREE_INT_CST_LOW (r) & 1) == 0)
5457 result = ffecom_1 (ABS_EXPR, rtype,
5458 result);
5459 }
5460
5461 /* Generate appropriate series of multiplies, preceded
5462 by divide if the exponent is negative. */
5463
5464 l = save_expr (l);
5465
5466 if (sgn < 0)
5467 {
5468 l = ffecom_tree_divide_ (ltype,
5469 convert (ltype, integer_one_node),
5470 l,
5471 NULL_TREE, NULL, NULL,
5472 ffebld_nonter_hook (expr));
5473 r = ffecom_1 (NEGATE_EXPR, rtype, r);
5474 assert (TREE_CODE (r) == INTEGER_CST);
5475
5476 if (tree_int_cst_sgn (r) < 0)
5477 { /* The "most negative" number. */
5478 r = ffecom_1 (NEGATE_EXPR, rtype,
5479 ffecom_2 (RSHIFT_EXPR, rtype,
5480 r,
5481 integer_one_node));
5482 l = save_expr (l);
5483 l = ffecom_2 (MULT_EXPR, ltype,
5484 l,
5485 l);
5486 }
5487 }
5488
5489 for (;;)
5490 {
5491 if (TREE_INT_CST_LOW (r) & 1)
5492 {
5493 if (result == NULL_TREE)
5494 result = l;
5495 else
5496 result = ffecom_2 (MULT_EXPR, ltype,
5497 result,
5498 l);
5499 }
5500
5501 r = ffecom_2 (RSHIFT_EXPR, rtype,
5502 r,
5503 integer_one_node);
5504 if (integer_zerop (r))
5505 break;
5506 assert (TREE_CODE (r) == INTEGER_CST);
5507
5508 l = save_expr (l);
5509 l = ffecom_2 (MULT_EXPR, ltype,
5510 l,
5511 l);
5512 }
5513 return result;
5514 }
5515
5516 /* Though rhs isn't a constant, in-line code cannot be expanded
5517 while transforming dummies
5518 because the back end cannot be easily convinced to generate
5519 stores (MODIFY_EXPR), handle temporaries, and so on before
5520 all the appropriate rtx's have been generated for things like
5521 dummy args referenced in rhs -- which doesn't happen until
5522 store_parm_decls() is called (expand_function_start, I believe,
5523 does the actual rtx-stuffing of PARM_DECLs).
5524
5525 So, in this case, let the caller generate the call to the
5526 run-time-library function to evaluate the power for us. */
5527
5528 if (ffecom_transform_only_dummies_)
5529 return NULL_TREE;
5530
5531 /* Right-hand operand not a constant, expand in-line code to figure
5532 out how to do the multiplies, &c.
5533
5534 The returned expression is expressed this way in GNU C, where l and
5535 r are the "inputs":
5536
5537 ({ typeof (r) rtmp = r;
5538 typeof (l) ltmp = l;
5539 typeof (l) result;
5540
5541 if (rtmp == 0)
5542 result = 1;
5543 else
5544 {
5545 if ((basetypeof (l) == basetypeof (int))
5546 && (rtmp < 0))
5547 {
5548 result = ((typeof (l)) 1) / ltmp;
5549 if ((ltmp < 0) && (((-rtmp) & 1) == 0))
5550 result = -result;
5551 }
5552 else
5553 {
5554 result = 1;
5555 if ((basetypeof (l) != basetypeof (int))
5556 && (rtmp < 0))
5557 {
5558 ltmp = ((typeof (l)) 1) / ltmp;
5559 rtmp = -rtmp;
5560 if (rtmp < 0)
5561 {
5562 rtmp = -(rtmp >> 1);
5563 ltmp *= ltmp;
5564 }
5565 }
5566 for (;;)
5567 {
5568 if (rtmp & 1)
5569 result *= ltmp;
5570 if ((rtmp >>= 1) == 0)
5571 break;
5572 ltmp *= ltmp;
5573 }
5574 }
5575 }
5576 result;
5577 })
5578
5579 Note that some of the above is compile-time collapsable, such as
5580 the first part of the if statements that checks the base type of
5581 l against int. The if statements are phrased that way to suggest
5582 an easy way to generate the if/else constructs here, knowing that
5583 the back end should (and probably does) eliminate the resulting
5584 dead code (either the int case or the non-int case), something
5585 it couldn't do without the redundant phrasing, requiring explicit
5586 dead-code elimination here, which would be kind of difficult to
5587 read. */
5588
5589 {
5590 tree rtmp;
5591 tree ltmp;
5592 tree divide;
5593 tree basetypeof_l_is_int;
5594 tree se;
5595 tree t;
5596
5597 basetypeof_l_is_int
5598 = build_int_2 ((TREE_CODE (ltype) == INTEGER_TYPE), 0);
5599
5600 se = expand_start_stmt_expr (/*has_scope=*/1);
5601
5602 ffecom_start_compstmt ();
5603
5604 rtmp = ffecom_make_tempvar ("power_r", rtype,
5605 FFETARGET_charactersizeNONE, -1);
5606 ltmp = ffecom_make_tempvar ("power_l", ltype,
5607 FFETARGET_charactersizeNONE, -1);
5608 result = ffecom_make_tempvar ("power_res", ltype,
5609 FFETARGET_charactersizeNONE, -1);
5610 if (TREE_CODE (ltype) == COMPLEX_TYPE
5611 || TREE_CODE (ltype) == RECORD_TYPE)
5612 divide = ffecom_make_tempvar ("power_div", ltype,
5613 FFETARGET_charactersizeNONE, -1);
5614 else
5615 divide = NULL_TREE;
5616
5617 expand_expr_stmt (ffecom_modify (void_type_node,
5618 rtmp,
5619 r));
5620 expand_expr_stmt (ffecom_modify (void_type_node,
5621 ltmp,
5622 l));
5623 expand_start_cond (ffecom_truth_value
5624 (ffecom_2 (EQ_EXPR, integer_type_node,
5625 rtmp,
5626 convert (rtype, integer_zero_node))),
5627 0);
5628 expand_expr_stmt (ffecom_modify (void_type_node,
5629 result,
5630 convert (ltype, integer_one_node)));
5631 expand_start_else ();
5632 if (! integer_zerop (basetypeof_l_is_int))
5633 {
5634 expand_start_cond (ffecom_2 (LT_EXPR, integer_type_node,
5635 rtmp,
5636 convert (rtype,
5637 integer_zero_node)),
5638 0);
5639 expand_expr_stmt (ffecom_modify (void_type_node,
5640 result,
5641 ffecom_tree_divide_
5642 (ltype,
5643 convert (ltype, integer_one_node),
5644 ltmp,
5645 NULL_TREE, NULL, NULL,
5646 divide)));
5647 expand_start_cond (ffecom_truth_value
5648 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5649 ffecom_2 (LT_EXPR, integer_type_node,
5650 ltmp,
5651 convert (ltype,
5652 integer_zero_node)),
5653 ffecom_2 (EQ_EXPR, integer_type_node,
5654 ffecom_2 (BIT_AND_EXPR,
5655 rtype,
5656 ffecom_1 (NEGATE_EXPR,
5657 rtype,
5658 rtmp),
5659 convert (rtype,
5660 integer_one_node)),
5661 convert (rtype,
5662 integer_zero_node)))),
5663 0);
5664 expand_expr_stmt (ffecom_modify (void_type_node,
5665 result,
5666 ffecom_1 (NEGATE_EXPR,
5667 ltype,
5668 result)));
5669 expand_end_cond ();
5670 expand_start_else ();
5671 }
5672 expand_expr_stmt (ffecom_modify (void_type_node,
5673 result,
5674 convert (ltype, integer_one_node)));
5675 expand_start_cond (ffecom_truth_value
5676 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5677 ffecom_truth_value_invert
5678 (basetypeof_l_is_int),
5679 ffecom_2 (LT_EXPR, integer_type_node,
5680 rtmp,
5681 convert (rtype,
5682 integer_zero_node)))),
5683 0);
5684 expand_expr_stmt (ffecom_modify (void_type_node,
5685 ltmp,
5686 ffecom_tree_divide_
5687 (ltype,
5688 convert (ltype, integer_one_node),
5689 ltmp,
5690 NULL_TREE, NULL, NULL,
5691 divide)));
5692 expand_expr_stmt (ffecom_modify (void_type_node,
5693 rtmp,
5694 ffecom_1 (NEGATE_EXPR, rtype,
5695 rtmp)));
5696 expand_start_cond (ffecom_truth_value
5697 (ffecom_2 (LT_EXPR, integer_type_node,
5698 rtmp,
5699 convert (rtype, integer_zero_node))),
5700 0);
5701 expand_expr_stmt (ffecom_modify (void_type_node,
5702 rtmp,
5703 ffecom_1 (NEGATE_EXPR, rtype,
5704 ffecom_2 (RSHIFT_EXPR,
5705 rtype,
5706 rtmp,
5707 integer_one_node))));
5708 expand_expr_stmt (ffecom_modify (void_type_node,
5709 ltmp,
5710 ffecom_2 (MULT_EXPR, ltype,
5711 ltmp,
5712 ltmp)));
5713 expand_end_cond ();
5714 expand_end_cond ();
5715 expand_start_loop (1);
5716 expand_start_cond (ffecom_truth_value
5717 (ffecom_2 (BIT_AND_EXPR, rtype,
5718 rtmp,
5719 convert (rtype, integer_one_node))),
5720 0);
5721 expand_expr_stmt (ffecom_modify (void_type_node,
5722 result,
5723 ffecom_2 (MULT_EXPR, ltype,
5724 result,
5725 ltmp)));
5726 expand_end_cond ();
5727 expand_exit_loop_if_false (NULL,
5728 ffecom_truth_value
5729 (ffecom_modify (rtype,
5730 rtmp,
5731 ffecom_2 (RSHIFT_EXPR,
5732 rtype,
5733 rtmp,
5734 integer_one_node))));
5735 expand_expr_stmt (ffecom_modify (void_type_node,
5736 ltmp,
5737 ffecom_2 (MULT_EXPR, ltype,
5738 ltmp,
5739 ltmp)));
5740 expand_end_loop ();
5741 expand_end_cond ();
5742 if (!integer_zerop (basetypeof_l_is_int))
5743 expand_end_cond ();
5744 expand_expr_stmt (result);
5745
5746 t = ffecom_end_compstmt ();
5747
5748 result = expand_end_stmt_expr (se);
5749
5750 /* This code comes from c-parse.in, after its expand_end_stmt_expr. */
5751
5752 if (TREE_CODE (t) == BLOCK)
5753 {
5754 /* Make a BIND_EXPR for the BLOCK already made. */
5755 result = build (BIND_EXPR, TREE_TYPE (result),
5756 NULL_TREE, result, t);
5757 /* Remove the block from the tree at this point.
5758 It gets put back at the proper place
5759 when the BIND_EXPR is expanded. */
5760 delete_block (t);
5761 }
5762 else
5763 result = t;
5764 }
5765
5766 return result;
5767 }
5768
5769 /* ffecom_expr_transform_ -- Transform symbols in expr
5770
5771 ffebld expr; // FFE expression.
5772 ffecom_expr_transform_ (expr);
5773
5774 Recursive descent on expr while transforming any untransformed SYMTERs. */
5775
5776 static void
5777 ffecom_expr_transform_ (ffebld expr)
5778 {
5779 tree t;
5780 ffesymbol s;
5781
5782 tail_recurse:
5783
5784 if (expr == NULL)
5785 return;
5786
5787 switch (ffebld_op (expr))
5788 {
5789 case FFEBLD_opSYMTER:
5790 s = ffebld_symter (expr);
5791 t = ffesymbol_hook (s).decl_tree;
5792 if ((t == NULL_TREE)
5793 && ((ffesymbol_kind (s) != FFEINFO_kindNONE)
5794 || ((ffesymbol_where (s) != FFEINFO_whereNONE)
5795 && (ffesymbol_where (s) != FFEINFO_whereINTRINSIC))))
5796 {
5797 s = ffecom_sym_transform_ (s);
5798 t = ffesymbol_hook (s).decl_tree; /* Sfunc expr non-dummy,
5799 DIMENSION expr? */
5800 }
5801 break; /* Ok if (t == NULL) here. */
5802
5803 case FFEBLD_opITEM:
5804 ffecom_expr_transform_ (ffebld_head (expr));
5805 expr = ffebld_trail (expr);
5806 goto tail_recurse; /* :::::::::::::::::::: */
5807
5808 default:
5809 break;
5810 }
5811
5812 switch (ffebld_arity (expr))
5813 {
5814 case 2:
5815 ffecom_expr_transform_ (ffebld_left (expr));
5816 expr = ffebld_right (expr);
5817 goto tail_recurse; /* :::::::::::::::::::: */
5818
5819 case 1:
5820 expr = ffebld_left (expr);
5821 goto tail_recurse; /* :::::::::::::::::::: */
5822
5823 default:
5824 break;
5825 }
5826
5827 return;
5828 }
5829
5830 /* Make a type based on info in live f2c.h file. */
5831
5832 static void
5833 ffecom_f2c_make_type_ (tree *type, int tcode, const char *name)
5834 {
5835 switch (tcode)
5836 {
5837 case FFECOM_f2ccodeCHAR:
5838 *type = make_signed_type (CHAR_TYPE_SIZE);
5839 break;
5840
5841 case FFECOM_f2ccodeSHORT:
5842 *type = make_signed_type (SHORT_TYPE_SIZE);
5843 break;
5844
5845 case FFECOM_f2ccodeINT:
5846 *type = make_signed_type (INT_TYPE_SIZE);
5847 break;
5848
5849 case FFECOM_f2ccodeLONG:
5850 *type = make_signed_type (LONG_TYPE_SIZE);
5851 break;
5852
5853 case FFECOM_f2ccodeLONGLONG:
5854 *type = make_signed_type (LONG_LONG_TYPE_SIZE);
5855 break;
5856
5857 case FFECOM_f2ccodeCHARPTR:
5858 *type = build_pointer_type (DEFAULT_SIGNED_CHAR
5859 ? signed_char_type_node
5860 : unsigned_char_type_node);
5861 break;
5862
5863 case FFECOM_f2ccodeFLOAT:
5864 *type = make_node (REAL_TYPE);
5865 TYPE_PRECISION (*type) = FLOAT_TYPE_SIZE;
5866 layout_type (*type);
5867 break;
5868
5869 case FFECOM_f2ccodeDOUBLE:
5870 *type = make_node (REAL_TYPE);
5871 TYPE_PRECISION (*type) = DOUBLE_TYPE_SIZE;
5872 layout_type (*type);
5873 break;
5874
5875 case FFECOM_f2ccodeLONGDOUBLE:
5876 *type = make_node (REAL_TYPE);
5877 TYPE_PRECISION (*type) = LONG_DOUBLE_TYPE_SIZE;
5878 layout_type (*type);
5879 break;
5880
5881 case FFECOM_f2ccodeTWOREALS:
5882 *type = ffecom_make_complex_type_ (ffecom_f2c_real_type_node);
5883 break;
5884
5885 case FFECOM_f2ccodeTWODOUBLEREALS:
5886 *type = ffecom_make_complex_type_ (ffecom_f2c_doublereal_type_node);
5887 break;
5888
5889 default:
5890 assert ("unexpected FFECOM_f2ccodeXYZZY!" == NULL);
5891 *type = error_mark_node;
5892 return;
5893 }
5894
5895 pushdecl (build_decl (TYPE_DECL,
5896 ffecom_get_invented_identifier ("__g77_f2c_%s", name),
5897 *type));
5898 }
5899
5900 /* Set the f2c list-directed-I/O code for whatever (integral) type has the
5901 given size. */
5902
5903 static void
5904 ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
5905 int code)
5906 {
5907 int j;
5908 tree t;
5909
5910 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
5911 if ((t = ffecom_tree_type[bt][j]) != NULL_TREE
5912 && compare_tree_int (TYPE_SIZE (t), size) == 0)
5913 {
5914 assert (code != -1);
5915 ffecom_f2c_typecode_[bt][j] = code;
5916 code = -1;
5917 }
5918 }
5919
5920 /* Finish up globals after doing all program units in file
5921
5922 Need to handle only uninitialized COMMON areas. */
5923
5924 static ffeglobal
5925 ffecom_finish_global_ (ffeglobal global)
5926 {
5927 tree cbtype;
5928 tree cbt;
5929 tree size;
5930
5931 if (ffeglobal_type (global) != FFEGLOBAL_typeCOMMON)
5932 return global;
5933
5934 if (ffeglobal_common_init (global))
5935 return global;
5936
5937 cbt = ffeglobal_hook (global);
5938 if ((cbt == NULL_TREE)
5939 || !ffeglobal_common_have_size (global))
5940 return global; /* No need to make common, never ref'd. */
5941
5942 DECL_EXTERNAL (cbt) = 0;
5943
5944 /* Give the array a size now. */
5945
5946 size = build_int_2 ((ffeglobal_common_size (global)
5947 + ffeglobal_common_pad (global)) - 1,
5948 0);
5949
5950 cbtype = TREE_TYPE (cbt);
5951 TYPE_DOMAIN (cbtype) = build_range_type (integer_type_node,
5952 integer_zero_node,
5953 size);
5954 if (!TREE_TYPE (size))
5955 TREE_TYPE (size) = TYPE_DOMAIN (cbtype);
5956 layout_type (cbtype);
5957
5958 cbt = start_decl (cbt, FALSE);
5959 assert (cbt == ffeglobal_hook (global));
5960
5961 finish_decl (cbt, NULL_TREE, FALSE);
5962
5963 return global;
5964 }
5965
5966 /* Finish up any untransformed symbols. */
5967
5968 static ffesymbol
5969 ffecom_finish_symbol_transform_ (ffesymbol s)
5970 {
5971 if ((s == NULL) || (TREE_CODE (current_function_decl) == ERROR_MARK))
5972 return s;
5973
5974 /* It's easy to know to transform an untransformed symbol, to make sure
5975 we put out debugging info for it. But COMMON variables, unlike
5976 EQUIVALENCE ones, aren't given declarations in addition to the
5977 tree expressions that specify offsets, because COMMON variables
5978 can be referenced in the outer scope where only dummy arguments
5979 (PARM_DECLs) should really be seen. To be safe, just don't do any
5980 VAR_DECLs for COMMON variables when we transform them for real
5981 use, and therefore we do all the VAR_DECL creating here. */
5982
5983 if (ffesymbol_hook (s).decl_tree == NULL_TREE)
5984 {
5985 if (ffesymbol_kind (s) != FFEINFO_kindNONE
5986 || (ffesymbol_where (s) != FFEINFO_whereNONE
5987 && ffesymbol_where (s) != FFEINFO_whereINTRINSIC
5988 && ffesymbol_where (s) != FFEINFO_whereDUMMY))
5989 /* Not transformed, and not CHARACTER*(*), and not a dummy
5990 argument, which can happen only if the entry point names
5991 it "rides in on" are all invalidated for other reasons. */
5992 s = ffecom_sym_transform_ (s);
5993 }
5994
5995 if ((ffesymbol_where (s) == FFEINFO_whereCOMMON)
5996 && (ffesymbol_hook (s).decl_tree != error_mark_node))
5997 {
5998 /* This isn't working, at least for dbxout. The .s file looks
5999 okay to me (burley), but in gdb 4.9 at least, the variables
6000 appear to reside somewhere outside of the common area, so
6001 it doesn't make sense to mislead anyone by generating the info
6002 on those variables until this is fixed. NOTE: Same problem
6003 with EQUIVALENCE, sadly...see similar #if later. */
6004 ffecom_member_phase2_ (ffesymbol_storage (ffesymbol_common (s)),
6005 ffesymbol_storage (s));
6006 }
6007
6008 return s;
6009 }
6010
6011 /* Append underscore(s) to name before calling get_identifier. "us"
6012 is nonzero if the name already contains an underscore and thus
6013 needs two underscores appended. */
6014
6015 static tree
6016 ffecom_get_appended_identifier_ (char us, const char *name)
6017 {
6018 int i;
6019 char *newname;
6020 tree id;
6021
6022 newname = xmalloc ((i = strlen (name)) + 1
6023 + ffe_is_underscoring ()
6024 + us);
6025 memcpy (newname, name, i);
6026 newname[i] = '_';
6027 newname[i + us] = '_';
6028 newname[i + 1 + us] = '\0';
6029 id = get_identifier (newname);
6030
6031 free (newname);
6032
6033 return id;
6034 }
6035
6036 /* Decide whether to append underscore to name before calling
6037 get_identifier. */
6038
6039 static tree
6040 ffecom_get_external_identifier_ (ffesymbol s)
6041 {
6042 char us;
6043 const char *name = ffesymbol_text (s);
6044
6045 /* If name is a built-in name, just return it as is. */
6046
6047 if (!ffe_is_underscoring ()
6048 || (strcmp (name, FFETARGET_nameBLANK_COMMON) == 0)
6049 || (strcmp (name, FFETARGET_nameUNNAMED_MAIN) == 0)
6050 || (strcmp (name, FFETARGET_nameUNNAMED_BLOCK_DATA) == 0))
6051 return get_identifier (name);
6052
6053 us = ffe_is_second_underscore ()
6054 ? (strchr (name, '_') != NULL)
6055 : 0;
6056
6057 return ffecom_get_appended_identifier_ (us, name);
6058 }
6059
6060 /* Decide whether to append underscore to internal name before calling
6061 get_identifier.
6062
6063 This is for non-external, top-function-context names only. Transform
6064 identifier so it doesn't conflict with the transformed result
6065 of using a _different_ external name. E.g. if "CALL FOO" is
6066 transformed into "FOO_();", then the variable in "FOO_ = 3"
6067 must be transformed into something that does not conflict, since
6068 these two things should be independent.
6069
6070 The transformation is as follows. If the name does not contain
6071 an underscore, there is no possible conflict, so just return.
6072 If the name does contain an underscore, then transform it just
6073 like we transform an external identifier. */
6074
6075 static tree
6076 ffecom_get_identifier_ (const char *name)
6077 {
6078 /* If name does not contain an underscore, just return it as is. */
6079
6080 if (!ffe_is_underscoring ()
6081 || (strchr (name, '_') == NULL))
6082 return get_identifier (name);
6083
6084 return ffecom_get_appended_identifier_ (ffe_is_second_underscore (),
6085 name);
6086 }
6087
6088 /* ffecom_gen_sfuncdef_ -- Generate definition of statement function
6089
6090 tree t;
6091 ffesymbol s; // kindFUNCTION, whereIMMEDIATE.
6092 t = ffecom_gen_sfuncdef_(s,ffesymbol_basictype(s),
6093 ffesymbol_kindtype(s));
6094
6095 Call after setting up containing function and getting trees for all
6096 other symbols. */
6097
6098 static tree
6099 ffecom_gen_sfuncdef_ (ffesymbol s, ffeinfoBasictype bt, ffeinfoKindtype kt)
6100 {
6101 ffebld expr = ffesymbol_sfexpr (s);
6102 tree type;
6103 tree func;
6104 tree result;
6105 bool charfunc = (bt == FFEINFO_basictypeCHARACTER);
6106 static bool recurse = FALSE;
6107 location_t old_loc = input_location;
6108
6109 ffecom_nested_entry_ = s;
6110
6111 /* For now, we don't have a handy pointer to where the sfunc is actually
6112 defined, though that should be easy to add to an ffesymbol. (The
6113 token/where info available might well point to the place where the type
6114 of the sfunc is declared, especially if that precedes the place where
6115 the sfunc itself is defined, which is typically the case.) We should
6116 put out a null pointer rather than point somewhere wrong, but I want to
6117 see how it works at this point. */
6118
6119 input_filename = ffesymbol_where_filename (s);
6120 input_line = ffesymbol_where_filelinenum (s);
6121
6122 /* Pretransform the expression so any newly discovered things belong to the
6123 outer program unit, not to the statement function. */
6124
6125 ffecom_expr_transform_ (expr);
6126
6127 /* Make sure no recursive invocation of this fn (a specific case of failing
6128 to pretransform an sfunc's expression, i.e. where its expression
6129 references another untransformed sfunc) happens. */
6130
6131 assert (!recurse);
6132 recurse = TRUE;
6133
6134 push_f_function_context ();
6135
6136 if (charfunc)
6137 type = void_type_node;
6138 else
6139 {
6140 type = ffecom_tree_type[bt][kt];
6141 if (type == NULL_TREE)
6142 type = integer_type_node; /* _sym_exec_transition reports
6143 error. */
6144 }
6145
6146 start_function (ffecom_get_identifier_ (ffesymbol_text (s)),
6147 build_function_type (type, NULL_TREE),
6148 1, /* nested/inline */
6149 0); /* TREE_PUBLIC */
6150
6151 /* We don't worry about COMPLEX return values here, because this is
6152 entirely internal to our code, and gcc has the ability to return COMPLEX
6153 directly as a value. */
6154
6155 if (charfunc)
6156 { /* Prepend arg for where result goes. */
6157 tree type;
6158
6159 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
6160
6161 result = ffecom_get_invented_identifier ("__g77_%s", "result");
6162
6163 ffecom_char_enhance_arg_ (&type, s); /* Ignore returned length. */
6164
6165 type = build_pointer_type (type);
6166 result = build_decl (PARM_DECL, result, type);
6167
6168 push_parm_decl (result);
6169 }
6170 else
6171 result = NULL_TREE; /* Not ref'd if !charfunc. */
6172
6173 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (s), TRUE);
6174
6175 store_parm_decls (0);
6176
6177 ffecom_start_compstmt ();
6178
6179 if (expr != NULL)
6180 {
6181 if (charfunc)
6182 {
6183 ffetargetCharacterSize sz = ffesymbol_size (s);
6184 tree result_length;
6185
6186 result_length = build_int_2 (sz, 0);
6187 TREE_TYPE (result_length) = ffecom_f2c_ftnlen_type_node;
6188
6189 ffecom_prepare_let_char_ (sz, expr);
6190
6191 ffecom_prepare_end ();
6192
6193 ffecom_let_char_ (result, result_length, sz, expr);
6194 expand_null_return ();
6195 }
6196 else
6197 {
6198 ffecom_prepare_expr (expr);
6199
6200 ffecom_prepare_end ();
6201
6202 expand_return (ffecom_modify (NULL_TREE,
6203 DECL_RESULT (current_function_decl),
6204 ffecom_expr (expr)));
6205 }
6206 }
6207
6208 ffecom_end_compstmt ();
6209
6210 func = current_function_decl;
6211 finish_function (1);
6212
6213 pop_f_function_context ();
6214
6215 recurse = FALSE;
6216
6217 input_location = old_loc;
6218
6219 ffecom_nested_entry_ = NULL;
6220
6221 return func;
6222 }
6223
6224 static const char *
6225 ffecom_gfrt_args_ (ffecomGfrt ix)
6226 {
6227 return ffecom_gfrt_argstring_[ix];
6228 }
6229
6230 static tree
6231 ffecom_gfrt_tree_ (ffecomGfrt ix)
6232 {
6233 if (ffecom_gfrt_[ix] == NULL_TREE)
6234 ffecom_make_gfrt_ (ix);
6235
6236 return ffecom_1 (ADDR_EXPR,
6237 build_pointer_type (TREE_TYPE (ffecom_gfrt_[ix])),
6238 ffecom_gfrt_[ix]);
6239 }
6240
6241 /* Return initialize-to-zero expression for this VAR_DECL. */
6242
6243 /* A somewhat evil way to prevent the garbage collector
6244 from collecting 'tree' structures. */
6245 #define NUM_TRACKED_CHUNK 63
6246 struct tree_ggc_tracker GTY(())
6247 {
6248 struct tree_ggc_tracker *next;
6249 tree trees[NUM_TRACKED_CHUNK];
6250 };
6251 static GTY(()) struct tree_ggc_tracker *tracker_head;
6252
6253 void
6254 ffecom_save_tree_forever (tree t)
6255 {
6256 int i;
6257 if (tracker_head != NULL)
6258 for (i = 0; i < NUM_TRACKED_CHUNK; i++)
6259 if (tracker_head->trees[i] == NULL)
6260 {
6261 tracker_head->trees[i] = t;
6262 return;
6263 }
6264
6265 {
6266 /* Need to allocate a new block. */
6267 struct tree_ggc_tracker *old_head = tracker_head;
6268
6269 tracker_head = ggc_alloc (sizeof (*tracker_head));
6270 tracker_head->next = old_head;
6271 tracker_head->trees[0] = t;
6272 for (i = 1; i < NUM_TRACKED_CHUNK; i++)
6273 tracker_head->trees[i] = NULL;
6274 }
6275 }
6276
6277 static tree
6278 ffecom_init_zero_ (tree decl)
6279 {
6280 tree init;
6281 int incremental = TREE_STATIC (decl);
6282 tree type = TREE_TYPE (decl);
6283
6284 if (incremental)
6285 {
6286 make_decl_rtl (decl, NULL);
6287 assemble_variable (decl, TREE_PUBLIC (decl) ? 1 : 0, 0, 1);
6288 }
6289
6290 if ((TREE_CODE (type) != ARRAY_TYPE)
6291 && (TREE_CODE (type) != RECORD_TYPE)
6292 && (TREE_CODE (type) != UNION_TYPE)
6293 && !incremental)
6294 init = convert (type, integer_zero_node);
6295 else if (!incremental)
6296 {
6297 init = build_constructor (type, NULL_TREE);
6298 TREE_CONSTANT (init) = 1;
6299 TREE_STATIC (init) = 1;
6300 }
6301 else
6302 {
6303 assemble_zeros (int_size_in_bytes (type));
6304 init = error_mark_node;
6305 }
6306
6307 return init;
6308 }
6309
6310 static tree
6311 ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
6312 tree *maybe_tree)
6313 {
6314 tree expr_tree;
6315 tree length_tree;
6316
6317 switch (ffebld_op (arg))
6318 {
6319 case FFEBLD_opCONTER: /* For F90, check 0-length. */
6320 if (ffetarget_length_character1
6321 (ffebld_constant_character1
6322 (ffebld_conter (arg))) == 0)
6323 {
6324 *maybe_tree = integer_zero_node;
6325 return convert (tree_type, integer_zero_node);
6326 }
6327
6328 *maybe_tree = integer_one_node;
6329 expr_tree = build_int_2 (*ffetarget_text_character1
6330 (ffebld_constant_character1
6331 (ffebld_conter (arg))),
6332 0);
6333 TREE_TYPE (expr_tree) = tree_type;
6334 return expr_tree;
6335
6336 case FFEBLD_opSYMTER:
6337 case FFEBLD_opARRAYREF:
6338 case FFEBLD_opFUNCREF:
6339 case FFEBLD_opSUBSTR:
6340 ffecom_char_args_ (&expr_tree, &length_tree, arg);
6341
6342 if ((expr_tree == error_mark_node)
6343 || (length_tree == error_mark_node))
6344 {
6345 *maybe_tree = error_mark_node;
6346 return error_mark_node;
6347 }
6348
6349 if (integer_zerop (length_tree))
6350 {
6351 *maybe_tree = integer_zero_node;
6352 return convert (tree_type, integer_zero_node);
6353 }
6354
6355 expr_tree
6356 = ffecom_1 (INDIRECT_REF,
6357 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6358 expr_tree);
6359 expr_tree
6360 = ffecom_2 (ARRAY_REF,
6361 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6362 expr_tree,
6363 integer_one_node);
6364 expr_tree = convert (tree_type, expr_tree);
6365
6366 if (TREE_CODE (length_tree) == INTEGER_CST)
6367 *maybe_tree = integer_one_node;
6368 else /* Must check length at run time. */
6369 *maybe_tree
6370 = ffecom_truth_value
6371 (ffecom_2 (GT_EXPR, integer_type_node,
6372 length_tree,
6373 ffecom_f2c_ftnlen_zero_node));
6374 return expr_tree;
6375
6376 case FFEBLD_opPAREN:
6377 case FFEBLD_opCONVERT:
6378 if (ffeinfo_size (ffebld_info (arg)) == 0)
6379 {
6380 *maybe_tree = integer_zero_node;
6381 return convert (tree_type, integer_zero_node);
6382 }
6383 return ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6384 maybe_tree);
6385
6386 case FFEBLD_opCONCATENATE:
6387 {
6388 tree maybe_left;
6389 tree maybe_right;
6390 tree expr_left;
6391 tree expr_right;
6392
6393 expr_left = ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6394 &maybe_left);
6395 expr_right = ffecom_intrinsic_ichar_ (tree_type, ffebld_right (arg),
6396 &maybe_right);
6397 *maybe_tree = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
6398 maybe_left,
6399 maybe_right);
6400 expr_tree = ffecom_3 (COND_EXPR, tree_type,
6401 maybe_left,
6402 expr_left,
6403 expr_right);
6404 return expr_tree;
6405 }
6406
6407 default:
6408 assert ("bad op in ICHAR" == NULL);
6409 return error_mark_node;
6410 }
6411 }
6412
6413 /* ffecom_intrinsic_len_ -- Return length info for char arg (LEN())
6414
6415 tree length_arg;
6416 ffebld expr;
6417 length_arg = ffecom_intrinsic_len_ (expr);
6418
6419 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
6420 subexpressions by constructing the appropriate tree for the
6421 length-of-character-text argument in a calling sequence. */
6422
6423 static tree
6424 ffecom_intrinsic_len_ (ffebld expr)
6425 {
6426 ffetargetCharacter1 val;
6427 tree length;
6428
6429 switch (ffebld_op (expr))
6430 {
6431 case FFEBLD_opCONTER:
6432 val = ffebld_constant_character1 (ffebld_conter (expr));
6433 length = build_int_2 (ffetarget_length_character1 (val), 0);
6434 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6435 break;
6436
6437 case FFEBLD_opSYMTER:
6438 {
6439 ffesymbol s = ffebld_symter (expr);
6440 tree item;
6441
6442 item = ffesymbol_hook (s).decl_tree;
6443 if (item == NULL_TREE)
6444 {
6445 s = ffecom_sym_transform_ (s);
6446 item = ffesymbol_hook (s).decl_tree;
6447 }
6448 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
6449 {
6450 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
6451 length = ffesymbol_hook (s).length_tree;
6452 else
6453 {
6454 length = build_int_2 (ffesymbol_size (s), 0);
6455 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6456 }
6457 }
6458 else if (item == error_mark_node)
6459 length = error_mark_node;
6460 else /* FFEINFO_kindFUNCTION: */
6461 length = NULL_TREE;
6462 }
6463 break;
6464
6465 case FFEBLD_opARRAYREF:
6466 length = ffecom_intrinsic_len_ (ffebld_left (expr));
6467 break;
6468
6469 case FFEBLD_opSUBSTR:
6470 {
6471 ffebld start;
6472 ffebld end;
6473 ffebld thing = ffebld_right (expr);
6474 tree start_tree;
6475 tree end_tree;
6476
6477 assert (ffebld_op (thing) == FFEBLD_opITEM);
6478 start = ffebld_head (thing);
6479 thing = ffebld_trail (thing);
6480 assert (ffebld_trail (thing) == NULL);
6481 end = ffebld_head (thing);
6482
6483 length = ffecom_intrinsic_len_ (ffebld_left (expr));
6484
6485 if (length == error_mark_node)
6486 break;
6487
6488 if (start == NULL)
6489 {
6490 if (end == NULL)
6491 ;
6492 else
6493 {
6494 length = convert (ffecom_f2c_ftnlen_type_node,
6495 ffecom_expr (end));
6496 }
6497 }
6498 else
6499 {
6500 start_tree = convert (ffecom_f2c_ftnlen_type_node,
6501 ffecom_expr (start));
6502
6503 if (start_tree == error_mark_node)
6504 {
6505 length = error_mark_node;
6506 break;
6507 }
6508
6509 if (end == NULL)
6510 {
6511 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6512 ffecom_f2c_ftnlen_one_node,
6513 ffecom_2 (MINUS_EXPR,
6514 ffecom_f2c_ftnlen_type_node,
6515 length,
6516 start_tree));
6517 }
6518 else
6519 {
6520 end_tree = convert (ffecom_f2c_ftnlen_type_node,
6521 ffecom_expr (end));
6522
6523 if (end_tree == error_mark_node)
6524 {
6525 length = error_mark_node;
6526 break;
6527 }
6528
6529 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6530 ffecom_f2c_ftnlen_one_node,
6531 ffecom_2 (MINUS_EXPR,
6532 ffecom_f2c_ftnlen_type_node,
6533 end_tree, start_tree));
6534 }
6535 }
6536 }
6537 break;
6538
6539 case FFEBLD_opCONCATENATE:
6540 length
6541 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6542 ffecom_intrinsic_len_ (ffebld_left (expr)),
6543 ffecom_intrinsic_len_ (ffebld_right (expr)));
6544 break;
6545
6546 case FFEBLD_opFUNCREF:
6547 case FFEBLD_opCONVERT:
6548 length = build_int_2 (ffebld_size (expr), 0);
6549 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6550 break;
6551
6552 default:
6553 assert ("bad op for single char arg expr" == NULL);
6554 length = ffecom_f2c_ftnlen_zero_node;
6555 break;
6556 }
6557
6558 assert (length != NULL_TREE);
6559
6560 return length;
6561 }
6562
6563 /* Handle CHARACTER assignments.
6564
6565 Generates code to do the assignment. Used by ordinary assignment
6566 statement handler ffecom_let_stmt and by statement-function
6567 handler to generate code for a statement function. */
6568
6569 static void
6570 ffecom_let_char_ (tree dest_tree, tree dest_length,
6571 ffetargetCharacterSize dest_size, ffebld source)
6572 {
6573 ffecomConcatList_ catlist;
6574 tree source_length;
6575 tree source_tree;
6576 tree expr_tree;
6577
6578 if ((dest_tree == error_mark_node)
6579 || (dest_length == error_mark_node))
6580 return;
6581
6582 assert (dest_tree != NULL_TREE);
6583 assert (dest_length != NULL_TREE);
6584
6585 /* Source might be an opCONVERT, which just means it is a different size
6586 than the destination. Since the underlying implementation here handles
6587 that (directly or via the s_copy or s_cat run-time-library functions),
6588 we don't need the "convenience" of an opCONVERT that tells us to
6589 truncate or blank-pad, particularly since the resulting implementation
6590 would probably be slower than otherwise. */
6591
6592 while (ffebld_op (source) == FFEBLD_opCONVERT)
6593 source = ffebld_left (source);
6594
6595 catlist = ffecom_concat_list_new_ (source, dest_size);
6596 switch (ffecom_concat_list_count_ (catlist))
6597 {
6598 case 0: /* Shouldn't happen, but in case it does... */
6599 ffecom_concat_list_kill_ (catlist);
6600 source_tree = null_pointer_node;
6601 source_length = ffecom_f2c_ftnlen_zero_node;
6602 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6603 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6604 TREE_CHAIN (TREE_CHAIN (expr_tree))
6605 = build_tree_list (NULL_TREE, dest_length);
6606 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6607 = build_tree_list (NULL_TREE, source_length);
6608
6609 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6610 TREE_SIDE_EFFECTS (expr_tree) = 1;
6611
6612 expand_expr_stmt (expr_tree);
6613
6614 return;
6615
6616 case 1: /* The (fairly) easy case. */
6617 ffecom_char_args_ (&source_tree, &source_length,
6618 ffecom_concat_list_expr_ (catlist, 0));
6619 ffecom_concat_list_kill_ (catlist);
6620 assert (source_tree != NULL_TREE);
6621 assert (source_length != NULL_TREE);
6622
6623 if ((source_tree == error_mark_node)
6624 || (source_length == error_mark_node))
6625 return;
6626
6627 if (dest_size == 1)
6628 {
6629 dest_tree
6630 = ffecom_1 (INDIRECT_REF,
6631 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6632 (dest_tree))),
6633 dest_tree);
6634 dest_tree
6635 = ffecom_2 (ARRAY_REF,
6636 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6637 (dest_tree))),
6638 dest_tree,
6639 integer_one_node);
6640 source_tree
6641 = ffecom_1 (INDIRECT_REF,
6642 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6643 (source_tree))),
6644 source_tree);
6645 source_tree
6646 = ffecom_2 (ARRAY_REF,
6647 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6648 (source_tree))),
6649 source_tree,
6650 integer_one_node);
6651
6652 expr_tree = ffecom_modify (void_type_node, dest_tree, source_tree);
6653
6654 expand_expr_stmt (expr_tree);
6655
6656 return;
6657 }
6658
6659 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6660 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6661 TREE_CHAIN (TREE_CHAIN (expr_tree))
6662 = build_tree_list (NULL_TREE, dest_length);
6663 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6664 = build_tree_list (NULL_TREE, source_length);
6665
6666 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6667 TREE_SIDE_EFFECTS (expr_tree) = 1;
6668
6669 expand_expr_stmt (expr_tree);
6670
6671 return;
6672
6673 default: /* Must actually concatenate things. */
6674 break;
6675 }
6676
6677 /* Heavy-duty concatenation. */
6678
6679 {
6680 int count = ffecom_concat_list_count_ (catlist);
6681 int i;
6682 tree lengths;
6683 tree items;
6684 tree length_array;
6685 tree item_array;
6686 tree citem;
6687 tree clength;
6688
6689 {
6690 tree hook;
6691
6692 hook = ffebld_nonter_hook (source);
6693 assert (hook);
6694 assert (TREE_CODE (hook) == TREE_VEC);
6695 assert (TREE_VEC_LENGTH (hook) == 2);
6696 length_array = lengths = TREE_VEC_ELT (hook, 0);
6697 item_array = items = TREE_VEC_ELT (hook, 1);
6698 }
6699
6700 for (i = 0; i < count; ++i)
6701 {
6702 ffecom_char_args_ (&citem, &clength,
6703 ffecom_concat_list_expr_ (catlist, i));
6704 if ((citem == error_mark_node)
6705 || (clength == error_mark_node))
6706 {
6707 ffecom_concat_list_kill_ (catlist);
6708 return;
6709 }
6710
6711 items
6712 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
6713 ffecom_modify (void_type_node,
6714 ffecom_2 (ARRAY_REF,
6715 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
6716 item_array,
6717 build_int_2 (i, 0)),
6718 citem),
6719 items);
6720 lengths
6721 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
6722 ffecom_modify (void_type_node,
6723 ffecom_2 (ARRAY_REF,
6724 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
6725 length_array,
6726 build_int_2 (i, 0)),
6727 clength),
6728 lengths);
6729 }
6730
6731 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6732 TREE_CHAIN (expr_tree)
6733 = build_tree_list (NULL_TREE,
6734 ffecom_1 (ADDR_EXPR,
6735 build_pointer_type (TREE_TYPE (items)),
6736 items));
6737 TREE_CHAIN (TREE_CHAIN (expr_tree))
6738 = build_tree_list (NULL_TREE,
6739 ffecom_1 (ADDR_EXPR,
6740 build_pointer_type (TREE_TYPE (lengths)),
6741 lengths));
6742 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6743 = build_tree_list
6744 (NULL_TREE,
6745 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
6746 convert (ffecom_f2c_ftnlen_type_node,
6747 build_int_2 (count, 0))));
6748 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree))))
6749 = build_tree_list (NULL_TREE, dest_length);
6750
6751 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCAT, expr_tree, NULL_TREE);
6752 TREE_SIDE_EFFECTS (expr_tree) = 1;
6753
6754 expand_expr_stmt (expr_tree);
6755 }
6756
6757 ffecom_concat_list_kill_ (catlist);
6758 }
6759
6760 /* ffecom_make_gfrt_ -- Make initial info for run-time routine
6761
6762 ffecomGfrt ix;
6763 ffecom_make_gfrt_(ix);
6764
6765 Assumes gfrt_[ix] is NULL_TREE, and replaces it with the FUNCTION_DECL
6766 for the indicated run-time routine (ix). */
6767
6768 static void
6769 ffecom_make_gfrt_ (ffecomGfrt ix)
6770 {
6771 tree t;
6772 tree ttype;
6773
6774 switch (ffecom_gfrt_type_[ix])
6775 {
6776 case FFECOM_rttypeVOID_:
6777 ttype = void_type_node;
6778 break;
6779
6780 case FFECOM_rttypeVOIDSTAR_:
6781 ttype = TREE_TYPE (null_pointer_node); /* `void *'. */
6782 break;
6783
6784 case FFECOM_rttypeFTNINT_:
6785 ttype = ffecom_f2c_ftnint_type_node;
6786 break;
6787
6788 case FFECOM_rttypeINTEGER_:
6789 ttype = ffecom_f2c_integer_type_node;
6790 break;
6791
6792 case FFECOM_rttypeLONGINT_:
6793 ttype = ffecom_f2c_longint_type_node;
6794 break;
6795
6796 case FFECOM_rttypeLOGICAL_:
6797 ttype = ffecom_f2c_logical_type_node;
6798 break;
6799
6800 case FFECOM_rttypeREAL_F2C_:
6801 ttype = double_type_node;
6802 break;
6803
6804 case FFECOM_rttypeREAL_GNU_:
6805 ttype = float_type_node;
6806 break;
6807
6808 case FFECOM_rttypeCOMPLEX_F2C_:
6809 ttype = void_type_node;
6810 break;
6811
6812 case FFECOM_rttypeCOMPLEX_GNU_:
6813 ttype = ffecom_f2c_complex_type_node;
6814 break;
6815
6816 case FFECOM_rttypeDOUBLE_:
6817 ttype = double_type_node;
6818 break;
6819
6820 case FFECOM_rttypeDOUBLEREAL_:
6821 ttype = ffecom_f2c_doublereal_type_node;
6822 break;
6823
6824 case FFECOM_rttypeDBLCMPLX_F2C_:
6825 ttype = void_type_node;
6826 break;
6827
6828 case FFECOM_rttypeDBLCMPLX_GNU_:
6829 ttype = ffecom_f2c_doublecomplex_type_node;
6830 break;
6831
6832 case FFECOM_rttypeCHARACTER_:
6833 ttype = void_type_node;
6834 break;
6835
6836 default:
6837 ttype = NULL;
6838 assert ("bad rttype" == NULL);
6839 break;
6840 }
6841
6842 ttype = build_function_type (ttype, NULL_TREE);
6843 t = build_decl (FUNCTION_DECL,
6844 get_identifier (ffecom_gfrt_name_[ix]),
6845 ttype);
6846 DECL_EXTERNAL (t) = 1;
6847 TREE_READONLY (t) = ffecom_gfrt_const_[ix] ? 1 : 0;
6848 TREE_PUBLIC (t) = 1;
6849 TREE_THIS_VOLATILE (t) = ffecom_gfrt_volatile_[ix] ? 1 : 0;
6850
6851 /* Sanity check: A function that's const cannot be volatile. */
6852
6853 assert (ffecom_gfrt_const_[ix] ? !ffecom_gfrt_volatile_[ix] : 1);
6854
6855 /* Sanity check: A function that's const cannot return complex. */
6856
6857 assert (ffecom_gfrt_const_[ix] ? !ffecom_gfrt_complex_[ix] : 1);
6858
6859 t = start_decl (t, TRUE);
6860
6861 finish_decl (t, NULL_TREE, TRUE);
6862
6863 ffecom_gfrt_[ix] = t;
6864 }
6865
6866 /* Phase 1 pass over each member of a COMMON/EQUIVALENCE group. */
6867
6868 static void
6869 ffecom_member_phase1_ (ffestorag mst UNUSED, ffestorag st)
6870 {
6871 ffesymbol s = ffestorag_symbol (st);
6872
6873 if (ffesymbol_namelisted (s))
6874 ffecom_member_namelisted_ = TRUE;
6875 }
6876
6877 /* Phase 2 pass over each member of a COMMON/EQUIVALENCE group. Declare
6878 the member so debugger will see it. Otherwise nobody should be
6879 referencing the member. */
6880
6881 static void
6882 ffecom_member_phase2_ (ffestorag mst, ffestorag st)
6883 {
6884 ffesymbol s;
6885 tree t;
6886 tree mt;
6887 tree type;
6888
6889 if ((mst == NULL)
6890 || ((mt = ffestorag_hook (mst)) == NULL)
6891 || (mt == error_mark_node))
6892 return;
6893
6894 if ((st == NULL)
6895 || ((s = ffestorag_symbol (st)) == NULL))
6896 return;
6897
6898 type = ffecom_type_localvar_ (s,
6899 ffesymbol_basictype (s),
6900 ffesymbol_kindtype (s));
6901 if (type == error_mark_node)
6902 return;
6903
6904 t = build_decl (VAR_DECL,
6905 ffecom_get_identifier_ (ffesymbol_text (s)),
6906 type);
6907
6908 TREE_STATIC (t) = TREE_STATIC (mt);
6909 DECL_INITIAL (t) = NULL_TREE;
6910 TREE_ASM_WRITTEN (t) = 1;
6911 TREE_USED (t) = 1;
6912
6913 SET_DECL_RTL (t,
6914 gen_rtx (MEM, TYPE_MODE (type),
6915 plus_constant (XEXP (DECL_RTL (mt), 0),
6916 ffestorag_modulo (mst)
6917 + ffestorag_offset (st)
6918 - ffestorag_offset (mst))));
6919
6920 t = start_decl (t, FALSE);
6921
6922 finish_decl (t, NULL_TREE, FALSE);
6923 }
6924
6925 /* Prepare source expression for assignment into a destination perhaps known
6926 to be of a specific size. */
6927
6928 static void
6929 ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size, ffebld source)
6930 {
6931 ffecomConcatList_ catlist;
6932 int count;
6933 int i;
6934 tree ltmp;
6935 tree itmp;
6936 tree tempvar = NULL_TREE;
6937
6938 while (ffebld_op (source) == FFEBLD_opCONVERT)
6939 source = ffebld_left (source);
6940
6941 catlist = ffecom_concat_list_new_ (source, dest_size);
6942 count = ffecom_concat_list_count_ (catlist);
6943
6944 if (count >= 2)
6945 {
6946 ltmp
6947 = ffecom_make_tempvar ("let_char_len", ffecom_f2c_ftnlen_type_node,
6948 FFETARGET_charactersizeNONE, count);
6949 itmp
6950 = ffecom_make_tempvar ("let_char_item", ffecom_f2c_address_type_node,
6951 FFETARGET_charactersizeNONE, count);
6952
6953 tempvar = make_tree_vec (2);
6954 TREE_VEC_ELT (tempvar, 0) = ltmp;
6955 TREE_VEC_ELT (tempvar, 1) = itmp;
6956 }
6957
6958 for (i = 0; i < count; ++i)
6959 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist, i));
6960
6961 ffecom_concat_list_kill_ (catlist);
6962
6963 if (tempvar)
6964 {
6965 ffebld_nonter_set_hook (source, tempvar);
6966 current_binding_level->prep_state = 1;
6967 }
6968 }
6969
6970 /* ffecom_push_dummy_decls_ -- Transform dummy args, push parm decls in order
6971
6972 Ignores STAR (alternate-return) dummies. All other get exec-transitioned
6973 (which generates their trees) and then their trees get push_parm_decl'd.
6974
6975 The second arg is TRUE if the dummies are for a statement function, in
6976 which case lengths are not pushed for character arguments (since they are
6977 always known by both the caller and the callee, though the code allows
6978 for someday permitting CHAR*(*) stmtfunc dummies). */
6979
6980 static void
6981 ffecom_push_dummy_decls_ (ffebld dummy_list, bool stmtfunc)
6982 {
6983 ffebld dummy;
6984 ffebld dumlist;
6985 ffesymbol s;
6986 tree parm;
6987
6988 ffecom_transform_only_dummies_ = TRUE;
6989
6990 /* First push the parms corresponding to actual dummy "contents". */
6991
6992 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
6993 {
6994 dummy = ffebld_head (dumlist);
6995 switch (ffebld_op (dummy))
6996 {
6997 case FFEBLD_opSTAR:
6998 case FFEBLD_opANY:
6999 continue; /* Forget alternate returns. */
7000
7001 default:
7002 break;
7003 }
7004 assert (ffebld_op (dummy) == FFEBLD_opSYMTER);
7005 s = ffebld_symter (dummy);
7006 parm = ffesymbol_hook (s).decl_tree;
7007 if (parm == NULL_TREE)
7008 {
7009 s = ffecom_sym_transform_ (s);
7010 parm = ffesymbol_hook (s).decl_tree;
7011 assert (parm != NULL_TREE);
7012 }
7013 if (parm != error_mark_node)
7014 push_parm_decl (parm);
7015 }
7016
7017 /* Then, for CHARACTER dummies, push the parms giving their lengths. */
7018
7019 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7020 {
7021 dummy = ffebld_head (dumlist);
7022 switch (ffebld_op (dummy))
7023 {
7024 case FFEBLD_opSTAR:
7025 case FFEBLD_opANY:
7026 continue; /* Forget alternate returns, they mean
7027 NOTHING! */
7028
7029 default:
7030 break;
7031 }
7032 s = ffebld_symter (dummy);
7033 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
7034 continue; /* Only looking for CHARACTER arguments. */
7035 if (stmtfunc && (ffesymbol_size (s) != FFETARGET_charactersizeNONE))
7036 continue; /* Stmtfunc arg with known size needs no
7037 length param. */
7038 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
7039 continue; /* Only looking for variables and arrays. */
7040 parm = ffesymbol_hook (s).length_tree;
7041 assert (parm != NULL_TREE);
7042 if (parm != error_mark_node)
7043 push_parm_decl (parm);
7044 }
7045
7046 ffecom_transform_only_dummies_ = FALSE;
7047 }
7048
7049 /* ffecom_start_progunit_ -- Beginning of program unit
7050
7051 Does GNU back end stuff necessary to teach it about the start of its
7052 equivalent of a Fortran program unit. */
7053
7054 static void
7055 ffecom_start_progunit_ ()
7056 {
7057 ffesymbol fn = ffecom_primary_entry_;
7058 ffebld arglist;
7059 tree id; /* Identifier (name) of function. */
7060 tree type; /* Type of function. */
7061 tree result; /* Result of function. */
7062 ffeinfoBasictype bt;
7063 ffeinfoKindtype kt;
7064 ffeglobal g;
7065 ffeglobalType gt;
7066 ffeglobalType egt = FFEGLOBAL_type;
7067 bool charfunc;
7068 bool cmplxfunc;
7069 bool altentries = (ffecom_num_entrypoints_ != 0);
7070 bool multi
7071 = altentries
7072 && (ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
7073 && (ffecom_master_bt_ == FFEINFO_basictypeNONE);
7074 bool main_program = FALSE;
7075 location_t old_loc = input_location;
7076
7077 assert (fn != NULL);
7078 assert (ffesymbol_hook (fn).decl_tree == NULL_TREE);
7079
7080 input_filename = ffesymbol_where_filename (fn);
7081 input_line = ffesymbol_where_filelinenum (fn);
7082
7083 switch (ffecom_primary_entry_kind_)
7084 {
7085 case FFEINFO_kindPROGRAM:
7086 main_program = TRUE;
7087 gt = FFEGLOBAL_typeMAIN;
7088 bt = FFEINFO_basictypeNONE;
7089 kt = FFEINFO_kindtypeNONE;
7090 type = ffecom_tree_fun_type_void;
7091 charfunc = FALSE;
7092 cmplxfunc = FALSE;
7093 break;
7094
7095 case FFEINFO_kindBLOCKDATA:
7096 gt = FFEGLOBAL_typeBDATA;
7097 bt = FFEINFO_basictypeNONE;
7098 kt = FFEINFO_kindtypeNONE;
7099 type = ffecom_tree_fun_type_void;
7100 charfunc = FALSE;
7101 cmplxfunc = FALSE;
7102 break;
7103
7104 case FFEINFO_kindFUNCTION:
7105 gt = FFEGLOBAL_typeFUNC;
7106 egt = FFEGLOBAL_typeEXT;
7107 bt = ffesymbol_basictype (fn);
7108 kt = ffesymbol_kindtype (fn);
7109 if (bt == FFEINFO_basictypeNONE)
7110 {
7111 ffeimplic_establish_symbol (fn);
7112 if (ffesymbol_funcresult (fn) != NULL)
7113 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
7114 bt = ffesymbol_basictype (fn);
7115 kt = ffesymbol_kindtype (fn);
7116 }
7117
7118 if (multi)
7119 charfunc = cmplxfunc = FALSE;
7120 else if (bt == FFEINFO_basictypeCHARACTER)
7121 charfunc = TRUE, cmplxfunc = FALSE;
7122 else if ((bt == FFEINFO_basictypeCOMPLEX)
7123 && ffesymbol_is_f2c (fn)
7124 && !altentries)
7125 charfunc = FALSE, cmplxfunc = TRUE;
7126 else
7127 charfunc = cmplxfunc = FALSE;
7128
7129 if (multi || charfunc)
7130 type = ffecom_tree_fun_type_void;
7131 else if (ffesymbol_is_f2c (fn) && !altentries)
7132 type = ffecom_tree_fun_type[bt][kt];
7133 else
7134 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
7135
7136 if ((type == NULL_TREE)
7137 || (TREE_TYPE (type) == NULL_TREE))
7138 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
7139 break;
7140
7141 case FFEINFO_kindSUBROUTINE:
7142 gt = FFEGLOBAL_typeSUBR;
7143 egt = FFEGLOBAL_typeEXT;
7144 bt = FFEINFO_basictypeNONE;
7145 kt = FFEINFO_kindtypeNONE;
7146 if (ffecom_is_altreturning_)
7147 type = ffecom_tree_subr_type;
7148 else
7149 type = ffecom_tree_fun_type_void;
7150 charfunc = FALSE;
7151 cmplxfunc = FALSE;
7152 break;
7153
7154 default:
7155 assert ("say what??" == NULL);
7156 /* Fall through. */
7157 case FFEINFO_kindANY:
7158 gt = FFEGLOBAL_typeANY;
7159 bt = FFEINFO_basictypeNONE;
7160 kt = FFEINFO_kindtypeNONE;
7161 type = error_mark_node;
7162 charfunc = FALSE;
7163 cmplxfunc = FALSE;
7164 break;
7165 }
7166
7167 if (altentries)
7168 {
7169 id = ffecom_get_invented_identifier ("__g77_masterfun_%s",
7170 ffesymbol_text (fn));
7171 }
7172 #if FFETARGET_isENFORCED_MAIN
7173 else if (main_program)
7174 id = get_identifier (FFETARGET_nameENFORCED_MAIN_NAME);
7175 #endif
7176 else
7177 id = ffecom_get_external_identifier_ (fn);
7178
7179 start_function (id,
7180 type,
7181 0, /* nested/inline */
7182 !altentries); /* TREE_PUBLIC */
7183
7184 TREE_USED (current_function_decl) = 1; /* Avoid spurious warning if altentries. */
7185
7186 if (!altentries
7187 && ((g = ffesymbol_global (fn)) != NULL)
7188 && ((ffeglobal_type (g) == gt)
7189 || (ffeglobal_type (g) == egt)))
7190 {
7191 ffeglobal_set_hook (g, current_function_decl);
7192 }
7193
7194 /* Arg handling needs exec-transitioned ffesymbols to work with. But
7195 exec-transitioning needs current_function_decl to be filled in. So we
7196 do these things in two phases. */
7197
7198 if (altentries)
7199 { /* 1st arg identifies which entrypoint. */
7200 ffecom_which_entrypoint_decl_
7201 = build_decl (PARM_DECL,
7202 ffecom_get_invented_identifier ("__g77_%s",
7203 "which_entrypoint"),
7204 integer_type_node);
7205 push_parm_decl (ffecom_which_entrypoint_decl_);
7206 }
7207
7208 if (charfunc
7209 || cmplxfunc
7210 || multi)
7211 { /* Arg for result (return value). */
7212 tree type;
7213 tree length;
7214
7215 if (charfunc)
7216 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
7217 else if (cmplxfunc)
7218 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
7219 else
7220 type = ffecom_multi_type_node_;
7221
7222 result = ffecom_get_invented_identifier ("__g77_%s", "result");
7223
7224 /* Make length arg _and_ enhance type info for CHAR arg itself. */
7225
7226 if (charfunc)
7227 length = ffecom_char_enhance_arg_ (&type, fn);
7228 else
7229 length = NULL_TREE; /* Not ref'd if !charfunc. */
7230
7231 type = build_pointer_type (type);
7232 result = build_decl (PARM_DECL, result, type);
7233
7234 push_parm_decl (result);
7235 if (multi)
7236 ffecom_multi_retval_ = result;
7237 else
7238 ffecom_func_result_ = result;
7239
7240 if (charfunc)
7241 {
7242 push_parm_decl (length);
7243 ffecom_func_length_ = length;
7244 }
7245 }
7246
7247 if (ffecom_primary_entry_is_proc_)
7248 {
7249 if (altentries)
7250 arglist = ffecom_master_arglist_;
7251 else
7252 arglist = ffesymbol_dummyargs (fn);
7253 ffecom_push_dummy_decls_ (arglist, FALSE);
7254 }
7255
7256 if (TREE_CODE (current_function_decl) != ERROR_MARK)
7257 store_parm_decls (main_program ? 1 : 0);
7258
7259 ffecom_start_compstmt ();
7260 /* Disallow temp vars at this level. */
7261 current_binding_level->prep_state = 2;
7262
7263 input_location = old_loc;
7264
7265 /* This handles any symbols still untransformed, in case -g specified.
7266 This used to be done in ffecom_finish_progunit, but it turns out to
7267 be necessary to do it here so that statement functions are
7268 expanded before code. But don't bother for BLOCK DATA. */
7269
7270 if (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
7271 ffesymbol_drive (ffecom_finish_symbol_transform_);
7272 }
7273
7274 /* ffecom_sym_transform_ -- Transform FFE sym into backend sym
7275
7276 ffesymbol s;
7277 ffecom_sym_transform_(s);
7278
7279 The ffesymbol_hook info for s is updated with appropriate backend info
7280 on the symbol. */
7281
7282 static ffesymbol
7283 ffecom_sym_transform_ (ffesymbol s)
7284 {
7285 tree t; /* Transformed thingy. */
7286 tree tlen; /* Length if CHAR*(*). */
7287 bool addr; /* Is t the address of the thingy? */
7288 ffeinfoBasictype bt;
7289 ffeinfoKindtype kt;
7290 ffeglobal g;
7291 location_t old_loc = input_location;
7292
7293 /* Must ensure special ASSIGN variables are declared at top of outermost
7294 block, else they'll end up in the innermost block when their first
7295 ASSIGN is seen, which leaves them out of scope when they're the
7296 subject of a GOTO or I/O statement.
7297
7298 We make this variable even if -fugly-assign. Just let it go unused,
7299 in case it turns out there are cases where we really want to use this
7300 variable anyway (e.g. ASSIGN to INTEGER*2 variable). */
7301
7302 if (! ffecom_transform_only_dummies_
7303 && ffesymbol_assigned (s)
7304 && ! ffesymbol_hook (s).assign_tree)
7305 s = ffecom_sym_transform_assign_ (s);
7306
7307 if (ffesymbol_sfdummyparent (s) == NULL)
7308 {
7309 input_filename = ffesymbol_where_filename (s);
7310 input_line = ffesymbol_where_filelinenum (s);
7311 }
7312 else
7313 {
7314 ffesymbol sf = ffesymbol_sfdummyparent (s);
7315
7316 input_filename = ffesymbol_where_filename (sf);
7317 input_line = ffesymbol_where_filelinenum (sf);
7318 }
7319
7320 bt = ffeinfo_basictype (ffebld_info (s));
7321 kt = ffeinfo_kindtype (ffebld_info (s));
7322
7323 t = NULL_TREE;
7324 tlen = NULL_TREE;
7325 addr = FALSE;
7326
7327 switch (ffesymbol_kind (s))
7328 {
7329 case FFEINFO_kindNONE:
7330 switch (ffesymbol_where (s))
7331 {
7332 case FFEINFO_whereDUMMY: /* Subroutine or function. */
7333 assert (ffecom_transform_only_dummies_);
7334
7335 /* Before 0.4, this could be ENTITY/DUMMY, but see
7336 ffestu_sym_end_transition -- no longer true (in particular, if
7337 it could be an ENTITY, it _will_ be made one, so that
7338 possibility won't come through here). So we never make length
7339 arg for CHARACTER type. */
7340
7341 t = build_decl (PARM_DECL,
7342 ffecom_get_identifier_ (ffesymbol_text (s)),
7343 ffecom_tree_ptr_to_subr_type);
7344 DECL_ARTIFICIAL (t) = 1;
7345 addr = TRUE;
7346 break;
7347
7348 case FFEINFO_whereGLOBAL: /* Subroutine or function. */
7349 assert (!ffecom_transform_only_dummies_);
7350
7351 if (((g = ffesymbol_global (s)) != NULL)
7352 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7353 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7354 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
7355 && (ffeglobal_hook (g) != NULL_TREE)
7356 && ffe_is_globals ())
7357 {
7358 t = ffeglobal_hook (g);
7359 break;
7360 }
7361
7362 t = build_decl (FUNCTION_DECL,
7363 ffecom_get_external_identifier_ (s),
7364 ffecom_tree_subr_type); /* Assume subr. */
7365 DECL_EXTERNAL (t) = 1;
7366 TREE_PUBLIC (t) = 1;
7367
7368 t = start_decl (t, FALSE);
7369 finish_decl (t, NULL_TREE, FALSE);
7370
7371 if ((g != NULL)
7372 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7373 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7374 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
7375 ffeglobal_set_hook (g, t);
7376
7377 ffecom_save_tree_forever (t);
7378
7379 break;
7380
7381 default:
7382 assert ("NONE where unexpected" == NULL);
7383 /* Fall through. */
7384 case FFEINFO_whereANY:
7385 break;
7386 }
7387 break;
7388
7389 case FFEINFO_kindENTITY:
7390 switch (ffeinfo_where (ffesymbol_info (s)))
7391 {
7392
7393 case FFEINFO_whereCONSTANT:
7394 /* ~~Debugging info needed? */
7395 assert (!ffecom_transform_only_dummies_);
7396 t = error_mark_node; /* Shouldn't ever see this in expr. */
7397 break;
7398
7399 case FFEINFO_whereLOCAL:
7400 assert (!ffecom_transform_only_dummies_);
7401
7402 {
7403 ffestorag st = ffesymbol_storage (s);
7404 tree type;
7405
7406 type = ffecom_type_localvar_ (s, bt, kt);
7407
7408 if (type == error_mark_node)
7409 {
7410 t = error_mark_node;
7411 break;
7412 }
7413
7414 if ((st != NULL)
7415 && (ffestorag_size (st) == 0))
7416 {
7417 t = error_mark_node;
7418 break;
7419 }
7420
7421 if ((st != NULL)
7422 && (ffestorag_parent (st) != NULL))
7423 { /* Child of EQUIVALENCE parent. */
7424 ffestorag est;
7425 tree et;
7426 ffetargetOffset offset;
7427
7428 est = ffestorag_parent (st);
7429 ffecom_transform_equiv_ (est);
7430
7431 et = ffestorag_hook (est);
7432 assert (et != NULL_TREE);
7433
7434 if (! TREE_STATIC (et))
7435 put_var_into_stack (et, /*rescan=*/true);
7436
7437 offset = ffestorag_modulo (est)
7438 + ffestorag_offset (ffesymbol_storage (s))
7439 - ffestorag_offset (est);
7440
7441 ffecom_debug_kludge_ (et, "EQUIVALENCE", s, type, offset);
7442
7443 /* (t_type *) (((char *) &et) + offset) */
7444
7445 t = convert (string_type_node, /* (char *) */
7446 ffecom_1 (ADDR_EXPR,
7447 build_pointer_type (TREE_TYPE (et)),
7448 et));
7449 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
7450 t,
7451 build_int_2 (offset, 0));
7452 t = convert (build_pointer_type (type),
7453 t);
7454 TREE_CONSTANT (t) = staticp (et);
7455
7456 addr = TRUE;
7457 }
7458 else
7459 {
7460 tree initexpr;
7461 bool init = ffesymbol_is_init (s);
7462
7463 t = build_decl (VAR_DECL,
7464 ffecom_get_identifier_ (ffesymbol_text (s)),
7465 type);
7466
7467 if (init
7468 || ffesymbol_namelisted (s)
7469 #ifdef FFECOM_sizeMAXSTACKITEM
7470 || ((st != NULL)
7471 && (ffestorag_size (st) > FFECOM_sizeMAXSTACKITEM))
7472 #endif
7473 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
7474 && (ffecom_primary_entry_kind_
7475 != FFEINFO_kindBLOCKDATA)
7476 && (ffesymbol_is_save (s) || ffe_is_saveall ())))
7477 TREE_STATIC (t) = !ffesymbol_attr (s, FFESYMBOL_attrADJUSTABLE);
7478 else
7479 TREE_STATIC (t) = 0; /* No need to make static. */
7480
7481 if (init || ffe_is_init_local_zero ())
7482 DECL_INITIAL (t) = error_mark_node;
7483
7484 /* Keep -Wunused from complaining about var if it
7485 is used as sfunc arg or DATA implied-DO. */
7486 if (ffesymbol_attrs (s) & FFESYMBOL_attrsSFARG)
7487 DECL_IN_SYSTEM_HEADER (t) = 1;
7488
7489 t = start_decl (t, FALSE);
7490
7491 if (init)
7492 {
7493 if (ffesymbol_init (s) != NULL)
7494 initexpr = ffecom_expr (ffesymbol_init (s));
7495 else
7496 initexpr = ffecom_init_zero_ (t);
7497 }
7498 else if (ffe_is_init_local_zero ())
7499 initexpr = ffecom_init_zero_ (t);
7500 else
7501 initexpr = NULL_TREE; /* Not ref'd if !init. */
7502
7503 finish_decl (t, initexpr, FALSE);
7504
7505 if (st != NULL && DECL_SIZE (t) != error_mark_node)
7506 {
7507 assert (TREE_CODE (DECL_SIZE_UNIT (t)) == INTEGER_CST);
7508 assert (0 == compare_tree_int (DECL_SIZE_UNIT (t),
7509 ffestorag_size (st)));
7510 }
7511 }
7512 }
7513 break;
7514
7515 case FFEINFO_whereRESULT:
7516 assert (!ffecom_transform_only_dummies_);
7517
7518 if (bt == FFEINFO_basictypeCHARACTER)
7519 { /* Result is already in list of dummies, use
7520 it (& length). */
7521 t = ffecom_func_result_;
7522 tlen = ffecom_func_length_;
7523 addr = TRUE;
7524 break;
7525 }
7526 if ((ffecom_num_entrypoints_ == 0)
7527 && (bt == FFEINFO_basictypeCOMPLEX)
7528 && (ffesymbol_is_f2c (ffecom_primary_entry_)))
7529 { /* Result is already in list of dummies, use
7530 it. */
7531 t = ffecom_func_result_;
7532 addr = TRUE;
7533 break;
7534 }
7535 if (ffecom_func_result_ != NULL_TREE)
7536 {
7537 t = ffecom_func_result_;
7538 break;
7539 }
7540 if ((ffecom_num_entrypoints_ != 0)
7541 && (ffecom_master_bt_ == FFEINFO_basictypeNONE))
7542 {
7543 assert (ffecom_multi_retval_ != NULL_TREE);
7544 t = ffecom_1 (INDIRECT_REF, ffecom_multi_type_node_,
7545 ffecom_multi_retval_);
7546 t = ffecom_2 (COMPONENT_REF, ffecom_tree_type[bt][kt],
7547 t, ffecom_multi_fields_[bt][kt]);
7548
7549 break;
7550 }
7551
7552 t = build_decl (VAR_DECL,
7553 ffecom_get_identifier_ (ffesymbol_text (s)),
7554 ffecom_tree_type[bt][kt]);
7555 TREE_STATIC (t) = 0; /* Put result on stack. */
7556 t = start_decl (t, FALSE);
7557 finish_decl (t, NULL_TREE, FALSE);
7558
7559 ffecom_func_result_ = t;
7560
7561 break;
7562
7563 case FFEINFO_whereDUMMY:
7564 {
7565 tree type;
7566 ffebld dl;
7567 ffebld dim;
7568 tree low;
7569 tree high;
7570 tree old_sizes;
7571 bool adjustable = FALSE; /* Conditionally adjustable? */
7572
7573 type = ffecom_tree_type[bt][kt];
7574 if (ffesymbol_sfdummyparent (s) != NULL)
7575 {
7576 if (current_function_decl == ffecom_outer_function_decl_)
7577 { /* Exec transition before sfunc
7578 context; get it later. */
7579 break;
7580 }
7581 t = ffecom_get_identifier_ (ffesymbol_text
7582 (ffesymbol_sfdummyparent (s)));
7583 }
7584 else
7585 t = ffecom_get_identifier_ (ffesymbol_text (s));
7586
7587 assert (ffecom_transform_only_dummies_);
7588
7589 old_sizes = get_pending_sizes ();
7590 put_pending_sizes (old_sizes);
7591
7592 if (bt == FFEINFO_basictypeCHARACTER)
7593 tlen = ffecom_char_enhance_arg_ (&type, s);
7594 type = ffecom_check_size_overflow_ (s, type, TRUE);
7595
7596 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
7597 {
7598 if (type == error_mark_node)
7599 break;
7600
7601 dim = ffebld_head (dl);
7602 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
7603 if ((ffebld_left (dim) == NULL) || ffecom_doing_entry_)
7604 low = ffecom_integer_one_node;
7605 else
7606 low = ffecom_expr (ffebld_left (dim));
7607 assert (ffebld_right (dim) != NULL);
7608 if ((ffebld_op (ffebld_right (dim)) == FFEBLD_opSTAR)
7609 || ffecom_doing_entry_)
7610 {
7611 /* Used to just do high=low. But for ffecom_tree_
7612 canonize_ref_, it probably is important to correctly
7613 assess the size. E.g. given COMPLEX C(*),CFUNC and
7614 C(2)=CFUNC(C), overlap can happen, while it can't
7615 for, say, C(1)=CFUNC(C(2)). */
7616 /* Even more recently used to set to INT_MAX, but that
7617 broke when some overflow checking went into the back
7618 end. Now we just leave the upper bound unspecified. */
7619 high = NULL;
7620 }
7621 else
7622 high = ffecom_expr (ffebld_right (dim));
7623
7624 /* Determine whether array is conditionally adjustable,
7625 to decide whether back-end magic is needed.
7626
7627 Normally the front end uses the back-end function
7628 variable_size to wrap SAVE_EXPR's around expressions
7629 affecting the size/shape of an array so that the
7630 size/shape info doesn't change during execution
7631 of the compiled code even though variables and
7632 functions referenced in those expressions might.
7633
7634 variable_size also makes sure those saved expressions
7635 get evaluated immediately upon entry to the
7636 compiled procedure -- the front end normally doesn't
7637 have to worry about that.
7638
7639 However, there is a problem with this that affects
7640 g77's implementation of entry points, and that is
7641 that it is _not_ true that each invocation of the
7642 compiled procedure is permitted to evaluate
7643 array size/shape info -- because it is possible
7644 that, for some invocations, that info is invalid (in
7645 which case it is "promised" -- i.e. a violation of
7646 the Fortran standard -- that the compiled code
7647 won't reference the array or its size/shape
7648 during that particular invocation).
7649
7650 To phrase this in C terms, consider this gcc function:
7651
7652 void foo (int *n, float (*a)[*n])
7653 {
7654 // a is "pointer to array ...", fyi.
7655 }
7656
7657 Suppose that, for some invocations, it is permitted
7658 for a caller of foo to do this:
7659
7660 foo (NULL, NULL);
7661
7662 Now the _written_ code for foo can take such a call
7663 into account by either testing explicitly for whether
7664 (a == NULL) || (n == NULL) -- presumably it is
7665 not permitted to reference *a in various fashions
7666 if (n == NULL) I suppose -- or it can avoid it by
7667 looking at other info (other arguments, static/global
7668 data, etc.).
7669
7670 However, this won't work in gcc 2.5.8 because it'll
7671 automatically emit the code to save the "*n"
7672 expression, which'll yield a NULL dereference for
7673 the "foo (NULL, NULL)" call, something the code
7674 for foo cannot prevent.
7675
7676 g77 definitely needs to avoid executing such
7677 code anytime the pointer to the adjustable array
7678 is NULL, because even if its bounds expressions
7679 don't have any references to possible "absent"
7680 variables like "*n" -- say all variable references
7681 are to COMMON variables, i.e. global (though in C,
7682 local static could actually make sense) -- the
7683 expressions could yield other run-time problems
7684 for allowably "dead" values in those variables.
7685
7686 For example, let's consider a more complicated
7687 version of foo:
7688
7689 extern int i;
7690 extern int j;
7691
7692 void foo (float (*a)[i/j])
7693 {
7694 ...
7695 }
7696
7697 The above is (essentially) quite valid for Fortran
7698 but, again, for a call like "foo (NULL);", it is
7699 permitted for i and j to be undefined when the
7700 call is made. If j happened to be zero, for
7701 example, emitting the code to evaluate "i/j"
7702 could result in a run-time error.
7703
7704 Offhand, though I don't have my F77 or F90
7705 standards handy, it might even be valid for a
7706 bounds expression to contain a function reference,
7707 in which case I doubt it is permitted for an
7708 implementation to invoke that function in the
7709 Fortran case involved here (invocation of an
7710 alternate ENTRY point that doesn't have the adjustable
7711 array as one of its arguments).
7712
7713 So, the code that the compiler would normally emit
7714 to preevaluate the size/shape info for an
7715 adjustable array _must not_ be executed at run time
7716 in certain cases. Specifically, for Fortran,
7717 the case is when the pointer to the adjustable
7718 array == NULL. (For gnu-ish C, it might be nice
7719 for the source code itself to specify an expression
7720 that, if TRUE, inhibits execution of the code. Or
7721 reverse the sense for elegance.)
7722
7723 (Note that g77 could use a different test than NULL,
7724 actually, since it happens to always pass an
7725 integer to the called function that specifies which
7726 entry point is being invoked. Hmm, this might
7727 solve the next problem.)
7728
7729 One way a user could, I suppose, write "foo" so
7730 it works is to insert COND_EXPR's for the
7731 size/shape info so the dangerous stuff isn't
7732 actually done, as in:
7733
7734 void foo (int *n, float (*a)[(a == NULL) ? 0 : *n])
7735 {
7736 ...
7737 }
7738
7739 The next problem is that the front end needs to
7740 be able to tell the back end about the array's
7741 decl _before_ it tells it about the conditional
7742 expression to inhibit evaluation of size/shape info,
7743 as shown above.
7744
7745 To solve this, the front end needs to be able
7746 to give the back end the expression to inhibit
7747 generation of the preevaluation code _after_
7748 it makes the decl for the adjustable array.
7749
7750 Until then, the above example using the COND_EXPR
7751 doesn't pass muster with gcc because the "(a == NULL)"
7752 part has a reference to "a", which is still
7753 undefined at that point.
7754
7755 g77 will therefore use a different mechanism in the
7756 meantime. */
7757
7758 if (!adjustable
7759 && ((TREE_CODE (low) != INTEGER_CST)
7760 || (high && TREE_CODE (high) != INTEGER_CST)))
7761 adjustable = TRUE;
7762
7763 #if 0 /* Old approach -- see below. */
7764 if (TREE_CODE (low) != INTEGER_CST)
7765 low = ffecom_3 (COND_EXPR, integer_type_node,
7766 ffecom_adjarray_passed_ (s),
7767 low,
7768 ffecom_integer_zero_node);
7769
7770 if (high && TREE_CODE (high) != INTEGER_CST)
7771 high = ffecom_3 (COND_EXPR, integer_type_node,
7772 ffecom_adjarray_passed_ (s),
7773 high,
7774 ffecom_integer_zero_node);
7775 #endif
7776
7777 /* ~~~gcc/stor-layout.c (layout_type) should do this,
7778 probably. Fixes 950302-1.f. */
7779
7780 if (TREE_CODE (low) != INTEGER_CST)
7781 low = variable_size (low);
7782
7783 /* ~~~Similarly, this fixes dumb0.f. The C front end
7784 does this, which is why dumb0.c would work. */
7785
7786 if (high && TREE_CODE (high) != INTEGER_CST)
7787 high = variable_size (high);
7788
7789 type
7790 = build_array_type
7791 (type,
7792 build_range_type (ffecom_integer_type_node,
7793 low, high));
7794 type = ffecom_check_size_overflow_ (s, type, TRUE);
7795 }
7796
7797 if (type == error_mark_node)
7798 {
7799 t = error_mark_node;
7800 break;
7801 }
7802
7803 if ((ffesymbol_sfdummyparent (s) == NULL)
7804 || (ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER))
7805 {
7806 type = build_pointer_type (type);
7807 addr = TRUE;
7808 }
7809
7810 t = build_decl (PARM_DECL, t, type);
7811 DECL_ARTIFICIAL (t) = 1;
7812
7813 /* If this arg is present in every entry point's list of
7814 dummy args, then we're done. */
7815
7816 if (ffesymbol_numentries (s)
7817 == (ffecom_num_entrypoints_ + 1))
7818 break;
7819
7820 #if 1
7821
7822 /* If variable_size in stor-layout has been called during
7823 the above, then get_pending_sizes should have the
7824 yet-to-be-evaluated saved expressions pending.
7825 Make the whole lot of them get emitted, conditionally
7826 on whether the array decl ("t" above) is not NULL. */
7827
7828 {
7829 tree sizes = get_pending_sizes ();
7830 tree tem;
7831
7832 for (tem = sizes;
7833 tem != old_sizes;
7834 tem = TREE_CHAIN (tem))
7835 {
7836 tree temv = TREE_VALUE (tem);
7837
7838 if (sizes == tem)
7839 sizes = temv;
7840 else
7841 sizes
7842 = ffecom_2 (COMPOUND_EXPR,
7843 TREE_TYPE (sizes),
7844 temv,
7845 sizes);
7846 }
7847
7848 if (sizes != tem)
7849 {
7850 sizes
7851 = ffecom_3 (COND_EXPR,
7852 TREE_TYPE (sizes),
7853 ffecom_2 (NE_EXPR,
7854 integer_type_node,
7855 t,
7856 null_pointer_node),
7857 sizes,
7858 convert (TREE_TYPE (sizes),
7859 integer_zero_node));
7860 sizes = ffecom_save_tree (sizes);
7861
7862 sizes
7863 = tree_cons (NULL_TREE, sizes, tem);
7864 }
7865
7866 if (sizes)
7867 put_pending_sizes (sizes);
7868 }
7869
7870 #else
7871 #if 0
7872 if (adjustable
7873 && (ffesymbol_numentries (s)
7874 != ffecom_num_entrypoints_ + 1))
7875 DECL_SOMETHING (t)
7876 = ffecom_2 (NE_EXPR, integer_type_node,
7877 t,
7878 null_pointer_node);
7879 #else
7880 #if 0
7881 if (adjustable
7882 && (ffesymbol_numentries (s)
7883 != ffecom_num_entrypoints_ + 1))
7884 {
7885 ffebad_start (FFEBAD_MISSING_ADJARRAY_UNSUPPORTED);
7886 ffebad_here (0, ffesymbol_where_line (s),
7887 ffesymbol_where_column (s));
7888 ffebad_string (ffesymbol_text (s));
7889 ffebad_finish ();
7890 }
7891 #endif
7892 #endif
7893 #endif
7894 }
7895 break;
7896
7897 case FFEINFO_whereCOMMON:
7898 {
7899 ffesymbol cs;
7900 ffeglobal cg;
7901 tree ct;
7902 ffestorag st = ffesymbol_storage (s);
7903 tree type;
7904
7905 cs = ffesymbol_common (s); /* The COMMON area itself. */
7906 if (st != NULL) /* Else not laid out. */
7907 {
7908 ffecom_transform_common_ (cs);
7909 st = ffesymbol_storage (s);
7910 }
7911
7912 type = ffecom_type_localvar_ (s, bt, kt);
7913
7914 cg = ffesymbol_global (cs); /* The global COMMON info. */
7915 if ((cg == NULL)
7916 || (ffeglobal_type (cg) != FFEGLOBAL_typeCOMMON))
7917 ct = NULL_TREE;
7918 else
7919 ct = ffeglobal_hook (cg); /* The common area's tree. */
7920
7921 if ((ct == NULL_TREE)
7922 || (st == NULL)
7923 || (type == error_mark_node))
7924 t = error_mark_node;
7925 else
7926 {
7927 ffetargetOffset offset;
7928 ffestorag cst;
7929
7930 cst = ffestorag_parent (st);
7931 assert (cst == ffesymbol_storage (cs));
7932
7933 offset = ffestorag_modulo (cst)
7934 + ffestorag_offset (st)
7935 - ffestorag_offset (cst);
7936
7937 ffecom_debug_kludge_ (ct, "COMMON", s, type, offset);
7938
7939 /* (t_type *) (((char *) &ct) + offset) */
7940
7941 t = convert (string_type_node, /* (char *) */
7942 ffecom_1 (ADDR_EXPR,
7943 build_pointer_type (TREE_TYPE (ct)),
7944 ct));
7945 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
7946 t,
7947 build_int_2 (offset, 0));
7948 t = convert (build_pointer_type (type),
7949 t);
7950 TREE_CONSTANT (t) = 1;
7951
7952 addr = TRUE;
7953 }
7954 }
7955 break;
7956
7957 case FFEINFO_whereIMMEDIATE:
7958 case FFEINFO_whereGLOBAL:
7959 case FFEINFO_whereFLEETING:
7960 case FFEINFO_whereFLEETING_CADDR:
7961 case FFEINFO_whereFLEETING_IADDR:
7962 case FFEINFO_whereINTRINSIC:
7963 case FFEINFO_whereCONSTANT_SUBOBJECT:
7964 default:
7965 assert ("ENTITY where unheard of" == NULL);
7966 /* Fall through. */
7967 case FFEINFO_whereANY:
7968 t = error_mark_node;
7969 break;
7970 }
7971 break;
7972
7973 case FFEINFO_kindFUNCTION:
7974 switch (ffeinfo_where (ffesymbol_info (s)))
7975 {
7976 case FFEINFO_whereLOCAL: /* Me. */
7977 assert (!ffecom_transform_only_dummies_);
7978 t = current_function_decl;
7979 break;
7980
7981 case FFEINFO_whereGLOBAL:
7982 assert (!ffecom_transform_only_dummies_);
7983
7984 if (((g = ffesymbol_global (s)) != NULL)
7985 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7986 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
7987 && (ffeglobal_hook (g) != NULL_TREE)
7988 && ffe_is_globals ())
7989 {
7990 t = ffeglobal_hook (g);
7991 break;
7992 }
7993
7994 if (ffesymbol_is_f2c (s)
7995 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
7996 t = ffecom_tree_fun_type[bt][kt];
7997 else
7998 t = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
7999
8000 t = build_decl (FUNCTION_DECL,
8001 ffecom_get_external_identifier_ (s),
8002 t);
8003 DECL_EXTERNAL (t) = 1;
8004 TREE_PUBLIC (t) = 1;
8005
8006 t = start_decl (t, FALSE);
8007 finish_decl (t, NULL_TREE, FALSE);
8008
8009 if ((g != NULL)
8010 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8011 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8012 ffeglobal_set_hook (g, t);
8013
8014 ffecom_save_tree_forever (t);
8015
8016 break;
8017
8018 case FFEINFO_whereDUMMY:
8019 assert (ffecom_transform_only_dummies_);
8020
8021 if (ffesymbol_is_f2c (s)
8022 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8023 t = ffecom_tree_ptr_to_fun_type[bt][kt];
8024 else
8025 t = build_pointer_type
8026 (build_function_type (ffecom_tree_type[bt][kt], NULL_TREE));
8027
8028 t = build_decl (PARM_DECL,
8029 ffecom_get_identifier_ (ffesymbol_text (s)),
8030 t);
8031 DECL_ARTIFICIAL (t) = 1;
8032 addr = TRUE;
8033 break;
8034
8035 case FFEINFO_whereCONSTANT: /* Statement function. */
8036 assert (!ffecom_transform_only_dummies_);
8037 t = ffecom_gen_sfuncdef_ (s, bt, kt);
8038 break;
8039
8040 case FFEINFO_whereINTRINSIC:
8041 assert (!ffecom_transform_only_dummies_);
8042 break; /* Let actual references generate their
8043 decls. */
8044
8045 default:
8046 assert ("FUNCTION where unheard of" == NULL);
8047 /* Fall through. */
8048 case FFEINFO_whereANY:
8049 t = error_mark_node;
8050 break;
8051 }
8052 break;
8053
8054 case FFEINFO_kindSUBROUTINE:
8055 switch (ffeinfo_where (ffesymbol_info (s)))
8056 {
8057 case FFEINFO_whereLOCAL: /* Me. */
8058 assert (!ffecom_transform_only_dummies_);
8059 t = current_function_decl;
8060 break;
8061
8062 case FFEINFO_whereGLOBAL:
8063 assert (!ffecom_transform_only_dummies_);
8064
8065 if (((g = ffesymbol_global (s)) != NULL)
8066 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8067 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8068 && (ffeglobal_hook (g) != NULL_TREE)
8069 && ffe_is_globals ())
8070 {
8071 t = ffeglobal_hook (g);
8072 break;
8073 }
8074
8075 t = build_decl (FUNCTION_DECL,
8076 ffecom_get_external_identifier_ (s),
8077 ffecom_tree_subr_type);
8078 DECL_EXTERNAL (t) = 1;
8079 TREE_PUBLIC (t) = 1;
8080
8081 t = start_decl (t, TRUE);
8082 finish_decl (t, NULL_TREE, TRUE);
8083
8084 if ((g != NULL)
8085 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8086 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8087 ffeglobal_set_hook (g, t);
8088
8089 ffecom_save_tree_forever (t);
8090
8091 break;
8092
8093 case FFEINFO_whereDUMMY:
8094 assert (ffecom_transform_only_dummies_);
8095
8096 t = build_decl (PARM_DECL,
8097 ffecom_get_identifier_ (ffesymbol_text (s)),
8098 ffecom_tree_ptr_to_subr_type);
8099 DECL_ARTIFICIAL (t) = 1;
8100 addr = TRUE;
8101 break;
8102
8103 case FFEINFO_whereINTRINSIC:
8104 assert (!ffecom_transform_only_dummies_);
8105 break; /* Let actual references generate their
8106 decls. */
8107
8108 default:
8109 assert ("SUBROUTINE where unheard of" == NULL);
8110 /* Fall through. */
8111 case FFEINFO_whereANY:
8112 t = error_mark_node;
8113 break;
8114 }
8115 break;
8116
8117 case FFEINFO_kindPROGRAM:
8118 switch (ffeinfo_where (ffesymbol_info (s)))
8119 {
8120 case FFEINFO_whereLOCAL: /* Me. */
8121 assert (!ffecom_transform_only_dummies_);
8122 t = current_function_decl;
8123 break;
8124
8125 case FFEINFO_whereCOMMON:
8126 case FFEINFO_whereDUMMY:
8127 case FFEINFO_whereGLOBAL:
8128 case FFEINFO_whereRESULT:
8129 case FFEINFO_whereFLEETING:
8130 case FFEINFO_whereFLEETING_CADDR:
8131 case FFEINFO_whereFLEETING_IADDR:
8132 case FFEINFO_whereIMMEDIATE:
8133 case FFEINFO_whereINTRINSIC:
8134 case FFEINFO_whereCONSTANT:
8135 case FFEINFO_whereCONSTANT_SUBOBJECT:
8136 default:
8137 assert ("PROGRAM where unheard of" == NULL);
8138 /* Fall through. */
8139 case FFEINFO_whereANY:
8140 t = error_mark_node;
8141 break;
8142 }
8143 break;
8144
8145 case FFEINFO_kindBLOCKDATA:
8146 switch (ffeinfo_where (ffesymbol_info (s)))
8147 {
8148 case FFEINFO_whereLOCAL: /* Me. */
8149 assert (!ffecom_transform_only_dummies_);
8150 t = current_function_decl;
8151 break;
8152
8153 case FFEINFO_whereGLOBAL:
8154 assert (!ffecom_transform_only_dummies_);
8155
8156 t = build_decl (FUNCTION_DECL,
8157 ffecom_get_external_identifier_ (s),
8158 ffecom_tree_blockdata_type);
8159 DECL_EXTERNAL (t) = 1;
8160 TREE_PUBLIC (t) = 1;
8161
8162 t = start_decl (t, FALSE);
8163 finish_decl (t, NULL_TREE, FALSE);
8164
8165 ffecom_save_tree_forever (t);
8166
8167 break;
8168
8169 case FFEINFO_whereCOMMON:
8170 case FFEINFO_whereDUMMY:
8171 case FFEINFO_whereRESULT:
8172 case FFEINFO_whereFLEETING:
8173 case FFEINFO_whereFLEETING_CADDR:
8174 case FFEINFO_whereFLEETING_IADDR:
8175 case FFEINFO_whereIMMEDIATE:
8176 case FFEINFO_whereINTRINSIC:
8177 case FFEINFO_whereCONSTANT:
8178 case FFEINFO_whereCONSTANT_SUBOBJECT:
8179 default:
8180 assert ("BLOCKDATA where unheard of" == NULL);
8181 /* Fall through. */
8182 case FFEINFO_whereANY:
8183 t = error_mark_node;
8184 break;
8185 }
8186 break;
8187
8188 case FFEINFO_kindCOMMON:
8189 switch (ffeinfo_where (ffesymbol_info (s)))
8190 {
8191 case FFEINFO_whereLOCAL:
8192 assert (!ffecom_transform_only_dummies_);
8193 ffecom_transform_common_ (s);
8194 break;
8195
8196 case FFEINFO_whereNONE:
8197 case FFEINFO_whereCOMMON:
8198 case FFEINFO_whereDUMMY:
8199 case FFEINFO_whereGLOBAL:
8200 case FFEINFO_whereRESULT:
8201 case FFEINFO_whereFLEETING:
8202 case FFEINFO_whereFLEETING_CADDR:
8203 case FFEINFO_whereFLEETING_IADDR:
8204 case FFEINFO_whereIMMEDIATE:
8205 case FFEINFO_whereINTRINSIC:
8206 case FFEINFO_whereCONSTANT:
8207 case FFEINFO_whereCONSTANT_SUBOBJECT:
8208 default:
8209 assert ("COMMON where unheard of" == NULL);
8210 /* Fall through. */
8211 case FFEINFO_whereANY:
8212 t = error_mark_node;
8213 break;
8214 }
8215 break;
8216
8217 case FFEINFO_kindCONSTRUCT:
8218 switch (ffeinfo_where (ffesymbol_info (s)))
8219 {
8220 case FFEINFO_whereLOCAL:
8221 assert (!ffecom_transform_only_dummies_);
8222 break;
8223
8224 case FFEINFO_whereNONE:
8225 case FFEINFO_whereCOMMON:
8226 case FFEINFO_whereDUMMY:
8227 case FFEINFO_whereGLOBAL:
8228 case FFEINFO_whereRESULT:
8229 case FFEINFO_whereFLEETING:
8230 case FFEINFO_whereFLEETING_CADDR:
8231 case FFEINFO_whereFLEETING_IADDR:
8232 case FFEINFO_whereIMMEDIATE:
8233 case FFEINFO_whereINTRINSIC:
8234 case FFEINFO_whereCONSTANT:
8235 case FFEINFO_whereCONSTANT_SUBOBJECT:
8236 default:
8237 assert ("CONSTRUCT where unheard of" == NULL);
8238 /* Fall through. */
8239 case FFEINFO_whereANY:
8240 t = error_mark_node;
8241 break;
8242 }
8243 break;
8244
8245 case FFEINFO_kindNAMELIST:
8246 switch (ffeinfo_where (ffesymbol_info (s)))
8247 {
8248 case FFEINFO_whereLOCAL:
8249 assert (!ffecom_transform_only_dummies_);
8250 t = ffecom_transform_namelist_ (s);
8251 break;
8252
8253 case FFEINFO_whereNONE:
8254 case FFEINFO_whereCOMMON:
8255 case FFEINFO_whereDUMMY:
8256 case FFEINFO_whereGLOBAL:
8257 case FFEINFO_whereRESULT:
8258 case FFEINFO_whereFLEETING:
8259 case FFEINFO_whereFLEETING_CADDR:
8260 case FFEINFO_whereFLEETING_IADDR:
8261 case FFEINFO_whereIMMEDIATE:
8262 case FFEINFO_whereINTRINSIC:
8263 case FFEINFO_whereCONSTANT:
8264 case FFEINFO_whereCONSTANT_SUBOBJECT:
8265 default:
8266 assert ("NAMELIST where unheard of" == NULL);
8267 /* Fall through. */
8268 case FFEINFO_whereANY:
8269 t = error_mark_node;
8270 break;
8271 }
8272 break;
8273
8274 default:
8275 assert ("kind unheard of" == NULL);
8276 /* Fall through. */
8277 case FFEINFO_kindANY:
8278 t = error_mark_node;
8279 break;
8280 }
8281
8282 ffesymbol_hook (s).decl_tree = t;
8283 ffesymbol_hook (s).length_tree = tlen;
8284 ffesymbol_hook (s).addr = addr;
8285
8286 input_location = old_loc;
8287
8288 return s;
8289 }
8290
8291 /* Transform into ASSIGNable symbol.
8292
8293 Symbol has already been transformed, but for whatever reason, the
8294 resulting decl_tree has been deemed not usable for an ASSIGN target.
8295 (E.g. it isn't wide enough to hold a pointer.) So, here we invent
8296 another local symbol of type void * and stuff that in the assign_tree
8297 argument. The F77/F90 standards allow this implementation. */
8298
8299 static ffesymbol
8300 ffecom_sym_transform_assign_ (ffesymbol s)
8301 {
8302 tree t; /* Transformed thingy. */
8303 location_t old_loc = input_location;
8304
8305 if (ffesymbol_sfdummyparent (s) == NULL)
8306 {
8307 input_filename = ffesymbol_where_filename (s);
8308 input_line = ffesymbol_where_filelinenum (s);
8309 }
8310 else
8311 {
8312 ffesymbol sf = ffesymbol_sfdummyparent (s);
8313
8314 input_filename = ffesymbol_where_filename (sf);
8315 input_line = ffesymbol_where_filelinenum (sf);
8316 }
8317
8318 assert (!ffecom_transform_only_dummies_);
8319
8320 t = build_decl (VAR_DECL,
8321 ffecom_get_invented_identifier ("__g77_ASSIGN_%s",
8322 ffesymbol_text (s)),
8323 TREE_TYPE (null_pointer_node));
8324
8325 switch (ffesymbol_where (s))
8326 {
8327 case FFEINFO_whereLOCAL:
8328 /* Unlike for regular vars, SAVE status is easy to determine for
8329 ASSIGNed vars, since there's no initialization, there's no
8330 effective storage association (so "SAVE J" does not apply to
8331 K even given "EQUIVALENCE (J,K)"), there's no size issue
8332 to worry about, etc. */
8333 if ((ffesymbol_is_save (s) || ffe_is_saveall ())
8334 && (ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8335 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA))
8336 TREE_STATIC (t) = 1; /* SAVEd in proc, make static. */
8337 else
8338 TREE_STATIC (t) = 0; /* No need to make static. */
8339 break;
8340
8341 case FFEINFO_whereCOMMON:
8342 TREE_STATIC (t) = 1; /* Assume COMMONs always SAVEd. */
8343 break;
8344
8345 case FFEINFO_whereDUMMY:
8346 /* Note that twinning a DUMMY means the caller won't see
8347 the ASSIGNed value. But both F77 and F90 allow implementations
8348 to do this, i.e. disallow Fortran code that would try and
8349 take advantage of actually putting a label into a variable
8350 via a dummy argument (or any other storage association, for
8351 that matter). */
8352 TREE_STATIC (t) = 0;
8353 break;
8354
8355 default:
8356 TREE_STATIC (t) = 0;
8357 break;
8358 }
8359
8360 t = start_decl (t, FALSE);
8361 finish_decl (t, NULL_TREE, FALSE);
8362
8363 ffesymbol_hook (s).assign_tree = t;
8364
8365 input_location = old_loc;
8366
8367 return s;
8368 }
8369
8370 /* Implement COMMON area in back end.
8371
8372 Because COMMON-based variables can be referenced in the dimension
8373 expressions of dummy (adjustable) arrays, and because dummies
8374 (in the gcc back end) need to be put in the outer binding level
8375 of a function (which has two binding levels, the outer holding
8376 the dummies and the inner holding the other vars), special care
8377 must be taken to handle COMMON areas.
8378
8379 The current strategy is basically to always tell the back end about
8380 the COMMON area as a top-level external reference to just a block
8381 of storage of the master type of that area (e.g. integer, real,
8382 character, whatever -- not a structure). As a distinct action,
8383 if initial values are provided, tell the back end about the area
8384 as a top-level non-external (initialized) area and remember not to
8385 allow further initialization or expansion of the area. Meanwhile,
8386 if no initialization happens at all, tell the back end about
8387 the largest size we've seen declared so the space does get reserved.
8388 (This function doesn't handle all that stuff, but it does some
8389 of the important things.)
8390
8391 Meanwhile, for COMMON variables themselves, just keep creating
8392 references like *((float *) (&common_area + offset)) each time
8393 we reference the variable. In other words, don't make a VAR_DECL
8394 or any kind of component reference (like we used to do before 0.4),
8395 though we might do that as well just for debugging purposes (and
8396 stuff the rtl with the appropriate offset expression). */
8397
8398 static void
8399 ffecom_transform_common_ (ffesymbol s)
8400 {
8401 ffestorag st = ffesymbol_storage (s);
8402 ffeglobal g = ffesymbol_global (s);
8403 tree cbt;
8404 tree cbtype;
8405 tree init;
8406 tree high;
8407 bool is_init = ffestorag_is_init (st);
8408
8409 assert (st != NULL);
8410
8411 if ((g == NULL)
8412 || (ffeglobal_type (g) != FFEGLOBAL_typeCOMMON))
8413 return;
8414
8415 /* First update the size of the area in global terms. */
8416
8417 ffeglobal_size_common (s, ffestorag_size (st));
8418
8419 if (!ffeglobal_common_init (g))
8420 is_init = FALSE; /* No explicit init, don't let erroneous joins init. */
8421
8422 cbt = ffeglobal_hook (g);
8423
8424 /* If we already have declared this common block for a previous program
8425 unit, and either we already initialized it or we don't have new
8426 initialization for it, just return what we have without changing it. */
8427
8428 if ((cbt != NULL_TREE)
8429 && (!is_init
8430 || !DECL_EXTERNAL (cbt)))
8431 {
8432 if (st->hook == NULL) ffestorag_set_hook (st, cbt);
8433 return;
8434 }
8435
8436 /* Process inits. */
8437
8438 if (is_init)
8439 {
8440 if (ffestorag_init (st) != NULL)
8441 {
8442 ffebld sexp;
8443
8444 /* Set the padding for the expression, so ffecom_expr
8445 knows to insert that many zeros. */
8446 switch (ffebld_op (sexp = ffestorag_init (st)))
8447 {
8448 case FFEBLD_opCONTER:
8449 ffebld_conter_set_pad (sexp, ffestorag_modulo (st));
8450 break;
8451
8452 case FFEBLD_opARRTER:
8453 ffebld_arrter_set_pad (sexp, ffestorag_modulo (st));
8454 break;
8455
8456 case FFEBLD_opACCTER:
8457 ffebld_accter_set_pad (sexp, ffestorag_modulo (st));
8458 break;
8459
8460 default:
8461 assert ("bad op for cmn init (pad)" == NULL);
8462 break;
8463 }
8464
8465 init = ffecom_expr (sexp);
8466 if (init == error_mark_node)
8467 { /* Hopefully the back end complained! */
8468 init = NULL_TREE;
8469 if (cbt != NULL_TREE)
8470 return;
8471 }
8472 }
8473 else
8474 init = error_mark_node;
8475 }
8476 else
8477 init = NULL_TREE;
8478
8479 /* cbtype must be permanently allocated! */
8480
8481 /* Allocate the MAX of the areas so far, seen filewide. */
8482 high = build_int_2 ((ffeglobal_common_size (g)
8483 + ffeglobal_common_pad (g)) - 1, 0);
8484 TREE_TYPE (high) = ffecom_integer_type_node;
8485
8486 if (init)
8487 cbtype = build_array_type (char_type_node,
8488 build_range_type (integer_type_node,
8489 integer_zero_node,
8490 high));
8491 else
8492 cbtype = build_array_type (char_type_node, NULL_TREE);
8493
8494 if (cbt == NULL_TREE)
8495 {
8496 cbt
8497 = build_decl (VAR_DECL,
8498 ffecom_get_external_identifier_ (s),
8499 cbtype);
8500 TREE_STATIC (cbt) = 1;
8501 TREE_PUBLIC (cbt) = 1;
8502 }
8503 else
8504 {
8505 assert (is_init);
8506 TREE_TYPE (cbt) = cbtype;
8507 }
8508 DECL_EXTERNAL (cbt) = init ? 0 : 1;
8509 DECL_INITIAL (cbt) = init ? error_mark_node : NULL_TREE;
8510
8511 cbt = start_decl (cbt, TRUE);
8512 if (ffeglobal_hook (g) != NULL)
8513 assert (cbt == ffeglobal_hook (g));
8514
8515 assert (!init || !DECL_EXTERNAL (cbt));
8516
8517 /* Make sure that any type can live in COMMON and be referenced
8518 without getting a bus error. We could pick the most restrictive
8519 alignment of all entities actually placed in the COMMON, but
8520 this seems easy enough. */
8521
8522 DECL_ALIGN (cbt) = BIGGEST_ALIGNMENT;
8523 DECL_USER_ALIGN (cbt) = 0;
8524
8525 if (is_init && (ffestorag_init (st) == NULL))
8526 init = ffecom_init_zero_ (cbt);
8527
8528 finish_decl (cbt, init, TRUE);
8529
8530 if (is_init)
8531 ffestorag_set_init (st, ffebld_new_any ());
8532
8533 if (init)
8534 {
8535 assert (DECL_SIZE_UNIT (cbt) != NULL_TREE);
8536 assert (TREE_CODE (DECL_SIZE_UNIT (cbt)) == INTEGER_CST);
8537 assert (0 == compare_tree_int (DECL_SIZE_UNIT (cbt),
8538 (ffeglobal_common_size (g)
8539 + ffeglobal_common_pad (g))));
8540 }
8541
8542 ffeglobal_set_hook (g, cbt);
8543
8544 ffestorag_set_hook (st, cbt);
8545
8546 ffecom_save_tree_forever (cbt);
8547 }
8548
8549 /* Make master area for local EQUIVALENCE. */
8550
8551 static void
8552 ffecom_transform_equiv_ (ffestorag eqst)
8553 {
8554 tree eqt;
8555 tree eqtype;
8556 tree init;
8557 tree high;
8558 bool is_init = ffestorag_is_init (eqst);
8559
8560 assert (eqst != NULL);
8561
8562 eqt = ffestorag_hook (eqst);
8563
8564 if (eqt != NULL_TREE)
8565 return;
8566
8567 /* Process inits. */
8568
8569 if (is_init)
8570 {
8571 if (ffestorag_init (eqst) != NULL)
8572 {
8573 ffebld sexp;
8574
8575 /* Set the padding for the expression, so ffecom_expr
8576 knows to insert that many zeros. */
8577 switch (ffebld_op (sexp = ffestorag_init (eqst)))
8578 {
8579 case FFEBLD_opCONTER:
8580 ffebld_conter_set_pad (sexp, ffestorag_modulo (eqst));
8581 break;
8582
8583 case FFEBLD_opARRTER:
8584 ffebld_arrter_set_pad (sexp, ffestorag_modulo (eqst));
8585 break;
8586
8587 case FFEBLD_opACCTER:
8588 ffebld_accter_set_pad (sexp, ffestorag_modulo (eqst));
8589 break;
8590
8591 default:
8592 assert ("bad op for eqv init (pad)" == NULL);
8593 break;
8594 }
8595
8596 init = ffecom_expr (sexp);
8597 if (init == error_mark_node)
8598 init = NULL_TREE; /* Hopefully the back end complained! */
8599 }
8600 else
8601 init = error_mark_node;
8602 }
8603 else if (ffe_is_init_local_zero ())
8604 init = error_mark_node;
8605 else
8606 init = NULL_TREE;
8607
8608 ffecom_member_namelisted_ = FALSE;
8609 ffestorag_drive (ffestorag_list_equivs (eqst),
8610 &ffecom_member_phase1_,
8611 eqst);
8612
8613 high = build_int_2 ((ffestorag_size (eqst)
8614 + ffestorag_modulo (eqst)) - 1, 0);
8615 TREE_TYPE (high) = ffecom_integer_type_node;
8616
8617 eqtype = build_array_type (char_type_node,
8618 build_range_type (ffecom_integer_type_node,
8619 ffecom_integer_zero_node,
8620 high));
8621
8622 eqt = build_decl (VAR_DECL,
8623 ffecom_get_invented_identifier ("__g77_equiv_%s",
8624 ffesymbol_text
8625 (ffestorag_symbol (eqst))),
8626 eqtype);
8627 DECL_EXTERNAL (eqt) = 0;
8628 if (is_init
8629 || ffecom_member_namelisted_
8630 #ifdef FFECOM_sizeMAXSTACKITEM
8631 || (ffestorag_size (eqst) > FFECOM_sizeMAXSTACKITEM)
8632 #endif
8633 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8634 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
8635 && (ffestorag_is_save (eqst) || ffe_is_saveall ())))
8636 TREE_STATIC (eqt) = 1;
8637 else
8638 TREE_STATIC (eqt) = 0;
8639 TREE_PUBLIC (eqt) = 0;
8640 TREE_ADDRESSABLE (eqt) = 1; /* Ensure non-register allocation */
8641 DECL_CONTEXT (eqt) = current_function_decl;
8642 if (init)
8643 DECL_INITIAL (eqt) = error_mark_node;
8644 else
8645 DECL_INITIAL (eqt) = NULL_TREE;
8646
8647 eqt = start_decl (eqt, FALSE);
8648
8649 /* Make sure that any type can live in EQUIVALENCE and be referenced
8650 without getting a bus error. We could pick the most restrictive
8651 alignment of all entities actually placed in the EQUIVALENCE, but
8652 this seems easy enough. */
8653
8654 DECL_ALIGN (eqt) = BIGGEST_ALIGNMENT;
8655 DECL_USER_ALIGN (eqt) = 0;
8656
8657 if ((!is_init && ffe_is_init_local_zero ())
8658 || (is_init && (ffestorag_init (eqst) == NULL)))
8659 init = ffecom_init_zero_ (eqt);
8660
8661 finish_decl (eqt, init, FALSE);
8662
8663 if (is_init)
8664 ffestorag_set_init (eqst, ffebld_new_any ());
8665
8666 {
8667 assert (TREE_CODE (DECL_SIZE_UNIT (eqt)) == INTEGER_CST);
8668 assert (0 == compare_tree_int (DECL_SIZE_UNIT (eqt),
8669 (ffestorag_size (eqst)
8670 + ffestorag_modulo (eqst))));
8671 }
8672
8673 ffestorag_set_hook (eqst, eqt);
8674
8675 ffestorag_drive (ffestorag_list_equivs (eqst),
8676 &ffecom_member_phase2_,
8677 eqst);
8678 }
8679
8680 /* Implement NAMELIST in back end. See f2c/format.c for more info. */
8681
8682 static tree
8683 ffecom_transform_namelist_ (ffesymbol s)
8684 {
8685 tree nmlt;
8686 tree nmltype = ffecom_type_namelist_ ();
8687 tree nmlinits;
8688 tree nameinit;
8689 tree varsinit;
8690 tree nvarsinit;
8691 tree field;
8692 tree high;
8693 int i;
8694 static int mynumber = 0;
8695
8696 nmlt = build_decl (VAR_DECL,
8697 ffecom_get_invented_identifier ("__g77_namelist_%d",
8698 mynumber++),
8699 nmltype);
8700 TREE_STATIC (nmlt) = 1;
8701 DECL_INITIAL (nmlt) = error_mark_node;
8702
8703 nmlt = start_decl (nmlt, FALSE);
8704
8705 /* Process inits. */
8706
8707 i = strlen (ffesymbol_text (s));
8708
8709 high = build_int_2 (i, 0);
8710 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
8711
8712 nameinit = ffecom_build_f2c_string_ (i + 1,
8713 ffesymbol_text (s));
8714 TREE_TYPE (nameinit)
8715 = build_type_variant
8716 (build_array_type
8717 (char_type_node,
8718 build_range_type (ffecom_f2c_ftnlen_type_node,
8719 ffecom_f2c_ftnlen_one_node,
8720 high)),
8721 1, 0);
8722 TREE_CONSTANT (nameinit) = 1;
8723 TREE_STATIC (nameinit) = 1;
8724 nameinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (nameinit)),
8725 nameinit);
8726
8727 varsinit = ffecom_vardesc_array_ (s);
8728 varsinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (varsinit)),
8729 varsinit);
8730 TREE_CONSTANT (varsinit) = 1;
8731 TREE_STATIC (varsinit) = 1;
8732
8733 {
8734 ffebld b;
8735
8736 for (i = 0, b = ffesymbol_namelist (s); b != NULL; b = ffebld_trail (b))
8737 ++i;
8738 }
8739 nvarsinit = build_int_2 (i, 0);
8740 TREE_TYPE (nvarsinit) = integer_type_node;
8741 TREE_CONSTANT (nvarsinit) = 1;
8742 TREE_STATIC (nvarsinit) = 1;
8743
8744 nmlinits = build_tree_list ((field = TYPE_FIELDS (nmltype)), nameinit);
8745 TREE_CHAIN (nmlinits) = build_tree_list ((field = TREE_CHAIN (field)),
8746 varsinit);
8747 TREE_CHAIN (TREE_CHAIN (nmlinits))
8748 = build_tree_list ((field = TREE_CHAIN (field)), nvarsinit);
8749
8750 nmlinits = build_constructor (nmltype, nmlinits);
8751 TREE_CONSTANT (nmlinits) = 1;
8752 TREE_STATIC (nmlinits) = 1;
8753
8754 finish_decl (nmlt, nmlinits, FALSE);
8755
8756 nmlt = ffecom_1 (ADDR_EXPR, build_pointer_type (nmltype), nmlt);
8757
8758 return nmlt;
8759 }
8760
8761 /* A subroutine of ffecom_tree_canonize_ref_. The incoming tree is
8762 analyzed on the assumption it is calculating a pointer to be
8763 indirected through. It must return the proper decl and offset,
8764 taking into account different units of measurements for offsets. */
8765
8766 static void
8767 ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
8768 tree t)
8769 {
8770 switch (TREE_CODE (t))
8771 {
8772 case NOP_EXPR:
8773 case CONVERT_EXPR:
8774 case NON_LVALUE_EXPR:
8775 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
8776 break;
8777
8778 case PLUS_EXPR:
8779 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
8780 if ((*decl == NULL_TREE)
8781 || (*decl == error_mark_node))
8782 break;
8783
8784 if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST)
8785 {
8786 /* An offset into COMMON. */
8787 *offset = fold (build (PLUS_EXPR, TREE_TYPE (*offset),
8788 *offset, TREE_OPERAND (t, 1)));
8789 /* Convert offset (presumably in bytes) into canonical units
8790 (presumably bits). */
8791 *offset = size_binop (MULT_EXPR,
8792 convert (bitsizetype, *offset),
8793 TYPE_SIZE (TREE_TYPE (TREE_TYPE (t))));
8794 break;
8795 }
8796 /* Not a COMMON reference, so an unrecognized pattern. */
8797 *decl = error_mark_node;
8798 break;
8799
8800 case PARM_DECL:
8801 *decl = t;
8802 *offset = bitsize_zero_node;
8803 break;
8804
8805 case ADDR_EXPR:
8806 if (TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL)
8807 {
8808 /* A reference to COMMON. */
8809 *decl = TREE_OPERAND (t, 0);
8810 *offset = bitsize_zero_node;
8811 break;
8812 }
8813 /* Fall through. */
8814 default:
8815 /* Not a COMMON reference, so an unrecognized pattern. */
8816 *decl = error_mark_node;
8817 break;
8818 }
8819 }
8820
8821 /* Given a tree that is possibly intended for use as an lvalue, return
8822 information representing a canonical view of that tree as a decl, an
8823 offset into that decl, and a size for the lvalue.
8824
8825 If there's no applicable decl, NULL_TREE is returned for the decl,
8826 and the other fields are left undefined.
8827
8828 If the tree doesn't fit the recognizable forms, an ERROR_MARK node
8829 is returned for the decl, and the other fields are left undefined.
8830
8831 Otherwise, the decl returned currently is either a VAR_DECL or a
8832 PARM_DECL.
8833
8834 The offset returned is always valid, but of course not necessarily
8835 a constant, and not necessarily converted into the appropriate
8836 type, leaving that up to the caller (so as to avoid that overhead
8837 if the decls being looked at are different anyway).
8838
8839 If the size cannot be determined (e.g. an adjustable array),
8840 an ERROR_MARK node is returned for the size. Otherwise, the
8841 size returned is valid, not necessarily a constant, and not
8842 necessarily converted into the appropriate type as with the
8843 offset.
8844
8845 Note that the offset and size expressions are expressed in the
8846 base storage units (usually bits) rather than in the units of
8847 the type of the decl, because two decls with different types
8848 might overlap but with apparently non-overlapping array offsets,
8849 whereas converting the array offsets to consistant offsets will
8850 reveal the overlap. */
8851
8852 static void
8853 ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
8854 tree *size, tree t)
8855 {
8856 /* The default path is to report a nonexistant decl. */
8857 *decl = NULL_TREE;
8858
8859 if (t == NULL_TREE)
8860 return;
8861
8862 switch (TREE_CODE (t))
8863 {
8864 case ERROR_MARK:
8865 case IDENTIFIER_NODE:
8866 case INTEGER_CST:
8867 case REAL_CST:
8868 case COMPLEX_CST:
8869 case STRING_CST:
8870 case CONST_DECL:
8871 case PLUS_EXPR:
8872 case MINUS_EXPR:
8873 case MULT_EXPR:
8874 case TRUNC_DIV_EXPR:
8875 case CEIL_DIV_EXPR:
8876 case FLOOR_DIV_EXPR:
8877 case ROUND_DIV_EXPR:
8878 case TRUNC_MOD_EXPR:
8879 case CEIL_MOD_EXPR:
8880 case FLOOR_MOD_EXPR:
8881 case ROUND_MOD_EXPR:
8882 case RDIV_EXPR:
8883 case EXACT_DIV_EXPR:
8884 case FIX_TRUNC_EXPR:
8885 case FIX_CEIL_EXPR:
8886 case FIX_FLOOR_EXPR:
8887 case FIX_ROUND_EXPR:
8888 case FLOAT_EXPR:
8889 case NEGATE_EXPR:
8890 case MIN_EXPR:
8891 case MAX_EXPR:
8892 case ABS_EXPR:
8893 case FFS_EXPR:
8894 case LSHIFT_EXPR:
8895 case RSHIFT_EXPR:
8896 case LROTATE_EXPR:
8897 case RROTATE_EXPR:
8898 case BIT_IOR_EXPR:
8899 case BIT_XOR_EXPR:
8900 case BIT_AND_EXPR:
8901 case BIT_ANDTC_EXPR:
8902 case BIT_NOT_EXPR:
8903 case TRUTH_ANDIF_EXPR:
8904 case TRUTH_ORIF_EXPR:
8905 case TRUTH_AND_EXPR:
8906 case TRUTH_OR_EXPR:
8907 case TRUTH_XOR_EXPR:
8908 case TRUTH_NOT_EXPR:
8909 case LT_EXPR:
8910 case LE_EXPR:
8911 case GT_EXPR:
8912 case GE_EXPR:
8913 case EQ_EXPR:
8914 case NE_EXPR:
8915 case COMPLEX_EXPR:
8916 case CONJ_EXPR:
8917 case REALPART_EXPR:
8918 case IMAGPART_EXPR:
8919 case LABEL_EXPR:
8920 case COMPONENT_REF:
8921 case COMPOUND_EXPR:
8922 case ADDR_EXPR:
8923 return;
8924
8925 case VAR_DECL:
8926 case PARM_DECL:
8927 *decl = t;
8928 *offset = bitsize_zero_node;
8929 *size = TYPE_SIZE (TREE_TYPE (t));
8930 return;
8931
8932 case ARRAY_REF:
8933 {
8934 tree array = TREE_OPERAND (t, 0);
8935 tree element = TREE_OPERAND (t, 1);
8936 tree init_offset;
8937
8938 if ((array == NULL_TREE)
8939 || (element == NULL_TREE))
8940 {
8941 *decl = error_mark_node;
8942 return;
8943 }
8944
8945 ffecom_tree_canonize_ref_ (decl, &init_offset, size,
8946 array);
8947 if ((*decl == NULL_TREE)
8948 || (*decl == error_mark_node))
8949 return;
8950
8951 /* Calculate ((element - base) * NBBY) + init_offset. */
8952 *offset = fold (build (MINUS_EXPR, TREE_TYPE (element),
8953 element,
8954 TYPE_MIN_VALUE (TYPE_DOMAIN
8955 (TREE_TYPE (array)))));
8956
8957 *offset = size_binop (MULT_EXPR,
8958 convert (bitsizetype, *offset),
8959 TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))));
8960
8961 *offset = size_binop (PLUS_EXPR, init_offset, *offset);
8962
8963 *size = TYPE_SIZE (TREE_TYPE (t));
8964 return;
8965 }
8966
8967 case INDIRECT_REF:
8968
8969 /* Most of this code is to handle references to COMMON. And so
8970 far that is useful only for calling library functions, since
8971 external (user) functions might reference common areas. But
8972 even calling an external function, it's worthwhile to decode
8973 COMMON references because if not storing into COMMON, we don't
8974 want COMMON-based arguments to gratuitously force use of a
8975 temporary. */
8976
8977 *size = TYPE_SIZE (TREE_TYPE (t));
8978
8979 ffecom_tree_canonize_ptr_ (decl, offset,
8980 TREE_OPERAND (t, 0));
8981
8982 return;
8983
8984 case CONVERT_EXPR:
8985 case NOP_EXPR:
8986 case MODIFY_EXPR:
8987 case NON_LVALUE_EXPR:
8988 case RESULT_DECL:
8989 case FIELD_DECL:
8990 case COND_EXPR: /* More cases than we can handle. */
8991 case SAVE_EXPR:
8992 case REFERENCE_EXPR:
8993 case PREDECREMENT_EXPR:
8994 case PREINCREMENT_EXPR:
8995 case POSTDECREMENT_EXPR:
8996 case POSTINCREMENT_EXPR:
8997 case CALL_EXPR:
8998 default:
8999 *decl = error_mark_node;
9000 return;
9001 }
9002 }
9003
9004 /* Do divide operation appropriate to type of operands. */
9005
9006 static tree
9007 ffecom_tree_divide_ (tree tree_type, tree left, tree right,
9008 tree dest_tree, ffebld dest, bool *dest_used,
9009 tree hook)
9010 {
9011 if ((left == error_mark_node)
9012 || (right == error_mark_node))
9013 return error_mark_node;
9014
9015 switch (TREE_CODE (tree_type))
9016 {
9017 case INTEGER_TYPE:
9018 return ffecom_2 (TRUNC_DIV_EXPR, tree_type,
9019 left,
9020 right);
9021
9022 case COMPLEX_TYPE:
9023 if (! optimize_size)
9024 return ffecom_2 (RDIV_EXPR, tree_type,
9025 left,
9026 right);
9027 {
9028 ffecomGfrt ix;
9029
9030 if (TREE_TYPE (tree_type)
9031 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9032 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9033 else
9034 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
9035
9036 left = ffecom_1 (ADDR_EXPR,
9037 build_pointer_type (TREE_TYPE (left)),
9038 left);
9039 left = build_tree_list (NULL_TREE, left);
9040 right = ffecom_1 (ADDR_EXPR,
9041 build_pointer_type (TREE_TYPE (right)),
9042 right);
9043 right = build_tree_list (NULL_TREE, right);
9044 TREE_CHAIN (left) = right;
9045
9046 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9047 ffecom_gfrt_kindtype (ix),
9048 ffe_is_f2c_library (),
9049 tree_type,
9050 left,
9051 dest_tree, dest, dest_used,
9052 NULL_TREE, TRUE, hook);
9053 }
9054 break;
9055
9056 case RECORD_TYPE:
9057 {
9058 ffecomGfrt ix;
9059
9060 if (TREE_TYPE (TYPE_FIELDS (tree_type))
9061 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9062 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9063 else
9064 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
9065
9066 left = ffecom_1 (ADDR_EXPR,
9067 build_pointer_type (TREE_TYPE (left)),
9068 left);
9069 left = build_tree_list (NULL_TREE, left);
9070 right = ffecom_1 (ADDR_EXPR,
9071 build_pointer_type (TREE_TYPE (right)),
9072 right);
9073 right = build_tree_list (NULL_TREE, right);
9074 TREE_CHAIN (left) = right;
9075
9076 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9077 ffecom_gfrt_kindtype (ix),
9078 ffe_is_f2c_library (),
9079 tree_type,
9080 left,
9081 dest_tree, dest, dest_used,
9082 NULL_TREE, TRUE, hook);
9083 }
9084 break;
9085
9086 default:
9087 return ffecom_2 (RDIV_EXPR, tree_type,
9088 left,
9089 right);
9090 }
9091 }
9092
9093 /* Build type info for non-dummy variable. */
9094
9095 static tree
9096 ffecom_type_localvar_ (ffesymbol s, ffeinfoBasictype bt,
9097 ffeinfoKindtype kt)
9098 {
9099 tree type;
9100 ffebld dl;
9101 ffebld dim;
9102 tree lowt;
9103 tree hight;
9104
9105 type = ffecom_tree_type[bt][kt];
9106 if (bt == FFEINFO_basictypeCHARACTER)
9107 {
9108 hight = build_int_2 (ffesymbol_size (s), 0);
9109 TREE_TYPE (hight) = ffecom_f2c_ftnlen_type_node;
9110
9111 type
9112 = build_array_type
9113 (type,
9114 build_range_type (ffecom_f2c_ftnlen_type_node,
9115 ffecom_f2c_ftnlen_one_node,
9116 hight));
9117 type = ffecom_check_size_overflow_ (s, type, FALSE);
9118 }
9119
9120 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
9121 {
9122 if (type == error_mark_node)
9123 break;
9124
9125 dim = ffebld_head (dl);
9126 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
9127
9128 if (ffebld_left (dim) == NULL)
9129 lowt = integer_one_node;
9130 else
9131 lowt = ffecom_expr (ffebld_left (dim));
9132
9133 if (TREE_CODE (lowt) != INTEGER_CST)
9134 lowt = variable_size (lowt);
9135
9136 assert (ffebld_right (dim) != NULL);
9137 hight = ffecom_expr (ffebld_right (dim));
9138
9139 if (TREE_CODE (hight) != INTEGER_CST)
9140 hight = variable_size (hight);
9141
9142 type = build_array_type (type,
9143 build_range_type (ffecom_integer_type_node,
9144 lowt, hight));
9145 type = ffecom_check_size_overflow_ (s, type, FALSE);
9146 }
9147
9148 return type;
9149 }
9150
9151 /* Build Namelist type. */
9152
9153 static GTY(()) tree ffecom_type_namelist_var;
9154 static tree
9155 ffecom_type_namelist_ ()
9156 {
9157 if (ffecom_type_namelist_var == NULL_TREE)
9158 {
9159 tree namefield, varsfield, nvarsfield, vardesctype, type;
9160
9161 vardesctype = ffecom_type_vardesc_ ();
9162
9163 type = make_node (RECORD_TYPE);
9164
9165 vardesctype = build_pointer_type (build_pointer_type (vardesctype));
9166
9167 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9168 string_type_node);
9169 varsfield = ffecom_decl_field (type, namefield, "vars", vardesctype);
9170 nvarsfield = ffecom_decl_field (type, varsfield, "nvars",
9171 integer_type_node);
9172
9173 TYPE_FIELDS (type) = namefield;
9174 layout_type (type);
9175
9176 ffecom_type_namelist_var = type;
9177 }
9178
9179 return ffecom_type_namelist_var;
9180 }
9181
9182 /* Build Vardesc type. */
9183
9184 static GTY(()) tree ffecom_type_vardesc_var;
9185 static tree
9186 ffecom_type_vardesc_ ()
9187 {
9188 if (ffecom_type_vardesc_var == NULL_TREE)
9189 {
9190 tree namefield, addrfield, dimsfield, typefield, type;
9191 type = make_node (RECORD_TYPE);
9192
9193 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9194 string_type_node);
9195 addrfield = ffecom_decl_field (type, namefield, "addr",
9196 string_type_node);
9197 dimsfield = ffecom_decl_field (type, addrfield, "dims",
9198 ffecom_f2c_ptr_to_ftnlen_type_node);
9199 typefield = ffecom_decl_field (type, dimsfield, "type",
9200 integer_type_node);
9201
9202 TYPE_FIELDS (type) = namefield;
9203 layout_type (type);
9204
9205 ffecom_type_vardesc_var = type;
9206 }
9207
9208 return ffecom_type_vardesc_var;
9209 }
9210
9211 static tree
9212 ffecom_vardesc_ (ffebld expr)
9213 {
9214 ffesymbol s;
9215
9216 assert (ffebld_op (expr) == FFEBLD_opSYMTER);
9217 s = ffebld_symter (expr);
9218
9219 if (ffesymbol_hook (s).vardesc_tree == NULL_TREE)
9220 {
9221 int i;
9222 tree vardesctype = ffecom_type_vardesc_ ();
9223 tree var;
9224 tree nameinit;
9225 tree dimsinit;
9226 tree addrinit;
9227 tree typeinit;
9228 tree field;
9229 tree varinits;
9230 static int mynumber = 0;
9231
9232 var = build_decl (VAR_DECL,
9233 ffecom_get_invented_identifier ("__g77_vardesc_%d",
9234 mynumber++),
9235 vardesctype);
9236 TREE_STATIC (var) = 1;
9237 DECL_INITIAL (var) = error_mark_node;
9238
9239 var = start_decl (var, FALSE);
9240
9241 /* Process inits. */
9242
9243 nameinit = ffecom_build_f2c_string_ ((i = strlen (ffesymbol_text (s)))
9244 + 1,
9245 ffesymbol_text (s));
9246 TREE_TYPE (nameinit)
9247 = build_type_variant
9248 (build_array_type
9249 (char_type_node,
9250 build_range_type (integer_type_node,
9251 integer_one_node,
9252 build_int_2 (i, 0))),
9253 1, 0);
9254 TREE_CONSTANT (nameinit) = 1;
9255 TREE_STATIC (nameinit) = 1;
9256 nameinit = ffecom_1 (ADDR_EXPR,
9257 build_pointer_type (TREE_TYPE (nameinit)),
9258 nameinit);
9259
9260 addrinit = ffecom_arg_ptr_to_expr (expr, &typeinit);
9261
9262 dimsinit = ffecom_vardesc_dims_ (s);
9263
9264 if (typeinit == NULL_TREE)
9265 {
9266 ffeinfoBasictype bt = ffesymbol_basictype (s);
9267 ffeinfoKindtype kt = ffesymbol_kindtype (s);
9268 int tc = ffecom_f2c_typecode (bt, kt);
9269
9270 assert (tc != -1);
9271 typeinit = build_int_2 (tc, (tc < 0) ? -1 : 0);
9272 }
9273 else
9274 typeinit = ffecom_1 (NEGATE_EXPR, TREE_TYPE (typeinit), typeinit);
9275
9276 varinits = build_tree_list ((field = TYPE_FIELDS (vardesctype)),
9277 nameinit);
9278 TREE_CHAIN (varinits) = build_tree_list ((field = TREE_CHAIN (field)),
9279 addrinit);
9280 TREE_CHAIN (TREE_CHAIN (varinits))
9281 = build_tree_list ((field = TREE_CHAIN (field)), dimsinit);
9282 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (varinits)))
9283 = build_tree_list ((field = TREE_CHAIN (field)), typeinit);
9284
9285 varinits = build_constructor (vardesctype, varinits);
9286 TREE_CONSTANT (varinits) = 1;
9287 TREE_STATIC (varinits) = 1;
9288
9289 finish_decl (var, varinits, FALSE);
9290
9291 var = ffecom_1 (ADDR_EXPR, build_pointer_type (vardesctype), var);
9292
9293 ffesymbol_hook (s).vardesc_tree = var;
9294 }
9295
9296 return ffesymbol_hook (s).vardesc_tree;
9297 }
9298
9299 static tree
9300 ffecom_vardesc_array_ (ffesymbol s)
9301 {
9302 ffebld b;
9303 tree list;
9304 tree item = NULL_TREE;
9305 tree var;
9306 int i;
9307 static int mynumber = 0;
9308
9309 for (i = 0, list = NULL_TREE, b = ffesymbol_namelist (s);
9310 b != NULL;
9311 b = ffebld_trail (b), ++i)
9312 {
9313 tree t;
9314
9315 t = ffecom_vardesc_ (ffebld_head (b));
9316
9317 if (list == NULL_TREE)
9318 list = item = build_tree_list (NULL_TREE, t);
9319 else
9320 {
9321 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9322 item = TREE_CHAIN (item);
9323 }
9324 }
9325
9326 item = build_array_type (build_pointer_type (ffecom_type_vardesc_ ()),
9327 build_range_type (integer_type_node,
9328 integer_one_node,
9329 build_int_2 (i, 0)));
9330 list = build_constructor (item, list);
9331 TREE_CONSTANT (list) = 1;
9332 TREE_STATIC (list) = 1;
9333
9334 var = ffecom_get_invented_identifier ("__g77_vardesc_array_%d", mynumber++);
9335 var = build_decl (VAR_DECL, var, item);
9336 TREE_STATIC (var) = 1;
9337 DECL_INITIAL (var) = error_mark_node;
9338 var = start_decl (var, FALSE);
9339 finish_decl (var, list, FALSE);
9340
9341 return var;
9342 }
9343
9344 static tree
9345 ffecom_vardesc_dims_ (ffesymbol s)
9346 {
9347 if (ffesymbol_dims (s) == NULL)
9348 return convert (ffecom_f2c_ptr_to_ftnlen_type_node,
9349 integer_zero_node);
9350
9351 {
9352 ffebld b;
9353 ffebld e;
9354 tree list;
9355 tree backlist;
9356 tree item = NULL_TREE;
9357 tree var;
9358 tree numdim;
9359 tree numelem;
9360 tree baseoff = NULL_TREE;
9361 static int mynumber = 0;
9362
9363 numdim = build_int_2 ((int) ffesymbol_rank (s), 0);
9364 TREE_TYPE (numdim) = ffecom_f2c_ftnlen_type_node;
9365
9366 numelem = ffecom_expr (ffesymbol_arraysize (s));
9367 TREE_TYPE (numelem) = ffecom_f2c_ftnlen_type_node;
9368
9369 list = NULL_TREE;
9370 backlist = NULL_TREE;
9371 for (b = ffesymbol_dims (s), e = ffesymbol_extents (s);
9372 b != NULL;
9373 b = ffebld_trail (b), e = ffebld_trail (e))
9374 {
9375 tree t;
9376 tree low;
9377 tree back;
9378
9379 if (ffebld_trail (b) == NULL)
9380 t = NULL_TREE;
9381 else
9382 {
9383 t = convert (ffecom_f2c_ftnlen_type_node,
9384 ffecom_expr (ffebld_head (e)));
9385
9386 if (list == NULL_TREE)
9387 list = item = build_tree_list (NULL_TREE, t);
9388 else
9389 {
9390 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9391 item = TREE_CHAIN (item);
9392 }
9393 }
9394
9395 if (ffebld_left (ffebld_head (b)) == NULL)
9396 low = ffecom_integer_one_node;
9397 else
9398 low = ffecom_expr (ffebld_left (ffebld_head (b)));
9399 low = convert (ffecom_f2c_ftnlen_type_node, low);
9400
9401 back = build_tree_list (low, t);
9402 TREE_CHAIN (back) = backlist;
9403 backlist = back;
9404 }
9405
9406 for (item = backlist; item != NULL_TREE; item = TREE_CHAIN (item))
9407 {
9408 if (TREE_VALUE (item) == NULL_TREE)
9409 baseoff = TREE_PURPOSE (item);
9410 else
9411 baseoff = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
9412 TREE_PURPOSE (item),
9413 ffecom_2 (MULT_EXPR,
9414 ffecom_f2c_ftnlen_type_node,
9415 TREE_VALUE (item),
9416 baseoff));
9417 }
9418
9419 /* backlist now dead, along with all TREE_PURPOSEs on it. */
9420
9421 baseoff = build_tree_list (NULL_TREE, baseoff);
9422 TREE_CHAIN (baseoff) = list;
9423
9424 numelem = build_tree_list (NULL_TREE, numelem);
9425 TREE_CHAIN (numelem) = baseoff;
9426
9427 numdim = build_tree_list (NULL_TREE, numdim);
9428 TREE_CHAIN (numdim) = numelem;
9429
9430 item = build_array_type (ffecom_f2c_ftnlen_type_node,
9431 build_range_type (integer_type_node,
9432 integer_zero_node,
9433 build_int_2
9434 ((int) ffesymbol_rank (s)
9435 + 2, 0)));
9436 list = build_constructor (item, numdim);
9437 TREE_CONSTANT (list) = 1;
9438 TREE_STATIC (list) = 1;
9439
9440 var = ffecom_get_invented_identifier ("__g77_dims_%d", mynumber++);
9441 var = build_decl (VAR_DECL, var, item);
9442 TREE_STATIC (var) = 1;
9443 DECL_INITIAL (var) = error_mark_node;
9444 var = start_decl (var, FALSE);
9445 finish_decl (var, list, FALSE);
9446
9447 var = ffecom_1 (ADDR_EXPR, build_pointer_type (item), var);
9448
9449 return var;
9450 }
9451 }
9452
9453 /* Essentially does a "fold (build1 (code, type, node))" while checking
9454 for certain housekeeping things.
9455
9456 NOTE: for building an ADDR_EXPR around a FUNCTION_DECL, use
9457 ffecom_1_fn instead. */
9458
9459 tree
9460 ffecom_1 (enum tree_code code, tree type, tree node)
9461 {
9462 tree item;
9463
9464 if ((node == error_mark_node)
9465 || (type == error_mark_node))
9466 return error_mark_node;
9467
9468 if (code == ADDR_EXPR)
9469 {
9470 if (!ffe_mark_addressable (node))
9471 assert ("can't mark_addressable this node!" == NULL);
9472 }
9473
9474 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
9475 {
9476 tree realtype;
9477
9478 case REALPART_EXPR:
9479 item = build (COMPONENT_REF, type, node, TYPE_FIELDS (TREE_TYPE (node)));
9480 break;
9481
9482 case IMAGPART_EXPR:
9483 item = build (COMPONENT_REF, type, node, TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (node))));
9484 break;
9485
9486
9487 case NEGATE_EXPR:
9488 if (TREE_CODE (type) != RECORD_TYPE)
9489 {
9490 item = build1 (code, type, node);
9491 break;
9492 }
9493 node = ffecom_stabilize_aggregate_ (node);
9494 realtype = TREE_TYPE (TYPE_FIELDS (type));
9495 item =
9496 ffecom_2 (COMPLEX_EXPR, type,
9497 ffecom_1 (NEGATE_EXPR, realtype,
9498 ffecom_1 (REALPART_EXPR, realtype,
9499 node)),
9500 ffecom_1 (NEGATE_EXPR, realtype,
9501 ffecom_1 (IMAGPART_EXPR, realtype,
9502 node)));
9503 break;
9504
9505 default:
9506 item = build1 (code, type, node);
9507 break;
9508 }
9509
9510 if (TREE_SIDE_EFFECTS (node))
9511 TREE_SIDE_EFFECTS (item) = 1;
9512 if (code == ADDR_EXPR && staticp (node))
9513 TREE_CONSTANT (item) = 1;
9514 else if (code == INDIRECT_REF)
9515 TREE_READONLY (item) = TYPE_READONLY (type);
9516 return fold (item);
9517 }
9518
9519 /* Like ffecom_1 (ADDR_EXPR, TREE_TYPE (node), node), except
9520 handles TREE_CODE (node) == FUNCTION_DECL. In particular,
9521 does not set TREE_ADDRESSABLE (because calling an inline
9522 function does not mean the function needs to be separately
9523 compiled). */
9524
9525 tree
9526 ffecom_1_fn (tree node)
9527 {
9528 tree item;
9529 tree type;
9530
9531 if (node == error_mark_node)
9532 return error_mark_node;
9533
9534 type = build_type_variant (TREE_TYPE (node),
9535 TREE_READONLY (node),
9536 TREE_THIS_VOLATILE (node));
9537 item = build1 (ADDR_EXPR,
9538 build_pointer_type (type), node);
9539 if (TREE_SIDE_EFFECTS (node))
9540 TREE_SIDE_EFFECTS (item) = 1;
9541 if (staticp (node))
9542 TREE_CONSTANT (item) = 1;
9543 return fold (item);
9544 }
9545
9546 /* Essentially does a "fold (build (code, type, node1, node2))" while
9547 checking for certain housekeeping things. */
9548
9549 tree
9550 ffecom_2 (enum tree_code code, tree type, tree node1,
9551 tree node2)
9552 {
9553 tree item;
9554
9555 if ((node1 == error_mark_node)
9556 || (node2 == error_mark_node)
9557 || (type == error_mark_node))
9558 return error_mark_node;
9559
9560 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
9561 {
9562 tree a, b, c, d, realtype;
9563
9564 case CONJ_EXPR:
9565 assert ("no CONJ_EXPR support yet" == NULL);
9566 return error_mark_node;
9567
9568 case COMPLEX_EXPR:
9569 item = build_tree_list (TYPE_FIELDS (type), node1);
9570 TREE_CHAIN (item) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), node2);
9571 item = build_constructor (type, item);
9572 break;
9573
9574 case PLUS_EXPR:
9575 if (TREE_CODE (type) != RECORD_TYPE)
9576 {
9577 item = build (code, type, node1, node2);
9578 break;
9579 }
9580 node1 = ffecom_stabilize_aggregate_ (node1);
9581 node2 = ffecom_stabilize_aggregate_ (node2);
9582 realtype = TREE_TYPE (TYPE_FIELDS (type));
9583 item =
9584 ffecom_2 (COMPLEX_EXPR, type,
9585 ffecom_2 (PLUS_EXPR, realtype,
9586 ffecom_1 (REALPART_EXPR, realtype,
9587 node1),
9588 ffecom_1 (REALPART_EXPR, realtype,
9589 node2)),
9590 ffecom_2 (PLUS_EXPR, realtype,
9591 ffecom_1 (IMAGPART_EXPR, realtype,
9592 node1),
9593 ffecom_1 (IMAGPART_EXPR, realtype,
9594 node2)));
9595 break;
9596
9597 case MINUS_EXPR:
9598 if (TREE_CODE (type) != RECORD_TYPE)
9599 {
9600 item = build (code, type, node1, node2);
9601 break;
9602 }
9603 node1 = ffecom_stabilize_aggregate_ (node1);
9604 node2 = ffecom_stabilize_aggregate_ (node2);
9605 realtype = TREE_TYPE (TYPE_FIELDS (type));
9606 item =
9607 ffecom_2 (COMPLEX_EXPR, type,
9608 ffecom_2 (MINUS_EXPR, realtype,
9609 ffecom_1 (REALPART_EXPR, realtype,
9610 node1),
9611 ffecom_1 (REALPART_EXPR, realtype,
9612 node2)),
9613 ffecom_2 (MINUS_EXPR, realtype,
9614 ffecom_1 (IMAGPART_EXPR, realtype,
9615 node1),
9616 ffecom_1 (IMAGPART_EXPR, realtype,
9617 node2)));
9618 break;
9619
9620 case MULT_EXPR:
9621 if (TREE_CODE (type) != RECORD_TYPE)
9622 {
9623 item = build (code, type, node1, node2);
9624 break;
9625 }
9626 node1 = ffecom_stabilize_aggregate_ (node1);
9627 node2 = ffecom_stabilize_aggregate_ (node2);
9628 realtype = TREE_TYPE (TYPE_FIELDS (type));
9629 a = save_expr (ffecom_1 (REALPART_EXPR, realtype,
9630 node1));
9631 b = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
9632 node1));
9633 c = save_expr (ffecom_1 (REALPART_EXPR, realtype,
9634 node2));
9635 d = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
9636 node2));
9637 item =
9638 ffecom_2 (COMPLEX_EXPR, type,
9639 ffecom_2 (MINUS_EXPR, realtype,
9640 ffecom_2 (MULT_EXPR, realtype,
9641 a,
9642 c),
9643 ffecom_2 (MULT_EXPR, realtype,
9644 b,
9645 d)),
9646 ffecom_2 (PLUS_EXPR, realtype,
9647 ffecom_2 (MULT_EXPR, realtype,
9648 a,
9649 d),
9650 ffecom_2 (MULT_EXPR, realtype,
9651 c,
9652 b)));
9653 break;
9654
9655 case EQ_EXPR:
9656 if ((TREE_CODE (node1) != RECORD_TYPE)
9657 && (TREE_CODE (node2) != RECORD_TYPE))
9658 {
9659 item = build (code, type, node1, node2);
9660 break;
9661 }
9662 assert (TREE_CODE (node1) == RECORD_TYPE);
9663 assert (TREE_CODE (node2) == RECORD_TYPE);
9664 node1 = ffecom_stabilize_aggregate_ (node1);
9665 node2 = ffecom_stabilize_aggregate_ (node2);
9666 realtype = TREE_TYPE (TYPE_FIELDS (type));
9667 item =
9668 ffecom_2 (TRUTH_ANDIF_EXPR, type,
9669 ffecom_2 (code, type,
9670 ffecom_1 (REALPART_EXPR, realtype,
9671 node1),
9672 ffecom_1 (REALPART_EXPR, realtype,
9673 node2)),
9674 ffecom_2 (code, type,
9675 ffecom_1 (IMAGPART_EXPR, realtype,
9676 node1),
9677 ffecom_1 (IMAGPART_EXPR, realtype,
9678 node2)));
9679 break;
9680
9681 case NE_EXPR:
9682 if ((TREE_CODE (node1) != RECORD_TYPE)
9683 && (TREE_CODE (node2) != RECORD_TYPE))
9684 {
9685 item = build (code, type, node1, node2);
9686 break;
9687 }
9688 assert (TREE_CODE (node1) == RECORD_TYPE);
9689 assert (TREE_CODE (node2) == RECORD_TYPE);
9690 node1 = ffecom_stabilize_aggregate_ (node1);
9691 node2 = ffecom_stabilize_aggregate_ (node2);
9692 realtype = TREE_TYPE (TYPE_FIELDS (type));
9693 item =
9694 ffecom_2 (TRUTH_ORIF_EXPR, type,
9695 ffecom_2 (code, type,
9696 ffecom_1 (REALPART_EXPR, realtype,
9697 node1),
9698 ffecom_1 (REALPART_EXPR, realtype,
9699 node2)),
9700 ffecom_2 (code, type,
9701 ffecom_1 (IMAGPART_EXPR, realtype,
9702 node1),
9703 ffecom_1 (IMAGPART_EXPR, realtype,
9704 node2)));
9705 break;
9706
9707 default:
9708 item = build (code, type, node1, node2);
9709 break;
9710 }
9711
9712 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2))
9713 TREE_SIDE_EFFECTS (item) = 1;
9714 return fold (item);
9715 }
9716
9717 /* ffecom_2pass_advise_entrypoint -- Advise that there's this entrypoint
9718
9719 ffesymbol s; // the ENTRY point itself
9720 if (ffecom_2pass_advise_entrypoint(s))
9721 // the ENTRY point has been accepted
9722
9723 Does whatever compiler needs to do when it learns about the entrypoint,
9724 like determine the return type of the master function, count the
9725 number of entrypoints, etc. Returns FALSE if the return type is
9726 not compatible with the return type(s) of other entrypoint(s).
9727
9728 NOTE: for every call to this fn that returns TRUE, _do_entrypoint must
9729 later (after _finish_progunit) be called with the same entrypoint(s)
9730 as passed to this fn for which TRUE was returned.
9731
9732 03-Jan-92 JCB 2.0
9733 Return FALSE if the return type conflicts with previous entrypoints. */
9734
9735 bool
9736 ffecom_2pass_advise_entrypoint (ffesymbol entry)
9737 {
9738 ffebld list; /* opITEM. */
9739 ffebld mlist; /* opITEM. */
9740 ffebld plist; /* opITEM. */
9741 ffebld arg; /* ffebld_head(opITEM). */
9742 ffebld item; /* opITEM. */
9743 ffesymbol s; /* ffebld_symter(arg). */
9744 ffeinfoBasictype bt = ffesymbol_basictype (entry);
9745 ffeinfoKindtype kt = ffesymbol_kindtype (entry);
9746 ffetargetCharacterSize size = ffesymbol_size (entry);
9747 bool ok;
9748
9749 if (ffecom_num_entrypoints_ == 0)
9750 { /* First entrypoint, make list of main
9751 arglist's dummies. */
9752 assert (ffecom_primary_entry_ != NULL);
9753
9754 ffecom_master_bt_ = ffesymbol_basictype (ffecom_primary_entry_);
9755 ffecom_master_kt_ = ffesymbol_kindtype (ffecom_primary_entry_);
9756 ffecom_master_size_ = ffesymbol_size (ffecom_primary_entry_);
9757
9758 for (plist = NULL, list = ffesymbol_dummyargs (ffecom_primary_entry_);
9759 list != NULL;
9760 list = ffebld_trail (list))
9761 {
9762 arg = ffebld_head (list);
9763 if (ffebld_op (arg) != FFEBLD_opSYMTER)
9764 continue; /* Alternate return or some such thing. */
9765 item = ffebld_new_item (arg, NULL);
9766 if (plist == NULL)
9767 ffecom_master_arglist_ = item;
9768 else
9769 ffebld_set_trail (plist, item);
9770 plist = item;
9771 }
9772 }
9773
9774 /* If necessary, scan entry arglist for alternate returns. Do this scan
9775 apparently redundantly (it's done below to UNIONize the arglists) so
9776 that we don't complain about RETURN 1 if an offending ENTRY is the only
9777 one with an alternate return. */
9778
9779 if (!ffecom_is_altreturning_)
9780 {
9781 for (list = ffesymbol_dummyargs (entry);
9782 list != NULL;
9783 list = ffebld_trail (list))
9784 {
9785 arg = ffebld_head (list);
9786 if (ffebld_op (arg) == FFEBLD_opSTAR)
9787 {
9788 ffecom_is_altreturning_ = TRUE;
9789 break;
9790 }
9791 }
9792 }
9793
9794 /* Now check type compatibility. */
9795
9796 switch (ffecom_master_bt_)
9797 {
9798 case FFEINFO_basictypeNONE:
9799 ok = (bt != FFEINFO_basictypeCHARACTER);
9800 break;
9801
9802 case FFEINFO_basictypeCHARACTER:
9803 ok
9804 = (bt == FFEINFO_basictypeCHARACTER)
9805 && (kt == ffecom_master_kt_)
9806 && (size == ffecom_master_size_);
9807 break;
9808
9809 case FFEINFO_basictypeANY:
9810 return FALSE; /* Just don't bother. */
9811
9812 default:
9813 if (bt == FFEINFO_basictypeCHARACTER)
9814 {
9815 ok = FALSE;
9816 break;
9817 }
9818 ok = TRUE;
9819 if ((bt != ffecom_master_bt_) || (kt != ffecom_master_kt_))
9820 {
9821 ffecom_master_bt_ = FFEINFO_basictypeNONE;
9822 ffecom_master_kt_ = FFEINFO_kindtypeNONE;
9823 }
9824 break;
9825 }
9826
9827 if (!ok)
9828 {
9829 ffebad_start (FFEBAD_ENTRY_CONFLICTS);
9830 ffest_ffebad_here_current_stmt (0);
9831 ffebad_finish ();
9832 return FALSE; /* Can't handle entrypoint. */
9833 }
9834
9835 /* Entrypoint type compatible with previous types. */
9836
9837 ++ffecom_num_entrypoints_;
9838
9839 /* Master-arg-list = UNION(Master-arg-list,entry-arg-list). */
9840
9841 for (list = ffesymbol_dummyargs (entry);
9842 list != NULL;
9843 list = ffebld_trail (list))
9844 {
9845 arg = ffebld_head (list);
9846 if (ffebld_op (arg) != FFEBLD_opSYMTER)
9847 continue; /* Alternate return or some such thing. */
9848 s = ffebld_symter (arg);
9849 for (plist = NULL, mlist = ffecom_master_arglist_;
9850 mlist != NULL;
9851 plist = mlist, mlist = ffebld_trail (mlist))
9852 { /* plist points to previous item for easy
9853 appending of arg. */
9854 if (ffebld_symter (ffebld_head (mlist)) == s)
9855 break; /* Already have this arg in the master list. */
9856 }
9857 if (mlist != NULL)
9858 continue; /* Already have this arg in the master list. */
9859
9860 /* Append this arg to the master list. */
9861
9862 item = ffebld_new_item (arg, NULL);
9863 if (plist == NULL)
9864 ffecom_master_arglist_ = item;
9865 else
9866 ffebld_set_trail (plist, item);
9867 }
9868
9869 return TRUE;
9870 }
9871
9872 /* ffecom_2pass_do_entrypoint -- Do compilation of entrypoint
9873
9874 ffesymbol s; // the ENTRY point itself
9875 ffecom_2pass_do_entrypoint(s);
9876
9877 Does whatever compiler needs to do to make the entrypoint actually
9878 happen. Must be called for each entrypoint after
9879 ffecom_finish_progunit is called. */
9880
9881 void
9882 ffecom_2pass_do_entrypoint (ffesymbol entry)
9883 {
9884 static int mfn_num = 0;
9885 static int ent_num;
9886
9887 if (mfn_num != ffecom_num_fns_)
9888 { /* First entrypoint for this program unit. */
9889 ent_num = 1;
9890 mfn_num = ffecom_num_fns_;
9891 ffecom_do_entry_ (ffecom_primary_entry_, 0);
9892 }
9893 else
9894 ++ent_num;
9895
9896 --ffecom_num_entrypoints_;
9897
9898 ffecom_do_entry_ (entry, ent_num);
9899 }
9900
9901 /* Essentially does a "fold (build (code, type, node1, node2))" while
9902 checking for certain housekeeping things. Always sets
9903 TREE_SIDE_EFFECTS. */
9904
9905 tree
9906 ffecom_2s (enum tree_code code, tree type, tree node1,
9907 tree node2)
9908 {
9909 tree item;
9910
9911 if ((node1 == error_mark_node)
9912 || (node2 == error_mark_node)
9913 || (type == error_mark_node))
9914 return error_mark_node;
9915
9916 item = build (code, type, node1, node2);
9917 TREE_SIDE_EFFECTS (item) = 1;
9918 return fold (item);
9919 }
9920
9921 /* Essentially does a "fold (build (code, type, node1, node2, node3))" while
9922 checking for certain housekeeping things. */
9923
9924 tree
9925 ffecom_3 (enum tree_code code, tree type, tree node1,
9926 tree node2, tree node3)
9927 {
9928 tree item;
9929
9930 if ((node1 == error_mark_node)
9931 || (node2 == error_mark_node)
9932 || (node3 == error_mark_node)
9933 || (type == error_mark_node))
9934 return error_mark_node;
9935
9936 item = build (code, type, node1, node2, node3);
9937 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2)
9938 || (node3 != NULL_TREE && TREE_SIDE_EFFECTS (node3)))
9939 TREE_SIDE_EFFECTS (item) = 1;
9940 return fold (item);
9941 }
9942
9943 /* Essentially does a "fold (build (code, type, node1, node2, node3))" while
9944 checking for certain housekeeping things. Always sets
9945 TREE_SIDE_EFFECTS. */
9946
9947 tree
9948 ffecom_3s (enum tree_code code, tree type, tree node1,
9949 tree node2, tree node3)
9950 {
9951 tree item;
9952
9953 if ((node1 == error_mark_node)
9954 || (node2 == error_mark_node)
9955 || (node3 == error_mark_node)
9956 || (type == error_mark_node))
9957 return error_mark_node;
9958
9959 item = build (code, type, node1, node2, node3);
9960 TREE_SIDE_EFFECTS (item) = 1;
9961 return fold (item);
9962 }
9963
9964 /* ffecom_arg_expr -- Transform argument expr into gcc tree
9965
9966 See use by ffecom_list_expr.
9967
9968 If expression is NULL, returns an integer zero tree. If it is not
9969 a CHARACTER expression, returns whatever ffecom_expr
9970 returns and sets the length return value to NULL_TREE. Otherwise
9971 generates code to evaluate the character expression, returns the proper
9972 pointer to the result, but does NOT set the length return value to a tree
9973 that specifies the length of the result. (In other words, the length
9974 variable is always set to NULL_TREE, because a length is never passed.)
9975
9976 21-Dec-91 JCB 1.1
9977 Don't set returned length, since nobody needs it (yet; someday if
9978 we allow CHARACTER*(*) dummies to statement functions, we'll need
9979 it). */
9980
9981 tree
9982 ffecom_arg_expr (ffebld expr, tree *length)
9983 {
9984 tree ign;
9985
9986 *length = NULL_TREE;
9987
9988 if (expr == NULL)
9989 return integer_zero_node;
9990
9991 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
9992 return ffecom_expr (expr);
9993
9994 return ffecom_arg_ptr_to_expr (expr, &ign);
9995 }
9996
9997 /* Transform expression into constant argument-pointer-to-expression tree.
9998
9999 If the expression can be transformed into a argument-pointer-to-expression
10000 tree that is constant, that is done, and the tree returned. Else
10001 NULL_TREE is returned.
10002
10003 That way, a caller can attempt to provide compile-time initialization
10004 of a variable and, if that fails, *then* choose to start a new block
10005 and resort to using temporaries, as appropriate. */
10006
10007 tree
10008 ffecom_arg_ptr_to_const_expr (ffebld expr, tree *length)
10009 {
10010 if (! expr)
10011 return integer_zero_node;
10012
10013 if (ffebld_op (expr) == FFEBLD_opANY)
10014 {
10015 if (length)
10016 *length = error_mark_node;
10017 return error_mark_node;
10018 }
10019
10020 if (ffebld_arity (expr) == 0
10021 && (ffebld_op (expr) != FFEBLD_opSYMTER
10022 || ffebld_where (expr) == FFEINFO_whereCOMMON
10023 || ffebld_where (expr) == FFEINFO_whereGLOBAL
10024 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
10025 {
10026 tree t;
10027
10028 t = ffecom_arg_ptr_to_expr (expr, length);
10029 assert (TREE_CONSTANT (t));
10030 assert (! length || TREE_CONSTANT (*length));
10031 return t;
10032 }
10033
10034 if (length
10035 && ffebld_size (expr) != FFETARGET_charactersizeNONE)
10036 *length = build_int_2 (ffebld_size (expr), 0);
10037 else if (length)
10038 *length = NULL_TREE;
10039 return NULL_TREE;
10040 }
10041
10042 /* ffecom_arg_ptr_to_expr -- Transform argument expr into gcc tree
10043
10044 See use by ffecom_list_ptr_to_expr.
10045
10046 If expression is NULL, returns an integer zero tree. If it is not
10047 a CHARACTER expression, returns whatever ffecom_ptr_to_expr
10048 returns and sets the length return value to NULL_TREE. Otherwise
10049 generates code to evaluate the character expression, returns the proper
10050 pointer to the result, AND sets the length return value to a tree that
10051 specifies the length of the result.
10052
10053 If the length argument is NULL, this is a slightly special
10054 case of building a FORMAT expression, that is, an expression that
10055 will be used at run time without regard to length. For the current
10056 implementation, which uses the libf2c library, this means it is nice
10057 to append a null byte to the end of the expression, where feasible,
10058 to make sure any diagnostic about the FORMAT string terminates at
10059 some useful point.
10060
10061 For now, treat %REF(char-expr) as the same as char-expr with a NULL
10062 length argument. This might even be seen as a feature, if a null
10063 byte can always be appended. */
10064
10065 tree
10066 ffecom_arg_ptr_to_expr (ffebld expr, tree *length)
10067 {
10068 tree item;
10069 tree ign_length;
10070 ffecomConcatList_ catlist;
10071
10072 if (length != NULL)
10073 *length = NULL_TREE;
10074
10075 if (expr == NULL)
10076 return integer_zero_node;
10077
10078 switch (ffebld_op (expr))
10079 {
10080 case FFEBLD_opPERCENT_VAL:
10081 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10082 return ffecom_expr (ffebld_left (expr));
10083 {
10084 tree temp_exp;
10085 tree temp_length;
10086
10087 temp_exp = ffecom_arg_ptr_to_expr (ffebld_left (expr), &temp_length);
10088 if (temp_exp == error_mark_node)
10089 return error_mark_node;
10090
10091 return ffecom_1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (temp_exp)),
10092 temp_exp);
10093 }
10094
10095 case FFEBLD_opPERCENT_REF:
10096 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10097 return ffecom_ptr_to_expr (ffebld_left (expr));
10098 if (length != NULL)
10099 {
10100 ign_length = NULL_TREE;
10101 length = &ign_length;
10102 }
10103 expr = ffebld_left (expr);
10104 break;
10105
10106 case FFEBLD_opPERCENT_DESCR:
10107 switch (ffeinfo_basictype (ffebld_info (expr)))
10108 {
10109 case FFEINFO_basictypeCHARACTER:
10110 break; /* Passed by descriptor anyway. */
10111
10112 default:
10113 item = ffecom_ptr_to_expr (expr);
10114 if (item != error_mark_node)
10115 *length = TYPE_SIZE (TREE_TYPE (TREE_TYPE (item)));
10116 break;
10117 }
10118 break;
10119
10120 default:
10121 break;
10122 }
10123
10124 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10125 return ffecom_ptr_to_expr (expr);
10126
10127 assert (ffeinfo_kindtype (ffebld_info (expr))
10128 == FFEINFO_kindtypeCHARACTER1);
10129
10130 while (ffebld_op (expr) == FFEBLD_opPAREN)
10131 expr = ffebld_left (expr);
10132
10133 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
10134 switch (ffecom_concat_list_count_ (catlist))
10135 {
10136 case 0: /* Shouldn't happen, but in case it does... */
10137 if (length != NULL)
10138 {
10139 *length = ffecom_f2c_ftnlen_zero_node;
10140 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10141 }
10142 ffecom_concat_list_kill_ (catlist);
10143 return null_pointer_node;
10144
10145 case 1: /* The (fairly) easy case. */
10146 if (length == NULL)
10147 ffecom_char_args_with_null_ (&item, &ign_length,
10148 ffecom_concat_list_expr_ (catlist, 0));
10149 else
10150 ffecom_char_args_ (&item, length,
10151 ffecom_concat_list_expr_ (catlist, 0));
10152 ffecom_concat_list_kill_ (catlist);
10153 assert (item != NULL_TREE);
10154 return item;
10155
10156 default: /* Must actually concatenate things. */
10157 break;
10158 }
10159
10160 {
10161 int count = ffecom_concat_list_count_ (catlist);
10162 int i;
10163 tree lengths;
10164 tree items;
10165 tree length_array;
10166 tree item_array;
10167 tree citem;
10168 tree clength;
10169 tree temporary;
10170 tree num;
10171 tree known_length;
10172 ffetargetCharacterSize sz;
10173
10174 sz = ffecom_concat_list_maxlen_ (catlist);
10175 /* ~~Kludge! */
10176 assert (sz != FFETARGET_charactersizeNONE);
10177
10178 {
10179 tree hook;
10180
10181 hook = ffebld_nonter_hook (expr);
10182 assert (hook);
10183 assert (TREE_CODE (hook) == TREE_VEC);
10184 assert (TREE_VEC_LENGTH (hook) == 3);
10185 length_array = lengths = TREE_VEC_ELT (hook, 0);
10186 item_array = items = TREE_VEC_ELT (hook, 1);
10187 temporary = TREE_VEC_ELT (hook, 2);
10188 }
10189
10190 known_length = ffecom_f2c_ftnlen_zero_node;
10191
10192 for (i = 0; i < count; ++i)
10193 {
10194 if ((i == count)
10195 && (length == NULL))
10196 ffecom_char_args_with_null_ (&citem, &clength,
10197 ffecom_concat_list_expr_ (catlist, i));
10198 else
10199 ffecom_char_args_ (&citem, &clength,
10200 ffecom_concat_list_expr_ (catlist, i));
10201 if ((citem == error_mark_node)
10202 || (clength == error_mark_node))
10203 {
10204 ffecom_concat_list_kill_ (catlist);
10205 *length = error_mark_node;
10206 return error_mark_node;
10207 }
10208
10209 items
10210 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
10211 ffecom_modify (void_type_node,
10212 ffecom_2 (ARRAY_REF,
10213 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
10214 item_array,
10215 build_int_2 (i, 0)),
10216 citem),
10217 items);
10218 clength = ffecom_save_tree (clength);
10219 if (length != NULL)
10220 known_length
10221 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
10222 known_length,
10223 clength);
10224 lengths
10225 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
10226 ffecom_modify (void_type_node,
10227 ffecom_2 (ARRAY_REF,
10228 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
10229 length_array,
10230 build_int_2 (i, 0)),
10231 clength),
10232 lengths);
10233 }
10234
10235 temporary = ffecom_1 (ADDR_EXPR,
10236 build_pointer_type (TREE_TYPE (temporary)),
10237 temporary);
10238
10239 item = build_tree_list (NULL_TREE, temporary);
10240 TREE_CHAIN (item)
10241 = build_tree_list (NULL_TREE,
10242 ffecom_1 (ADDR_EXPR,
10243 build_pointer_type (TREE_TYPE (items)),
10244 items));
10245 TREE_CHAIN (TREE_CHAIN (item))
10246 = build_tree_list (NULL_TREE,
10247 ffecom_1 (ADDR_EXPR,
10248 build_pointer_type (TREE_TYPE (lengths)),
10249 lengths));
10250 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
10251 = build_tree_list
10252 (NULL_TREE,
10253 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
10254 convert (ffecom_f2c_ftnlen_type_node,
10255 build_int_2 (count, 0))));
10256 num = build_int_2 (sz, 0);
10257 TREE_TYPE (num) = ffecom_f2c_ftnlen_type_node;
10258 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item))))
10259 = build_tree_list (NULL_TREE, num);
10260
10261 item = ffecom_call_gfrt (FFECOM_gfrtCAT, item, NULL_TREE);
10262 TREE_SIDE_EFFECTS (item) = 1;
10263 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (temporary),
10264 item,
10265 temporary);
10266
10267 if (length != NULL)
10268 *length = known_length;
10269 }
10270
10271 ffecom_concat_list_kill_ (catlist);
10272 assert (item != NULL_TREE);
10273 return item;
10274 }
10275
10276 /* Generate call to run-time function.
10277
10278 The first arg is the GNU Fortran Run-Time function index, the second
10279 arg is the list of arguments to pass to it. Returned is the expression
10280 (WITHOUT TREE_SIDE_EFFECTS set!) that makes the call and returns the
10281 result (which may be void). */
10282
10283 tree
10284 ffecom_call_gfrt (ffecomGfrt ix, tree args, tree hook)
10285 {
10286 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
10287 ffecom_gfrt_kindtype (ix),
10288 ffe_is_f2c_library () && ffecom_gfrt_complex_[ix],
10289 NULL_TREE, args, NULL_TREE, NULL,
10290 NULL, NULL_TREE, TRUE, hook);
10291 }
10292
10293 /* Transform constant-union to tree. */
10294
10295 tree
10296 ffecom_constantunion (ffebldConstantUnion *cu, ffeinfoBasictype bt,
10297 ffeinfoKindtype kt, tree tree_type)
10298 {
10299 tree item;
10300
10301 switch (bt)
10302 {
10303 case FFEINFO_basictypeINTEGER:
10304 {
10305 HOST_WIDE_INT hi, lo;
10306
10307 switch (kt)
10308 {
10309 #if FFETARGET_okINTEGER1
10310 case FFEINFO_kindtypeINTEGER1:
10311 lo = ffebld_cu_val_integer1 (*cu);
10312 hi = (lo < 0) ? -1 : 0;
10313 break;
10314 #endif
10315
10316 #if FFETARGET_okINTEGER2
10317 case FFEINFO_kindtypeINTEGER2:
10318 lo = ffebld_cu_val_integer2 (*cu);
10319 hi = (lo < 0) ? -1 : 0;
10320 break;
10321 #endif
10322
10323 #if FFETARGET_okINTEGER3
10324 case FFEINFO_kindtypeINTEGER3:
10325 lo = ffebld_cu_val_integer3 (*cu);
10326 hi = (lo < 0) ? -1 : 0;
10327 break;
10328 #endif
10329
10330 #if FFETARGET_okINTEGER4
10331 case FFEINFO_kindtypeINTEGER4:
10332 #if HOST_BITS_PER_LONGLONG > HOST_BITS_PER_WIDE_INT
10333 {
10334 long long int big = ffebld_cu_val_integer4 (*cu);
10335 hi = (HOST_WIDE_INT) (big >> HOST_BITS_PER_WIDE_INT);
10336 lo = (HOST_WIDE_INT) big;
10337 }
10338 #else
10339 lo = ffebld_cu_val_integer4 (*cu);
10340 hi = (lo < 0) ? -1 : 0;
10341 #endif
10342 break;
10343 #endif
10344
10345 default:
10346 assert ("bad INTEGER constant kind type" == NULL);
10347 /* Fall through. */
10348 case FFEINFO_kindtypeANY:
10349 return error_mark_node;
10350 }
10351 item = build_int_2 (lo, hi);
10352 TREE_TYPE (item) = tree_type;
10353 }
10354 break;
10355
10356 case FFEINFO_basictypeLOGICAL:
10357 {
10358 int val;
10359
10360 switch (kt)
10361 {
10362 #if FFETARGET_okLOGICAL1
10363 case FFEINFO_kindtypeLOGICAL1:
10364 val = ffebld_cu_val_logical1 (*cu);
10365 break;
10366 #endif
10367
10368 #if FFETARGET_okLOGICAL2
10369 case FFEINFO_kindtypeLOGICAL2:
10370 val = ffebld_cu_val_logical2 (*cu);
10371 break;
10372 #endif
10373
10374 #if FFETARGET_okLOGICAL3
10375 case FFEINFO_kindtypeLOGICAL3:
10376 val = ffebld_cu_val_logical3 (*cu);
10377 break;
10378 #endif
10379
10380 #if FFETARGET_okLOGICAL4
10381 case FFEINFO_kindtypeLOGICAL4:
10382 val = ffebld_cu_val_logical4 (*cu);
10383 break;
10384 #endif
10385
10386 default:
10387 assert ("bad LOGICAL constant kind type" == NULL);
10388 /* Fall through. */
10389 case FFEINFO_kindtypeANY:
10390 return error_mark_node;
10391 }
10392 item = build_int_2 (val, (val < 0) ? -1 : 0);
10393 TREE_TYPE (item) = tree_type;
10394 }
10395 break;
10396
10397 case FFEINFO_basictypeREAL:
10398 {
10399 REAL_VALUE_TYPE val;
10400
10401 switch (kt)
10402 {
10403 #if FFETARGET_okREAL1
10404 case FFEINFO_kindtypeREAL1:
10405 val = ffetarget_value_real1 (ffebld_cu_val_real1 (*cu));
10406 break;
10407 #endif
10408
10409 #if FFETARGET_okREAL2
10410 case FFEINFO_kindtypeREAL2:
10411 val = ffetarget_value_real2 (ffebld_cu_val_real2 (*cu));
10412 break;
10413 #endif
10414
10415 #if FFETARGET_okREAL3
10416 case FFEINFO_kindtypeREAL3:
10417 val = ffetarget_value_real3 (ffebld_cu_val_real3 (*cu));
10418 break;
10419 #endif
10420
10421 default:
10422 assert ("bad REAL constant kind type" == NULL);
10423 /* Fall through. */
10424 case FFEINFO_kindtypeANY:
10425 return error_mark_node;
10426 }
10427 item = build_real (tree_type, val);
10428 }
10429 break;
10430
10431 case FFEINFO_basictypeCOMPLEX:
10432 {
10433 REAL_VALUE_TYPE real;
10434 REAL_VALUE_TYPE imag;
10435 tree el_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
10436
10437 switch (kt)
10438 {
10439 #if FFETARGET_okCOMPLEX1
10440 case FFEINFO_kindtypeREAL1:
10441 real = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).real);
10442 imag = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).imaginary);
10443 break;
10444 #endif
10445
10446 #if FFETARGET_okCOMPLEX2
10447 case FFEINFO_kindtypeREAL2:
10448 real = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).real);
10449 imag = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).imaginary);
10450 break;
10451 #endif
10452
10453 #if FFETARGET_okCOMPLEX3
10454 case FFEINFO_kindtypeREAL3:
10455 real = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).real);
10456 imag = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).imaginary);
10457 break;
10458 #endif
10459
10460 default:
10461 assert ("bad REAL constant kind type" == NULL);
10462 /* Fall through. */
10463 case FFEINFO_kindtypeANY:
10464 return error_mark_node;
10465 }
10466 item = ffecom_build_complex_constant_ (tree_type,
10467 build_real (el_type, real),
10468 build_real (el_type, imag));
10469 }
10470 break;
10471
10472 case FFEINFO_basictypeCHARACTER:
10473 { /* Happens only in DATA and similar contexts. */
10474 ffetargetCharacter1 val;
10475
10476 switch (kt)
10477 {
10478 #if FFETARGET_okCHARACTER1
10479 case FFEINFO_kindtypeLOGICAL1:
10480 val = ffebld_cu_val_character1 (*cu);
10481 break;
10482 #endif
10483
10484 default:
10485 assert ("bad CHARACTER constant kind type" == NULL);
10486 /* Fall through. */
10487 case FFEINFO_kindtypeANY:
10488 return error_mark_node;
10489 }
10490 item = build_string (ffetarget_length_character1 (val),
10491 ffetarget_text_character1 (val));
10492 TREE_TYPE (item)
10493 = build_type_variant (build_array_type (char_type_node,
10494 build_range_type
10495 (integer_type_node,
10496 integer_one_node,
10497 build_int_2
10498 (ffetarget_length_character1
10499 (val), 0))),
10500 1, 0);
10501 }
10502 break;
10503
10504 case FFEINFO_basictypeHOLLERITH:
10505 {
10506 ffetargetHollerith h;
10507
10508 h = ffebld_cu_val_hollerith (*cu);
10509
10510 /* If not at least as wide as default INTEGER, widen it. */
10511 if (h.length >= FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE)
10512 item = build_string (h.length, h.text);
10513 else
10514 {
10515 char str[FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE];
10516
10517 memcpy (str, h.text, h.length);
10518 memset (&str[h.length], ' ',
10519 FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE
10520 - h.length);
10521 item = build_string (FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE,
10522 str);
10523 }
10524 TREE_TYPE (item)
10525 = build_type_variant (build_array_type (char_type_node,
10526 build_range_type
10527 (integer_type_node,
10528 integer_one_node,
10529 build_int_2
10530 (h.length, 0))),
10531 1, 0);
10532 }
10533 break;
10534
10535 case FFEINFO_basictypeTYPELESS:
10536 {
10537 ffetargetInteger1 ival;
10538 ffetargetTypeless tless;
10539 ffebad error;
10540
10541 tless = ffebld_cu_val_typeless (*cu);
10542 error = ffetarget_convert_integer1_typeless (&ival, tless);
10543 assert (error == FFEBAD);
10544
10545 item = build_int_2 ((int) ival, 0);
10546 }
10547 break;
10548
10549 default:
10550 assert ("not yet on constant type" == NULL);
10551 /* Fall through. */
10552 case FFEINFO_basictypeANY:
10553 return error_mark_node;
10554 }
10555
10556 TREE_CONSTANT (item) = 1;
10557
10558 return item;
10559 }
10560
10561 /* Transform constant-union to tree, with the type known. */
10562
10563 tree
10564 ffecom_constantunion_with_type (ffebldConstantUnion *cu,
10565 tree tree_type, ffebldConst ct)
10566 {
10567 tree item;
10568
10569 int val;
10570
10571 switch (ct)
10572 {
10573 #if FFETARGET_okINTEGER1
10574 case FFEBLD_constINTEGER1:
10575 val = ffebld_cu_val_integer1 (*cu);
10576 item = build_int_2 (val, (val < 0) ? -1 : 0);
10577 break;
10578 #endif
10579 #if FFETARGET_okINTEGER2
10580 case FFEBLD_constINTEGER2:
10581 val = ffebld_cu_val_integer2 (*cu);
10582 item = build_int_2 (val, (val < 0) ? -1 : 0);
10583 break;
10584 #endif
10585 #if FFETARGET_okINTEGER3
10586 case FFEBLD_constINTEGER3:
10587 val = ffebld_cu_val_integer3 (*cu);
10588 item = build_int_2 (val, (val < 0) ? -1 : 0);
10589 break;
10590 #endif
10591 #if FFETARGET_okINTEGER4
10592 case FFEBLD_constINTEGER4:
10593 #if HOST_BITS_PER_LONGLONG > HOST_BITS_PER_WIDE_INT
10594 {
10595 long long int big = ffebld_cu_val_integer4 (*cu);
10596 item = build_int_2 ((HOST_WIDE_INT) big,
10597 (HOST_WIDE_INT)
10598 (big >> HOST_BITS_PER_WIDE_INT));
10599 }
10600 #else
10601 val = ffebld_cu_val_integer4 (*cu);
10602 item = build_int_2 (val, (val < 0) ? -1 : 0);
10603 #endif
10604 break;
10605 #endif
10606 #if FFETARGET_okLOGICAL1
10607 case FFEBLD_constLOGICAL1:
10608 val = ffebld_cu_val_logical1 (*cu);
10609 item = build_int_2 (val, (val < 0) ? -1 : 0);
10610 break;
10611 #endif
10612 #if FFETARGET_okLOGICAL2
10613 case FFEBLD_constLOGICAL2:
10614 val = ffebld_cu_val_logical2 (*cu);
10615 item = build_int_2 (val, (val < 0) ? -1 : 0);
10616 break;
10617 #endif
10618 #if FFETARGET_okLOGICAL3
10619 case FFEBLD_constLOGICAL3:
10620 val = ffebld_cu_val_logical3 (*cu);
10621 item = build_int_2 (val, (val < 0) ? -1 : 0);
10622 break;
10623 #endif
10624 #if FFETARGET_okLOGICAL4
10625 case FFEBLD_constLOGICAL4:
10626 val = ffebld_cu_val_logical4 (*cu);
10627 item = build_int_2 (val, (val < 0) ? -1 : 0);
10628 break;
10629 #endif
10630 default:
10631 assert ("constant type not supported"==NULL);
10632 return error_mark_node;
10633 break;
10634 }
10635
10636 TREE_TYPE (item) = tree_type;
10637
10638 TREE_CONSTANT (item) = 1;
10639
10640 return item;
10641 }
10642 /* Transform expression into constant tree.
10643
10644 If the expression can be transformed into a tree that is constant,
10645 that is done, and the tree returned. Else NULL_TREE is returned.
10646
10647 That way, a caller can attempt to provide compile-time initialization
10648 of a variable and, if that fails, *then* choose to start a new block
10649 and resort to using temporaries, as appropriate. */
10650
10651 tree
10652 ffecom_const_expr (ffebld expr)
10653 {
10654 if (! expr)
10655 return integer_zero_node;
10656
10657 if (ffebld_op (expr) == FFEBLD_opANY)
10658 return error_mark_node;
10659
10660 if (ffebld_arity (expr) == 0
10661 && (ffebld_op (expr) != FFEBLD_opSYMTER
10662 || ffebld_where (expr) == FFEINFO_whereGLOBAL
10663 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
10664 {
10665 tree t;
10666
10667 t = ffecom_expr (expr);
10668 assert (TREE_CONSTANT (t));
10669 return t;
10670 }
10671
10672 return NULL_TREE;
10673 }
10674
10675 /* Handy way to make a field in a struct/union. */
10676
10677 tree
10678 ffecom_decl_field (tree context, tree prevfield,
10679 const char *name, tree type)
10680 {
10681 tree field;
10682
10683 field = build_decl (FIELD_DECL, get_identifier (name), type);
10684 DECL_CONTEXT (field) = context;
10685 DECL_ALIGN (field) = 0;
10686 DECL_USER_ALIGN (field) = 0;
10687 if (prevfield != NULL_TREE)
10688 TREE_CHAIN (prevfield) = field;
10689
10690 return field;
10691 }
10692
10693 void
10694 ffecom_close_include (FILE *f)
10695 {
10696 ffecom_close_include_ (f);
10697 }
10698
10699 /* End a compound statement (block). */
10700
10701 tree
10702 ffecom_end_compstmt (void)
10703 {
10704 return bison_rule_compstmt_ ();
10705 }
10706
10707 /* ffecom_end_transition -- Perform end transition on all symbols
10708
10709 ffecom_end_transition();
10710
10711 Calls ffecom_sym_end_transition for each global and local symbol. */
10712
10713 void
10714 ffecom_end_transition ()
10715 {
10716 ffebld item;
10717
10718 if (ffe_is_ffedebug ())
10719 fprintf (dmpout, "; end_stmt_transition\n");
10720
10721 ffecom_list_blockdata_ = NULL;
10722 ffecom_list_common_ = NULL;
10723
10724 ffesymbol_drive (ffecom_sym_end_transition);
10725 if (ffe_is_ffedebug ())
10726 {
10727 ffestorag_report ();
10728 }
10729
10730 ffecom_start_progunit_ ();
10731
10732 for (item = ffecom_list_blockdata_;
10733 item != NULL;
10734 item = ffebld_trail (item))
10735 {
10736 ffebld callee;
10737 ffesymbol s;
10738 tree dt;
10739 tree t;
10740 tree var;
10741 static int number = 0;
10742
10743 callee = ffebld_head (item);
10744 s = ffebld_symter (callee);
10745 t = ffesymbol_hook (s).decl_tree;
10746 if (t == NULL_TREE)
10747 {
10748 s = ffecom_sym_transform_ (s);
10749 t = ffesymbol_hook (s).decl_tree;
10750 }
10751
10752 dt = build_pointer_type (TREE_TYPE (t));
10753
10754 var = build_decl (VAR_DECL,
10755 ffecom_get_invented_identifier ("__g77_forceload_%d",
10756 number++),
10757 dt);
10758 DECL_EXTERNAL (var) = 0;
10759 TREE_STATIC (var) = 1;
10760 TREE_PUBLIC (var) = 0;
10761 DECL_INITIAL (var) = error_mark_node;
10762 TREE_USED (var) = 1;
10763
10764 var = start_decl (var, FALSE);
10765
10766 t = ffecom_1 (ADDR_EXPR, dt, t);
10767
10768 finish_decl (var, t, FALSE);
10769 }
10770
10771 /* This handles any COMMON areas that weren't referenced but have, for
10772 example, important initial data. */
10773
10774 for (item = ffecom_list_common_;
10775 item != NULL;
10776 item = ffebld_trail (item))
10777 ffecom_transform_common_ (ffebld_symter (ffebld_head (item)));
10778
10779 ffecom_list_common_ = NULL;
10780 }
10781
10782 /* ffecom_exec_transition -- Perform exec transition on all symbols
10783
10784 ffecom_exec_transition();
10785
10786 Calls ffecom_sym_exec_transition for each global and local symbol.
10787 Make sure error updating not inhibited. */
10788
10789 void
10790 ffecom_exec_transition ()
10791 {
10792 bool inhibited;
10793
10794 if (ffe_is_ffedebug ())
10795 fprintf (dmpout, "; exec_stmt_transition\n");
10796
10797 inhibited = ffebad_inhibit ();
10798 ffebad_set_inhibit (FALSE);
10799
10800 ffesymbol_drive (ffecom_sym_exec_transition); /* Don't retract! */
10801 ffeequiv_exec_transition (); /* Handle all pending EQUIVALENCEs. */
10802 if (ffe_is_ffedebug ())
10803 {
10804 ffestorag_report ();
10805 }
10806
10807 if (inhibited)
10808 ffebad_set_inhibit (TRUE);
10809 }
10810
10811 /* Handle assignment statement.
10812
10813 Convert dest and source using ffecom_expr, then join them
10814 with an ASSIGN op and pass the whole thing to expand_expr_stmt. */
10815
10816 void
10817 ffecom_expand_let_stmt (ffebld dest, ffebld source)
10818 {
10819 tree dest_tree;
10820 tree dest_length;
10821 tree source_tree;
10822 tree expr_tree;
10823
10824 if (ffeinfo_basictype (ffebld_info (dest)) != FFEINFO_basictypeCHARACTER)
10825 {
10826 bool dest_used;
10827 tree assign_temp;
10828
10829 /* This attempts to replicate the test below, but must not be
10830 true when the test below is false. (Always err on the side
10831 of creating unused temporaries, to avoid ICEs.) */
10832 if (ffebld_op (dest) != FFEBLD_opSYMTER
10833 || ((dest_tree = ffesymbol_hook (ffebld_symter (dest)).decl_tree)
10834 && (TREE_CODE (dest_tree) != VAR_DECL
10835 || TREE_ADDRESSABLE (dest_tree))))
10836 {
10837 ffecom_prepare_expr_ (source, dest);
10838 dest_used = TRUE;
10839 }
10840 else
10841 {
10842 ffecom_prepare_expr_ (source, NULL);
10843 dest_used = FALSE;
10844 }
10845
10846 ffecom_prepare_expr_w (NULL_TREE, dest);
10847
10848 /* For COMPLEX assignment like C1=C2, if partial overlap is possible,
10849 create a temporary through which the assignment is to take place,
10850 since MODIFY_EXPR doesn't handle partial overlap properly. */
10851 if (ffebld_basictype (dest) == FFEINFO_basictypeCOMPLEX
10852 && ffecom_possible_partial_overlap_ (dest, source))
10853 {
10854 assign_temp = ffecom_make_tempvar ("complex_let",
10855 ffecom_tree_type
10856 [ffebld_basictype (dest)]
10857 [ffebld_kindtype (dest)],
10858 FFETARGET_charactersizeNONE,
10859 -1);
10860 }
10861 else
10862 assign_temp = NULL_TREE;
10863
10864 ffecom_prepare_end ();
10865
10866 dest_tree = ffecom_expr_w (NULL_TREE, dest);
10867 if (dest_tree == error_mark_node)
10868 return;
10869
10870 if ((TREE_CODE (dest_tree) != VAR_DECL)
10871 || TREE_ADDRESSABLE (dest_tree))
10872 source_tree = ffecom_expr_ (source, dest_tree, dest, &dest_used,
10873 FALSE, FALSE);
10874 else
10875 {
10876 assert (! dest_used);
10877 dest_used = FALSE;
10878 source_tree = ffecom_expr (source);
10879 }
10880 if (source_tree == error_mark_node)
10881 return;
10882
10883 if (dest_used)
10884 expr_tree = source_tree;
10885 else if (assign_temp)
10886 {
10887 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
10888 assign_temp,
10889 source_tree);
10890 expand_expr_stmt (expr_tree);
10891 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
10892 dest_tree,
10893 assign_temp);
10894 }
10895 else
10896 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
10897 dest_tree,
10898 source_tree);
10899
10900 expand_expr_stmt (expr_tree);
10901 return;
10902 }
10903
10904 ffecom_prepare_let_char_ (ffebld_size_known (dest), source);
10905 ffecom_prepare_expr_w (NULL_TREE, dest);
10906
10907 ffecom_prepare_end ();
10908
10909 ffecom_char_args_ (&dest_tree, &dest_length, dest);
10910 ffecom_let_char_ (dest_tree, dest_length, ffebld_size_known (dest),
10911 source);
10912 }
10913
10914 /* ffecom_expr -- Transform expr into gcc tree
10915
10916 tree t;
10917 ffebld expr; // FFE expression.
10918 tree = ffecom_expr(expr);
10919
10920 Recursive descent on expr while making corresponding tree nodes and
10921 attaching type info and such. */
10922
10923 tree
10924 ffecom_expr (ffebld expr)
10925 {
10926 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, FALSE, FALSE);
10927 }
10928
10929 /* Like ffecom_expr, but return tree usable for assigned GOTO or FORMAT. */
10930
10931 tree
10932 ffecom_expr_assign (ffebld expr)
10933 {
10934 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
10935 }
10936
10937 /* Like ffecom_expr_rw, but return tree usable for ASSIGN. */
10938
10939 tree
10940 ffecom_expr_assign_w (ffebld expr)
10941 {
10942 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
10943 }
10944
10945 /* Transform expr for use as into read/write tree and stabilize the
10946 reference. Not for use on CHARACTER expressions.
10947
10948 Recursive descent on expr while making corresponding tree nodes and
10949 attaching type info and such. */
10950
10951 tree
10952 ffecom_expr_rw (tree type, ffebld expr)
10953 {
10954 assert (expr != NULL);
10955 /* Different target types not yet supported. */
10956 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
10957
10958 return stabilize_reference (ffecom_expr (expr));
10959 }
10960
10961 /* Transform expr for use as into write tree and stabilize the
10962 reference. Not for use on CHARACTER expressions.
10963
10964 Recursive descent on expr while making corresponding tree nodes and
10965 attaching type info and such. */
10966
10967 tree
10968 ffecom_expr_w (tree type, ffebld expr)
10969 {
10970 assert (expr != NULL);
10971 /* Different target types not yet supported. */
10972 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
10973
10974 return stabilize_reference (ffecom_expr (expr));
10975 }
10976
10977 /* Do global stuff. */
10978
10979 void
10980 ffecom_finish_compile ()
10981 {
10982 assert (ffecom_outer_function_decl_ == NULL_TREE);
10983 assert (current_function_decl == NULL_TREE);
10984
10985 ffeglobal_drive (ffecom_finish_global_);
10986 }
10987
10988 /* Public entry point for front end to access finish_decl. */
10989
10990 void
10991 ffecom_finish_decl (tree decl, tree init, bool is_top_level)
10992 {
10993 assert (!is_top_level);
10994 finish_decl (decl, init, FALSE);
10995 }
10996
10997 /* Finish a program unit. */
10998
10999 void
11000 ffecom_finish_progunit ()
11001 {
11002 ffecom_end_compstmt ();
11003
11004 ffecom_previous_function_decl_ = current_function_decl;
11005 ffecom_which_entrypoint_decl_ = NULL_TREE;
11006
11007 finish_function (0);
11008 }
11009
11010 /* Wrapper for get_identifier. pattern is sprintf-like. */
11011
11012 tree
11013 ffecom_get_invented_identifier (const char *pattern, ...)
11014 {
11015 tree decl;
11016 char *nam;
11017 va_list ap;
11018
11019 va_start (ap, pattern);
11020 if (vasprintf (&nam, pattern, ap) == 0)
11021 abort ();
11022 va_end (ap);
11023 decl = get_identifier (nam);
11024 free (nam);
11025 IDENTIFIER_INVENTED (decl) = 1;
11026 return decl;
11027 }
11028
11029 ffeinfoBasictype
11030 ffecom_gfrt_basictype (ffecomGfrt gfrt)
11031 {
11032 assert (gfrt < FFECOM_gfrt);
11033
11034 switch (ffecom_gfrt_type_[gfrt])
11035 {
11036 case FFECOM_rttypeVOID_:
11037 case FFECOM_rttypeVOIDSTAR_:
11038 return FFEINFO_basictypeNONE;
11039
11040 case FFECOM_rttypeFTNINT_:
11041 return FFEINFO_basictypeINTEGER;
11042
11043 case FFECOM_rttypeINTEGER_:
11044 return FFEINFO_basictypeINTEGER;
11045
11046 case FFECOM_rttypeLONGINT_:
11047 return FFEINFO_basictypeINTEGER;
11048
11049 case FFECOM_rttypeLOGICAL_:
11050 return FFEINFO_basictypeLOGICAL;
11051
11052 case FFECOM_rttypeREAL_F2C_:
11053 case FFECOM_rttypeREAL_GNU_:
11054 return FFEINFO_basictypeREAL;
11055
11056 case FFECOM_rttypeCOMPLEX_F2C_:
11057 case FFECOM_rttypeCOMPLEX_GNU_:
11058 return FFEINFO_basictypeCOMPLEX;
11059
11060 case FFECOM_rttypeDOUBLE_:
11061 case FFECOM_rttypeDOUBLEREAL_:
11062 return FFEINFO_basictypeREAL;
11063
11064 case FFECOM_rttypeDBLCMPLX_F2C_:
11065 case FFECOM_rttypeDBLCMPLX_GNU_:
11066 return FFEINFO_basictypeCOMPLEX;
11067
11068 case FFECOM_rttypeCHARACTER_:
11069 return FFEINFO_basictypeCHARACTER;
11070
11071 default:
11072 return FFEINFO_basictypeANY;
11073 }
11074 }
11075
11076 ffeinfoKindtype
11077 ffecom_gfrt_kindtype (ffecomGfrt gfrt)
11078 {
11079 assert (gfrt < FFECOM_gfrt);
11080
11081 switch (ffecom_gfrt_type_[gfrt])
11082 {
11083 case FFECOM_rttypeVOID_:
11084 case FFECOM_rttypeVOIDSTAR_:
11085 return FFEINFO_kindtypeNONE;
11086
11087 case FFECOM_rttypeFTNINT_:
11088 return FFEINFO_kindtypeINTEGER1;
11089
11090 case FFECOM_rttypeINTEGER_:
11091 return FFEINFO_kindtypeINTEGER1;
11092
11093 case FFECOM_rttypeLONGINT_:
11094 return FFEINFO_kindtypeINTEGER4;
11095
11096 case FFECOM_rttypeLOGICAL_:
11097 return FFEINFO_kindtypeLOGICAL1;
11098
11099 case FFECOM_rttypeREAL_F2C_:
11100 case FFECOM_rttypeREAL_GNU_:
11101 return FFEINFO_kindtypeREAL1;
11102
11103 case FFECOM_rttypeCOMPLEX_F2C_:
11104 case FFECOM_rttypeCOMPLEX_GNU_:
11105 return FFEINFO_kindtypeREAL1;
11106
11107 case FFECOM_rttypeDOUBLE_:
11108 case FFECOM_rttypeDOUBLEREAL_:
11109 return FFEINFO_kindtypeREAL2;
11110
11111 case FFECOM_rttypeDBLCMPLX_F2C_:
11112 case FFECOM_rttypeDBLCMPLX_GNU_:
11113 return FFEINFO_kindtypeREAL2;
11114
11115 case FFECOM_rttypeCHARACTER_:
11116 return FFEINFO_kindtypeCHARACTER1;
11117
11118 default:
11119 return FFEINFO_kindtypeANY;
11120 }
11121 }
11122
11123 void
11124 ffecom_init_0 ()
11125 {
11126 tree endlink;
11127 int i;
11128 int j;
11129 tree t;
11130 tree field;
11131 ffetype type;
11132 ffetype base_type;
11133 tree double_ftype_double, double_ftype_double_double;
11134 tree float_ftype_float, float_ftype_float_float;
11135 tree ldouble_ftype_ldouble, ldouble_ftype_ldouble_ldouble;
11136 tree ffecom_tree_ptr_to_fun_type_void;
11137
11138 /* This block of code comes from the now-obsolete cktyps.c. It checks
11139 whether the compiler environment is buggy in known ways, some of which
11140 would, if not explicitly checked here, result in subtle bugs in g77. */
11141
11142 if (ffe_is_do_internal_checks ())
11143 {
11144 static const char names[][12]
11145 =
11146 {"bar", "bletch", "foo", "foobar"};
11147 const char *name;
11148 unsigned long ul;
11149 double fl;
11150
11151 name = bsearch ("foo", &names[0], ARRAY_SIZE (names), sizeof (names[0]),
11152 (int (*)(const void *, const void *)) strcmp);
11153 if (name != &names[2][0])
11154 {
11155 assert ("bsearch doesn't work, #define FFEPROJ_BSEARCH 0 in proj.h"
11156 == NULL);
11157 abort ();
11158 }
11159
11160 ul = strtoul ("123456789", NULL, 10);
11161 if (ul != 123456789L)
11162 {
11163 assert ("strtoul doesn't have enough range, #define FFEPROJ_STRTOUL 0\
11164 in proj.h" == NULL);
11165 abort ();
11166 }
11167
11168 fl = atof ("56.789");
11169 if ((fl < 56.788) || (fl > 56.79))
11170 {
11171 assert ("atof not type double, fix your #include <stdio.h>"
11172 == NULL);
11173 abort ();
11174 }
11175 }
11176
11177 ffecom_outer_function_decl_ = NULL_TREE;
11178 current_function_decl = NULL_TREE;
11179 named_labels = NULL_TREE;
11180 current_binding_level = NULL_BINDING_LEVEL;
11181 free_binding_level = NULL_BINDING_LEVEL;
11182 /* Make the binding_level structure for global names. */
11183 pushlevel (0);
11184 global_binding_level = current_binding_level;
11185 current_binding_level->prep_state = 2;
11186
11187 build_common_tree_nodes (1);
11188
11189 /* Define `int' and `char' first so that dbx will output them first. */
11190 pushdecl (build_decl (TYPE_DECL, get_identifier ("int"),
11191 integer_type_node));
11192 /* CHARACTER*1 is unsigned in ICHAR contexts. */
11193 char_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
11194 pushdecl (build_decl (TYPE_DECL, get_identifier ("char"),
11195 char_type_node));
11196 pushdecl (build_decl (TYPE_DECL, get_identifier ("long int"),
11197 long_integer_type_node));
11198 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned int"),
11199 unsigned_type_node));
11200 pushdecl (build_decl (TYPE_DECL, get_identifier ("long unsigned int"),
11201 long_unsigned_type_node));
11202 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long int"),
11203 long_long_integer_type_node));
11204 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"),
11205 long_long_unsigned_type_node));
11206 pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"),
11207 short_integer_type_node));
11208 pushdecl (build_decl (TYPE_DECL, get_identifier ("short unsigned int"),
11209 short_unsigned_type_node));
11210
11211 /* Set the sizetype before we make other types. This *should* be the
11212 first type we create. */
11213
11214 set_sizetype
11215 (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))));
11216 ffecom_typesize_pointer_
11217 = TREE_INT_CST_LOW (TYPE_SIZE (sizetype)) / BITS_PER_UNIT;
11218
11219 build_common_tree_nodes_2 (0);
11220
11221 /* Define both `signed char' and `unsigned char'. */
11222 pushdecl (build_decl (TYPE_DECL, get_identifier ("signed char"),
11223 signed_char_type_node));
11224
11225 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned char"),
11226 unsigned_char_type_node));
11227
11228 pushdecl (build_decl (TYPE_DECL, get_identifier ("float"),
11229 float_type_node));
11230 pushdecl (build_decl (TYPE_DECL, get_identifier ("double"),
11231 double_type_node));
11232 pushdecl (build_decl (TYPE_DECL, get_identifier ("long double"),
11233 long_double_type_node));
11234
11235 /* For now, override what build_common_tree_nodes has done. */
11236 complex_integer_type_node = ffecom_make_complex_type_ (integer_type_node);
11237 complex_float_type_node = ffecom_make_complex_type_ (float_type_node);
11238 complex_double_type_node = ffecom_make_complex_type_ (double_type_node);
11239 complex_long_double_type_node
11240 = ffecom_make_complex_type_ (long_double_type_node);
11241
11242 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"),
11243 complex_integer_type_node));
11244 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"),
11245 complex_float_type_node));
11246 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"),
11247 complex_double_type_node));
11248 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"),
11249 complex_long_double_type_node));
11250
11251 pushdecl (build_decl (TYPE_DECL, get_identifier ("void"),
11252 void_type_node));
11253 /* We are not going to have real types in C with less than byte alignment,
11254 so we might as well not have any types that claim to have it. */
11255 TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
11256 TYPE_USER_ALIGN (void_type_node) = 0;
11257
11258 string_type_node = build_pointer_type (char_type_node);
11259
11260 ffecom_tree_fun_type_void
11261 = build_function_type (void_type_node, NULL_TREE);
11262
11263 ffecom_tree_ptr_to_fun_type_void
11264 = build_pointer_type (ffecom_tree_fun_type_void);
11265
11266 endlink = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
11267
11268 t = tree_cons (NULL_TREE, float_type_node, endlink);
11269 float_ftype_float = build_function_type (float_type_node, t);
11270 t = tree_cons (NULL_TREE, float_type_node, t);
11271 float_ftype_float_float = build_function_type (float_type_node, t);
11272
11273 t = tree_cons (NULL_TREE, double_type_node, endlink);
11274 double_ftype_double = build_function_type (double_type_node, t);
11275 t = tree_cons (NULL_TREE, double_type_node, t);
11276 double_ftype_double_double = build_function_type (double_type_node, t);
11277
11278 t = tree_cons (NULL_TREE, long_double_type_node, endlink);
11279 ldouble_ftype_ldouble = build_function_type (long_double_type_node, t);
11280 t = tree_cons (NULL_TREE, long_double_type_node, t);
11281 ldouble_ftype_ldouble_ldouble = build_function_type (long_double_type_node,
11282 t);
11283
11284 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11285 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11286 {
11287 ffecom_tree_type[i][j] = NULL_TREE;
11288 ffecom_tree_fun_type[i][j] = NULL_TREE;
11289 ffecom_tree_ptr_to_fun_type[i][j] = NULL_TREE;
11290 ffecom_f2c_typecode_[i][j] = -1;
11291 }
11292
11293 /* Set up standard g77 types. Note that INTEGER and LOGICAL are set
11294 to size FLOAT_TYPE_SIZE because they have to be the same size as
11295 REAL, which also is FLOAT_TYPE_SIZE, according to the standard.
11296 Compiler options and other such stuff that change the ways these
11297 types are set should not affect this particular setup. */
11298
11299 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1]
11300 = t = make_signed_type (FLOAT_TYPE_SIZE);
11301 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer"),
11302 t));
11303 type = ffetype_new ();
11304 base_type = type;
11305 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER1,
11306 type);
11307 ffetype_set_ams (type,
11308 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11309 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11310 ffetype_set_star (base_type,
11311 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11312 type);
11313 ffetype_set_kind (base_type, 1, type);
11314 ffecom_typesize_integer1_ = ffetype_size (type);
11315 assert (ffetype_size (type) == sizeof (ffetargetInteger1));
11316
11317 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER1]
11318 = t = make_unsigned_type (FLOAT_TYPE_SIZE); /* HOLLERITH means unsigned. */
11319 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned"),
11320 t));
11321
11322 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER2]
11323 = t = make_signed_type (CHAR_TYPE_SIZE);
11324 pushdecl (build_decl (TYPE_DECL, get_identifier ("byte"),
11325 t));
11326 type = ffetype_new ();
11327 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER2,
11328 type);
11329 ffetype_set_ams (type,
11330 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11331 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11332 ffetype_set_star (base_type,
11333 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11334 type);
11335 ffetype_set_kind (base_type, 3, type);
11336 assert (ffetype_size (type) == sizeof (ffetargetInteger2));
11337
11338 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER2]
11339 = t = make_unsigned_type (CHAR_TYPE_SIZE);
11340 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned byte"),
11341 t));
11342
11343 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER3]
11344 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11345 pushdecl (build_decl (TYPE_DECL, get_identifier ("word"),
11346 t));
11347 type = ffetype_new ();
11348 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER3,
11349 type);
11350 ffetype_set_ams (type,
11351 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11352 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11353 ffetype_set_star (base_type,
11354 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11355 type);
11356 ffetype_set_kind (base_type, 6, type);
11357 assert (ffetype_size (type) == sizeof (ffetargetInteger3));
11358
11359 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER3]
11360 = t = make_unsigned_type (CHAR_TYPE_SIZE * 2);
11361 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned word"),
11362 t));
11363
11364 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER4]
11365 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11366 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer4"),
11367 t));
11368 type = ffetype_new ();
11369 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER4,
11370 type);
11371 ffetype_set_ams (type,
11372 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11373 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11374 ffetype_set_star (base_type,
11375 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11376 type);
11377 ffetype_set_kind (base_type, 2, type);
11378 assert (ffetype_size (type) == sizeof (ffetargetInteger4));
11379
11380 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER4]
11381 = t = make_unsigned_type (FLOAT_TYPE_SIZE * 2);
11382 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned4"),
11383 t));
11384
11385 #if 0
11386 if (ffe_is_do_internal_checks ()
11387 && LONG_TYPE_SIZE != FLOAT_TYPE_SIZE
11388 && LONG_TYPE_SIZE != CHAR_TYPE_SIZE
11389 && LONG_TYPE_SIZE != SHORT_TYPE_SIZE
11390 && LONG_TYPE_SIZE != LONG_LONG_TYPE_SIZE)
11391 {
11392 fprintf (stderr, "Sorry, no g77 support for LONG_TYPE_SIZE (%d bits) yet.\n",
11393 LONG_TYPE_SIZE);
11394 }
11395 #endif
11396
11397 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL1]
11398 = t = make_signed_type (FLOAT_TYPE_SIZE);
11399 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical"),
11400 t));
11401 type = ffetype_new ();
11402 base_type = type;
11403 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL1,
11404 type);
11405 ffetype_set_ams (type,
11406 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11407 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11408 ffetype_set_star (base_type,
11409 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11410 type);
11411 ffetype_set_kind (base_type, 1, type);
11412 assert (ffetype_size (type) == sizeof (ffetargetLogical1));
11413
11414 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL2]
11415 = t = make_signed_type (CHAR_TYPE_SIZE);
11416 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical2"),
11417 t));
11418 type = ffetype_new ();
11419 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL2,
11420 type);
11421 ffetype_set_ams (type,
11422 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11423 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11424 ffetype_set_star (base_type,
11425 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11426 type);
11427 ffetype_set_kind (base_type, 3, type);
11428 assert (ffetype_size (type) == sizeof (ffetargetLogical2));
11429
11430 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL3]
11431 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11432 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical3"),
11433 t));
11434 type = ffetype_new ();
11435 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL3,
11436 type);
11437 ffetype_set_ams (type,
11438 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11439 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11440 ffetype_set_star (base_type,
11441 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11442 type);
11443 ffetype_set_kind (base_type, 6, type);
11444 assert (ffetype_size (type) == sizeof (ffetargetLogical3));
11445
11446 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL4]
11447 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11448 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical4"),
11449 t));
11450 type = ffetype_new ();
11451 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL4,
11452 type);
11453 ffetype_set_ams (type,
11454 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11455 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11456 ffetype_set_star (base_type,
11457 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11458 type);
11459 ffetype_set_kind (base_type, 2, type);
11460 assert (ffetype_size (type) == sizeof (ffetargetLogical4));
11461
11462 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
11463 = t = make_node (REAL_TYPE);
11464 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE;
11465 pushdecl (build_decl (TYPE_DECL, get_identifier ("real"),
11466 t));
11467 layout_type (t);
11468 type = ffetype_new ();
11469 base_type = type;
11470 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREAL1,
11471 type);
11472 ffetype_set_ams (type,
11473 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11474 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11475 ffetype_set_star (base_type,
11476 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11477 type);
11478 ffetype_set_kind (base_type, 1, type);
11479 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
11480 = FFETARGET_f2cTYREAL;
11481 assert (ffetype_size (type) == sizeof (ffetargetReal1));
11482
11483 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREALDOUBLE]
11484 = t = make_node (REAL_TYPE);
11485 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE * 2; /* Always twice REAL. */
11486 pushdecl (build_decl (TYPE_DECL, get_identifier ("double precision"),
11487 t));
11488 layout_type (t);
11489 type = ffetype_new ();
11490 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREALDOUBLE,
11491 type);
11492 ffetype_set_ams (type,
11493 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11494 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11495 ffetype_set_star (base_type,
11496 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11497 type);
11498 ffetype_set_kind (base_type, 2, type);
11499 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]
11500 = FFETARGET_f2cTYDREAL;
11501 assert (ffetype_size (type) == sizeof (ffetargetReal2));
11502
11503 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
11504 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]);
11505 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex"),
11506 t));
11507 type = ffetype_new ();
11508 base_type = type;
11509 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREAL1,
11510 type);
11511 ffetype_set_ams (type,
11512 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11513 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11514 ffetype_set_star (base_type,
11515 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11516 type);
11517 ffetype_set_kind (base_type, 1, type);
11518 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
11519 = FFETARGET_f2cTYCOMPLEX;
11520 assert (ffetype_size (type) == sizeof (ffetargetComplex1));
11521
11522 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREALDOUBLE]
11523 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]);
11524 pushdecl (build_decl (TYPE_DECL, get_identifier ("double complex"),
11525 t));
11526 type = ffetype_new ();
11527 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREALDOUBLE,
11528 type);
11529 ffetype_set_ams (type,
11530 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11531 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11532 ffetype_set_star (base_type,
11533 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11534 type);
11535 ffetype_set_kind (base_type, 2,
11536 type);
11537 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL2]
11538 = FFETARGET_f2cTYDCOMPLEX;
11539 assert (ffetype_size (type) == sizeof (ffetargetComplex2));
11540
11541 /* Make function and ptr-to-function types for non-CHARACTER types. */
11542
11543 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11544 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11545 {
11546 if ((t = ffecom_tree_type[i][j]) != NULL_TREE)
11547 {
11548 if (i == FFEINFO_basictypeINTEGER)
11549 {
11550 /* Figure out the smallest INTEGER type that can hold
11551 a pointer on this machine. */
11552 if (GET_MODE_SIZE (TYPE_MODE (t))
11553 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
11554 {
11555 if ((ffecom_pointer_kind_ == FFEINFO_kindtypeNONE)
11556 || (GET_MODE_SIZE (TYPE_MODE (ffecom_tree_type[i][ffecom_pointer_kind_]))
11557 > GET_MODE_SIZE (TYPE_MODE (t))))
11558 ffecom_pointer_kind_ = j;
11559 }
11560 }
11561 else if (i == FFEINFO_basictypeCOMPLEX)
11562 t = void_type_node;
11563 /* For f2c compatibility, REAL functions are really
11564 implemented as DOUBLE PRECISION. */
11565 else if ((i == FFEINFO_basictypeREAL)
11566 && (j == FFEINFO_kindtypeREAL1))
11567 t = ffecom_tree_type
11568 [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2];
11569
11570 t = ffecom_tree_fun_type[i][j] = build_function_type (t,
11571 NULL_TREE);
11572 ffecom_tree_ptr_to_fun_type[i][j] = build_pointer_type (t);
11573 }
11574 }
11575
11576 /* Set up pointer types. */
11577
11578 if (ffecom_pointer_kind_ == FFEINFO_basictypeNONE)
11579 fatal_error ("no INTEGER type can hold a pointer on this configuration");
11580 else if (0 && ffe_is_do_internal_checks ())
11581 fprintf (stderr, "Pointer type kt=%d\n", ffecom_pointer_kind_);
11582 ffetype_set_kind (ffeinfo_type (FFEINFO_basictypeINTEGER,
11583 FFEINFO_kindtypeINTEGERDEFAULT),
11584 7,
11585 ffeinfo_type (FFEINFO_basictypeINTEGER,
11586 ffecom_pointer_kind_));
11587
11588 if (ffe_is_ugly_assign ())
11589 ffecom_label_kind_ = ffecom_pointer_kind_; /* Require ASSIGN etc to this. */
11590 else
11591 ffecom_label_kind_ = FFEINFO_kindtypeINTEGERDEFAULT;
11592 if (0 && ffe_is_do_internal_checks ())
11593 fprintf (stderr, "Label type kt=%d\n", ffecom_label_kind_);
11594
11595 ffecom_integer_type_node
11596 = ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1];
11597 ffecom_integer_zero_node = convert (ffecom_integer_type_node,
11598 integer_zero_node);
11599 ffecom_integer_one_node = convert (ffecom_integer_type_node,
11600 integer_one_node);
11601
11602 /* Yes, the "FLOAT_TYPE_SIZE" references below are intentional.
11603 Turns out that by TYLONG, runtime/libI77/lio.h really means
11604 "whatever size an ftnint is". For consistency and sanity,
11605 com.h and runtime/f2c.h.in agree that flag, ftnint, and ftlen
11606 all are INTEGER, which we also make out of whatever back-end
11607 integer type is FLOAT_TYPE_SIZE bits wide. This change, from
11608 LONG_TYPE_SIZE, for TYLONG and TYLOGICAL, was necessary to
11609 accommodate machines like the Alpha. Note that this suggests
11610 f2c and libf2c are missing a distinction perhaps needed on
11611 some machines between "int" and "long int". -- burley 0.5.5 950215 */
11612
11613 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, FLOAT_TYPE_SIZE,
11614 FFETARGET_f2cTYLONG);
11615 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, SHORT_TYPE_SIZE,
11616 FFETARGET_f2cTYSHORT);
11617 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, CHAR_TYPE_SIZE,
11618 FFETARGET_f2cTYINT1);
11619 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, LONG_LONG_TYPE_SIZE,
11620 FFETARGET_f2cTYQUAD);
11621 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, FLOAT_TYPE_SIZE,
11622 FFETARGET_f2cTYLOGICAL);
11623 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, SHORT_TYPE_SIZE,
11624 FFETARGET_f2cTYLOGICAL2);
11625 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, CHAR_TYPE_SIZE,
11626 FFETARGET_f2cTYLOGICAL1);
11627 /* ~~~Not really such a type in libf2c, e.g. I/O support? */
11628 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, LONG_LONG_TYPE_SIZE,
11629 FFETARGET_f2cTYQUAD);
11630
11631 /* CHARACTER stuff is all special-cased, so it is not handled in the above
11632 loop. CHARACTER items are built as arrays of unsigned char. */
11633
11634 ffecom_tree_type[FFEINFO_basictypeCHARACTER]
11635 [FFEINFO_kindtypeCHARACTER1] = t = char_type_node;
11636 type = ffetype_new ();
11637 base_type = type;
11638 ffeinfo_set_type (FFEINFO_basictypeCHARACTER,
11639 FFEINFO_kindtypeCHARACTER1,
11640 type);
11641 ffetype_set_ams (type,
11642 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11643 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11644 ffetype_set_kind (base_type, 1, type);
11645 assert (ffetype_size (type)
11646 == sizeof (((ffetargetCharacter1) { 0, NULL }).text[0]));
11647
11648 ffecom_tree_fun_type[FFEINFO_basictypeCHARACTER]
11649 [FFEINFO_kindtypeCHARACTER1] = ffecom_tree_fun_type_void;
11650 ffecom_tree_ptr_to_fun_type[FFEINFO_basictypeCHARACTER]
11651 [FFEINFO_kindtypeCHARACTER1]
11652 = ffecom_tree_ptr_to_fun_type_void;
11653 ffecom_f2c_typecode_[FFEINFO_basictypeCHARACTER][FFEINFO_kindtypeCHARACTER1]
11654 = FFETARGET_f2cTYCHAR;
11655
11656 ffecom_f2c_typecode_[FFEINFO_basictypeANY][FFEINFO_kindtypeANY]
11657 = 0;
11658
11659 /* Make multi-return-value type and fields. */
11660
11661 ffecom_multi_type_node_ = make_node (UNION_TYPE);
11662
11663 field = NULL_TREE;
11664
11665 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11666 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11667 {
11668 char name[30];
11669
11670 if (ffecom_tree_type[i][j] == NULL_TREE)
11671 continue; /* Not supported. */
11672 sprintf (&name[0], "bt_%s_kt_%s",
11673 ffeinfo_basictype_string ((ffeinfoBasictype) i),
11674 ffeinfo_kindtype_string ((ffeinfoKindtype) j));
11675 ffecom_multi_fields_[i][j] = build_decl (FIELD_DECL,
11676 get_identifier (name),
11677 ffecom_tree_type[i][j]);
11678 DECL_CONTEXT (ffecom_multi_fields_[i][j])
11679 = ffecom_multi_type_node_;
11680 DECL_ALIGN (ffecom_multi_fields_[i][j]) = 0;
11681 DECL_USER_ALIGN (ffecom_multi_fields_[i][j]) = 0;
11682 TREE_CHAIN (ffecom_multi_fields_[i][j]) = field;
11683 field = ffecom_multi_fields_[i][j];
11684 }
11685
11686 TYPE_FIELDS (ffecom_multi_type_node_) = field;
11687 layout_type (ffecom_multi_type_node_);
11688
11689 /* Subroutines usually return integer because they might have alternate
11690 returns. */
11691
11692 ffecom_tree_subr_type
11693 = build_function_type (integer_type_node, NULL_TREE);
11694 ffecom_tree_ptr_to_subr_type
11695 = build_pointer_type (ffecom_tree_subr_type);
11696 ffecom_tree_blockdata_type
11697 = build_function_type (void_type_node, NULL_TREE);
11698
11699 builtin_function ("__builtin_atanf", float_ftype_float,
11700 BUILT_IN_ATANF, BUILT_IN_NORMAL, "atanf", NULL_TREE);
11701 builtin_function ("__builtin_atan", double_ftype_double,
11702 BUILT_IN_ATAN, BUILT_IN_NORMAL, "atan", NULL_TREE);
11703 builtin_function ("__builtin_atanl", ldouble_ftype_ldouble,
11704 BUILT_IN_ATANL, BUILT_IN_NORMAL, "atanl", NULL_TREE);
11705
11706 builtin_function ("__builtin_atan2f", float_ftype_float_float,
11707 BUILT_IN_ATAN2F, BUILT_IN_NORMAL, "atan2f", NULL_TREE);
11708 builtin_function ("__builtin_atan2", double_ftype_double_double,
11709 BUILT_IN_ATAN2, BUILT_IN_NORMAL, "atan2", NULL_TREE);
11710 builtin_function ("__builtin_atan2l", ldouble_ftype_ldouble_ldouble,
11711 BUILT_IN_ATAN2L, BUILT_IN_NORMAL, "atan2l", NULL_TREE);
11712
11713 builtin_function ("__builtin_cosf", float_ftype_float,
11714 BUILT_IN_COSF, BUILT_IN_NORMAL, "cosf", NULL_TREE);
11715 builtin_function ("__builtin_cos", double_ftype_double,
11716 BUILT_IN_COS, BUILT_IN_NORMAL, "cos", NULL_TREE);
11717 builtin_function ("__builtin_cosl", ldouble_ftype_ldouble,
11718 BUILT_IN_COSL, BUILT_IN_NORMAL, "cosl", NULL_TREE);
11719
11720 builtin_function ("__builtin_expf", float_ftype_float,
11721 BUILT_IN_EXPF, BUILT_IN_NORMAL, "expf", NULL_TREE);
11722 builtin_function ("__builtin_exp", double_ftype_double,
11723 BUILT_IN_EXP, BUILT_IN_NORMAL, "exp", NULL_TREE);
11724 builtin_function ("__builtin_expl", ldouble_ftype_ldouble,
11725 BUILT_IN_EXPL, BUILT_IN_NORMAL, "expl", NULL_TREE);
11726
11727 builtin_function ("__builtin_floorf", float_ftype_float,
11728 BUILT_IN_FLOORF, BUILT_IN_NORMAL, "floorf", NULL_TREE);
11729 builtin_function ("__builtin_floor", double_ftype_double,
11730 BUILT_IN_FLOOR, BUILT_IN_NORMAL, "floor", NULL_TREE);
11731 builtin_function ("__builtin_floorl", ldouble_ftype_ldouble,
11732 BUILT_IN_FLOORL, BUILT_IN_NORMAL, "floorl", NULL_TREE);
11733
11734 builtin_function ("__builtin_fmodf", float_ftype_float_float,
11735 BUILT_IN_FMODF, BUILT_IN_NORMAL, "fmodf", NULL_TREE);
11736 builtin_function ("__builtin_fmod", double_ftype_double_double,
11737 BUILT_IN_FMOD, BUILT_IN_NORMAL, "fmod", NULL_TREE);
11738 builtin_function ("__builtin_fmodl", ldouble_ftype_ldouble_ldouble,
11739 BUILT_IN_FMODL, BUILT_IN_NORMAL, "fmodl", NULL_TREE);
11740
11741 builtin_function ("__builtin_logf", float_ftype_float,
11742 BUILT_IN_LOGF, BUILT_IN_NORMAL, "logf", NULL_TREE);
11743 builtin_function ("__builtin_log", double_ftype_double,
11744 BUILT_IN_LOG, BUILT_IN_NORMAL, "log", NULL_TREE);
11745 builtin_function ("__builtin_logl", ldouble_ftype_ldouble,
11746 BUILT_IN_LOGL, BUILT_IN_NORMAL, "logl", NULL_TREE);
11747
11748 builtin_function ("__builtin_powf", float_ftype_float_float,
11749 BUILT_IN_POWF, BUILT_IN_NORMAL, "powf", NULL_TREE);
11750 builtin_function ("__builtin_pow", double_ftype_double_double,
11751 BUILT_IN_POW, BUILT_IN_NORMAL, "pow", NULL_TREE);
11752 builtin_function ("__builtin_powl", ldouble_ftype_ldouble_ldouble,
11753 BUILT_IN_POWL, BUILT_IN_NORMAL, "powl", NULL_TREE);
11754
11755 builtin_function ("__builtin_sinf", float_ftype_float,
11756 BUILT_IN_SINF, BUILT_IN_NORMAL, "sinf", NULL_TREE);
11757 builtin_function ("__builtin_sin", double_ftype_double,
11758 BUILT_IN_SIN, BUILT_IN_NORMAL, "sin", NULL_TREE);
11759 builtin_function ("__builtin_sinl", ldouble_ftype_ldouble,
11760 BUILT_IN_SINL, BUILT_IN_NORMAL, "sinl", NULL_TREE);
11761
11762 builtin_function ("__builtin_sqrtf", float_ftype_float,
11763 BUILT_IN_SQRTF, BUILT_IN_NORMAL, "sqrtf", NULL_TREE);
11764 builtin_function ("__builtin_sqrt", double_ftype_double,
11765 BUILT_IN_SQRT, BUILT_IN_NORMAL, "sqrt", NULL_TREE);
11766 builtin_function ("__builtin_sqrtl", ldouble_ftype_ldouble,
11767 BUILT_IN_SQRTL, BUILT_IN_NORMAL, "sqrtl", NULL_TREE);
11768
11769 builtin_function ("__builtin_tanf", float_ftype_float,
11770 BUILT_IN_TANF, BUILT_IN_NORMAL, "tanf", NULL_TREE);
11771 builtin_function ("__builtin_tan", double_ftype_double,
11772 BUILT_IN_TAN, BUILT_IN_NORMAL, "tan", NULL_TREE);
11773 builtin_function ("__builtin_tanl", ldouble_ftype_ldouble,
11774 BUILT_IN_TANL, BUILT_IN_NORMAL, "tanl", NULL_TREE);
11775
11776 pedantic_lvalues = FALSE;
11777
11778 ffecom_f2c_make_type_ (&ffecom_f2c_integer_type_node,
11779 FFECOM_f2cINTEGER,
11780 "integer");
11781 ffecom_f2c_make_type_ (&ffecom_f2c_address_type_node,
11782 FFECOM_f2cADDRESS,
11783 "address");
11784 ffecom_f2c_make_type_ (&ffecom_f2c_real_type_node,
11785 FFECOM_f2cREAL,
11786 "real");
11787 ffecom_f2c_make_type_ (&ffecom_f2c_doublereal_type_node,
11788 FFECOM_f2cDOUBLEREAL,
11789 "doublereal");
11790 ffecom_f2c_make_type_ (&ffecom_f2c_complex_type_node,
11791 FFECOM_f2cCOMPLEX,
11792 "complex");
11793 ffecom_f2c_make_type_ (&ffecom_f2c_doublecomplex_type_node,
11794 FFECOM_f2cDOUBLECOMPLEX,
11795 "doublecomplex");
11796 ffecom_f2c_make_type_ (&ffecom_f2c_longint_type_node,
11797 FFECOM_f2cLONGINT,
11798 "longint");
11799 ffecom_f2c_make_type_ (&ffecom_f2c_logical_type_node,
11800 FFECOM_f2cLOGICAL,
11801 "logical");
11802 ffecom_f2c_make_type_ (&ffecom_f2c_flag_type_node,
11803 FFECOM_f2cFLAG,
11804 "flag");
11805 ffecom_f2c_make_type_ (&ffecom_f2c_ftnlen_type_node,
11806 FFECOM_f2cFTNLEN,
11807 "ftnlen");
11808 ffecom_f2c_make_type_ (&ffecom_f2c_ftnint_type_node,
11809 FFECOM_f2cFTNINT,
11810 "ftnint");
11811
11812 ffecom_f2c_ftnlen_zero_node
11813 = convert (ffecom_f2c_ftnlen_type_node, integer_zero_node);
11814
11815 ffecom_f2c_ftnlen_one_node
11816 = convert (ffecom_f2c_ftnlen_type_node, integer_one_node);
11817
11818 ffecom_f2c_ftnlen_two_node = build_int_2 (2, 0);
11819 TREE_TYPE (ffecom_f2c_ftnlen_two_node) = ffecom_integer_type_node;
11820
11821 ffecom_f2c_ptr_to_ftnlen_type_node
11822 = build_pointer_type (ffecom_f2c_ftnlen_type_node);
11823
11824 ffecom_f2c_ptr_to_ftnint_type_node
11825 = build_pointer_type (ffecom_f2c_ftnint_type_node);
11826
11827 ffecom_f2c_ptr_to_integer_type_node
11828 = build_pointer_type (ffecom_f2c_integer_type_node);
11829
11830 ffecom_f2c_ptr_to_real_type_node
11831 = build_pointer_type (ffecom_f2c_real_type_node);
11832
11833 ffecom_float_zero_ = build_real (float_type_node, dconst0);
11834 ffecom_double_zero_ = build_real (double_type_node, dconst0);
11835 {
11836 REAL_VALUE_TYPE point_5;
11837
11838 REAL_ARITHMETIC (point_5, RDIV_EXPR, dconst1, dconst2);
11839 ffecom_float_half_ = build_real (float_type_node, point_5);
11840 ffecom_double_half_ = build_real (double_type_node, point_5);
11841 }
11842
11843 /* Do "extern int xargc;". */
11844
11845 ffecom_tree_xargc_ = build_decl (VAR_DECL,
11846 get_identifier ("f__xargc"),
11847 integer_type_node);
11848 DECL_EXTERNAL (ffecom_tree_xargc_) = 1;
11849 TREE_STATIC (ffecom_tree_xargc_) = 1;
11850 TREE_PUBLIC (ffecom_tree_xargc_) = 1;
11851 ffecom_tree_xargc_ = start_decl (ffecom_tree_xargc_, FALSE);
11852 finish_decl (ffecom_tree_xargc_, NULL_TREE, FALSE);
11853
11854 #if 0 /* This is being fixed, and seems to be working now. */
11855 if ((FLOAT_TYPE_SIZE != 32)
11856 || (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))) != 32))
11857 {
11858 warning ("configuration: REAL, INTEGER, and LOGICAL are %d bits wide,",
11859 (int) FLOAT_TYPE_SIZE);
11860 warning ("and pointers are %d bits wide, but g77 doesn't yet work",
11861 (int) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))));
11862 warning ("properly unless they all are 32 bits wide");
11863 warning ("Please keep this in mind before you report bugs.");
11864 }
11865 #endif
11866
11867 #if 0 /* Code in ste.c that would crash has been commented out. */
11868 if (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
11869 < TYPE_PRECISION (string_type_node))
11870 /* I/O will probably crash. */
11871 warning ("configuration: char * holds %d bits, but ftnlen only %d",
11872 TYPE_PRECISION (string_type_node),
11873 TYPE_PRECISION (ffecom_f2c_ftnlen_type_node));
11874 #endif
11875
11876 #if 0 /* ASSIGN-related stuff has been changed to accommodate this. */
11877 if (TYPE_PRECISION (ffecom_integer_type_node)
11878 < TYPE_PRECISION (string_type_node))
11879 /* ASSIGN 10 TO I will crash. */
11880 warning ("configuration: char * holds %d bits, but INTEGER only %d --\n\
11881 ASSIGN statement might fail",
11882 TYPE_PRECISION (string_type_node),
11883 TYPE_PRECISION (ffecom_integer_type_node));
11884 #endif
11885 }
11886
11887 /* ffecom_init_2 -- Initialize
11888
11889 ffecom_init_2(); */
11890
11891 void
11892 ffecom_init_2 ()
11893 {
11894 assert (ffecom_outer_function_decl_ == NULL_TREE);
11895 assert (current_function_decl == NULL_TREE);
11896 assert (ffecom_which_entrypoint_decl_ == NULL_TREE);
11897
11898 ffecom_master_arglist_ = NULL;
11899 ++ffecom_num_fns_;
11900 ffecom_primary_entry_ = NULL;
11901 ffecom_is_altreturning_ = FALSE;
11902 ffecom_func_result_ = NULL_TREE;
11903 ffecom_multi_retval_ = NULL_TREE;
11904 }
11905
11906 /* ffecom_list_expr -- Transform list of exprs into gcc tree
11907
11908 tree t;
11909 ffebld expr; // FFE opITEM list.
11910 tree = ffecom_list_expr(expr);
11911
11912 List of actual args is transformed into corresponding gcc backend list. */
11913
11914 tree
11915 ffecom_list_expr (ffebld expr)
11916 {
11917 tree list;
11918 tree *plist = &list;
11919 tree trail = NULL_TREE; /* Append char length args here. */
11920 tree *ptrail = &trail;
11921 tree length;
11922
11923 while (expr != NULL)
11924 {
11925 tree texpr = ffecom_arg_expr (ffebld_head (expr), &length);
11926
11927 if (texpr == error_mark_node)
11928 return error_mark_node;
11929
11930 *plist = build_tree_list (NULL_TREE, texpr);
11931 plist = &TREE_CHAIN (*plist);
11932 expr = ffebld_trail (expr);
11933 if (length != NULL_TREE)
11934 {
11935 *ptrail = build_tree_list (NULL_TREE, length);
11936 ptrail = &TREE_CHAIN (*ptrail);
11937 }
11938 }
11939
11940 *plist = trail;
11941
11942 return list;
11943 }
11944
11945 /* ffecom_list_ptr_to_expr -- Transform list of exprs into gcc tree
11946
11947 tree t;
11948 ffebld expr; // FFE opITEM list.
11949 tree = ffecom_list_ptr_to_expr(expr);
11950
11951 List of actual args is transformed into corresponding gcc backend list for
11952 use in calling an external procedure (vs. a statement function). */
11953
11954 tree
11955 ffecom_list_ptr_to_expr (ffebld expr)
11956 {
11957 tree list;
11958 tree *plist = &list;
11959 tree trail = NULL_TREE; /* Append char length args here. */
11960 tree *ptrail = &trail;
11961 tree length;
11962
11963 while (expr != NULL)
11964 {
11965 tree texpr = ffecom_arg_ptr_to_expr (ffebld_head (expr), &length);
11966
11967 if (texpr == error_mark_node)
11968 return error_mark_node;
11969
11970 *plist = build_tree_list (NULL_TREE, texpr);
11971 plist = &TREE_CHAIN (*plist);
11972 expr = ffebld_trail (expr);
11973 if (length != NULL_TREE)
11974 {
11975 *ptrail = build_tree_list (NULL_TREE, length);
11976 ptrail = &TREE_CHAIN (*ptrail);
11977 }
11978 }
11979
11980 *plist = trail;
11981
11982 return list;
11983 }
11984
11985 /* Obtain gcc's LABEL_DECL tree for label. */
11986
11987 tree
11988 ffecom_lookup_label (ffelab label)
11989 {
11990 tree glabel;
11991
11992 if (ffelab_hook (label) == NULL_TREE)
11993 {
11994 char labelname[16];
11995
11996 switch (ffelab_type (label))
11997 {
11998 case FFELAB_typeLOOPEND:
11999 case FFELAB_typeNOTLOOP:
12000 case FFELAB_typeENDIF:
12001 sprintf (labelname, "%" ffelabValue_f "u", ffelab_value (label));
12002 glabel = build_decl (LABEL_DECL, get_identifier (labelname),
12003 void_type_node);
12004 DECL_CONTEXT (glabel) = current_function_decl;
12005 DECL_MODE (glabel) = VOIDmode;
12006 break;
12007
12008 case FFELAB_typeFORMAT:
12009 glabel = build_decl (VAR_DECL,
12010 ffecom_get_invented_identifier
12011 ("__g77_format_%d", (int) ffelab_value (label)),
12012 build_type_variant (build_array_type
12013 (char_type_node,
12014 NULL_TREE),
12015 1, 0));
12016 TREE_CONSTANT (glabel) = 1;
12017 TREE_STATIC (glabel) = 1;
12018 DECL_CONTEXT (glabel) = current_function_decl;
12019 DECL_INITIAL (glabel) = NULL;
12020 make_decl_rtl (glabel, NULL);
12021 expand_decl (glabel);
12022
12023 ffecom_save_tree_forever (glabel);
12024
12025 break;
12026
12027 case FFELAB_typeANY:
12028 glabel = error_mark_node;
12029 break;
12030
12031 default:
12032 assert ("bad label type" == NULL);
12033 glabel = NULL;
12034 break;
12035 }
12036 ffelab_set_hook (label, glabel);
12037 }
12038 else
12039 {
12040 glabel = ffelab_hook (label);
12041 }
12042
12043 return glabel;
12044 }
12045
12046 /* Stabilizes the arguments. Don't use this if the lhs and rhs come from
12047 a single source specification (as in the fourth argument of MVBITS).
12048 If the type is NULL_TREE, the type of lhs is used to make the type of
12049 the MODIFY_EXPR. */
12050
12051 tree
12052 ffecom_modify (tree newtype, tree lhs,
12053 tree rhs)
12054 {
12055 if (lhs == error_mark_node || rhs == error_mark_node)
12056 return error_mark_node;
12057
12058 if (newtype == NULL_TREE)
12059 newtype = TREE_TYPE (lhs);
12060
12061 if (TREE_SIDE_EFFECTS (lhs))
12062 lhs = stabilize_reference (lhs);
12063
12064 return ffecom_2s (MODIFY_EXPR, newtype, lhs, rhs);
12065 }
12066
12067 /* Register source file name. */
12068
12069 void
12070 ffecom_file (const char *name)
12071 {
12072 ffecom_file_ (name);
12073 }
12074
12075 /* ffecom_notify_init_storage -- An aggregate storage is now fully init'ed
12076
12077 ffestorag st;
12078 ffecom_notify_init_storage(st);
12079
12080 Gets called when all possible units in an aggregate storage area (a LOCAL
12081 with equivalences or a COMMON) have been initialized. The initialization
12082 info either is in ffestorag_init or, if that is NULL,
12083 ffestorag_accretion:
12084
12085 ffestorag_init may contain an opCONTER or opARRTER. opCONTER may occur
12086 even for an array if the array is one element in length!
12087
12088 ffestorag_accretion will contain an opACCTER. It is much like an
12089 opARRTER except it has an ffebit object in it instead of just a size.
12090 The back end can use the info in the ffebit object, if it wants, to
12091 reduce the amount of actual initialization, but in any case it should
12092 kill the ffebit object when done. Also, set accretion to NULL but
12093 init to a non-NULL value.
12094
12095 After performing initialization, DO NOT set init to NULL, because that'll
12096 tell the front end it is ok for more initialization to happen. Instead,
12097 set init to an opANY expression or some such thing that you can use to
12098 tell that you've already initialized the object.
12099
12100 27-Oct-91 JCB 1.1
12101 Support two-pass FFE. */
12102
12103 void
12104 ffecom_notify_init_storage (ffestorag st)
12105 {
12106 ffebld init; /* The initialization expression. */
12107
12108 if (ffestorag_init (st) == NULL)
12109 {
12110 init = ffestorag_accretion (st);
12111 assert (init != NULL);
12112 ffestorag_set_accretion (st, NULL);
12113 ffestorag_set_accretes (st, 0);
12114 ffestorag_set_init (st, init);
12115 }
12116 }
12117
12118 /* ffecom_notify_init_symbol -- A symbol is now fully init'ed
12119
12120 ffesymbol s;
12121 ffecom_notify_init_symbol(s);
12122
12123 Gets called when all possible units in a symbol (not placed in COMMON
12124 or involved in EQUIVALENCE, unless it as yet has no ffestorag object)
12125 have been initialized. The initialization info either is in
12126 ffesymbol_init or, if that is NULL, ffesymbol_accretion:
12127
12128 ffesymbol_init may contain an opCONTER or opARRTER. opCONTER may occur
12129 even for an array if the array is one element in length!
12130
12131 ffesymbol_accretion will contain an opACCTER. It is much like an
12132 opARRTER except it has an ffebit object in it instead of just a size.
12133 The back end can use the info in the ffebit object, if it wants, to
12134 reduce the amount of actual initialization, but in any case it should
12135 kill the ffebit object when done. Also, set accretion to NULL but
12136 init to a non-NULL value.
12137
12138 After performing initialization, DO NOT set init to NULL, because that'll
12139 tell the front end it is ok for more initialization to happen. Instead,
12140 set init to an opANY expression or some such thing that you can use to
12141 tell that you've already initialized the object.
12142
12143 27-Oct-91 JCB 1.1
12144 Support two-pass FFE. */
12145
12146 void
12147 ffecom_notify_init_symbol (ffesymbol s)
12148 {
12149 ffebld init; /* The initialization expression. */
12150
12151 if (ffesymbol_storage (s) == NULL)
12152 return; /* Do nothing until COMMON/EQUIVALENCE
12153 possibilities checked. */
12154
12155 if ((ffesymbol_init (s) == NULL)
12156 && ((init = ffesymbol_accretion (s)) != NULL))
12157 {
12158 ffesymbol_set_accretion (s, NULL);
12159 ffesymbol_set_accretes (s, 0);
12160 ffesymbol_set_init (s, init);
12161 }
12162 }
12163
12164 /* ffecom_notify_primary_entry -- Learn which is the primary entry point
12165
12166 ffesymbol s;
12167 ffecom_notify_primary_entry(s);
12168
12169 Gets called when implicit or explicit PROGRAM statement seen or when
12170 FUNCTION, SUBROUTINE, or BLOCK DATA statement seen, with the primary
12171 global symbol that serves as the entry point. */
12172
12173 void
12174 ffecom_notify_primary_entry (ffesymbol s)
12175 {
12176 ffecom_primary_entry_ = s;
12177 ffecom_primary_entry_kind_ = ffesymbol_kind (s);
12178
12179 if ((ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
12180 || (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE))
12181 ffecom_primary_entry_is_proc_ = TRUE;
12182 else
12183 ffecom_primary_entry_is_proc_ = FALSE;
12184
12185 if (!ffe_is_silent ())
12186 {
12187 if (ffecom_primary_entry_kind_ == FFEINFO_kindPROGRAM)
12188 fprintf (stderr, "%s:\n", ffesymbol_text (s));
12189 else
12190 fprintf (stderr, " %s:\n", ffesymbol_text (s));
12191 }
12192
12193 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
12194 {
12195 ffebld list;
12196 ffebld arg;
12197
12198 for (list = ffesymbol_dummyargs (s);
12199 list != NULL;
12200 list = ffebld_trail (list))
12201 {
12202 arg = ffebld_head (list);
12203 if (ffebld_op (arg) == FFEBLD_opSTAR)
12204 {
12205 ffecom_is_altreturning_ = TRUE;
12206 break;
12207 }
12208 }
12209 }
12210 }
12211
12212 FILE *
12213 ffecom_open_include (char *name, ffewhereLine l, ffewhereColumn c)
12214 {
12215 return ffecom_open_include_ (name, l, c);
12216 }
12217
12218 /* ffecom_ptr_to_expr -- Transform expr into gcc tree with & in front
12219
12220 tree t;
12221 ffebld expr; // FFE expression.
12222 tree = ffecom_ptr_to_expr(expr);
12223
12224 Like ffecom_expr, but sticks address-of in front of most things. */
12225
12226 tree
12227 ffecom_ptr_to_expr (ffebld expr)
12228 {
12229 tree item;
12230 ffeinfoBasictype bt;
12231 ffeinfoKindtype kt;
12232 ffesymbol s;
12233
12234 assert (expr != NULL);
12235
12236 switch (ffebld_op (expr))
12237 {
12238 case FFEBLD_opSYMTER:
12239 s = ffebld_symter (expr);
12240 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
12241 {
12242 ffecomGfrt ix;
12243
12244 ix = ffeintrin_gfrt_indirect (ffebld_symter_implementation (expr));
12245 assert (ix != FFECOM_gfrt);
12246 if ((item = ffecom_gfrt_[ix]) == NULL_TREE)
12247 {
12248 ffecom_make_gfrt_ (ix);
12249 item = ffecom_gfrt_[ix];
12250 }
12251 }
12252 else
12253 {
12254 item = ffesymbol_hook (s).decl_tree;
12255 if (item == NULL_TREE)
12256 {
12257 s = ffecom_sym_transform_ (s);
12258 item = ffesymbol_hook (s).decl_tree;
12259 }
12260 }
12261 assert (item != NULL);
12262 if (item == error_mark_node)
12263 return item;
12264 if (!ffesymbol_hook (s).addr)
12265 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12266 item);
12267 return item;
12268
12269 case FFEBLD_opARRAYREF:
12270 return ffecom_arrayref_ (NULL_TREE, expr, 1);
12271
12272 case FFEBLD_opCONTER:
12273
12274 bt = ffeinfo_basictype (ffebld_info (expr));
12275 kt = ffeinfo_kindtype (ffebld_info (expr));
12276
12277 item = ffecom_constantunion (&ffebld_constant_union
12278 (ffebld_conter (expr)), bt, kt,
12279 ffecom_tree_type[bt][kt]);
12280 if (item == error_mark_node)
12281 return error_mark_node;
12282 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12283 item);
12284 return item;
12285
12286 case FFEBLD_opANY:
12287 return error_mark_node;
12288
12289 default:
12290 bt = ffeinfo_basictype (ffebld_info (expr));
12291 kt = ffeinfo_kindtype (ffebld_info (expr));
12292
12293 item = ffecom_expr (expr);
12294 if (item == error_mark_node)
12295 return error_mark_node;
12296
12297 /* The back end currently optimizes a bit too zealously for us, in that
12298 we fail JCB001 if the following block of code is omitted. It checks
12299 to see if the transformed expression is a symbol or array reference,
12300 and encloses it in a SAVE_EXPR if that is the case. */
12301
12302 STRIP_NOPS (item);
12303 if ((TREE_CODE (item) == VAR_DECL)
12304 || (TREE_CODE (item) == PARM_DECL)
12305 || (TREE_CODE (item) == RESULT_DECL)
12306 || (TREE_CODE (item) == INDIRECT_REF)
12307 || (TREE_CODE (item) == ARRAY_REF)
12308 || (TREE_CODE (item) == COMPONENT_REF)
12309 #ifdef OFFSET_REF
12310 || (TREE_CODE (item) == OFFSET_REF)
12311 #endif
12312 || (TREE_CODE (item) == BUFFER_REF)
12313 || (TREE_CODE (item) == REALPART_EXPR)
12314 || (TREE_CODE (item) == IMAGPART_EXPR))
12315 {
12316 item = ffecom_save_tree (item);
12317 }
12318
12319 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12320 item);
12321 return item;
12322 }
12323
12324 assert ("fall-through error" == NULL);
12325 return error_mark_node;
12326 }
12327
12328 /* Obtain a temp var with given data type.
12329
12330 size is FFETARGET_charactersizeNONE for a non-CHARACTER type
12331 or >= 0 for a CHARACTER type.
12332
12333 elements is -1 for a scalar or > 0 for an array of type. */
12334
12335 tree
12336 ffecom_make_tempvar (const char *commentary, tree type,
12337 ffetargetCharacterSize size, int elements)
12338 {
12339 tree t;
12340 static int mynumber;
12341
12342 assert (current_binding_level->prep_state < 2);
12343
12344 if (type == error_mark_node)
12345 return error_mark_node;
12346
12347 if (size != FFETARGET_charactersizeNONE)
12348 type = build_array_type (type,
12349 build_range_type (ffecom_f2c_ftnlen_type_node,
12350 ffecom_f2c_ftnlen_one_node,
12351 build_int_2 (size, 0)));
12352 if (elements != -1)
12353 type = build_array_type (type,
12354 build_range_type (integer_type_node,
12355 integer_zero_node,
12356 build_int_2 (elements - 1,
12357 0)));
12358 t = build_decl (VAR_DECL,
12359 ffecom_get_invented_identifier ("__g77_%s_%d",
12360 commentary,
12361 mynumber++),
12362 type);
12363
12364 t = start_decl (t, FALSE);
12365 finish_decl (t, NULL_TREE, FALSE);
12366
12367 return t;
12368 }
12369
12370 /* Prepare argument pointer to expression.
12371
12372 Like ffecom_prepare_expr, except for expressions to be evaluated
12373 via ffecom_arg_ptr_to_expr. */
12374
12375 void
12376 ffecom_prepare_arg_ptr_to_expr (ffebld expr)
12377 {
12378 /* ~~For now, it seems to be the same thing. */
12379 ffecom_prepare_expr (expr);
12380 return;
12381 }
12382
12383 /* End of preparations. */
12384
12385 bool
12386 ffecom_prepare_end (void)
12387 {
12388 int prep_state = current_binding_level->prep_state;
12389
12390 assert (prep_state < 2);
12391 current_binding_level->prep_state = 2;
12392
12393 return (prep_state == 1) ? TRUE : FALSE;
12394 }
12395
12396 /* Prepare expression.
12397
12398 This is called before any code is generated for the current block.
12399 It scans the expression, declares any temporaries that might be needed
12400 during evaluation of the expression, and stores those temporaries in
12401 the appropriate "hook" fields of the expression. `dest', if not NULL,
12402 specifies the destination that ffecom_expr_ will see, in case that
12403 helps avoid generating unused temporaries.
12404
12405 ~~Improve to avoid allocating unused temporaries by taking `dest'
12406 into account vis-a-vis aliasing requirements of complex/character
12407 functions. */
12408
12409 void
12410 ffecom_prepare_expr_ (ffebld expr, ffebld dest UNUSED)
12411 {
12412 ffeinfoBasictype bt;
12413 ffeinfoKindtype kt;
12414 ffetargetCharacterSize sz;
12415 tree tempvar = NULL_TREE;
12416
12417 assert (current_binding_level->prep_state < 2);
12418
12419 if (! expr)
12420 return;
12421
12422 bt = ffeinfo_basictype (ffebld_info (expr));
12423 kt = ffeinfo_kindtype (ffebld_info (expr));
12424 sz = ffeinfo_size (ffebld_info (expr));
12425
12426 /* Generate whatever temporaries are needed to represent the result
12427 of the expression. */
12428
12429 if (bt == FFEINFO_basictypeCHARACTER)
12430 {
12431 while (ffebld_op (expr) == FFEBLD_opPAREN)
12432 expr = ffebld_left (expr);
12433 }
12434
12435 switch (ffebld_op (expr))
12436 {
12437 default:
12438 /* Don't make temps for SYMTER, CONTER, etc. */
12439 if (ffebld_arity (expr) == 0)
12440 break;
12441
12442 switch (bt)
12443 {
12444 case FFEINFO_basictypeCOMPLEX:
12445 if (ffebld_op (expr) == FFEBLD_opFUNCREF)
12446 {
12447 ffesymbol s;
12448
12449 if (ffebld_op (ffebld_left (expr)) != FFEBLD_opSYMTER)
12450 break;
12451
12452 s = ffebld_symter (ffebld_left (expr));
12453 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT
12454 || (ffesymbol_where (s) != FFEINFO_whereINTRINSIC
12455 && ! ffesymbol_is_f2c (s))
12456 || (ffesymbol_where (s) == FFEINFO_whereINTRINSIC
12457 && ! ffe_is_f2c_library ()))
12458 break;
12459 }
12460 else if (ffebld_op (expr) == FFEBLD_opPOWER)
12461 {
12462 /* Requires special treatment. There's no POW_CC function
12463 in libg2c, so POW_ZZ is used, which means we always
12464 need a double-complex temp, not a single-complex. */
12465 kt = FFEINFO_kindtypeREAL2;
12466 }
12467 else if (ffebld_op (expr) != FFEBLD_opDIVIDE)
12468 /* The other ops don't need temps for complex operands. */
12469 break;
12470
12471 /* ~~~Avoid making temps for some intrinsics, such as AIMAG(C),
12472 REAL(C). See 19990325-0.f, routine `check', for cases. */
12473 tempvar = ffecom_make_tempvar ("complex",
12474 ffecom_tree_type
12475 [FFEINFO_basictypeCOMPLEX][kt],
12476 FFETARGET_charactersizeNONE,
12477 -1);
12478 break;
12479
12480 case FFEINFO_basictypeCHARACTER:
12481 if (ffebld_op (expr) != FFEBLD_opFUNCREF)
12482 break;
12483
12484 if (sz == FFETARGET_charactersizeNONE)
12485 /* ~~Kludge alert! This should someday be fixed. */
12486 sz = 24;
12487
12488 tempvar = ffecom_make_tempvar ("char", char_type_node, sz, -1);
12489 break;
12490
12491 default:
12492 break;
12493 }
12494 break;
12495
12496 case FFEBLD_opCONCATENATE:
12497 {
12498 /* This gets special handling, because only one set of temps
12499 is needed for a tree of these -- the tree is treated as
12500 a flattened list of concatenations when generating code. */
12501
12502 ffecomConcatList_ catlist;
12503 tree ltmp, itmp, result;
12504 int count;
12505 int i;
12506
12507 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
12508 count = ffecom_concat_list_count_ (catlist);
12509
12510 if (count >= 2)
12511 {
12512 ltmp
12513 = ffecom_make_tempvar ("concat_len",
12514 ffecom_f2c_ftnlen_type_node,
12515 FFETARGET_charactersizeNONE, count);
12516 itmp
12517 = ffecom_make_tempvar ("concat_item",
12518 ffecom_f2c_address_type_node,
12519 FFETARGET_charactersizeNONE, count);
12520 result
12521 = ffecom_make_tempvar ("concat_res",
12522 char_type_node,
12523 ffecom_concat_list_maxlen_ (catlist),
12524 -1);
12525
12526 tempvar = make_tree_vec (3);
12527 TREE_VEC_ELT (tempvar, 0) = ltmp;
12528 TREE_VEC_ELT (tempvar, 1) = itmp;
12529 TREE_VEC_ELT (tempvar, 2) = result;
12530 }
12531
12532 for (i = 0; i < count; ++i)
12533 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist,
12534 i));
12535
12536 ffecom_concat_list_kill_ (catlist);
12537
12538 if (tempvar)
12539 {
12540 ffebld_nonter_set_hook (expr, tempvar);
12541 current_binding_level->prep_state = 1;
12542 }
12543 }
12544 return;
12545
12546 case FFEBLD_opCONVERT:
12547 if (bt == FFEINFO_basictypeCHARACTER
12548 && ((ffebld_size_known (ffebld_left (expr))
12549 == FFETARGET_charactersizeNONE)
12550 || (ffebld_size_known (ffebld_left (expr)) >= sz)))
12551 tempvar = ffecom_make_tempvar ("convert", char_type_node, sz, -1);
12552 break;
12553 }
12554
12555 if (tempvar)
12556 {
12557 ffebld_nonter_set_hook (expr, tempvar);
12558 current_binding_level->prep_state = 1;
12559 }
12560
12561 /* Prepare subexpressions for this expr. */
12562
12563 switch (ffebld_op (expr))
12564 {
12565 case FFEBLD_opPERCENT_LOC:
12566 ffecom_prepare_ptr_to_expr (ffebld_left (expr));
12567 break;
12568
12569 case FFEBLD_opPERCENT_VAL:
12570 case FFEBLD_opPERCENT_REF:
12571 ffecom_prepare_expr (ffebld_left (expr));
12572 break;
12573
12574 case FFEBLD_opPERCENT_DESCR:
12575 ffecom_prepare_arg_ptr_to_expr (ffebld_left (expr));
12576 break;
12577
12578 case FFEBLD_opITEM:
12579 {
12580 ffebld item;
12581
12582 for (item = expr;
12583 item != NULL;
12584 item = ffebld_trail (item))
12585 if (ffebld_head (item) != NULL)
12586 ffecom_prepare_expr (ffebld_head (item));
12587 }
12588 break;
12589
12590 default:
12591 /* Need to handle character conversion specially. */
12592 switch (ffebld_arity (expr))
12593 {
12594 case 2:
12595 ffecom_prepare_expr (ffebld_left (expr));
12596 ffecom_prepare_expr (ffebld_right (expr));
12597 break;
12598
12599 case 1:
12600 ffecom_prepare_expr (ffebld_left (expr));
12601 break;
12602
12603 default:
12604 break;
12605 }
12606 }
12607
12608 return;
12609 }
12610
12611 /* Prepare expression for reading and writing.
12612
12613 Like ffecom_prepare_expr, except for expressions to be evaluated
12614 via ffecom_expr_rw. */
12615
12616 void
12617 ffecom_prepare_expr_rw (tree type, ffebld expr)
12618 {
12619 /* This is all we support for now. */
12620 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
12621
12622 /* ~~For now, it seems to be the same thing. */
12623 ffecom_prepare_expr (expr);
12624 return;
12625 }
12626
12627 /* Prepare expression for writing.
12628
12629 Like ffecom_prepare_expr, except for expressions to be evaluated
12630 via ffecom_expr_w. */
12631
12632 void
12633 ffecom_prepare_expr_w (tree type, ffebld expr)
12634 {
12635 /* This is all we support for now. */
12636 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
12637
12638 /* ~~For now, it seems to be the same thing. */
12639 ffecom_prepare_expr (expr);
12640 return;
12641 }
12642
12643 /* Prepare expression for returning.
12644
12645 Like ffecom_prepare_expr, except for expressions to be evaluated
12646 via ffecom_return_expr. */
12647
12648 void
12649 ffecom_prepare_return_expr (ffebld expr)
12650 {
12651 assert (current_binding_level->prep_state < 2);
12652
12653 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE
12654 && ffecom_is_altreturning_
12655 && expr != NULL)
12656 ffecom_prepare_expr (expr);
12657 }
12658
12659 /* Prepare pointer to expression.
12660
12661 Like ffecom_prepare_expr, except for expressions to be evaluated
12662 via ffecom_ptr_to_expr. */
12663
12664 void
12665 ffecom_prepare_ptr_to_expr (ffebld expr)
12666 {
12667 /* ~~For now, it seems to be the same thing. */
12668 ffecom_prepare_expr (expr);
12669 return;
12670 }
12671
12672 /* Transform expression into constant pointer-to-expression tree.
12673
12674 If the expression can be transformed into a pointer-to-expression tree
12675 that is constant, that is done, and the tree returned. Else NULL_TREE
12676 is returned.
12677
12678 That way, a caller can attempt to provide compile-time initialization
12679 of a variable and, if that fails, *then* choose to start a new block
12680 and resort to using temporaries, as appropriate. */
12681
12682 tree
12683 ffecom_ptr_to_const_expr (ffebld expr)
12684 {
12685 if (! expr)
12686 return integer_zero_node;
12687
12688 if (ffebld_op (expr) == FFEBLD_opANY)
12689 return error_mark_node;
12690
12691 if (ffebld_arity (expr) == 0
12692 && (ffebld_op (expr) != FFEBLD_opSYMTER
12693 || ffebld_where (expr) == FFEINFO_whereCOMMON
12694 || ffebld_where (expr) == FFEINFO_whereGLOBAL
12695 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
12696 {
12697 tree t;
12698
12699 t = ffecom_ptr_to_expr (expr);
12700 assert (TREE_CONSTANT (t));
12701 return t;
12702 }
12703
12704 return NULL_TREE;
12705 }
12706
12707 /* ffecom_return_expr -- Returns return-value expr given alt return expr
12708
12709 tree rtn; // NULL_TREE means use expand_null_return()
12710 ffebld expr; // NULL if no alt return expr to RETURN stmt
12711 rtn = ffecom_return_expr(expr);
12712
12713 Based on the program unit type and other info (like return function
12714 type, return master function type when alternate ENTRY points,
12715 whether subroutine has any alternate RETURN points, etc), returns the
12716 appropriate expression to be returned to the caller, or NULL_TREE
12717 meaning no return value or the caller expects it to be returned somewhere
12718 else (which is handled by other parts of this module). */
12719
12720 tree
12721 ffecom_return_expr (ffebld expr)
12722 {
12723 tree rtn;
12724
12725 switch (ffecom_primary_entry_kind_)
12726 {
12727 case FFEINFO_kindPROGRAM:
12728 case FFEINFO_kindBLOCKDATA:
12729 rtn = NULL_TREE;
12730 break;
12731
12732 case FFEINFO_kindSUBROUTINE:
12733 if (!ffecom_is_altreturning_)
12734 rtn = NULL_TREE; /* No alt returns, never an expr. */
12735 else if (expr == NULL)
12736 rtn = integer_zero_node;
12737 else
12738 rtn = ffecom_expr (expr);
12739 break;
12740
12741 case FFEINFO_kindFUNCTION:
12742 if ((ffecom_multi_retval_ != NULL_TREE)
12743 || (ffesymbol_basictype (ffecom_primary_entry_)
12744 == FFEINFO_basictypeCHARACTER)
12745 || ((ffesymbol_basictype (ffecom_primary_entry_)
12746 == FFEINFO_basictypeCOMPLEX)
12747 && (ffecom_num_entrypoints_ == 0)
12748 && ffesymbol_is_f2c (ffecom_primary_entry_)))
12749 { /* Value is returned by direct assignment
12750 into (implicit) dummy. */
12751 rtn = NULL_TREE;
12752 break;
12753 }
12754 rtn = ffecom_func_result_;
12755 #if 0
12756 /* Spurious error if RETURN happens before first reference! So elide
12757 this code. In particular, for debugging registry, rtn should always
12758 be non-null after all, but TREE_USED won't be set until we encounter
12759 a reference in the code. Perfectly okay (but weird) code that,
12760 e.g., has "GOTO 20;10 RETURN;20 RTN=0;GOTO 10", would result in
12761 this diagnostic for no reason. Have people use -O -Wuninitialized
12762 and leave it to the back end to find obviously weird cases. */
12763
12764 /* Used to "assert(rtn != NULL_TREE);" here, but it's kind of a valid
12765 situation; if the return value has never been referenced, it won't
12766 have a tree under 2pass mode. */
12767 if ((rtn == NULL_TREE)
12768 || !TREE_USED (rtn))
12769 {
12770 ffebad_start (FFEBAD_RETURN_VALUE_UNSET);
12771 ffebad_here (0, ffesymbol_where_line (ffecom_primary_entry_),
12772 ffesymbol_where_column (ffecom_primary_entry_));
12773 ffebad_string (ffesymbol_text (ffesymbol_funcresult
12774 (ffecom_primary_entry_)));
12775 ffebad_finish ();
12776 }
12777 #endif
12778 break;
12779
12780 default:
12781 assert ("bad unit kind" == NULL);
12782 case FFEINFO_kindANY:
12783 rtn = error_mark_node;
12784 break;
12785 }
12786
12787 return rtn;
12788 }
12789
12790 /* Do save_expr only if tree is not error_mark_node. */
12791
12792 tree
12793 ffecom_save_tree (tree t)
12794 {
12795 return save_expr (t);
12796 }
12797
12798 /* Start a compound statement (block). */
12799
12800 void
12801 ffecom_start_compstmt (void)
12802 {
12803 bison_rule_pushlevel_ ();
12804 }
12805
12806 /* Public entry point for front end to access start_decl. */
12807
12808 tree
12809 ffecom_start_decl (tree decl, bool is_initialized)
12810 {
12811 DECL_INITIAL (decl) = is_initialized ? error_mark_node : NULL_TREE;
12812 return start_decl (decl, FALSE);
12813 }
12814
12815 /* ffecom_sym_commit -- Symbol's state being committed to reality
12816
12817 ffesymbol s;
12818 ffecom_sym_commit(s);
12819
12820 Does whatever the backend needs when a symbol is committed after having
12821 been backtrackable for a period of time. */
12822
12823 void
12824 ffecom_sym_commit (ffesymbol s UNUSED)
12825 {
12826 assert (!ffesymbol_retractable ());
12827 }
12828
12829 /* ffecom_sym_end_transition -- Perform end transition on all symbols
12830
12831 ffecom_sym_end_transition();
12832
12833 Does backend-specific stuff and also calls ffest_sym_end_transition
12834 to do the necessary FFE stuff.
12835
12836 Backtracking is never enabled when this fn is called, so don't worry
12837 about it. */
12838
12839 ffesymbol
12840 ffecom_sym_end_transition (ffesymbol s)
12841 {
12842 ffestorag st;
12843
12844 assert (!ffesymbol_retractable ());
12845
12846 s = ffest_sym_end_transition (s);
12847
12848 if ((ffesymbol_kind (s) == FFEINFO_kindBLOCKDATA)
12849 && (ffesymbol_where (s) == FFEINFO_whereGLOBAL))
12850 {
12851 ffecom_list_blockdata_
12852 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
12853 FFEINTRIN_specNONE,
12854 FFEINTRIN_impNONE),
12855 ffecom_list_blockdata_);
12856 }
12857
12858 /* This is where we finally notice that a symbol has partial initialization
12859 and finalize it. */
12860
12861 if (ffesymbol_accretion (s) != NULL)
12862 {
12863 assert (ffesymbol_init (s) == NULL);
12864 ffecom_notify_init_symbol (s);
12865 }
12866 else if (((st = ffesymbol_storage (s)) != NULL)
12867 && ((st = ffestorag_parent (st)) != NULL)
12868 && (ffestorag_accretion (st) != NULL))
12869 {
12870 assert (ffestorag_init (st) == NULL);
12871 ffecom_notify_init_storage (st);
12872 }
12873
12874 if ((ffesymbol_kind (s) == FFEINFO_kindCOMMON)
12875 && (ffesymbol_where (s) == FFEINFO_whereLOCAL)
12876 && (ffesymbol_storage (s) != NULL))
12877 {
12878 ffecom_list_common_
12879 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
12880 FFEINTRIN_specNONE,
12881 FFEINTRIN_impNONE),
12882 ffecom_list_common_);
12883 }
12884
12885 return s;
12886 }
12887
12888 /* ffecom_sym_exec_transition -- Perform exec transition on all symbols
12889
12890 ffecom_sym_exec_transition();
12891
12892 Does backend-specific stuff and also calls ffest_sym_exec_transition
12893 to do the necessary FFE stuff.
12894
12895 See the long-winded description in ffecom_sym_learned for info
12896 on handling the situation where backtracking is inhibited. */
12897
12898 ffesymbol
12899 ffecom_sym_exec_transition (ffesymbol s)
12900 {
12901 s = ffest_sym_exec_transition (s);
12902
12903 return s;
12904 }
12905
12906 /* ffecom_sym_learned -- Initial or more info gained on symbol after exec
12907
12908 ffesymbol s;
12909 s = ffecom_sym_learned(s);
12910
12911 Called when a new symbol is seen after the exec transition or when more
12912 info (perhaps) is gained for an UNCERTAIN symbol. The symbol state when
12913 it arrives here is that all its latest info is updated already, so its
12914 state may be UNCERTAIN or UNDERSTOOD, it might already have the hook
12915 field filled in if its gone through here or exec_transition first, and
12916 so on.
12917
12918 The backend probably wants to check ffesymbol_retractable() to see if
12919 backtracking is in effect. If so, the FFE's changes to the symbol may
12920 be retracted (undone) or committed (ratified), at which time the
12921 appropriate ffecom_sym_retract or _commit function will be called
12922 for that function.
12923
12924 If the backend has its own backtracking mechanism, great, use it so that
12925 committal is a simple operation. Though it doesn't make much difference,
12926 I suppose: the reason for tentative symbol evolution in the FFE is to
12927 enable error detection in weird incorrect statements early and to disable
12928 incorrect error detection on a correct statement. The backend is not
12929 likely to introduce any information that'll get involved in these
12930 considerations, so it is probably just fine that the implementation
12931 model for this fn and for _exec_transition is to not do anything
12932 (besides the required FFE stuff) if ffesymbol_retractable() returns TRUE
12933 and instead wait until ffecom_sym_commit is called (which it never
12934 will be as long as we're using ambiguity-detecting statement analysis in
12935 the FFE, which we are initially to shake out the code, but don't depend
12936 on this), otherwise go ahead and do whatever is needed.
12937
12938 In essence, then, when this fn and _exec_transition get called while
12939 backtracking is enabled, a general mechanism would be to flag which (or
12940 both) of these were called (and in what order? neat question as to what
12941 might happen that I'm too lame to think through right now) and then when
12942 _commit is called reproduce the original calling sequence, if any, for
12943 the two fns (at which point backtracking will, of course, be disabled). */
12944
12945 ffesymbol
12946 ffecom_sym_learned (ffesymbol s)
12947 {
12948 ffestorag_exec_layout (s);
12949
12950 return s;
12951 }
12952
12953 /* ffecom_sym_retract -- Symbol's state being retracted from reality
12954
12955 ffesymbol s;
12956 ffecom_sym_retract(s);
12957
12958 Does whatever the backend needs when a symbol is retracted after having
12959 been backtrackable for a period of time. */
12960
12961 void
12962 ffecom_sym_retract (ffesymbol s UNUSED)
12963 {
12964 assert (!ffesymbol_retractable ());
12965
12966 #if 0 /* GCC doesn't commit any backtrackable sins,
12967 so nothing needed here. */
12968 switch (ffesymbol_hook (s).state)
12969 {
12970 case 0: /* nothing happened yet. */
12971 break;
12972
12973 case 1: /* exec transition happened. */
12974 break;
12975
12976 case 2: /* learned happened. */
12977 break;
12978
12979 case 3: /* learned then exec. */
12980 break;
12981
12982 case 4: /* exec then learned. */
12983 break;
12984
12985 default:
12986 assert ("bad hook state" == NULL);
12987 break;
12988 }
12989 #endif
12990 }
12991
12992 /* Create temporary gcc label. */
12993
12994 tree
12995 ffecom_temp_label ()
12996 {
12997 tree glabel;
12998 static int mynumber = 0;
12999
13000 glabel = build_decl (LABEL_DECL,
13001 ffecom_get_invented_identifier ("__g77_label_%d",
13002 mynumber++),
13003 void_type_node);
13004 DECL_CONTEXT (glabel) = current_function_decl;
13005 DECL_MODE (glabel) = VOIDmode;
13006
13007 return glabel;
13008 }
13009
13010 /* Return an expression that is usable as an arg in a conditional context
13011 (IF, DO WHILE, .NOT., and so on).
13012
13013 Use the one provided for the back end as of >2.6.0. */
13014
13015 tree
13016 ffecom_truth_value (tree expr)
13017 {
13018 return ffe_truthvalue_conversion (expr);
13019 }
13020
13021 /* Return the inversion of a truth value (the inversion of what
13022 ffecom_truth_value builds).
13023
13024 Apparently invert_truthvalue, which is properly in the back end, is
13025 enough for now, so just use it. */
13026
13027 tree
13028 ffecom_truth_value_invert (tree expr)
13029 {
13030 return invert_truthvalue (ffecom_truth_value (expr));
13031 }
13032
13033 /* Return the tree that is the type of the expression, as would be
13034 returned in TREE_TYPE(ffecom_expr(expr)), without otherwise
13035 transforming the expression, generating temporaries, etc. */
13036
13037 tree
13038 ffecom_type_expr (ffebld expr)
13039 {
13040 ffeinfoBasictype bt;
13041 ffeinfoKindtype kt;
13042 tree tree_type;
13043
13044 assert (expr != NULL);
13045
13046 bt = ffeinfo_basictype (ffebld_info (expr));
13047 kt = ffeinfo_kindtype (ffebld_info (expr));
13048 tree_type = ffecom_tree_type[bt][kt];
13049
13050 switch (ffebld_op (expr))
13051 {
13052 case FFEBLD_opCONTER:
13053 case FFEBLD_opSYMTER:
13054 case FFEBLD_opARRAYREF:
13055 case FFEBLD_opUPLUS:
13056 case FFEBLD_opPAREN:
13057 case FFEBLD_opUMINUS:
13058 case FFEBLD_opADD:
13059 case FFEBLD_opSUBTRACT:
13060 case FFEBLD_opMULTIPLY:
13061 case FFEBLD_opDIVIDE:
13062 case FFEBLD_opPOWER:
13063 case FFEBLD_opNOT:
13064 case FFEBLD_opFUNCREF:
13065 case FFEBLD_opSUBRREF:
13066 case FFEBLD_opAND:
13067 case FFEBLD_opOR:
13068 case FFEBLD_opXOR:
13069 case FFEBLD_opNEQV:
13070 case FFEBLD_opEQV:
13071 case FFEBLD_opCONVERT:
13072 case FFEBLD_opLT:
13073 case FFEBLD_opLE:
13074 case FFEBLD_opEQ:
13075 case FFEBLD_opNE:
13076 case FFEBLD_opGT:
13077 case FFEBLD_opGE:
13078 case FFEBLD_opPERCENT_LOC:
13079 return tree_type;
13080
13081 case FFEBLD_opACCTER:
13082 case FFEBLD_opARRTER:
13083 case FFEBLD_opITEM:
13084 case FFEBLD_opSTAR:
13085 case FFEBLD_opBOUNDS:
13086 case FFEBLD_opREPEAT:
13087 case FFEBLD_opLABTER:
13088 case FFEBLD_opLABTOK:
13089 case FFEBLD_opIMPDO:
13090 case FFEBLD_opCONCATENATE:
13091 case FFEBLD_opSUBSTR:
13092 default:
13093 assert ("bad op for ffecom_type_expr" == NULL);
13094 /* Fall through. */
13095 case FFEBLD_opANY:
13096 return error_mark_node;
13097 }
13098 }
13099
13100 /* Return PARM_DECL for arg#1 of master fn containing alternate ENTRY points
13101
13102 If the PARM_DECL already exists, return it, else create it. It's an
13103 integer_type_node argument for the master function that implements a
13104 subroutine or function with more than one entrypoint and is bound at
13105 run time with the entrypoint number (0 for SUBROUTINE/FUNCTION, 1 for
13106 first ENTRY statement, and so on). */
13107
13108 tree
13109 ffecom_which_entrypoint_decl ()
13110 {
13111 assert (ffecom_which_entrypoint_decl_ != NULL_TREE);
13112
13113 return ffecom_which_entrypoint_decl_;
13114 }
13115 \f
13116 /* The following sections consists of private and public functions
13117 that have the same names and perform roughly the same functions
13118 as counterparts in the C front end. Changes in the C front end
13119 might affect how things should be done here. Only functions
13120 needed by the back end should be public here; the rest should
13121 be private (static in the C sense). Functions needed by other
13122 g77 front-end modules should be accessed by them via public
13123 ffecom_* names, which should themselves call private versions
13124 in this section so the private versions are easy to recognize
13125 when upgrading to a new gcc and finding interesting changes
13126 in the front end.
13127
13128 Functions named after rule "foo:" in c-parse.y are named
13129 "bison_rule_foo_" so they are easy to find. */
13130
13131 static void
13132 bison_rule_pushlevel_ ()
13133 {
13134 emit_line_note (input_filename, input_line);
13135 pushlevel (0);
13136 clear_last_expr ();
13137 expand_start_bindings (0);
13138 }
13139
13140 static tree
13141 bison_rule_compstmt_ ()
13142 {
13143 tree t;
13144 int keep = kept_level_p ();
13145
13146 /* Make the temps go away. */
13147 if (! keep)
13148 current_binding_level->names = NULL_TREE;
13149
13150 emit_line_note (input_filename, input_line);
13151 expand_end_bindings (getdecls (), keep, 0);
13152 t = poplevel (keep, 1, 0);
13153
13154 return t;
13155 }
13156
13157 /* Return a definition for a builtin function named NAME and whose data type
13158 is TYPE. TYPE should be a function type with argument types.
13159 FUNCTION_CODE tells later passes how to compile calls to this function.
13160 See tree.h for its possible values.
13161
13162 If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
13163 the name to be called if we can't opencode the function. If
13164 ATTRS is nonzero, use that for the function's attribute list. */
13165
13166 tree
13167 builtin_function (const char *name, tree type, int function_code,
13168 enum built_in_class class,
13169 const char *library_name,
13170 tree attrs ATTRIBUTE_UNUSED)
13171 {
13172 tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
13173 DECL_EXTERNAL (decl) = 1;
13174 TREE_PUBLIC (decl) = 1;
13175 if (library_name)
13176 SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
13177 make_decl_rtl (decl, NULL);
13178 pushdecl (decl);
13179 DECL_BUILT_IN_CLASS (decl) = class;
13180 DECL_FUNCTION_CODE (decl) = function_code;
13181
13182 return decl;
13183 }
13184
13185 /* Handle when a new declaration NEWDECL
13186 has the same name as an old one OLDDECL
13187 in the same binding contour.
13188 Prints an error message if appropriate.
13189
13190 If safely possible, alter OLDDECL to look like NEWDECL, and return 1.
13191 Otherwise, return 0. */
13192
13193 static int
13194 duplicate_decls (tree newdecl, tree olddecl)
13195 {
13196 int types_match = 1;
13197 int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
13198 && DECL_INITIAL (newdecl) != 0);
13199 tree oldtype = TREE_TYPE (olddecl);
13200 tree newtype = TREE_TYPE (newdecl);
13201
13202 if (olddecl == newdecl)
13203 return 1;
13204
13205 if (TREE_CODE (newtype) == ERROR_MARK
13206 || TREE_CODE (oldtype) == ERROR_MARK)
13207 types_match = 0;
13208
13209 /* New decl is completely inconsistent with the old one =>
13210 tell caller to replace the old one.
13211 This is always an error except in the case of shadowing a builtin. */
13212 if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
13213 return 0;
13214
13215 /* For real parm decl following a forward decl,
13216 return 1 so old decl will be reused. */
13217 if (types_match && TREE_CODE (newdecl) == PARM_DECL
13218 && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
13219 return 1;
13220
13221 /* The new declaration is the same kind of object as the old one.
13222 The declarations may partially match. Print warnings if they don't
13223 match enough. Ultimately, copy most of the information from the new
13224 decl to the old one, and keep using the old one. */
13225
13226 if (TREE_CODE (olddecl) == FUNCTION_DECL
13227 && DECL_BUILT_IN (olddecl))
13228 {
13229 /* A function declaration for a built-in function. */
13230 if (!TREE_PUBLIC (newdecl))
13231 return 0;
13232 else if (!types_match)
13233 {
13234 /* Accept the return type of the new declaration if same modes. */
13235 tree oldreturntype = TREE_TYPE (TREE_TYPE (olddecl));
13236 tree newreturntype = TREE_TYPE (TREE_TYPE (newdecl));
13237
13238 if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
13239 {
13240 /* Function types may be shared, so we can't just modify
13241 the return type of olddecl's function type. */
13242 tree newtype
13243 = build_function_type (newreturntype,
13244 TYPE_ARG_TYPES (TREE_TYPE (olddecl)));
13245
13246 types_match = 1;
13247 if (types_match)
13248 TREE_TYPE (olddecl) = newtype;
13249 }
13250 }
13251 if (!types_match)
13252 return 0;
13253 }
13254 else if (TREE_CODE (olddecl) == FUNCTION_DECL
13255 && DECL_SOURCE_LINE (olddecl) == 0)
13256 {
13257 /* A function declaration for a predeclared function
13258 that isn't actually built in. */
13259 if (!TREE_PUBLIC (newdecl))
13260 return 0;
13261 else if (!types_match)
13262 {
13263 /* If the types don't match, preserve volatility indication.
13264 Later on, we will discard everything else about the
13265 default declaration. */
13266 TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
13267 }
13268 }
13269
13270 /* Copy all the DECL_... slots specified in the new decl
13271 except for any that we copy here from the old type.
13272
13273 Past this point, we don't change OLDTYPE and NEWTYPE
13274 even if we change the types of NEWDECL and OLDDECL. */
13275
13276 if (types_match)
13277 {
13278 /* Merge the data types specified in the two decls. */
13279 if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
13280 TREE_TYPE (newdecl)
13281 = TREE_TYPE (olddecl)
13282 = TREE_TYPE (newdecl);
13283
13284 /* Lay the type out, unless already done. */
13285 if (oldtype != TREE_TYPE (newdecl))
13286 {
13287 if (TREE_TYPE (newdecl) != error_mark_node)
13288 layout_type (TREE_TYPE (newdecl));
13289 if (TREE_CODE (newdecl) != FUNCTION_DECL
13290 && TREE_CODE (newdecl) != TYPE_DECL
13291 && TREE_CODE (newdecl) != CONST_DECL)
13292 layout_decl (newdecl, 0);
13293 }
13294 else
13295 {
13296 /* Since the type is OLDDECL's, make OLDDECL's size go with. */
13297 DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
13298 DECL_SIZE_UNIT (newdecl) = DECL_SIZE_UNIT (olddecl);
13299 if (TREE_CODE (olddecl) != FUNCTION_DECL)
13300 if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
13301 {
13302 DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
13303 DECL_USER_ALIGN (newdecl) |= DECL_USER_ALIGN (olddecl);
13304 }
13305 }
13306
13307 /* Keep the old rtl since we can safely use it. */
13308 COPY_DECL_RTL (olddecl, newdecl);
13309
13310 /* Merge the type qualifiers. */
13311 if (TREE_READONLY (newdecl))
13312 TREE_READONLY (olddecl) = 1;
13313 if (TREE_THIS_VOLATILE (newdecl))
13314 {
13315 TREE_THIS_VOLATILE (olddecl) = 1;
13316 if (TREE_CODE (newdecl) == VAR_DECL)
13317 make_var_volatile (newdecl);
13318 }
13319
13320 /* Keep source location of definition rather than declaration.
13321 Likewise, keep decl at outer scope. */
13322 if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
13323 || (DECL_CONTEXT (newdecl) != 0 && DECL_CONTEXT (olddecl) == 0))
13324 {
13325 DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
13326 DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl);
13327
13328 if (DECL_CONTEXT (olddecl) == 0
13329 && TREE_CODE (newdecl) != FUNCTION_DECL)
13330 DECL_CONTEXT (newdecl) = 0;
13331 }
13332
13333 /* Merge the unused-warning information. */
13334 if (DECL_IN_SYSTEM_HEADER (olddecl))
13335 DECL_IN_SYSTEM_HEADER (newdecl) = 1;
13336 else if (DECL_IN_SYSTEM_HEADER (newdecl))
13337 DECL_IN_SYSTEM_HEADER (olddecl) = 1;
13338
13339 /* Merge the initialization information. */
13340 if (DECL_INITIAL (newdecl) == 0)
13341 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
13342
13343 /* Merge the section attribute.
13344 We want to issue an error if the sections conflict but that must be
13345 done later in decl_attributes since we are called before attributes
13346 are assigned. */
13347 if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
13348 DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
13349
13350 /* Copy the assembler name. */
13351 COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
13352
13353 if (TREE_CODE (newdecl) == FUNCTION_DECL)
13354 {
13355 DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
13356 DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
13357 TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
13358 TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
13359 DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
13360 DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl);
13361 }
13362 }
13363 /* If cannot merge, then use the new type and qualifiers,
13364 and don't preserve the old rtl. */
13365 else
13366 {
13367 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
13368 TREE_READONLY (olddecl) = TREE_READONLY (newdecl);
13369 TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl);
13370 TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl);
13371 }
13372
13373 /* Merge the storage class information. */
13374 /* For functions, static overrides non-static. */
13375 if (TREE_CODE (newdecl) == FUNCTION_DECL)
13376 {
13377 TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
13378 /* This is since we don't automatically
13379 copy the attributes of NEWDECL into OLDDECL. */
13380 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
13381 /* If this clears `static', clear it in the identifier too. */
13382 if (! TREE_PUBLIC (olddecl))
13383 TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
13384 }
13385 if (DECL_EXTERNAL (newdecl))
13386 {
13387 TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
13388 DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
13389 /* An extern decl does not override previous storage class. */
13390 TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
13391 }
13392 else
13393 {
13394 TREE_STATIC (olddecl) = TREE_STATIC (newdecl);
13395 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
13396 }
13397
13398 /* If either decl says `inline', this fn is inline,
13399 unless its definition was passed already. */
13400 if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
13401 DECL_INLINE (olddecl) = 1;
13402 DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
13403
13404 /* Get rid of any built-in function if new arg types don't match it
13405 or if we have a function definition. */
13406 if (TREE_CODE (newdecl) == FUNCTION_DECL
13407 && DECL_BUILT_IN (olddecl)
13408 && (!types_match || new_is_definition))
13409 {
13410 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
13411 DECL_BUILT_IN_CLASS (olddecl) = NOT_BUILT_IN;
13412 }
13413
13414 /* If redeclaring a builtin function, and not a definition,
13415 it stays built in.
13416 Also preserve various other info from the definition. */
13417 if (TREE_CODE (newdecl) == FUNCTION_DECL && !new_is_definition)
13418 {
13419 if (DECL_BUILT_IN (olddecl))
13420 {
13421 DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
13422 DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
13423 }
13424
13425 DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
13426 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
13427 DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
13428 DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
13429 }
13430
13431 /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
13432 But preserve olddecl's DECL_UID. */
13433 {
13434 register unsigned olddecl_uid = DECL_UID (olddecl);
13435
13436 memcpy ((char *) olddecl + sizeof (struct tree_common),
13437 (char *) newdecl + sizeof (struct tree_common),
13438 sizeof (struct tree_decl) - sizeof (struct tree_common));
13439 DECL_UID (olddecl) = olddecl_uid;
13440 }
13441
13442 return 1;
13443 }
13444
13445 /* Finish processing of a declaration;
13446 install its initial value.
13447 If the length of an array type is not known before,
13448 it must be determined now, from the initial value, or it is an error. */
13449
13450 static void
13451 finish_decl (tree decl, tree init, bool is_top_level)
13452 {
13453 register tree type = TREE_TYPE (decl);
13454 int was_incomplete = (DECL_SIZE (decl) == 0);
13455 bool at_top_level = (current_binding_level == global_binding_level);
13456 bool top_level = is_top_level || at_top_level;
13457
13458 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
13459 level anyway. */
13460 assert (!is_top_level || !at_top_level);
13461
13462 if (TREE_CODE (decl) == PARM_DECL)
13463 assert (init == NULL_TREE);
13464 /* Remember that PARM_DECL doesn't have a DECL_INITIAL field per se -- it
13465 overlaps DECL_ARG_TYPE. */
13466 else if (init == NULL_TREE)
13467 assert (DECL_INITIAL (decl) == NULL_TREE);
13468 else
13469 assert (DECL_INITIAL (decl) == error_mark_node);
13470
13471 if (init != NULL_TREE)
13472 {
13473 if (TREE_CODE (decl) != TYPE_DECL)
13474 DECL_INITIAL (decl) = init;
13475 else
13476 {
13477 /* typedef foo = bar; store the type of bar as the type of foo. */
13478 TREE_TYPE (decl) = TREE_TYPE (init);
13479 DECL_INITIAL (decl) = init = 0;
13480 }
13481 }
13482
13483 /* Deduce size of array from initialization, if not already known */
13484
13485 if (TREE_CODE (type) == ARRAY_TYPE
13486 && TYPE_DOMAIN (type) == 0
13487 && TREE_CODE (decl) != TYPE_DECL)
13488 {
13489 assert (top_level);
13490 assert (was_incomplete);
13491
13492 layout_decl (decl, 0);
13493 }
13494
13495 if (TREE_CODE (decl) == VAR_DECL)
13496 {
13497 if (DECL_SIZE (decl) == NULL_TREE
13498 && TYPE_SIZE (TREE_TYPE (decl)) != NULL_TREE)
13499 layout_decl (decl, 0);
13500
13501 if (DECL_SIZE (decl) == NULL_TREE
13502 && (TREE_STATIC (decl)
13503 ?
13504 /* A static variable with an incomplete type is an error if it is
13505 initialized. Also if it is not file scope. Otherwise, let it
13506 through, but if it is not `extern' then it may cause an error
13507 message later. */
13508 (DECL_INITIAL (decl) != 0 || DECL_CONTEXT (decl) != 0)
13509 :
13510 /* An automatic variable with an incomplete type is an error. */
13511 !DECL_EXTERNAL (decl)))
13512 {
13513 assert ("storage size not known" == NULL);
13514 abort ();
13515 }
13516
13517 if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
13518 && (DECL_SIZE (decl) != 0)
13519 && (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST))
13520 {
13521 assert ("storage size not constant" == NULL);
13522 abort ();
13523 }
13524 }
13525
13526 /* Output the assembler code and/or RTL code for variables and functions,
13527 unless the type is an undefined structure or union. If not, it will get
13528 done when the type is completed. */
13529
13530 if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
13531 {
13532 rest_of_decl_compilation (decl, NULL,
13533 DECL_CONTEXT (decl) == 0,
13534 0);
13535
13536 if (DECL_CONTEXT (decl) != 0)
13537 {
13538 /* Recompute the RTL of a local array now if it used to be an
13539 incomplete type. */
13540 if (was_incomplete
13541 && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
13542 {
13543 /* If we used it already as memory, it must stay in memory. */
13544 TREE_ADDRESSABLE (decl) = TREE_USED (decl);
13545 /* If it's still incomplete now, no init will save it. */
13546 if (DECL_SIZE (decl) == 0)
13547 DECL_INITIAL (decl) = 0;
13548 expand_decl (decl);
13549 }
13550 /* Compute and store the initial value. */
13551 if (TREE_CODE (decl) != FUNCTION_DECL)
13552 expand_decl_init (decl);
13553 }
13554 }
13555 else if (TREE_CODE (decl) == TYPE_DECL)
13556 {
13557 rest_of_decl_compilation (decl, NULL,
13558 DECL_CONTEXT (decl) == 0,
13559 0);
13560 }
13561
13562 /* At the end of a declaration, throw away any variable type sizes of types
13563 defined inside that declaration. There is no use computing them in the
13564 following function definition. */
13565 if (current_binding_level == global_binding_level)
13566 get_pending_sizes ();
13567 }
13568
13569 /* Finish up a function declaration and compile that function
13570 all the way to assembler language output. The free the storage
13571 for the function definition.
13572
13573 This is called after parsing the body of the function definition.
13574
13575 NESTED is nonzero if the function being finished is nested in another. */
13576
13577 static void
13578 finish_function (int nested)
13579 {
13580 register tree fndecl = current_function_decl;
13581
13582 assert (fndecl != NULL_TREE);
13583 if (TREE_CODE (fndecl) != ERROR_MARK)
13584 {
13585 if (nested)
13586 assert (DECL_CONTEXT (fndecl) != NULL_TREE);
13587 else
13588 assert (DECL_CONTEXT (fndecl) == NULL_TREE);
13589 }
13590
13591 /* TREE_READONLY (fndecl) = 1;
13592 This caused &foo to be of type ptr-to-const-function
13593 which then got a warning when stored in a ptr-to-function variable. */
13594
13595 poplevel (1, 0, 1);
13596
13597 if (TREE_CODE (fndecl) != ERROR_MARK)
13598 {
13599 BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
13600
13601 /* Must mark the RESULT_DECL as being in this function. */
13602
13603 DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
13604
13605 /* Obey `register' declarations if `setjmp' is called in this fn. */
13606 /* Generate rtl for function exit. */
13607 expand_function_end (input_filename, input_line, 0);
13608
13609 /* If this is a nested function, protect the local variables in the stack
13610 above us from being collected while we're compiling this function. */
13611 if (nested)
13612 ggc_push_context ();
13613
13614 /* Run the optimizers and output the assembler code for this function. */
13615 rest_of_compilation (fndecl);
13616
13617 /* Undo the GC context switch. */
13618 if (nested)
13619 ggc_pop_context ();
13620 }
13621
13622 if (TREE_CODE (fndecl) != ERROR_MARK
13623 && !nested
13624 && DECL_SAVED_INSNS (fndecl) == 0)
13625 {
13626 /* Stop pointing to the local nodes about to be freed. */
13627 /* But DECL_INITIAL must remain nonzero so we know this was an actual
13628 function definition. */
13629 /* For a nested function, this is done in pop_f_function_context. */
13630 /* If rest_of_compilation set this to 0, leave it 0. */
13631 if (DECL_INITIAL (fndecl) != 0)
13632 DECL_INITIAL (fndecl) = error_mark_node;
13633 DECL_ARGUMENTS (fndecl) = 0;
13634 }
13635
13636 if (!nested)
13637 {
13638 /* Let the error reporting routines know that we're outside a function.
13639 For a nested function, this value is used in pop_c_function_context
13640 and then reset via pop_function_context. */
13641 ffecom_outer_function_decl_ = current_function_decl = NULL;
13642 }
13643 }
13644
13645 /* Plug-in replacement for identifying the name of a decl and, for a
13646 function, what we call it in diagnostics. For now, "program unit"
13647 should suffice, since it's a bit of a hassle to figure out which
13648 of several kinds of things it is. Note that it could conceivably
13649 be a statement function, which probably isn't really a program unit
13650 per se, but if that comes up, it should be easy to check (being a
13651 nested function and all). */
13652
13653 static const char *
13654 ffe_printable_name (tree decl, int v)
13655 {
13656 /* Just to keep GCC quiet about the unused variable.
13657 In theory, differing values of V should produce different
13658 output. */
13659 switch (v)
13660 {
13661 default:
13662 if (TREE_CODE (decl) == ERROR_MARK)
13663 return "erroneous code";
13664 return IDENTIFIER_POINTER (DECL_NAME (decl));
13665 }
13666 }
13667
13668 /* g77's function to print out name of current function that caused
13669 an error. */
13670
13671 static void
13672 ffe_print_error_function (diagnostic_context *context __attribute__((unused)),
13673 const char *file)
13674 {
13675 static ffeglobal last_g = NULL;
13676 static ffesymbol last_s = NULL;
13677 ffeglobal g;
13678 ffesymbol s;
13679 const char *kind;
13680
13681 if ((ffecom_primary_entry_ == NULL)
13682 || (ffesymbol_global (ffecom_primary_entry_) == NULL))
13683 {
13684 g = NULL;
13685 s = NULL;
13686 kind = NULL;
13687 }
13688 else
13689 {
13690 g = ffesymbol_global (ffecom_primary_entry_);
13691 if (ffecom_nested_entry_ == NULL)
13692 {
13693 s = ffecom_primary_entry_;
13694 kind = _(ffeinfo_kind_message (ffesymbol_kind (s)));
13695 }
13696 else
13697 {
13698 s = ffecom_nested_entry_;
13699 kind = _("In statement function");
13700 }
13701 }
13702
13703 if ((last_g != g) || (last_s != s))
13704 {
13705 if (file)
13706 fprintf (stderr, "%s: ", file);
13707
13708 if (s == NULL)
13709 fprintf (stderr, _("Outside of any program unit:\n"));
13710 else
13711 {
13712 const char *name = ffesymbol_text (s);
13713
13714 fprintf (stderr, "%s `%s':\n", kind, name);
13715 }
13716
13717 last_g = g;
13718 last_s = s;
13719 }
13720 }
13721
13722 /* Similar to `lookup_name' but look only at current binding level. */
13723
13724 static tree
13725 lookup_name_current_level (tree name)
13726 {
13727 register tree t;
13728
13729 if (current_binding_level == global_binding_level)
13730 return IDENTIFIER_GLOBAL_VALUE (name);
13731
13732 if (IDENTIFIER_LOCAL_VALUE (name) == 0)
13733 return 0;
13734
13735 for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
13736 if (DECL_NAME (t) == name)
13737 break;
13738
13739 return t;
13740 }
13741
13742 /* Create a new `struct f_binding_level'. */
13743
13744 static struct f_binding_level *
13745 make_binding_level ()
13746 {
13747 /* NOSTRICT */
13748 return ggc_alloc (sizeof (struct f_binding_level));
13749 }
13750
13751 /* Save and restore the variables in this file and elsewhere
13752 that keep track of the progress of compilation of the current function.
13753 Used for nested functions. */
13754
13755 struct f_function
13756 {
13757 struct f_function *next;
13758 tree named_labels;
13759 tree shadowed_labels;
13760 struct f_binding_level *binding_level;
13761 };
13762
13763 struct f_function *f_function_chain;
13764
13765 /* Restore the variables used during compilation of a C function. */
13766
13767 static void
13768 pop_f_function_context ()
13769 {
13770 struct f_function *p = f_function_chain;
13771 tree link;
13772
13773 /* Bring back all the labels that were shadowed. */
13774 for (link = shadowed_labels; link; link = TREE_CHAIN (link))
13775 if (DECL_NAME (TREE_VALUE (link)) != 0)
13776 IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)))
13777 = TREE_VALUE (link);
13778
13779 if (current_function_decl != error_mark_node
13780 && DECL_SAVED_INSNS (current_function_decl) == 0)
13781 {
13782 /* Stop pointing to the local nodes about to be freed. */
13783 /* But DECL_INITIAL must remain nonzero so we know this was an actual
13784 function definition. */
13785 DECL_INITIAL (current_function_decl) = error_mark_node;
13786 DECL_ARGUMENTS (current_function_decl) = 0;
13787 }
13788
13789 pop_function_context ();
13790
13791 f_function_chain = p->next;
13792
13793 named_labels = p->named_labels;
13794 shadowed_labels = p->shadowed_labels;
13795 current_binding_level = p->binding_level;
13796
13797 free (p);
13798 }
13799
13800 /* Save and reinitialize the variables
13801 used during compilation of a C function. */
13802
13803 static void
13804 push_f_function_context ()
13805 {
13806 struct f_function *p
13807 = (struct f_function *) xmalloc (sizeof (struct f_function));
13808
13809 push_function_context ();
13810
13811 p->next = f_function_chain;
13812 f_function_chain = p;
13813
13814 p->named_labels = named_labels;
13815 p->shadowed_labels = shadowed_labels;
13816 p->binding_level = current_binding_level;
13817 }
13818
13819 static void
13820 push_parm_decl (tree parm)
13821 {
13822 int old_immediate_size_expand = immediate_size_expand;
13823
13824 /* Don't try computing parm sizes now -- wait till fn is called. */
13825
13826 immediate_size_expand = 0;
13827
13828 /* Fill in arg stuff. */
13829
13830 DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
13831 DECL_ARG_TYPE_AS_WRITTEN (parm) = TREE_TYPE (parm);
13832 TREE_READONLY (parm) = 1; /* All implementation args are read-only. */
13833
13834 parm = pushdecl (parm);
13835
13836 immediate_size_expand = old_immediate_size_expand;
13837
13838 finish_decl (parm, NULL_TREE, FALSE);
13839 }
13840
13841 /* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, if appropriate. */
13842
13843 static tree
13844 pushdecl_top_level (tree x)
13845 {
13846 register tree t;
13847 register struct f_binding_level *b = current_binding_level;
13848 register tree f = current_function_decl;
13849
13850 current_binding_level = global_binding_level;
13851 current_function_decl = NULL_TREE;
13852 t = pushdecl (x);
13853 current_binding_level = b;
13854 current_function_decl = f;
13855 return t;
13856 }
13857
13858 /* Store the list of declarations of the current level.
13859 This is done for the parameter declarations of a function being defined,
13860 after they are modified in the light of any missing parameters. */
13861
13862 static tree
13863 storedecls (tree decls)
13864 {
13865 return current_binding_level->names = decls;
13866 }
13867
13868 /* Store the parameter declarations into the current function declaration.
13869 This is called after parsing the parameter declarations, before
13870 digesting the body of the function.
13871
13872 For an old-style definition, modify the function's type
13873 to specify at least the number of arguments. */
13874
13875 static void
13876 store_parm_decls (int is_main_program UNUSED)
13877 {
13878 register tree fndecl = current_function_decl;
13879
13880 if (fndecl == error_mark_node)
13881 return;
13882
13883 /* This is a chain of PARM_DECLs from old-style parm declarations. */
13884 DECL_ARGUMENTS (fndecl) = storedecls (nreverse (getdecls ()));
13885
13886 /* Initialize the RTL code for the function. */
13887
13888 init_function_start (fndecl, input_filename, input_line);
13889
13890 /* Set up parameters and prepare for return, for the function. */
13891
13892 expand_function_start (fndecl, 0);
13893 }
13894
13895 static tree
13896 start_decl (tree decl, bool is_top_level)
13897 {
13898 register tree tem;
13899 bool at_top_level = (current_binding_level == global_binding_level);
13900 bool top_level = is_top_level || at_top_level;
13901
13902 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
13903 level anyway. */
13904 assert (!is_top_level || !at_top_level);
13905
13906 if (DECL_INITIAL (decl) != NULL_TREE)
13907 {
13908 assert (DECL_INITIAL (decl) == error_mark_node);
13909 assert (!DECL_EXTERNAL (decl));
13910 }
13911 else if (top_level)
13912 assert ((TREE_STATIC (decl) == 1) || DECL_EXTERNAL (decl) == 1);
13913
13914 /* For Fortran, we by default put things in .common when possible. */
13915 DECL_COMMON (decl) = 1;
13916
13917 /* Add this decl to the current binding level. TEM may equal DECL or it may
13918 be a previous decl of the same name. */
13919 if (is_top_level)
13920 tem = pushdecl_top_level (decl);
13921 else
13922 tem = pushdecl (decl);
13923
13924 /* For a local variable, define the RTL now. */
13925 if (!top_level
13926 /* But not if this is a duplicate decl and we preserved the rtl from the
13927 previous one (which may or may not happen). */
13928 && !DECL_RTL_SET_P (tem))
13929 {
13930 if (TYPE_SIZE (TREE_TYPE (tem)) != 0)
13931 expand_decl (tem);
13932 else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
13933 && DECL_INITIAL (tem) != 0)
13934 expand_decl (tem);
13935 }
13936
13937 return tem;
13938 }
13939
13940 /* Create the FUNCTION_DECL for a function definition.
13941 DECLSPECS and DECLARATOR are the parts of the declaration;
13942 they describe the function's name and the type it returns,
13943 but twisted together in a fashion that parallels the syntax of C.
13944
13945 This function creates a binding context for the function body
13946 as well as setting up the FUNCTION_DECL in current_function_decl.
13947
13948 Returns 1 on success. If the DECLARATOR is not suitable for a function
13949 (it defines a datum instead), we return 0, which tells
13950 ffe_parse_file to report a parse error.
13951
13952 NESTED is nonzero for a function nested within another function. */
13953
13954 static void
13955 start_function (tree name, tree type, int nested, int public)
13956 {
13957 tree decl1;
13958 tree restype;
13959 int old_immediate_size_expand = immediate_size_expand;
13960
13961 named_labels = 0;
13962 shadowed_labels = 0;
13963
13964 /* Don't expand any sizes in the return type of the function. */
13965 immediate_size_expand = 0;
13966
13967 if (nested)
13968 {
13969 assert (!public);
13970 assert (current_function_decl != NULL_TREE);
13971 assert (DECL_CONTEXT (current_function_decl) == NULL_TREE);
13972 }
13973 else
13974 {
13975 assert (current_function_decl == NULL_TREE);
13976 }
13977
13978 if (TREE_CODE (type) == ERROR_MARK)
13979 decl1 = current_function_decl = error_mark_node;
13980 else
13981 {
13982 decl1 = build_decl (FUNCTION_DECL,
13983 name,
13984 type);
13985 TREE_PUBLIC (decl1) = public ? 1 : 0;
13986 if (nested)
13987 DECL_INLINE (decl1) = 1;
13988 TREE_STATIC (decl1) = 1;
13989 DECL_EXTERNAL (decl1) = 0;
13990
13991 announce_function (decl1);
13992
13993 /* Make the init_value nonzero so pushdecl knows this is not tentative.
13994 error_mark_node is replaced below (in poplevel) with the BLOCK. */
13995 DECL_INITIAL (decl1) = error_mark_node;
13996
13997 /* Record the decl so that the function name is defined. If we already have
13998 a decl for this name, and it is a FUNCTION_DECL, use the old decl. */
13999
14000 current_function_decl = pushdecl (decl1);
14001 }
14002
14003 if (!nested)
14004 ffecom_outer_function_decl_ = current_function_decl;
14005
14006 pushlevel (0);
14007 current_binding_level->prep_state = 2;
14008
14009 if (TREE_CODE (current_function_decl) != ERROR_MARK)
14010 {
14011 make_decl_rtl (current_function_decl, NULL);
14012
14013 restype = TREE_TYPE (TREE_TYPE (current_function_decl));
14014 DECL_RESULT (current_function_decl)
14015 = build_decl (RESULT_DECL, NULL_TREE, restype);
14016 }
14017
14018 if (!nested && (TREE_CODE (current_function_decl) != ERROR_MARK))
14019 TREE_ADDRESSABLE (current_function_decl) = 1;
14020
14021 immediate_size_expand = old_immediate_size_expand;
14022 }
14023 \f
14024 /* Here are the public functions the GNU back end needs. */
14025
14026 tree
14027 convert (tree type, tree expr)
14028 {
14029 register tree e = expr;
14030 register enum tree_code code = TREE_CODE (type);
14031
14032 if (type == TREE_TYPE (e)
14033 || TREE_CODE (e) == ERROR_MARK)
14034 return e;
14035 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
14036 return fold (build1 (NOP_EXPR, type, e));
14037 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
14038 || code == ERROR_MARK)
14039 return error_mark_node;
14040 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
14041 {
14042 assert ("void value not ignored as it ought to be" == NULL);
14043 return error_mark_node;
14044 }
14045 if (code == VOID_TYPE)
14046 return build1 (CONVERT_EXPR, type, e);
14047 if ((code != RECORD_TYPE)
14048 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
14049 e = ffecom_1 (REALPART_EXPR, TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e))),
14050 e);
14051 if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
14052 return fold (convert_to_integer (type, e));
14053 if (code == POINTER_TYPE)
14054 return fold (convert_to_pointer (type, e));
14055 if (code == REAL_TYPE)
14056 return fold (convert_to_real (type, e));
14057 if (code == COMPLEX_TYPE)
14058 return fold (convert_to_complex (type, e));
14059 if (code == RECORD_TYPE)
14060 return fold (ffecom_convert_to_complex_ (type, e));
14061
14062 assert ("conversion to non-scalar type requested" == NULL);
14063 return error_mark_node;
14064 }
14065
14066 /* Return the list of declarations of the current level.
14067 Note that this list is in reverse order unless/until
14068 you nreverse it; and when you do nreverse it, you must
14069 store the result back using `storedecls' or you will lose. */
14070
14071 tree
14072 getdecls ()
14073 {
14074 return current_binding_level->names;
14075 }
14076
14077 /* Nonzero if we are currently in the global binding level. */
14078
14079 int
14080 global_bindings_p ()
14081 {
14082 return current_binding_level == global_binding_level;
14083 }
14084
14085 static void
14086 ffecom_init_decl_processing ()
14087 {
14088 malloc_init ();
14089
14090 ffe_init_0 ();
14091 }
14092
14093 /* Delete the node BLOCK from the current binding level.
14094 This is used for the block inside a stmt expr ({...})
14095 so that the block can be reinserted where appropriate. */
14096
14097 static void
14098 delete_block (tree block)
14099 {
14100 tree t;
14101 if (current_binding_level->blocks == block)
14102 current_binding_level->blocks = TREE_CHAIN (block);
14103 for (t = current_binding_level->blocks; t;)
14104 {
14105 if (TREE_CHAIN (t) == block)
14106 TREE_CHAIN (t) = TREE_CHAIN (block);
14107 else
14108 t = TREE_CHAIN (t);
14109 }
14110 TREE_CHAIN (block) = NULL;
14111 /* Clear TREE_USED which is always set by poplevel.
14112 The flag is set again if insert_block is called. */
14113 TREE_USED (block) = 0;
14114 }
14115
14116 void
14117 insert_block (tree block)
14118 {
14119 TREE_USED (block) = 1;
14120 current_binding_level->blocks
14121 = chainon (current_binding_level->blocks, block);
14122 }
14123
14124 /* Each front end provides its own. */
14125 static bool ffe_init PARAMS ((void));
14126 static void ffe_finish PARAMS ((void));
14127 static bool ffe_post_options PARAMS ((const char **));
14128 static void ffe_print_identifier PARAMS ((FILE *, tree, int));
14129
14130 struct language_function GTY(())
14131 {
14132 int unused;
14133 };
14134
14135 #undef LANG_HOOKS_NAME
14136 #define LANG_HOOKS_NAME "GNU F77"
14137 #undef LANG_HOOKS_INIT
14138 #define LANG_HOOKS_INIT ffe_init
14139 #undef LANG_HOOKS_FINISH
14140 #define LANG_HOOKS_FINISH ffe_finish
14141 #undef LANG_HOOKS_INIT_OPTIONS
14142 #define LANG_HOOKS_INIT_OPTIONS ffe_init_options
14143 #undef LANG_HOOKS_HANDLE_OPTION
14144 #define LANG_HOOKS_HANDLE_OPTION ffe_handle_option
14145 #undef LANG_HOOKS_POST_OPTIONS
14146 #define LANG_HOOKS_POST_OPTIONS ffe_post_options
14147 #undef LANG_HOOKS_PARSE_FILE
14148 #define LANG_HOOKS_PARSE_FILE ffe_parse_file
14149 #undef LANG_HOOKS_MARK_ADDRESSABLE
14150 #define LANG_HOOKS_MARK_ADDRESSABLE ffe_mark_addressable
14151 #undef LANG_HOOKS_PRINT_IDENTIFIER
14152 #define LANG_HOOKS_PRINT_IDENTIFIER ffe_print_identifier
14153 #undef LANG_HOOKS_DECL_PRINTABLE_NAME
14154 #define LANG_HOOKS_DECL_PRINTABLE_NAME ffe_printable_name
14155 #undef LANG_HOOKS_PRINT_ERROR_FUNCTION
14156 #define LANG_HOOKS_PRINT_ERROR_FUNCTION ffe_print_error_function
14157 #undef LANG_HOOKS_TRUTHVALUE_CONVERSION
14158 #define LANG_HOOKS_TRUTHVALUE_CONVERSION ffe_truthvalue_conversion
14159
14160 #undef LANG_HOOKS_TYPE_FOR_MODE
14161 #define LANG_HOOKS_TYPE_FOR_MODE ffe_type_for_mode
14162 #undef LANG_HOOKS_TYPE_FOR_SIZE
14163 #define LANG_HOOKS_TYPE_FOR_SIZE ffe_type_for_size
14164 #undef LANG_HOOKS_SIGNED_TYPE
14165 #define LANG_HOOKS_SIGNED_TYPE ffe_signed_type
14166 #undef LANG_HOOKS_UNSIGNED_TYPE
14167 #define LANG_HOOKS_UNSIGNED_TYPE ffe_unsigned_type
14168 #undef LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE
14169 #define LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE ffe_signed_or_unsigned_type
14170
14171 /* We do not wish to use alias-set based aliasing at all. Used in the
14172 extreme (every object with its own set, with equivalences recorded) it
14173 might be helpful, but there are problems when it comes to inlining. We
14174 get on ok with flag_argument_noalias, and alias-set aliasing does
14175 currently limit how stack slots can be reused, which is a lose. */
14176 #undef LANG_HOOKS_GET_ALIAS_SET
14177 #define LANG_HOOKS_GET_ALIAS_SET hook_get_alias_set_0
14178
14179 const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
14180
14181 /* Table indexed by tree code giving a string containing a character
14182 classifying the tree code. Possibilities are
14183 t, d, s, c, r, <, 1, 2 and e. See tree.def for details. */
14184
14185 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
14186
14187 const char tree_code_type[] = {
14188 #include "tree.def"
14189 };
14190 #undef DEFTREECODE
14191
14192 /* Table indexed by tree code giving number of expression
14193 operands beyond the fixed part of the node structure.
14194 Not used for types or decls. */
14195
14196 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
14197
14198 const unsigned char tree_code_length[] = {
14199 #include "tree.def"
14200 };
14201 #undef DEFTREECODE
14202
14203 /* Names of tree components.
14204 Used for printing out the tree and error messages. */
14205 #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
14206
14207 const char *const tree_code_name[] = {
14208 #include "tree.def"
14209 };
14210 #undef DEFTREECODE
14211
14212 static bool
14213 ffe_post_options (pfilename)
14214 const char **pfilename;
14215 {
14216 const char *filename = *pfilename;
14217
14218 /* Open input file. */
14219 if (filename == 0 || !strcmp (filename, "-"))
14220 {
14221 finput = stdin;
14222 filename = "stdin";
14223 }
14224 else
14225 finput = fopen (filename, "r");
14226
14227 if (finput == 0)
14228 fatal_error ("can't open %s: %m", filename);
14229
14230 return false;
14231 }
14232
14233
14234 static bool
14235 ffe_init ()
14236 {
14237 #ifdef IO_BUFFER_SIZE
14238 setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);
14239 #endif
14240
14241 ffecom_init_decl_processing ();
14242
14243 /* If the file is output from cpp, it should contain a first line
14244 `# 1 "real-filename"', and the current design of gcc (toplev.c
14245 in particular and the way it sets up information relied on by
14246 INCLUDE) requires that we read this now, and store the
14247 "real-filename" info in master_input_filename. Ask the lexer
14248 to try doing this. */
14249 ffelex_hash_kludge (finput);
14250
14251 /* FIXME: The ffelex_hash_kludge code needs to be cleaned up to
14252 set the new file name. Maybe in ffe_post_options. */
14253 return true;
14254 }
14255
14256 static void
14257 ffe_finish ()
14258 {
14259 ffe_terminate_0 ();
14260
14261 if (ffe_is_ffedebug ())
14262 malloc_pool_display (malloc_pool_image ());
14263
14264 fclose (finput);
14265 }
14266
14267 static bool
14268 ffe_mark_addressable (tree exp)
14269 {
14270 register tree x = exp;
14271 while (1)
14272 switch (TREE_CODE (x))
14273 {
14274 case ADDR_EXPR:
14275 case COMPONENT_REF:
14276 case ARRAY_REF:
14277 x = TREE_OPERAND (x, 0);
14278 break;
14279
14280 case CONSTRUCTOR:
14281 TREE_ADDRESSABLE (x) = 1;
14282 return true;
14283
14284 case VAR_DECL:
14285 case CONST_DECL:
14286 case PARM_DECL:
14287 case RESULT_DECL:
14288 if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)
14289 && DECL_NONLOCAL (x))
14290 {
14291 if (TREE_PUBLIC (x))
14292 {
14293 assert ("address of global register var requested" == NULL);
14294 return false;
14295 }
14296 assert ("address of register variable requested" == NULL);
14297 }
14298 else if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x))
14299 {
14300 if (TREE_PUBLIC (x))
14301 {
14302 assert ("address of global register var requested" == NULL);
14303 return false;
14304 }
14305 assert ("address of register var requested" == NULL);
14306 }
14307 put_var_into_stack (x, /*rescan=*/true);
14308
14309 /* drops in */
14310 case FUNCTION_DECL:
14311 TREE_ADDRESSABLE (x) = 1;
14312 #if 0 /* poplevel deals with this now. */
14313 if (DECL_CONTEXT (x) == 0)
14314 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
14315 #endif
14316
14317 default:
14318 return true;
14319 }
14320 }
14321
14322 /* Exit a binding level.
14323 Pop the level off, and restore the state of the identifier-decl mappings
14324 that were in effect when this level was entered.
14325
14326 If KEEP is nonzero, this level had explicit declarations, so
14327 and create a "block" (a BLOCK node) for the level
14328 to record its declarations and subblocks for symbol table output.
14329
14330 If FUNCTIONBODY is nonzero, this level is the body of a function,
14331 so create a block as if KEEP were set and also clear out all
14332 label names.
14333
14334 If REVERSE is nonzero, reverse the order of decls before putting
14335 them into the BLOCK. */
14336
14337 tree
14338 poplevel (int keep, int reverse, int functionbody)
14339 {
14340 register tree link;
14341 /* The chain of decls was accumulated in reverse order.
14342 Put it into forward order, just for cleanliness. */
14343 tree decls;
14344 tree subblocks = current_binding_level->blocks;
14345 tree block = 0;
14346 tree decl;
14347 int block_previously_created;
14348
14349 /* Get the decls in the order they were written.
14350 Usually current_binding_level->names is in reverse order.
14351 But parameter decls were previously put in forward order. */
14352
14353 if (reverse)
14354 current_binding_level->names
14355 = decls = nreverse (current_binding_level->names);
14356 else
14357 decls = current_binding_level->names;
14358
14359 /* Output any nested inline functions within this block
14360 if they weren't already output. */
14361
14362 for (decl = decls; decl; decl = TREE_CHAIN (decl))
14363 if (TREE_CODE (decl) == FUNCTION_DECL
14364 && ! TREE_ASM_WRITTEN (decl)
14365 && DECL_INITIAL (decl) != 0
14366 && TREE_ADDRESSABLE (decl))
14367 {
14368 /* If this decl was copied from a file-scope decl
14369 on account of a block-scope extern decl,
14370 propagate TREE_ADDRESSABLE to the file-scope decl.
14371
14372 DECL_ABSTRACT_ORIGIN can be set to itself if warn_return_type is
14373 true, since then the decl goes through save_for_inline_copying. */
14374 if (DECL_ABSTRACT_ORIGIN (decl) != 0
14375 && DECL_ABSTRACT_ORIGIN (decl) != decl)
14376 TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
14377 else if (DECL_SAVED_INSNS (decl) != 0)
14378 {
14379 push_function_context ();
14380 output_inline_function (decl);
14381 pop_function_context ();
14382 }
14383 }
14384
14385 /* If there were any declarations or structure tags in that level,
14386 or if this level is a function body,
14387 create a BLOCK to record them for the life of this function. */
14388
14389 block = 0;
14390 block_previously_created = (current_binding_level->this_block != 0);
14391 if (block_previously_created)
14392 block = current_binding_level->this_block;
14393 else if (keep || functionbody)
14394 block = make_node (BLOCK);
14395 if (block != 0)
14396 {
14397 BLOCK_VARS (block) = decls;
14398 BLOCK_SUBBLOCKS (block) = subblocks;
14399 }
14400
14401 /* In each subblock, record that this is its superior. */
14402
14403 for (link = subblocks; link; link = TREE_CHAIN (link))
14404 BLOCK_SUPERCONTEXT (link) = block;
14405
14406 /* Clear out the meanings of the local variables of this level. */
14407
14408 for (link = decls; link; link = TREE_CHAIN (link))
14409 {
14410 if (DECL_NAME (link) != 0)
14411 {
14412 /* If the ident. was used or addressed via a local extern decl,
14413 don't forget that fact. */
14414 if (DECL_EXTERNAL (link))
14415 {
14416 if (TREE_USED (link))
14417 TREE_USED (DECL_NAME (link)) = 1;
14418 if (TREE_ADDRESSABLE (link))
14419 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
14420 }
14421 IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0;
14422 }
14423 }
14424
14425 /* If the level being exited is the top level of a function,
14426 check over all the labels, and clear out the current
14427 (function local) meanings of their names. */
14428
14429 if (functionbody)
14430 {
14431 /* If this is the top level block of a function,
14432 the vars are the function's parameters.
14433 Don't leave them in the BLOCK because they are
14434 found in the FUNCTION_DECL instead. */
14435
14436 BLOCK_VARS (block) = 0;
14437 }
14438
14439 /* Pop the current level, and free the structure for reuse. */
14440
14441 {
14442 register struct f_binding_level *level = current_binding_level;
14443 current_binding_level = current_binding_level->level_chain;
14444
14445 level->level_chain = free_binding_level;
14446 free_binding_level = level;
14447 }
14448
14449 /* Dispose of the block that we just made inside some higher level. */
14450 if (functionbody
14451 && current_function_decl != error_mark_node)
14452 DECL_INITIAL (current_function_decl) = block;
14453 else if (block)
14454 {
14455 if (!block_previously_created)
14456 current_binding_level->blocks
14457 = chainon (current_binding_level->blocks, block);
14458 }
14459 /* If we did not make a block for the level just exited,
14460 any blocks made for inner levels
14461 (since they cannot be recorded as subblocks in that level)
14462 must be carried forward so they will later become subblocks
14463 of something else. */
14464 else if (subblocks)
14465 current_binding_level->blocks
14466 = chainon (current_binding_level->blocks, subblocks);
14467
14468 if (block)
14469 TREE_USED (block) = 1;
14470 return block;
14471 }
14472
14473 static void
14474 ffe_print_identifier (FILE *file, tree node, int indent)
14475 {
14476 print_node (file, "global", IDENTIFIER_GLOBAL_VALUE (node), indent + 4);
14477 print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4);
14478 }
14479
14480 /* Record a decl-node X as belonging to the current lexical scope.
14481 Check for errors (such as an incompatible declaration for the same
14482 name already seen in the same scope).
14483
14484 Returns either X or an old decl for the same name.
14485 If an old decl is returned, it may have been smashed
14486 to agree with what X says. */
14487
14488 tree
14489 pushdecl (tree x)
14490 {
14491 register tree t;
14492 register tree name = DECL_NAME (x);
14493 register struct f_binding_level *b = current_binding_level;
14494
14495 if ((TREE_CODE (x) == FUNCTION_DECL)
14496 && (DECL_INITIAL (x) == 0)
14497 && DECL_EXTERNAL (x))
14498 DECL_CONTEXT (x) = NULL_TREE;
14499 else
14500 DECL_CONTEXT (x) = current_function_decl;
14501
14502 if (name)
14503 {
14504 if (IDENTIFIER_INVENTED (name))
14505 {
14506 DECL_ARTIFICIAL (x) = 1;
14507 DECL_IN_SYSTEM_HEADER (x) = 1;
14508 }
14509
14510 t = lookup_name_current_level (name);
14511
14512 assert ((t == NULL_TREE) || (DECL_CONTEXT (x) == NULL_TREE));
14513
14514 /* Don't push non-parms onto list for parms until we understand
14515 why we're doing this and whether it works. */
14516
14517 assert ((b == global_binding_level)
14518 || !ffecom_transform_only_dummies_
14519 || TREE_CODE (x) == PARM_DECL);
14520
14521 if ((t != NULL_TREE) && duplicate_decls (x, t))
14522 return t;
14523
14524 /* If we are processing a typedef statement, generate a whole new
14525 ..._TYPE node (which will be just an variant of the existing
14526 ..._TYPE node with identical properties) and then install the
14527 TYPE_DECL node generated to represent the typedef name as the
14528 TYPE_NAME of this brand new (duplicate) ..._TYPE node.
14529
14530 The whole point here is to end up with a situation where each and every
14531 ..._TYPE node the compiler creates will be uniquely associated with
14532 AT MOST one node representing a typedef name. This way, even though
14533 the compiler substitutes corresponding ..._TYPE nodes for TYPE_DECL
14534 (i.e. "typedef name") nodes very early on, later parts of the
14535 compiler can always do the reverse translation and get back the
14536 corresponding typedef name. For example, given:
14537
14538 typedef struct S MY_TYPE; MY_TYPE object;
14539
14540 Later parts of the compiler might only know that `object' was of type
14541 `struct S' if it were not for code just below. With this code
14542 however, later parts of the compiler see something like:
14543
14544 struct S' == struct S typedef struct S' MY_TYPE; struct S' object;
14545
14546 And they can then deduce (from the node for type struct S') that the
14547 original object declaration was:
14548
14549 MY_TYPE object;
14550
14551 Being able to do this is important for proper support of protoize, and
14552 also for generating precise symbolic debugging information which
14553 takes full account of the programmer's (typedef) vocabulary.
14554
14555 Obviously, we don't want to generate a duplicate ..._TYPE node if the
14556 TYPE_DECL node that we are now processing really represents a
14557 standard built-in type.
14558
14559 Since all standard types are effectively declared at line zero in the
14560 source file, we can easily check to see if we are working on a
14561 standard type by checking the current value of lineno. */
14562
14563 if (TREE_CODE (x) == TYPE_DECL)
14564 {
14565 if (DECL_SOURCE_LINE (x) == 0)
14566 {
14567 if (TYPE_NAME (TREE_TYPE (x)) == 0)
14568 TYPE_NAME (TREE_TYPE (x)) = x;
14569 }
14570 else if (TREE_TYPE (x) != error_mark_node)
14571 {
14572 tree tt = TREE_TYPE (x);
14573
14574 tt = build_type_copy (tt);
14575 TYPE_NAME (tt) = x;
14576 TREE_TYPE (x) = tt;
14577 }
14578 }
14579
14580 /* This name is new in its binding level. Install the new declaration
14581 and return it. */
14582 if (b == global_binding_level)
14583 IDENTIFIER_GLOBAL_VALUE (name) = x;
14584 else
14585 IDENTIFIER_LOCAL_VALUE (name) = x;
14586 }
14587
14588 /* Put decls on list in reverse order. We will reverse them later if
14589 necessary. */
14590 TREE_CHAIN (x) = b->names;
14591 b->names = x;
14592
14593 return x;
14594 }
14595
14596 /* Nonzero if the current level needs to have a BLOCK made. */
14597
14598 static int
14599 kept_level_p ()
14600 {
14601 tree decl;
14602
14603 for (decl = current_binding_level->names;
14604 decl;
14605 decl = TREE_CHAIN (decl))
14606 {
14607 if (TREE_USED (decl) || TREE_CODE (decl) != VAR_DECL
14608 || (DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl)))
14609 /* Currently, there aren't supposed to be non-artificial names
14610 at other than the top block for a function -- they're
14611 believed to always be temps. But it's wise to check anyway. */
14612 return 1;
14613 }
14614 return 0;
14615 }
14616
14617 /* Enter a new binding level.
14618 If TAG_TRANSPARENT is nonzero, do so only for the name space of variables,
14619 not for that of tags. */
14620
14621 void
14622 pushlevel (int tag_transparent)
14623 {
14624 register struct f_binding_level *newlevel = NULL_BINDING_LEVEL;
14625
14626 assert (! tag_transparent);
14627
14628 if (current_binding_level == global_binding_level)
14629 {
14630 named_labels = 0;
14631 }
14632
14633 /* Reuse or create a struct for this binding level. */
14634
14635 if (free_binding_level)
14636 {
14637 newlevel = free_binding_level;
14638 free_binding_level = free_binding_level->level_chain;
14639 }
14640 else
14641 {
14642 newlevel = make_binding_level ();
14643 }
14644
14645 /* Add this level to the front of the chain (stack) of levels that
14646 are active. */
14647
14648 *newlevel = clear_binding_level;
14649 newlevel->level_chain = current_binding_level;
14650 current_binding_level = newlevel;
14651 }
14652
14653 /* Set the BLOCK node for the innermost scope
14654 (the one we are currently in). */
14655
14656 void
14657 set_block (tree block)
14658 {
14659 current_binding_level->this_block = block;
14660 current_binding_level->names = chainon (current_binding_level->names,
14661 BLOCK_VARS (block));
14662 current_binding_level->blocks = chainon (current_binding_level->blocks,
14663 BLOCK_SUBBLOCKS (block));
14664 }
14665
14666 static tree
14667 ffe_signed_or_unsigned_type (int unsignedp, tree type)
14668 {
14669 tree type2;
14670
14671 if (! INTEGRAL_TYPE_P (type))
14672 return type;
14673 if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
14674 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
14675 if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
14676 return unsignedp ? unsigned_type_node : integer_type_node;
14677 if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node))
14678 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
14679 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node))
14680 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
14681 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node))
14682 return (unsignedp ? long_long_unsigned_type_node
14683 : long_long_integer_type_node);
14684
14685 type2 = ffe_type_for_size (TYPE_PRECISION (type), unsignedp);
14686 if (type2 == NULL_TREE)
14687 return type;
14688
14689 return type2;
14690 }
14691
14692 static tree
14693 ffe_signed_type (tree type)
14694 {
14695 tree type1 = TYPE_MAIN_VARIANT (type);
14696 ffeinfoKindtype kt;
14697 tree type2;
14698
14699 if (type1 == unsigned_char_type_node || type1 == char_type_node)
14700 return signed_char_type_node;
14701 if (type1 == unsigned_type_node)
14702 return integer_type_node;
14703 if (type1 == short_unsigned_type_node)
14704 return short_integer_type_node;
14705 if (type1 == long_unsigned_type_node)
14706 return long_integer_type_node;
14707 if (type1 == long_long_unsigned_type_node)
14708 return long_long_integer_type_node;
14709 #if 0 /* gcc/c-* files only */
14710 if (type1 == unsigned_intDI_type_node)
14711 return intDI_type_node;
14712 if (type1 == unsigned_intSI_type_node)
14713 return intSI_type_node;
14714 if (type1 == unsigned_intHI_type_node)
14715 return intHI_type_node;
14716 if (type1 == unsigned_intQI_type_node)
14717 return intQI_type_node;
14718 #endif
14719
14720 type2 = ffe_type_for_size (TYPE_PRECISION (type1), 0);
14721 if (type2 != NULL_TREE)
14722 return type2;
14723
14724 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
14725 {
14726 type2 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
14727
14728 if (type1 == type2)
14729 return ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
14730 }
14731
14732 return type;
14733 }
14734
14735 /* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
14736 or validate its data type for an `if' or `while' statement or ?..: exp.
14737
14738 This preparation consists of taking the ordinary
14739 representation of an expression expr and producing a valid tree
14740 boolean expression describing whether expr is nonzero. We could
14741 simply always do build_binary_op (NE_EXPR, expr, integer_zero_node, 1),
14742 but we optimize comparisons, &&, ||, and !.
14743
14744 The resulting type should always be `integer_type_node'. */
14745
14746 static tree
14747 ffe_truthvalue_conversion (tree expr)
14748 {
14749 if (TREE_CODE (expr) == ERROR_MARK)
14750 return expr;
14751
14752 #if 0 /* This appears to be wrong for C++. */
14753 /* These really should return error_mark_node after 2.4 is stable.
14754 But not all callers handle ERROR_MARK properly. */
14755 switch (TREE_CODE (TREE_TYPE (expr)))
14756 {
14757 case RECORD_TYPE:
14758 error ("struct type value used where scalar is required");
14759 return integer_zero_node;
14760
14761 case UNION_TYPE:
14762 error ("union type value used where scalar is required");
14763 return integer_zero_node;
14764
14765 case ARRAY_TYPE:
14766 error ("array type value used where scalar is required");
14767 return integer_zero_node;
14768
14769 default:
14770 break;
14771 }
14772 #endif /* 0 */
14773
14774 switch (TREE_CODE (expr))
14775 {
14776 /* It is simpler and generates better code to have only TRUTH_*_EXPR
14777 or comparison expressions as truth values at this level. */
14778 #if 0
14779 case COMPONENT_REF:
14780 /* A one-bit unsigned bit-field is already acceptable. */
14781 if (1 == TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (expr, 1)))
14782 && TREE_UNSIGNED (TREE_OPERAND (expr, 1)))
14783 return expr;
14784 break;
14785 #endif
14786
14787 case EQ_EXPR:
14788 /* It is simpler and generates better code to have only TRUTH_*_EXPR
14789 or comparison expressions as truth values at this level. */
14790 #if 0
14791 if (integer_zerop (TREE_OPERAND (expr, 1)))
14792 return build_unary_op (TRUTH_NOT_EXPR, TREE_OPERAND (expr, 0), 0);
14793 #endif
14794 case NE_EXPR: case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
14795 case TRUTH_ANDIF_EXPR:
14796 case TRUTH_ORIF_EXPR:
14797 case TRUTH_AND_EXPR:
14798 case TRUTH_OR_EXPR:
14799 case TRUTH_XOR_EXPR:
14800 TREE_TYPE (expr) = integer_type_node;
14801 return expr;
14802
14803 case ERROR_MARK:
14804 return expr;
14805
14806 case INTEGER_CST:
14807 return integer_zerop (expr) ? integer_zero_node : integer_one_node;
14808
14809 case REAL_CST:
14810 return real_zerop (expr) ? integer_zero_node : integer_one_node;
14811
14812 case ADDR_EXPR:
14813 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0)))
14814 return build (COMPOUND_EXPR, integer_type_node,
14815 TREE_OPERAND (expr, 0), integer_one_node);
14816 else
14817 return integer_one_node;
14818
14819 case COMPLEX_EXPR:
14820 return ffecom_2 ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
14821 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
14822 integer_type_node,
14823 ffe_truthvalue_conversion (TREE_OPERAND (expr, 0)),
14824 ffe_truthvalue_conversion (TREE_OPERAND (expr, 1)));
14825
14826 case NEGATE_EXPR:
14827 case ABS_EXPR:
14828 case FLOAT_EXPR:
14829 case FFS_EXPR:
14830 /* These don't change whether an object is nonzero or zero. */
14831 return ffe_truthvalue_conversion (TREE_OPERAND (expr, 0));
14832
14833 case LROTATE_EXPR:
14834 case RROTATE_EXPR:
14835 /* These don't change whether an object is zero or nonzero, but
14836 we can't ignore them if their second arg has side-effects. */
14837 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
14838 return build (COMPOUND_EXPR, integer_type_node, TREE_OPERAND (expr, 1),
14839 ffe_truthvalue_conversion (TREE_OPERAND (expr, 0)));
14840 else
14841 return ffe_truthvalue_conversion (TREE_OPERAND (expr, 0));
14842
14843 case COND_EXPR:
14844 {
14845 /* Distribute the conversion into the arms of a COND_EXPR. */
14846 tree arg1 = TREE_OPERAND (expr, 1);
14847 tree arg2 = TREE_OPERAND (expr, 2);
14848 if (! VOID_TYPE_P (TREE_TYPE (arg1)))
14849 arg1 = ffe_truthvalue_conversion (arg1);
14850 if (! VOID_TYPE_P (TREE_TYPE (arg2)))
14851 arg2 = ffe_truthvalue_conversion (arg2);
14852 return fold (build (COND_EXPR, integer_type_node,
14853 TREE_OPERAND (expr, 0), arg1, arg2));
14854 }
14855
14856 case CONVERT_EXPR:
14857 /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
14858 since that affects how `default_conversion' will behave. */
14859 if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE
14860 || TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
14861 break;
14862 /* fall through... */
14863 case NOP_EXPR:
14864 /* If this is widening the argument, we can ignore it. */
14865 if (TYPE_PRECISION (TREE_TYPE (expr))
14866 >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
14867 return ffe_truthvalue_conversion (TREE_OPERAND (expr, 0));
14868 break;
14869
14870 case MINUS_EXPR:
14871 /* With IEEE arithmetic, x - x may not equal 0, so we can't optimize
14872 this case. */
14873 if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
14874 && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE)
14875 break;
14876 /* fall through... */
14877 case BIT_XOR_EXPR:
14878 /* This and MINUS_EXPR can be changed into a comparison of the
14879 two objects. */
14880 if (TREE_TYPE (TREE_OPERAND (expr, 0))
14881 == TREE_TYPE (TREE_OPERAND (expr, 1)))
14882 return ffecom_2 (NE_EXPR, integer_type_node,
14883 TREE_OPERAND (expr, 0),
14884 TREE_OPERAND (expr, 1));
14885 return ffecom_2 (NE_EXPR, integer_type_node,
14886 TREE_OPERAND (expr, 0),
14887 fold (build1 (NOP_EXPR,
14888 TREE_TYPE (TREE_OPERAND (expr, 0)),
14889 TREE_OPERAND (expr, 1))));
14890
14891 case BIT_AND_EXPR:
14892 if (integer_onep (TREE_OPERAND (expr, 1)))
14893 return expr;
14894 break;
14895
14896 case MODIFY_EXPR:
14897 #if 0 /* No such thing in Fortran. */
14898 if (warn_parentheses && C_EXP_ORIGINAL_CODE (expr) == MODIFY_EXPR)
14899 warning ("suggest parentheses around assignment used as truth value");
14900 #endif
14901 break;
14902
14903 default:
14904 break;
14905 }
14906
14907 if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
14908 return (ffecom_2
14909 ((TREE_SIDE_EFFECTS (expr)
14910 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
14911 integer_type_node,
14912 ffe_truthvalue_conversion (ffecom_1 (REALPART_EXPR,
14913 TREE_TYPE (TREE_TYPE (expr)),
14914 expr)),
14915 ffe_truthvalue_conversion (ffecom_1 (IMAGPART_EXPR,
14916 TREE_TYPE (TREE_TYPE (expr)),
14917 expr))));
14918
14919 return ffecom_2 (NE_EXPR, integer_type_node,
14920 expr,
14921 convert (TREE_TYPE (expr), integer_zero_node));
14922 }
14923
14924 static tree
14925 ffe_type_for_mode (enum machine_mode mode, int unsignedp)
14926 {
14927 int i;
14928 int j;
14929 tree t;
14930
14931 if (mode == TYPE_MODE (integer_type_node))
14932 return unsignedp ? unsigned_type_node : integer_type_node;
14933
14934 if (mode == TYPE_MODE (signed_char_type_node))
14935 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
14936
14937 if (mode == TYPE_MODE (short_integer_type_node))
14938 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
14939
14940 if (mode == TYPE_MODE (long_integer_type_node))
14941 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
14942
14943 if (mode == TYPE_MODE (long_long_integer_type_node))
14944 return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
14945
14946 #if HOST_BITS_PER_WIDE_INT >= 64
14947 if (mode == TYPE_MODE (intTI_type_node))
14948 return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
14949 #endif
14950
14951 if (mode == TYPE_MODE (float_type_node))
14952 return float_type_node;
14953
14954 if (mode == TYPE_MODE (double_type_node))
14955 return double_type_node;
14956
14957 if (mode == TYPE_MODE (long_double_type_node))
14958 return long_double_type_node;
14959
14960 if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
14961 return build_pointer_type (char_type_node);
14962
14963 if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
14964 return build_pointer_type (integer_type_node);
14965
14966 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
14967 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
14968 {
14969 if (((t = ffecom_tree_type[i][j]) != NULL_TREE)
14970 && (mode == TYPE_MODE (t)))
14971 {
14972 if ((i == FFEINFO_basictypeINTEGER) && unsignedp)
14973 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][j];
14974 else
14975 return t;
14976 }
14977 }
14978
14979 return 0;
14980 }
14981
14982 static tree
14983 ffe_type_for_size (unsigned bits, int unsignedp)
14984 {
14985 ffeinfoKindtype kt;
14986 tree type_node;
14987
14988 if (bits == TYPE_PRECISION (integer_type_node))
14989 return unsignedp ? unsigned_type_node : integer_type_node;
14990
14991 if (bits == TYPE_PRECISION (signed_char_type_node))
14992 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
14993
14994 if (bits == TYPE_PRECISION (short_integer_type_node))
14995 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
14996
14997 if (bits == TYPE_PRECISION (long_integer_type_node))
14998 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
14999
15000 if (bits == TYPE_PRECISION (long_long_integer_type_node))
15001 return (unsignedp ? long_long_unsigned_type_node
15002 : long_long_integer_type_node);
15003
15004 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15005 {
15006 type_node = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15007
15008 if ((type_node != NULL_TREE) && (bits == TYPE_PRECISION (type_node)))
15009 return unsignedp ? ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt]
15010 : type_node;
15011 }
15012
15013 return 0;
15014 }
15015
15016 static tree
15017 ffe_unsigned_type (tree type)
15018 {
15019 tree type1 = TYPE_MAIN_VARIANT (type);
15020 ffeinfoKindtype kt;
15021 tree type2;
15022
15023 if (type1 == signed_char_type_node || type1 == char_type_node)
15024 return unsigned_char_type_node;
15025 if (type1 == integer_type_node)
15026 return unsigned_type_node;
15027 if (type1 == short_integer_type_node)
15028 return short_unsigned_type_node;
15029 if (type1 == long_integer_type_node)
15030 return long_unsigned_type_node;
15031 if (type1 == long_long_integer_type_node)
15032 return long_long_unsigned_type_node;
15033 #if 0 /* gcc/c-* files only */
15034 if (type1 == intDI_type_node)
15035 return unsigned_intDI_type_node;
15036 if (type1 == intSI_type_node)
15037 return unsigned_intSI_type_node;
15038 if (type1 == intHI_type_node)
15039 return unsigned_intHI_type_node;
15040 if (type1 == intQI_type_node)
15041 return unsigned_intQI_type_node;
15042 #endif
15043
15044 type2 = ffe_type_for_size (TYPE_PRECISION (type1), 1);
15045 if (type2 != NULL_TREE)
15046 return type2;
15047
15048 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15049 {
15050 type2 = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15051
15052 if (type1 == type2)
15053 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
15054 }
15055
15056 return type;
15057 }
15058 \f
15059 /* From gcc/cccp.c, the code to handle -I. */
15060
15061 /* Skip leading "./" from a directory name.
15062 This may yield the empty string, which represents the current directory. */
15063
15064 static const char *
15065 skip_redundant_dir_prefix (const char *dir)
15066 {
15067 while (dir[0] == '.' && dir[1] == '/')
15068 for (dir += 2; *dir == '/'; dir++)
15069 continue;
15070 if (dir[0] == '.' && !dir[1])
15071 dir++;
15072 return dir;
15073 }
15074
15075 /* The file_name_map structure holds a mapping of file names for a
15076 particular directory. This mapping is read from the file named
15077 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
15078 map filenames on a file system with severe filename restrictions,
15079 such as DOS. The format of the file name map file is just a series
15080 of lines with two tokens on each line. The first token is the name
15081 to map, and the second token is the actual name to use. */
15082
15083 struct file_name_map
15084 {
15085 struct file_name_map *map_next;
15086 char *map_from;
15087 char *map_to;
15088 };
15089
15090 #define FILE_NAME_MAP_FILE "header.gcc"
15091
15092 /* Current maximum length of directory names in the search path
15093 for include files. (Altered as we get more of them.) */
15094
15095 static int max_include_len = 0;
15096
15097 struct file_name_list
15098 {
15099 struct file_name_list *next;
15100 const char *fname;
15101 /* Mapping of file names for this directory. */
15102 struct file_name_map *name_map;
15103 /* Nonzero if name_map is valid. */
15104 int got_name_map;
15105 };
15106
15107 static struct file_name_list *include = NULL; /* First dir to search */
15108 static struct file_name_list *last_include = NULL; /* Last in chain */
15109
15110 /* I/O buffer structure.
15111 The `fname' field is nonzero for source files and #include files
15112 and for the dummy text used for -D and -U.
15113 It is zero for rescanning results of macro expansion
15114 and for expanding macro arguments. */
15115 #define INPUT_STACK_MAX 400
15116 static struct file_buf {
15117 const char *fname;
15118 /* Filename specified with #line command. */
15119 const char *nominal_fname;
15120 /* Record where in the search path this file was found.
15121 For #include_next. */
15122 struct file_name_list *dir;
15123 ffewhereLine line;
15124 ffewhereColumn column;
15125 } instack[INPUT_STACK_MAX];
15126
15127 static int last_error_tick = 0; /* Incremented each time we print it. */
15128 static int input_file_stack_tick = 0; /* Incremented when status changes. */
15129
15130 /* Current nesting level of input sources.
15131 `instack[indepth]' is the level currently being read. */
15132 static int indepth = -1;
15133
15134 typedef struct file_buf FILE_BUF;
15135
15136 /* Nonzero means -I- has been seen,
15137 so don't look for #include "foo" the source-file directory. */
15138 static int ignore_srcdir;
15139
15140 #ifndef INCLUDE_LEN_FUDGE
15141 #define INCLUDE_LEN_FUDGE 0
15142 #endif
15143
15144 static void append_include_chain (struct file_name_list *first,
15145 struct file_name_list *last);
15146 static FILE *open_include_file (char *filename,
15147 struct file_name_list *searchptr);
15148 static void print_containing_files (ffebadSeverity sev);
15149 static char *read_filename_string (int ch, FILE *f);
15150 static struct file_name_map *read_name_map (const char *dirname);
15151
15152 /* Append a chain of `struct file_name_list's
15153 to the end of the main include chain.
15154 FIRST is the beginning of the chain to append, and LAST is the end. */
15155
15156 static void
15157 append_include_chain (struct file_name_list *first, struct file_name_list *last)
15158 {
15159 struct file_name_list *dir;
15160
15161 if (!first || !last)
15162 return;
15163
15164 if (include == 0)
15165 include = first;
15166 else
15167 last_include->next = first;
15168
15169 for (dir = first; ; dir = dir->next) {
15170 int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE;
15171 if (len > max_include_len)
15172 max_include_len = len;
15173 if (dir == last)
15174 break;
15175 }
15176
15177 last->next = NULL;
15178 last_include = last;
15179 }
15180
15181 /* Try to open include file FILENAME. SEARCHPTR is the directory
15182 being tried from the include file search path. This function maps
15183 filenames on file systems based on information read by
15184 read_name_map. */
15185
15186 static FILE *
15187 open_include_file (char *filename, struct file_name_list *searchptr)
15188 {
15189 register struct file_name_map *map;
15190 register char *from;
15191 char *p, *dir;
15192
15193 if (searchptr && ! searchptr->got_name_map)
15194 {
15195 searchptr->name_map = read_name_map (searchptr->fname
15196 ? searchptr->fname : ".");
15197 searchptr->got_name_map = 1;
15198 }
15199
15200 /* First check the mapping for the directory we are using. */
15201 if (searchptr && searchptr->name_map)
15202 {
15203 from = filename;
15204 if (searchptr->fname)
15205 from += strlen (searchptr->fname) + 1;
15206 for (map = searchptr->name_map; map; map = map->map_next)
15207 {
15208 if (! strcmp (map->map_from, from))
15209 {
15210 /* Found a match. */
15211 return fopen (map->map_to, "r");
15212 }
15213 }
15214 }
15215
15216 /* Try to find a mapping file for the particular directory we are
15217 looking in. Thus #include <sys/types.h> will look up sys/types.h
15218 in /usr/include/header.gcc and look up types.h in
15219 /usr/include/sys/header.gcc. */
15220 p = strrchr (filename, '/');
15221 #ifdef DIR_SEPARATOR
15222 if (! p) p = strrchr (filename, DIR_SEPARATOR);
15223 else {
15224 char *tmp = strrchr (filename, DIR_SEPARATOR);
15225 if (tmp != NULL && tmp > p) p = tmp;
15226 }
15227 #endif
15228 if (! p)
15229 p = filename;
15230 if (searchptr
15231 && searchptr->fname
15232 && strlen (searchptr->fname) == (size_t) (p - filename)
15233 && ! strncmp (searchptr->fname, filename, (int) (p - filename)))
15234 {
15235 /* FILENAME is in SEARCHPTR, which we've already checked. */
15236 return fopen (filename, "r");
15237 }
15238
15239 if (p == filename)
15240 {
15241 from = filename;
15242 map = read_name_map (".");
15243 }
15244 else
15245 {
15246 dir = (char *) xmalloc (p - filename + 1);
15247 memcpy (dir, filename, p - filename);
15248 dir[p - filename] = '\0';
15249 from = p + 1;
15250 map = read_name_map (dir);
15251 free (dir);
15252 }
15253 for (; map; map = map->map_next)
15254 if (! strcmp (map->map_from, from))
15255 return fopen (map->map_to, "r");
15256
15257 return fopen (filename, "r");
15258 }
15259
15260 /* Print the file names and line numbers of the #include
15261 commands which led to the current file. */
15262
15263 static void
15264 print_containing_files (ffebadSeverity sev)
15265 {
15266 FILE_BUF *ip = NULL;
15267 int i;
15268 int first = 1;
15269 const char *str1;
15270 const char *str2;
15271
15272 /* If stack of files hasn't changed since we last printed
15273 this info, don't repeat it. */
15274 if (last_error_tick == input_file_stack_tick)
15275 return;
15276
15277 for (i = indepth; i >= 0; i--)
15278 if (instack[i].fname != NULL) {
15279 ip = &instack[i];
15280 break;
15281 }
15282
15283 /* Give up if we don't find a source file. */
15284 if (ip == NULL)
15285 return;
15286
15287 /* Find the other, outer source files. */
15288 for (i--; i >= 0; i--)
15289 if (instack[i].fname != NULL)
15290 {
15291 ip = &instack[i];
15292 if (first)
15293 {
15294 first = 0;
15295 str1 = "In file included";
15296 }
15297 else
15298 {
15299 str1 = "... ...";
15300 }
15301
15302 if (i == 1)
15303 str2 = ":";
15304 else
15305 str2 = "";
15306
15307 /* xgettext:no-c-format */
15308 ffebad_start_msg ("%A from %B at %0%C", sev);
15309 ffebad_here (0, ip->line, ip->column);
15310 ffebad_string (str1);
15311 ffebad_string (ip->nominal_fname);
15312 ffebad_string (str2);
15313 ffebad_finish ();
15314 }
15315
15316 /* Record we have printed the status as of this time. */
15317 last_error_tick = input_file_stack_tick;
15318 }
15319
15320 /* Read a space delimited string of unlimited length from a stdio
15321 file. */
15322
15323 static char *
15324 read_filename_string (int ch, FILE *f)
15325 {
15326 char *alloc, *set;
15327 int len;
15328
15329 len = 20;
15330 set = alloc = xmalloc (len + 1);
15331 if (! ISSPACE (ch))
15332 {
15333 *set++ = ch;
15334 while ((ch = getc (f)) != EOF && ! ISSPACE (ch))
15335 {
15336 if (set - alloc == len)
15337 {
15338 len *= 2;
15339 alloc = xrealloc (alloc, len + 1);
15340 set = alloc + len / 2;
15341 }
15342 *set++ = ch;
15343 }
15344 }
15345 *set = '\0';
15346 ungetc (ch, f);
15347 return alloc;
15348 }
15349
15350 /* Read the file name map file for DIRNAME. */
15351
15352 static struct file_name_map *
15353 read_name_map (const char *dirname)
15354 {
15355 /* This structure holds a linked list of file name maps, one per
15356 directory. */
15357 struct file_name_map_list
15358 {
15359 struct file_name_map_list *map_list_next;
15360 char *map_list_name;
15361 struct file_name_map *map_list_map;
15362 };
15363 static struct file_name_map_list *map_list;
15364 register struct file_name_map_list *map_list_ptr;
15365 char *name;
15366 FILE *f;
15367 size_t dirlen;
15368 int separator_needed;
15369
15370 dirname = skip_redundant_dir_prefix (dirname);
15371
15372 for (map_list_ptr = map_list; map_list_ptr;
15373 map_list_ptr = map_list_ptr->map_list_next)
15374 if (! strcmp (map_list_ptr->map_list_name, dirname))
15375 return map_list_ptr->map_list_map;
15376
15377 map_list_ptr = ((struct file_name_map_list *)
15378 xmalloc (sizeof (struct file_name_map_list)));
15379 map_list_ptr->map_list_name = xstrdup (dirname);
15380 map_list_ptr->map_list_map = NULL;
15381
15382 dirlen = strlen (dirname);
15383 separator_needed = dirlen != 0 && dirname[dirlen - 1] != '/';
15384 if (separator_needed)
15385 name = concat (dirname, "/", FILE_NAME_MAP_FILE, NULL);
15386 else
15387 name = concat (dirname, FILE_NAME_MAP_FILE, NULL);
15388 f = fopen (name, "r");
15389 free (name);
15390 if (!f)
15391 map_list_ptr->map_list_map = NULL;
15392 else
15393 {
15394 int ch;
15395
15396 while ((ch = getc (f)) != EOF)
15397 {
15398 char *from, *to;
15399 struct file_name_map *ptr;
15400
15401 if (ISSPACE (ch))
15402 continue;
15403 from = read_filename_string (ch, f);
15404 while ((ch = getc (f)) != EOF && ISSPACE (ch) && ch != '\n')
15405 ;
15406 to = read_filename_string (ch, f);
15407
15408 ptr = ((struct file_name_map *)
15409 xmalloc (sizeof (struct file_name_map)));
15410 ptr->map_from = from;
15411
15412 /* Make the real filename absolute. */
15413 if (*to == '/')
15414 ptr->map_to = to;
15415 else
15416 {
15417 if (separator_needed)
15418 ptr->map_to = concat (dirname, "/", to, NULL);
15419 else
15420 ptr->map_to = concat (dirname, to, NULL);
15421 free (to);
15422 }
15423
15424 ptr->map_next = map_list_ptr->map_list_map;
15425 map_list_ptr->map_list_map = ptr;
15426
15427 while ((ch = getc (f)) != '\n')
15428 if (ch == EOF)
15429 break;
15430 }
15431 fclose (f);
15432 }
15433
15434 map_list_ptr->map_list_next = map_list;
15435 map_list = map_list_ptr;
15436
15437 return map_list_ptr->map_list_map;
15438 }
15439
15440 static void
15441 ffecom_file_ (const char *name)
15442 {
15443 FILE_BUF *fp;
15444
15445 /* Do partial setup of input buffer for the sake of generating
15446 early #line directives (when -g is in effect). */
15447
15448 fp = &instack[++indepth];
15449 memset ((char *) fp, 0, sizeof (FILE_BUF));
15450 if (name == NULL)
15451 name = "";
15452 fp->nominal_fname = fp->fname = name;
15453 }
15454
15455 static void
15456 ffecom_close_include_ (FILE *f)
15457 {
15458 fclose (f);
15459
15460 indepth--;
15461 input_file_stack_tick++;
15462
15463 ffewhere_line_kill (instack[indepth].line);
15464 ffewhere_column_kill (instack[indepth].column);
15465 }
15466
15467 void
15468 ffecom_decode_include_option (const char *dir)
15469 {
15470 if (! ignore_srcdir && !strcmp (dir, "-"))
15471 ignore_srcdir = 1;
15472 else
15473 {
15474 struct file_name_list *dirtmp = (struct file_name_list *)
15475 xmalloc (sizeof (struct file_name_list));
15476 dirtmp->next = 0; /* New one goes on the end */
15477 dirtmp->fname = dir;
15478 dirtmp->got_name_map = 0;
15479 append_include_chain (dirtmp, dirtmp);
15480 }
15481 }
15482
15483 /* Open INCLUDEd file. */
15484
15485 static FILE *
15486 ffecom_open_include_ (char *name, ffewhereLine l, ffewhereColumn c)
15487 {
15488 char *fbeg = name;
15489 size_t flen = strlen (fbeg);
15490 struct file_name_list *search_start = include; /* Chain of dirs to search */
15491 struct file_name_list dsp[1]; /* First in chain, if #include "..." */
15492 struct file_name_list *searchptr = 0;
15493 char *fname; /* Dynamically allocated fname buffer */
15494 FILE *f;
15495 FILE_BUF *fp;
15496
15497 if (flen == 0)
15498 return NULL;
15499
15500 dsp[0].fname = NULL;
15501
15502 /* If -I- was specified, don't search current dir, only spec'd ones. */
15503 if (!ignore_srcdir)
15504 {
15505 for (fp = &instack[indepth]; fp >= instack; fp--)
15506 {
15507 int n;
15508 char *ep;
15509 const char *nam;
15510
15511 if ((nam = fp->nominal_fname) != NULL)
15512 {
15513 /* Found a named file. Figure out dir of the file,
15514 and put it in front of the search list. */
15515 dsp[0].next = search_start;
15516 search_start = dsp;
15517 #ifndef VMS
15518 ep = strrchr (nam, '/');
15519 #ifdef DIR_SEPARATOR
15520 if (ep == NULL) ep = strrchr (nam, DIR_SEPARATOR);
15521 else {
15522 char *tmp = strrchr (nam, DIR_SEPARATOR);
15523 if (tmp != NULL && tmp > ep) ep = tmp;
15524 }
15525 #endif
15526 #else /* VMS */
15527 ep = strrchr (nam, ']');
15528 if (ep == NULL) ep = strrchr (nam, '>');
15529 if (ep == NULL) ep = strrchr (nam, ':');
15530 if (ep != NULL) ep++;
15531 #endif /* VMS */
15532 if (ep != NULL)
15533 {
15534 n = ep - nam;
15535 fname = xmalloc (n + 1);
15536 strncpy (fname, nam, n);
15537 fname[n] = '\0';
15538 dsp[0].fname = fname;
15539 if (n + INCLUDE_LEN_FUDGE > max_include_len)
15540 max_include_len = n + INCLUDE_LEN_FUDGE;
15541 }
15542 else
15543 dsp[0].fname = NULL; /* Current directory */
15544 dsp[0].got_name_map = 0;
15545 break;
15546 }
15547 }
15548 }
15549
15550 /* Allocate this permanently, because it gets stored in the definitions
15551 of macros. */
15552 fname = xmalloc (max_include_len + flen + 4);
15553 /* + 2 above for slash and terminating null. */
15554 /* + 2 added for '.h' on VMS (to support '#include filename') (NOT USED
15555 for g77 yet). */
15556
15557 /* If specified file name is absolute, just open it. */
15558
15559 if (*fbeg == '/'
15560 #ifdef DIR_SEPARATOR
15561 || *fbeg == DIR_SEPARATOR
15562 #endif
15563 )
15564 {
15565 strncpy (fname, (char *) fbeg, flen);
15566 fname[flen] = 0;
15567 f = open_include_file (fname, NULL);
15568 }
15569 else
15570 {
15571 f = NULL;
15572
15573 /* Search directory path, trying to open the file.
15574 Copy each filename tried into FNAME. */
15575
15576 for (searchptr = search_start; searchptr; searchptr = searchptr->next)
15577 {
15578 if (searchptr->fname)
15579 {
15580 /* The empty string in a search path is ignored.
15581 This makes it possible to turn off entirely
15582 a standard piece of the list. */
15583 if (searchptr->fname[0] == 0)
15584 continue;
15585 strcpy (fname, skip_redundant_dir_prefix (searchptr->fname));
15586 if (fname[0] && fname[strlen (fname) - 1] != '/')
15587 strcat (fname, "/");
15588 fname[strlen (fname) + flen] = 0;
15589 }
15590 else
15591 fname[0] = 0;
15592
15593 strncat (fname, fbeg, flen);
15594 #ifdef VMS
15595 /* Change this 1/2 Unix 1/2 VMS file specification into a
15596 full VMS file specification */
15597 if (searchptr->fname && (searchptr->fname[0] != 0))
15598 {
15599 /* Fix up the filename */
15600 hack_vms_include_specification (fname);
15601 }
15602 else
15603 {
15604 /* This is a normal VMS filespec, so use it unchanged. */
15605 strncpy (fname, (char *) fbeg, flen);
15606 fname[flen] = 0;
15607 #if 0 /* Not for g77. */
15608 /* if it's '#include filename', add the missing .h */
15609 if (strchr (fname, '.') == NULL)
15610 strcat (fname, ".h");
15611 #endif
15612 }
15613 #endif /* VMS */
15614 f = open_include_file (fname, searchptr);
15615 #ifdef EACCES
15616 if (f == NULL && errno == EACCES)
15617 {
15618 print_containing_files (FFEBAD_severityWARNING);
15619 /* xgettext:no-c-format */
15620 ffebad_start_msg ("At %0, INCLUDE file %A exists, but is not readable",
15621 FFEBAD_severityWARNING);
15622 ffebad_string (fname);
15623 ffebad_here (0, l, c);
15624 ffebad_finish ();
15625 }
15626 #endif
15627 if (f != NULL)
15628 break;
15629 }
15630 }
15631
15632 if (f == NULL)
15633 {
15634 /* A file that was not found. */
15635
15636 strncpy (fname, (char *) fbeg, flen);
15637 fname[flen] = 0;
15638 print_containing_files (ffebad_severity (FFEBAD_OPEN_INCLUDE));
15639 ffebad_start (FFEBAD_OPEN_INCLUDE);
15640 ffebad_here (0, l, c);
15641 ffebad_string (fname);
15642 ffebad_finish ();
15643 }
15644
15645 if (dsp[0].fname != NULL)
15646 free ((char *) dsp[0].fname);
15647
15648 if (f == NULL)
15649 return NULL;
15650
15651 if (indepth >= (INPUT_STACK_MAX - 1))
15652 {
15653 print_containing_files (FFEBAD_severityFATAL);
15654 /* xgettext:no-c-format */
15655 ffebad_start_msg ("At %0, INCLUDE nesting too deep",
15656 FFEBAD_severityFATAL);
15657 ffebad_string (fname);
15658 ffebad_here (0, l, c);
15659 ffebad_finish ();
15660 return NULL;
15661 }
15662
15663 instack[indepth].line = ffewhere_line_use (l);
15664 instack[indepth].column = ffewhere_column_use (c);
15665
15666 fp = &instack[indepth + 1];
15667 memset ((char *) fp, 0, sizeof (FILE_BUF));
15668 fp->nominal_fname = fp->fname = fname;
15669 fp->dir = searchptr;
15670
15671 indepth++;
15672 input_file_stack_tick++;
15673
15674 return f;
15675 }
15676
15677 /**INDENT* (Do not reformat this comment even with -fca option.)
15678 Data-gathering files: Given the source file listed below, compiled with
15679 f2c I obtained the output file listed after that, and from the output
15680 file I derived the above code.
15681
15682 -------- (begin input file to f2c)
15683 implicit none
15684 character*10 A1,A2
15685 complex C1,C2
15686 integer I1,I2
15687 real R1,R2
15688 double precision D1,D2
15689 C
15690 call getem(A1,A2,C1,C2,I1,I2,R1,R2,D1,D2)
15691 c /
15692 call fooI(I1/I2)
15693 call fooR(R1/I1)
15694 call fooD(D1/I1)
15695 call fooC(C1/I1)
15696 call fooR(R1/R2)
15697 call fooD(R1/D1)
15698 call fooD(D1/D2)
15699 call fooD(D1/R1)
15700 call fooC(C1/C2)
15701 call fooC(C1/R1)
15702 call fooZ(C1/D1)
15703 c **
15704 call fooI(I1**I2)
15705 call fooR(R1**I1)
15706 call fooD(D1**I1)
15707 call fooC(C1**I1)
15708 call fooR(R1**R2)
15709 call fooD(R1**D1)
15710 call fooD(D1**D2)
15711 call fooD(D1**R1)
15712 call fooC(C1**C2)
15713 call fooC(C1**R1)
15714 call fooZ(C1**D1)
15715 c FFEINTRIN_impABS
15716 call fooR(ABS(R1))
15717 c FFEINTRIN_impACOS
15718 call fooR(ACOS(R1))
15719 c FFEINTRIN_impAIMAG
15720 call fooR(AIMAG(C1))
15721 c FFEINTRIN_impAINT
15722 call fooR(AINT(R1))
15723 c FFEINTRIN_impALOG
15724 call fooR(ALOG(R1))
15725 c FFEINTRIN_impALOG10
15726 call fooR(ALOG10(R1))
15727 c FFEINTRIN_impAMAX0
15728 call fooR(AMAX0(I1,I2))
15729 c FFEINTRIN_impAMAX1
15730 call fooR(AMAX1(R1,R2))
15731 c FFEINTRIN_impAMIN0
15732 call fooR(AMIN0(I1,I2))
15733 c FFEINTRIN_impAMIN1
15734 call fooR(AMIN1(R1,R2))
15735 c FFEINTRIN_impAMOD
15736 call fooR(AMOD(R1,R2))
15737 c FFEINTRIN_impANINT
15738 call fooR(ANINT(R1))
15739 c FFEINTRIN_impASIN
15740 call fooR(ASIN(R1))
15741 c FFEINTRIN_impATAN
15742 call fooR(ATAN(R1))
15743 c FFEINTRIN_impATAN2
15744 call fooR(ATAN2(R1,R2))
15745 c FFEINTRIN_impCABS
15746 call fooR(CABS(C1))
15747 c FFEINTRIN_impCCOS
15748 call fooC(CCOS(C1))
15749 c FFEINTRIN_impCEXP
15750 call fooC(CEXP(C1))
15751 c FFEINTRIN_impCHAR
15752 call fooA(CHAR(I1))
15753 c FFEINTRIN_impCLOG
15754 call fooC(CLOG(C1))
15755 c FFEINTRIN_impCONJG
15756 call fooC(CONJG(C1))
15757 c FFEINTRIN_impCOS
15758 call fooR(COS(R1))
15759 c FFEINTRIN_impCOSH
15760 call fooR(COSH(R1))
15761 c FFEINTRIN_impCSIN
15762 call fooC(CSIN(C1))
15763 c FFEINTRIN_impCSQRT
15764 call fooC(CSQRT(C1))
15765 c FFEINTRIN_impDABS
15766 call fooD(DABS(D1))
15767 c FFEINTRIN_impDACOS
15768 call fooD(DACOS(D1))
15769 c FFEINTRIN_impDASIN
15770 call fooD(DASIN(D1))
15771 c FFEINTRIN_impDATAN
15772 call fooD(DATAN(D1))
15773 c FFEINTRIN_impDATAN2
15774 call fooD(DATAN2(D1,D2))
15775 c FFEINTRIN_impDCOS
15776 call fooD(DCOS(D1))
15777 c FFEINTRIN_impDCOSH
15778 call fooD(DCOSH(D1))
15779 c FFEINTRIN_impDDIM
15780 call fooD(DDIM(D1,D2))
15781 c FFEINTRIN_impDEXP
15782 call fooD(DEXP(D1))
15783 c FFEINTRIN_impDIM
15784 call fooR(DIM(R1,R2))
15785 c FFEINTRIN_impDINT
15786 call fooD(DINT(D1))
15787 c FFEINTRIN_impDLOG
15788 call fooD(DLOG(D1))
15789 c FFEINTRIN_impDLOG10
15790 call fooD(DLOG10(D1))
15791 c FFEINTRIN_impDMAX1
15792 call fooD(DMAX1(D1,D2))
15793 c FFEINTRIN_impDMIN1
15794 call fooD(DMIN1(D1,D2))
15795 c FFEINTRIN_impDMOD
15796 call fooD(DMOD(D1,D2))
15797 c FFEINTRIN_impDNINT
15798 call fooD(DNINT(D1))
15799 c FFEINTRIN_impDPROD
15800 call fooD(DPROD(R1,R2))
15801 c FFEINTRIN_impDSIGN
15802 call fooD(DSIGN(D1,D2))
15803 c FFEINTRIN_impDSIN
15804 call fooD(DSIN(D1))
15805 c FFEINTRIN_impDSINH
15806 call fooD(DSINH(D1))
15807 c FFEINTRIN_impDSQRT
15808 call fooD(DSQRT(D1))
15809 c FFEINTRIN_impDTAN
15810 call fooD(DTAN(D1))
15811 c FFEINTRIN_impDTANH
15812 call fooD(DTANH(D1))
15813 c FFEINTRIN_impEXP
15814 call fooR(EXP(R1))
15815 c FFEINTRIN_impIABS
15816 call fooI(IABS(I1))
15817 c FFEINTRIN_impICHAR
15818 call fooI(ICHAR(A1))
15819 c FFEINTRIN_impIDIM
15820 call fooI(IDIM(I1,I2))
15821 c FFEINTRIN_impIDNINT
15822 call fooI(IDNINT(D1))
15823 c FFEINTRIN_impINDEX
15824 call fooI(INDEX(A1,A2))
15825 c FFEINTRIN_impISIGN
15826 call fooI(ISIGN(I1,I2))
15827 c FFEINTRIN_impLEN
15828 call fooI(LEN(A1))
15829 c FFEINTRIN_impLGE
15830 call fooL(LGE(A1,A2))
15831 c FFEINTRIN_impLGT
15832 call fooL(LGT(A1,A2))
15833 c FFEINTRIN_impLLE
15834 call fooL(LLE(A1,A2))
15835 c FFEINTRIN_impLLT
15836 call fooL(LLT(A1,A2))
15837 c FFEINTRIN_impMAX0
15838 call fooI(MAX0(I1,I2))
15839 c FFEINTRIN_impMAX1
15840 call fooI(MAX1(R1,R2))
15841 c FFEINTRIN_impMIN0
15842 call fooI(MIN0(I1,I2))
15843 c FFEINTRIN_impMIN1
15844 call fooI(MIN1(R1,R2))
15845 c FFEINTRIN_impMOD
15846 call fooI(MOD(I1,I2))
15847 c FFEINTRIN_impNINT
15848 call fooI(NINT(R1))
15849 c FFEINTRIN_impSIGN
15850 call fooR(SIGN(R1,R2))
15851 c FFEINTRIN_impSIN
15852 call fooR(SIN(R1))
15853 c FFEINTRIN_impSINH
15854 call fooR(SINH(R1))
15855 c FFEINTRIN_impSQRT
15856 call fooR(SQRT(R1))
15857 c FFEINTRIN_impTAN
15858 call fooR(TAN(R1))
15859 c FFEINTRIN_impTANH
15860 call fooR(TANH(R1))
15861 c FFEINTRIN_imp_CMPLX_C
15862 call fooC(cmplx(C1,C2))
15863 c FFEINTRIN_imp_CMPLX_D
15864 call fooZ(cmplx(D1,D2))
15865 c FFEINTRIN_imp_CMPLX_I
15866 call fooC(cmplx(I1,I2))
15867 c FFEINTRIN_imp_CMPLX_R
15868 call fooC(cmplx(R1,R2))
15869 c FFEINTRIN_imp_DBLE_C
15870 call fooD(dble(C1))
15871 c FFEINTRIN_imp_DBLE_D
15872 call fooD(dble(D1))
15873 c FFEINTRIN_imp_DBLE_I
15874 call fooD(dble(I1))
15875 c FFEINTRIN_imp_DBLE_R
15876 call fooD(dble(R1))
15877 c FFEINTRIN_imp_INT_C
15878 call fooI(int(C1))
15879 c FFEINTRIN_imp_INT_D
15880 call fooI(int(D1))
15881 c FFEINTRIN_imp_INT_I
15882 call fooI(int(I1))
15883 c FFEINTRIN_imp_INT_R
15884 call fooI(int(R1))
15885 c FFEINTRIN_imp_REAL_C
15886 call fooR(real(C1))
15887 c FFEINTRIN_imp_REAL_D
15888 call fooR(real(D1))
15889 c FFEINTRIN_imp_REAL_I
15890 call fooR(real(I1))
15891 c FFEINTRIN_imp_REAL_R
15892 call fooR(real(R1))
15893 c
15894 c FFEINTRIN_imp_INT_D:
15895 c
15896 c FFEINTRIN_specIDINT
15897 call fooI(IDINT(D1))
15898 c
15899 c FFEINTRIN_imp_INT_R:
15900 c
15901 c FFEINTRIN_specIFIX
15902 call fooI(IFIX(R1))
15903 c FFEINTRIN_specINT
15904 call fooI(INT(R1))
15905 c
15906 c FFEINTRIN_imp_REAL_D:
15907 c
15908 c FFEINTRIN_specSNGL
15909 call fooR(SNGL(D1))
15910 c
15911 c FFEINTRIN_imp_REAL_I:
15912 c
15913 c FFEINTRIN_specFLOAT
15914 call fooR(FLOAT(I1))
15915 c FFEINTRIN_specREAL
15916 call fooR(REAL(I1))
15917 c
15918 end
15919 -------- (end input file to f2c)
15920
15921 -------- (begin output from providing above input file as input to:
15922 -------- `f2c | gcc -E -C - | sed -e "s:/[*]*://:g" -e "s:[*]*[/]://:g" \
15923 -------- -e "s:^#.*$::g"')
15924
15925 // -- translated by f2c (version 19950223).
15926 You must link the resulting object file with the libraries:
15927 -lf2c -lm (in that order)
15928 //
15929
15930
15931 // f2c.h -- Standard Fortran to C header file //
15932
15933 /// barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed."
15934
15935 - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) //
15936
15937
15938
15939
15940 // F2C_INTEGER will normally be `int' but would be `long' on 16-bit systems //
15941 // we assume short, float are OK //
15942 typedef long int // long int // integer;
15943 typedef char *address;
15944 typedef short int shortint;
15945 typedef float real;
15946 typedef double doublereal;
15947 typedef struct { real r, i; } complex;
15948 typedef struct { doublereal r, i; } doublecomplex;
15949 typedef long int // long int // logical;
15950 typedef short int shortlogical;
15951 typedef char logical1;
15952 typedef char integer1;
15953 // typedef long long longint; // // system-dependent //
15954
15955
15956
15957
15958 // Extern is for use with -E //
15959
15960
15961
15962
15963 // I/O stuff //
15964
15965
15966
15967
15968
15969
15970
15971
15972 typedef long int // int or long int // flag;
15973 typedef long int // int or long int // ftnlen;
15974 typedef long int // int or long int // ftnint;
15975
15976
15977 //external read, write//
15978 typedef struct
15979 { flag cierr;
15980 ftnint ciunit;
15981 flag ciend;
15982 char *cifmt;
15983 ftnint cirec;
15984 } cilist;
15985
15986 //internal read, write//
15987 typedef struct
15988 { flag icierr;
15989 char *iciunit;
15990 flag iciend;
15991 char *icifmt;
15992 ftnint icirlen;
15993 ftnint icirnum;
15994 } icilist;
15995
15996 //open//
15997 typedef struct
15998 { flag oerr;
15999 ftnint ounit;
16000 char *ofnm;
16001 ftnlen ofnmlen;
16002 char *osta;
16003 char *oacc;
16004 char *ofm;
16005 ftnint orl;
16006 char *oblnk;
16007 } olist;
16008
16009 //close//
16010 typedef struct
16011 { flag cerr;
16012 ftnint cunit;
16013 char *csta;
16014 } cllist;
16015
16016 //rewind, backspace, endfile//
16017 typedef struct
16018 { flag aerr;
16019 ftnint aunit;
16020 } alist;
16021
16022 // inquire //
16023 typedef struct
16024 { flag inerr;
16025 ftnint inunit;
16026 char *infile;
16027 ftnlen infilen;
16028 ftnint *inex; //parameters in standard's order//
16029 ftnint *inopen;
16030 ftnint *innum;
16031 ftnint *innamed;
16032 char *inname;
16033 ftnlen innamlen;
16034 char *inacc;
16035 ftnlen inacclen;
16036 char *inseq;
16037 ftnlen inseqlen;
16038 char *indir;
16039 ftnlen indirlen;
16040 char *infmt;
16041 ftnlen infmtlen;
16042 char *inform;
16043 ftnint informlen;
16044 char *inunf;
16045 ftnlen inunflen;
16046 ftnint *inrecl;
16047 ftnint *innrec;
16048 char *inblank;
16049 ftnlen inblanklen;
16050 } inlist;
16051
16052
16053
16054 union Multitype { // for multiple entry points //
16055 integer1 g;
16056 shortint h;
16057 integer i;
16058 // longint j; //
16059 real r;
16060 doublereal d;
16061 complex c;
16062 doublecomplex z;
16063 };
16064
16065 typedef union Multitype Multitype;
16066
16067 typedef long Long; // No longer used; formerly in Namelist //
16068
16069 struct Vardesc { // for Namelist //
16070 char *name;
16071 char *addr;
16072 ftnlen *dims;
16073 int type;
16074 };
16075 typedef struct Vardesc Vardesc;
16076
16077 struct Namelist {
16078 char *name;
16079 Vardesc **vars;
16080 int nvars;
16081 };
16082 typedef struct Namelist Namelist;
16083
16084
16085
16086
16087
16088
16089
16090
16091 // procedure parameter types for -A and -C++ //
16092
16093
16094
16095
16096 typedef int // Unknown procedure type // (*U_fp)();
16097 typedef shortint (*J_fp)();
16098 typedef integer (*I_fp)();
16099 typedef real (*R_fp)();
16100 typedef doublereal (*D_fp)(), (*E_fp)();
16101 typedef // Complex // void (*C_fp)();
16102 typedef // Double Complex // void (*Z_fp)();
16103 typedef logical (*L_fp)();
16104 typedef shortlogical (*K_fp)();
16105 typedef // Character // void (*H_fp)();
16106 typedef // Subroutine // int (*S_fp)();
16107
16108 // E_fp is for real functions when -R is not specified //
16109 typedef void C_f; // complex function //
16110 typedef void H_f; // character function //
16111 typedef void Z_f; // double complex function //
16112 typedef doublereal E_f; // real function with -R not specified //
16113
16114 // undef any lower-case symbols that your C compiler predefines, e.g.: //
16115
16116
16117 // (No such symbols should be defined in a strict ANSI C compiler.
16118 We can avoid trouble with f2c-translated code by using
16119 gcc -ansi.) //
16120
16121
16122
16123
16124
16125
16126
16127
16128
16129
16130
16131
16132
16133
16134
16135
16136
16137
16138
16139
16140
16141
16142
16143 // Main program // MAIN__()
16144 {
16145 // System generated locals //
16146 integer i__1;
16147 real r__1, r__2;
16148 doublereal d__1, d__2;
16149 complex q__1;
16150 doublecomplex z__1, z__2, z__3;
16151 logical L__1;
16152 char ch__1[1];
16153
16154 // Builtin functions //
16155 void c_div();
16156 integer pow_ii();
16157 double pow_ri(), pow_di();
16158 void pow_ci();
16159 double pow_dd();
16160 void pow_zz();
16161 double acos(), r_imag(), r_int(), log(), r_lg10(), r_mod(), r_nint(),
16162 asin(), atan(), atan2(), c_abs();
16163 void c_cos(), c_exp(), c_log(), r_cnjg();
16164 double cos(), cosh();
16165 void c_sin(), c_sqrt();
16166 double d_dim(), exp(), r_dim(), d_int(), d_lg10(), d_mod(), d_nint(),
16167 d_sign(), sin(), sinh(), sqrt(), tan(), tanh();
16168 integer i_dim(), i_dnnt(), i_indx(), i_sign(), i_len();
16169 logical l_ge(), l_gt(), l_le(), l_lt();
16170 integer i_nint();
16171 double r_sign();
16172
16173 // Local variables //
16174 extern // Subroutine // int fooa_(), fooc_(), food_(), fooi_(), foor_(),
16175 fool_(), fooz_(), getem_();
16176 static char a1[10], a2[10];
16177 static complex c1, c2;
16178 static doublereal d1, d2;
16179 static integer i1, i2;
16180 static real r1, r2;
16181
16182
16183 getem_(a1, a2, &c1, &c2, &i1, &i2, &r1, &r2, &d1, &d2, 10L, 10L);
16184 // / //
16185 i__1 = i1 / i2;
16186 fooi_(&i__1);
16187 r__1 = r1 / i1;
16188 foor_(&r__1);
16189 d__1 = d1 / i1;
16190 food_(&d__1);
16191 d__1 = (doublereal) i1;
16192 q__1.r = c1.r / d__1, q__1.i = c1.i / d__1;
16193 fooc_(&q__1);
16194 r__1 = r1 / r2;
16195 foor_(&r__1);
16196 d__1 = r1 / d1;
16197 food_(&d__1);
16198 d__1 = d1 / d2;
16199 food_(&d__1);
16200 d__1 = d1 / r1;
16201 food_(&d__1);
16202 c_div(&q__1, &c1, &c2);
16203 fooc_(&q__1);
16204 q__1.r = c1.r / r1, q__1.i = c1.i / r1;
16205 fooc_(&q__1);
16206 z__1.r = c1.r / d1, z__1.i = c1.i / d1;
16207 fooz_(&z__1);
16208 // ** //
16209 i__1 = pow_ii(&i1, &i2);
16210 fooi_(&i__1);
16211 r__1 = pow_ri(&r1, &i1);
16212 foor_(&r__1);
16213 d__1 = pow_di(&d1, &i1);
16214 food_(&d__1);
16215 pow_ci(&q__1, &c1, &i1);
16216 fooc_(&q__1);
16217 d__1 = (doublereal) r1;
16218 d__2 = (doublereal) r2;
16219 r__1 = pow_dd(&d__1, &d__2);
16220 foor_(&r__1);
16221 d__2 = (doublereal) r1;
16222 d__1 = pow_dd(&d__2, &d1);
16223 food_(&d__1);
16224 d__1 = pow_dd(&d1, &d2);
16225 food_(&d__1);
16226 d__2 = (doublereal) r1;
16227 d__1 = pow_dd(&d1, &d__2);
16228 food_(&d__1);
16229 z__2.r = c1.r, z__2.i = c1.i;
16230 z__3.r = c2.r, z__3.i = c2.i;
16231 pow_zz(&z__1, &z__2, &z__3);
16232 q__1.r = z__1.r, q__1.i = z__1.i;
16233 fooc_(&q__1);
16234 z__2.r = c1.r, z__2.i = c1.i;
16235 z__3.r = r1, z__3.i = 0.;
16236 pow_zz(&z__1, &z__2, &z__3);
16237 q__1.r = z__1.r, q__1.i = z__1.i;
16238 fooc_(&q__1);
16239 z__2.r = c1.r, z__2.i = c1.i;
16240 z__3.r = d1, z__3.i = 0.;
16241 pow_zz(&z__1, &z__2, &z__3);
16242 fooz_(&z__1);
16243 // FFEINTRIN_impABS //
16244 r__1 = (doublereal)(( r1 ) >= 0 ? ( r1 ) : -( r1 )) ;
16245 foor_(&r__1);
16246 // FFEINTRIN_impACOS //
16247 r__1 = acos(r1);
16248 foor_(&r__1);
16249 // FFEINTRIN_impAIMAG //
16250 r__1 = r_imag(&c1);
16251 foor_(&r__1);
16252 // FFEINTRIN_impAINT //
16253 r__1 = r_int(&r1);
16254 foor_(&r__1);
16255 // FFEINTRIN_impALOG //
16256 r__1 = log(r1);
16257 foor_(&r__1);
16258 // FFEINTRIN_impALOG10 //
16259 r__1 = r_lg10(&r1);
16260 foor_(&r__1);
16261 // FFEINTRIN_impAMAX0 //
16262 r__1 = (real) (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
16263 foor_(&r__1);
16264 // FFEINTRIN_impAMAX1 //
16265 r__1 = (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
16266 foor_(&r__1);
16267 // FFEINTRIN_impAMIN0 //
16268 r__1 = (real) (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
16269 foor_(&r__1);
16270 // FFEINTRIN_impAMIN1 //
16271 r__1 = (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
16272 foor_(&r__1);
16273 // FFEINTRIN_impAMOD //
16274 r__1 = r_mod(&r1, &r2);
16275 foor_(&r__1);
16276 // FFEINTRIN_impANINT //
16277 r__1 = r_nint(&r1);
16278 foor_(&r__1);
16279 // FFEINTRIN_impASIN //
16280 r__1 = asin(r1);
16281 foor_(&r__1);
16282 // FFEINTRIN_impATAN //
16283 r__1 = atan(r1);
16284 foor_(&r__1);
16285 // FFEINTRIN_impATAN2 //
16286 r__1 = atan2(r1, r2);
16287 foor_(&r__1);
16288 // FFEINTRIN_impCABS //
16289 r__1 = c_abs(&c1);
16290 foor_(&r__1);
16291 // FFEINTRIN_impCCOS //
16292 c_cos(&q__1, &c1);
16293 fooc_(&q__1);
16294 // FFEINTRIN_impCEXP //
16295 c_exp(&q__1, &c1);
16296 fooc_(&q__1);
16297 // FFEINTRIN_impCHAR //
16298 *(unsigned char *)&ch__1[0] = i1;
16299 fooa_(ch__1, 1L);
16300 // FFEINTRIN_impCLOG //
16301 c_log(&q__1, &c1);
16302 fooc_(&q__1);
16303 // FFEINTRIN_impCONJG //
16304 r_cnjg(&q__1, &c1);
16305 fooc_(&q__1);
16306 // FFEINTRIN_impCOS //
16307 r__1 = cos(r1);
16308 foor_(&r__1);
16309 // FFEINTRIN_impCOSH //
16310 r__1 = cosh(r1);
16311 foor_(&r__1);
16312 // FFEINTRIN_impCSIN //
16313 c_sin(&q__1, &c1);
16314 fooc_(&q__1);
16315 // FFEINTRIN_impCSQRT //
16316 c_sqrt(&q__1, &c1);
16317 fooc_(&q__1);
16318 // FFEINTRIN_impDABS //
16319 d__1 = (( d1 ) >= 0 ? ( d1 ) : -( d1 )) ;
16320 food_(&d__1);
16321 // FFEINTRIN_impDACOS //
16322 d__1 = acos(d1);
16323 food_(&d__1);
16324 // FFEINTRIN_impDASIN //
16325 d__1 = asin(d1);
16326 food_(&d__1);
16327 // FFEINTRIN_impDATAN //
16328 d__1 = atan(d1);
16329 food_(&d__1);
16330 // FFEINTRIN_impDATAN2 //
16331 d__1 = atan2(d1, d2);
16332 food_(&d__1);
16333 // FFEINTRIN_impDCOS //
16334 d__1 = cos(d1);
16335 food_(&d__1);
16336 // FFEINTRIN_impDCOSH //
16337 d__1 = cosh(d1);
16338 food_(&d__1);
16339 // FFEINTRIN_impDDIM //
16340 d__1 = d_dim(&d1, &d2);
16341 food_(&d__1);
16342 // FFEINTRIN_impDEXP //
16343 d__1 = exp(d1);
16344 food_(&d__1);
16345 // FFEINTRIN_impDIM //
16346 r__1 = r_dim(&r1, &r2);
16347 foor_(&r__1);
16348 // FFEINTRIN_impDINT //
16349 d__1 = d_int(&d1);
16350 food_(&d__1);
16351 // FFEINTRIN_impDLOG //
16352 d__1 = log(d1);
16353 food_(&d__1);
16354 // FFEINTRIN_impDLOG10 //
16355 d__1 = d_lg10(&d1);
16356 food_(&d__1);
16357 // FFEINTRIN_impDMAX1 //
16358 d__1 = (( d1 ) >= ( d2 ) ? ( d1 ) : ( d2 )) ;
16359 food_(&d__1);
16360 // FFEINTRIN_impDMIN1 //
16361 d__1 = (( d1 ) <= ( d2 ) ? ( d1 ) : ( d2 )) ;
16362 food_(&d__1);
16363 // FFEINTRIN_impDMOD //
16364 d__1 = d_mod(&d1, &d2);
16365 food_(&d__1);
16366 // FFEINTRIN_impDNINT //
16367 d__1 = d_nint(&d1);
16368 food_(&d__1);
16369 // FFEINTRIN_impDPROD //
16370 d__1 = (doublereal) r1 * r2;
16371 food_(&d__1);
16372 // FFEINTRIN_impDSIGN //
16373 d__1 = d_sign(&d1, &d2);
16374 food_(&d__1);
16375 // FFEINTRIN_impDSIN //
16376 d__1 = sin(d1);
16377 food_(&d__1);
16378 // FFEINTRIN_impDSINH //
16379 d__1 = sinh(d1);
16380 food_(&d__1);
16381 // FFEINTRIN_impDSQRT //
16382 d__1 = sqrt(d1);
16383 food_(&d__1);
16384 // FFEINTRIN_impDTAN //
16385 d__1 = tan(d1);
16386 food_(&d__1);
16387 // FFEINTRIN_impDTANH //
16388 d__1 = tanh(d1);
16389 food_(&d__1);
16390 // FFEINTRIN_impEXP //
16391 r__1 = exp(r1);
16392 foor_(&r__1);
16393 // FFEINTRIN_impIABS //
16394 i__1 = (( i1 ) >= 0 ? ( i1 ) : -( i1 )) ;
16395 fooi_(&i__1);
16396 // FFEINTRIN_impICHAR //
16397 i__1 = *(unsigned char *)a1;
16398 fooi_(&i__1);
16399 // FFEINTRIN_impIDIM //
16400 i__1 = i_dim(&i1, &i2);
16401 fooi_(&i__1);
16402 // FFEINTRIN_impIDNINT //
16403 i__1 = i_dnnt(&d1);
16404 fooi_(&i__1);
16405 // FFEINTRIN_impINDEX //
16406 i__1 = i_indx(a1, a2, 10L, 10L);
16407 fooi_(&i__1);
16408 // FFEINTRIN_impISIGN //
16409 i__1 = i_sign(&i1, &i2);
16410 fooi_(&i__1);
16411 // FFEINTRIN_impLEN //
16412 i__1 = i_len(a1, 10L);
16413 fooi_(&i__1);
16414 // FFEINTRIN_impLGE //
16415 L__1 = l_ge(a1, a2, 10L, 10L);
16416 fool_(&L__1);
16417 // FFEINTRIN_impLGT //
16418 L__1 = l_gt(a1, a2, 10L, 10L);
16419 fool_(&L__1);
16420 // FFEINTRIN_impLLE //
16421 L__1 = l_le(a1, a2, 10L, 10L);
16422 fool_(&L__1);
16423 // FFEINTRIN_impLLT //
16424 L__1 = l_lt(a1, a2, 10L, 10L);
16425 fool_(&L__1);
16426 // FFEINTRIN_impMAX0 //
16427 i__1 = (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
16428 fooi_(&i__1);
16429 // FFEINTRIN_impMAX1 //
16430 i__1 = (integer) (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
16431 fooi_(&i__1);
16432 // FFEINTRIN_impMIN0 //
16433 i__1 = (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
16434 fooi_(&i__1);
16435 // FFEINTRIN_impMIN1 //
16436 i__1 = (integer) (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
16437 fooi_(&i__1);
16438 // FFEINTRIN_impMOD //
16439 i__1 = i1 % i2;
16440 fooi_(&i__1);
16441 // FFEINTRIN_impNINT //
16442 i__1 = i_nint(&r1);
16443 fooi_(&i__1);
16444 // FFEINTRIN_impSIGN //
16445 r__1 = r_sign(&r1, &r2);
16446 foor_(&r__1);
16447 // FFEINTRIN_impSIN //
16448 r__1 = sin(r1);
16449 foor_(&r__1);
16450 // FFEINTRIN_impSINH //
16451 r__1 = sinh(r1);
16452 foor_(&r__1);
16453 // FFEINTRIN_impSQRT //
16454 r__1 = sqrt(r1);
16455 foor_(&r__1);
16456 // FFEINTRIN_impTAN //
16457 r__1 = tan(r1);
16458 foor_(&r__1);
16459 // FFEINTRIN_impTANH //
16460 r__1 = tanh(r1);
16461 foor_(&r__1);
16462 // FFEINTRIN_imp_CMPLX_C //
16463 r__1 = c1.r;
16464 r__2 = c2.r;
16465 q__1.r = r__1, q__1.i = r__2;
16466 fooc_(&q__1);
16467 // FFEINTRIN_imp_CMPLX_D //
16468 z__1.r = d1, z__1.i = d2;
16469 fooz_(&z__1);
16470 // FFEINTRIN_imp_CMPLX_I //
16471 r__1 = (real) i1;
16472 r__2 = (real) i2;
16473 q__1.r = r__1, q__1.i = r__2;
16474 fooc_(&q__1);
16475 // FFEINTRIN_imp_CMPLX_R //
16476 q__1.r = r1, q__1.i = r2;
16477 fooc_(&q__1);
16478 // FFEINTRIN_imp_DBLE_C //
16479 d__1 = (doublereal) c1.r;
16480 food_(&d__1);
16481 // FFEINTRIN_imp_DBLE_D //
16482 d__1 = d1;
16483 food_(&d__1);
16484 // FFEINTRIN_imp_DBLE_I //
16485 d__1 = (doublereal) i1;
16486 food_(&d__1);
16487 // FFEINTRIN_imp_DBLE_R //
16488 d__1 = (doublereal) r1;
16489 food_(&d__1);
16490 // FFEINTRIN_imp_INT_C //
16491 i__1 = (integer) c1.r;
16492 fooi_(&i__1);
16493 // FFEINTRIN_imp_INT_D //
16494 i__1 = (integer) d1;
16495 fooi_(&i__1);
16496 // FFEINTRIN_imp_INT_I //
16497 i__1 = i1;
16498 fooi_(&i__1);
16499 // FFEINTRIN_imp_INT_R //
16500 i__1 = (integer) r1;
16501 fooi_(&i__1);
16502 // FFEINTRIN_imp_REAL_C //
16503 r__1 = c1.r;
16504 foor_(&r__1);
16505 // FFEINTRIN_imp_REAL_D //
16506 r__1 = (real) d1;
16507 foor_(&r__1);
16508 // FFEINTRIN_imp_REAL_I //
16509 r__1 = (real) i1;
16510 foor_(&r__1);
16511 // FFEINTRIN_imp_REAL_R //
16512 r__1 = r1;
16513 foor_(&r__1);
16514
16515 // FFEINTRIN_imp_INT_D: //
16516
16517 // FFEINTRIN_specIDINT //
16518 i__1 = (integer) d1;
16519 fooi_(&i__1);
16520
16521 // FFEINTRIN_imp_INT_R: //
16522
16523 // FFEINTRIN_specIFIX //
16524 i__1 = (integer) r1;
16525 fooi_(&i__1);
16526 // FFEINTRIN_specINT //
16527 i__1 = (integer) r1;
16528 fooi_(&i__1);
16529
16530 // FFEINTRIN_imp_REAL_D: //
16531
16532 // FFEINTRIN_specSNGL //
16533 r__1 = (real) d1;
16534 foor_(&r__1);
16535
16536 // FFEINTRIN_imp_REAL_I: //
16537
16538 // FFEINTRIN_specFLOAT //
16539 r__1 = (real) i1;
16540 foor_(&r__1);
16541 // FFEINTRIN_specREAL //
16542 r__1 = (real) i1;
16543 foor_(&r__1);
16544
16545 } // MAIN__ //
16546
16547 -------- (end output file from f2c)
16548
16549 */
16550
16551 #include "gt-f-com.h"
16552 #include "gtype-f.h"