1 /* com.c -- Implementation File (module.c template V1.0)
2 Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
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 int ffecom_decode_include_option_ (char *spec);
393 static FILE *ffecom_open_include_ (char *name, ffewhereLine l,
394 ffewhereColumn c);
395
396 /* Static objects accessed by functions in this module. */
397
398 static ffesymbol ffecom_primary_entry_ = NULL;
399 static ffesymbol ffecom_nested_entry_ = NULL;
400 static ffeinfoKind ffecom_primary_entry_kind_;
401 static bool ffecom_primary_entry_is_proc_;
402 static GTY(()) tree ffecom_outer_function_decl_;
403 static GTY(()) tree ffecom_previous_function_decl_;
404 static GTY(()) tree ffecom_which_entrypoint_decl_;
405 static GTY(()) tree ffecom_float_zero_;
406 static GTY(()) tree ffecom_float_half_;
407 static GTY(()) tree ffecom_double_zero_;
408 static GTY(()) tree ffecom_double_half_;
409 static GTY(()) tree ffecom_func_result_;/* For functions. */
410 static GTY(()) tree ffecom_func_length_;/* For CHARACTER fns. */
411 static ffebld ffecom_list_blockdata_;
412 static ffebld ffecom_list_common_;
413 static ffebld ffecom_master_arglist_;
414 static ffeinfoBasictype ffecom_master_bt_;
415 static ffeinfoKindtype ffecom_master_kt_;
416 static ffetargetCharacterSize ffecom_master_size_;
417 static int ffecom_num_fns_ = 0;
418 static int ffecom_num_entrypoints_ = 0;
419 static bool ffecom_is_altreturning_ = FALSE;
420 static GTY(()) tree ffecom_multi_type_node_;
421 static GTY(()) tree ffecom_multi_retval_;
422 static GTY(()) tree
423 ffecom_multi_fields_[FFEINFO_basictype][FFEINFO_kindtype];
424 static bool ffecom_member_namelisted_; /* _member_phase1_ namelisted? */
425 static bool ffecom_doing_entry_ = FALSE;
426 static bool ffecom_transform_only_dummies_ = FALSE;
427 static int ffecom_typesize_pointer_;
428 static int ffecom_typesize_integer1_;
429
430 /* Holds pointer-to-function expressions. */
431
432 static GTY(()) tree ffecom_gfrt_[FFECOM_gfrt];
433
434 /* Holds the external names of the functions. */
435
436 static const char *const ffecom_gfrt_name_[FFECOM_gfrt]
437 =
438 {
439 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) NAME,
440 #include "com-rt.def"
441 #undef DEFGFRT
442 };
443
444 /* Whether the function returns. */
445
446 static const bool ffecom_gfrt_volatile_[FFECOM_gfrt]
447 =
448 {
449 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) VOLATILE,
450 #include "com-rt.def"
451 #undef DEFGFRT
452 };
453
454 /* Whether the function returns type complex. */
455
456 static const bool ffecom_gfrt_complex_[FFECOM_gfrt]
457 =
458 {
459 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) COMPLEX,
460 #include "com-rt.def"
461 #undef DEFGFRT
462 };
463
464 /* Whether the function is const
465 (i.e., has no side effects and only depends on its arguments). */
466
467 static const bool ffecom_gfrt_const_[FFECOM_gfrt]
468 =
469 {
470 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) CONST,
471 #include "com-rt.def"
472 #undef DEFGFRT
473 };
474
475 /* Type code for the function return value. */
476
477 static const ffecomRttype_ ffecom_gfrt_type_[FFECOM_gfrt]
478 =
479 {
480 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) TYPE,
481 #include "com-rt.def"
482 #undef DEFGFRT
483 };
484
485 /* String of codes for the function's arguments. */
486
487 static const char *const ffecom_gfrt_argstring_[FFECOM_gfrt]
488 =
489 {
490 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) ARGS,
491 #include "com-rt.def"
492 #undef DEFGFRT
493 };
494
495 /* Internal macros. */
496
497 /* We let tm.h override the types used here, to handle trivial differences
498 such as the choice of unsigned int or long unsigned int for size_t.
499 When machines start needing nontrivial differences in the size type,
500 it would be best to do something here to figure out automatically
501 from other information what type to use. */
502
503 #ifndef SIZE_TYPE
504 #define SIZE_TYPE "long unsigned int"
505 #endif
506
507 #define ffecom_concat_list_count_(catlist) ((catlist).count)
508 #define ffecom_concat_list_expr_(catlist,i) ((catlist).exprs[(i)])
509 #define ffecom_concat_list_maxlen_(catlist) ((catlist).maxlen)
510 #define ffecom_concat_list_minlen_(catlist) ((catlist).minlen)
511
512 #define ffecom_char_args_(i,l,e) ffecom_char_args_x_((i),(l),(e),FALSE)
513 #define ffecom_char_args_with_null_(i,l,e) ffecom_char_args_x_((i),(l),(e),TRUE)
514
515 /* For each binding contour we allocate a binding_level structure
516 * which records the names defined in that contour.
517 * Contours include:
518 * 0) the global one
519 * 1) one for each function definition,
520 * where internal declarations of the parameters appear.
521 *
522 * The current meaning of a name can be found by searching the levels from
523 * the current one out to the global one.
524 */
525
526 /* Note that the information in the `names' component of the global contour
527 is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
528
529 struct f_binding_level GTY(())
530 {
531 /* A chain of _DECL nodes for all variables, constants, functions,
532 and typedef types. These are in the reverse of the order supplied.
533 */
534 tree names;
535
536 /* For each level (except not the global one),
537 a chain of BLOCK nodes for all the levels
538 that were entered and exited one level down. */
539 tree blocks;
540
541 /* The BLOCK node for this level, if one has been preallocated.
542 If 0, the BLOCK is allocated (if needed) when the level is popped. */
543 tree this_block;
544
545 /* The binding level which this one is contained in (inherits from). */
546 struct f_binding_level *level_chain;
547
548 /* 0: no ffecom_prepare_* functions called at this level yet;
549 1: ffecom_prepare* functions called, except not ffecom_prepare_end;
550 2: ffecom_prepare_end called. */
551 int prep_state;
552 };
553
554 #define NULL_BINDING_LEVEL (struct f_binding_level *) NULL
555
556 /* The binding level currently in effect. */
557
558 static GTY(()) struct f_binding_level *current_binding_level;
559
560 /* A chain of binding_level structures awaiting reuse. */
561
562 static GTY((deletable (""))) struct f_binding_level *free_binding_level;
563
564 /* The outermost binding level, for names of file scope.
565 This is created when the compiler is started and exists
566 through the entire run. */
567
568 static struct f_binding_level *global_binding_level;
569
570 /* Binding level structures are initialized by copying this one. */
571
572 static const struct f_binding_level clear_binding_level
573 =
574 {NULL, NULL, NULL, NULL_BINDING_LEVEL, 0};
575
576 /* Language-dependent contents of an identifier. */
577
578 struct lang_identifier GTY(())
579 {
580 struct tree_identifier common;
581 tree global_value;
582 tree local_value;
583 tree label_value;
584 bool invented;
585 };
586
587 /* Macros for access to language-specific slots in an identifier. */
588 /* Each of these slots contains a DECL node or null. */
589
590 /* This represents the value which the identifier has in the
591 file-scope namespace. */
592 #define IDENTIFIER_GLOBAL_VALUE(NODE) \
593 (((struct lang_identifier *)(NODE))->global_value)
594 /* This represents the value which the identifier has in the current
595 scope. */
596 #define IDENTIFIER_LOCAL_VALUE(NODE) \
597 (((struct lang_identifier *)(NODE))->local_value)
598 /* This represents the value which the identifier has as a label in
599 the current label scope. */
600 #define IDENTIFIER_LABEL_VALUE(NODE) \
601 (((struct lang_identifier *)(NODE))->label_value)
602 /* This is nonzero if the identifier was "made up" by g77 code. */
603 #define IDENTIFIER_INVENTED(NODE) \
604 (((struct lang_identifier *)(NODE))->invented)
605
606 /* The resulting tree type. */
607 union lang_tree_node
608 GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
609 chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
610 {
611 union tree_node GTY ((tag ("0"),
612 desc ("tree_node_structure (&%h)")))
613 generic;
614 struct lang_identifier GTY ((tag ("1"))) identifier;
615 };
616
617 /* Fortran doesn't use either of these. */
618 struct lang_decl GTY(())
619 {
620 };
621 struct lang_type GTY(())
622 {
623 };
624
625 /* In identifiers, C uses the following fields in a special way:
626 TREE_PUBLIC to record that there was a previous local extern decl.
627 TREE_USED to record that such a decl was used.
628 TREE_ADDRESSABLE to record that the address of such a decl was used. */
629
630 /* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
631 that have names. Here so we can clear out their names' definitions
632 at the end of the function. */
633
634 static GTY(()) tree named_labels;
635
636 /* A list of LABEL_DECLs from outer contexts that are currently shadowed. */
637
638 static GTY(()) tree shadowed_labels;
639
640 /* Return the subscript expression, modified to do range-checking.
641
642 `array' is the array type to be checked against.
643 `element' is the subscript expression to check.
644 `dim' is the dimension number (starting at 0).
645 `total_dims' is the total number of dimensions (0 for CHARACTER substring).
646 `item' is the array decl or NULL_TREE.
647 */
648
649 static tree
ffecom_subscript_check_(tree array,tree element,int dim,int total_dims,const char * array_name,tree item)650 ffecom_subscript_check_ (tree array, tree element, int dim, int total_dims,
651 const char *array_name, tree item)
652 {
653 tree low = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
654 tree high = TYPE_MAX_VALUE (TYPE_DOMAIN (array));
655 tree cond;
656 tree die;
657 tree args;
658
659 if (element == error_mark_node)
660 return element;
661
662 if (TREE_TYPE (low) != TREE_TYPE (element))
663 {
664 if (TYPE_PRECISION (TREE_TYPE (low))
665 > TYPE_PRECISION (TREE_TYPE (element)))
666 element = convert (TREE_TYPE (low), element);
667 else
668 {
669 low = convert (TREE_TYPE (element), low);
670 if (high)
671 high = convert (TREE_TYPE (element), high);
672 }
673 }
674
675 element = ffecom_save_tree (element);
676 if (total_dims == 0)
677 {
678 /* Special handling for substring range checks. Fortran allows the
679 end subscript < begin subscript, which means that expressions like
680 string(1:0) are valid (and yield a null string). In view of this,
681 enforce two simpler conditions:
682 1) element<=high for end-substring;
683 2) element>=low for start-substring.
684 Run-time character movement will enforce remaining conditions.
685
686 More complicated checks would be better, but present structure only
687 provides one index element at a time, so it is not possible to
688 enforce a check of both i and j in string(i:j). If it were, the
689 complete set of rules would read,
690 if ( ((j<i) && ((low<=i<=high) || (low<=j<=high))) ||
691 ((low<=i<=high) && (low<=j<=high)) )
692 ok ;
693 else
694 range error ;
695 */
696 if (dim)
697 cond = ffecom_2 (LE_EXPR, integer_type_node, element, high);
698 else
699 cond = ffecom_2 (LE_EXPR, integer_type_node, low, element);
700 }
701 else
702 {
703 /* Array reference substring range checking. */
704
705 cond = ffecom_2 (LE_EXPR, integer_type_node,
706 low,
707 element);
708 if (high)
709 {
710 cond = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
711 cond,
712 ffecom_2 (LE_EXPR, integer_type_node,
713 element,
714 high));
715 }
716 }
717
718 /* If the array index is safe at compile-time, return element. */
719 if (integer_nonzerop (cond))
720 return element;
721
722 {
723 int len;
724 char *proc;
725 char *var;
726 tree arg3;
727 tree arg2;
728 tree arg1;
729 tree arg4;
730
731 switch (total_dims)
732 {
733 case 0:
734 var = concat (array_name, "[", (dim ? "end" : "start"),
735 "-substring]", NULL);
736 len = strlen (var) + 1;
737 arg1 = build_string (len, var);
738 free (var);
739 break;
740
741 case 1:
742 len = strlen (array_name) + 1;
743 arg1 = build_string (len, array_name);
744 break;
745
746 default:
747 var = xmalloc (strlen (array_name) + 40);
748 sprintf (var, "%s[subscript-%d-of-%d]",
749 array_name,
750 dim + 1, total_dims);
751 len = strlen (var) + 1;
752 arg1 = build_string (len, var);
753 free (var);
754 break;
755 }
756
757 TREE_TYPE (arg1)
758 = build_type_variant (build_array_type (char_type_node,
759 build_range_type
760 (integer_type_node,
761 integer_one_node,
762 build_int_2 (len, 0))),
763 1, 0);
764 TREE_CONSTANT (arg1) = 1;
765 TREE_STATIC (arg1) = 1;
766 arg1 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg1)),
767 arg1);
768
769 /* s_rnge adds one to the element to print it, so bias against
770 that -- want to print a faithful *subscript* value. */
771 arg2 = convert (ffecom_f2c_ftnint_type_node,
772 ffecom_2 (MINUS_EXPR,
773 TREE_TYPE (element),
774 element,
775 convert (TREE_TYPE (element),
776 integer_one_node)));
777
778 proc = concat (input_filename, "/",
779 IDENTIFIER_POINTER (DECL_NAME (current_function_decl)),
780 NULL);
781 len = strlen (proc) + 1;
782 arg3 = build_string (len, proc);
783
784 free (proc);
785
786 TREE_TYPE (arg3)
787 = build_type_variant (build_array_type (char_type_node,
788 build_range_type
789 (integer_type_node,
790 integer_one_node,
791 build_int_2 (len, 0))),
792 1, 0);
793 TREE_CONSTANT (arg3) = 1;
794 TREE_STATIC (arg3) = 1;
795 arg3 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg3)),
796 arg3);
797
798 arg4 = convert (ffecom_f2c_ftnint_type_node,
799 build_int_2 (lineno, 0));
800
801 arg1 = build_tree_list (NULL_TREE, arg1);
802 arg2 = build_tree_list (NULL_TREE, arg2);
803 arg3 = build_tree_list (NULL_TREE, arg3);
804 arg4 = build_tree_list (NULL_TREE, arg4);
805 TREE_CHAIN (arg3) = arg4;
806 TREE_CHAIN (arg2) = arg3;
807 TREE_CHAIN (arg1) = arg2;
808
809 args = arg1;
810 }
811 die = ffecom_call_gfrt (FFECOM_gfrtRANGE,
812 args, NULL_TREE);
813 TREE_SIDE_EFFECTS (die) = 1;
814 die = convert (void_type_node, die);
815
816 if (integer_zerop (cond) && item)
817 ffe_mark_addressable (item);
818
819 return ffecom_3 (COND_EXPR, TREE_TYPE (element), cond, element, die);
820 }
821
822 /* Return the computed element of an array reference.
823
824 `item' is NULL_TREE, or the transformed pointer to the array.
825 `expr' is the original opARRAYREF expression, which is transformed
826 if `item' is NULL_TREE.
827 `want_ptr' is nonzero if a pointer to the element, instead of
828 the element itself, is to be returned. */
829
830 static tree
ffecom_arrayref_(tree item,ffebld expr,int want_ptr)831 ffecom_arrayref_ (tree item, ffebld expr, int want_ptr)
832 {
833 ffebld dims[FFECOM_dimensionsMAX];
834 int i;
835 int total_dims;
836 int flatten = ffe_is_flatten_arrays ();
837 int need_ptr;
838 tree array;
839 tree element;
840 tree tree_type;
841 tree tree_type_x;
842 const char *array_name;
843 ffetype type;
844 ffebld list;
845
846 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER)
847 array_name = ffesymbol_text (ffebld_symter (ffebld_left (expr)));
848 else
849 array_name = "[expr?]";
850
851 /* Build up ARRAY_REFs in reverse order (since we're column major
852 here in Fortran land). */
853
854 for (i = 0, list = ffebld_right (expr);
855 list != NULL;
856 ++i, list = ffebld_trail (list))
857 {
858 dims[i] = ffebld_head (list);
859 type = ffeinfo_type (ffebld_basictype (dims[i]),
860 ffebld_kindtype (dims[i]));
861 if (! flatten
862 && ffecom_typesize_pointer_ > ffecom_typesize_integer1_
863 && ffetype_size (type) > ffecom_typesize_integer1_)
864 /* E.g. ARRAY(INDEX), given INTEGER*8 INDEX, on a system with 64-bit
865 pointers and 32-bit integers. Do the full 64-bit pointer
866 arithmetic, for codes using arrays for nonstandard heap-like
867 work. */
868 flatten = 1;
869 }
870
871 total_dims = i;
872
873 need_ptr = want_ptr || flatten;
874
875 if (! item)
876 {
877 if (need_ptr)
878 item = ffecom_ptr_to_expr (ffebld_left (expr));
879 else
880 item = ffecom_expr (ffebld_left (expr));
881
882 if (item == error_mark_node)
883 return item;
884
885 if (ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereFLEETING
886 && ! ffe_mark_addressable (item))
887 return error_mark_node;
888 }
889
890 if (item == error_mark_node)
891 return item;
892
893 if (need_ptr)
894 {
895 tree min;
896
897 for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
898 i >= 0;
899 --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
900 {
901 min = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
902 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
903 if (flag_bounds_check)
904 element = ffecom_subscript_check_ (array, element, i, total_dims,
905 array_name, item);
906 if (element == error_mark_node)
907 return element;
908
909 /* Widen integral arithmetic as desired while preserving
910 signedness. */
911 tree_type = TREE_TYPE (element);
912 tree_type_x = tree_type;
913 if (tree_type
914 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
915 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
916 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
917
918 if (TREE_TYPE (min) != tree_type_x)
919 min = convert (tree_type_x, min);
920 if (TREE_TYPE (element) != tree_type_x)
921 element = convert (tree_type_x, element);
922
923 item = ffecom_2 (PLUS_EXPR,
924 build_pointer_type (TREE_TYPE (array)),
925 item,
926 size_binop (MULT_EXPR,
927 size_in_bytes (TREE_TYPE (array)),
928 convert (sizetype,
929 fold (build (MINUS_EXPR,
930 tree_type_x,
931 element, min)))));
932 }
933 if (! want_ptr)
934 {
935 item = ffecom_1 (INDIRECT_REF,
936 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
937 item);
938 }
939 }
940 else
941 {
942 for (--i;
943 i >= 0;
944 --i)
945 {
946 array = TYPE_MAIN_VARIANT (TREE_TYPE (item));
947
948 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
949 if (flag_bounds_check)
950 element = ffecom_subscript_check_ (array, element, i, total_dims,
951 array_name, item);
952 if (element == error_mark_node)
953 return element;
954
955 /* Widen integral arithmetic as desired while preserving
956 signedness. */
957 tree_type = TREE_TYPE (element);
958 tree_type_x = tree_type;
959 if (tree_type
960 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
961 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
962 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
963
964 element = convert (tree_type_x, element);
965
966 item = ffecom_2 (ARRAY_REF,
967 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
968 item,
969 element);
970 }
971 }
972
973 return item;
974 }
975
976 /* This is like gcc's stabilize_reference -- in fact, most of the code
977 comes from that -- but it handles the situation where the reference
978 is going to have its subparts picked at, and it shouldn't change
979 (or trigger extra invocations of functions in the subtrees) due to
980 this. save_expr is a bit overzealous, because we don't need the
981 entire thing calculated and saved like a temp. So, for DECLs, no
982 change is needed, because these are stable aggregates, and ARRAY_REF
983 and such might well be stable too, but for things like calculations,
984 we do need to calculate a snapshot of a value before picking at it. */
985
986 static tree
ffecom_stabilize_aggregate_(tree ref)987 ffecom_stabilize_aggregate_ (tree ref)
988 {
989 tree result;
990 enum tree_code code = TREE_CODE (ref);
991
992 switch (code)
993 {
994 case VAR_DECL:
995 case PARM_DECL:
996 case RESULT_DECL:
997 /* No action is needed in this case. */
998 return ref;
999
1000 case NOP_EXPR:
1001 case CONVERT_EXPR:
1002 case FLOAT_EXPR:
1003 case FIX_TRUNC_EXPR:
1004 case FIX_FLOOR_EXPR:
1005 case FIX_ROUND_EXPR:
1006 case FIX_CEIL_EXPR:
1007 result = build_nt (code, stabilize_reference (TREE_OPERAND (ref, 0)));
1008 break;
1009
1010 case INDIRECT_REF:
1011 result = build_nt (INDIRECT_REF,
1012 stabilize_reference_1 (TREE_OPERAND (ref, 0)));
1013 break;
1014
1015 case COMPONENT_REF:
1016 result = build_nt (COMPONENT_REF,
1017 stabilize_reference (TREE_OPERAND (ref, 0)),
1018 TREE_OPERAND (ref, 1));
1019 break;
1020
1021 case BIT_FIELD_REF:
1022 result = build_nt (BIT_FIELD_REF,
1023 stabilize_reference (TREE_OPERAND (ref, 0)),
1024 stabilize_reference_1 (TREE_OPERAND (ref, 1)),
1025 stabilize_reference_1 (TREE_OPERAND (ref, 2)));
1026 break;
1027
1028 case ARRAY_REF:
1029 result = build_nt (ARRAY_REF,
1030 stabilize_reference (TREE_OPERAND (ref, 0)),
1031 stabilize_reference_1 (TREE_OPERAND (ref, 1)));
1032 break;
1033
1034 case COMPOUND_EXPR:
1035 result = build_nt (COMPOUND_EXPR,
1036 stabilize_reference_1 (TREE_OPERAND (ref, 0)),
1037 stabilize_reference (TREE_OPERAND (ref, 1)));
1038 break;
1039
1040 case RTL_EXPR:
1041 abort ();
1042
1043
1044 default:
1045 return save_expr (ref);
1046
1047 case ERROR_MARK:
1048 return error_mark_node;
1049 }
1050
1051 TREE_TYPE (result) = TREE_TYPE (ref);
1052 TREE_READONLY (result) = TREE_READONLY (ref);
1053 TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (ref);
1054 TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (ref);
1055
1056 return result;
1057 }
1058
1059 /* A rip-off of gcc's convert.c convert_to_complex function,
1060 reworked to handle complex implemented as C structures
1061 (RECORD_TYPE with two fields, real and imaginary `r' and `i'). */
1062
1063 static tree
ffecom_convert_to_complex_(tree type,tree expr)1064 ffecom_convert_to_complex_ (tree type, tree expr)
1065 {
1066 register enum tree_code form = TREE_CODE (TREE_TYPE (expr));
1067 tree subtype;
1068
1069 assert (TREE_CODE (type) == RECORD_TYPE);
1070
1071 subtype = TREE_TYPE (TYPE_FIELDS (type));
1072
1073 if (form == REAL_TYPE || form == INTEGER_TYPE || form == ENUMERAL_TYPE)
1074 {
1075 expr = convert (subtype, expr);
1076 return ffecom_2 (COMPLEX_EXPR, type, expr,
1077 convert (subtype, integer_zero_node));
1078 }
1079
1080 if (form == RECORD_TYPE)
1081 {
1082 tree elt_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr)));
1083 if (TYPE_MAIN_VARIANT (elt_type) == TYPE_MAIN_VARIANT (subtype))
1084 return expr;
1085 else
1086 {
1087 expr = save_expr (expr);
1088 return ffecom_2 (COMPLEX_EXPR,
1089 type,
1090 convert (subtype,
1091 ffecom_1 (REALPART_EXPR,
1092 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1093 expr)),
1094 convert (subtype,
1095 ffecom_1 (IMAGPART_EXPR,
1096 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1097 expr)));
1098 }
1099 }
1100
1101 if (form == POINTER_TYPE || form == REFERENCE_TYPE)
1102 error ("pointer value used where a complex was expected");
1103 else
1104 error ("aggregate value used where a complex was expected");
1105
1106 return ffecom_2 (COMPLEX_EXPR, type,
1107 convert (subtype, integer_zero_node),
1108 convert (subtype, integer_zero_node));
1109 }
1110
1111 /* Like gcc's convert(), but crashes if widening might happen. */
1112
1113 static tree
ffecom_convert_narrow_(type,expr)1114 ffecom_convert_narrow_ (type, expr)
1115 tree type, expr;
1116 {
1117 register tree e = expr;
1118 register enum tree_code code = TREE_CODE (type);
1119
1120 if (type == TREE_TYPE (e)
1121 || TREE_CODE (e) == ERROR_MARK)
1122 return e;
1123 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1124 return fold (build1 (NOP_EXPR, type, e));
1125 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1126 || code == ERROR_MARK)
1127 return error_mark_node;
1128 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1129 {
1130 assert ("void value not ignored as it ought to be" == NULL);
1131 return error_mark_node;
1132 }
1133 assert (code != VOID_TYPE);
1134 if ((code != RECORD_TYPE)
1135 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1136 assert ("converting COMPLEX to REAL" == NULL);
1137 assert (code != ENUMERAL_TYPE);
1138 if (code == INTEGER_TYPE)
1139 {
1140 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1141 && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)))
1142 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1143 && (TYPE_PRECISION (type)
1144 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
1145 return fold (convert_to_integer (type, e));
1146 }
1147 if (code == POINTER_TYPE)
1148 {
1149 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1150 return fold (convert_to_pointer (type, e));
1151 }
1152 if (code == REAL_TYPE)
1153 {
1154 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1155 assert (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)));
1156 return fold (convert_to_real (type, e));
1157 }
1158 if (code == COMPLEX_TYPE)
1159 {
1160 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1161 assert (TYPE_PRECISION (TREE_TYPE (type)) <= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1162 return fold (convert_to_complex (type, e));
1163 }
1164 if (code == RECORD_TYPE)
1165 {
1166 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
1167 /* Check that at least the first field name agrees. */
1168 assert (DECL_NAME (TYPE_FIELDS (type))
1169 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
1170 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1171 <= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
1172 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1173 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1174 return e;
1175 return fold (ffecom_convert_to_complex_ (type, e));
1176 }
1177
1178 assert ("conversion to non-scalar type requested" == NULL);
1179 return error_mark_node;
1180 }
1181
1182 /* Like gcc's convert(), but crashes if narrowing might happen. */
1183
1184 static tree
ffecom_convert_widen_(type,expr)1185 ffecom_convert_widen_ (type, expr)
1186 tree type, expr;
1187 {
1188 register tree e = expr;
1189 register enum tree_code code = TREE_CODE (type);
1190
1191 if (type == TREE_TYPE (e)
1192 || TREE_CODE (e) == ERROR_MARK)
1193 return e;
1194 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1195 return fold (build1 (NOP_EXPR, type, e));
1196 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1197 || code == ERROR_MARK)
1198 return error_mark_node;
1199 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1200 {
1201 assert ("void value not ignored as it ought to be" == NULL);
1202 return error_mark_node;
1203 }
1204 assert (code != VOID_TYPE);
1205 if ((code != RECORD_TYPE)
1206 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1207 assert ("narrowing COMPLEX to REAL" == NULL);
1208 assert (code != ENUMERAL_TYPE);
1209 if (code == INTEGER_TYPE)
1210 {
1211 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1212 && TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)))
1213 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1214 && (TYPE_PRECISION (type)
1215 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
1216 return fold (convert_to_integer (type, e));
1217 }
1218 if (code == POINTER_TYPE)
1219 {
1220 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1221 return fold (convert_to_pointer (type, e));
1222 }
1223 if (code == REAL_TYPE)
1224 {
1225 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1226 assert (TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)));
1227 return fold (convert_to_real (type, e));
1228 }
1229 if (code == COMPLEX_TYPE)
1230 {
1231 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1232 assert (TYPE_PRECISION (TREE_TYPE (type)) >= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1233 return fold (convert_to_complex (type, e));
1234 }
1235 if (code == RECORD_TYPE)
1236 {
1237 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
1238 /* Check that at least the first field name agrees. */
1239 assert (DECL_NAME (TYPE_FIELDS (type))
1240 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
1241 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1242 >= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
1243 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1244 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1245 return e;
1246 return fold (ffecom_convert_to_complex_ (type, e));
1247 }
1248
1249 assert ("conversion to non-scalar type requested" == NULL);
1250 return error_mark_node;
1251 }
1252
1253 /* Handles making a COMPLEX type, either the standard
1254 (but buggy?) gbe way, or the safer (but less elegant?)
1255 f2c way. */
1256
1257 static tree
ffecom_make_complex_type_(tree subtype)1258 ffecom_make_complex_type_ (tree subtype)
1259 {
1260 tree type;
1261 tree realfield;
1262 tree imagfield;
1263
1264 if (ffe_is_emulate_complex ())
1265 {
1266 type = make_node (RECORD_TYPE);
1267 realfield = ffecom_decl_field (type, NULL_TREE, "r", subtype);
1268 imagfield = ffecom_decl_field (type, realfield, "i", subtype);
1269 TYPE_FIELDS (type) = realfield;
1270 layout_type (type);
1271 }
1272 else
1273 {
1274 type = make_node (COMPLEX_TYPE);
1275 TREE_TYPE (type) = subtype;
1276 layout_type (type);
1277 }
1278
1279 return type;
1280 }
1281
1282 /* Chooses either the gbe or the f2c way to build a
1283 complex constant. */
1284
1285 static tree
ffecom_build_complex_constant_(tree type,tree realpart,tree imagpart)1286 ffecom_build_complex_constant_ (tree type, tree realpart, tree imagpart)
1287 {
1288 tree bothparts;
1289
1290 if (ffe_is_emulate_complex ())
1291 {
1292 bothparts = build_tree_list (TYPE_FIELDS (type), realpart);
1293 TREE_CHAIN (bothparts) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), imagpart);
1294 bothparts = build (CONSTRUCTOR, type, NULL_TREE, bothparts);
1295 }
1296 else
1297 {
1298 bothparts = build_complex (type, realpart, imagpart);
1299 }
1300
1301 return bothparts;
1302 }
1303
1304 static tree
ffecom_arglist_expr_(const char * c,ffebld expr)1305 ffecom_arglist_expr_ (const char *c, ffebld expr)
1306 {
1307 tree list;
1308 tree *plist = &list;
1309 tree trail = NULL_TREE; /* Append char length args here. */
1310 tree *ptrail = &trail;
1311 tree length;
1312 ffebld exprh;
1313 tree item;
1314 bool ptr = FALSE;
1315 tree wanted = NULL_TREE;
1316 static const char zed[] = "0";
1317
1318 if (c == NULL)
1319 c = &zed[0];
1320
1321 while (expr != NULL)
1322 {
1323 if (*c != '\0')
1324 {
1325 ptr = FALSE;
1326 if (*c == '&')
1327 {
1328 ptr = TRUE;
1329 ++c;
1330 }
1331 switch (*(c++))
1332 {
1333 case '\0':
1334 ptr = TRUE;
1335 wanted = NULL_TREE;
1336 break;
1337
1338 case 'a':
1339 assert (ptr);
1340 wanted = NULL_TREE;
1341 break;
1342
1343 case 'c':
1344 wanted = ffecom_f2c_complex_type_node;
1345 break;
1346
1347 case 'd':
1348 wanted = ffecom_f2c_doublereal_type_node;
1349 break;
1350
1351 case 'e':
1352 wanted = ffecom_f2c_doublecomplex_type_node;
1353 break;
1354
1355 case 'f':
1356 wanted = ffecom_f2c_real_type_node;
1357 break;
1358
1359 case 'i':
1360 wanted = ffecom_f2c_integer_type_node;
1361 break;
1362
1363 case 'j':
1364 wanted = ffecom_f2c_longint_type_node;
1365 break;
1366
1367 default:
1368 assert ("bad argstring code" == NULL);
1369 wanted = NULL_TREE;
1370 break;
1371 }
1372 }
1373
1374 exprh = ffebld_head (expr);
1375 if (exprh == NULL)
1376 wanted = NULL_TREE;
1377
1378 if ((wanted == NULL_TREE)
1379 || (ptr
1380 && (TYPE_MODE
1381 (ffecom_tree_type[ffeinfo_basictype (ffebld_info (exprh))]
1382 [ffeinfo_kindtype (ffebld_info (exprh))])
1383 == TYPE_MODE (wanted))))
1384 *plist
1385 = build_tree_list (NULL_TREE,
1386 ffecom_arg_ptr_to_expr (exprh,
1387 &length));
1388 else
1389 {
1390 item = ffecom_arg_expr (exprh, &length);
1391 item = ffecom_convert_widen_ (wanted, item);
1392 if (ptr)
1393 {
1394 item = ffecom_1 (ADDR_EXPR,
1395 build_pointer_type (TREE_TYPE (item)),
1396 item);
1397 }
1398 *plist
1399 = build_tree_list (NULL_TREE,
1400 item);
1401 }
1402
1403 plist = &TREE_CHAIN (*plist);
1404 expr = ffebld_trail (expr);
1405 if (length != NULL_TREE)
1406 {
1407 *ptrail = build_tree_list (NULL_TREE, length);
1408 ptrail = &TREE_CHAIN (*ptrail);
1409 }
1410 }
1411
1412 /* We've run out of args in the call; if the implementation expects
1413 more, supply null pointers for them, which the implementation can
1414 check to see if an arg was omitted. */
1415
1416 while (*c != '\0' && *c != '0')
1417 {
1418 if (*c == '&')
1419 ++c;
1420 else
1421 assert ("missing arg to run-time routine!" == NULL);
1422
1423 switch (*(c++))
1424 {
1425 case '\0':
1426 case 'a':
1427 case 'c':
1428 case 'd':
1429 case 'e':
1430 case 'f':
1431 case 'i':
1432 case 'j':
1433 break;
1434
1435 default:
1436 assert ("bad arg string code" == NULL);
1437 break;
1438 }
1439 *plist
1440 = build_tree_list (NULL_TREE,
1441 null_pointer_node);
1442 plist = &TREE_CHAIN (*plist);
1443 }
1444
1445 *plist = trail;
1446
1447 return list;
1448 }
1449
1450 static tree
ffecom_widest_expr_type_(ffebld list)1451 ffecom_widest_expr_type_ (ffebld list)
1452 {
1453 ffebld item;
1454 ffebld widest = NULL;
1455 ffetype type;
1456 ffetype widest_type = NULL;
1457 tree t;
1458
1459 for (; list != NULL; list = ffebld_trail (list))
1460 {
1461 item = ffebld_head (list);
1462 if (item == NULL)
1463 continue;
1464 if ((widest != NULL)
1465 && (ffeinfo_basictype (ffebld_info (item))
1466 != ffeinfo_basictype (ffebld_info (widest))))
1467 continue;
1468 type = ffeinfo_type (ffeinfo_basictype (ffebld_info (item)),
1469 ffeinfo_kindtype (ffebld_info (item)));
1470 if ((widest == FFEINFO_kindtypeNONE)
1471 || (ffetype_size (type)
1472 > ffetype_size (widest_type)))
1473 {
1474 widest = item;
1475 widest_type = type;
1476 }
1477 }
1478
1479 assert (widest != NULL);
1480 t = ffecom_tree_type[ffeinfo_basictype (ffebld_info (widest))]
1481 [ffeinfo_kindtype (ffebld_info (widest))];
1482 assert (t != NULL_TREE);
1483 return t;
1484 }
1485
1486 /* Check whether a partial overlap between two expressions is possible.
1487
1488 Can *starting* to write a portion of expr1 change the value
1489 computed (perhaps already, *partially*) by expr2?
1490
1491 Currently, this is a concern only for a COMPLEX expr1. But if it
1492 isn't in COMMON or local EQUIVALENCE, since we don't support
1493 aliasing of arguments, it isn't a concern. */
1494
1495 static bool
ffecom_possible_partial_overlap_(ffebld expr1,ffebld expr2 ATTRIBUTE_UNUSED)1496 ffecom_possible_partial_overlap_ (ffebld expr1, ffebld expr2 ATTRIBUTE_UNUSED)
1497 {
1498 ffesymbol sym;
1499 ffestorag st;
1500
1501 switch (ffebld_op (expr1))
1502 {
1503 case FFEBLD_opSYMTER:
1504 sym = ffebld_symter (expr1);
1505 break;
1506
1507 case FFEBLD_opARRAYREF:
1508 if (ffebld_op (ffebld_left (expr1)) != FFEBLD_opSYMTER)
1509 return FALSE;
1510 sym = ffebld_symter (ffebld_left (expr1));
1511 break;
1512
1513 default:
1514 return FALSE;
1515 }
1516
1517 if (ffesymbol_where (sym) != FFEINFO_whereCOMMON
1518 && (ffesymbol_where (sym) != FFEINFO_whereLOCAL
1519 || ! (st = ffesymbol_storage (sym))
1520 || ! ffestorag_parent (st)))
1521 return FALSE;
1522
1523 /* It's in COMMON or local EQUIVALENCE. */
1524
1525 return TRUE;
1526 }
1527
1528 /* Check whether dest and source might overlap. ffebld versions of these
1529 might or might not be passed, will be NULL if not.
1530
1531 The test is really whether source_tree is modifiable and, if modified,
1532 might overlap destination such that the value(s) in the destination might
1533 change before it is finally modified. dest_* are the canonized
1534 destination itself. */
1535
1536 static bool
ffecom_overlap_(tree dest_decl,tree dest_offset,tree dest_size,tree source_tree,ffebld source UNUSED,bool scalar_arg)1537 ffecom_overlap_ (tree dest_decl, tree dest_offset, tree dest_size,
1538 tree source_tree, ffebld source UNUSED,
1539 bool scalar_arg)
1540 {
1541 tree source_decl;
1542 tree source_offset;
1543 tree source_size;
1544 tree t;
1545
1546 if (source_tree == NULL_TREE)
1547 return FALSE;
1548
1549 switch (TREE_CODE (source_tree))
1550 {
1551 case ERROR_MARK:
1552 case IDENTIFIER_NODE:
1553 case INTEGER_CST:
1554 case REAL_CST:
1555 case COMPLEX_CST:
1556 case STRING_CST:
1557 case CONST_DECL:
1558 case VAR_DECL:
1559 case RESULT_DECL:
1560 case FIELD_DECL:
1561 case MINUS_EXPR:
1562 case MULT_EXPR:
1563 case TRUNC_DIV_EXPR:
1564 case CEIL_DIV_EXPR:
1565 case FLOOR_DIV_EXPR:
1566 case ROUND_DIV_EXPR:
1567 case TRUNC_MOD_EXPR:
1568 case CEIL_MOD_EXPR:
1569 case FLOOR_MOD_EXPR:
1570 case ROUND_MOD_EXPR:
1571 case RDIV_EXPR:
1572 case EXACT_DIV_EXPR:
1573 case FIX_TRUNC_EXPR:
1574 case FIX_CEIL_EXPR:
1575 case FIX_FLOOR_EXPR:
1576 case FIX_ROUND_EXPR:
1577 case FLOAT_EXPR:
1578 case NEGATE_EXPR:
1579 case MIN_EXPR:
1580 case MAX_EXPR:
1581 case ABS_EXPR:
1582 case FFS_EXPR:
1583 case LSHIFT_EXPR:
1584 case RSHIFT_EXPR:
1585 case LROTATE_EXPR:
1586 case RROTATE_EXPR:
1587 case BIT_IOR_EXPR:
1588 case BIT_XOR_EXPR:
1589 case BIT_AND_EXPR:
1590 case BIT_ANDTC_EXPR:
1591 case BIT_NOT_EXPR:
1592 case TRUTH_ANDIF_EXPR:
1593 case TRUTH_ORIF_EXPR:
1594 case TRUTH_AND_EXPR:
1595 case TRUTH_OR_EXPR:
1596 case TRUTH_XOR_EXPR:
1597 case TRUTH_NOT_EXPR:
1598 case LT_EXPR:
1599 case LE_EXPR:
1600 case GT_EXPR:
1601 case GE_EXPR:
1602 case EQ_EXPR:
1603 case NE_EXPR:
1604 case COMPLEX_EXPR:
1605 case CONJ_EXPR:
1606 case REALPART_EXPR:
1607 case IMAGPART_EXPR:
1608 case LABEL_EXPR:
1609 case COMPONENT_REF:
1610 return FALSE;
1611
1612 case COMPOUND_EXPR:
1613 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1614 TREE_OPERAND (source_tree, 1), NULL,
1615 scalar_arg);
1616
1617 case MODIFY_EXPR:
1618 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1619 TREE_OPERAND (source_tree, 0), NULL,
1620 scalar_arg);
1621
1622 case CONVERT_EXPR:
1623 case NOP_EXPR:
1624 case NON_LVALUE_EXPR:
1625 case PLUS_EXPR:
1626 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1627 return TRUE;
1628
1629 ffecom_tree_canonize_ptr_ (&source_decl, &source_offset,
1630 source_tree);
1631 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1632 break;
1633
1634 case COND_EXPR:
1635 return
1636 ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1637 TREE_OPERAND (source_tree, 1), NULL,
1638 scalar_arg)
1639 || ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1640 TREE_OPERAND (source_tree, 2), NULL,
1641 scalar_arg);
1642
1643
1644 case ADDR_EXPR:
1645 ffecom_tree_canonize_ref_ (&source_decl, &source_offset,
1646 &source_size,
1647 TREE_OPERAND (source_tree, 0));
1648 break;
1649
1650 case PARM_DECL:
1651 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1652 return TRUE;
1653
1654 source_decl = source_tree;
1655 source_offset = bitsize_zero_node;
1656 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1657 break;
1658
1659 case SAVE_EXPR:
1660 case REFERENCE_EXPR:
1661 case PREDECREMENT_EXPR:
1662 case PREINCREMENT_EXPR:
1663 case POSTDECREMENT_EXPR:
1664 case POSTINCREMENT_EXPR:
1665 case INDIRECT_REF:
1666 case ARRAY_REF:
1667 case CALL_EXPR:
1668 default:
1669 return TRUE;
1670 }
1671
1672 /* Come here when source_decl, source_offset, and source_size filled
1673 in appropriately. */
1674
1675 if (source_decl == NULL_TREE)
1676 return FALSE; /* No decl involved, so no overlap. */
1677
1678 if (source_decl != dest_decl)
1679 return FALSE; /* Different decl, no overlap. */
1680
1681 if (TREE_CODE (dest_size) == ERROR_MARK)
1682 return TRUE; /* Assignment into entire assumed-size
1683 array? Shouldn't happen.... */
1684
1685 t = ffecom_2 (LE_EXPR, integer_type_node,
1686 ffecom_2 (PLUS_EXPR, TREE_TYPE (dest_offset),
1687 dest_offset,
1688 convert (TREE_TYPE (dest_offset),
1689 dest_size)),
1690 convert (TREE_TYPE (dest_offset),
1691 source_offset));
1692
1693 if (integer_onep (t))
1694 return FALSE; /* Destination precedes source. */
1695
1696 if (!scalar_arg
1697 || (source_size == NULL_TREE)
1698 || (TREE_CODE (source_size) == ERROR_MARK)
1699 || integer_zerop (source_size))
1700 return TRUE; /* No way to tell if dest follows source. */
1701
1702 t = ffecom_2 (LE_EXPR, integer_type_node,
1703 ffecom_2 (PLUS_EXPR, TREE_TYPE (source_offset),
1704 source_offset,
1705 convert (TREE_TYPE (source_offset),
1706 source_size)),
1707 convert (TREE_TYPE (source_offset),
1708 dest_offset));
1709
1710 if (integer_onep (t))
1711 return FALSE; /* Destination follows source. */
1712
1713 return TRUE; /* Destination and source overlap. */
1714 }
1715
1716 /* Check whether dest might overlap any of a list of arguments or is
1717 in a COMMON area the callee might know about (and thus modify). */
1718
1719 static bool
ffecom_args_overlapping_(tree dest_tree,ffebld dest UNUSED,tree args,tree callee_commons,bool scalar_args)1720 ffecom_args_overlapping_ (tree dest_tree, ffebld dest UNUSED,
1721 tree args, tree callee_commons,
1722 bool scalar_args)
1723 {
1724 tree arg;
1725 tree dest_decl;
1726 tree dest_offset;
1727 tree dest_size;
1728
1729 ffecom_tree_canonize_ref_ (&dest_decl, &dest_offset, &dest_size,
1730 dest_tree);
1731
1732 if (dest_decl == NULL_TREE)
1733 return FALSE; /* Seems unlikely! */
1734
1735 /* If the decl cannot be determined reliably, or if its in COMMON
1736 and the callee isn't known to not futz with COMMON via other
1737 means, overlap might happen. */
1738
1739 if ((TREE_CODE (dest_decl) == ERROR_MARK)
1740 || ((callee_commons != NULL_TREE)
1741 && TREE_PUBLIC (dest_decl)))
1742 return TRUE;
1743
1744 for (; args != NULL_TREE; args = TREE_CHAIN (args))
1745 {
1746 if (((arg = TREE_VALUE (args)) != NULL_TREE)
1747 && ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1748 arg, NULL, scalar_args))
1749 return TRUE;
1750 }
1751
1752 return FALSE;
1753 }
1754
1755 /* Build a string for a variable name as used by NAMELIST. This means that
1756 if we're using the f2c library, we build an uppercase string, since
1757 f2c does this. */
1758
1759 static tree
ffecom_build_f2c_string_(int i,const char * s)1760 ffecom_build_f2c_string_ (int i, const char *s)
1761 {
1762 if (!ffe_is_f2c_library ())
1763 return build_string (i, s);
1764
1765 {
1766 char *tmp;
1767 const char *p;
1768 char *q;
1769 char space[34];
1770 tree t;
1771
1772 if (((size_t) i) > ARRAY_SIZE (space))
1773 tmp = malloc_new_ks (malloc_pool_image (), "f2c_string", i);
1774 else
1775 tmp = &space[0];
1776
1777 for (p = s, q = tmp; *p != '\0'; ++p, ++q)
1778 *q = TOUPPER (*p);
1779 *q = '\0';
1780
1781 t = build_string (i, tmp);
1782
1783 if (((size_t) i) > ARRAY_SIZE (space))
1784 malloc_kill_ks (malloc_pool_image (), tmp, i);
1785
1786 return t;
1787 }
1788 }
1789
1790 /* Returns CALL_EXPR or equivalent with given type (pass NULL_TREE for
1791 type to just get whatever the function returns), handling the
1792 f2c value-returning convention, if required, by prepending
1793 to the arglist a pointer to a temporary to receive the return value. */
1794
1795 static tree
ffecom_call_(tree fn,ffeinfoKindtype kt,bool is_f2c_complex,tree type,tree args,tree dest_tree,ffebld dest,bool * dest_used,tree callee_commons,bool scalar_args,tree hook)1796 ffecom_call_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1797 tree type, tree args, tree dest_tree,
1798 ffebld dest, bool *dest_used, tree callee_commons,
1799 bool scalar_args, tree hook)
1800 {
1801 tree item;
1802 tree tempvar;
1803
1804 if (dest_used != NULL)
1805 *dest_used = FALSE;
1806
1807 if (is_f2c_complex)
1808 {
1809 if ((dest_used == NULL)
1810 || (dest == NULL)
1811 || (ffeinfo_basictype (ffebld_info (dest))
1812 != FFEINFO_basictypeCOMPLEX)
1813 || (ffeinfo_kindtype (ffebld_info (dest)) != kt)
1814 || ((type != NULL_TREE) && (TREE_TYPE (dest_tree) != type))
1815 || ffecom_args_overlapping_ (dest_tree, dest, args,
1816 callee_commons,
1817 scalar_args))
1818 {
1819 tempvar = hook;
1820 assert (tempvar);
1821 }
1822 else
1823 {
1824 *dest_used = TRUE;
1825 tempvar = dest_tree;
1826 type = NULL_TREE;
1827 }
1828
1829 item
1830 = build_tree_list (NULL_TREE,
1831 ffecom_1 (ADDR_EXPR,
1832 build_pointer_type (TREE_TYPE (tempvar)),
1833 tempvar));
1834 TREE_CHAIN (item) = args;
1835
1836 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1837 item, NULL_TREE);
1838
1839 if (tempvar != dest_tree)
1840 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item, tempvar);
1841 }
1842 else
1843 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1844 args, NULL_TREE);
1845
1846 if ((type != NULL_TREE) && (TREE_TYPE (item) != type))
1847 item = ffecom_convert_narrow_ (type, item);
1848
1849 return item;
1850 }
1851
1852 /* Given two arguments, transform them and make a call to the given
1853 function via ffecom_call_. */
1854
1855 static tree
ffecom_call_binop_(tree fn,ffeinfoKindtype kt,bool is_f2c_complex,tree type,ffebld left,ffebld right,tree dest_tree,ffebld dest,bool * dest_used,tree callee_commons,bool scalar_args,bool ref,tree hook)1856 ffecom_call_binop_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1857 tree type, ffebld left, ffebld right,
1858 tree dest_tree, ffebld dest, bool *dest_used,
1859 tree callee_commons, bool scalar_args, bool ref, tree hook)
1860 {
1861 tree left_tree;
1862 tree right_tree;
1863 tree left_length;
1864 tree right_length;
1865
1866 if (ref)
1867 {
1868 /* Pass arguments by reference. */
1869 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
1870 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
1871 }
1872 else
1873 {
1874 /* Pass arguments by value. */
1875 left_tree = ffecom_arg_expr (left, &left_length);
1876 right_tree = ffecom_arg_expr (right, &right_length);
1877 }
1878
1879
1880 left_tree = build_tree_list (NULL_TREE, left_tree);
1881 right_tree = build_tree_list (NULL_TREE, right_tree);
1882 TREE_CHAIN (left_tree) = right_tree;
1883
1884 if (left_length != NULL_TREE)
1885 {
1886 left_length = build_tree_list (NULL_TREE, left_length);
1887 TREE_CHAIN (right_tree) = left_length;
1888 }
1889
1890 if (right_length != NULL_TREE)
1891 {
1892 right_length = build_tree_list (NULL_TREE, right_length);
1893 if (left_length != NULL_TREE)
1894 TREE_CHAIN (left_length) = right_length;
1895 else
1896 TREE_CHAIN (right_tree) = right_length;
1897 }
1898
1899 return ffecom_call_ (fn, kt, is_f2c_complex, type, left_tree,
1900 dest_tree, dest, dest_used, callee_commons,
1901 scalar_args, hook);
1902 }
1903
1904 /* Return ptr/length args for char subexpression
1905
1906 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
1907 subexpressions by constructing the appropriate trees for the ptr-to-
1908 character-text and length-of-character-text arguments in a calling
1909 sequence.
1910
1911 Note that if with_null is TRUE, and the expression is an opCONTER,
1912 a null byte is appended to the string. */
1913
1914 static void
ffecom_char_args_x_(tree * xitem,tree * length,ffebld expr,bool with_null)1915 ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
1916 {
1917 tree item;
1918 tree high;
1919 ffetargetCharacter1 val;
1920 ffetargetCharacterSize newlen;
1921
1922 switch (ffebld_op (expr))
1923 {
1924 case FFEBLD_opCONTER:
1925 val = ffebld_constant_character1 (ffebld_conter (expr));
1926 newlen = ffetarget_length_character1 (val);
1927 if (with_null)
1928 {
1929 /* Begin FFETARGET-NULL-KLUDGE. */
1930 if (newlen != 0)
1931 ++newlen;
1932 }
1933 *length = build_int_2 (newlen, 0);
1934 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
1935 high = build_int_2 (newlen, 0);
1936 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
1937 item = build_string (newlen,
1938 ffetarget_text_character1 (val));
1939 /* End FFETARGET-NULL-KLUDGE. */
1940 TREE_TYPE (item)
1941 = build_type_variant
1942 (build_array_type
1943 (char_type_node,
1944 build_range_type
1945 (ffecom_f2c_ftnlen_type_node,
1946 ffecom_f2c_ftnlen_one_node,
1947 high)),
1948 1, 0);
1949 TREE_CONSTANT (item) = 1;
1950 TREE_STATIC (item) = 1;
1951 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
1952 item);
1953 break;
1954
1955 case FFEBLD_opSYMTER:
1956 {
1957 ffesymbol s = ffebld_symter (expr);
1958
1959 item = ffesymbol_hook (s).decl_tree;
1960 if (item == NULL_TREE)
1961 {
1962 s = ffecom_sym_transform_ (s);
1963 item = ffesymbol_hook (s).decl_tree;
1964 }
1965 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
1966 {
1967 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
1968 *length = ffesymbol_hook (s).length_tree;
1969 else
1970 {
1971 *length = build_int_2 (ffesymbol_size (s), 0);
1972 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
1973 }
1974 }
1975 else if (item == error_mark_node)
1976 *length = error_mark_node;
1977 else
1978 /* FFEINFO_kindFUNCTION. */
1979 *length = NULL_TREE;
1980 if (!ffesymbol_hook (s).addr
1981 && (item != error_mark_node))
1982 item = ffecom_1 (ADDR_EXPR,
1983 build_pointer_type (TREE_TYPE (item)),
1984 item);
1985 }
1986 break;
1987
1988 case FFEBLD_opARRAYREF:
1989 {
1990 ffecom_char_args_ (&item, length, ffebld_left (expr));
1991
1992 if (item == error_mark_node || *length == error_mark_node)
1993 {
1994 item = *length = error_mark_node;
1995 break;
1996 }
1997
1998 item = ffecom_arrayref_ (item, expr, 1);
1999 }
2000 break;
2001
2002 case FFEBLD_opSUBSTR:
2003 {
2004 ffebld start;
2005 ffebld end;
2006 ffebld thing = ffebld_right (expr);
2007 tree start_tree;
2008 tree end_tree;
2009 const char *char_name;
2010 ffebld left_symter;
2011 tree array;
2012
2013 assert (ffebld_op (thing) == FFEBLD_opITEM);
2014 start = ffebld_head (thing);
2015 thing = ffebld_trail (thing);
2016 assert (ffebld_trail (thing) == NULL);
2017 end = ffebld_head (thing);
2018
2019 /* Determine name for pretty-printing range-check errors. */
2020 for (left_symter = ffebld_left (expr);
2021 left_symter && ffebld_op (left_symter) == FFEBLD_opARRAYREF;
2022 left_symter = ffebld_left (left_symter))
2023 ;
2024 if (ffebld_op (left_symter) == FFEBLD_opSYMTER)
2025 char_name = ffesymbol_text (ffebld_symter (left_symter));
2026 else
2027 char_name = "[expr?]";
2028
2029 ffecom_char_args_ (&item, length, ffebld_left (expr));
2030
2031 if (item == error_mark_node || *length == error_mark_node)
2032 {
2033 item = *length = error_mark_node;
2034 break;
2035 }
2036
2037 array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
2038
2039 /* ~~~~Handle INTEGER*8 start/end, a la FFEBLD_opARRAYREF. */
2040
2041 if (start == NULL)
2042 {
2043 if (end == NULL)
2044 ;
2045 else
2046 {
2047 end_tree = ffecom_expr (end);
2048 if (flag_bounds_check)
2049 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2050 char_name, NULL_TREE);
2051 end_tree = convert (ffecom_f2c_ftnlen_type_node,
2052 end_tree);
2053
2054 if (end_tree == error_mark_node)
2055 {
2056 item = *length = error_mark_node;
2057 break;
2058 }
2059
2060 *length = end_tree;
2061 }
2062 }
2063 else
2064 {
2065 start_tree = ffecom_expr (start);
2066 if (flag_bounds_check)
2067 start_tree = ffecom_subscript_check_ (array, start_tree, 0, 0,
2068 char_name, NULL_TREE);
2069 start_tree = convert (ffecom_f2c_ftnlen_type_node,
2070 start_tree);
2071
2072 if (start_tree == error_mark_node)
2073 {
2074 item = *length = error_mark_node;
2075 break;
2076 }
2077
2078 start_tree = ffecom_save_tree (start_tree);
2079
2080 item = ffecom_2 (PLUS_EXPR, TREE_TYPE (item),
2081 item,
2082 ffecom_2 (MINUS_EXPR,
2083 TREE_TYPE (start_tree),
2084 start_tree,
2085 ffecom_f2c_ftnlen_one_node));
2086
2087 if (end == NULL)
2088 {
2089 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2090 ffecom_f2c_ftnlen_one_node,
2091 ffecom_2 (MINUS_EXPR,
2092 ffecom_f2c_ftnlen_type_node,
2093 *length,
2094 start_tree));
2095 }
2096 else
2097 {
2098 end_tree = ffecom_expr (end);
2099 if (flag_bounds_check)
2100 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2101 char_name, NULL_TREE);
2102 end_tree = convert (ffecom_f2c_ftnlen_type_node,
2103 end_tree);
2104
2105 if (end_tree == error_mark_node)
2106 {
2107 item = *length = error_mark_node;
2108 break;
2109 }
2110
2111 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2112 ffecom_f2c_ftnlen_one_node,
2113 ffecom_2 (MINUS_EXPR,
2114 ffecom_f2c_ftnlen_type_node,
2115 end_tree, start_tree));
2116 }
2117 }
2118 }
2119 break;
2120
2121 case FFEBLD_opFUNCREF:
2122 {
2123 ffesymbol s = ffebld_symter (ffebld_left (expr));
2124 tree tempvar;
2125 tree args;
2126 ffetargetCharacterSize size = ffeinfo_size (ffebld_info (expr));
2127 ffecomGfrt ix;
2128
2129 if (size == FFETARGET_charactersizeNONE)
2130 /* ~~Kludge alert! This should someday be fixed. */
2131 size = 24;
2132
2133 *length = build_int_2 (size, 0);
2134 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2135
2136 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
2137 == FFEINFO_whereINTRINSIC)
2138 {
2139 if (size == 1)
2140 {
2141 /* Invocation of an intrinsic returning CHARACTER*1. */
2142 item = ffecom_expr_intrinsic_ (expr, NULL_TREE,
2143 NULL, NULL);
2144 break;
2145 }
2146 ix = ffeintrin_gfrt_direct (ffebld_symter_implementation (ffebld_left (expr)));
2147 assert (ix != FFECOM_gfrt);
2148 item = ffecom_gfrt_tree_ (ix);
2149 }
2150 else
2151 {
2152 ix = FFECOM_gfrt;
2153 item = ffesymbol_hook (s).decl_tree;
2154 if (item == NULL_TREE)
2155 {
2156 s = ffecom_sym_transform_ (s);
2157 item = ffesymbol_hook (s).decl_tree;
2158 }
2159 if (item == error_mark_node)
2160 {
2161 item = *length = error_mark_node;
2162 break;
2163 }
2164
2165 if (!ffesymbol_hook (s).addr)
2166 item = ffecom_1_fn (item);
2167 }
2168 tempvar = ffebld_nonter_hook (expr);
2169 assert (tempvar);
2170 tempvar = ffecom_1 (ADDR_EXPR,
2171 build_pointer_type (TREE_TYPE (tempvar)),
2172 tempvar);
2173
2174 args = build_tree_list (NULL_TREE, tempvar);
2175
2176 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT) /* Sfunc args by value. */
2177 TREE_CHAIN (args) = ffecom_list_expr (ffebld_right (expr));
2178 else
2179 {
2180 TREE_CHAIN (args) = build_tree_list (NULL_TREE, *length);
2181 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
2182 {
2183 TREE_CHAIN (TREE_CHAIN (args))
2184 = ffecom_arglist_expr_ (ffecom_gfrt_args_ (ix),
2185 ffebld_right (expr));
2186 }
2187 else
2188 {
2189 TREE_CHAIN (TREE_CHAIN (args))
2190 = ffecom_list_ptr_to_expr (ffebld_right (expr));
2191 }
2192 }
2193
2194 item = ffecom_3s (CALL_EXPR,
2195 TREE_TYPE (TREE_TYPE (TREE_TYPE (item))),
2196 item, args, NULL_TREE);
2197 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item,
2198 tempvar);
2199 }
2200 break;
2201
2202 case FFEBLD_opCONVERT:
2203
2204 ffecom_char_args_ (&item, length, ffebld_left (expr));
2205
2206 if (item == error_mark_node || *length == error_mark_node)
2207 {
2208 item = *length = error_mark_node;
2209 break;
2210 }
2211
2212 if ((ffebld_size_known (ffebld_left (expr))
2213 == FFETARGET_charactersizeNONE)
2214 || (ffebld_size_known (ffebld_left (expr)) < (ffebld_size (expr))))
2215 { /* Possible blank-padding needed, copy into
2216 temporary. */
2217 tree tempvar;
2218 tree args;
2219 tree newlen;
2220
2221 tempvar = ffebld_nonter_hook (expr);
2222 assert (tempvar);
2223 tempvar = ffecom_1 (ADDR_EXPR,
2224 build_pointer_type (TREE_TYPE (tempvar)),
2225 tempvar);
2226
2227 newlen = build_int_2 (ffebld_size (expr), 0);
2228 TREE_TYPE (newlen) = ffecom_f2c_ftnlen_type_node;
2229
2230 args = build_tree_list (NULL_TREE, tempvar);
2231 TREE_CHAIN (args) = build_tree_list (NULL_TREE, item);
2232 TREE_CHAIN (TREE_CHAIN (args)) = build_tree_list (NULL_TREE, newlen);
2233 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (args)))
2234 = build_tree_list (NULL_TREE, *length);
2235
2236 item = ffecom_call_gfrt (FFECOM_gfrtCOPY, args, NULL_TREE);
2237 TREE_SIDE_EFFECTS (item) = 1;
2238 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), fold (item),
2239 tempvar);
2240 *length = newlen;
2241 }
2242 else
2243 { /* Just truncate the length. */
2244 *length = build_int_2 (ffebld_size (expr), 0);
2245 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2246 }
2247 break;
2248
2249 default:
2250 assert ("bad op for single char arg expr" == NULL);
2251 item = NULL_TREE;
2252 break;
2253 }
2254
2255 *xitem = item;
2256 }
2257
2258 /* Check the size of the type to be sure it doesn't overflow the
2259 "portable" capacities of the compiler back end. `dummy' types
2260 can generally overflow the normal sizes as long as the computations
2261 themselves don't overflow. A particular target of the back end
2262 must still enforce its size requirements, though, and the back
2263 end takes care of this in stor-layout.c. */
2264
2265 static tree
ffecom_check_size_overflow_(ffesymbol s,tree type,bool dummy)2266 ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy)
2267 {
2268 if (TREE_CODE (type) == ERROR_MARK)
2269 return type;
2270
2271 if (TYPE_SIZE (type) == NULL_TREE)
2272 return type;
2273
2274 if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
2275 return type;
2276
2277 /* An array is too large if size is negative or the type_size overflows
2278 or its "upper half" is larger than 3 (which would make the signed
2279 byte size and offset computations overflow). */
2280
2281 if ((tree_int_cst_sgn (TYPE_SIZE (type)) < 0)
2282 || (!dummy && (TREE_INT_CST_HIGH (TYPE_SIZE (type)) > 3
2283 || TREE_OVERFLOW (TYPE_SIZE (type)))))
2284 {
2285 ffebad_start (FFEBAD_ARRAY_LARGE);
2286 ffebad_string (ffesymbol_text (s));
2287 ffebad_here (0, ffesymbol_where_line (s), ffesymbol_where_column (s));
2288 ffebad_finish ();
2289
2290 return error_mark_node;
2291 }
2292
2293 return type;
2294 }
2295
2296 /* Builds a length argument (PARM_DECL). Also wraps type in an array type
2297 where the dimension info is (1:size) where <size> is ffesymbol_size(s) if
2298 known, length_arg if not known (FFETARGET_charactersizeNONE). */
2299
2300 static tree
ffecom_char_enhance_arg_(tree * xtype,ffesymbol s)2301 ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s)
2302 {
2303 ffetargetCharacterSize sz = ffesymbol_size (s);
2304 tree highval;
2305 tree tlen;
2306 tree type = *xtype;
2307
2308 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
2309 tlen = NULL_TREE; /* A statement function, no length passed. */
2310 else
2311 {
2312 if (ffesymbol_where (s) == FFEINFO_whereDUMMY)
2313 tlen = ffecom_get_invented_identifier ("__g77_length_%s",
2314 ffesymbol_text (s));
2315 else
2316 tlen = ffecom_get_invented_identifier ("__g77_%s", "length");
2317 tlen = build_decl (PARM_DECL, tlen, ffecom_f2c_ftnlen_type_node);
2318 DECL_ARTIFICIAL (tlen) = 1;
2319 }
2320
2321 if (sz == FFETARGET_charactersizeNONE)
2322 {
2323 assert (tlen != NULL_TREE);
2324 highval = variable_size (tlen);
2325 }
2326 else
2327 {
2328 highval = build_int_2 (sz, 0);
2329 TREE_TYPE (highval) = ffecom_f2c_ftnlen_type_node;
2330 }
2331
2332 type = build_array_type (type,
2333 build_range_type (ffecom_f2c_ftnlen_type_node,
2334 ffecom_f2c_ftnlen_one_node,
2335 highval));
2336
2337 *xtype = type;
2338 return tlen;
2339 }
2340
2341 /* ffecom_concat_list_gather_ -- Gather list of concatenated string exprs
2342
2343 ffecomConcatList_ catlist;
2344 ffebld expr; // expr of CHARACTER basictype.
2345 ffetargetCharacterSize max; // max chars to gather or _...NONE if no max
2346 catlist = ffecom_concat_list_gather_(catlist,expr,max);
2347
2348 Scans expr for character subexpressions, updates and returns catlist
2349 accordingly. */
2350
2351 static ffecomConcatList_
ffecom_concat_list_gather_(ffecomConcatList_ catlist,ffebld expr,ffetargetCharacterSize max)2352 ffecom_concat_list_gather_ (ffecomConcatList_ catlist, ffebld expr,
2353 ffetargetCharacterSize max)
2354 {
2355 ffetargetCharacterSize sz;
2356
2357 recurse:
2358
2359 if (expr == NULL)
2360 return catlist;
2361
2362 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen >= max))
2363 return catlist; /* Don't append any more items. */
2364
2365 switch (ffebld_op (expr))
2366 {
2367 case FFEBLD_opCONTER:
2368 case FFEBLD_opSYMTER:
2369 case FFEBLD_opARRAYREF:
2370 case FFEBLD_opFUNCREF:
2371 case FFEBLD_opSUBSTR:
2372 case FFEBLD_opCONVERT: /* Callers should strip this off beforehand
2373 if they don't need to preserve it. */
2374 if (catlist.count == catlist.max)
2375 { /* Make a (larger) list. */
2376 ffebld *newx;
2377 int newmax;
2378
2379 newmax = (catlist.max == 0) ? 8 : catlist.max * 2;
2380 newx = malloc_new_ks (malloc_pool_image (), "catlist",
2381 newmax * sizeof (newx[0]));
2382 if (catlist.max != 0)
2383 {
2384 memcpy (newx, catlist.exprs, catlist.max * sizeof (newx[0]));
2385 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2386 catlist.max * sizeof (newx[0]));
2387 }
2388 catlist.max = newmax;
2389 catlist.exprs = newx;
2390 }
2391 if ((sz = ffebld_size_known (expr)) != FFETARGET_charactersizeNONE)
2392 catlist.minlen += sz;
2393 else
2394 ++catlist.minlen; /* Not true for F90; can be 0 length. */
2395 if ((sz = ffebld_size_max (expr)) == FFETARGET_charactersizeNONE)
2396 catlist.maxlen = sz;
2397 else
2398 catlist.maxlen += sz;
2399 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen > max))
2400 { /* This item overlaps (or is beyond) the end
2401 of the destination. */
2402 switch (ffebld_op (expr))
2403 {
2404 case FFEBLD_opCONTER:
2405 case FFEBLD_opSYMTER:
2406 case FFEBLD_opARRAYREF:
2407 case FFEBLD_opFUNCREF:
2408 case FFEBLD_opSUBSTR:
2409 /* ~~Do useful truncations here. */
2410 break;
2411
2412 default:
2413 assert ("op changed or inconsistent switches!" == NULL);
2414 break;
2415 }
2416 }
2417 catlist.exprs[catlist.count++] = expr;
2418 return catlist;
2419
2420 case FFEBLD_opPAREN:
2421 expr = ffebld_left (expr);
2422 goto recurse; /* :::::::::::::::::::: */
2423
2424 case FFEBLD_opCONCATENATE:
2425 catlist = ffecom_concat_list_gather_ (catlist, ffebld_left (expr), max);
2426 expr = ffebld_right (expr);
2427 goto recurse; /* :::::::::::::::::::: */
2428
2429 #if 0 /* Breaks passing small actual arg to larger
2430 dummy arg of sfunc */
2431 case FFEBLD_opCONVERT:
2432 expr = ffebld_left (expr);
2433 {
2434 ffetargetCharacterSize cmax;
2435
2436 cmax = catlist.len + ffebld_size_known (expr);
2437
2438 if ((max == FFETARGET_charactersizeNONE) || (max > cmax))
2439 max = cmax;
2440 }
2441 goto recurse; /* :::::::::::::::::::: */
2442 #endif
2443
2444 case FFEBLD_opANY:
2445 return catlist;
2446
2447 default:
2448 assert ("bad op in _gather_" == NULL);
2449 return catlist;
2450 }
2451 }
2452
2453 /* ffecom_concat_list_kill_ -- Kill list of concatenated string exprs
2454
2455 ffecomConcatList_ catlist;
2456 ffecom_concat_list_kill_(catlist);
2457
2458 Anything allocated within the list info is deallocated. */
2459
2460 static void
ffecom_concat_list_kill_(ffecomConcatList_ catlist)2461 ffecom_concat_list_kill_ (ffecomConcatList_ catlist)
2462 {
2463 if (catlist.max != 0)
2464 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2465 catlist.max * sizeof (catlist.exprs[0]));
2466 }
2467
2468 /* Make list of concatenated string exprs.
2469
2470 Returns a flattened list of concatenated subexpressions given a
2471 tree of such expressions. */
2472
2473 static ffecomConcatList_
ffecom_concat_list_new_(ffebld expr,ffetargetCharacterSize max)2474 ffecom_concat_list_new_ (ffebld expr, ffetargetCharacterSize max)
2475 {
2476 ffecomConcatList_ catlist;
2477
2478 catlist.maxlen = catlist.minlen = catlist.max = catlist.count = 0;
2479 return ffecom_concat_list_gather_ (catlist, expr, max);
2480 }
2481
2482 /* Provide some kind of useful info on member of aggregate area,
2483 since current g77/gcc technology does not provide debug info
2484 on these members. */
2485
2486 static void
ffecom_debug_kludge_(tree aggr,const char * aggr_type,ffesymbol member,tree member_type UNUSED,ffetargetOffset offset)2487 ffecom_debug_kludge_ (tree aggr, const char *aggr_type, ffesymbol member,
2488 tree member_type UNUSED, ffetargetOffset offset)
2489 {
2490 tree value;
2491 tree decl;
2492 int len;
2493 char *buff;
2494 char space[120];
2495 #if 0
2496 tree type_id;
2497
2498 for (type_id = member_type;
2499 TREE_CODE (type_id) != IDENTIFIER_NODE;
2500 )
2501 {
2502 switch (TREE_CODE (type_id))
2503 {
2504 case INTEGER_TYPE:
2505 case REAL_TYPE:
2506 type_id = TYPE_NAME (type_id);
2507 break;
2508
2509 case ARRAY_TYPE:
2510 case COMPLEX_TYPE:
2511 type_id = TREE_TYPE (type_id);
2512 break;
2513
2514 default:
2515 assert ("no IDENTIFIER_NODE for type!" == NULL);
2516 type_id = error_mark_node;
2517 break;
2518 }
2519 }
2520 #endif
2521
2522 if (ffecom_transform_only_dummies_
2523 || !ffe_is_debug_kludge ())
2524 return; /* Can't do this yet, maybe later. */
2525
2526 len = 60
2527 + strlen (aggr_type)
2528 + IDENTIFIER_LENGTH (DECL_NAME (aggr));
2529 #if 0
2530 + IDENTIFIER_LENGTH (type_id);
2531 #endif
2532
2533 if (((size_t) len) >= ARRAY_SIZE (space))
2534 buff = malloc_new_ks (malloc_pool_image (), "debug_kludge", len + 1);
2535 else
2536 buff = &space[0];
2537
2538 sprintf (&buff[0], "At (%s) `%s' plus %ld bytes",
2539 aggr_type,
2540 IDENTIFIER_POINTER (DECL_NAME (aggr)),
2541 (long int) offset);
2542
2543 value = build_string (len, buff);
2544 TREE_TYPE (value)
2545 = build_type_variant (build_array_type (char_type_node,
2546 build_range_type
2547 (integer_type_node,
2548 integer_one_node,
2549 build_int_2 (strlen (buff), 0))),
2550 1, 0);
2551 decl = build_decl (VAR_DECL,
2552 ffecom_get_identifier_ (ffesymbol_text (member)),
2553 TREE_TYPE (value));
2554 TREE_CONSTANT (decl) = 1;
2555 TREE_STATIC (decl) = 1;
2556 DECL_INITIAL (decl) = error_mark_node;
2557 DECL_IN_SYSTEM_HEADER (decl) = 1; /* Don't let -Wunused complain. */
2558 decl = start_decl (decl, FALSE);
2559 finish_decl (decl, value, FALSE);
2560
2561 if (buff != &space[0])
2562 malloc_kill_ks (malloc_pool_image (), buff, len + 1);
2563 }
2564
2565 /* ffecom_do_entry_ -- Do compilation of a particular entrypoint
2566
2567 ffesymbol fn; // the SUBROUTINE, FUNCTION, or ENTRY symbol itself
2568 int i; // entry# for this entrypoint (used by master fn)
2569 ffecom_do_entrypoint_(s,i);
2570
2571 Makes a public entry point that calls our private master fn (already
2572 compiled). */
2573
2574 static void
ffecom_do_entry_(ffesymbol fn,int entrynum)2575 ffecom_do_entry_ (ffesymbol fn, int entrynum)
2576 {
2577 ffebld item;
2578 tree type; /* Type of function. */
2579 tree multi_retval; /* Var holding return value (union). */
2580 tree result; /* Var holding result. */
2581 ffeinfoBasictype bt;
2582 ffeinfoKindtype kt;
2583 ffeglobal g;
2584 ffeglobalType gt;
2585 bool charfunc; /* All entry points return same type
2586 CHARACTER. */
2587 bool cmplxfunc; /* Use f2c way of returning COMPLEX. */
2588 bool multi; /* Master fn has multiple return types. */
2589 bool altreturning = FALSE; /* This entry point has alternate returns. */
2590 int old_lineno = lineno;
2591 const char *old_input_filename = input_filename;
2592
2593 input_filename = ffesymbol_where_filename (fn);
2594 lineno = ffesymbol_where_filelinenum (fn);
2595
2596 ffecom_doing_entry_ = TRUE; /* Don't bother with array dimensions. */
2597
2598 switch (ffecom_primary_entry_kind_)
2599 {
2600 case FFEINFO_kindFUNCTION:
2601
2602 /* Determine actual return type for function. */
2603
2604 gt = FFEGLOBAL_typeFUNC;
2605 bt = ffesymbol_basictype (fn);
2606 kt = ffesymbol_kindtype (fn);
2607 if (bt == FFEINFO_basictypeNONE)
2608 {
2609 ffeimplic_establish_symbol (fn);
2610 if (ffesymbol_funcresult (fn) != NULL)
2611 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
2612 bt = ffesymbol_basictype (fn);
2613 kt = ffesymbol_kindtype (fn);
2614 }
2615
2616 if (bt == FFEINFO_basictypeCHARACTER)
2617 charfunc = TRUE, cmplxfunc = FALSE;
2618 else if ((bt == FFEINFO_basictypeCOMPLEX)
2619 && ffesymbol_is_f2c (fn))
2620 charfunc = FALSE, cmplxfunc = TRUE;
2621 else
2622 charfunc = cmplxfunc = FALSE;
2623
2624 if (charfunc)
2625 type = ffecom_tree_fun_type_void;
2626 else if (ffesymbol_is_f2c (fn))
2627 type = ffecom_tree_fun_type[bt][kt];
2628 else
2629 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
2630
2631 if ((type == NULL_TREE)
2632 || (TREE_TYPE (type) == NULL_TREE))
2633 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
2634
2635 multi = (ffecom_master_bt_ == FFEINFO_basictypeNONE);
2636 break;
2637
2638 case FFEINFO_kindSUBROUTINE:
2639 gt = FFEGLOBAL_typeSUBR;
2640 bt = FFEINFO_basictypeNONE;
2641 kt = FFEINFO_kindtypeNONE;
2642 if (ffecom_is_altreturning_)
2643 { /* Am _I_ altreturning? */
2644 for (item = ffesymbol_dummyargs (fn);
2645 item != NULL;
2646 item = ffebld_trail (item))
2647 {
2648 if (ffebld_op (ffebld_head (item)) == FFEBLD_opSTAR)
2649 {
2650 altreturning = TRUE;
2651 break;
2652 }
2653 }
2654 if (altreturning)
2655 type = ffecom_tree_subr_type;
2656 else
2657 type = ffecom_tree_fun_type_void;
2658 }
2659 else
2660 type = ffecom_tree_fun_type_void;
2661 charfunc = FALSE;
2662 cmplxfunc = FALSE;
2663 multi = FALSE;
2664 break;
2665
2666 default:
2667 assert ("say what??" == NULL);
2668 /* Fall through. */
2669 case FFEINFO_kindANY:
2670 gt = FFEGLOBAL_typeANY;
2671 bt = FFEINFO_basictypeNONE;
2672 kt = FFEINFO_kindtypeNONE;
2673 type = error_mark_node;
2674 charfunc = FALSE;
2675 cmplxfunc = FALSE;
2676 multi = FALSE;
2677 break;
2678 }
2679
2680 /* build_decl uses the current lineno and input_filename to set the decl
2681 source info. So, I've putzed with ffestd and ffeste code to update that
2682 source info to point to the appropriate statement just before calling
2683 ffecom_do_entrypoint (which calls this fn). */
2684
2685 start_function (ffecom_get_external_identifier_ (fn),
2686 type,
2687 0, /* nested/inline */
2688 1); /* TREE_PUBLIC */
2689
2690 if (((g = ffesymbol_global (fn)) != NULL)
2691 && ((ffeglobal_type (g) == gt)
2692 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
2693 {
2694 ffeglobal_set_hook (g, current_function_decl);
2695 }
2696
2697 /* Reset args in master arg list so they get retransitioned. */
2698
2699 for (item = ffecom_master_arglist_;
2700 item != NULL;
2701 item = ffebld_trail (item))
2702 {
2703 ffebld arg;
2704 ffesymbol s;
2705
2706 arg = ffebld_head (item);
2707 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2708 continue; /* Alternate return or some such thing. */
2709 s = ffebld_symter (arg);
2710 ffesymbol_hook (s).decl_tree = NULL_TREE;
2711 ffesymbol_hook (s).length_tree = NULL_TREE;
2712 }
2713
2714 /* Build dummy arg list for this entry point. */
2715
2716 if (charfunc || cmplxfunc)
2717 { /* Prepend arg for where result goes. */
2718 tree type;
2719 tree length;
2720
2721 if (charfunc)
2722 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
2723 else
2724 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
2725
2726 result = ffecom_get_invented_identifier ("__g77_%s", "result");
2727
2728 /* Make length arg _and_ enhance type info for CHAR arg itself. */
2729
2730 if (charfunc)
2731 length = ffecom_char_enhance_arg_ (&type, fn);
2732 else
2733 length = NULL_TREE; /* Not ref'd if !charfunc. */
2734
2735 type = build_pointer_type (type);
2736 result = build_decl (PARM_DECL, result, type);
2737
2738 push_parm_decl (result);
2739 ffecom_func_result_ = result;
2740
2741 if (charfunc)
2742 {
2743 push_parm_decl (length);
2744 ffecom_func_length_ = length;
2745 }
2746 }
2747 else
2748 result = DECL_RESULT (current_function_decl);
2749
2750 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (fn), FALSE);
2751
2752 store_parm_decls (0);
2753
2754 ffecom_start_compstmt ();
2755 /* Disallow temp vars at this level. */
2756 current_binding_level->prep_state = 2;
2757
2758 /* Make local var to hold return type for multi-type master fn. */
2759
2760 if (multi)
2761 {
2762 multi_retval = ffecom_get_invented_identifier ("__g77_%s",
2763 "multi_retval");
2764 multi_retval = build_decl (VAR_DECL, multi_retval,
2765 ffecom_multi_type_node_);
2766 multi_retval = start_decl (multi_retval, FALSE);
2767 finish_decl (multi_retval, NULL_TREE, FALSE);
2768 }
2769 else
2770 multi_retval = NULL_TREE; /* Not actually ref'd if !multi. */
2771
2772 /* Here we emit the actual code for the entry point. */
2773
2774 {
2775 ffebld list;
2776 ffebld arg;
2777 ffesymbol s;
2778 tree arglist = NULL_TREE;
2779 tree *plist = &arglist;
2780 tree prepend;
2781 tree call;
2782 tree actarg;
2783 tree master_fn;
2784
2785 /* Prepare actual arg list based on master arg list. */
2786
2787 for (list = ffecom_master_arglist_;
2788 list != NULL;
2789 list = ffebld_trail (list))
2790 {
2791 arg = ffebld_head (list);
2792 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2793 continue;
2794 s = ffebld_symter (arg);
2795 if (ffesymbol_hook (s).decl_tree == NULL_TREE
2796 || ffesymbol_hook (s).decl_tree == error_mark_node)
2797 actarg = null_pointer_node; /* We don't have this arg. */
2798 else
2799 actarg = ffesymbol_hook (s).decl_tree;
2800 *plist = build_tree_list (NULL_TREE, actarg);
2801 plist = &TREE_CHAIN (*plist);
2802 }
2803
2804 /* This code appends the length arguments for character
2805 variables/arrays. */
2806
2807 for (list = ffecom_master_arglist_;
2808 list != NULL;
2809 list = ffebld_trail (list))
2810 {
2811 arg = ffebld_head (list);
2812 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2813 continue;
2814 s = ffebld_symter (arg);
2815 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
2816 continue; /* Only looking for CHARACTER arguments. */
2817 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
2818 continue; /* Only looking for variables and arrays. */
2819 if (ffesymbol_hook (s).length_tree == NULL_TREE
2820 || ffesymbol_hook (s).length_tree == error_mark_node)
2821 actarg = ffecom_f2c_ftnlen_zero_node; /* We don't have this arg. */
2822 else
2823 actarg = ffesymbol_hook (s).length_tree;
2824 *plist = build_tree_list (NULL_TREE, actarg);
2825 plist = &TREE_CHAIN (*plist);
2826 }
2827
2828 /* Prepend character-value return info to actual arg list. */
2829
2830 if (charfunc)
2831 {
2832 prepend = build_tree_list (NULL_TREE, ffecom_func_result_);
2833 TREE_CHAIN (prepend)
2834 = build_tree_list (NULL_TREE, ffecom_func_length_);
2835 TREE_CHAIN (TREE_CHAIN (prepend)) = arglist;
2836 arglist = prepend;
2837 }
2838
2839 /* Prepend multi-type return value to actual arg list. */
2840
2841 if (multi)
2842 {
2843 prepend
2844 = build_tree_list (NULL_TREE,
2845 ffecom_1 (ADDR_EXPR,
2846 build_pointer_type (TREE_TYPE (multi_retval)),
2847 multi_retval));
2848 TREE_CHAIN (prepend) = arglist;
2849 arglist = prepend;
2850 }
2851
2852 /* Prepend my entry-point number to the actual arg list. */
2853
2854 prepend = build_tree_list (NULL_TREE, build_int_2 (entrynum, 0));
2855 TREE_CHAIN (prepend) = arglist;
2856 arglist = prepend;
2857
2858 /* Build the call to the master function. */
2859
2860 master_fn = ffecom_1_fn (ffecom_previous_function_decl_);
2861 call = ffecom_3s (CALL_EXPR,
2862 TREE_TYPE (TREE_TYPE (TREE_TYPE (master_fn))),
2863 master_fn, arglist, NULL_TREE);
2864
2865 /* Decide whether the master function is a function or subroutine, and
2866 handle the return value for my entry point. */
2867
2868 if (charfunc || ((ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
2869 && !altreturning))
2870 {
2871 expand_expr_stmt (call);
2872 expand_null_return ();
2873 }
2874 else if (multi && cmplxfunc)
2875 {
2876 expand_expr_stmt (call);
2877 result
2878 = ffecom_1 (INDIRECT_REF,
2879 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
2880 result);
2881 result = ffecom_modify (NULL_TREE, result,
2882 ffecom_2 (COMPONENT_REF, TREE_TYPE (result),
2883 multi_retval,
2884 ffecom_multi_fields_[bt][kt]));
2885 expand_expr_stmt (result);
2886 expand_null_return ();
2887 }
2888 else if (multi)
2889 {
2890 expand_expr_stmt (call);
2891 result
2892 = ffecom_modify (NULL_TREE, result,
2893 convert (TREE_TYPE (result),
2894 ffecom_2 (COMPONENT_REF,
2895 ffecom_tree_type[bt][kt],
2896 multi_retval,
2897 ffecom_multi_fields_[bt][kt])));
2898 expand_return (result);
2899 }
2900 else if (cmplxfunc)
2901 {
2902 result
2903 = ffecom_1 (INDIRECT_REF,
2904 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
2905 result);
2906 result = ffecom_modify (NULL_TREE, result, call);
2907 expand_expr_stmt (result);
2908 expand_null_return ();
2909 }
2910 else
2911 {
2912 result = ffecom_modify (NULL_TREE,
2913 result,
2914 convert (TREE_TYPE (result),
2915 call));
2916 expand_return (result);
2917 }
2918 }
2919
2920 ffecom_end_compstmt ();
2921
2922 finish_function (0);
2923
2924 lineno = old_lineno;
2925 input_filename = old_input_filename;
2926
2927 ffecom_doing_entry_ = FALSE;
2928 }
2929
2930 /* Transform expr into gcc tree with possible destination
2931
2932 Recursive descent on expr while making corresponding tree nodes and
2933 attaching type info and such. If destination supplied and compatible
2934 with temporary that would be made in certain cases, temporary isn't
2935 made, destination used instead, and dest_used flag set TRUE. */
2936
2937 static tree
ffecom_expr_(ffebld expr,tree dest_tree,ffebld dest,bool * dest_used,bool assignp,bool widenp)2938 ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
2939 bool *dest_used, bool assignp, bool widenp)
2940 {
2941 tree item;
2942 tree list;
2943 tree args;
2944 ffeinfoBasictype bt;
2945 ffeinfoKindtype kt;
2946 tree t;
2947 tree dt; /* decl_tree for an ffesymbol. */
2948 tree tree_type, tree_type_x;
2949 tree left, right;
2950 ffesymbol s;
2951 enum tree_code code;
2952
2953 assert (expr != NULL);
2954
2955 if (dest_used != NULL)
2956 *dest_used = FALSE;
2957
2958 bt = ffeinfo_basictype (ffebld_info (expr));
2959 kt = ffeinfo_kindtype (ffebld_info (expr));
2960 tree_type = ffecom_tree_type[bt][kt];
2961
2962 /* Widen integral arithmetic as desired while preserving signedness. */
2963 tree_type_x = NULL_TREE;
2964 if (widenp && tree_type
2965 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
2966 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
2967 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
2968
2969 switch (ffebld_op (expr))
2970 {
2971 case FFEBLD_opACCTER:
2972 {
2973 ffebitCount i;
2974 ffebit bits = ffebld_accter_bits (expr);
2975 ffetargetOffset source_offset = 0;
2976 ffetargetOffset dest_offset = ffebld_accter_pad (expr);
2977 tree purpose;
2978
2979 assert (dest_offset == 0
2980 || (bt == FFEINFO_basictypeCHARACTER
2981 && kt == FFEINFO_kindtypeCHARACTER1));
2982
2983 list = item = NULL;
2984 for (;;)
2985 {
2986 ffebldConstantUnion cu;
2987 ffebitCount length;
2988 bool value;
2989 ffebldConstantArray ca = ffebld_accter (expr);
2990
2991 ffebit_test (bits, source_offset, &value, &length);
2992 if (length == 0)
2993 break;
2994
2995 if (value)
2996 {
2997 for (i = 0; i < length; ++i)
2998 {
2999 cu = ffebld_constantarray_get (ca, bt, kt,
3000 source_offset + i);
3001
3002 t = ffecom_constantunion (&cu, bt, kt, tree_type);
3003
3004 if (i == 0
3005 && dest_offset != 0)
3006 purpose = build_int_2 (dest_offset, 0);
3007 else
3008 purpose = NULL_TREE;
3009
3010 if (list == NULL_TREE)
3011 list = item = build_tree_list (purpose, t);
3012 else
3013 {
3014 TREE_CHAIN (item) = build_tree_list (purpose, t);
3015 item = TREE_CHAIN (item);
3016 }
3017 }
3018 }
3019 source_offset += length;
3020 dest_offset += length;
3021 }
3022 }
3023
3024 item = build_int_2 ((ffebld_accter_size (expr)
3025 + ffebld_accter_pad (expr)) - 1, 0);
3026 ffebit_kill (ffebld_accter_bits (expr));
3027 TREE_TYPE (item) = ffecom_integer_type_node;
3028 item
3029 = build_array_type
3030 (tree_type,
3031 build_range_type (ffecom_integer_type_node,
3032 ffecom_integer_zero_node,
3033 item));
3034 list = build (CONSTRUCTOR, item, NULL_TREE, list);
3035 TREE_CONSTANT (list) = 1;
3036 TREE_STATIC (list) = 1;
3037 return list;
3038
3039 case FFEBLD_opARRTER:
3040 {
3041 ffetargetOffset i;
3042
3043 list = NULL_TREE;
3044 if (ffebld_arrter_pad (expr) == 0)
3045 item = NULL_TREE;
3046 else
3047 {
3048 assert (bt == FFEINFO_basictypeCHARACTER
3049 && kt == FFEINFO_kindtypeCHARACTER1);
3050
3051 /* Becomes PURPOSE first time through loop. */
3052 item = build_int_2 (ffebld_arrter_pad (expr), 0);
3053 }
3054
3055 for (i = 0; i < ffebld_arrter_size (expr); ++i)
3056 {
3057 ffebldConstantUnion cu
3058 = ffebld_constantarray_get (ffebld_arrter (expr), bt, kt, i);
3059
3060 t = ffecom_constantunion (&cu, bt, kt, tree_type);
3061
3062 if (list == NULL_TREE)
3063 /* Assume item is PURPOSE first time through loop. */
3064 list = item = build_tree_list (item, t);
3065 else
3066 {
3067 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
3068 item = TREE_CHAIN (item);
3069 }
3070 }
3071 }
3072
3073 item = build_int_2 ((ffebld_arrter_size (expr)
3074 + ffebld_arrter_pad (expr)) - 1, 0);
3075 TREE_TYPE (item) = ffecom_integer_type_node;
3076 item
3077 = build_array_type
3078 (tree_type,
3079 build_range_type (ffecom_integer_type_node,
3080 ffecom_integer_zero_node,
3081 item));
3082 list = build (CONSTRUCTOR, item, NULL_TREE, list);
3083 TREE_CONSTANT (list) = 1;
3084 TREE_STATIC (list) = 1;
3085 return list;
3086
3087 case FFEBLD_opCONTER:
3088 assert (ffebld_conter_pad (expr) == 0);
3089 item
3090 = ffecom_constantunion (&ffebld_constant_union (ffebld_conter (expr)),
3091 bt, kt, tree_type);
3092 return item;
3093
3094 case FFEBLD_opSYMTER:
3095 if ((ffebld_symter_generic (expr) != FFEINTRIN_genNONE)
3096 || (ffebld_symter_specific (expr) != FFEINTRIN_specNONE))
3097 return ffecom_ptr_to_expr (expr); /* Same as %REF(intrinsic). */
3098 s = ffebld_symter (expr);
3099 t = ffesymbol_hook (s).decl_tree;
3100
3101 if (assignp)
3102 { /* ASSIGN'ed-label expr. */
3103 if (ffe_is_ugly_assign ())
3104 {
3105 /* User explicitly wants ASSIGN'ed variables to be at the same
3106 memory address as the variables when used in non-ASSIGN
3107 contexts. That can make old, arcane, non-standard code
3108 work, but don't try to do it when a pointer wouldn't fit
3109 in the normal variable (take other approach, and warn,
3110 instead). */
3111
3112 if (t == NULL_TREE)
3113 {
3114 s = ffecom_sym_transform_ (s);
3115 t = ffesymbol_hook (s).decl_tree;
3116 assert (t != NULL_TREE);
3117 }
3118
3119 if (t == error_mark_node)
3120 return t;
3121
3122 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (t)))
3123 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
3124 {
3125 if (ffesymbol_hook (s).addr)
3126 t = ffecom_1 (INDIRECT_REF,
3127 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3128 return t;
3129 }
3130
3131 if (ffesymbol_hook (s).assign_tree == NULL_TREE)
3132 {
3133 /* xgettext:no-c-format */
3134 ffebad_start_msg ("ASSIGN'ed label cannot fit into `%A' at %0 -- using wider sibling",
3135 FFEBAD_severityWARNING);
3136 ffebad_string (ffesymbol_text (s));
3137 ffebad_here (0, ffesymbol_where_line (s),
3138 ffesymbol_where_column (s));
3139 ffebad_finish ();
3140 }
3141 }
3142
3143 /* Don't use the normal variable's tree for ASSIGN, though mark
3144 it as in the system header (housekeeping). Use an explicit,
3145 specially created sibling that is known to be wide enough
3146 to hold pointers to labels. */
3147
3148 if (t != NULL_TREE
3149 && TREE_CODE (t) == VAR_DECL)
3150 DECL_IN_SYSTEM_HEADER (t) = 1; /* Don't let -Wunused complain. */
3151
3152 t = ffesymbol_hook (s).assign_tree;
3153 if (t == NULL_TREE)
3154 {
3155 s = ffecom_sym_transform_assign_ (s);
3156 t = ffesymbol_hook (s).assign_tree;
3157 assert (t != NULL_TREE);
3158 }
3159 }
3160 else
3161 {
3162 if (t == NULL_TREE)
3163 {
3164 s = ffecom_sym_transform_ (s);
3165 t = ffesymbol_hook (s).decl_tree;
3166 assert (t != NULL_TREE);
3167 }
3168 if (ffesymbol_hook (s).addr)
3169 t = ffecom_1 (INDIRECT_REF,
3170 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3171 }
3172 return t;
3173
3174 case FFEBLD_opARRAYREF:
3175 return ffecom_arrayref_ (NULL_TREE, expr, 0);
3176
3177 case FFEBLD_opUPLUS:
3178 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3179 return ffecom_1 (NOP_EXPR, tree_type, left);
3180
3181 case FFEBLD_opPAREN:
3182 /* ~~~Make sure Fortran rules respected here */
3183 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3184 return ffecom_1 (NOP_EXPR, tree_type, left);
3185
3186 case FFEBLD_opUMINUS:
3187 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3188 if (tree_type_x)
3189 {
3190 tree_type = tree_type_x;
3191 left = convert (tree_type, left);
3192 }
3193 return ffecom_1 (NEGATE_EXPR, tree_type, left);
3194
3195 case FFEBLD_opADD:
3196 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3197 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3198 if (tree_type_x)
3199 {
3200 tree_type = tree_type_x;
3201 left = convert (tree_type, left);
3202 right = convert (tree_type, right);
3203 }
3204 return ffecom_2 (PLUS_EXPR, tree_type, left, right);
3205
3206 case FFEBLD_opSUBTRACT:
3207 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3208 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3209 if (tree_type_x)
3210 {
3211 tree_type = tree_type_x;
3212 left = convert (tree_type, left);
3213 right = convert (tree_type, right);
3214 }
3215 return ffecom_2 (MINUS_EXPR, tree_type, left, right);
3216
3217 case FFEBLD_opMULTIPLY:
3218 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3219 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3220 if (tree_type_x)
3221 {
3222 tree_type = tree_type_x;
3223 left = convert (tree_type, left);
3224 right = convert (tree_type, right);
3225 }
3226 return ffecom_2 (MULT_EXPR, tree_type, left, right);
3227
3228 case FFEBLD_opDIVIDE:
3229 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3230 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3231 if (tree_type_x)
3232 {
3233 tree_type = tree_type_x;
3234 left = convert (tree_type, left);
3235 right = convert (tree_type, right);
3236 }
3237 return ffecom_tree_divide_ (tree_type, left, right,
3238 dest_tree, dest, dest_used,
3239 ffebld_nonter_hook (expr));
3240
3241 case FFEBLD_opPOWER:
3242 {
3243 ffebld left = ffebld_left (expr);
3244 ffebld right = ffebld_right (expr);
3245 ffecomGfrt code;
3246 ffeinfoKindtype rtkt;
3247 ffeinfoKindtype ltkt;
3248 bool ref = TRUE;
3249
3250 switch (ffeinfo_basictype (ffebld_info (right)))
3251 {
3252
3253 case FFEINFO_basictypeINTEGER:
3254 if (1 || optimize)
3255 {
3256 item = ffecom_expr_power_integer_ (expr);
3257 if (item != NULL_TREE)
3258 return item;
3259 }
3260
3261 rtkt = FFEINFO_kindtypeINTEGER1;
3262 switch (ffeinfo_basictype (ffebld_info (left)))
3263 {
3264 case FFEINFO_basictypeINTEGER:
3265 if ((ffeinfo_kindtype (ffebld_info (left))
3266 == FFEINFO_kindtypeINTEGER4)
3267 || (ffeinfo_kindtype (ffebld_info (right))
3268 == FFEINFO_kindtypeINTEGER4))
3269 {
3270 code = FFECOM_gfrtPOW_QQ;
3271 ltkt = FFEINFO_kindtypeINTEGER4;
3272 rtkt = FFEINFO_kindtypeINTEGER4;
3273 }
3274 else
3275 {
3276 code = FFECOM_gfrtPOW_II;
3277 ltkt = FFEINFO_kindtypeINTEGER1;
3278 }
3279 break;
3280
3281 case FFEINFO_basictypeREAL:
3282 if (ffeinfo_kindtype (ffebld_info (left))
3283 == FFEINFO_kindtypeREAL1)
3284 {
3285 code = FFECOM_gfrtPOW_RI;
3286 ltkt = FFEINFO_kindtypeREAL1;
3287 }
3288 else
3289 {
3290 code = FFECOM_gfrtPOW_DI;
3291 ltkt = FFEINFO_kindtypeREAL2;
3292 }
3293 break;
3294
3295 case FFEINFO_basictypeCOMPLEX:
3296 if (ffeinfo_kindtype (ffebld_info (left))
3297 == FFEINFO_kindtypeREAL1)
3298 {
3299 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
3300 ltkt = FFEINFO_kindtypeREAL1;
3301 }
3302 else
3303 {
3304 code = FFECOM_gfrtPOW_ZI; /* Overlapping result okay. */
3305 ltkt = FFEINFO_kindtypeREAL2;
3306 }
3307 break;
3308
3309 default:
3310 assert ("bad pow_*i" == NULL);
3311 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
3312 ltkt = FFEINFO_kindtypeREAL1;
3313 break;
3314 }
3315 if (ffeinfo_kindtype (ffebld_info (left)) != ltkt)
3316 left = ffeexpr_convert (left, NULL, NULL,
3317 ffeinfo_basictype (ffebld_info (left)),
3318 ltkt, 0,
3319 FFETARGET_charactersizeNONE,
3320 FFEEXPR_contextLET);
3321 if (ffeinfo_kindtype (ffebld_info (right)) != rtkt)
3322 right = ffeexpr_convert (right, NULL, NULL,
3323 FFEINFO_basictypeINTEGER,
3324 rtkt, 0,
3325 FFETARGET_charactersizeNONE,
3326 FFEEXPR_contextLET);
3327 break;
3328
3329 case FFEINFO_basictypeREAL:
3330 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3331 left = ffeexpr_convert (left, NULL, NULL, FFEINFO_basictypeREAL,
3332 FFEINFO_kindtypeREALDOUBLE, 0,
3333 FFETARGET_charactersizeNONE,
3334 FFEEXPR_contextLET);
3335 if (ffeinfo_kindtype (ffebld_info (right))
3336 == FFEINFO_kindtypeREAL1)
3337 right = ffeexpr_convert (right, NULL, NULL,
3338 FFEINFO_basictypeREAL,
3339 FFEINFO_kindtypeREALDOUBLE, 0,
3340 FFETARGET_charactersizeNONE,
3341 FFEEXPR_contextLET);
3342 /* We used to call FFECOM_gfrtPOW_DD here,
3343 which passes arguments by reference. */
3344 code = FFECOM_gfrtL_POW;
3345 /* Pass arguments by value. */
3346 ref = FALSE;
3347 break;
3348
3349 case FFEINFO_basictypeCOMPLEX:
3350 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3351 left = ffeexpr_convert (left, NULL, NULL,
3352 FFEINFO_basictypeCOMPLEX,
3353 FFEINFO_kindtypeREALDOUBLE, 0,
3354 FFETARGET_charactersizeNONE,
3355 FFEEXPR_contextLET);
3356 if (ffeinfo_kindtype (ffebld_info (right))
3357 == FFEINFO_kindtypeREAL1)
3358 right = ffeexpr_convert (right, NULL, NULL,
3359 FFEINFO_basictypeCOMPLEX,
3360 FFEINFO_kindtypeREALDOUBLE, 0,
3361 FFETARGET_charactersizeNONE,
3362 FFEEXPR_contextLET);
3363 code = FFECOM_gfrtPOW_ZZ; /* Overlapping result okay. */
3364 ref = TRUE; /* Pass arguments by reference. */
3365 break;
3366
3367 default:
3368 assert ("bad pow_x*" == NULL);
3369 code = FFECOM_gfrtPOW_II;
3370 break;
3371 }
3372 return ffecom_call_binop_ (ffecom_gfrt_tree_ (code),
3373 ffecom_gfrt_kindtype (code),
3374 (ffe_is_f2c_library ()
3375 && ffecom_gfrt_complex_[code]),
3376 tree_type, left, right,
3377 dest_tree, dest, dest_used,
3378 NULL_TREE, FALSE, ref,
3379 ffebld_nonter_hook (expr));
3380 }
3381
3382 case FFEBLD_opNOT:
3383 switch (bt)
3384 {
3385 case FFEINFO_basictypeLOGICAL:
3386 item = ffecom_truth_value_invert (ffecom_expr (ffebld_left (expr)));
3387 return convert (tree_type, item);
3388
3389 case FFEINFO_basictypeINTEGER:
3390 return ffecom_1 (BIT_NOT_EXPR, tree_type,
3391 ffecom_expr (ffebld_left (expr)));
3392
3393 default:
3394 assert ("NOT bad basictype" == NULL);
3395 /* Fall through. */
3396 case FFEINFO_basictypeANY:
3397 return error_mark_node;
3398 }
3399 break;
3400
3401 case FFEBLD_opFUNCREF:
3402 assert (ffeinfo_basictype (ffebld_info (expr))
3403 != FFEINFO_basictypeCHARACTER);
3404 /* Fall through. */
3405 case FFEBLD_opSUBRREF:
3406 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
3407 == FFEINFO_whereINTRINSIC)
3408 { /* Invocation of an intrinsic. */
3409 item = ffecom_expr_intrinsic_ (expr, dest_tree, dest,
3410 dest_used);
3411 return item;
3412 }
3413 s = ffebld_symter (ffebld_left (expr));
3414 dt = ffesymbol_hook (s).decl_tree;
3415 if (dt == NULL_TREE)
3416 {
3417 s = ffecom_sym_transform_ (s);
3418 dt = ffesymbol_hook (s).decl_tree;
3419 }
3420 if (dt == error_mark_node)
3421 return dt;
3422
3423 if (ffesymbol_hook (s).addr)
3424 item = dt;
3425 else
3426 item = ffecom_1_fn (dt);
3427
3428 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
3429 args = ffecom_list_expr (ffebld_right (expr));
3430 else
3431 args = ffecom_list_ptr_to_expr (ffebld_right (expr));
3432
3433 if (args == error_mark_node)
3434 return error_mark_node;
3435
3436 item = ffecom_call_ (item, kt,
3437 ffesymbol_is_f2c (s)
3438 && (bt == FFEINFO_basictypeCOMPLEX)
3439 && (ffesymbol_where (s)
3440 != FFEINFO_whereCONSTANT),
3441 tree_type,
3442 args,
3443 dest_tree, dest, dest_used,
3444 error_mark_node, FALSE,
3445 ffebld_nonter_hook (expr));
3446 TREE_SIDE_EFFECTS (item) = 1;
3447 return item;
3448
3449 case FFEBLD_opAND:
3450 switch (bt)
3451 {
3452 case FFEINFO_basictypeLOGICAL:
3453 item
3454 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3455 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3456 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3457 return convert (tree_type, item);
3458
3459 case FFEINFO_basictypeINTEGER:
3460 return ffecom_2 (BIT_AND_EXPR, tree_type,
3461 ffecom_expr (ffebld_left (expr)),
3462 ffecom_expr (ffebld_right (expr)));
3463
3464 default:
3465 assert ("AND bad basictype" == NULL);
3466 /* Fall through. */
3467 case FFEINFO_basictypeANY:
3468 return error_mark_node;
3469 }
3470 break;
3471
3472 case FFEBLD_opOR:
3473 switch (bt)
3474 {
3475 case FFEINFO_basictypeLOGICAL:
3476 item
3477 = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
3478 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3479 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3480 return convert (tree_type, item);
3481
3482 case FFEINFO_basictypeINTEGER:
3483 return ffecom_2 (BIT_IOR_EXPR, tree_type,
3484 ffecom_expr (ffebld_left (expr)),
3485 ffecom_expr (ffebld_right (expr)));
3486
3487 default:
3488 assert ("OR bad basictype" == NULL);
3489 /* Fall through. */
3490 case FFEINFO_basictypeANY:
3491 return error_mark_node;
3492 }
3493 break;
3494
3495 case FFEBLD_opXOR:
3496 case FFEBLD_opNEQV:
3497 switch (bt)
3498 {
3499 case FFEINFO_basictypeLOGICAL:
3500 item
3501 = ffecom_2 (NE_EXPR, integer_type_node,
3502 ffecom_expr (ffebld_left (expr)),
3503 ffecom_expr (ffebld_right (expr)));
3504 return convert (tree_type, ffecom_truth_value (item));
3505
3506 case FFEINFO_basictypeINTEGER:
3507 return ffecom_2 (BIT_XOR_EXPR, tree_type,
3508 ffecom_expr (ffebld_left (expr)),
3509 ffecom_expr (ffebld_right (expr)));
3510
3511 default:
3512 assert ("XOR/NEQV bad basictype" == NULL);
3513 /* Fall through. */
3514 case FFEINFO_basictypeANY:
3515 return error_mark_node;
3516 }
3517 break;
3518
3519 case FFEBLD_opEQV:
3520 switch (bt)
3521 {
3522 case FFEINFO_basictypeLOGICAL:
3523 item
3524 = ffecom_2 (EQ_EXPR, integer_type_node,
3525 ffecom_expr (ffebld_left (expr)),
3526 ffecom_expr (ffebld_right (expr)));
3527 return convert (tree_type, ffecom_truth_value (item));
3528
3529 case FFEINFO_basictypeINTEGER:
3530 return
3531 ffecom_1 (BIT_NOT_EXPR, tree_type,
3532 ffecom_2 (BIT_XOR_EXPR, tree_type,
3533 ffecom_expr (ffebld_left (expr)),
3534 ffecom_expr (ffebld_right (expr))));
3535
3536 default:
3537 assert ("EQV bad basictype" == NULL);
3538 /* Fall through. */
3539 case FFEINFO_basictypeANY:
3540 return error_mark_node;
3541 }
3542 break;
3543
3544 case FFEBLD_opCONVERT:
3545 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opANY)
3546 return error_mark_node;
3547
3548 switch (bt)
3549 {
3550 case FFEINFO_basictypeLOGICAL:
3551 case FFEINFO_basictypeINTEGER:
3552 case FFEINFO_basictypeREAL:
3553 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3554
3555 case FFEINFO_basictypeCOMPLEX:
3556 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3557 {
3558 case FFEINFO_basictypeINTEGER:
3559 case FFEINFO_basictypeLOGICAL:
3560 case FFEINFO_basictypeREAL:
3561 item = ffecom_expr (ffebld_left (expr));
3562 if (item == error_mark_node)
3563 return error_mark_node;
3564 /* convert() takes care of converting to the subtype first,
3565 at least in gcc-2.7.2. */
3566 item = convert (tree_type, item);
3567 return item;
3568
3569 case FFEINFO_basictypeCOMPLEX:
3570 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3571
3572 default:
3573 assert ("CONVERT COMPLEX bad basictype" == NULL);
3574 /* Fall through. */
3575 case FFEINFO_basictypeANY:
3576 return error_mark_node;
3577 }
3578 break;
3579
3580 default:
3581 assert ("CONVERT bad basictype" == NULL);
3582 /* Fall through. */
3583 case FFEINFO_basictypeANY:
3584 return error_mark_node;
3585 }
3586 break;
3587
3588 case FFEBLD_opLT:
3589 code = LT_EXPR;
3590 goto relational; /* :::::::::::::::::::: */
3591
3592 case FFEBLD_opLE:
3593 code = LE_EXPR;
3594 goto relational; /* :::::::::::::::::::: */
3595
3596 case FFEBLD_opEQ:
3597 code = EQ_EXPR;
3598 goto relational; /* :::::::::::::::::::: */
3599
3600 case FFEBLD_opNE:
3601 code = NE_EXPR;
3602 goto relational; /* :::::::::::::::::::: */
3603
3604 case FFEBLD_opGT:
3605 code = GT_EXPR;
3606 goto relational; /* :::::::::::::::::::: */
3607
3608 case FFEBLD_opGE:
3609 code = GE_EXPR;
3610
3611 relational: /* :::::::::::::::::::: */
3612 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3613 {
3614 case FFEINFO_basictypeLOGICAL:
3615 case FFEINFO_basictypeINTEGER:
3616 case FFEINFO_basictypeREAL:
3617 item = ffecom_2 (code, integer_type_node,
3618 ffecom_expr (ffebld_left (expr)),
3619 ffecom_expr (ffebld_right (expr)));
3620 return convert (tree_type, item);
3621
3622 case FFEINFO_basictypeCOMPLEX:
3623 assert (code == EQ_EXPR || code == NE_EXPR);
3624 {
3625 tree real_type;
3626 tree arg1 = ffecom_expr (ffebld_left (expr));
3627 tree arg2 = ffecom_expr (ffebld_right (expr));
3628
3629 if (arg1 == error_mark_node || arg2 == error_mark_node)
3630 return error_mark_node;
3631
3632 arg1 = ffecom_save_tree (arg1);
3633 arg2 = ffecom_save_tree (arg2);
3634
3635 if (TREE_CODE (TREE_TYPE (arg1)) == COMPLEX_TYPE)
3636 {
3637 real_type = TREE_TYPE (TREE_TYPE (arg1));
3638 assert (real_type == TREE_TYPE (TREE_TYPE (arg2)));
3639 }
3640 else
3641 {
3642 real_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg1)));
3643 assert (real_type == TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg2))));
3644 }
3645
3646 item
3647 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3648 ffecom_2 (EQ_EXPR, integer_type_node,
3649 ffecom_1 (REALPART_EXPR, real_type, arg1),
3650 ffecom_1 (REALPART_EXPR, real_type, arg2)),
3651 ffecom_2 (EQ_EXPR, integer_type_node,
3652 ffecom_1 (IMAGPART_EXPR, real_type, arg1),
3653 ffecom_1 (IMAGPART_EXPR, real_type,
3654 arg2)));
3655 if (code == EQ_EXPR)
3656 item = ffecom_truth_value (item);
3657 else
3658 item = ffecom_truth_value_invert (item);
3659 return convert (tree_type, item);
3660 }
3661
3662 case FFEINFO_basictypeCHARACTER:
3663 {
3664 ffebld left = ffebld_left (expr);
3665 ffebld right = ffebld_right (expr);
3666 tree left_tree;
3667 tree right_tree;
3668 tree left_length;
3669 tree right_length;
3670
3671 /* f2c run-time functions do the implicit blank-padding for us,
3672 so we don't usually have to implement blank-padding ourselves.
3673 (The exception is when we pass an argument to a separately
3674 compiled statement function -- if we know the arg is not the
3675 same length as the dummy, we must truncate or extend it. If
3676 we "inline" statement functions, that necessity goes away as
3677 well.)
3678
3679 Strip off the CONVERT operators that blank-pad. (Truncation by
3680 CONVERT shouldn't happen here, but it can happen in
3681 assignments.) */
3682
3683 while (ffebld_op (left) == FFEBLD_opCONVERT)
3684 left = ffebld_left (left);
3685 while (ffebld_op (right) == FFEBLD_opCONVERT)
3686 right = ffebld_left (right);
3687
3688 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
3689 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
3690
3691 if (left_tree == error_mark_node || left_length == error_mark_node
3692 || right_tree == error_mark_node
3693 || right_length == error_mark_node)
3694 return error_mark_node;
3695
3696 if ((ffebld_size_known (left) == 1)
3697 && (ffebld_size_known (right) == 1))
3698 {
3699 left_tree
3700 = ffecom_1 (INDIRECT_REF,
3701 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3702 left_tree);
3703 right_tree
3704 = ffecom_1 (INDIRECT_REF,
3705 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3706 right_tree);
3707
3708 item
3709 = ffecom_2 (code, integer_type_node,
3710 ffecom_2 (ARRAY_REF,
3711 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3712 left_tree,
3713 integer_one_node),
3714 ffecom_2 (ARRAY_REF,
3715 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3716 right_tree,
3717 integer_one_node));
3718 }
3719 else
3720 {
3721 item = build_tree_list (NULL_TREE, left_tree);
3722 TREE_CHAIN (item) = build_tree_list (NULL_TREE, right_tree);
3723 TREE_CHAIN (TREE_CHAIN (item)) = build_tree_list (NULL_TREE,
3724 left_length);
3725 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
3726 = build_tree_list (NULL_TREE, right_length);
3727 item = ffecom_call_gfrt (FFECOM_gfrtCMP, item, NULL_TREE);
3728 item = ffecom_2 (code, integer_type_node,
3729 item,
3730 convert (TREE_TYPE (item),
3731 integer_zero_node));
3732 }
3733 item = convert (tree_type, item);
3734 }
3735
3736 return item;
3737
3738 default:
3739 assert ("relational bad basictype" == NULL);
3740 /* Fall through. */
3741 case FFEINFO_basictypeANY:
3742 return error_mark_node;
3743 }
3744 break;
3745
3746 case FFEBLD_opPERCENT_LOC:
3747 item = ffecom_arg_ptr_to_expr (ffebld_left (expr), &list);
3748 return convert (tree_type, item);
3749
3750 case FFEBLD_opPERCENT_VAL:
3751 item = ffecom_arg_expr (ffebld_left (expr), &list);
3752 return convert (tree_type, item);
3753
3754 case FFEBLD_opITEM:
3755 case FFEBLD_opSTAR:
3756 case FFEBLD_opBOUNDS:
3757 case FFEBLD_opREPEAT:
3758 case FFEBLD_opLABTER:
3759 case FFEBLD_opLABTOK:
3760 case FFEBLD_opIMPDO:
3761 case FFEBLD_opCONCATENATE:
3762 case FFEBLD_opSUBSTR:
3763 default:
3764 assert ("bad op" == NULL);
3765 /* Fall through. */
3766 case FFEBLD_opANY:
3767 return error_mark_node;
3768 }
3769
3770 #if 1
3771 assert ("didn't think anything got here anymore!!" == NULL);
3772 #else
3773 switch (ffebld_arity (expr))
3774 {
3775 case 2:
3776 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3777 TREE_OPERAND (item, 1) = ffecom_expr (ffebld_right (expr));
3778 if (TREE_OPERAND (item, 0) == error_mark_node
3779 || TREE_OPERAND (item, 1) == error_mark_node)
3780 return error_mark_node;
3781 break;
3782
3783 case 1:
3784 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3785 if (TREE_OPERAND (item, 0) == error_mark_node)
3786 return error_mark_node;
3787 break;
3788
3789 default:
3790 break;
3791 }
3792
3793 return fold (item);
3794 #endif
3795 }
3796
3797 /* Returns the tree that does the intrinsic invocation.
3798
3799 Note: this function applies only to intrinsics returning
3800 CHARACTER*1 or non-CHARACTER results, and to intrinsic
3801 subroutines. */
3802
3803 static tree
ffecom_expr_intrinsic_(ffebld expr,tree dest_tree,ffebld dest,bool * dest_used)3804 ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
3805 ffebld dest, bool *dest_used)
3806 {
3807 tree expr_tree;
3808 tree saved_expr1; /* For those who need it. */
3809 tree saved_expr2; /* For those who need it. */
3810 ffeinfoBasictype bt;
3811 ffeinfoKindtype kt;
3812 tree tree_type;
3813 tree arg1_type;
3814 tree real_type; /* REAL type corresponding to COMPLEX. */
3815 tree tempvar;
3816 ffebld list = ffebld_right (expr); /* List of (some) args. */
3817 ffebld arg1; /* For handy reference. */
3818 ffebld arg2;
3819 ffebld arg3;
3820 ffeintrinImp codegen_imp;
3821 ffecomGfrt gfrt;
3822
3823 assert (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER);
3824
3825 if (dest_used != NULL)
3826 *dest_used = FALSE;
3827
3828 bt = ffeinfo_basictype (ffebld_info (expr));
3829 kt = ffeinfo_kindtype (ffebld_info (expr));
3830 tree_type = ffecom_tree_type[bt][kt];
3831
3832 if (list != NULL)
3833 {
3834 arg1 = ffebld_head (list);
3835 if (arg1 != NULL && ffebld_op (arg1) == FFEBLD_opANY)
3836 return error_mark_node;
3837 if ((list = ffebld_trail (list)) != NULL)
3838 {
3839 arg2 = ffebld_head (list);
3840 if (arg2 != NULL && ffebld_op (arg2) == FFEBLD_opANY)
3841 return error_mark_node;
3842 if ((list = ffebld_trail (list)) != NULL)
3843 {
3844 arg3 = ffebld_head (list);
3845 if (arg3 != NULL && ffebld_op (arg3) == FFEBLD_opANY)
3846 return error_mark_node;
3847 }
3848 else
3849 arg3 = NULL;
3850 }
3851 else
3852 arg2 = arg3 = NULL;
3853 }
3854 else
3855 arg1 = arg2 = arg3 = NULL;
3856
3857 /* <list> ends up at the opITEM of the 3rd arg, or NULL if there are < 3
3858 args. This is used by the MAX/MIN expansions. */
3859
3860 if (arg1 != NULL)
3861 arg1_type = ffecom_tree_type
3862 [ffeinfo_basictype (ffebld_info (arg1))]
3863 [ffeinfo_kindtype (ffebld_info (arg1))];
3864 else
3865 arg1_type = NULL_TREE; /* Really not needed, but might catch bugs
3866 here. */
3867
3868 /* There are several ways for each of the cases in the following switch
3869 statements to exit (from simplest to use to most complicated):
3870
3871 break; (when expr_tree == NULL)
3872
3873 A standard call is made to the specific intrinsic just as if it had been
3874 passed in as a dummy procedure and called as any old procedure. This
3875 method can produce slower code but in some cases it's the easiest way for
3876 now. However, if a (presumably faster) direct call is available,
3877 that is used, so this is the easiest way in many more cases now.
3878
3879 gfrt = FFECOM_gfrtWHATEVER;
3880 break;
3881
3882 gfrt contains the gfrt index of a library function to call, passing the
3883 argument(s) by value rather than by reference. Used when a more
3884 careful choice of library function is needed than that provided
3885 by the vanilla `break;'.
3886
3887 return expr_tree;
3888
3889 The expr_tree has been completely set up and is ready to be returned
3890 as is. No further actions are taken. Use this when the tree is not
3891 in the simple form for one of the arity_n labels. */
3892
3893 /* For info on how the switch statement cases were written, see the files
3894 enclosed in comments below the switch statement. */
3895
3896 codegen_imp = ffebld_symter_implementation (ffebld_left (expr));
3897 gfrt = ffeintrin_gfrt_direct (codegen_imp);
3898 if (gfrt == FFECOM_gfrt)
3899 gfrt = ffeintrin_gfrt_indirect (codegen_imp);
3900
3901 switch (codegen_imp)
3902 {
3903 case FFEINTRIN_impABS:
3904 case FFEINTRIN_impCABS:
3905 case FFEINTRIN_impCDABS:
3906 case FFEINTRIN_impDABS:
3907 case FFEINTRIN_impIABS:
3908 if (ffeinfo_basictype (ffebld_info (arg1))
3909 == FFEINFO_basictypeCOMPLEX)
3910 {
3911 if (kt == FFEINFO_kindtypeREAL1)
3912 gfrt = FFECOM_gfrtCABS;
3913 else if (kt == FFEINFO_kindtypeREAL2)
3914 gfrt = FFECOM_gfrtCDABS;
3915 break;
3916 }
3917 return ffecom_1 (ABS_EXPR, tree_type,
3918 convert (tree_type, ffecom_expr (arg1)));
3919
3920 case FFEINTRIN_impACOS:
3921 case FFEINTRIN_impDACOS:
3922 break;
3923
3924 case FFEINTRIN_impAIMAG:
3925 case FFEINTRIN_impDIMAG:
3926 case FFEINTRIN_impIMAGPART:
3927 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
3928 arg1_type = TREE_TYPE (arg1_type);
3929 else
3930 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
3931
3932 return
3933 convert (tree_type,
3934 ffecom_1 (IMAGPART_EXPR, arg1_type,
3935 ffecom_expr (arg1)));
3936
3937 case FFEINTRIN_impAINT:
3938 case FFEINTRIN_impDINT:
3939 #if 0
3940 /* ~~Someday implement FIX_TRUNC_EXPR yielding same type as arg. */
3941 return ffecom_1 (FIX_TRUNC_EXPR, tree_type, ffecom_expr (arg1));
3942 #else /* in the meantime, must use floor to avoid range problems with ints */
3943 /* r__1 = r1 >= 0 ? floor(r1) : -floor(-r1); */
3944 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
3945 return
3946 convert (tree_type,
3947 ffecom_3 (COND_EXPR, double_type_node,
3948 ffecom_truth_value
3949 (ffecom_2 (GE_EXPR, integer_type_node,
3950 saved_expr1,
3951 convert (arg1_type,
3952 ffecom_float_zero_))),
3953 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
3954 build_tree_list (NULL_TREE,
3955 convert (double_type_node,
3956 saved_expr1)),
3957 NULL_TREE),
3958 ffecom_1 (NEGATE_EXPR, double_type_node,
3959 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
3960 build_tree_list (NULL_TREE,
3961 convert (double_type_node,
3962 ffecom_1 (NEGATE_EXPR,
3963 arg1_type,
3964 saved_expr1))),
3965 NULL_TREE)
3966 ))
3967 );
3968 #endif
3969
3970 case FFEINTRIN_impANINT:
3971 case FFEINTRIN_impDNINT:
3972 #if 0 /* This way of doing it won't handle real
3973 numbers of large magnitudes. */
3974 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
3975 expr_tree = convert (tree_type,
3976 convert (integer_type_node,
3977 ffecom_3 (COND_EXPR, tree_type,
3978 ffecom_truth_value
3979 (ffecom_2 (GE_EXPR,
3980 integer_type_node,
3981 saved_expr1,
3982 ffecom_float_zero_)),
3983 ffecom_2 (PLUS_EXPR,
3984 tree_type,
3985 saved_expr1,
3986 ffecom_float_half_),
3987 ffecom_2 (MINUS_EXPR,
3988 tree_type,
3989 saved_expr1,
3990 ffecom_float_half_))));
3991 return expr_tree;
3992 #else /* So we instead call floor. */
3993 /* r__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1) */
3994 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
3995 return
3996 convert (tree_type,
3997 ffecom_3 (COND_EXPR, double_type_node,
3998 ffecom_truth_value
3999 (ffecom_2 (GE_EXPR, integer_type_node,
4000 saved_expr1,
4001 convert (arg1_type,
4002 ffecom_float_zero_))),
4003 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4004 build_tree_list (NULL_TREE,
4005 convert (double_type_node,
4006 ffecom_2 (PLUS_EXPR,
4007 arg1_type,
4008 saved_expr1,
4009 convert (arg1_type,
4010 ffecom_float_half_)))),
4011 NULL_TREE),
4012 ffecom_1 (NEGATE_EXPR, double_type_node,
4013 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4014 build_tree_list (NULL_TREE,
4015 convert (double_type_node,
4016 ffecom_2 (MINUS_EXPR,
4017 arg1_type,
4018 convert (arg1_type,
4019 ffecom_float_half_),
4020 saved_expr1))),
4021 NULL_TREE))
4022 )
4023 );
4024 #endif
4025
4026 case FFEINTRIN_impASIN:
4027 case FFEINTRIN_impDASIN:
4028 case FFEINTRIN_impATAN:
4029 case FFEINTRIN_impDATAN:
4030 case FFEINTRIN_impATAN2:
4031 case FFEINTRIN_impDATAN2:
4032 break;
4033
4034 case FFEINTRIN_impCHAR:
4035 case FFEINTRIN_impACHAR:
4036 tempvar = ffebld_nonter_hook (expr);
4037 assert (tempvar);
4038 {
4039 tree tmv = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (tempvar)));
4040
4041 expr_tree = ffecom_modify (tmv,
4042 ffecom_2 (ARRAY_REF, tmv, tempvar,
4043 integer_one_node),
4044 convert (tmv, ffecom_expr (arg1)));
4045 }
4046 expr_tree = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar),
4047 expr_tree,
4048 tempvar);
4049 expr_tree = ffecom_1 (ADDR_EXPR,
4050 build_pointer_type (TREE_TYPE (expr_tree)),
4051 expr_tree);
4052 return expr_tree;
4053
4054 case FFEINTRIN_impCMPLX:
4055 case FFEINTRIN_impDCMPLX:
4056 if (arg2 == NULL)
4057 return
4058 convert (tree_type, ffecom_expr (arg1));
4059
4060 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4061 return
4062 ffecom_2 (COMPLEX_EXPR, tree_type,
4063 convert (real_type, ffecom_expr (arg1)),
4064 convert (real_type,
4065 ffecom_expr (arg2)));
4066
4067 case FFEINTRIN_impCOMPLEX:
4068 return
4069 ffecom_2 (COMPLEX_EXPR, tree_type,
4070 ffecom_expr (arg1),
4071 ffecom_expr (arg2));
4072
4073 case FFEINTRIN_impCONJG:
4074 case FFEINTRIN_impDCONJG:
4075 {
4076 tree arg1_tree;
4077
4078 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4079 arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4080 return
4081 ffecom_2 (COMPLEX_EXPR, tree_type,
4082 ffecom_1 (REALPART_EXPR, real_type, arg1_tree),
4083 ffecom_1 (NEGATE_EXPR, real_type,
4084 ffecom_1 (IMAGPART_EXPR, real_type, arg1_tree)));
4085 }
4086
4087 case FFEINTRIN_impCOS:
4088 case FFEINTRIN_impCCOS:
4089 case FFEINTRIN_impCDCOS:
4090 case FFEINTRIN_impDCOS:
4091 if (bt == FFEINFO_basictypeCOMPLEX)
4092 {
4093 if (kt == FFEINFO_kindtypeREAL1)
4094 gfrt = FFECOM_gfrtCCOS; /* Overlapping result okay. */
4095 else if (kt == FFEINFO_kindtypeREAL2)
4096 gfrt = FFECOM_gfrtCDCOS; /* Overlapping result okay. */
4097 }
4098 break;
4099
4100 case FFEINTRIN_impCOSH:
4101 case FFEINTRIN_impDCOSH:
4102 break;
4103
4104 case FFEINTRIN_impDBLE:
4105 case FFEINTRIN_impDFLOAT:
4106 case FFEINTRIN_impDREAL:
4107 case FFEINTRIN_impFLOAT:
4108 case FFEINTRIN_impIDINT:
4109 case FFEINTRIN_impIFIX:
4110 case FFEINTRIN_impINT2:
4111 case FFEINTRIN_impINT8:
4112 case FFEINTRIN_impINT:
4113 case FFEINTRIN_impLONG:
4114 case FFEINTRIN_impREAL:
4115 case FFEINTRIN_impSHORT:
4116 case FFEINTRIN_impSNGL:
4117 return convert (tree_type, ffecom_expr (arg1));
4118
4119 case FFEINTRIN_impDIM:
4120 case FFEINTRIN_impDDIM:
4121 case FFEINTRIN_impIDIM:
4122 saved_expr1 = ffecom_save_tree (convert (tree_type,
4123 ffecom_expr (arg1)));
4124 saved_expr2 = ffecom_save_tree (convert (tree_type,
4125 ffecom_expr (arg2)));
4126 return
4127 ffecom_3 (COND_EXPR, tree_type,
4128 ffecom_truth_value
4129 (ffecom_2 (GT_EXPR, integer_type_node,
4130 saved_expr1,
4131 saved_expr2)),
4132 ffecom_2 (MINUS_EXPR, tree_type,
4133 saved_expr1,
4134 saved_expr2),
4135 convert (tree_type, ffecom_float_zero_));
4136
4137 case FFEINTRIN_impDPROD:
4138 return
4139 ffecom_2 (MULT_EXPR, tree_type,
4140 convert (tree_type, ffecom_expr (arg1)),
4141 convert (tree_type, ffecom_expr (arg2)));
4142
4143 case FFEINTRIN_impEXP:
4144 case FFEINTRIN_impCDEXP:
4145 case FFEINTRIN_impCEXP:
4146 case FFEINTRIN_impDEXP:
4147 if (bt == FFEINFO_basictypeCOMPLEX)
4148 {
4149 if (kt == FFEINFO_kindtypeREAL1)
4150 gfrt = FFECOM_gfrtCEXP; /* Overlapping result okay. */
4151 else if (kt == FFEINFO_kindtypeREAL2)
4152 gfrt = FFECOM_gfrtCDEXP; /* Overlapping result okay. */
4153 }
4154 break;
4155
4156 case FFEINTRIN_impICHAR:
4157 case FFEINTRIN_impIACHAR:
4158 #if 0 /* The simple approach. */
4159 ffecom_char_args_ (&expr_tree, &saved_expr1 /* Ignored */ , arg1);
4160 expr_tree
4161 = ffecom_1 (INDIRECT_REF,
4162 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4163 expr_tree);
4164 expr_tree
4165 = ffecom_2 (ARRAY_REF,
4166 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4167 expr_tree,
4168 integer_one_node);
4169 return convert (tree_type, expr_tree);
4170 #else /* The more interesting (and more optimal) approach. */
4171 expr_tree = ffecom_intrinsic_ichar_ (tree_type, arg1, &saved_expr1);
4172 expr_tree = ffecom_3 (COND_EXPR, tree_type,
4173 saved_expr1,
4174 expr_tree,
4175 convert (tree_type, integer_zero_node));
4176 return expr_tree;
4177 #endif
4178
4179 case FFEINTRIN_impINDEX:
4180 break;
4181
4182 case FFEINTRIN_impLEN:
4183 #if 0
4184 break; /* The simple approach. */
4185 #else
4186 return ffecom_intrinsic_len_ (arg1); /* The more optimal approach. */
4187 #endif
4188
4189 case FFEINTRIN_impLGE:
4190 case FFEINTRIN_impLGT:
4191 case FFEINTRIN_impLLE:
4192 case FFEINTRIN_impLLT:
4193 break;
4194
4195 case FFEINTRIN_impLOG:
4196 case FFEINTRIN_impALOG:
4197 case FFEINTRIN_impCDLOG:
4198 case FFEINTRIN_impCLOG:
4199 case FFEINTRIN_impDLOG:
4200 if (bt == FFEINFO_basictypeCOMPLEX)
4201 {
4202 if (kt == FFEINFO_kindtypeREAL1)
4203 gfrt = FFECOM_gfrtCLOG; /* Overlapping result okay. */
4204 else if (kt == FFEINFO_kindtypeREAL2)
4205 gfrt = FFECOM_gfrtCDLOG; /* Overlapping result okay. */
4206 }
4207 break;
4208
4209 case FFEINTRIN_impLOG10:
4210 case FFEINTRIN_impALOG10:
4211 case FFEINTRIN_impDLOG10:
4212 if (gfrt != FFECOM_gfrt)
4213 break; /* Already picked one, stick with it. */
4214
4215 if (kt == FFEINFO_kindtypeREAL1)
4216 /* We used to call FFECOM_gfrtALOG10 here. */
4217 gfrt = FFECOM_gfrtL_LOG10;
4218 else if (kt == FFEINFO_kindtypeREAL2)
4219 /* We used to call FFECOM_gfrtDLOG10 here. */
4220 gfrt = FFECOM_gfrtL_LOG10;
4221 break;
4222
4223 case FFEINTRIN_impMAX:
4224 case FFEINTRIN_impAMAX0:
4225 case FFEINTRIN_impAMAX1:
4226 case FFEINTRIN_impDMAX1:
4227 case FFEINTRIN_impMAX0:
4228 case FFEINTRIN_impMAX1:
4229 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4230 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4231 else
4232 arg1_type = tree_type;
4233 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4234 convert (arg1_type, ffecom_expr (arg1)),
4235 convert (arg1_type, ffecom_expr (arg2)));
4236 for (; list != NULL; list = ffebld_trail (list))
4237 {
4238 if ((ffebld_head (list) == NULL)
4239 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4240 continue;
4241 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4242 expr_tree,
4243 convert (arg1_type,
4244 ffecom_expr (ffebld_head (list))));
4245 }
4246 return convert (tree_type, expr_tree);
4247
4248 case FFEINTRIN_impMIN:
4249 case FFEINTRIN_impAMIN0:
4250 case FFEINTRIN_impAMIN1:
4251 case FFEINTRIN_impDMIN1:
4252 case FFEINTRIN_impMIN0:
4253 case FFEINTRIN_impMIN1:
4254 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4255 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4256 else
4257 arg1_type = tree_type;
4258 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4259 convert (arg1_type, ffecom_expr (arg1)),
4260 convert (arg1_type, ffecom_expr (arg2)));
4261 for (; list != NULL; list = ffebld_trail (list))
4262 {
4263 if ((ffebld_head (list) == NULL)
4264 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4265 continue;
4266 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4267 expr_tree,
4268 convert (arg1_type,
4269 ffecom_expr (ffebld_head (list))));
4270 }
4271 return convert (tree_type, expr_tree);
4272
4273 case FFEINTRIN_impMOD:
4274 case FFEINTRIN_impAMOD:
4275 case FFEINTRIN_impDMOD:
4276 if (bt != FFEINFO_basictypeREAL)
4277 return ffecom_2 (TRUNC_MOD_EXPR, tree_type,
4278 convert (tree_type, ffecom_expr (arg1)),
4279 convert (tree_type, ffecom_expr (arg2)));
4280
4281 if (kt == FFEINFO_kindtypeREAL1)
4282 /* We used to call FFECOM_gfrtAMOD here. */
4283 gfrt = FFECOM_gfrtL_FMOD;
4284 else if (kt == FFEINFO_kindtypeREAL2)
4285 /* We used to call FFECOM_gfrtDMOD here. */
4286 gfrt = FFECOM_gfrtL_FMOD;
4287 break;
4288
4289 case FFEINTRIN_impNINT:
4290 case FFEINTRIN_impIDNINT:
4291 #if 0
4292 /* ~~Ideally FIX_ROUND_EXPR would be implemented, but it ain't yet. */
4293 return ffecom_1 (FIX_ROUND_EXPR, tree_type, ffecom_expr (arg1));
4294 #else
4295 /* i__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1); */
4296 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4297 return
4298 convert (ffecom_integer_type_node,
4299 ffecom_3 (COND_EXPR, arg1_type,
4300 ffecom_truth_value
4301 (ffecom_2 (GE_EXPR, integer_type_node,
4302 saved_expr1,
4303 convert (arg1_type,
4304 ffecom_float_zero_))),
4305 ffecom_2 (PLUS_EXPR, arg1_type,
4306 saved_expr1,
4307 convert (arg1_type,
4308 ffecom_float_half_)),
4309 ffecom_2 (MINUS_EXPR, arg1_type,
4310 saved_expr1,
4311 convert (arg1_type,
4312 ffecom_float_half_))));
4313 #endif
4314
4315 case FFEINTRIN_impSIGN:
4316 case FFEINTRIN_impDSIGN:
4317 case FFEINTRIN_impISIGN:
4318 {
4319 tree arg2_tree = ffecom_expr (arg2);
4320
4321 saved_expr1
4322 = ffecom_save_tree
4323 (ffecom_1 (ABS_EXPR, tree_type,
4324 convert (tree_type,
4325 ffecom_expr (arg1))));
4326 expr_tree
4327 = ffecom_3 (COND_EXPR, tree_type,
4328 ffecom_truth_value
4329 (ffecom_2 (GE_EXPR, integer_type_node,
4330 arg2_tree,
4331 convert (TREE_TYPE (arg2_tree),
4332 integer_zero_node))),
4333 saved_expr1,
4334 ffecom_1 (NEGATE_EXPR, tree_type, saved_expr1));
4335 /* Make sure SAVE_EXPRs get referenced early enough. */
4336 expr_tree
4337 = ffecom_2 (COMPOUND_EXPR, tree_type,
4338 convert (void_type_node, saved_expr1),
4339 expr_tree);
4340 }
4341 return expr_tree;
4342
4343 case FFEINTRIN_impSIN:
4344 case FFEINTRIN_impCDSIN:
4345 case FFEINTRIN_impCSIN:
4346 case FFEINTRIN_impDSIN:
4347 if (bt == FFEINFO_basictypeCOMPLEX)
4348 {
4349 if (kt == FFEINFO_kindtypeREAL1)
4350 gfrt = FFECOM_gfrtCSIN; /* Overlapping result okay. */
4351 else if (kt == FFEINFO_kindtypeREAL2)
4352 gfrt = FFECOM_gfrtCDSIN; /* Overlapping result okay. */
4353 }
4354 break;
4355
4356 case FFEINTRIN_impSINH:
4357 case FFEINTRIN_impDSINH:
4358 break;
4359
4360 case FFEINTRIN_impSQRT:
4361 case FFEINTRIN_impCDSQRT:
4362 case FFEINTRIN_impCSQRT:
4363 case FFEINTRIN_impDSQRT:
4364 if (bt == FFEINFO_basictypeCOMPLEX)
4365 {
4366 if (kt == FFEINFO_kindtypeREAL1)
4367 gfrt = FFECOM_gfrtCSQRT; /* Overlapping result okay. */
4368 else if (kt == FFEINFO_kindtypeREAL2)
4369 gfrt = FFECOM_gfrtCDSQRT; /* Overlapping result okay. */
4370 }
4371 break;
4372
4373 case FFEINTRIN_impTAN:
4374 case FFEINTRIN_impDTAN:
4375 case FFEINTRIN_impTANH:
4376 case FFEINTRIN_impDTANH:
4377 break;
4378
4379 case FFEINTRIN_impREALPART:
4380 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4381 arg1_type = TREE_TYPE (arg1_type);
4382 else
4383 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4384
4385 return
4386 convert (tree_type,
4387 ffecom_1 (REALPART_EXPR, arg1_type,
4388 ffecom_expr (arg1)));
4389
4390 case FFEINTRIN_impIAND:
4391 case FFEINTRIN_impAND:
4392 return ffecom_2 (BIT_AND_EXPR, tree_type,
4393 convert (tree_type,
4394 ffecom_expr (arg1)),
4395 convert (tree_type,
4396 ffecom_expr (arg2)));
4397
4398 case FFEINTRIN_impIOR:
4399 case FFEINTRIN_impOR:
4400 return ffecom_2 (BIT_IOR_EXPR, tree_type,
4401 convert (tree_type,
4402 ffecom_expr (arg1)),
4403 convert (tree_type,
4404 ffecom_expr (arg2)));
4405
4406 case FFEINTRIN_impIEOR:
4407 case FFEINTRIN_impXOR:
4408 return ffecom_2 (BIT_XOR_EXPR, tree_type,
4409 convert (tree_type,
4410 ffecom_expr (arg1)),
4411 convert (tree_type,
4412 ffecom_expr (arg2)));
4413
4414 case FFEINTRIN_impLSHIFT:
4415 return ffecom_2 (LSHIFT_EXPR, tree_type,
4416 ffecom_expr (arg1),
4417 convert (integer_type_node,
4418 ffecom_expr (arg2)));
4419
4420 case FFEINTRIN_impRSHIFT:
4421 return ffecom_2 (RSHIFT_EXPR, tree_type,
4422 ffecom_expr (arg1),
4423 convert (integer_type_node,
4424 ffecom_expr (arg2)));
4425
4426 case FFEINTRIN_impNOT:
4427 return ffecom_1 (BIT_NOT_EXPR, tree_type, ffecom_expr (arg1));
4428
4429 case FFEINTRIN_impBIT_SIZE:
4430 return convert (tree_type, TYPE_SIZE (arg1_type));
4431
4432 case FFEINTRIN_impBTEST:
4433 {
4434 ffetargetLogical1 target_true;
4435 ffetargetLogical1 target_false;
4436 tree true_tree;
4437 tree false_tree;
4438
4439 ffetarget_logical1 (&target_true, TRUE);
4440 ffetarget_logical1 (&target_false, FALSE);
4441 if (target_true == 1)
4442 true_tree = convert (tree_type, integer_one_node);
4443 else
4444 true_tree = convert (tree_type, build_int_2 (target_true, 0));
4445 if (target_false == 0)
4446 false_tree = convert (tree_type, integer_zero_node);
4447 else
4448 false_tree = convert (tree_type, build_int_2 (target_false, 0));
4449
4450 return
4451 ffecom_3 (COND_EXPR, tree_type,
4452 ffecom_truth_value
4453 (ffecom_2 (EQ_EXPR, integer_type_node,
4454 ffecom_2 (BIT_AND_EXPR, arg1_type,
4455 ffecom_expr (arg1),
4456 ffecom_2 (LSHIFT_EXPR, arg1_type,
4457 convert (arg1_type,
4458 integer_one_node),
4459 convert (integer_type_node,
4460 ffecom_expr (arg2)))),
4461 convert (arg1_type,
4462 integer_zero_node))),
4463 false_tree,
4464 true_tree);
4465 }
4466
4467 case FFEINTRIN_impIBCLR:
4468 return
4469 ffecom_2 (BIT_AND_EXPR, tree_type,
4470 ffecom_expr (arg1),
4471 ffecom_1 (BIT_NOT_EXPR, tree_type,
4472 ffecom_2 (LSHIFT_EXPR, tree_type,
4473 convert (tree_type,
4474 integer_one_node),
4475 convert (integer_type_node,
4476 ffecom_expr (arg2)))));
4477
4478 case FFEINTRIN_impIBITS:
4479 {
4480 tree arg3_tree = ffecom_save_tree (convert (integer_type_node,
4481 ffecom_expr (arg3)));
4482 tree uns_type
4483 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4484
4485 expr_tree
4486 = ffecom_2 (BIT_AND_EXPR, tree_type,
4487 ffecom_2 (RSHIFT_EXPR, tree_type,
4488 ffecom_expr (arg1),
4489 convert (integer_type_node,
4490 ffecom_expr (arg2))),
4491 convert (tree_type,
4492 ffecom_2 (RSHIFT_EXPR, uns_type,
4493 ffecom_1 (BIT_NOT_EXPR,
4494 uns_type,
4495 convert (uns_type,
4496 integer_zero_node)),
4497 ffecom_2 (MINUS_EXPR,
4498 integer_type_node,
4499 TYPE_SIZE (uns_type),
4500 arg3_tree))));
4501 /* Fix up, because the RSHIFT_EXPR above can't shift over TYPE_SIZE. */
4502 expr_tree
4503 = ffecom_3 (COND_EXPR, tree_type,
4504 ffecom_truth_value
4505 (ffecom_2 (NE_EXPR, integer_type_node,
4506 arg3_tree,
4507 integer_zero_node)),
4508 expr_tree,
4509 convert (tree_type, integer_zero_node));
4510 }
4511 return expr_tree;
4512
4513 case FFEINTRIN_impIBSET:
4514 return
4515 ffecom_2 (BIT_IOR_EXPR, tree_type,
4516 ffecom_expr (arg1),
4517 ffecom_2 (LSHIFT_EXPR, tree_type,
4518 convert (tree_type, integer_one_node),
4519 convert (integer_type_node,
4520 ffecom_expr (arg2))));
4521
4522 case FFEINTRIN_impISHFT:
4523 {
4524 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4525 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4526 ffecom_expr (arg2)));
4527 tree uns_type
4528 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4529
4530 expr_tree
4531 = ffecom_3 (COND_EXPR, tree_type,
4532 ffecom_truth_value
4533 (ffecom_2 (GE_EXPR, integer_type_node,
4534 arg2_tree,
4535 integer_zero_node)),
4536 ffecom_2 (LSHIFT_EXPR, tree_type,
4537 arg1_tree,
4538 arg2_tree),
4539 convert (tree_type,
4540 ffecom_2 (RSHIFT_EXPR, uns_type,
4541 convert (uns_type, arg1_tree),
4542 ffecom_1 (NEGATE_EXPR,
4543 integer_type_node,
4544 arg2_tree))));
4545 /* Fix up, because {L|R}SHIFT_EXPR don't go over TYPE_SIZE bounds. */
4546 expr_tree
4547 = ffecom_3 (COND_EXPR, tree_type,
4548 ffecom_truth_value
4549 (ffecom_2 (NE_EXPR, integer_type_node,
4550 ffecom_1 (ABS_EXPR,
4551 integer_type_node,
4552 arg2_tree),
4553 TYPE_SIZE (uns_type))),
4554 expr_tree,
4555 convert (tree_type, integer_zero_node));
4556 /* Make sure SAVE_EXPRs get referenced early enough. */
4557 expr_tree
4558 = ffecom_2 (COMPOUND_EXPR, tree_type,
4559 convert (void_type_node, arg1_tree),
4560 ffecom_2 (COMPOUND_EXPR, tree_type,
4561 convert (void_type_node, arg2_tree),
4562 expr_tree));
4563 }
4564 return expr_tree;
4565
4566 case FFEINTRIN_impISHFTC:
4567 {
4568 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4569 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4570 ffecom_expr (arg2)));
4571 tree arg3_tree = (arg3 == NULL) ? TYPE_SIZE (tree_type)
4572 : ffecom_save_tree (convert (integer_type_node, ffecom_expr (arg3)));
4573 tree shift_neg;
4574 tree shift_pos;
4575 tree mask_arg1;
4576 tree masked_arg1;
4577 tree uns_type
4578 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4579
4580 mask_arg1
4581 = ffecom_2 (LSHIFT_EXPR, tree_type,
4582 ffecom_1 (BIT_NOT_EXPR, tree_type,
4583 convert (tree_type, integer_zero_node)),
4584 arg3_tree);
4585 /* Fix up, because LSHIFT_EXPR above can't shift over TYPE_SIZE. */
4586 mask_arg1
4587 = ffecom_3 (COND_EXPR, tree_type,
4588 ffecom_truth_value
4589 (ffecom_2 (NE_EXPR, integer_type_node,
4590 arg3_tree,
4591 TYPE_SIZE (uns_type))),
4592 mask_arg1,
4593 convert (tree_type, integer_zero_node));
4594 mask_arg1 = ffecom_save_tree (mask_arg1);
4595 masked_arg1
4596 = ffecom_2 (BIT_AND_EXPR, tree_type,
4597 arg1_tree,
4598 ffecom_1 (BIT_NOT_EXPR, tree_type,
4599 mask_arg1));
4600 masked_arg1 = ffecom_save_tree (masked_arg1);
4601 shift_neg
4602 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4603 convert (tree_type,
4604 ffecom_2 (RSHIFT_EXPR, uns_type,
4605 convert (uns_type, masked_arg1),
4606 ffecom_1 (NEGATE_EXPR,
4607 integer_type_node,
4608 arg2_tree))),
4609 ffecom_2 (LSHIFT_EXPR, tree_type,
4610 arg1_tree,
4611 ffecom_2 (PLUS_EXPR, integer_type_node,
4612 arg2_tree,
4613 arg3_tree)));
4614 shift_pos
4615 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4616 ffecom_2 (LSHIFT_EXPR, tree_type,
4617 arg1_tree,
4618 arg2_tree),
4619 convert (tree_type,
4620 ffecom_2 (RSHIFT_EXPR, uns_type,
4621 convert (uns_type, masked_arg1),
4622 ffecom_2 (MINUS_EXPR,
4623 integer_type_node,
4624 arg3_tree,
4625 arg2_tree))));
4626 expr_tree
4627 = ffecom_3 (COND_EXPR, tree_type,
4628 ffecom_truth_value
4629 (ffecom_2 (LT_EXPR, integer_type_node,
4630 arg2_tree,
4631 integer_zero_node)),
4632 shift_neg,
4633 shift_pos);
4634 expr_tree
4635 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4636 ffecom_2 (BIT_AND_EXPR, tree_type,
4637 mask_arg1,
4638 arg1_tree),
4639 ffecom_2 (BIT_AND_EXPR, tree_type,
4640 ffecom_1 (BIT_NOT_EXPR, tree_type,
4641 mask_arg1),
4642 expr_tree));
4643 expr_tree
4644 = ffecom_3 (COND_EXPR, tree_type,
4645 ffecom_truth_value
4646 (ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
4647 ffecom_2 (EQ_EXPR, integer_type_node,
4648 ffecom_1 (ABS_EXPR,
4649 integer_type_node,
4650 arg2_tree),
4651 arg3_tree),
4652 ffecom_2 (EQ_EXPR, integer_type_node,
4653 arg2_tree,
4654 integer_zero_node))),
4655 arg1_tree,
4656 expr_tree);
4657 /* Make sure SAVE_EXPRs get referenced early enough. */
4658 expr_tree
4659 = ffecom_2 (COMPOUND_EXPR, tree_type,
4660 convert (void_type_node, arg1_tree),
4661 ffecom_2 (COMPOUND_EXPR, tree_type,
4662 convert (void_type_node, arg2_tree),
4663 ffecom_2 (COMPOUND_EXPR, tree_type,
4664 convert (void_type_node,
4665 mask_arg1),
4666 ffecom_2 (COMPOUND_EXPR, tree_type,
4667 convert (void_type_node,
4668 masked_arg1),
4669 expr_tree))));
4670 expr_tree
4671 = ffecom_2 (COMPOUND_EXPR, tree_type,
4672 convert (void_type_node,
4673 arg3_tree),
4674 expr_tree);
4675 }
4676 return expr_tree;
4677
4678 case FFEINTRIN_impLOC:
4679 {
4680 tree arg1_tree = ffecom_expr (arg1);
4681
4682 expr_tree
4683 = convert (tree_type,
4684 ffecom_1 (ADDR_EXPR,
4685 build_pointer_type (TREE_TYPE (arg1_tree)),
4686 arg1_tree));
4687 }
4688 return expr_tree;
4689
4690 case FFEINTRIN_impMVBITS:
4691 {
4692 tree arg1_tree;
4693 tree arg2_tree;
4694 tree arg3_tree;
4695 ffebld arg4 = ffebld_head (ffebld_trail (list));
4696 tree arg4_tree;
4697 tree arg4_type;
4698 ffebld arg5 = ffebld_head (ffebld_trail (ffebld_trail (list)));
4699 tree arg5_tree;
4700 tree prep_arg1;
4701 tree prep_arg4;
4702 tree arg5_plus_arg3;
4703
4704 arg2_tree = convert (integer_type_node,
4705 ffecom_expr (arg2));
4706 arg3_tree = ffecom_save_tree (convert (integer_type_node,
4707 ffecom_expr (arg3)));
4708 arg4_tree = ffecom_expr_rw (NULL_TREE, arg4);
4709 arg4_type = TREE_TYPE (arg4_tree);
4710
4711 arg1_tree = ffecom_save_tree (convert (arg4_type,
4712 ffecom_expr (arg1)));
4713
4714 arg5_tree = ffecom_save_tree (convert (integer_type_node,
4715 ffecom_expr (arg5)));
4716
4717 prep_arg1
4718 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4719 ffecom_2 (BIT_AND_EXPR, arg4_type,
4720 ffecom_2 (RSHIFT_EXPR, arg4_type,
4721 arg1_tree,
4722 arg2_tree),
4723 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4724 ffecom_2 (LSHIFT_EXPR, arg4_type,
4725 ffecom_1 (BIT_NOT_EXPR,
4726 arg4_type,
4727 convert
4728 (arg4_type,
4729 integer_zero_node)),
4730 arg3_tree))),
4731 arg5_tree);
4732 arg5_plus_arg3
4733 = ffecom_save_tree (ffecom_2 (PLUS_EXPR, arg4_type,
4734 arg5_tree,
4735 arg3_tree));
4736 prep_arg4
4737 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4738 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4739 convert (arg4_type,
4740 integer_zero_node)),
4741 arg5_plus_arg3);
4742 /* Fix up, because LSHIFT_EXPR above can't shift over TYPE_SIZE. */
4743 prep_arg4
4744 = ffecom_3 (COND_EXPR, arg4_type,
4745 ffecom_truth_value
4746 (ffecom_2 (NE_EXPR, integer_type_node,
4747 arg5_plus_arg3,
4748 convert (TREE_TYPE (arg5_plus_arg3),
4749 TYPE_SIZE (arg4_type)))),
4750 prep_arg4,
4751 convert (arg4_type, integer_zero_node));
4752 prep_arg4
4753 = ffecom_2 (BIT_AND_EXPR, arg4_type,
4754 arg4_tree,
4755 ffecom_2 (BIT_IOR_EXPR, arg4_type,
4756 prep_arg4,
4757 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4758 ffecom_2 (LSHIFT_EXPR, arg4_type,
4759 ffecom_1 (BIT_NOT_EXPR,
4760 arg4_type,
4761 convert
4762 (arg4_type,
4763 integer_zero_node)),
4764 arg5_tree))));
4765 prep_arg1
4766 = ffecom_2 (BIT_IOR_EXPR, arg4_type,
4767 prep_arg1,
4768 prep_arg4);
4769 /* Fix up (twice), because LSHIFT_EXPR above
4770 can't shift over TYPE_SIZE. */
4771 prep_arg1
4772 = ffecom_3 (COND_EXPR, arg4_type,
4773 ffecom_truth_value
4774 (ffecom_2 (NE_EXPR, integer_type_node,
4775 arg3_tree,
4776 convert (TREE_TYPE (arg3_tree),
4777 integer_zero_node))),
4778 prep_arg1,
4779 arg4_tree);
4780 prep_arg1
4781 = ffecom_3 (COND_EXPR, arg4_type,
4782 ffecom_truth_value
4783 (ffecom_2 (NE_EXPR, integer_type_node,
4784 arg3_tree,
4785 convert (TREE_TYPE (arg3_tree),
4786 TYPE_SIZE (arg4_type)))),
4787 prep_arg1,
4788 arg1_tree);
4789 expr_tree
4790 = ffecom_2s (MODIFY_EXPR, void_type_node,
4791 arg4_tree,
4792 prep_arg1);
4793 /* Make sure SAVE_EXPRs get referenced early enough. */
4794 expr_tree
4795 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4796 arg1_tree,
4797 ffecom_2 (COMPOUND_EXPR, void_type_node,
4798 arg3_tree,
4799 ffecom_2 (COMPOUND_EXPR, void_type_node,
4800 arg5_tree,
4801 ffecom_2 (COMPOUND_EXPR, void_type_node,
4802 arg5_plus_arg3,
4803 expr_tree))));
4804 expr_tree
4805 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4806 arg4_tree,
4807 expr_tree);
4808
4809 }
4810 return expr_tree;
4811
4812 case FFEINTRIN_impDERF:
4813 case FFEINTRIN_impERF:
4814 case FFEINTRIN_impDERFC:
4815 case FFEINTRIN_impERFC:
4816 break;
4817
4818 case FFEINTRIN_impIARGC:
4819 /* extern int xargc; i__1 = xargc - 1; */
4820 expr_tree = ffecom_2 (MINUS_EXPR, TREE_TYPE (ffecom_tree_xargc_),
4821 ffecom_tree_xargc_,
4822 convert (TREE_TYPE (ffecom_tree_xargc_),
4823 integer_one_node));
4824 return expr_tree;
4825
4826 case FFEINTRIN_impSIGNAL_func:
4827 case FFEINTRIN_impSIGNAL_subr:
4828 {
4829 tree arg1_tree;
4830 tree arg2_tree;
4831 tree arg3_tree;
4832
4833 arg1_tree = convert (ffecom_f2c_integer_type_node,
4834 ffecom_expr (arg1));
4835 arg1_tree = ffecom_1 (ADDR_EXPR,
4836 build_pointer_type (TREE_TYPE (arg1_tree)),
4837 arg1_tree);
4838
4839 /* Pass procedure as a pointer to it, anything else by value. */
4840 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4841 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4842 else
4843 arg2_tree = ffecom_ptr_to_expr (arg2);
4844 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4845 arg2_tree);
4846
4847 if (arg3 != NULL)
4848 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
4849 else
4850 arg3_tree = NULL_TREE;
4851
4852 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4853 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4854 TREE_CHAIN (arg1_tree) = arg2_tree;
4855
4856 expr_tree
4857 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4858 ffecom_gfrt_kindtype (gfrt),
4859 FALSE,
4860 ((codegen_imp == FFEINTRIN_impSIGNAL_subr) ?
4861 NULL_TREE :
4862 tree_type),
4863 arg1_tree,
4864 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4865 ffebld_nonter_hook (expr));
4866
4867 if (arg3_tree != NULL_TREE)
4868 expr_tree
4869 = ffecom_modify (NULL_TREE, arg3_tree,
4870 convert (TREE_TYPE (arg3_tree),
4871 expr_tree));
4872 }
4873 return expr_tree;
4874
4875 case FFEINTRIN_impALARM:
4876 {
4877 tree arg1_tree;
4878 tree arg2_tree;
4879 tree arg3_tree;
4880
4881 arg1_tree = convert (ffecom_f2c_integer_type_node,
4882 ffecom_expr (arg1));
4883 arg1_tree = ffecom_1 (ADDR_EXPR,
4884 build_pointer_type (TREE_TYPE (arg1_tree)),
4885 arg1_tree);
4886
4887 /* Pass procedure as a pointer to it, anything else by value. */
4888 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4889 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4890 else
4891 arg2_tree = ffecom_ptr_to_expr (arg2);
4892 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4893 arg2_tree);
4894
4895 if (arg3 != NULL)
4896 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
4897 else
4898 arg3_tree = NULL_TREE;
4899
4900 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4901 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4902 TREE_CHAIN (arg1_tree) = arg2_tree;
4903
4904 expr_tree
4905 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4906 ffecom_gfrt_kindtype (gfrt),
4907 FALSE,
4908 NULL_TREE,
4909 arg1_tree,
4910 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4911 ffebld_nonter_hook (expr));
4912
4913 if (arg3_tree != NULL_TREE)
4914 expr_tree
4915 = ffecom_modify (NULL_TREE, arg3_tree,
4916 convert (TREE_TYPE (arg3_tree),
4917 expr_tree));
4918 }
4919 return expr_tree;
4920
4921 case FFEINTRIN_impCHDIR_subr:
4922 case FFEINTRIN_impFDATE_subr:
4923 case FFEINTRIN_impFGET_subr:
4924 case FFEINTRIN_impFPUT_subr:
4925 case FFEINTRIN_impGETCWD_subr:
4926 case FFEINTRIN_impHOSTNM_subr:
4927 case FFEINTRIN_impSYSTEM_subr:
4928 case FFEINTRIN_impUNLINK_subr:
4929 {
4930 tree arg1_len = integer_zero_node;
4931 tree arg1_tree;
4932 tree arg2_tree;
4933
4934 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
4935
4936 if (arg2 != NULL)
4937 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
4938 else
4939 arg2_tree = NULL_TREE;
4940
4941 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4942 arg1_len = build_tree_list (NULL_TREE, arg1_len);
4943 TREE_CHAIN (arg1_tree) = arg1_len;
4944
4945 expr_tree
4946 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4947 ffecom_gfrt_kindtype (gfrt),
4948 FALSE,
4949 NULL_TREE,
4950 arg1_tree,
4951 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4952 ffebld_nonter_hook (expr));
4953
4954 if (arg2_tree != NULL_TREE)
4955 expr_tree
4956 = ffecom_modify (NULL_TREE, arg2_tree,
4957 convert (TREE_TYPE (arg2_tree),
4958 expr_tree));
4959 }
4960 return expr_tree;
4961
4962 case FFEINTRIN_impEXIT:
4963 if (arg1 != NULL)
4964 break;
4965
4966 expr_tree = build_tree_list (NULL_TREE,
4967 ffecom_1 (ADDR_EXPR,
4968 build_pointer_type
4969 (ffecom_integer_type_node),
4970 integer_zero_node));
4971
4972 return
4973 ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4974 ffecom_gfrt_kindtype (gfrt),
4975 FALSE,
4976 void_type_node,
4977 expr_tree,
4978 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4979 ffebld_nonter_hook (expr));
4980
4981 case FFEINTRIN_impFLUSH:
4982 if (arg1 == NULL)
4983 gfrt = FFECOM_gfrtFLUSH;
4984 else
4985 gfrt = FFECOM_gfrtFLUSH1;
4986 break;
4987
4988 case FFEINTRIN_impCHMOD_subr:
4989 case FFEINTRIN_impLINK_subr:
4990 case FFEINTRIN_impRENAME_subr:
4991 case FFEINTRIN_impSYMLNK_subr:
4992 {
4993 tree arg1_len = integer_zero_node;
4994 tree arg1_tree;
4995 tree arg2_len = integer_zero_node;
4996 tree arg2_tree;
4997 tree arg3_tree;
4998
4999 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5000 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
5001 if (arg3 != NULL)
5002 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5003 else
5004 arg3_tree = NULL_TREE;
5005
5006 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5007 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5008 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5009 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5010 TREE_CHAIN (arg1_tree) = arg2_tree;
5011 TREE_CHAIN (arg2_tree) = arg1_len;
5012 TREE_CHAIN (arg1_len) = arg2_len;
5013 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5014 ffecom_gfrt_kindtype (gfrt),
5015 FALSE,
5016 NULL_TREE,
5017 arg1_tree,
5018 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5019 ffebld_nonter_hook (expr));
5020 if (arg3_tree != NULL_TREE)
5021 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5022 convert (TREE_TYPE (arg3_tree),
5023 expr_tree));
5024 }
5025 return expr_tree;
5026
5027 case FFEINTRIN_impLSTAT_subr:
5028 case FFEINTRIN_impSTAT_subr:
5029 {
5030 tree arg1_len = integer_zero_node;
5031 tree arg1_tree;
5032 tree arg2_tree;
5033 tree arg3_tree;
5034
5035 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5036
5037 arg2_tree = ffecom_ptr_to_expr (arg2);
5038
5039 if (arg3 != NULL)
5040 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5041 else
5042 arg3_tree = NULL_TREE;
5043
5044 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5045 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5046 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5047 TREE_CHAIN (arg1_tree) = arg2_tree;
5048 TREE_CHAIN (arg2_tree) = arg1_len;
5049 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5050 ffecom_gfrt_kindtype (gfrt),
5051 FALSE,
5052 NULL_TREE,
5053 arg1_tree,
5054 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5055 ffebld_nonter_hook (expr));
5056 if (arg3_tree != NULL_TREE)
5057 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5058 convert (TREE_TYPE (arg3_tree),
5059 expr_tree));
5060 }
5061 return expr_tree;
5062
5063 case FFEINTRIN_impFGETC_subr:
5064 case FFEINTRIN_impFPUTC_subr:
5065 {
5066 tree arg1_tree;
5067 tree arg2_tree;
5068 tree arg2_len = integer_zero_node;
5069 tree arg3_tree;
5070
5071 arg1_tree = convert (ffecom_f2c_integer_type_node,
5072 ffecom_expr (arg1));
5073 arg1_tree = ffecom_1 (ADDR_EXPR,
5074 build_pointer_type (TREE_TYPE (arg1_tree)),
5075 arg1_tree);
5076
5077 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
5078 if (arg3 != NULL)
5079 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5080 else
5081 arg3_tree = NULL_TREE;
5082
5083 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5084 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5085 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5086 TREE_CHAIN (arg1_tree) = arg2_tree;
5087 TREE_CHAIN (arg2_tree) = arg2_len;
5088
5089 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5090 ffecom_gfrt_kindtype (gfrt),
5091 FALSE,
5092 NULL_TREE,
5093 arg1_tree,
5094 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5095 ffebld_nonter_hook (expr));
5096 if (arg3_tree != NULL_TREE)
5097 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5098 convert (TREE_TYPE (arg3_tree),
5099 expr_tree));
5100 }
5101 return expr_tree;
5102
5103 case FFEINTRIN_impFSTAT_subr:
5104 {
5105 tree arg1_tree;
5106 tree arg2_tree;
5107 tree arg3_tree;
5108
5109 arg1_tree = convert (ffecom_f2c_integer_type_node,
5110 ffecom_expr (arg1));
5111 arg1_tree = ffecom_1 (ADDR_EXPR,
5112 build_pointer_type (TREE_TYPE (arg1_tree)),
5113 arg1_tree);
5114
5115 arg2_tree = convert (ffecom_f2c_ptr_to_integer_type_node,
5116 ffecom_ptr_to_expr (arg2));
5117
5118 if (arg3 == NULL)
5119 arg3_tree = NULL_TREE;
5120 else
5121 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5122
5123 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5124 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5125 TREE_CHAIN (arg1_tree) = arg2_tree;
5126 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5127 ffecom_gfrt_kindtype (gfrt),
5128 FALSE,
5129 NULL_TREE,
5130 arg1_tree,
5131 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5132 ffebld_nonter_hook (expr));
5133 if (arg3_tree != NULL_TREE) {
5134 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5135 convert (TREE_TYPE (arg3_tree),
5136 expr_tree));
5137 }
5138 }
5139 return expr_tree;
5140
5141 case FFEINTRIN_impKILL_subr:
5142 {
5143 tree arg1_tree;
5144 tree arg2_tree;
5145 tree arg3_tree;
5146
5147 arg1_tree = convert (ffecom_f2c_integer_type_node,
5148 ffecom_expr (arg1));
5149 arg1_tree = ffecom_1 (ADDR_EXPR,
5150 build_pointer_type (TREE_TYPE (arg1_tree)),
5151 arg1_tree);
5152
5153 arg2_tree = convert (ffecom_f2c_integer_type_node,
5154 ffecom_expr (arg2));
5155 arg2_tree = ffecom_1 (ADDR_EXPR,
5156 build_pointer_type (TREE_TYPE (arg2_tree)),
5157 arg2_tree);
5158
5159 if (arg3 == NULL)
5160 arg3_tree = NULL_TREE;
5161 else
5162 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5163
5164 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5165 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5166 TREE_CHAIN (arg1_tree) = arg2_tree;
5167 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5168 ffecom_gfrt_kindtype (gfrt),
5169 FALSE,
5170 NULL_TREE,
5171 arg1_tree,
5172 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5173 ffebld_nonter_hook (expr));
5174 if (arg3_tree != NULL_TREE) {
5175 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5176 convert (TREE_TYPE (arg3_tree),
5177 expr_tree));
5178 }
5179 }
5180 return expr_tree;
5181
5182 case FFEINTRIN_impCTIME_subr:
5183 case FFEINTRIN_impTTYNAM_subr:
5184 {
5185 tree arg1_len = integer_zero_node;
5186 tree arg1_tree;
5187 tree arg2_tree;
5188
5189 arg1_tree = ffecom_arg_ptr_to_expr (arg2, &arg1_len);
5190
5191 arg2_tree = convert (((codegen_imp == FFEINTRIN_impCTIME_subr) ?
5192 ffecom_f2c_longint_type_node :
5193 ffecom_f2c_integer_type_node),
5194 ffecom_expr (arg1));
5195 arg2_tree = ffecom_1 (ADDR_EXPR,
5196 build_pointer_type (TREE_TYPE (arg2_tree)),
5197 arg2_tree);
5198
5199 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5200 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5201 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5202 TREE_CHAIN (arg1_len) = arg2_tree;
5203 TREE_CHAIN (arg1_tree) = arg1_len;
5204
5205 expr_tree
5206 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5207 ffecom_gfrt_kindtype (gfrt),
5208 FALSE,
5209 NULL_TREE,
5210 arg1_tree,
5211 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5212 ffebld_nonter_hook (expr));
5213 TREE_SIDE_EFFECTS (expr_tree) = 1;
5214 }
5215 return expr_tree;
5216
5217 case FFEINTRIN_impIRAND:
5218 case FFEINTRIN_impRAND:
5219 /* Arg defaults to 0 (normal random case) */
5220 {
5221 tree arg1_tree;
5222
5223 if (arg1 == NULL)
5224 arg1_tree = ffecom_integer_zero_node;
5225 else
5226 arg1_tree = ffecom_expr (arg1);
5227 arg1_tree = convert (ffecom_f2c_integer_type_node,
5228 arg1_tree);
5229 arg1_tree = ffecom_1 (ADDR_EXPR,
5230 build_pointer_type (TREE_TYPE (arg1_tree)),
5231 arg1_tree);
5232 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5233
5234 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5235 ffecom_gfrt_kindtype (gfrt),
5236 FALSE,
5237 ((codegen_imp == FFEINTRIN_impIRAND) ?
5238 ffecom_f2c_integer_type_node :
5239 ffecom_f2c_real_type_node),
5240 arg1_tree,
5241 dest_tree, dest, dest_used,
5242 NULL_TREE, TRUE,
5243 ffebld_nonter_hook (expr));
5244 }
5245 return expr_tree;
5246
5247 case FFEINTRIN_impFTELL_subr:
5248 case FFEINTRIN_impUMASK_subr:
5249 {
5250 tree arg1_tree;
5251 tree arg2_tree;
5252
5253 arg1_tree = convert (ffecom_f2c_integer_type_node,
5254 ffecom_expr (arg1));
5255 arg1_tree = ffecom_1 (ADDR_EXPR,
5256 build_pointer_type (TREE_TYPE (arg1_tree)),
5257 arg1_tree);
5258
5259 if (arg2 == NULL)
5260 arg2_tree = NULL_TREE;
5261 else
5262 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
5263
5264 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5265 ffecom_gfrt_kindtype (gfrt),
5266 FALSE,
5267 NULL_TREE,
5268 build_tree_list (NULL_TREE, arg1_tree),
5269 NULL_TREE, NULL, NULL, NULL_TREE,
5270 TRUE,
5271 ffebld_nonter_hook (expr));
5272 if (arg2_tree != NULL_TREE) {
5273 expr_tree = ffecom_modify (NULL_TREE, arg2_tree,
5274 convert (TREE_TYPE (arg2_tree),
5275 expr_tree));
5276 }
5277 }
5278 return expr_tree;
5279
5280 case FFEINTRIN_impCPU_TIME:
5281 case FFEINTRIN_impSECOND_subr:
5282 {
5283 tree arg1_tree;
5284
5285 arg1_tree = ffecom_expr_w (NULL_TREE, arg1);
5286
5287 expr_tree
5288 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5289 ffecom_gfrt_kindtype (gfrt),
5290 FALSE,
5291 NULL_TREE,
5292 NULL_TREE,
5293 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5294 ffebld_nonter_hook (expr));
5295
5296 expr_tree
5297 = ffecom_modify (NULL_TREE, arg1_tree,
5298 convert (TREE_TYPE (arg1_tree),
5299 expr_tree));
5300 }
5301 return expr_tree;
5302
5303 case FFEINTRIN_impDTIME_subr:
5304 case FFEINTRIN_impETIME_subr:
5305 {
5306 tree arg1_tree;
5307 tree result_tree;
5308
5309 result_tree = ffecom_expr_w (NULL_TREE, arg2);
5310
5311 arg1_tree = ffecom_ptr_to_expr (arg1);
5312
5313 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5314 ffecom_gfrt_kindtype (gfrt),
5315 FALSE,
5316 NULL_TREE,
5317 build_tree_list (NULL_TREE, arg1_tree),
5318 NULL_TREE, NULL, NULL, NULL_TREE,
5319 TRUE,
5320 ffebld_nonter_hook (expr));
5321 expr_tree = ffecom_modify (NULL_TREE, result_tree,
5322 convert (TREE_TYPE (result_tree),
5323 expr_tree));
5324 }
5325 return expr_tree;
5326
5327 /* Straightforward calls of libf2c routines: */
5328 case FFEINTRIN_impABORT:
5329 case FFEINTRIN_impACCESS:
5330 case FFEINTRIN_impBESJ0:
5331 case FFEINTRIN_impBESJ1:
5332 case FFEINTRIN_impBESJN:
5333 case FFEINTRIN_impBESY0:
5334 case FFEINTRIN_impBESY1:
5335 case FFEINTRIN_impBESYN:
5336 case FFEINTRIN_impCHDIR_func:
5337 case FFEINTRIN_impCHMOD_func:
5338 case FFEINTRIN_impDATE:
5339 case FFEINTRIN_impDATE_AND_TIME:
5340 case FFEINTRIN_impDBESJ0:
5341 case FFEINTRIN_impDBESJ1:
5342 case FFEINTRIN_impDBESJN:
5343 case FFEINTRIN_impDBESY0:
5344 case FFEINTRIN_impDBESY1:
5345 case FFEINTRIN_impDBESYN:
5346 case FFEINTRIN_impDTIME_func:
5347 case FFEINTRIN_impETIME_func:
5348 case FFEINTRIN_impFGETC_func:
5349 case FFEINTRIN_impFGET_func:
5350 case FFEINTRIN_impFNUM:
5351 case FFEINTRIN_impFPUTC_func:
5352 case FFEINTRIN_impFPUT_func:
5353 case FFEINTRIN_impFSEEK:
5354 case FFEINTRIN_impFSTAT_func:
5355 case FFEINTRIN_impFTELL_func:
5356 case FFEINTRIN_impGERROR:
5357 case FFEINTRIN_impGETARG:
5358 case FFEINTRIN_impGETCWD_func:
5359 case FFEINTRIN_impGETENV:
5360 case FFEINTRIN_impGETGID:
5361 case FFEINTRIN_impGETLOG:
5362 case FFEINTRIN_impGETPID:
5363 case FFEINTRIN_impGETUID:
5364 case FFEINTRIN_impGMTIME:
5365 case FFEINTRIN_impHOSTNM_func:
5366 case FFEINTRIN_impIDATE_unix:
5367 case FFEINTRIN_impIDATE_vxt:
5368 case FFEINTRIN_impIERRNO:
5369 case FFEINTRIN_impISATTY:
5370 case FFEINTRIN_impITIME:
5371 case FFEINTRIN_impKILL_func:
5372 case FFEINTRIN_impLINK_func:
5373 case FFEINTRIN_impLNBLNK:
5374 case FFEINTRIN_impLSTAT_func:
5375 case FFEINTRIN_impLTIME:
5376 case FFEINTRIN_impMCLOCK8:
5377 case FFEINTRIN_impMCLOCK:
5378 case FFEINTRIN_impPERROR:
5379 case FFEINTRIN_impRENAME_func:
5380 case FFEINTRIN_impSECNDS:
5381 case FFEINTRIN_impSECOND_func:
5382 case FFEINTRIN_impSLEEP:
5383 case FFEINTRIN_impSRAND:
5384 case FFEINTRIN_impSTAT_func:
5385 case FFEINTRIN_impSYMLNK_func:
5386 case FFEINTRIN_impSYSTEM_CLOCK:
5387 case FFEINTRIN_impSYSTEM_func:
5388 case FFEINTRIN_impTIME8:
5389 case FFEINTRIN_impTIME_unix:
5390 case FFEINTRIN_impTIME_vxt:
5391 case FFEINTRIN_impUMASK_func:
5392 case FFEINTRIN_impUNLINK_func:
5393 break;
5394
5395 case FFEINTRIN_impCTIME_func: /* CHARACTER functions not handled here. */
5396 case FFEINTRIN_impFDATE_func: /* CHARACTER functions not handled here. */
5397 case FFEINTRIN_impTTYNAM_func: /* CHARACTER functions not handled here. */
5398 case FFEINTRIN_impNONE:
5399 case FFEINTRIN_imp: /* Hush up gcc warning. */
5400 fprintf (stderr, "No %s implementation.\n",
5401 ffeintrin_name_implementation (ffebld_symter_implementation (ffebld_left (expr))));
5402 assert ("unimplemented intrinsic" == NULL);
5403 return error_mark_node;
5404 }
5405
5406 assert (gfrt != FFECOM_gfrt); /* Must have an implementation! */
5407
5408 expr_tree = ffecom_arglist_expr_ (ffecom_gfrt_args_ (gfrt),
5409 ffebld_right (expr));
5410
5411 return ffecom_call_ (ffecom_gfrt_tree_ (gfrt), ffecom_gfrt_kindtype (gfrt),
5412 (ffe_is_f2c_library () && ffecom_gfrt_complex_[gfrt]),
5413 tree_type,
5414 expr_tree, dest_tree, dest, dest_used,
5415 NULL_TREE, TRUE,
5416 ffebld_nonter_hook (expr));
5417
5418 /* See bottom of this file for f2c transforms used to determine
5419 many of the above implementations. The info seems to confuse
5420 Emacs's C mode indentation, which is why it's been moved to
5421 the bottom of this source file. */
5422 }
5423
5424 /* For power (exponentiation) where right-hand operand is type INTEGER,
5425 generate in-line code to do it the fast way (which, if the operand
5426 is a constant, might just mean a series of multiplies). */
5427
5428 static tree
ffecom_expr_power_integer_(ffebld expr)5429 ffecom_expr_power_integer_ (ffebld expr)
5430 {
5431 tree l = ffecom_expr (ffebld_left (expr));
5432 tree r = ffecom_expr (ffebld_right (expr));
5433 tree ltype = TREE_TYPE (l);
5434 tree rtype = TREE_TYPE (r);
5435 tree result = NULL_TREE;
5436
5437 if (l == error_mark_node
5438 || r == error_mark_node)
5439 return error_mark_node;
5440
5441 if (TREE_CODE (r) == INTEGER_CST)
5442 {
5443 int sgn = tree_int_cst_sgn (r);
5444
5445 if (sgn == 0)
5446 return convert (ltype, integer_one_node);
5447
5448 if ((TREE_CODE (ltype) == INTEGER_TYPE)
5449 && (sgn < 0))
5450 {
5451 /* Reciprocal of integer is either 0, -1, or 1, so after
5452 calculating that (which we leave to the back end to do
5453 or not do optimally), don't bother with any multiplying. */
5454
5455 result = ffecom_tree_divide_ (ltype,
5456 convert (ltype, integer_one_node),
5457 l,
5458 NULL_TREE, NULL, NULL, NULL_TREE);
5459 r = ffecom_1 (NEGATE_EXPR,
5460 rtype,
5461 r);
5462 if ((TREE_INT_CST_LOW (r) & 1) == 0)
5463 result = ffecom_1 (ABS_EXPR, rtype,
5464 result);
5465 }
5466
5467 /* Generate appropriate series of multiplies, preceded
5468 by divide if the exponent is negative. */
5469
5470 l = save_expr (l);
5471
5472 if (sgn < 0)
5473 {
5474 l = ffecom_tree_divide_ (ltype,
5475 convert (ltype, integer_one_node),
5476 l,
5477 NULL_TREE, NULL, NULL,
5478 ffebld_nonter_hook (expr));
5479 r = ffecom_1 (NEGATE_EXPR, rtype, r);
5480 assert (TREE_CODE (r) == INTEGER_CST);
5481
5482 if (tree_int_cst_sgn (r) < 0)
5483 { /* The "most negative" number. */
5484 r = ffecom_1 (NEGATE_EXPR, rtype,
5485 ffecom_2 (RSHIFT_EXPR, rtype,
5486 r,
5487 integer_one_node));
5488 l = save_expr (l);
5489 l = ffecom_2 (MULT_EXPR, ltype,
5490 l,
5491 l);
5492 }
5493 }
5494
5495 for (;;)
5496 {
5497 if (TREE_INT_CST_LOW (r) & 1)
5498 {
5499 if (result == NULL_TREE)
5500 result = l;
5501 else
5502 result = ffecom_2 (MULT_EXPR, ltype,
5503 result,
5504 l);
5505 }
5506
5507 r = ffecom_2 (RSHIFT_EXPR, rtype,
5508 r,
5509 integer_one_node);
5510 if (integer_zerop (r))
5511 break;
5512 assert (TREE_CODE (r) == INTEGER_CST);
5513
5514 l = save_expr (l);
5515 l = ffecom_2 (MULT_EXPR, ltype,
5516 l,
5517 l);
5518 }
5519 return result;
5520 }
5521
5522 /* Though rhs isn't a constant, in-line code cannot be expanded
5523 while transforming dummies
5524 because the back end cannot be easily convinced to generate
5525 stores (MODIFY_EXPR), handle temporaries, and so on before
5526 all the appropriate rtx's have been generated for things like
5527 dummy args referenced in rhs -- which doesn't happen until
5528 store_parm_decls() is called (expand_function_start, I believe,
5529 does the actual rtx-stuffing of PARM_DECLs).
5530
5531 So, in this case, let the caller generate the call to the
5532 run-time-library function to evaluate the power for us. */
5533
5534 if (ffecom_transform_only_dummies_)
5535 return NULL_TREE;
5536
5537 /* Right-hand operand not a constant, expand in-line code to figure
5538 out how to do the multiplies, &c.
5539
5540 The returned expression is expressed this way in GNU C, where l and
5541 r are the "inputs":
5542
5543 ({ typeof (r) rtmp = r;
5544 typeof (l) ltmp = l;
5545 typeof (l) result;
5546
5547 if (rtmp == 0)
5548 result = 1;
5549 else
5550 {
5551 if ((basetypeof (l) == basetypeof (int))
5552 && (rtmp < 0))
5553 {
5554 result = ((typeof (l)) 1) / ltmp;
5555 if ((ltmp < 0) && (((-rtmp) & 1) == 0))
5556 result = -result;
5557 }
5558 else
5559 {
5560 result = 1;
5561 if ((basetypeof (l) != basetypeof (int))
5562 && (rtmp < 0))
5563 {
5564 ltmp = ((typeof (l)) 1) / ltmp;
5565 rtmp = -rtmp;
5566 if (rtmp < 0)
5567 {
5568 rtmp = -(rtmp >> 1);
5569 ltmp *= ltmp;
5570 }
5571 }
5572 for (;;)
5573 {
5574 if (rtmp & 1)
5575 result *= ltmp;
5576 if ((rtmp >>= 1) == 0)
5577 break;
5578 ltmp *= ltmp;
5579 }
5580 }
5581 }
5582 result;
5583 })
5584
5585 Note that some of the above is compile-time collapsable, such as
5586 the first part of the if statements that checks the base type of
5587 l against int. The if statements are phrased that way to suggest
5588 an easy way to generate the if/else constructs here, knowing that
5589 the back end should (and probably does) eliminate the resulting
5590 dead code (either the int case or the non-int case), something
5591 it couldn't do without the redundant phrasing, requiring explicit
5592 dead-code elimination here, which would be kind of difficult to
5593 read. */
5594
5595 {
5596 tree rtmp;
5597 tree ltmp;
5598 tree divide;
5599 tree basetypeof_l_is_int;
5600 tree se;
5601 tree t;
5602
5603 basetypeof_l_is_int
5604 = build_int_2 ((TREE_CODE (ltype) == INTEGER_TYPE), 0);
5605
5606 se = expand_start_stmt_expr (/*has_scope=*/1);
5607
5608 ffecom_start_compstmt ();
5609
5610 rtmp = ffecom_make_tempvar ("power_r", rtype,
5611 FFETARGET_charactersizeNONE, -1);
5612 ltmp = ffecom_make_tempvar ("power_l", ltype,
5613 FFETARGET_charactersizeNONE, -1);
5614 result = ffecom_make_tempvar ("power_res", ltype,
5615 FFETARGET_charactersizeNONE, -1);
5616 if (TREE_CODE (ltype) == COMPLEX_TYPE
5617 || TREE_CODE (ltype) == RECORD_TYPE)
5618 divide = ffecom_make_tempvar ("power_div", ltype,
5619 FFETARGET_charactersizeNONE, -1);
5620 else
5621 divide = NULL_TREE;
5622
5623 expand_expr_stmt (ffecom_modify (void_type_node,
5624 rtmp,
5625 r));
5626 expand_expr_stmt (ffecom_modify (void_type_node,
5627 ltmp,
5628 l));
5629 expand_start_cond (ffecom_truth_value
5630 (ffecom_2 (EQ_EXPR, integer_type_node,
5631 rtmp,
5632 convert (rtype, integer_zero_node))),
5633 0);
5634 expand_expr_stmt (ffecom_modify (void_type_node,
5635 result,
5636 convert (ltype, integer_one_node)));
5637 expand_start_else ();
5638 if (! integer_zerop (basetypeof_l_is_int))
5639 {
5640 expand_start_cond (ffecom_2 (LT_EXPR, integer_type_node,
5641 rtmp,
5642 convert (rtype,
5643 integer_zero_node)),
5644 0);
5645 expand_expr_stmt (ffecom_modify (void_type_node,
5646 result,
5647 ffecom_tree_divide_
5648 (ltype,
5649 convert (ltype, integer_one_node),
5650 ltmp,
5651 NULL_TREE, NULL, NULL,
5652 divide)));
5653 expand_start_cond (ffecom_truth_value
5654 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5655 ffecom_2 (LT_EXPR, integer_type_node,
5656 ltmp,
5657 convert (ltype,
5658 integer_zero_node)),
5659 ffecom_2 (EQ_EXPR, integer_type_node,
5660 ffecom_2 (BIT_AND_EXPR,
5661 rtype,
5662 ffecom_1 (NEGATE_EXPR,
5663 rtype,
5664 rtmp),
5665 convert (rtype,
5666 integer_one_node)),
5667 convert (rtype,
5668 integer_zero_node)))),
5669 0);
5670 expand_expr_stmt (ffecom_modify (void_type_node,
5671 result,
5672 ffecom_1 (NEGATE_EXPR,
5673 ltype,
5674 result)));
5675 expand_end_cond ();
5676 expand_start_else ();
5677 }
5678 expand_expr_stmt (ffecom_modify (void_type_node,
5679 result,
5680 convert (ltype, integer_one_node)));
5681 expand_start_cond (ffecom_truth_value
5682 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5683 ffecom_truth_value_invert
5684 (basetypeof_l_is_int),
5685 ffecom_2 (LT_EXPR, integer_type_node,
5686 rtmp,
5687 convert (rtype,
5688 integer_zero_node)))),
5689 0);
5690 expand_expr_stmt (ffecom_modify (void_type_node,
5691 ltmp,
5692 ffecom_tree_divide_
5693 (ltype,
5694 convert (ltype, integer_one_node),
5695 ltmp,
5696 NULL_TREE, NULL, NULL,
5697 divide)));
5698 expand_expr_stmt (ffecom_modify (void_type_node,
5699 rtmp,
5700 ffecom_1 (NEGATE_EXPR, rtype,
5701 rtmp)));
5702 expand_start_cond (ffecom_truth_value
5703 (ffecom_2 (LT_EXPR, integer_type_node,
5704 rtmp,
5705 convert (rtype, integer_zero_node))),
5706 0);
5707 expand_expr_stmt (ffecom_modify (void_type_node,
5708 rtmp,
5709 ffecom_1 (NEGATE_EXPR, rtype,
5710 ffecom_2 (RSHIFT_EXPR,
5711 rtype,
5712 rtmp,
5713 integer_one_node))));
5714 expand_expr_stmt (ffecom_modify (void_type_node,
5715 ltmp,
5716 ffecom_2 (MULT_EXPR, ltype,
5717 ltmp,
5718 ltmp)));
5719 expand_end_cond ();
5720 expand_end_cond ();
5721 expand_start_loop (1);
5722 expand_start_cond (ffecom_truth_value
5723 (ffecom_2 (BIT_AND_EXPR, rtype,
5724 rtmp,
5725 convert (rtype, integer_one_node))),
5726 0);
5727 expand_expr_stmt (ffecom_modify (void_type_node,
5728 result,
5729 ffecom_2 (MULT_EXPR, ltype,
5730 result,
5731 ltmp)));
5732 expand_end_cond ();
5733 expand_exit_loop_if_false (NULL,
5734 ffecom_truth_value
5735 (ffecom_modify (rtype,
5736 rtmp,
5737 ffecom_2 (RSHIFT_EXPR,
5738 rtype,
5739 rtmp,
5740 integer_one_node))));
5741 expand_expr_stmt (ffecom_modify (void_type_node,
5742 ltmp,
5743 ffecom_2 (MULT_EXPR, ltype,
5744 ltmp,
5745 ltmp)));
5746 expand_end_loop ();
5747 expand_end_cond ();
5748 if (!integer_zerop (basetypeof_l_is_int))
5749 expand_end_cond ();
5750 expand_expr_stmt (result);
5751
5752 t = ffecom_end_compstmt ();
5753
5754 result = expand_end_stmt_expr (se);
5755
5756 /* This code comes from c-parse.in, after its expand_end_stmt_expr. */
5757
5758 if (TREE_CODE (t) == BLOCK)
5759 {
5760 /* Make a BIND_EXPR for the BLOCK already made. */
5761 result = build (BIND_EXPR, TREE_TYPE (result),
5762 NULL_TREE, result, t);
5763 /* Remove the block from the tree at this point.
5764 It gets put back at the proper place
5765 when the BIND_EXPR is expanded. */
5766 delete_block (t);
5767 }
5768 else
5769 result = t;
5770 }
5771
5772 return result;
5773 }
5774
5775 /* ffecom_expr_transform_ -- Transform symbols in expr
5776
5777 ffebld expr; // FFE expression.
5778 ffecom_expr_transform_ (expr);
5779
5780 Recursive descent on expr while transforming any untransformed SYMTERs. */
5781
5782 static void
ffecom_expr_transform_(ffebld expr)5783 ffecom_expr_transform_ (ffebld expr)
5784 {
5785 tree t;
5786 ffesymbol s;
5787
5788 tail_recurse:
5789
5790 if (expr == NULL)
5791 return;
5792
5793 switch (ffebld_op (expr))
5794 {
5795 case FFEBLD_opSYMTER:
5796 s = ffebld_symter (expr);
5797 t = ffesymbol_hook (s).decl_tree;
5798 if ((t == NULL_TREE)
5799 && ((ffesymbol_kind (s) != FFEINFO_kindNONE)
5800 || ((ffesymbol_where (s) != FFEINFO_whereNONE)
5801 && (ffesymbol_where (s) != FFEINFO_whereINTRINSIC))))
5802 {
5803 s = ffecom_sym_transform_ (s);
5804 t = ffesymbol_hook (s).decl_tree; /* Sfunc expr non-dummy,
5805 DIMENSION expr? */
5806 }
5807 break; /* Ok if (t == NULL) here. */
5808
5809 case FFEBLD_opITEM:
5810 ffecom_expr_transform_ (ffebld_head (expr));
5811 expr = ffebld_trail (expr);
5812 goto tail_recurse; /* :::::::::::::::::::: */
5813
5814 default:
5815 break;
5816 }
5817
5818 switch (ffebld_arity (expr))
5819 {
5820 case 2:
5821 ffecom_expr_transform_ (ffebld_left (expr));
5822 expr = ffebld_right (expr);
5823 goto tail_recurse; /* :::::::::::::::::::: */
5824
5825 case 1:
5826 expr = ffebld_left (expr);
5827 goto tail_recurse; /* :::::::::::::::::::: */
5828
5829 default:
5830 break;
5831 }
5832
5833 return;
5834 }
5835
5836 /* Make a type based on info in live f2c.h file. */
5837
5838 static void
ffecom_f2c_make_type_(tree * type,int tcode,const char * name)5839 ffecom_f2c_make_type_ (tree *type, int tcode, const char *name)
5840 {
5841 switch (tcode)
5842 {
5843 case FFECOM_f2ccodeCHAR:
5844 *type = make_signed_type (CHAR_TYPE_SIZE);
5845 break;
5846
5847 case FFECOM_f2ccodeSHORT:
5848 *type = make_signed_type (SHORT_TYPE_SIZE);
5849 break;
5850
5851 case FFECOM_f2ccodeINT:
5852 *type = make_signed_type (INT_TYPE_SIZE);
5853 break;
5854
5855 case FFECOM_f2ccodeLONG:
5856 *type = make_signed_type (LONG_TYPE_SIZE);
5857 break;
5858
5859 case FFECOM_f2ccodeLONGLONG:
5860 *type = make_signed_type (LONG_LONG_TYPE_SIZE);
5861 break;
5862
5863 case FFECOM_f2ccodeCHARPTR:
5864 *type = build_pointer_type (DEFAULT_SIGNED_CHAR
5865 ? signed_char_type_node
5866 : unsigned_char_type_node);
5867 break;
5868
5869 case FFECOM_f2ccodeFLOAT:
5870 *type = make_node (REAL_TYPE);
5871 TYPE_PRECISION (*type) = FLOAT_TYPE_SIZE;
5872 layout_type (*type);
5873 break;
5874
5875 case FFECOM_f2ccodeDOUBLE:
5876 *type = make_node (REAL_TYPE);
5877 TYPE_PRECISION (*type) = DOUBLE_TYPE_SIZE;
5878 layout_type (*type);
5879 break;
5880
5881 case FFECOM_f2ccodeLONGDOUBLE:
5882 *type = make_node (REAL_TYPE);
5883 TYPE_PRECISION (*type) = LONG_DOUBLE_TYPE_SIZE;
5884 layout_type (*type);
5885 break;
5886
5887 case FFECOM_f2ccodeTWOREALS:
5888 *type = ffecom_make_complex_type_ (ffecom_f2c_real_type_node);
5889 break;
5890
5891 case FFECOM_f2ccodeTWODOUBLEREALS:
5892 *type = ffecom_make_complex_type_ (ffecom_f2c_doublereal_type_node);
5893 break;
5894
5895 default:
5896 assert ("unexpected FFECOM_f2ccodeXYZZY!" == NULL);
5897 *type = error_mark_node;
5898 return;
5899 }
5900
5901 pushdecl (build_decl (TYPE_DECL,
5902 ffecom_get_invented_identifier ("__g77_f2c_%s", name),
5903 *type));
5904 }
5905
5906 /* Set the f2c list-directed-I/O code for whatever (integral) type has the
5907 given size. */
5908
5909 static void
ffecom_f2c_set_lio_code_(ffeinfoBasictype bt,int size,int code)5910 ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
5911 int code)
5912 {
5913 int j;
5914 tree t;
5915
5916 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
5917 if ((t = ffecom_tree_type[bt][j]) != NULL_TREE
5918 && compare_tree_int (TYPE_SIZE (t), size) == 0)
5919 {
5920 assert (code != -1);
5921 ffecom_f2c_typecode_[bt][j] = code;
5922 code = -1;
5923 }
5924 }
5925
5926 /* Finish up globals after doing all program units in file
5927
5928 Need to handle only uninitialized COMMON areas. */
5929
5930 static ffeglobal
ffecom_finish_global_(ffeglobal global)5931 ffecom_finish_global_ (ffeglobal global)
5932 {
5933 tree cbtype;
5934 tree cbt;
5935 tree size;
5936
5937 if (ffeglobal_type (global) != FFEGLOBAL_typeCOMMON)
5938 return global;
5939
5940 if (ffeglobal_common_init (global))
5941 return global;
5942
5943 cbt = ffeglobal_hook (global);
5944 if ((cbt == NULL_TREE)
5945 || !ffeglobal_common_have_size (global))
5946 return global; /* No need to make common, never ref'd. */
5947
5948 DECL_EXTERNAL (cbt) = 0;
5949
5950 /* Give the array a size now. */
5951
5952 size = build_int_2 ((ffeglobal_common_size (global)
5953 + ffeglobal_common_pad (global)) - 1,
5954 0);
5955
5956 cbtype = TREE_TYPE (cbt);
5957 TYPE_DOMAIN (cbtype) = build_range_type (integer_type_node,
5958 integer_zero_node,
5959 size);
5960 if (!TREE_TYPE (size))
5961 TREE_TYPE (size) = TYPE_DOMAIN (cbtype);
5962 layout_type (cbtype);
5963
5964 cbt = start_decl (cbt, FALSE);
5965 assert (cbt == ffeglobal_hook (global));
5966
5967 finish_decl (cbt, NULL_TREE, FALSE);
5968
5969 return global;
5970 }
5971
5972 /* Finish up any untransformed symbols. */
5973
5974 static ffesymbol
ffecom_finish_symbol_transform_(ffesymbol s)5975 ffecom_finish_symbol_transform_ (ffesymbol s)
5976 {
5977 if ((s == NULL) || (TREE_CODE (current_function_decl) == ERROR_MARK))
5978 return s;
5979
5980 /* It's easy to know to transform an untransformed symbol, to make sure
5981 we put out debugging info for it. But COMMON variables, unlike
5982 EQUIVALENCE ones, aren't given declarations in addition to the
5983 tree expressions that specify offsets, because COMMON variables
5984 can be referenced in the outer scope where only dummy arguments
5985 (PARM_DECLs) should really be seen. To be safe, just don't do any
5986 VAR_DECLs for COMMON variables when we transform them for real
5987 use, and therefore we do all the VAR_DECL creating here. */
5988
5989 if (ffesymbol_hook (s).decl_tree == NULL_TREE)
5990 {
5991 if (ffesymbol_kind (s) != FFEINFO_kindNONE
5992 || (ffesymbol_where (s) != FFEINFO_whereNONE
5993 && ffesymbol_where (s) != FFEINFO_whereINTRINSIC
5994 && ffesymbol_where (s) != FFEINFO_whereDUMMY))
5995 /* Not transformed, and not CHARACTER*(*), and not a dummy
5996 argument, which can happen only if the entry point names
5997 it "rides in on" are all invalidated for other reasons. */
5998 s = ffecom_sym_transform_ (s);
5999 }
6000
6001 if ((ffesymbol_where (s) == FFEINFO_whereCOMMON)
6002 && (ffesymbol_hook (s).decl_tree != error_mark_node))
6003 {
6004 /* This isn't working, at least for dbxout. The .s file looks
6005 okay to me (burley), but in gdb 4.9 at least, the variables
6006 appear to reside somewhere outside of the common area, so
6007 it doesn't make sense to mislead anyone by generating the info
6008 on those variables until this is fixed. NOTE: Same problem
6009 with EQUIVALENCE, sadly...see similar #if later. */
6010 ffecom_member_phase2_ (ffesymbol_storage (ffesymbol_common (s)),
6011 ffesymbol_storage (s));
6012 }
6013
6014 return s;
6015 }
6016
6017 /* Append underscore(s) to name before calling get_identifier. "us"
6018 is nonzero if the name already contains an underscore and thus
6019 needs two underscores appended. */
6020
6021 static tree
ffecom_get_appended_identifier_(char us,const char * name)6022 ffecom_get_appended_identifier_ (char us, const char *name)
6023 {
6024 int i;
6025 char *newname;
6026 tree id;
6027
6028 newname = xmalloc ((i = strlen (name)) + 1
6029 + ffe_is_underscoring ()
6030 + us);
6031 memcpy (newname, name, i);
6032 newname[i] = '_';
6033 newname[i + us] = '_';
6034 newname[i + 1 + us] = '\0';
6035 id = get_identifier (newname);
6036
6037 free (newname);
6038
6039 return id;
6040 }
6041
6042 /* Decide whether to append underscore to name before calling
6043 get_identifier. */
6044
6045 static tree
ffecom_get_external_identifier_(ffesymbol s)6046 ffecom_get_external_identifier_ (ffesymbol s)
6047 {
6048 char us;
6049 const char *name = ffesymbol_text (s);
6050
6051 /* If name is a built-in name, just return it as is. */
6052
6053 if (!ffe_is_underscoring ()
6054 || (strcmp (name, FFETARGET_nameBLANK_COMMON) == 0)
6055 #if FFETARGET_isENFORCED_MAIN_NAME
6056 || (strcmp (name, FFETARGET_nameENFORCED_NAME) == 0)
6057 #else
6058 || (strcmp (name, FFETARGET_nameUNNAMED_MAIN) == 0)
6059 #endif
6060 || (strcmp (name, FFETARGET_nameUNNAMED_BLOCK_DATA) == 0))
6061 return get_identifier (name);
6062
6063 us = ffe_is_second_underscore ()
6064 ? (strchr (name, '_') != NULL)
6065 : 0;
6066
6067 return ffecom_get_appended_identifier_ (us, name);
6068 }
6069
6070 /* Decide whether to append underscore to internal name before calling
6071 get_identifier.
6072
6073 This is for non-external, top-function-context names only. Transform
6074 identifier so it doesn't conflict with the transformed result
6075 of using a _different_ external name. E.g. if "CALL FOO" is
6076 transformed into "FOO_();", then the variable in "FOO_ = 3"
6077 must be transformed into something that does not conflict, since
6078 these two things should be independent.
6079
6080 The transformation is as follows. If the name does not contain
6081 an underscore, there is no possible conflict, so just return.
6082 If the name does contain an underscore, then transform it just
6083 like we transform an external identifier. */
6084
6085 static tree
ffecom_get_identifier_(const char * name)6086 ffecom_get_identifier_ (const char *name)
6087 {
6088 /* If name does not contain an underscore, just return it as is. */
6089
6090 if (!ffe_is_underscoring ()
6091 || (strchr (name, '_') == NULL))
6092 return get_identifier (name);
6093
6094 return ffecom_get_appended_identifier_ (ffe_is_second_underscore (),
6095 name);
6096 }
6097
6098 /* ffecom_gen_sfuncdef_ -- Generate definition of statement function
6099
6100 tree t;
6101 ffesymbol s; // kindFUNCTION, whereIMMEDIATE.
6102 t = ffecom_gen_sfuncdef_(s,ffesymbol_basictype(s),
6103 ffesymbol_kindtype(s));
6104
6105 Call after setting up containing function and getting trees for all
6106 other symbols. */
6107
6108 static tree
ffecom_gen_sfuncdef_(ffesymbol s,ffeinfoBasictype bt,ffeinfoKindtype kt)6109 ffecom_gen_sfuncdef_ (ffesymbol s, ffeinfoBasictype bt, ffeinfoKindtype kt)
6110 {
6111 ffebld expr = ffesymbol_sfexpr (s);
6112 tree type;
6113 tree func;
6114 tree result;
6115 bool charfunc = (bt == FFEINFO_basictypeCHARACTER);
6116 static bool recurse = FALSE;
6117 int old_lineno = lineno;
6118 const char *old_input_filename = input_filename;
6119
6120 ffecom_nested_entry_ = s;
6121
6122 /* For now, we don't have a handy pointer to where the sfunc is actually
6123 defined, though that should be easy to add to an ffesymbol. (The
6124 token/where info available might well point to the place where the type
6125 of the sfunc is declared, especially if that precedes the place where
6126 the sfunc itself is defined, which is typically the case.) We should
6127 put out a null pointer rather than point somewhere wrong, but I want to
6128 see how it works at this point. */
6129
6130 input_filename = ffesymbol_where_filename (s);
6131 lineno = ffesymbol_where_filelinenum (s);
6132
6133 /* Pretransform the expression so any newly discovered things belong to the
6134 outer program unit, not to the statement function. */
6135
6136 ffecom_expr_transform_ (expr);
6137
6138 /* Make sure no recursive invocation of this fn (a specific case of failing
6139 to pretransform an sfunc's expression, i.e. where its expression
6140 references another untransformed sfunc) happens. */
6141
6142 assert (!recurse);
6143 recurse = TRUE;
6144
6145 push_f_function_context ();
6146
6147 if (charfunc)
6148 type = void_type_node;
6149 else
6150 {
6151 type = ffecom_tree_type[bt][kt];
6152 if (type == NULL_TREE)
6153 type = integer_type_node; /* _sym_exec_transition reports
6154 error. */
6155 }
6156
6157 start_function (ffecom_get_identifier_ (ffesymbol_text (s)),
6158 build_function_type (type, NULL_TREE),
6159 1, /* nested/inline */
6160 0); /* TREE_PUBLIC */
6161
6162 /* We don't worry about COMPLEX return values here, because this is
6163 entirely internal to our code, and gcc has the ability to return COMPLEX
6164 directly as a value. */
6165
6166 if (charfunc)
6167 { /* Prepend arg for where result goes. */
6168 tree type;
6169
6170 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
6171
6172 result = ffecom_get_invented_identifier ("__g77_%s", "result");
6173
6174 ffecom_char_enhance_arg_ (&type, s); /* Ignore returned length. */
6175
6176 type = build_pointer_type (type);
6177 result = build_decl (PARM_DECL, result, type);
6178
6179 push_parm_decl (result);
6180 }
6181 else
6182 result = NULL_TREE; /* Not ref'd if !charfunc. */
6183
6184 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (s), TRUE);
6185
6186 store_parm_decls (0);
6187
6188 ffecom_start_compstmt ();
6189
6190 if (expr != NULL)
6191 {
6192 if (charfunc)
6193 {
6194 ffetargetCharacterSize sz = ffesymbol_size (s);
6195 tree result_length;
6196
6197 result_length = build_int_2 (sz, 0);
6198 TREE_TYPE (result_length) = ffecom_f2c_ftnlen_type_node;
6199
6200 ffecom_prepare_let_char_ (sz, expr);
6201
6202 ffecom_prepare_end ();
6203
6204 ffecom_let_char_ (result, result_length, sz, expr);
6205 expand_null_return ();
6206 }
6207 else
6208 {
6209 ffecom_prepare_expr (expr);
6210
6211 ffecom_prepare_end ();
6212
6213 expand_return (ffecom_modify (NULL_TREE,
6214 DECL_RESULT (current_function_decl),
6215 ffecom_expr (expr)));
6216 }
6217 }
6218
6219 ffecom_end_compstmt ();
6220
6221 func = current_function_decl;
6222 finish_function (1);
6223
6224 pop_f_function_context ();
6225
6226 recurse = FALSE;
6227
6228 lineno = old_lineno;
6229 input_filename = old_input_filename;
6230
6231 ffecom_nested_entry_ = NULL;
6232
6233 return func;
6234 }
6235
6236 static const char *
ffecom_gfrt_args_(ffecomGfrt ix)6237 ffecom_gfrt_args_ (ffecomGfrt ix)
6238 {
6239 return ffecom_gfrt_argstring_[ix];
6240 }
6241
6242 static tree
ffecom_gfrt_tree_(ffecomGfrt ix)6243 ffecom_gfrt_tree_ (ffecomGfrt ix)
6244 {
6245 if (ffecom_gfrt_[ix] == NULL_TREE)
6246 ffecom_make_gfrt_ (ix);
6247
6248 return ffecom_1 (ADDR_EXPR,
6249 build_pointer_type (TREE_TYPE (ffecom_gfrt_[ix])),
6250 ffecom_gfrt_[ix]);
6251 }
6252
6253 /* Return initialize-to-zero expression for this VAR_DECL. */
6254
6255 /* A somewhat evil way to prevent the garbage collector
6256 from collecting 'tree' structures. */
6257 #define NUM_TRACKED_CHUNK 63
6258 struct tree_ggc_tracker GTY(())
6259 {
6260 struct tree_ggc_tracker *next;
6261 tree trees[NUM_TRACKED_CHUNK];
6262 };
6263 static GTY(()) struct tree_ggc_tracker *tracker_head;
6264
6265 void
ffecom_save_tree_forever(tree t)6266 ffecom_save_tree_forever (tree t)
6267 {
6268 int i;
6269 if (tracker_head != NULL)
6270 for (i = 0; i < NUM_TRACKED_CHUNK; i++)
6271 if (tracker_head->trees[i] == NULL)
6272 {
6273 tracker_head->trees[i] = t;
6274 return;
6275 }
6276
6277 {
6278 /* Need to allocate a new block. */
6279 struct tree_ggc_tracker *old_head = tracker_head;
6280
6281 tracker_head = ggc_alloc (sizeof (*tracker_head));
6282 tracker_head->next = old_head;
6283 tracker_head->trees[0] = t;
6284 for (i = 1; i < NUM_TRACKED_CHUNK; i++)
6285 tracker_head->trees[i] = NULL;
6286 }
6287 }
6288
6289 static tree
ffecom_init_zero_(tree decl)6290 ffecom_init_zero_ (tree decl)
6291 {
6292 tree init;
6293 int incremental = TREE_STATIC (decl);
6294 tree type = TREE_TYPE (decl);
6295
6296 if (incremental)
6297 {
6298 make_decl_rtl (decl, NULL);
6299 assemble_variable (decl, TREE_PUBLIC (decl) ? 1 : 0, 0, 1);
6300 }
6301
6302 if ((TREE_CODE (type) != ARRAY_TYPE)
6303 && (TREE_CODE (type) != RECORD_TYPE)
6304 && (TREE_CODE (type) != UNION_TYPE)
6305 && !incremental)
6306 init = convert (type, integer_zero_node);
6307 else if (!incremental)
6308 {
6309 init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
6310 TREE_CONSTANT (init) = 1;
6311 TREE_STATIC (init) = 1;
6312 }
6313 else
6314 {
6315 assemble_zeros (int_size_in_bytes (type));
6316 init = error_mark_node;
6317 }
6318
6319 return init;
6320 }
6321
6322 static tree
ffecom_intrinsic_ichar_(tree tree_type,ffebld arg,tree * maybe_tree)6323 ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
6324 tree *maybe_tree)
6325 {
6326 tree expr_tree;
6327 tree length_tree;
6328
6329 switch (ffebld_op (arg))
6330 {
6331 case FFEBLD_opCONTER: /* For F90, check 0-length. */
6332 if (ffetarget_length_character1
6333 (ffebld_constant_character1
6334 (ffebld_conter (arg))) == 0)
6335 {
6336 *maybe_tree = integer_zero_node;
6337 return convert (tree_type, integer_zero_node);
6338 }
6339
6340 *maybe_tree = integer_one_node;
6341 expr_tree = build_int_2 (*ffetarget_text_character1
6342 (ffebld_constant_character1
6343 (ffebld_conter (arg))),
6344 0);
6345 TREE_TYPE (expr_tree) = tree_type;
6346 return expr_tree;
6347
6348 case FFEBLD_opSYMTER:
6349 case FFEBLD_opARRAYREF:
6350 case FFEBLD_opFUNCREF:
6351 case FFEBLD_opSUBSTR:
6352 ffecom_char_args_ (&expr_tree, &length_tree, arg);
6353
6354 if ((expr_tree == error_mark_node)
6355 || (length_tree == error_mark_node))
6356 {
6357 *maybe_tree = error_mark_node;
6358 return error_mark_node;
6359 }
6360
6361 if (integer_zerop (length_tree))
6362 {
6363 *maybe_tree = integer_zero_node;
6364 return convert (tree_type, integer_zero_node);
6365 }
6366
6367 expr_tree
6368 = ffecom_1 (INDIRECT_REF,
6369 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6370 expr_tree);
6371 expr_tree
6372 = ffecom_2 (ARRAY_REF,
6373 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6374 expr_tree,
6375 integer_one_node);
6376 expr_tree = convert (tree_type, expr_tree);
6377
6378 if (TREE_CODE (length_tree) == INTEGER_CST)
6379 *maybe_tree = integer_one_node;
6380 else /* Must check length at run time. */
6381 *maybe_tree
6382 = ffecom_truth_value
6383 (ffecom_2 (GT_EXPR, integer_type_node,
6384 length_tree,
6385 ffecom_f2c_ftnlen_zero_node));
6386 return expr_tree;
6387
6388 case FFEBLD_opPAREN:
6389 case FFEBLD_opCONVERT:
6390 if (ffeinfo_size (ffebld_info (arg)) == 0)
6391 {
6392 *maybe_tree = integer_zero_node;
6393 return convert (tree_type, integer_zero_node);
6394 }
6395 return ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6396 maybe_tree);
6397
6398 case FFEBLD_opCONCATENATE:
6399 {
6400 tree maybe_left;
6401 tree maybe_right;
6402 tree expr_left;
6403 tree expr_right;
6404
6405 expr_left = ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6406 &maybe_left);
6407 expr_right = ffecom_intrinsic_ichar_ (tree_type, ffebld_right (arg),
6408 &maybe_right);
6409 *maybe_tree = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
6410 maybe_left,
6411 maybe_right);
6412 expr_tree = ffecom_3 (COND_EXPR, tree_type,
6413 maybe_left,
6414 expr_left,
6415 expr_right);
6416 return expr_tree;
6417 }
6418
6419 default:
6420 assert ("bad op in ICHAR" == NULL);
6421 return error_mark_node;
6422 }
6423 }
6424
6425 /* ffecom_intrinsic_len_ -- Return length info for char arg (LEN())
6426
6427 tree length_arg;
6428 ffebld expr;
6429 length_arg = ffecom_intrinsic_len_ (expr);
6430
6431 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
6432 subexpressions by constructing the appropriate tree for the
6433 length-of-character-text argument in a calling sequence. */
6434
6435 static tree
ffecom_intrinsic_len_(ffebld expr)6436 ffecom_intrinsic_len_ (ffebld expr)
6437 {
6438 ffetargetCharacter1 val;
6439 tree length;
6440
6441 switch (ffebld_op (expr))
6442 {
6443 case FFEBLD_opCONTER:
6444 val = ffebld_constant_character1 (ffebld_conter (expr));
6445 length = build_int_2 (ffetarget_length_character1 (val), 0);
6446 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6447 break;
6448
6449 case FFEBLD_opSYMTER:
6450 {
6451 ffesymbol s = ffebld_symter (expr);
6452 tree item;
6453
6454 item = ffesymbol_hook (s).decl_tree;
6455 if (item == NULL_TREE)
6456 {
6457 s = ffecom_sym_transform_ (s);
6458 item = ffesymbol_hook (s).decl_tree;
6459 }
6460 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
6461 {
6462 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
6463 length = ffesymbol_hook (s).length_tree;
6464 else
6465 {
6466 length = build_int_2 (ffesymbol_size (s), 0);
6467 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6468 }
6469 }
6470 else if (item == error_mark_node)
6471 length = error_mark_node;
6472 else /* FFEINFO_kindFUNCTION: */
6473 length = NULL_TREE;
6474 }
6475 break;
6476
6477 case FFEBLD_opARRAYREF:
6478 length = ffecom_intrinsic_len_ (ffebld_left (expr));
6479 break;
6480
6481 case FFEBLD_opSUBSTR:
6482 {
6483 ffebld start;
6484 ffebld end;
6485 ffebld thing = ffebld_right (expr);
6486 tree start_tree;
6487 tree end_tree;
6488
6489 assert (ffebld_op (thing) == FFEBLD_opITEM);
6490 start = ffebld_head (thing);
6491 thing = ffebld_trail (thing);
6492 assert (ffebld_trail (thing) == NULL);
6493 end = ffebld_head (thing);
6494
6495 length = ffecom_intrinsic_len_ (ffebld_left (expr));
6496
6497 if (length == error_mark_node)
6498 break;
6499
6500 if (start == NULL)
6501 {
6502 if (end == NULL)
6503 ;
6504 else
6505 {
6506 length = convert (ffecom_f2c_ftnlen_type_node,
6507 ffecom_expr (end));
6508 }
6509 }
6510 else
6511 {
6512 start_tree = convert (ffecom_f2c_ftnlen_type_node,
6513 ffecom_expr (start));
6514
6515 if (start_tree == error_mark_node)
6516 {
6517 length = error_mark_node;
6518 break;
6519 }
6520
6521 if (end == NULL)
6522 {
6523 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6524 ffecom_f2c_ftnlen_one_node,
6525 ffecom_2 (MINUS_EXPR,
6526 ffecom_f2c_ftnlen_type_node,
6527 length,
6528 start_tree));
6529 }
6530 else
6531 {
6532 end_tree = convert (ffecom_f2c_ftnlen_type_node,
6533 ffecom_expr (end));
6534
6535 if (end_tree == error_mark_node)
6536 {
6537 length = error_mark_node;
6538 break;
6539 }
6540
6541 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6542 ffecom_f2c_ftnlen_one_node,
6543 ffecom_2 (MINUS_EXPR,
6544 ffecom_f2c_ftnlen_type_node,
6545 end_tree, start_tree));
6546 }
6547 }
6548 }
6549 break;
6550
6551 case FFEBLD_opCONCATENATE:
6552 length
6553 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6554 ffecom_intrinsic_len_ (ffebld_left (expr)),
6555 ffecom_intrinsic_len_ (ffebld_right (expr)));
6556 break;
6557
6558 case FFEBLD_opFUNCREF:
6559 case FFEBLD_opCONVERT:
6560 length = build_int_2 (ffebld_size (expr), 0);
6561 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6562 break;
6563
6564 default:
6565 assert ("bad op for single char arg expr" == NULL);
6566 length = ffecom_f2c_ftnlen_zero_node;
6567 break;
6568 }
6569
6570 assert (length != NULL_TREE);
6571
6572 return length;
6573 }
6574
6575 /* Handle CHARACTER assignments.
6576
6577 Generates code to do the assignment. Used by ordinary assignment
6578 statement handler ffecom_let_stmt and by statement-function
6579 handler to generate code for a statement function. */
6580
6581 static void
ffecom_let_char_(tree dest_tree,tree dest_length,ffetargetCharacterSize dest_size,ffebld source)6582 ffecom_let_char_ (tree dest_tree, tree dest_length,
6583 ffetargetCharacterSize dest_size, ffebld source)
6584 {
6585 ffecomConcatList_ catlist;
6586 tree source_length;
6587 tree source_tree;
6588 tree expr_tree;
6589
6590 if ((dest_tree == error_mark_node)
6591 || (dest_length == error_mark_node))
6592 return;
6593
6594 assert (dest_tree != NULL_TREE);
6595 assert (dest_length != NULL_TREE);
6596
6597 /* Source might be an opCONVERT, which just means it is a different size
6598 than the destination. Since the underlying implementation here handles
6599 that (directly or via the s_copy or s_cat run-time-library functions),
6600 we don't need the "convenience" of an opCONVERT that tells us to
6601 truncate or blank-pad, particularly since the resulting implementation
6602 would probably be slower than otherwise. */
6603
6604 while (ffebld_op (source) == FFEBLD_opCONVERT)
6605 source = ffebld_left (source);
6606
6607 catlist = ffecom_concat_list_new_ (source, dest_size);
6608 switch (ffecom_concat_list_count_ (catlist))
6609 {
6610 case 0: /* Shouldn't happen, but in case it does... */
6611 ffecom_concat_list_kill_ (catlist);
6612 source_tree = null_pointer_node;
6613 source_length = ffecom_f2c_ftnlen_zero_node;
6614 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6615 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6616 TREE_CHAIN (TREE_CHAIN (expr_tree))
6617 = build_tree_list (NULL_TREE, dest_length);
6618 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6619 = build_tree_list (NULL_TREE, source_length);
6620
6621 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6622 TREE_SIDE_EFFECTS (expr_tree) = 1;
6623
6624 expand_expr_stmt (expr_tree);
6625
6626 return;
6627
6628 case 1: /* The (fairly) easy case. */
6629 ffecom_char_args_ (&source_tree, &source_length,
6630 ffecom_concat_list_expr_ (catlist, 0));
6631 ffecom_concat_list_kill_ (catlist);
6632 assert (source_tree != NULL_TREE);
6633 assert (source_length != NULL_TREE);
6634
6635 if ((source_tree == error_mark_node)
6636 || (source_length == error_mark_node))
6637 return;
6638
6639 if (dest_size == 1)
6640 {
6641 dest_tree
6642 = ffecom_1 (INDIRECT_REF,
6643 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6644 (dest_tree))),
6645 dest_tree);
6646 dest_tree
6647 = ffecom_2 (ARRAY_REF,
6648 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6649 (dest_tree))),
6650 dest_tree,
6651 integer_one_node);
6652 source_tree
6653 = ffecom_1 (INDIRECT_REF,
6654 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6655 (source_tree))),
6656 source_tree);
6657 source_tree
6658 = ffecom_2 (ARRAY_REF,
6659 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6660 (source_tree))),
6661 source_tree,
6662 integer_one_node);
6663
6664 expr_tree = ffecom_modify (void_type_node, dest_tree, source_tree);
6665
6666 expand_expr_stmt (expr_tree);
6667
6668 return;
6669 }
6670
6671 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6672 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6673 TREE_CHAIN (TREE_CHAIN (expr_tree))
6674 = build_tree_list (NULL_TREE, dest_length);
6675 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6676 = build_tree_list (NULL_TREE, source_length);
6677
6678 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6679 TREE_SIDE_EFFECTS (expr_tree) = 1;
6680
6681 expand_expr_stmt (expr_tree);
6682
6683 return;
6684
6685 default: /* Must actually concatenate things. */
6686 break;
6687 }
6688
6689 /* Heavy-duty concatenation. */
6690
6691 {
6692 int count = ffecom_concat_list_count_ (catlist);
6693 int i;
6694 tree lengths;
6695 tree items;
6696 tree length_array;
6697 tree item_array;
6698 tree citem;
6699 tree clength;
6700
6701 {
6702 tree hook;
6703
6704 hook = ffebld_nonter_hook (source);
6705 assert (hook);
6706 assert (TREE_CODE (hook) == TREE_VEC);
6707 assert (TREE_VEC_LENGTH (hook) == 2);
6708 length_array = lengths = TREE_VEC_ELT (hook, 0);
6709 item_array = items = TREE_VEC_ELT (hook, 1);
6710 }
6711
6712 for (i = 0; i < count; ++i)
6713 {
6714 ffecom_char_args_ (&citem, &clength,
6715 ffecom_concat_list_expr_ (catlist, i));
6716 if ((citem == error_mark_node)
6717 || (clength == error_mark_node))
6718 {
6719 ffecom_concat_list_kill_ (catlist);
6720 return;
6721 }
6722
6723 items
6724 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
6725 ffecom_modify (void_type_node,
6726 ffecom_2 (ARRAY_REF,
6727 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
6728 item_array,
6729 build_int_2 (i, 0)),
6730 citem),
6731 items);
6732 lengths
6733 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
6734 ffecom_modify (void_type_node,
6735 ffecom_2 (ARRAY_REF,
6736 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
6737 length_array,
6738 build_int_2 (i, 0)),
6739 clength),
6740 lengths);
6741 }
6742
6743 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6744 TREE_CHAIN (expr_tree)
6745 = build_tree_list (NULL_TREE,
6746 ffecom_1 (ADDR_EXPR,
6747 build_pointer_type (TREE_TYPE (items)),
6748 items));
6749 TREE_CHAIN (TREE_CHAIN (expr_tree))
6750 = build_tree_list (NULL_TREE,
6751 ffecom_1 (ADDR_EXPR,
6752 build_pointer_type (TREE_TYPE (lengths)),
6753 lengths));
6754 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6755 = build_tree_list
6756 (NULL_TREE,
6757 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
6758 convert (ffecom_f2c_ftnlen_type_node,
6759 build_int_2 (count, 0))));
6760 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree))))
6761 = build_tree_list (NULL_TREE, dest_length);
6762
6763 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCAT, expr_tree, NULL_TREE);
6764 TREE_SIDE_EFFECTS (expr_tree) = 1;
6765
6766 expand_expr_stmt (expr_tree);
6767 }
6768
6769 ffecom_concat_list_kill_ (catlist);
6770 }
6771
6772 /* ffecom_make_gfrt_ -- Make initial info for run-time routine
6773
6774 ffecomGfrt ix;
6775 ffecom_make_gfrt_(ix);
6776
6777 Assumes gfrt_[ix] is NULL_TREE, and replaces it with the FUNCTION_DECL
6778 for the indicated run-time routine (ix). */
6779
6780 static void
ffecom_make_gfrt_(ffecomGfrt ix)6781 ffecom_make_gfrt_ (ffecomGfrt ix)
6782 {
6783 tree t;
6784 tree ttype;
6785
6786 switch (ffecom_gfrt_type_[ix])
6787 {
6788 case FFECOM_rttypeVOID_:
6789 ttype = void_type_node;
6790 break;
6791
6792 case FFECOM_rttypeVOIDSTAR_:
6793 ttype = TREE_TYPE (null_pointer_node); /* `void *'. */
6794 break;
6795
6796 case FFECOM_rttypeFTNINT_:
6797 ttype = ffecom_f2c_ftnint_type_node;
6798 break;
6799
6800 case FFECOM_rttypeINTEGER_:
6801 ttype = ffecom_f2c_integer_type_node;
6802 break;
6803
6804 case FFECOM_rttypeLONGINT_:
6805 ttype = ffecom_f2c_longint_type_node;
6806 break;
6807
6808 case FFECOM_rttypeLOGICAL_:
6809 ttype = ffecom_f2c_logical_type_node;
6810 break;
6811
6812 case FFECOM_rttypeREAL_F2C_:
6813 ttype = double_type_node;
6814 break;
6815
6816 case FFECOM_rttypeREAL_GNU_:
6817 ttype = float_type_node;
6818 break;
6819
6820 case FFECOM_rttypeCOMPLEX_F2C_:
6821 ttype = void_type_node;
6822 break;
6823
6824 case FFECOM_rttypeCOMPLEX_GNU_:
6825 ttype = ffecom_f2c_complex_type_node;
6826 break;
6827
6828 case FFECOM_rttypeDOUBLE_:
6829 ttype = double_type_node;
6830 break;
6831
6832 case FFECOM_rttypeDOUBLEREAL_:
6833 ttype = ffecom_f2c_doublereal_type_node;
6834 break;
6835
6836 case FFECOM_rttypeDBLCMPLX_F2C_:
6837 ttype = void_type_node;
6838 break;
6839
6840 case FFECOM_rttypeDBLCMPLX_GNU_:
6841 ttype = ffecom_f2c_doublecomplex_type_node;
6842 break;
6843
6844 case FFECOM_rttypeCHARACTER_:
6845 ttype = void_type_node;
6846 break;
6847
6848 default:
6849 ttype = NULL;
6850 assert ("bad rttype" == NULL);
6851 break;
6852 }
6853
6854 ttype = build_function_type (ttype, NULL_TREE);
6855 t = build_decl (FUNCTION_DECL,
6856 get_identifier (ffecom_gfrt_name_[ix]),
6857 ttype);
6858 DECL_EXTERNAL (t) = 1;
6859 TREE_READONLY (t) = ffecom_gfrt_const_[ix] ? 1 : 0;
6860 TREE_PUBLIC (t) = 1;
6861 TREE_THIS_VOLATILE (t) = ffecom_gfrt_volatile_[ix] ? 1 : 0;
6862
6863 /* Sanity check: A function that's const cannot be volatile. */
6864
6865 assert (ffecom_gfrt_const_[ix] ? !ffecom_gfrt_volatile_[ix] : 1);
6866
6867 /* Sanity check: A function that's const cannot return complex. */
6868
6869 assert (ffecom_gfrt_const_[ix] ? !ffecom_gfrt_complex_[ix] : 1);
6870
6871 t = start_decl (t, TRUE);
6872
6873 finish_decl (t, NULL_TREE, TRUE);
6874
6875 ffecom_gfrt_[ix] = t;
6876 }
6877
6878 /* Phase 1 pass over each member of a COMMON/EQUIVALENCE group. */
6879
6880 static void
ffecom_member_phase1_(ffestorag mst UNUSED,ffestorag st)6881 ffecom_member_phase1_ (ffestorag mst UNUSED, ffestorag st)
6882 {
6883 ffesymbol s = ffestorag_symbol (st);
6884
6885 if (ffesymbol_namelisted (s))
6886 ffecom_member_namelisted_ = TRUE;
6887 }
6888
6889 /* Phase 2 pass over each member of a COMMON/EQUIVALENCE group. Declare
6890 the member so debugger will see it. Otherwise nobody should be
6891 referencing the member. */
6892
6893 static void
ffecom_member_phase2_(ffestorag mst,ffestorag st)6894 ffecom_member_phase2_ (ffestorag mst, ffestorag st)
6895 {
6896 ffesymbol s;
6897 tree t;
6898 tree mt;
6899 tree type;
6900
6901 if ((mst == NULL)
6902 || ((mt = ffestorag_hook (mst)) == NULL)
6903 || (mt == error_mark_node))
6904 return;
6905
6906 if ((st == NULL)
6907 || ((s = ffestorag_symbol (st)) == NULL))
6908 return;
6909
6910 type = ffecom_type_localvar_ (s,
6911 ffesymbol_basictype (s),
6912 ffesymbol_kindtype (s));
6913 if (type == error_mark_node)
6914 return;
6915
6916 t = build_decl (VAR_DECL,
6917 ffecom_get_identifier_ (ffesymbol_text (s)),
6918 type);
6919
6920 TREE_STATIC (t) = TREE_STATIC (mt);
6921 DECL_INITIAL (t) = NULL_TREE;
6922 TREE_ASM_WRITTEN (t) = 1;
6923 TREE_USED (t) = 1;
6924
6925 SET_DECL_RTL (t,
6926 gen_rtx (MEM, TYPE_MODE (type),
6927 plus_constant (XEXP (DECL_RTL (mt), 0),
6928 ffestorag_modulo (mst)
6929 + ffestorag_offset (st)
6930 - ffestorag_offset (mst))));
6931
6932 t = start_decl (t, FALSE);
6933
6934 finish_decl (t, NULL_TREE, FALSE);
6935 }
6936
6937 /* Prepare source expression for assignment into a destination perhaps known
6938 to be of a specific size. */
6939
6940 static void
ffecom_prepare_let_char_(ffetargetCharacterSize dest_size,ffebld source)6941 ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size, ffebld source)
6942 {
6943 ffecomConcatList_ catlist;
6944 int count;
6945 int i;
6946 tree ltmp;
6947 tree itmp;
6948 tree tempvar = NULL_TREE;
6949
6950 while (ffebld_op (source) == FFEBLD_opCONVERT)
6951 source = ffebld_left (source);
6952
6953 catlist = ffecom_concat_list_new_ (source, dest_size);
6954 count = ffecom_concat_list_count_ (catlist);
6955
6956 if (count >= 2)
6957 {
6958 ltmp
6959 = ffecom_make_tempvar ("let_char_len", ffecom_f2c_ftnlen_type_node,
6960 FFETARGET_charactersizeNONE, count);
6961 itmp
6962 = ffecom_make_tempvar ("let_char_item", ffecom_f2c_address_type_node,
6963 FFETARGET_charactersizeNONE, count);
6964
6965 tempvar = make_tree_vec (2);
6966 TREE_VEC_ELT (tempvar, 0) = ltmp;
6967 TREE_VEC_ELT (tempvar, 1) = itmp;
6968 }
6969
6970 for (i = 0; i < count; ++i)
6971 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist, i));
6972
6973 ffecom_concat_list_kill_ (catlist);
6974
6975 if (tempvar)
6976 {
6977 ffebld_nonter_set_hook (source, tempvar);
6978 current_binding_level->prep_state = 1;
6979 }
6980 }
6981
6982 /* ffecom_push_dummy_decls_ -- Transform dummy args, push parm decls in order
6983
6984 Ignores STAR (alternate-return) dummies. All other get exec-transitioned
6985 (which generates their trees) and then their trees get push_parm_decl'd.
6986
6987 The second arg is TRUE if the dummies are for a statement function, in
6988 which case lengths are not pushed for character arguments (since they are
6989 always known by both the caller and the callee, though the code allows
6990 for someday permitting CHAR*(*) stmtfunc dummies). */
6991
6992 static void
ffecom_push_dummy_decls_(ffebld dummy_list,bool stmtfunc)6993 ffecom_push_dummy_decls_ (ffebld dummy_list, bool stmtfunc)
6994 {
6995 ffebld dummy;
6996 ffebld dumlist;
6997 ffesymbol s;
6998 tree parm;
6999
7000 ffecom_transform_only_dummies_ = TRUE;
7001
7002 /* First push the parms corresponding to actual dummy "contents". */
7003
7004 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7005 {
7006 dummy = ffebld_head (dumlist);
7007 switch (ffebld_op (dummy))
7008 {
7009 case FFEBLD_opSTAR:
7010 case FFEBLD_opANY:
7011 continue; /* Forget alternate returns. */
7012
7013 default:
7014 break;
7015 }
7016 assert (ffebld_op (dummy) == FFEBLD_opSYMTER);
7017 s = ffebld_symter (dummy);
7018 parm = ffesymbol_hook (s).decl_tree;
7019 if (parm == NULL_TREE)
7020 {
7021 s = ffecom_sym_transform_ (s);
7022 parm = ffesymbol_hook (s).decl_tree;
7023 assert (parm != NULL_TREE);
7024 }
7025 if (parm != error_mark_node)
7026 push_parm_decl (parm);
7027 }
7028
7029 /* Then, for CHARACTER dummies, push the parms giving their lengths. */
7030
7031 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7032 {
7033 dummy = ffebld_head (dumlist);
7034 switch (ffebld_op (dummy))
7035 {
7036 case FFEBLD_opSTAR:
7037 case FFEBLD_opANY:
7038 continue; /* Forget alternate returns, they mean
7039 NOTHING! */
7040
7041 default:
7042 break;
7043 }
7044 s = ffebld_symter (dummy);
7045 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
7046 continue; /* Only looking for CHARACTER arguments. */
7047 if (stmtfunc && (ffesymbol_size (s) != FFETARGET_charactersizeNONE))
7048 continue; /* Stmtfunc arg with known size needs no
7049 length param. */
7050 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
7051 continue; /* Only looking for variables and arrays. */
7052 parm = ffesymbol_hook (s).length_tree;
7053 assert (parm != NULL_TREE);
7054 if (parm != error_mark_node)
7055 push_parm_decl (parm);
7056 }
7057
7058 ffecom_transform_only_dummies_ = FALSE;
7059 }
7060
7061 /* ffecom_start_progunit_ -- Beginning of program unit
7062
7063 Does GNU back end stuff necessary to teach it about the start of its
7064 equivalent of a Fortran program unit. */
7065
7066 static void
ffecom_start_progunit_()7067 ffecom_start_progunit_ ()
7068 {
7069 ffesymbol fn = ffecom_primary_entry_;
7070 ffebld arglist;
7071 tree id; /* Identifier (name) of function. */
7072 tree type; /* Type of function. */
7073 tree result; /* Result of function. */
7074 ffeinfoBasictype bt;
7075 ffeinfoKindtype kt;
7076 ffeglobal g;
7077 ffeglobalType gt;
7078 ffeglobalType egt = FFEGLOBAL_type;
7079 bool charfunc;
7080 bool cmplxfunc;
7081 bool altentries = (ffecom_num_entrypoints_ != 0);
7082 bool multi
7083 = altentries
7084 && (ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
7085 && (ffecom_master_bt_ == FFEINFO_basictypeNONE);
7086 bool main_program = FALSE;
7087 int old_lineno = lineno;
7088 const char *old_input_filename = input_filename;
7089
7090 assert (fn != NULL);
7091 assert (ffesymbol_hook (fn).decl_tree == NULL_TREE);
7092
7093 input_filename = ffesymbol_where_filename (fn);
7094 lineno = ffesymbol_where_filelinenum (fn);
7095
7096 switch (ffecom_primary_entry_kind_)
7097 {
7098 case FFEINFO_kindPROGRAM:
7099 main_program = TRUE;
7100 gt = FFEGLOBAL_typeMAIN;
7101 bt = FFEINFO_basictypeNONE;
7102 kt = FFEINFO_kindtypeNONE;
7103 type = ffecom_tree_fun_type_void;
7104 charfunc = FALSE;
7105 cmplxfunc = FALSE;
7106 break;
7107
7108 case FFEINFO_kindBLOCKDATA:
7109 gt = FFEGLOBAL_typeBDATA;
7110 bt = FFEINFO_basictypeNONE;
7111 kt = FFEINFO_kindtypeNONE;
7112 type = ffecom_tree_fun_type_void;
7113 charfunc = FALSE;
7114 cmplxfunc = FALSE;
7115 break;
7116
7117 case FFEINFO_kindFUNCTION:
7118 gt = FFEGLOBAL_typeFUNC;
7119 egt = FFEGLOBAL_typeEXT;
7120 bt = ffesymbol_basictype (fn);
7121 kt = ffesymbol_kindtype (fn);
7122 if (bt == FFEINFO_basictypeNONE)
7123 {
7124 ffeimplic_establish_symbol (fn);
7125 if (ffesymbol_funcresult (fn) != NULL)
7126 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
7127 bt = ffesymbol_basictype (fn);
7128 kt = ffesymbol_kindtype (fn);
7129 }
7130
7131 if (multi)
7132 charfunc = cmplxfunc = FALSE;
7133 else if (bt == FFEINFO_basictypeCHARACTER)
7134 charfunc = TRUE, cmplxfunc = FALSE;
7135 else if ((bt == FFEINFO_basictypeCOMPLEX)
7136 && ffesymbol_is_f2c (fn)
7137 && !altentries)
7138 charfunc = FALSE, cmplxfunc = TRUE;
7139 else
7140 charfunc = cmplxfunc = FALSE;
7141
7142 if (multi || charfunc)
7143 type = ffecom_tree_fun_type_void;
7144 else if (ffesymbol_is_f2c (fn) && !altentries)
7145 type = ffecom_tree_fun_type[bt][kt];
7146 else
7147 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
7148
7149 if ((type == NULL_TREE)
7150 || (TREE_TYPE (type) == NULL_TREE))
7151 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
7152 break;
7153
7154 case FFEINFO_kindSUBROUTINE:
7155 gt = FFEGLOBAL_typeSUBR;
7156 egt = FFEGLOBAL_typeEXT;
7157 bt = FFEINFO_basictypeNONE;
7158 kt = FFEINFO_kindtypeNONE;
7159 if (ffecom_is_altreturning_)
7160 type = ffecom_tree_subr_type;
7161 else
7162 type = ffecom_tree_fun_type_void;
7163 charfunc = FALSE;
7164 cmplxfunc = FALSE;
7165 break;
7166
7167 default:
7168 assert ("say what??" == NULL);
7169 /* Fall through. */
7170 case FFEINFO_kindANY:
7171 gt = FFEGLOBAL_typeANY;
7172 bt = FFEINFO_basictypeNONE;
7173 kt = FFEINFO_kindtypeNONE;
7174 type = error_mark_node;
7175 charfunc = FALSE;
7176 cmplxfunc = FALSE;
7177 break;
7178 }
7179
7180 if (altentries)
7181 {
7182 id = ffecom_get_invented_identifier ("__g77_masterfun_%s",
7183 ffesymbol_text (fn));
7184 }
7185 #if FFETARGET_isENFORCED_MAIN
7186 else if (main_program)
7187 id = get_identifier (FFETARGET_nameENFORCED_MAIN_NAME);
7188 #endif
7189 else
7190 id = ffecom_get_external_identifier_ (fn);
7191
7192 start_function (id,
7193 type,
7194 0, /* nested/inline */
7195 !altentries); /* TREE_PUBLIC */
7196
7197 TREE_USED (current_function_decl) = 1; /* Avoid spurious warning if altentries. */
7198
7199 if (!altentries
7200 && ((g = ffesymbol_global (fn)) != NULL)
7201 && ((ffeglobal_type (g) == gt)
7202 || (ffeglobal_type (g) == egt)))
7203 {
7204 ffeglobal_set_hook (g, current_function_decl);
7205 }
7206
7207 /* Arg handling needs exec-transitioned ffesymbols to work with. But
7208 exec-transitioning needs current_function_decl to be filled in. So we
7209 do these things in two phases. */
7210
7211 if (altentries)
7212 { /* 1st arg identifies which entrypoint. */
7213 ffecom_which_entrypoint_decl_
7214 = build_decl (PARM_DECL,
7215 ffecom_get_invented_identifier ("__g77_%s",
7216 "which_entrypoint"),
7217 integer_type_node);
7218 push_parm_decl (ffecom_which_entrypoint_decl_);
7219 }
7220
7221 if (charfunc
7222 || cmplxfunc
7223 || multi)
7224 { /* Arg for result (return value). */
7225 tree type;
7226 tree length;
7227
7228 if (charfunc)
7229 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
7230 else if (cmplxfunc)
7231 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
7232 else
7233 type = ffecom_multi_type_node_;
7234
7235 result = ffecom_get_invented_identifier ("__g77_%s", "result");
7236
7237 /* Make length arg _and_ enhance type info for CHAR arg itself. */
7238
7239 if (charfunc)
7240 length = ffecom_char_enhance_arg_ (&type, fn);
7241 else
7242 length = NULL_TREE; /* Not ref'd if !charfunc. */
7243
7244 type = build_pointer_type (type);
7245 result = build_decl (PARM_DECL, result, type);
7246
7247 push_parm_decl (result);
7248 if (multi)
7249 ffecom_multi_retval_ = result;
7250 else
7251 ffecom_func_result_ = result;
7252
7253 if (charfunc)
7254 {
7255 push_parm_decl (length);
7256 ffecom_func_length_ = length;
7257 }
7258 }
7259
7260 if (ffecom_primary_entry_is_proc_)
7261 {
7262 if (altentries)
7263 arglist = ffecom_master_arglist_;
7264 else
7265 arglist = ffesymbol_dummyargs (fn);
7266 ffecom_push_dummy_decls_ (arglist, FALSE);
7267 }
7268
7269 if (TREE_CODE (current_function_decl) != ERROR_MARK)
7270 store_parm_decls (main_program ? 1 : 0);
7271
7272 ffecom_start_compstmt ();
7273 /* Disallow temp vars at this level. */
7274 current_binding_level->prep_state = 2;
7275
7276 lineno = old_lineno;
7277 input_filename = old_input_filename;
7278
7279 /* This handles any symbols still untransformed, in case -g specified.
7280 This used to be done in ffecom_finish_progunit, but it turns out to
7281 be necessary to do it here so that statement functions are
7282 expanded before code. But don't bother for BLOCK DATA. */
7283
7284 if (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
7285 ffesymbol_drive (ffecom_finish_symbol_transform_);
7286 }
7287
7288 /* ffecom_sym_transform_ -- Transform FFE sym into backend sym
7289
7290 ffesymbol s;
7291 ffecom_sym_transform_(s);
7292
7293 The ffesymbol_hook info for s is updated with appropriate backend info
7294 on the symbol. */
7295
7296 static ffesymbol
ffecom_sym_transform_(ffesymbol s)7297 ffecom_sym_transform_ (ffesymbol s)
7298 {
7299 tree t; /* Transformed thingy. */
7300 tree tlen; /* Length if CHAR*(*). */
7301 bool addr; /* Is t the address of the thingy? */
7302 ffeinfoBasictype bt;
7303 ffeinfoKindtype kt;
7304 ffeglobal g;
7305 int old_lineno = lineno;
7306 const char *old_input_filename = input_filename;
7307
7308 /* Must ensure special ASSIGN variables are declared at top of outermost
7309 block, else they'll end up in the innermost block when their first
7310 ASSIGN is seen, which leaves them out of scope when they're the
7311 subject of a GOTO or I/O statement.
7312
7313 We make this variable even if -fugly-assign. Just let it go unused,
7314 in case it turns out there are cases where we really want to use this
7315 variable anyway (e.g. ASSIGN to INTEGER*2 variable). */
7316
7317 if (! ffecom_transform_only_dummies_
7318 && ffesymbol_assigned (s)
7319 && ! ffesymbol_hook (s).assign_tree)
7320 s = ffecom_sym_transform_assign_ (s);
7321
7322 if (ffesymbol_sfdummyparent (s) == NULL)
7323 {
7324 input_filename = ffesymbol_where_filename (s);
7325 lineno = ffesymbol_where_filelinenum (s);
7326 }
7327 else
7328 {
7329 ffesymbol sf = ffesymbol_sfdummyparent (s);
7330
7331 input_filename = ffesymbol_where_filename (sf);
7332 lineno = ffesymbol_where_filelinenum (sf);
7333 }
7334
7335 bt = ffeinfo_basictype (ffebld_info (s));
7336 kt = ffeinfo_kindtype (ffebld_info (s));
7337
7338 t = NULL_TREE;
7339 tlen = NULL_TREE;
7340 addr = FALSE;
7341
7342 switch (ffesymbol_kind (s))
7343 {
7344 case FFEINFO_kindNONE:
7345 switch (ffesymbol_where (s))
7346 {
7347 case FFEINFO_whereDUMMY: /* Subroutine or function. */
7348 assert (ffecom_transform_only_dummies_);
7349
7350 /* Before 0.4, this could be ENTITY/DUMMY, but see
7351 ffestu_sym_end_transition -- no longer true (in particular, if
7352 it could be an ENTITY, it _will_ be made one, so that
7353 possibility won't come through here). So we never make length
7354 arg for CHARACTER type. */
7355
7356 t = build_decl (PARM_DECL,
7357 ffecom_get_identifier_ (ffesymbol_text (s)),
7358 ffecom_tree_ptr_to_subr_type);
7359 DECL_ARTIFICIAL (t) = 1;
7360 addr = TRUE;
7361 break;
7362
7363 case FFEINFO_whereGLOBAL: /* Subroutine or function. */
7364 assert (!ffecom_transform_only_dummies_);
7365
7366 if (((g = ffesymbol_global (s)) != NULL)
7367 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7368 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7369 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
7370 && (ffeglobal_hook (g) != NULL_TREE)
7371 && ffe_is_globals ())
7372 {
7373 t = ffeglobal_hook (g);
7374 break;
7375 }
7376
7377 t = build_decl (FUNCTION_DECL,
7378 ffecom_get_external_identifier_ (s),
7379 ffecom_tree_subr_type); /* Assume subr. */
7380 DECL_EXTERNAL (t) = 1;
7381 TREE_PUBLIC (t) = 1;
7382
7383 t = start_decl (t, FALSE);
7384 finish_decl (t, NULL_TREE, FALSE);
7385
7386 if ((g != NULL)
7387 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7388 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7389 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
7390 ffeglobal_set_hook (g, t);
7391
7392 ffecom_save_tree_forever (t);
7393
7394 break;
7395
7396 default:
7397 assert ("NONE where unexpected" == NULL);
7398 /* Fall through. */
7399 case FFEINFO_whereANY:
7400 break;
7401 }
7402 break;
7403
7404 case FFEINFO_kindENTITY:
7405 switch (ffeinfo_where (ffesymbol_info (s)))
7406 {
7407
7408 case FFEINFO_whereCONSTANT:
7409 /* ~~Debugging info needed? */
7410 assert (!ffecom_transform_only_dummies_);
7411 t = error_mark_node; /* Shouldn't ever see this in expr. */
7412 break;
7413
7414 case FFEINFO_whereLOCAL:
7415 assert (!ffecom_transform_only_dummies_);
7416
7417 {
7418 ffestorag st = ffesymbol_storage (s);
7419 tree type;
7420
7421 if ((st != NULL)
7422 && (ffestorag_size (st) == 0))
7423 {
7424 t = error_mark_node;
7425 break;
7426 }
7427
7428 type = ffecom_type_localvar_ (s, bt, kt);
7429
7430 if (type == error_mark_node)
7431 {
7432 t = error_mark_node;
7433 break;
7434 }
7435
7436 if ((st != NULL)
7437 && (ffestorag_parent (st) != NULL))
7438 { /* Child of EQUIVALENCE parent. */
7439 ffestorag est;
7440 tree et;
7441 ffetargetOffset offset;
7442
7443 est = ffestorag_parent (st);
7444 ffecom_transform_equiv_ (est);
7445
7446 et = ffestorag_hook (est);
7447 assert (et != NULL_TREE);
7448
7449 if (! TREE_STATIC (et))
7450 put_var_into_stack (et, /*rescan=*/true);
7451
7452 offset = ffestorag_modulo (est)
7453 + ffestorag_offset (ffesymbol_storage (s))
7454 - ffestorag_offset (est);
7455
7456 ffecom_debug_kludge_ (et, "EQUIVALENCE", s, type, offset);
7457
7458 /* (t_type *) (((char *) &et) + offset) */
7459
7460 t = convert (string_type_node, /* (char *) */
7461 ffecom_1 (ADDR_EXPR,
7462 build_pointer_type (TREE_TYPE (et)),
7463 et));
7464 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
7465 t,
7466 build_int_2 (offset, 0));
7467 t = convert (build_pointer_type (type),
7468 t);
7469 TREE_CONSTANT (t) = staticp (et);
7470
7471 addr = TRUE;
7472 }
7473 else
7474 {
7475 tree initexpr;
7476 bool init = ffesymbol_is_init (s);
7477
7478 t = build_decl (VAR_DECL,
7479 ffecom_get_identifier_ (ffesymbol_text (s)),
7480 type);
7481
7482 if (init
7483 || ffesymbol_namelisted (s)
7484 #ifdef FFECOM_sizeMAXSTACKITEM
7485 || ((st != NULL)
7486 && (ffestorag_size (st) > FFECOM_sizeMAXSTACKITEM))
7487 #endif
7488 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
7489 && (ffecom_primary_entry_kind_
7490 != FFEINFO_kindBLOCKDATA)
7491 && (ffesymbol_is_save (s) || ffe_is_saveall ())))
7492 TREE_STATIC (t) = !ffesymbol_attr (s, FFESYMBOL_attrADJUSTABLE);
7493 else
7494 TREE_STATIC (t) = 0; /* No need to make static. */
7495
7496 if (init || ffe_is_init_local_zero ())
7497 DECL_INITIAL (t) = error_mark_node;
7498
7499 /* Keep -Wunused from complaining about var if it
7500 is used as sfunc arg or DATA implied-DO. */
7501 if (ffesymbol_attrs (s) & FFESYMBOL_attrsSFARG)
7502 DECL_IN_SYSTEM_HEADER (t) = 1;
7503
7504 t = start_decl (t, FALSE);
7505
7506 if (init)
7507 {
7508 if (ffesymbol_init (s) != NULL)
7509 initexpr = ffecom_expr (ffesymbol_init (s));
7510 else
7511 initexpr = ffecom_init_zero_ (t);
7512 }
7513 else if (ffe_is_init_local_zero ())
7514 initexpr = ffecom_init_zero_ (t);
7515 else
7516 initexpr = NULL_TREE; /* Not ref'd if !init. */
7517
7518 finish_decl (t, initexpr, FALSE);
7519
7520 if (st != NULL && DECL_SIZE (t) != error_mark_node)
7521 {
7522 assert (TREE_CODE (DECL_SIZE_UNIT (t)) == INTEGER_CST);
7523 assert (0 == compare_tree_int (DECL_SIZE_UNIT (t),
7524 ffestorag_size (st)));
7525 }
7526 }
7527 }
7528 break;
7529
7530 case FFEINFO_whereRESULT:
7531 assert (!ffecom_transform_only_dummies_);
7532
7533 if (bt == FFEINFO_basictypeCHARACTER)
7534 { /* Result is already in list of dummies, use
7535 it (& length). */
7536 t = ffecom_func_result_;
7537 tlen = ffecom_func_length_;
7538 addr = TRUE;
7539 break;
7540 }
7541 if ((ffecom_num_entrypoints_ == 0)
7542 && (bt == FFEINFO_basictypeCOMPLEX)
7543 && (ffesymbol_is_f2c (ffecom_primary_entry_)))
7544 { /* Result is already in list of dummies, use
7545 it. */
7546 t = ffecom_func_result_;
7547 addr = TRUE;
7548 break;
7549 }
7550 if (ffecom_func_result_ != NULL_TREE)
7551 {
7552 t = ffecom_func_result_;
7553 break;
7554 }
7555 if ((ffecom_num_entrypoints_ != 0)
7556 && (ffecom_master_bt_ == FFEINFO_basictypeNONE))
7557 {
7558 assert (ffecom_multi_retval_ != NULL_TREE);
7559 t = ffecom_1 (INDIRECT_REF, ffecom_multi_type_node_,
7560 ffecom_multi_retval_);
7561 t = ffecom_2 (COMPONENT_REF, ffecom_tree_type[bt][kt],
7562 t, ffecom_multi_fields_[bt][kt]);
7563
7564 break;
7565 }
7566
7567 t = build_decl (VAR_DECL,
7568 ffecom_get_identifier_ (ffesymbol_text (s)),
7569 ffecom_tree_type[bt][kt]);
7570 TREE_STATIC (t) = 0; /* Put result on stack. */
7571 t = start_decl (t, FALSE);
7572 finish_decl (t, NULL_TREE, FALSE);
7573
7574 ffecom_func_result_ = t;
7575
7576 break;
7577
7578 case FFEINFO_whereDUMMY:
7579 {
7580 tree type;
7581 ffebld dl;
7582 ffebld dim;
7583 tree low;
7584 tree high;
7585 tree old_sizes;
7586 bool adjustable = FALSE; /* Conditionally adjustable? */
7587
7588 type = ffecom_tree_type[bt][kt];
7589 if (ffesymbol_sfdummyparent (s) != NULL)
7590 {
7591 if (current_function_decl == ffecom_outer_function_decl_)
7592 { /* Exec transition before sfunc
7593 context; get it later. */
7594 break;
7595 }
7596 t = ffecom_get_identifier_ (ffesymbol_text
7597 (ffesymbol_sfdummyparent (s)));
7598 }
7599 else
7600 t = ffecom_get_identifier_ (ffesymbol_text (s));
7601
7602 assert (ffecom_transform_only_dummies_);
7603
7604 old_sizes = get_pending_sizes ();
7605 put_pending_sizes (old_sizes);
7606
7607 if (bt == FFEINFO_basictypeCHARACTER)
7608 tlen = ffecom_char_enhance_arg_ (&type, s);
7609 type = ffecom_check_size_overflow_ (s, type, TRUE);
7610
7611 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
7612 {
7613 if (type == error_mark_node)
7614 break;
7615
7616 dim = ffebld_head (dl);
7617 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
7618 if ((ffebld_left (dim) == NULL) || ffecom_doing_entry_)
7619 low = ffecom_integer_one_node;
7620 else
7621 low = ffecom_expr (ffebld_left (dim));
7622 assert (ffebld_right (dim) != NULL);
7623 if ((ffebld_op (ffebld_right (dim)) == FFEBLD_opSTAR)
7624 || ffecom_doing_entry_)
7625 {
7626 /* Used to just do high=low. But for ffecom_tree_
7627 canonize_ref_, it probably is important to correctly
7628 assess the size. E.g. given COMPLEX C(*),CFUNC and
7629 C(2)=CFUNC(C), overlap can happen, while it can't
7630 for, say, C(1)=CFUNC(C(2)). */
7631 /* Even more recently used to set to INT_MAX, but that
7632 broke when some overflow checking went into the back
7633 end. Now we just leave the upper bound unspecified. */
7634 high = NULL;
7635 }
7636 else
7637 high = ffecom_expr (ffebld_right (dim));
7638
7639 /* Determine whether array is conditionally adjustable,
7640 to decide whether back-end magic is needed.
7641
7642 Normally the front end uses the back-end function
7643 variable_size to wrap SAVE_EXPR's around expressions
7644 affecting the size/shape of an array so that the
7645 size/shape info doesn't change during execution
7646 of the compiled code even though variables and
7647 functions referenced in those expressions might.
7648
7649 variable_size also makes sure those saved expressions
7650 get evaluated immediately upon entry to the
7651 compiled procedure -- the front end normally doesn't
7652 have to worry about that.
7653
7654 However, there is a problem with this that affects
7655 g77's implementation of entry points, and that is
7656 that it is _not_ true that each invocation of the
7657 compiled procedure is permitted to evaluate
7658 array size/shape info -- because it is possible
7659 that, for some invocations, that info is invalid (in
7660 which case it is "promised" -- i.e. a violation of
7661 the Fortran standard -- that the compiled code
7662 won't reference the array or its size/shape
7663 during that particular invocation).
7664
7665 To phrase this in C terms, consider this gcc function:
7666
7667 void foo (int *n, float (*a)[*n])
7668 {
7669 // a is "pointer to array ...", fyi.
7670 }
7671
7672 Suppose that, for some invocations, it is permitted
7673 for a caller of foo to do this:
7674
7675 foo (NULL, NULL);
7676
7677 Now the _written_ code for foo can take such a call
7678 into account by either testing explicitly for whether
7679 (a == NULL) || (n == NULL) -- presumably it is
7680 not permitted to reference *a in various fashions
7681 if (n == NULL) I suppose -- or it can avoid it by
7682 looking at other info (other arguments, static/global
7683 data, etc.).
7684
7685 However, this won't work in gcc 2.5.8 because it'll
7686 automatically emit the code to save the "*n"
7687 expression, which'll yield a NULL dereference for
7688 the "foo (NULL, NULL)" call, something the code
7689 for foo cannot prevent.
7690
7691 g77 definitely needs to avoid executing such
7692 code anytime the pointer to the adjustable array
7693 is NULL, because even if its bounds expressions
7694 don't have any references to possible "absent"
7695 variables like "*n" -- say all variable references
7696 are to COMMON variables, i.e. global (though in C,
7697 local static could actually make sense) -- the
7698 expressions could yield other run-time problems
7699 for allowably "dead" values in those variables.
7700
7701 For example, let's consider a more complicated
7702 version of foo:
7703
7704 extern int i;
7705 extern int j;
7706
7707 void foo (float (*a)[i/j])
7708 {
7709 ...
7710 }
7711
7712 The above is (essentially) quite valid for Fortran
7713 but, again, for a call like "foo (NULL);", it is
7714 permitted for i and j to be undefined when the
7715 call is made. If j happened to be zero, for
7716 example, emitting the code to evaluate "i/j"
7717 could result in a run-time error.
7718
7719 Offhand, though I don't have my F77 or F90
7720 standards handy, it might even be valid for a
7721 bounds expression to contain a function reference,
7722 in which case I doubt it is permitted for an
7723 implementation to invoke that function in the
7724 Fortran case involved here (invocation of an
7725 alternate ENTRY point that doesn't have the adjustable
7726 array as one of its arguments).
7727
7728 So, the code that the compiler would normally emit
7729 to preevaluate the size/shape info for an
7730 adjustable array _must not_ be executed at run time
7731 in certain cases. Specifically, for Fortran,
7732 the case is when the pointer to the adjustable
7733 array == NULL. (For gnu-ish C, it might be nice
7734 for the source code itself to specify an expression
7735 that, if TRUE, inhibits execution of the code. Or
7736 reverse the sense for elegance.)
7737
7738 (Note that g77 could use a different test than NULL,
7739 actually, since it happens to always pass an
7740 integer to the called function that specifies which
7741 entry point is being invoked. Hmm, this might
7742 solve the next problem.)
7743
7744 One way a user could, I suppose, write "foo" so
7745 it works is to insert COND_EXPR's for the
7746 size/shape info so the dangerous stuff isn't
7747 actually done, as in:
7748
7749 void foo (int *n, float (*a)[(a == NULL) ? 0 : *n])
7750 {
7751 ...
7752 }
7753
7754 The next problem is that the front end needs to
7755 be able to tell the back end about the array's
7756 decl _before_ it tells it about the conditional
7757 expression to inhibit evaluation of size/shape info,
7758 as shown above.
7759
7760 To solve this, the front end needs to be able
7761 to give the back end the expression to inhibit
7762 generation of the preevaluation code _after_
7763 it makes the decl for the adjustable array.
7764
7765 Until then, the above example using the COND_EXPR
7766 doesn't pass muster with gcc because the "(a == NULL)"
7767 part has a reference to "a", which is still
7768 undefined at that point.
7769
7770 g77 will therefore use a different mechanism in the
7771 meantime. */
7772
7773 if (!adjustable
7774 && ((TREE_CODE (low) != INTEGER_CST)
7775 || (high && TREE_CODE (high) != INTEGER_CST)))
7776 adjustable = TRUE;
7777
7778 #if 0 /* Old approach -- see below. */
7779 if (TREE_CODE (low) != INTEGER_CST)
7780 low = ffecom_3 (COND_EXPR, integer_type_node,
7781 ffecom_adjarray_passed_ (s),
7782 low,
7783 ffecom_integer_zero_node);
7784
7785 if (high && TREE_CODE (high) != INTEGER_CST)
7786 high = ffecom_3 (COND_EXPR, integer_type_node,
7787 ffecom_adjarray_passed_ (s),
7788 high,
7789 ffecom_integer_zero_node);
7790 #endif
7791
7792 /* ~~~gcc/stor-layout.c (layout_type) should do this,
7793 probably. Fixes 950302-1.f. */
7794
7795 if (TREE_CODE (low) != INTEGER_CST)
7796 low = variable_size (low);
7797
7798 /* ~~~Similarly, this fixes dumb0.f. The C front end
7799 does this, which is why dumb0.c would work. */
7800
7801 if (high && TREE_CODE (high) != INTEGER_CST)
7802 high = variable_size (high);
7803
7804 type
7805 = build_array_type
7806 (type,
7807 build_range_type (ffecom_integer_type_node,
7808 low, high));
7809 type = ffecom_check_size_overflow_ (s, type, TRUE);
7810 }
7811
7812 if (type == error_mark_node)
7813 {
7814 t = error_mark_node;
7815 break;
7816 }
7817
7818 if ((ffesymbol_sfdummyparent (s) == NULL)
7819 || (ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER))
7820 {
7821 type = build_pointer_type (type);
7822 addr = TRUE;
7823 }
7824
7825 t = build_decl (PARM_DECL, t, type);
7826 DECL_ARTIFICIAL (t) = 1;
7827
7828 /* If this arg is present in every entry point's list of
7829 dummy args, then we're done. */
7830
7831 if (ffesymbol_numentries (s)
7832 == (ffecom_num_entrypoints_ + 1))
7833 break;
7834
7835 #if 1
7836
7837 /* If variable_size in stor-layout has been called during
7838 the above, then get_pending_sizes should have the
7839 yet-to-be-evaluated saved expressions pending.
7840 Make the whole lot of them get emitted, conditionally
7841 on whether the array decl ("t" above) is not NULL. */
7842
7843 {
7844 tree sizes = get_pending_sizes ();
7845 tree tem;
7846
7847 for (tem = sizes;
7848 tem != old_sizes;
7849 tem = TREE_CHAIN (tem))
7850 {
7851 tree temv = TREE_VALUE (tem);
7852
7853 if (sizes == tem)
7854 sizes = temv;
7855 else
7856 sizes
7857 = ffecom_2 (COMPOUND_EXPR,
7858 TREE_TYPE (sizes),
7859 temv,
7860 sizes);
7861 }
7862
7863 if (sizes != tem)
7864 {
7865 sizes
7866 = ffecom_3 (COND_EXPR,
7867 TREE_TYPE (sizes),
7868 ffecom_2 (NE_EXPR,
7869 integer_type_node,
7870 t,
7871 null_pointer_node),
7872 sizes,
7873 convert (TREE_TYPE (sizes),
7874 integer_zero_node));
7875 sizes = ffecom_save_tree (sizes);
7876
7877 sizes
7878 = tree_cons (NULL_TREE, sizes, tem);
7879 }
7880
7881 if (sizes)
7882 put_pending_sizes (sizes);
7883 }
7884
7885 #else
7886 #if 0
7887 if (adjustable
7888 && (ffesymbol_numentries (s)
7889 != ffecom_num_entrypoints_ + 1))
7890 DECL_SOMETHING (t)
7891 = ffecom_2 (NE_EXPR, integer_type_node,
7892 t,
7893 null_pointer_node);
7894 #else
7895 #if 0
7896 if (adjustable
7897 && (ffesymbol_numentries (s)
7898 != ffecom_num_entrypoints_ + 1))
7899 {
7900 ffebad_start (FFEBAD_MISSING_ADJARRAY_UNSUPPORTED);
7901 ffebad_here (0, ffesymbol_where_line (s),
7902 ffesymbol_where_column (s));
7903 ffebad_string (ffesymbol_text (s));
7904 ffebad_finish ();
7905 }
7906 #endif
7907 #endif
7908 #endif
7909 }
7910 break;
7911
7912 case FFEINFO_whereCOMMON:
7913 {
7914 ffesymbol cs;
7915 ffeglobal cg;
7916 tree ct;
7917 ffestorag st = ffesymbol_storage (s);
7918 tree type;
7919
7920 cs = ffesymbol_common (s); /* The COMMON area itself. */
7921 if (st != NULL) /* Else not laid out. */
7922 {
7923 ffecom_transform_common_ (cs);
7924 st = ffesymbol_storage (s);
7925 }
7926
7927 type = ffecom_type_localvar_ (s, bt, kt);
7928
7929 cg = ffesymbol_global (cs); /* The global COMMON info. */
7930 if ((cg == NULL)
7931 || (ffeglobal_type (cg) != FFEGLOBAL_typeCOMMON))
7932 ct = NULL_TREE;
7933 else
7934 ct = ffeglobal_hook (cg); /* The common area's tree. */
7935
7936 if ((ct == NULL_TREE)
7937 || (st == NULL)
7938 || (type == error_mark_node))
7939 t = error_mark_node;
7940 else
7941 {
7942 ffetargetOffset offset;
7943 ffestorag cst;
7944
7945 cst = ffestorag_parent (st);
7946 assert (cst == ffesymbol_storage (cs));
7947
7948 offset = ffestorag_modulo (cst)
7949 + ffestorag_offset (st)
7950 - ffestorag_offset (cst);
7951
7952 ffecom_debug_kludge_ (ct, "COMMON", s, type, offset);
7953
7954 /* (t_type *) (((char *) &ct) + offset) */
7955
7956 t = convert (string_type_node, /* (char *) */
7957 ffecom_1 (ADDR_EXPR,
7958 build_pointer_type (TREE_TYPE (ct)),
7959 ct));
7960 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
7961 t,
7962 build_int_2 (offset, 0));
7963 t = convert (build_pointer_type (type),
7964 t);
7965 TREE_CONSTANT (t) = 1;
7966
7967 addr = TRUE;
7968 }
7969 }
7970 break;
7971
7972 case FFEINFO_whereIMMEDIATE:
7973 case FFEINFO_whereGLOBAL:
7974 case FFEINFO_whereFLEETING:
7975 case FFEINFO_whereFLEETING_CADDR:
7976 case FFEINFO_whereFLEETING_IADDR:
7977 case FFEINFO_whereINTRINSIC:
7978 case FFEINFO_whereCONSTANT_SUBOBJECT:
7979 default:
7980 assert ("ENTITY where unheard of" == NULL);
7981 /* Fall through. */
7982 case FFEINFO_whereANY:
7983 t = error_mark_node;
7984 break;
7985 }
7986 break;
7987
7988 case FFEINFO_kindFUNCTION:
7989 switch (ffeinfo_where (ffesymbol_info (s)))
7990 {
7991 case FFEINFO_whereLOCAL: /* Me. */
7992 assert (!ffecom_transform_only_dummies_);
7993 t = current_function_decl;
7994 break;
7995
7996 case FFEINFO_whereGLOBAL:
7997 assert (!ffecom_transform_only_dummies_);
7998
7999 if (((g = ffesymbol_global (s)) != NULL)
8000 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8001 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8002 && (ffeglobal_hook (g) != NULL_TREE)
8003 && ffe_is_globals ())
8004 {
8005 t = ffeglobal_hook (g);
8006 break;
8007 }
8008
8009 if (ffesymbol_is_f2c (s)
8010 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8011 t = ffecom_tree_fun_type[bt][kt];
8012 else
8013 t = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
8014
8015 t = build_decl (FUNCTION_DECL,
8016 ffecom_get_external_identifier_ (s),
8017 t);
8018 DECL_EXTERNAL (t) = 1;
8019 TREE_PUBLIC (t) = 1;
8020
8021 t = start_decl (t, FALSE);
8022 finish_decl (t, NULL_TREE, FALSE);
8023
8024 if ((g != NULL)
8025 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8026 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8027 ffeglobal_set_hook (g, t);
8028
8029 ffecom_save_tree_forever (t);
8030
8031 break;
8032
8033 case FFEINFO_whereDUMMY:
8034 assert (ffecom_transform_only_dummies_);
8035
8036 if (ffesymbol_is_f2c (s)
8037 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8038 t = ffecom_tree_ptr_to_fun_type[bt][kt];
8039 else
8040 t = build_pointer_type
8041 (build_function_type (ffecom_tree_type[bt][kt], NULL_TREE));
8042
8043 t = build_decl (PARM_DECL,
8044 ffecom_get_identifier_ (ffesymbol_text (s)),
8045 t);
8046 DECL_ARTIFICIAL (t) = 1;
8047 addr = TRUE;
8048 break;
8049
8050 case FFEINFO_whereCONSTANT: /* Statement function. */
8051 assert (!ffecom_transform_only_dummies_);
8052 t = ffecom_gen_sfuncdef_ (s, bt, kt);
8053 break;
8054
8055 case FFEINFO_whereINTRINSIC:
8056 assert (!ffecom_transform_only_dummies_);
8057 break; /* Let actual references generate their
8058 decls. */
8059
8060 default:
8061 assert ("FUNCTION where unheard of" == NULL);
8062 /* Fall through. */
8063 case FFEINFO_whereANY:
8064 t = error_mark_node;
8065 break;
8066 }
8067 break;
8068
8069 case FFEINFO_kindSUBROUTINE:
8070 switch (ffeinfo_where (ffesymbol_info (s)))
8071 {
8072 case FFEINFO_whereLOCAL: /* Me. */
8073 assert (!ffecom_transform_only_dummies_);
8074 t = current_function_decl;
8075 break;
8076
8077 case FFEINFO_whereGLOBAL:
8078 assert (!ffecom_transform_only_dummies_);
8079
8080 if (((g = ffesymbol_global (s)) != NULL)
8081 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8082 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8083 && (ffeglobal_hook (g) != NULL_TREE)
8084 && ffe_is_globals ())
8085 {
8086 t = ffeglobal_hook (g);
8087 break;
8088 }
8089
8090 t = build_decl (FUNCTION_DECL,
8091 ffecom_get_external_identifier_ (s),
8092 ffecom_tree_subr_type);
8093 DECL_EXTERNAL (t) = 1;
8094 TREE_PUBLIC (t) = 1;
8095
8096 t = start_decl (t, ffe_is_globals ());
8097 finish_decl (t, NULL_TREE, ffe_is_globals ());
8098
8099 if ((g != NULL)
8100 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8101 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8102 ffeglobal_set_hook (g, t);
8103
8104 ffecom_save_tree_forever (t);
8105
8106 break;
8107
8108 case FFEINFO_whereDUMMY:
8109 assert (ffecom_transform_only_dummies_);
8110
8111 t = build_decl (PARM_DECL,
8112 ffecom_get_identifier_ (ffesymbol_text (s)),
8113 ffecom_tree_ptr_to_subr_type);
8114 DECL_ARTIFICIAL (t) = 1;
8115 addr = TRUE;
8116 break;
8117
8118 case FFEINFO_whereINTRINSIC:
8119 assert (!ffecom_transform_only_dummies_);
8120 break; /* Let actual references generate their
8121 decls. */
8122
8123 default:
8124 assert ("SUBROUTINE where unheard of" == NULL);
8125 /* Fall through. */
8126 case FFEINFO_whereANY:
8127 t = error_mark_node;
8128 break;
8129 }
8130 break;
8131
8132 case FFEINFO_kindPROGRAM:
8133 switch (ffeinfo_where (ffesymbol_info (s)))
8134 {
8135 case FFEINFO_whereLOCAL: /* Me. */
8136 assert (!ffecom_transform_only_dummies_);
8137 t = current_function_decl;
8138 break;
8139
8140 case FFEINFO_whereCOMMON:
8141 case FFEINFO_whereDUMMY:
8142 case FFEINFO_whereGLOBAL:
8143 case FFEINFO_whereRESULT:
8144 case FFEINFO_whereFLEETING:
8145 case FFEINFO_whereFLEETING_CADDR:
8146 case FFEINFO_whereFLEETING_IADDR:
8147 case FFEINFO_whereIMMEDIATE:
8148 case FFEINFO_whereINTRINSIC:
8149 case FFEINFO_whereCONSTANT:
8150 case FFEINFO_whereCONSTANT_SUBOBJECT:
8151 default:
8152 assert ("PROGRAM where unheard of" == NULL);
8153 /* Fall through. */
8154 case FFEINFO_whereANY:
8155 t = error_mark_node;
8156 break;
8157 }
8158 break;
8159
8160 case FFEINFO_kindBLOCKDATA:
8161 switch (ffeinfo_where (ffesymbol_info (s)))
8162 {
8163 case FFEINFO_whereLOCAL: /* Me. */
8164 assert (!ffecom_transform_only_dummies_);
8165 t = current_function_decl;
8166 break;
8167
8168 case FFEINFO_whereGLOBAL:
8169 assert (!ffecom_transform_only_dummies_);
8170
8171 t = build_decl (FUNCTION_DECL,
8172 ffecom_get_external_identifier_ (s),
8173 ffecom_tree_blockdata_type);
8174 DECL_EXTERNAL (t) = 1;
8175 TREE_PUBLIC (t) = 1;
8176
8177 t = start_decl (t, FALSE);
8178 finish_decl (t, NULL_TREE, FALSE);
8179
8180 ffecom_save_tree_forever (t);
8181
8182 break;
8183
8184 case FFEINFO_whereCOMMON:
8185 case FFEINFO_whereDUMMY:
8186 case FFEINFO_whereRESULT:
8187 case FFEINFO_whereFLEETING:
8188 case FFEINFO_whereFLEETING_CADDR:
8189 case FFEINFO_whereFLEETING_IADDR:
8190 case FFEINFO_whereIMMEDIATE:
8191 case FFEINFO_whereINTRINSIC:
8192 case FFEINFO_whereCONSTANT:
8193 case FFEINFO_whereCONSTANT_SUBOBJECT:
8194 default:
8195 assert ("BLOCKDATA where unheard of" == NULL);
8196 /* Fall through. */
8197 case FFEINFO_whereANY:
8198 t = error_mark_node;
8199 break;
8200 }
8201 break;
8202
8203 case FFEINFO_kindCOMMON:
8204 switch (ffeinfo_where (ffesymbol_info (s)))
8205 {
8206 case FFEINFO_whereLOCAL:
8207 assert (!ffecom_transform_only_dummies_);
8208 ffecom_transform_common_ (s);
8209 break;
8210
8211 case FFEINFO_whereNONE:
8212 case FFEINFO_whereCOMMON:
8213 case FFEINFO_whereDUMMY:
8214 case FFEINFO_whereGLOBAL:
8215 case FFEINFO_whereRESULT:
8216 case FFEINFO_whereFLEETING:
8217 case FFEINFO_whereFLEETING_CADDR:
8218 case FFEINFO_whereFLEETING_IADDR:
8219 case FFEINFO_whereIMMEDIATE:
8220 case FFEINFO_whereINTRINSIC:
8221 case FFEINFO_whereCONSTANT:
8222 case FFEINFO_whereCONSTANT_SUBOBJECT:
8223 default:
8224 assert ("COMMON where unheard of" == NULL);
8225 /* Fall through. */
8226 case FFEINFO_whereANY:
8227 t = error_mark_node;
8228 break;
8229 }
8230 break;
8231
8232 case FFEINFO_kindCONSTRUCT:
8233 switch (ffeinfo_where (ffesymbol_info (s)))
8234 {
8235 case FFEINFO_whereLOCAL:
8236 assert (!ffecom_transform_only_dummies_);
8237 break;
8238
8239 case FFEINFO_whereNONE:
8240 case FFEINFO_whereCOMMON:
8241 case FFEINFO_whereDUMMY:
8242 case FFEINFO_whereGLOBAL:
8243 case FFEINFO_whereRESULT:
8244 case FFEINFO_whereFLEETING:
8245 case FFEINFO_whereFLEETING_CADDR:
8246 case FFEINFO_whereFLEETING_IADDR:
8247 case FFEINFO_whereIMMEDIATE:
8248 case FFEINFO_whereINTRINSIC:
8249 case FFEINFO_whereCONSTANT:
8250 case FFEINFO_whereCONSTANT_SUBOBJECT:
8251 default:
8252 assert ("CONSTRUCT where unheard of" == NULL);
8253 /* Fall through. */
8254 case FFEINFO_whereANY:
8255 t = error_mark_node;
8256 break;
8257 }
8258 break;
8259
8260 case FFEINFO_kindNAMELIST:
8261 switch (ffeinfo_where (ffesymbol_info (s)))
8262 {
8263 case FFEINFO_whereLOCAL:
8264 assert (!ffecom_transform_only_dummies_);
8265 t = ffecom_transform_namelist_ (s);
8266 break;
8267
8268 case FFEINFO_whereNONE:
8269 case FFEINFO_whereCOMMON:
8270 case FFEINFO_whereDUMMY:
8271 case FFEINFO_whereGLOBAL:
8272 case FFEINFO_whereRESULT:
8273 case FFEINFO_whereFLEETING:
8274 case FFEINFO_whereFLEETING_CADDR:
8275 case FFEINFO_whereFLEETING_IADDR:
8276 case FFEINFO_whereIMMEDIATE:
8277 case FFEINFO_whereINTRINSIC:
8278 case FFEINFO_whereCONSTANT:
8279 case FFEINFO_whereCONSTANT_SUBOBJECT:
8280 default:
8281 assert ("NAMELIST where unheard of" == NULL);
8282 /* Fall through. */
8283 case FFEINFO_whereANY:
8284 t = error_mark_node;
8285 break;
8286 }
8287 break;
8288
8289 default:
8290 assert ("kind unheard of" == NULL);
8291 /* Fall through. */
8292 case FFEINFO_kindANY:
8293 t = error_mark_node;
8294 break;
8295 }
8296
8297 ffesymbol_hook (s).decl_tree = t;
8298 ffesymbol_hook (s).length_tree = tlen;
8299 ffesymbol_hook (s).addr = addr;
8300
8301 lineno = old_lineno;
8302 input_filename = old_input_filename;
8303
8304 return s;
8305 }
8306
8307 /* Transform into ASSIGNable symbol.
8308
8309 Symbol has already been transformed, but for whatever reason, the
8310 resulting decl_tree has been deemed not usable for an ASSIGN target.
8311 (E.g. it isn't wide enough to hold a pointer.) So, here we invent
8312 another local symbol of type void * and stuff that in the assign_tree
8313 argument. The F77/F90 standards allow this implementation. */
8314
8315 static ffesymbol
ffecom_sym_transform_assign_(ffesymbol s)8316 ffecom_sym_transform_assign_ (ffesymbol s)
8317 {
8318 tree t; /* Transformed thingy. */
8319 int old_lineno = lineno;
8320 const char *old_input_filename = input_filename;
8321
8322 if (ffesymbol_sfdummyparent (s) == NULL)
8323 {
8324 input_filename = ffesymbol_where_filename (s);
8325 lineno = ffesymbol_where_filelinenum (s);
8326 }
8327 else
8328 {
8329 ffesymbol sf = ffesymbol_sfdummyparent (s);
8330
8331 input_filename = ffesymbol_where_filename (sf);
8332 lineno = ffesymbol_where_filelinenum (sf);
8333 }
8334
8335 assert (!ffecom_transform_only_dummies_);
8336
8337 t = build_decl (VAR_DECL,
8338 ffecom_get_invented_identifier ("__g77_ASSIGN_%s",
8339 ffesymbol_text (s)),
8340 TREE_TYPE (null_pointer_node));
8341
8342 switch (ffesymbol_where (s))
8343 {
8344 case FFEINFO_whereLOCAL:
8345 /* Unlike for regular vars, SAVE status is easy to determine for
8346 ASSIGNed vars, since there's no initialization, there's no
8347 effective storage association (so "SAVE J" does not apply to
8348 K even given "EQUIVALENCE (J,K)"), there's no size issue
8349 to worry about, etc. */
8350 if ((ffesymbol_is_save (s) || ffe_is_saveall ())
8351 && (ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8352 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA))
8353 TREE_STATIC (t) = 1; /* SAVEd in proc, make static. */
8354 else
8355 TREE_STATIC (t) = 0; /* No need to make static. */
8356 break;
8357
8358 case FFEINFO_whereCOMMON:
8359 TREE_STATIC (t) = 1; /* Assume COMMONs always SAVEd. */
8360 break;
8361
8362 case FFEINFO_whereDUMMY:
8363 /* Note that twinning a DUMMY means the caller won't see
8364 the ASSIGNed value. But both F77 and F90 allow implementations
8365 to do this, i.e. disallow Fortran code that would try and
8366 take advantage of actually putting a label into a variable
8367 via a dummy argument (or any other storage association, for
8368 that matter). */
8369 TREE_STATIC (t) = 0;
8370 break;
8371
8372 default:
8373 TREE_STATIC (t) = 0;
8374 break;
8375 }
8376
8377 t = start_decl (t, FALSE);
8378 finish_decl (t, NULL_TREE, FALSE);
8379
8380 ffesymbol_hook (s).assign_tree = t;
8381
8382 lineno = old_lineno;
8383 input_filename = old_input_filename;
8384
8385 return s;
8386 }
8387
8388 /* Implement COMMON area in back end.
8389
8390 Because COMMON-based variables can be referenced in the dimension
8391 expressions of dummy (adjustable) arrays, and because dummies
8392 (in the gcc back end) need to be put in the outer binding level
8393 of a function (which has two binding levels, the outer holding
8394 the dummies and the inner holding the other vars), special care
8395 must be taken to handle COMMON areas.
8396
8397 The current strategy is basically to always tell the back end about
8398 the COMMON area as a top-level external reference to just a block
8399 of storage of the master type of that area (e.g. integer, real,
8400 character, whatever -- not a structure). As a distinct action,
8401 if initial values are provided, tell the back end about the area
8402 as a top-level non-external (initialized) area and remember not to
8403 allow further initialization or expansion of the area. Meanwhile,
8404 if no initialization happens at all, tell the back end about
8405 the largest size we've seen declared so the space does get reserved.
8406 (This function doesn't handle all that stuff, but it does some
8407 of the important things.)
8408
8409 Meanwhile, for COMMON variables themselves, just keep creating
8410 references like *((float *) (&common_area + offset)) each time
8411 we reference the variable. In other words, don't make a VAR_DECL
8412 or any kind of component reference (like we used to do before 0.4),
8413 though we might do that as well just for debugging purposes (and
8414 stuff the rtl with the appropriate offset expression). */
8415
8416 static void
ffecom_transform_common_(ffesymbol s)8417 ffecom_transform_common_ (ffesymbol s)
8418 {
8419 ffestorag st = ffesymbol_storage (s);
8420 ffeglobal g = ffesymbol_global (s);
8421 tree cbt;
8422 tree cbtype;
8423 tree init;
8424 tree high;
8425 bool is_init = ffestorag_is_init (st);
8426
8427 assert (st != NULL);
8428
8429 if ((g == NULL)
8430 || (ffeglobal_type (g) != FFEGLOBAL_typeCOMMON))
8431 return;
8432
8433 /* First update the size of the area in global terms. */
8434
8435 ffeglobal_size_common (s, ffestorag_size (st));
8436
8437 if (!ffeglobal_common_init (g))
8438 is_init = FALSE; /* No explicit init, don't let erroneous joins init. */
8439
8440 cbt = ffeglobal_hook (g);
8441
8442 /* If we already have declared this common block for a previous program
8443 unit, and either we already initialized it or we don't have new
8444 initialization for it, just return what we have without changing it. */
8445
8446 if ((cbt != NULL_TREE)
8447 && (!is_init
8448 || !DECL_EXTERNAL (cbt)))
8449 {
8450 if (st->hook == NULL) ffestorag_set_hook (st, cbt);
8451 return;
8452 }
8453
8454 /* Process inits. */
8455
8456 if (is_init)
8457 {
8458 if (ffestorag_init (st) != NULL)
8459 {
8460 ffebld sexp;
8461
8462 /* Set the padding for the expression, so ffecom_expr
8463 knows to insert that many zeros. */
8464 switch (ffebld_op (sexp = ffestorag_init (st)))
8465 {
8466 case FFEBLD_opCONTER:
8467 ffebld_conter_set_pad (sexp, ffestorag_modulo (st));
8468 break;
8469
8470 case FFEBLD_opARRTER:
8471 ffebld_arrter_set_pad (sexp, ffestorag_modulo (st));
8472 break;
8473
8474 case FFEBLD_opACCTER:
8475 ffebld_accter_set_pad (sexp, ffestorag_modulo (st));
8476 break;
8477
8478 default:
8479 assert ("bad op for cmn init (pad)" == NULL);
8480 break;
8481 }
8482
8483 init = ffecom_expr (sexp);
8484 if (init == error_mark_node)
8485 { /* Hopefully the back end complained! */
8486 init = NULL_TREE;
8487 if (cbt != NULL_TREE)
8488 return;
8489 }
8490 }
8491 else
8492 init = error_mark_node;
8493 }
8494 else
8495 init = NULL_TREE;
8496
8497 /* cbtype must be permanently allocated! */
8498
8499 /* Allocate the MAX of the areas so far, seen filewide. */
8500 high = build_int_2 ((ffeglobal_common_size (g)
8501 + ffeglobal_common_pad (g)) - 1, 0);
8502 TREE_TYPE (high) = ffecom_integer_type_node;
8503
8504 if (init)
8505 cbtype = build_array_type (char_type_node,
8506 build_range_type (integer_type_node,
8507 integer_zero_node,
8508 high));
8509 else
8510 cbtype = build_array_type (char_type_node, NULL_TREE);
8511
8512 if (cbt == NULL_TREE)
8513 {
8514 cbt
8515 = build_decl (VAR_DECL,
8516 ffecom_get_external_identifier_ (s),
8517 cbtype);
8518 TREE_STATIC (cbt) = 1;
8519 TREE_PUBLIC (cbt) = 1;
8520 }
8521 else
8522 {
8523 assert (is_init);
8524 TREE_TYPE (cbt) = cbtype;
8525 }
8526 DECL_EXTERNAL (cbt) = init ? 0 : 1;
8527 DECL_INITIAL (cbt) = init ? error_mark_node : NULL_TREE;
8528
8529 cbt = start_decl (cbt, TRUE);
8530 if (ffeglobal_hook (g) != NULL)
8531 assert (cbt == ffeglobal_hook (g));
8532
8533 assert (!init || !DECL_EXTERNAL (cbt));
8534
8535 /* Make sure that any type can live in COMMON and be referenced
8536 without getting a bus error. We could pick the most restrictive
8537 alignment of all entities actually placed in the COMMON, but
8538 this seems easy enough. */
8539
8540 DECL_ALIGN (cbt) = BIGGEST_ALIGNMENT;
8541 DECL_USER_ALIGN (cbt) = 0;
8542
8543 if (is_init && (ffestorag_init (st) == NULL))
8544 init = ffecom_init_zero_ (cbt);
8545
8546 finish_decl (cbt, init, TRUE);
8547
8548 if (is_init)
8549 ffestorag_set_init (st, ffebld_new_any ());
8550
8551 if (init)
8552 {
8553 assert (DECL_SIZE_UNIT (cbt) != NULL_TREE);
8554 assert (TREE_CODE (DECL_SIZE_UNIT (cbt)) == INTEGER_CST);
8555 assert (0 == compare_tree_int (DECL_SIZE_UNIT (cbt),
8556 (ffeglobal_common_size (g)
8557 + ffeglobal_common_pad (g))));
8558 }
8559
8560 ffeglobal_set_hook (g, cbt);
8561
8562 ffestorag_set_hook (st, cbt);
8563
8564 ffecom_save_tree_forever (cbt);
8565 }
8566
8567 /* Make master area for local EQUIVALENCE. */
8568
8569 static void
ffecom_transform_equiv_(ffestorag eqst)8570 ffecom_transform_equiv_ (ffestorag eqst)
8571 {
8572 tree eqt;
8573 tree eqtype;
8574 tree init;
8575 tree high;
8576 bool is_init = ffestorag_is_init (eqst);
8577
8578 assert (eqst != NULL);
8579
8580 eqt = ffestorag_hook (eqst);
8581
8582 if (eqt != NULL_TREE)
8583 return;
8584
8585 /* Process inits. */
8586
8587 if (is_init)
8588 {
8589 if (ffestorag_init (eqst) != NULL)
8590 {
8591 ffebld sexp;
8592
8593 /* Set the padding for the expression, so ffecom_expr
8594 knows to insert that many zeros. */
8595 switch (ffebld_op (sexp = ffestorag_init (eqst)))
8596 {
8597 case FFEBLD_opCONTER:
8598 ffebld_conter_set_pad (sexp, ffestorag_modulo (eqst));
8599 break;
8600
8601 case FFEBLD_opARRTER:
8602 ffebld_arrter_set_pad (sexp, ffestorag_modulo (eqst));
8603 break;
8604
8605 case FFEBLD_opACCTER:
8606 ffebld_accter_set_pad (sexp, ffestorag_modulo (eqst));
8607 break;
8608
8609 default:
8610 assert ("bad op for eqv init (pad)" == NULL);
8611 break;
8612 }
8613
8614 init = ffecom_expr (sexp);
8615 if (init == error_mark_node)
8616 init = NULL_TREE; /* Hopefully the back end complained! */
8617 }
8618 else
8619 init = error_mark_node;
8620 }
8621 else if (ffe_is_init_local_zero ())
8622 init = error_mark_node;
8623 else
8624 init = NULL_TREE;
8625
8626 ffecom_member_namelisted_ = FALSE;
8627 ffestorag_drive (ffestorag_list_equivs (eqst),
8628 &ffecom_member_phase1_,
8629 eqst);
8630
8631 high = build_int_2 ((ffestorag_size (eqst)
8632 + ffestorag_modulo (eqst)) - 1, 0);
8633 TREE_TYPE (high) = ffecom_integer_type_node;
8634
8635 eqtype = build_array_type (char_type_node,
8636 build_range_type (ffecom_integer_type_node,
8637 ffecom_integer_zero_node,
8638 high));
8639
8640 eqt = build_decl (VAR_DECL,
8641 ffecom_get_invented_identifier ("__g77_equiv_%s",
8642 ffesymbol_text
8643 (ffestorag_symbol (eqst))),
8644 eqtype);
8645 DECL_EXTERNAL (eqt) = 0;
8646 if (is_init
8647 || ffecom_member_namelisted_
8648 #ifdef FFECOM_sizeMAXSTACKITEM
8649 || (ffestorag_size (eqst) > FFECOM_sizeMAXSTACKITEM)
8650 #endif
8651 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8652 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
8653 && (ffestorag_is_save (eqst) || ffe_is_saveall ())))
8654 TREE_STATIC (eqt) = 1;
8655 else
8656 TREE_STATIC (eqt) = 0;
8657 TREE_PUBLIC (eqt) = 0;
8658 TREE_ADDRESSABLE (eqt) = 1; /* Ensure non-register allocation */
8659 DECL_CONTEXT (eqt) = current_function_decl;
8660 if (init)
8661 DECL_INITIAL (eqt) = error_mark_node;
8662 else
8663 DECL_INITIAL (eqt) = NULL_TREE;
8664
8665 eqt = start_decl (eqt, FALSE);
8666
8667 /* Make sure that any type can live in EQUIVALENCE and be referenced
8668 without getting a bus error. We could pick the most restrictive
8669 alignment of all entities actually placed in the EQUIVALENCE, but
8670 this seems easy enough. */
8671
8672 DECL_ALIGN (eqt) = BIGGEST_ALIGNMENT;
8673 DECL_USER_ALIGN (eqt) = 0;
8674
8675 if ((!is_init && ffe_is_init_local_zero ())
8676 || (is_init && (ffestorag_init (eqst) == NULL)))
8677 init = ffecom_init_zero_ (eqt);
8678
8679 finish_decl (eqt, init, FALSE);
8680
8681 if (is_init)
8682 ffestorag_set_init (eqst, ffebld_new_any ());
8683
8684 {
8685 assert (TREE_CODE (DECL_SIZE_UNIT (eqt)) == INTEGER_CST);
8686 assert (0 == compare_tree_int (DECL_SIZE_UNIT (eqt),
8687 (ffestorag_size (eqst)
8688 + ffestorag_modulo (eqst))));
8689 }
8690
8691 ffestorag_set_hook (eqst, eqt);
8692
8693 ffestorag_drive (ffestorag_list_equivs (eqst),
8694 &ffecom_member_phase2_,
8695 eqst);
8696 }
8697
8698 /* Implement NAMELIST in back end. See f2c/format.c for more info. */
8699
8700 static tree
ffecom_transform_namelist_(ffesymbol s)8701 ffecom_transform_namelist_ (ffesymbol s)
8702 {
8703 tree nmlt;
8704 tree nmltype = ffecom_type_namelist_ ();
8705 tree nmlinits;
8706 tree nameinit;
8707 tree varsinit;
8708 tree nvarsinit;
8709 tree field;
8710 tree high;
8711 int i;
8712 static int mynumber = 0;
8713
8714 nmlt = build_decl (VAR_DECL,
8715 ffecom_get_invented_identifier ("__g77_namelist_%d",
8716 mynumber++),
8717 nmltype);
8718 TREE_STATIC (nmlt) = 1;
8719 DECL_INITIAL (nmlt) = error_mark_node;
8720
8721 nmlt = start_decl (nmlt, FALSE);
8722
8723 /* Process inits. */
8724
8725 i = strlen (ffesymbol_text (s));
8726
8727 high = build_int_2 (i, 0);
8728 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
8729
8730 nameinit = ffecom_build_f2c_string_ (i + 1,
8731 ffesymbol_text (s));
8732 TREE_TYPE (nameinit)
8733 = build_type_variant
8734 (build_array_type
8735 (char_type_node,
8736 build_range_type (ffecom_f2c_ftnlen_type_node,
8737 ffecom_f2c_ftnlen_one_node,
8738 high)),
8739 1, 0);
8740 TREE_CONSTANT (nameinit) = 1;
8741 TREE_STATIC (nameinit) = 1;
8742 nameinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (nameinit)),
8743 nameinit);
8744
8745 varsinit = ffecom_vardesc_array_ (s);
8746 varsinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (varsinit)),
8747 varsinit);
8748 TREE_CONSTANT (varsinit) = 1;
8749 TREE_STATIC (varsinit) = 1;
8750
8751 {
8752 ffebld b;
8753
8754 for (i = 0, b = ffesymbol_namelist (s); b != NULL; b = ffebld_trail (b))
8755 ++i;
8756 }
8757 nvarsinit = build_int_2 (i, 0);
8758 TREE_TYPE (nvarsinit) = integer_type_node;
8759 TREE_CONSTANT (nvarsinit) = 1;
8760 TREE_STATIC (nvarsinit) = 1;
8761
8762 nmlinits = build_tree_list ((field = TYPE_FIELDS (nmltype)), nameinit);
8763 TREE_CHAIN (nmlinits) = build_tree_list ((field = TREE_CHAIN (field)),
8764 varsinit);
8765 TREE_CHAIN (TREE_CHAIN (nmlinits))
8766 = build_tree_list ((field = TREE_CHAIN (field)), nvarsinit);
8767
8768 nmlinits = build (CONSTRUCTOR, nmltype, NULL_TREE, nmlinits);
8769 TREE_CONSTANT (nmlinits) = 1;
8770 TREE_STATIC (nmlinits) = 1;
8771
8772 finish_decl (nmlt, nmlinits, FALSE);
8773
8774 nmlt = ffecom_1 (ADDR_EXPR, build_pointer_type (nmltype), nmlt);
8775
8776 return nmlt;
8777 }
8778
8779 /* A subroutine of ffecom_tree_canonize_ref_. The incoming tree is
8780 analyzed on the assumption it is calculating a pointer to be
8781 indirected through. It must return the proper decl and offset,
8782 taking into account different units of measurements for offsets. */
8783
8784 static void
ffecom_tree_canonize_ptr_(tree * decl,tree * offset,tree t)8785 ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
8786 tree t)
8787 {
8788 switch (TREE_CODE (t))
8789 {
8790 case NOP_EXPR:
8791 case CONVERT_EXPR:
8792 case NON_LVALUE_EXPR:
8793 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
8794 break;
8795
8796 case PLUS_EXPR:
8797 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
8798 if ((*decl == NULL_TREE)
8799 || (*decl == error_mark_node))
8800 break;
8801
8802 if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST)
8803 {
8804 /* An offset into COMMON. */
8805 *offset = fold (build (PLUS_EXPR, TREE_TYPE (*offset),
8806 *offset, TREE_OPERAND (t, 1)));
8807 /* Convert offset (presumably in bytes) into canonical units
8808 (presumably bits). */
8809 *offset = size_binop (MULT_EXPR,
8810 convert (bitsizetype, *offset),
8811 TYPE_SIZE (TREE_TYPE (TREE_TYPE (t))));
8812 break;
8813 }
8814 /* Not a COMMON reference, so an unrecognized pattern. */
8815 *decl = error_mark_node;
8816 break;
8817
8818 case PARM_DECL:
8819 *decl = t;
8820 *offset = bitsize_zero_node;
8821 break;
8822
8823 case ADDR_EXPR:
8824 if (TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL)
8825 {
8826 /* A reference to COMMON. */
8827 *decl = TREE_OPERAND (t, 0);
8828 *offset = bitsize_zero_node;
8829 break;
8830 }
8831 /* Fall through. */
8832 default:
8833 /* Not a COMMON reference, so an unrecognized pattern. */
8834 *decl = error_mark_node;
8835 break;
8836 }
8837 }
8838
8839 /* Given a tree that is possibly intended for use as an lvalue, return
8840 information representing a canonical view of that tree as a decl, an
8841 offset into that decl, and a size for the lvalue.
8842
8843 If there's no applicable decl, NULL_TREE is returned for the decl,
8844 and the other fields are left undefined.
8845
8846 If the tree doesn't fit the recognizable forms, an ERROR_MARK node
8847 is returned for the decl, and the other fields are left undefined.
8848
8849 Otherwise, the decl returned currently is either a VAR_DECL or a
8850 PARM_DECL.
8851
8852 The offset returned is always valid, but of course not necessarily
8853 a constant, and not necessarily converted into the appropriate
8854 type, leaving that up to the caller (so as to avoid that overhead
8855 if the decls being looked at are different anyway).
8856
8857 If the size cannot be determined (e.g. an adjustable array),
8858 an ERROR_MARK node is returned for the size. Otherwise, the
8859 size returned is valid, not necessarily a constant, and not
8860 necessarily converted into the appropriate type as with the
8861 offset.
8862
8863 Note that the offset and size expressions are expressed in the
8864 base storage units (usually bits) rather than in the units of
8865 the type of the decl, because two decls with different types
8866 might overlap but with apparently non-overlapping array offsets,
8867 whereas converting the array offsets to consistant offsets will
8868 reveal the overlap. */
8869
8870 static void
ffecom_tree_canonize_ref_(tree * decl,tree * offset,tree * size,tree t)8871 ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
8872 tree *size, tree t)
8873 {
8874 /* The default path is to report a nonexistant decl. */
8875 *decl = NULL_TREE;
8876
8877 if (t == NULL_TREE)
8878 return;
8879
8880 switch (TREE_CODE (t))
8881 {
8882 case ERROR_MARK:
8883 case IDENTIFIER_NODE:
8884 case INTEGER_CST:
8885 case REAL_CST:
8886 case COMPLEX_CST:
8887 case STRING_CST:
8888 case CONST_DECL:
8889 case PLUS_EXPR:
8890 case MINUS_EXPR:
8891 case MULT_EXPR:
8892 case TRUNC_DIV_EXPR:
8893 case CEIL_DIV_EXPR:
8894 case FLOOR_DIV_EXPR:
8895 case ROUND_DIV_EXPR:
8896 case TRUNC_MOD_EXPR:
8897 case CEIL_MOD_EXPR:
8898 case FLOOR_MOD_EXPR:
8899 case ROUND_MOD_EXPR:
8900 case RDIV_EXPR:
8901 case EXACT_DIV_EXPR:
8902 case FIX_TRUNC_EXPR:
8903 case FIX_CEIL_EXPR:
8904 case FIX_FLOOR_EXPR:
8905 case FIX_ROUND_EXPR:
8906 case FLOAT_EXPR:
8907 case NEGATE_EXPR:
8908 case MIN_EXPR:
8909 case MAX_EXPR:
8910 case ABS_EXPR:
8911 case FFS_EXPR:
8912 case LSHIFT_EXPR:
8913 case RSHIFT_EXPR:
8914 case LROTATE_EXPR:
8915 case RROTATE_EXPR:
8916 case BIT_IOR_EXPR:
8917 case BIT_XOR_EXPR:
8918 case BIT_AND_EXPR:
8919 case BIT_ANDTC_EXPR:
8920 case BIT_NOT_EXPR:
8921 case TRUTH_ANDIF_EXPR:
8922 case TRUTH_ORIF_EXPR:
8923 case TRUTH_AND_EXPR:
8924 case TRUTH_OR_EXPR:
8925 case TRUTH_XOR_EXPR:
8926 case TRUTH_NOT_EXPR:
8927 case LT_EXPR:
8928 case LE_EXPR:
8929 case GT_EXPR:
8930 case GE_EXPR:
8931 case EQ_EXPR:
8932 case NE_EXPR:
8933 case COMPLEX_EXPR:
8934 case CONJ_EXPR:
8935 case REALPART_EXPR:
8936 case IMAGPART_EXPR:
8937 case LABEL_EXPR:
8938 case COMPONENT_REF:
8939 case COMPOUND_EXPR:
8940 case ADDR_EXPR:
8941 return;
8942
8943 case VAR_DECL:
8944 case PARM_DECL:
8945 *decl = t;
8946 *offset = bitsize_zero_node;
8947 *size = TYPE_SIZE (TREE_TYPE (t));
8948 return;
8949
8950 case ARRAY_REF:
8951 {
8952 tree array = TREE_OPERAND (t, 0);
8953 tree element = TREE_OPERAND (t, 1);
8954 tree init_offset;
8955
8956 if ((array == NULL_TREE)
8957 || (element == NULL_TREE))
8958 {
8959 *decl = error_mark_node;
8960 return;
8961 }
8962
8963 ffecom_tree_canonize_ref_ (decl, &init_offset, size,
8964 array);
8965 if ((*decl == NULL_TREE)
8966 || (*decl == error_mark_node))
8967 return;
8968
8969 /* Calculate ((element - base) * NBBY) + init_offset. */
8970 *offset = fold (build (MINUS_EXPR, TREE_TYPE (element),
8971 element,
8972 TYPE_MIN_VALUE (TYPE_DOMAIN
8973 (TREE_TYPE (array)))));
8974
8975 *offset = size_binop (MULT_EXPR,
8976 convert (bitsizetype, *offset),
8977 TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))));
8978
8979 *offset = size_binop (PLUS_EXPR, init_offset, *offset);
8980
8981 *size = TYPE_SIZE (TREE_TYPE (t));
8982 return;
8983 }
8984
8985 case INDIRECT_REF:
8986
8987 /* Most of this code is to handle references to COMMON. And so
8988 far that is useful only for calling library functions, since
8989 external (user) functions might reference common areas. But
8990 even calling an external function, it's worthwhile to decode
8991 COMMON references because if not storing into COMMON, we don't
8992 want COMMON-based arguments to gratuitously force use of a
8993 temporary. */
8994
8995 *size = TYPE_SIZE (TREE_TYPE (t));
8996
8997 ffecom_tree_canonize_ptr_ (decl, offset,
8998 TREE_OPERAND (t, 0));
8999
9000 return;
9001
9002 case CONVERT_EXPR:
9003 case NOP_EXPR:
9004 case MODIFY_EXPR:
9005 case NON_LVALUE_EXPR:
9006 case RESULT_DECL:
9007 case FIELD_DECL:
9008 case COND_EXPR: /* More cases than we can handle. */
9009 case SAVE_EXPR:
9010 case REFERENCE_EXPR:
9011 case PREDECREMENT_EXPR:
9012 case PREINCREMENT_EXPR:
9013 case POSTDECREMENT_EXPR:
9014 case POSTINCREMENT_EXPR:
9015 case CALL_EXPR:
9016 default:
9017 *decl = error_mark_node;
9018 return;
9019 }
9020 }
9021
9022 /* Do divide operation appropriate to type of operands. */
9023
9024 static tree
ffecom_tree_divide_(tree tree_type,tree left,tree right,tree dest_tree,ffebld dest,bool * dest_used,tree hook)9025 ffecom_tree_divide_ (tree tree_type, tree left, tree right,
9026 tree dest_tree, ffebld dest, bool *dest_used,
9027 tree hook)
9028 {
9029 if ((left == error_mark_node)
9030 || (right == error_mark_node))
9031 return error_mark_node;
9032
9033 switch (TREE_CODE (tree_type))
9034 {
9035 case INTEGER_TYPE:
9036 return ffecom_2 (TRUNC_DIV_EXPR, tree_type,
9037 left,
9038 right);
9039
9040 case COMPLEX_TYPE:
9041 if (! optimize_size)
9042 return ffecom_2 (RDIV_EXPR, tree_type,
9043 left,
9044 right);
9045 {
9046 ffecomGfrt ix;
9047
9048 if (TREE_TYPE (tree_type)
9049 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9050 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9051 else
9052 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
9053
9054 left = ffecom_1 (ADDR_EXPR,
9055 build_pointer_type (TREE_TYPE (left)),
9056 left);
9057 left = build_tree_list (NULL_TREE, left);
9058 right = ffecom_1 (ADDR_EXPR,
9059 build_pointer_type (TREE_TYPE (right)),
9060 right);
9061 right = build_tree_list (NULL_TREE, right);
9062 TREE_CHAIN (left) = right;
9063
9064 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9065 ffecom_gfrt_kindtype (ix),
9066 ffe_is_f2c_library (),
9067 tree_type,
9068 left,
9069 dest_tree, dest, dest_used,
9070 NULL_TREE, TRUE, hook);
9071 }
9072 break;
9073
9074 case RECORD_TYPE:
9075 {
9076 ffecomGfrt ix;
9077
9078 if (TREE_TYPE (TYPE_FIELDS (tree_type))
9079 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9080 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9081 else
9082 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
9083
9084 left = ffecom_1 (ADDR_EXPR,
9085 build_pointer_type (TREE_TYPE (left)),
9086 left);
9087 left = build_tree_list (NULL_TREE, left);
9088 right = ffecom_1 (ADDR_EXPR,
9089 build_pointer_type (TREE_TYPE (right)),
9090 right);
9091 right = build_tree_list (NULL_TREE, right);
9092 TREE_CHAIN (left) = right;
9093
9094 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9095 ffecom_gfrt_kindtype (ix),
9096 ffe_is_f2c_library (),
9097 tree_type,
9098 left,
9099 dest_tree, dest, dest_used,
9100 NULL_TREE, TRUE, hook);
9101 }
9102 break;
9103
9104 default:
9105 return ffecom_2 (RDIV_EXPR, tree_type,
9106 left,
9107 right);
9108 }
9109 }
9110
9111 /* Build type info for non-dummy variable. */
9112
9113 static tree
ffecom_type_localvar_(ffesymbol s,ffeinfoBasictype bt,ffeinfoKindtype kt)9114 ffecom_type_localvar_ (ffesymbol s, ffeinfoBasictype bt,
9115 ffeinfoKindtype kt)
9116 {
9117 tree type;
9118 ffebld dl;
9119 ffebld dim;
9120 tree lowt;
9121 tree hight;
9122
9123 type = ffecom_tree_type[bt][kt];
9124 if (bt == FFEINFO_basictypeCHARACTER)
9125 {
9126 hight = build_int_2 (ffesymbol_size (s), 0);
9127 TREE_TYPE (hight) = ffecom_f2c_ftnlen_type_node;
9128
9129 type
9130 = build_array_type
9131 (type,
9132 build_range_type (ffecom_f2c_ftnlen_type_node,
9133 ffecom_f2c_ftnlen_one_node,
9134 hight));
9135 type = ffecom_check_size_overflow_ (s, type, FALSE);
9136 }
9137
9138 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
9139 {
9140 if (type == error_mark_node)
9141 break;
9142
9143 dim = ffebld_head (dl);
9144 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
9145
9146 if (ffebld_left (dim) == NULL)
9147 lowt = integer_one_node;
9148 else
9149 lowt = ffecom_expr (ffebld_left (dim));
9150
9151 if (TREE_CODE (lowt) != INTEGER_CST)
9152 lowt = variable_size (lowt);
9153
9154 assert (ffebld_right (dim) != NULL);
9155 hight = ffecom_expr (ffebld_right (dim));
9156
9157 if (TREE_CODE (hight) != INTEGER_CST)
9158 hight = variable_size (hight);
9159
9160 type = build_array_type (type,
9161 build_range_type (ffecom_integer_type_node,
9162 lowt, hight));
9163 type = ffecom_check_size_overflow_ (s, type, FALSE);
9164 }
9165
9166 return type;
9167 }
9168
9169 /* Build Namelist type. */
9170
9171 static GTY(()) tree ffecom_type_namelist_var;
9172 static tree
ffecom_type_namelist_()9173 ffecom_type_namelist_ ()
9174 {
9175 if (ffecom_type_namelist_var == NULL_TREE)
9176 {
9177 tree namefield, varsfield, nvarsfield, vardesctype, type;
9178
9179 vardesctype = ffecom_type_vardesc_ ();
9180
9181 type = make_node (RECORD_TYPE);
9182
9183 vardesctype = build_pointer_type (build_pointer_type (vardesctype));
9184
9185 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9186 string_type_node);
9187 varsfield = ffecom_decl_field (type, namefield, "vars", vardesctype);
9188 nvarsfield = ffecom_decl_field (type, varsfield, "nvars",
9189 integer_type_node);
9190
9191 TYPE_FIELDS (type) = namefield;
9192 layout_type (type);
9193
9194 ffecom_type_namelist_var = type;
9195 }
9196
9197 return ffecom_type_namelist_var;
9198 }
9199
9200 /* Build Vardesc type. */
9201
9202 static GTY(()) tree ffecom_type_vardesc_var;
9203 static tree
ffecom_type_vardesc_()9204 ffecom_type_vardesc_ ()
9205 {
9206 if (ffecom_type_vardesc_var == NULL_TREE)
9207 {
9208 tree namefield, addrfield, dimsfield, typefield, type;
9209 type = make_node (RECORD_TYPE);
9210
9211 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9212 string_type_node);
9213 addrfield = ffecom_decl_field (type, namefield, "addr",
9214 string_type_node);
9215 dimsfield = ffecom_decl_field (type, addrfield, "dims",
9216 ffecom_f2c_ptr_to_ftnlen_type_node);
9217 typefield = ffecom_decl_field (type, dimsfield, "type",
9218 integer_type_node);
9219
9220 TYPE_FIELDS (type) = namefield;
9221 layout_type (type);
9222
9223 ffecom_type_vardesc_var = type;
9224 }
9225
9226 return ffecom_type_vardesc_var;
9227 }
9228
9229 static tree
ffecom_vardesc_(ffebld expr)9230 ffecom_vardesc_ (ffebld expr)
9231 {
9232 ffesymbol s;
9233
9234 assert (ffebld_op (expr) == FFEBLD_opSYMTER);
9235 s = ffebld_symter (expr);
9236
9237 if (ffesymbol_hook (s).vardesc_tree == NULL_TREE)
9238 {
9239 int i;
9240 tree vardesctype = ffecom_type_vardesc_ ();
9241 tree var;
9242 tree nameinit;
9243 tree dimsinit;
9244 tree addrinit;
9245 tree typeinit;
9246 tree field;
9247 tree varinits;
9248 static int mynumber = 0;
9249
9250 var = build_decl (VAR_DECL,
9251 ffecom_get_invented_identifier ("__g77_vardesc_%d",
9252 mynumber++),
9253 vardesctype);
9254 TREE_STATIC (var) = 1;
9255 DECL_INITIAL (var) = error_mark_node;
9256
9257 var = start_decl (var, FALSE);
9258
9259 /* Process inits. */
9260
9261 nameinit = ffecom_build_f2c_string_ ((i = strlen (ffesymbol_text (s)))
9262 + 1,
9263 ffesymbol_text (s));
9264 TREE_TYPE (nameinit)
9265 = build_type_variant
9266 (build_array_type
9267 (char_type_node,
9268 build_range_type (integer_type_node,
9269 integer_one_node,
9270 build_int_2 (i, 0))),
9271 1, 0);
9272 TREE_CONSTANT (nameinit) = 1;
9273 TREE_STATIC (nameinit) = 1;
9274 nameinit = ffecom_1 (ADDR_EXPR,
9275 build_pointer_type (TREE_TYPE (nameinit)),
9276 nameinit);
9277
9278 addrinit = ffecom_arg_ptr_to_expr (expr, &typeinit);
9279
9280 dimsinit = ffecom_vardesc_dims_ (s);
9281
9282 if (typeinit == NULL_TREE)
9283 {
9284 ffeinfoBasictype bt = ffesymbol_basictype (s);
9285 ffeinfoKindtype kt = ffesymbol_kindtype (s);
9286 int tc = ffecom_f2c_typecode (bt, kt);
9287
9288 assert (tc != -1);
9289 typeinit = build_int_2 (tc, (tc < 0) ? -1 : 0);
9290 }
9291 else
9292 typeinit = ffecom_1 (NEGATE_EXPR, TREE_TYPE (typeinit), typeinit);
9293
9294 varinits = build_tree_list ((field = TYPE_FIELDS (vardesctype)),
9295 nameinit);
9296 TREE_CHAIN (varinits) = build_tree_list ((field = TREE_CHAIN (field)),
9297 addrinit);
9298 TREE_CHAIN (TREE_CHAIN (varinits))
9299 = build_tree_list ((field = TREE_CHAIN (field)), dimsinit);
9300 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (varinits)))
9301 = build_tree_list ((field = TREE_CHAIN (field)), typeinit);
9302
9303 varinits = build (CONSTRUCTOR, vardesctype, NULL_TREE, varinits);
9304 TREE_CONSTANT (varinits) = 1;
9305 TREE_STATIC (varinits) = 1;
9306
9307 finish_decl (var, varinits, FALSE);
9308
9309 var = ffecom_1 (ADDR_EXPR, build_pointer_type (vardesctype), var);
9310
9311 ffesymbol_hook (s).vardesc_tree = var;
9312 }
9313
9314 return ffesymbol_hook (s).vardesc_tree;
9315 }
9316
9317 static tree
ffecom_vardesc_array_(ffesymbol s)9318 ffecom_vardesc_array_ (ffesymbol s)
9319 {
9320 ffebld b;
9321 tree list;
9322 tree item = NULL_TREE;
9323 tree var;
9324 int i;
9325 static int mynumber = 0;
9326
9327 for (i = 0, list = NULL_TREE, b = ffesymbol_namelist (s);
9328 b != NULL;
9329 b = ffebld_trail (b), ++i)
9330 {
9331 tree t;
9332
9333 t = ffecom_vardesc_ (ffebld_head (b));
9334
9335 if (list == NULL_TREE)
9336 list = item = build_tree_list (NULL_TREE, t);
9337 else
9338 {
9339 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9340 item = TREE_CHAIN (item);
9341 }
9342 }
9343
9344 item = build_array_type (build_pointer_type (ffecom_type_vardesc_ ()),
9345 build_range_type (integer_type_node,
9346 integer_one_node,
9347 build_int_2 (i, 0)));
9348 list = build (CONSTRUCTOR, item, NULL_TREE, list);
9349 TREE_CONSTANT (list) = 1;
9350 TREE_STATIC (list) = 1;
9351
9352 var = ffecom_get_invented_identifier ("__g77_vardesc_array_%d", mynumber++);
9353 var = build_decl (VAR_DECL, var, item);
9354 TREE_STATIC (var) = 1;
9355 DECL_INITIAL (var) = error_mark_node;
9356 var = start_decl (var, FALSE);
9357 finish_decl (var, list, FALSE);
9358
9359 return var;
9360 }
9361
9362 static tree
ffecom_vardesc_dims_(ffesymbol s)9363 ffecom_vardesc_dims_ (ffesymbol s)
9364 {
9365 if (ffesymbol_dims (s) == NULL)
9366 return convert (ffecom_f2c_ptr_to_ftnlen_type_node,
9367 integer_zero_node);
9368
9369 {
9370 ffebld b;
9371 ffebld e;
9372 tree list;
9373 tree backlist;
9374 tree item = NULL_TREE;
9375 tree var;
9376 tree numdim;
9377 tree numelem;
9378 tree baseoff = NULL_TREE;
9379 static int mynumber = 0;
9380
9381 numdim = build_int_2 ((int) ffesymbol_rank (s), 0);
9382 TREE_TYPE (numdim) = ffecom_f2c_ftnlen_type_node;
9383
9384 numelem = ffecom_expr (ffesymbol_arraysize (s));
9385 TREE_TYPE (numelem) = ffecom_f2c_ftnlen_type_node;
9386
9387 list = NULL_TREE;
9388 backlist = NULL_TREE;
9389 for (b = ffesymbol_dims (s), e = ffesymbol_extents (s);
9390 b != NULL;
9391 b = ffebld_trail (b), e = ffebld_trail (e))
9392 {
9393 tree t;
9394 tree low;
9395 tree back;
9396
9397 if (ffebld_trail (b) == NULL)
9398 t = NULL_TREE;
9399 else
9400 {
9401 t = convert (ffecom_f2c_ftnlen_type_node,
9402 ffecom_expr (ffebld_head (e)));
9403
9404 if (list == NULL_TREE)
9405 list = item = build_tree_list (NULL_TREE, t);
9406 else
9407 {
9408 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9409 item = TREE_CHAIN (item);
9410 }
9411 }
9412
9413 if (ffebld_left (ffebld_head (b)) == NULL)
9414 low = ffecom_integer_one_node;
9415 else
9416 low = ffecom_expr (ffebld_left (ffebld_head (b)));
9417 low = convert (ffecom_f2c_ftnlen_type_node, low);
9418
9419 back = build_tree_list (low, t);
9420 TREE_CHAIN (back) = backlist;
9421 backlist = back;
9422 }
9423
9424 for (item = backlist; item != NULL_TREE; item = TREE_CHAIN (item))
9425 {
9426 if (TREE_VALUE (item) == NULL_TREE)
9427 baseoff = TREE_PURPOSE (item);
9428 else
9429 baseoff = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
9430 TREE_PURPOSE (item),
9431 ffecom_2 (MULT_EXPR,
9432 ffecom_f2c_ftnlen_type_node,
9433 TREE_VALUE (item),
9434 baseoff));
9435 }
9436
9437 /* backlist now dead, along with all TREE_PURPOSEs on it. */
9438
9439 baseoff = build_tree_list (NULL_TREE, baseoff);
9440 TREE_CHAIN (baseoff) = list;
9441
9442 numelem = build_tree_list (NULL_TREE, numelem);
9443 TREE_CHAIN (numelem) = baseoff;
9444
9445 numdim = build_tree_list (NULL_TREE, numdim);
9446 TREE_CHAIN (numdim) = numelem;
9447
9448 item = build_array_type (ffecom_f2c_ftnlen_type_node,
9449 build_range_type (integer_type_node,
9450 integer_zero_node,
9451 build_int_2
9452 ((int) ffesymbol_rank (s)
9453 + 2, 0)));
9454 list = build (CONSTRUCTOR, item, NULL_TREE, numdim);
9455 TREE_CONSTANT (list) = 1;
9456 TREE_STATIC (list) = 1;
9457
9458 var = ffecom_get_invented_identifier ("__g77_dims_%d", mynumber++);
9459 var = build_decl (VAR_DECL, var, item);
9460 TREE_STATIC (var) = 1;
9461 DECL_INITIAL (var) = error_mark_node;
9462 var = start_decl (var, FALSE);
9463 finish_decl (var, list, FALSE);
9464
9465 var = ffecom_1 (ADDR_EXPR, build_pointer_type (item), var);
9466
9467 return var;
9468 }
9469 }
9470
9471 /* Essentially does a "fold (build1 (code, type, node))" while checking
9472 for certain housekeeping things.
9473
9474 NOTE: for building an ADDR_EXPR around a FUNCTION_DECL, use
9475 ffecom_1_fn instead. */
9476
9477 tree
ffecom_1(enum tree_code code,tree type,tree node)9478 ffecom_1 (enum tree_code code, tree type, tree node)
9479 {
9480 tree item;
9481
9482 if ((node == error_mark_node)
9483 || (type == error_mark_node))
9484 return error_mark_node;
9485
9486 if (code == ADDR_EXPR)
9487 {
9488 if (!ffe_mark_addressable (node))
9489 assert ("can't mark_addressable this node!" == NULL);
9490 }
9491
9492 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
9493 {
9494 tree realtype;
9495
9496 case REALPART_EXPR:
9497 item = build (COMPONENT_REF, type, node, TYPE_FIELDS (TREE_TYPE (node)));
9498 break;
9499
9500 case IMAGPART_EXPR:
9501 item = build (COMPONENT_REF, type, node, TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (node))));
9502 break;
9503
9504
9505 case NEGATE_EXPR:
9506 if (TREE_CODE (type) != RECORD_TYPE)
9507 {
9508 item = build1 (code, type, node);
9509 break;
9510 }
9511 node = ffecom_stabilize_aggregate_ (node);
9512 realtype = TREE_TYPE (TYPE_FIELDS (type));
9513 item =
9514 ffecom_2 (COMPLEX_EXPR, type,
9515 ffecom_1 (NEGATE_EXPR, realtype,
9516 ffecom_1 (REALPART_EXPR, realtype,
9517 node)),
9518 ffecom_1 (NEGATE_EXPR, realtype,
9519 ffecom_1 (IMAGPART_EXPR, realtype,
9520 node)));
9521 break;
9522
9523 default:
9524 item = build1 (code, type, node);
9525 break;
9526 }
9527
9528 if (TREE_SIDE_EFFECTS (node))
9529 TREE_SIDE_EFFECTS (item) = 1;
9530 if (code == ADDR_EXPR && staticp (node))
9531 TREE_CONSTANT (item) = 1;
9532 else if (code == INDIRECT_REF)
9533 TREE_READONLY (item) = TYPE_READONLY (type);
9534 return fold (item);
9535 }
9536
9537 /* Like ffecom_1 (ADDR_EXPR, TREE_TYPE (node), node), except
9538 handles TREE_CODE (node) == FUNCTION_DECL. In particular,
9539 does not set TREE_ADDRESSABLE (because calling an inline
9540 function does not mean the function needs to be separately
9541 compiled). */
9542
9543 tree
ffecom_1_fn(tree node)9544 ffecom_1_fn (tree node)
9545 {
9546 tree item;
9547 tree type;
9548
9549 if (node == error_mark_node)
9550 return error_mark_node;
9551
9552 type = build_type_variant (TREE_TYPE (node),
9553 TREE_READONLY (node),
9554 TREE_THIS_VOLATILE (node));
9555 item = build1 (ADDR_EXPR,
9556 build_pointer_type (type), node);
9557 if (TREE_SIDE_EFFECTS (node))
9558 TREE_SIDE_EFFECTS (item) = 1;
9559 if (staticp (node))
9560 TREE_CONSTANT (item) = 1;
9561 return fold (item);
9562 }
9563
9564 /* Essentially does a "fold (build (code, type, node1, node2))" while
9565 checking for certain housekeeping things. */
9566
9567 tree
ffecom_2(enum tree_code code,tree type,tree node1,tree node2)9568 ffecom_2 (enum tree_code code, tree type, tree node1,
9569 tree node2)
9570 {
9571 tree item;
9572
9573 if ((node1 == error_mark_node)
9574 || (node2 == error_mark_node)
9575 || (type == error_mark_node))
9576 return error_mark_node;
9577
9578 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
9579 {
9580 tree a, b, c, d, realtype;
9581
9582 case CONJ_EXPR:
9583 assert ("no CONJ_EXPR support yet" == NULL);
9584 return error_mark_node;
9585
9586 case COMPLEX_EXPR:
9587 item = build_tree_list (TYPE_FIELDS (type), node1);
9588 TREE_CHAIN (item) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), node2);
9589 item = build (CONSTRUCTOR, type, NULL_TREE, item);
9590 break;
9591
9592 case PLUS_EXPR:
9593 if (TREE_CODE (type) != RECORD_TYPE)
9594 {
9595 item = build (code, type, node1, node2);
9596 break;
9597 }
9598 node1 = ffecom_stabilize_aggregate_ (node1);
9599 node2 = ffecom_stabilize_aggregate_ (node2);
9600 realtype = TREE_TYPE (TYPE_FIELDS (type));
9601 item =
9602 ffecom_2 (COMPLEX_EXPR, type,
9603 ffecom_2 (PLUS_EXPR, realtype,
9604 ffecom_1 (REALPART_EXPR, realtype,
9605 node1),
9606 ffecom_1 (REALPART_EXPR, realtype,
9607 node2)),
9608 ffecom_2 (PLUS_EXPR, realtype,
9609 ffecom_1 (IMAGPART_EXPR, realtype,
9610 node1),
9611 ffecom_1 (IMAGPART_EXPR, realtype,
9612 node2)));
9613 break;
9614
9615 case MINUS_EXPR:
9616 if (TREE_CODE (type) != RECORD_TYPE)
9617 {
9618 item = build (code, type, node1, node2);
9619 break;
9620 }
9621 node1 = ffecom_stabilize_aggregate_ (node1);
9622 node2 = ffecom_stabilize_aggregate_ (node2);
9623 realtype = TREE_TYPE (TYPE_FIELDS (type));
9624 item =
9625 ffecom_2 (COMPLEX_EXPR, type,
9626 ffecom_2 (MINUS_EXPR, realtype,
9627 ffecom_1 (REALPART_EXPR, realtype,
9628 node1),
9629 ffecom_1 (REALPART_EXPR, realtype,
9630 node2)),
9631 ffecom_2 (MINUS_EXPR, realtype,
9632 ffecom_1 (IMAGPART_EXPR, realtype,
9633 node1),
9634 ffecom_1 (IMAGPART_EXPR, realtype,
9635 node2)));
9636 break;
9637
9638 case MULT_EXPR:
9639 if (TREE_CODE (type) != RECORD_TYPE)
9640 {
9641 item = build (code, type, node1, node2);
9642 break;
9643 }
9644 node1 = ffecom_stabilize_aggregate_ (node1);
9645 node2 = ffecom_stabilize_aggregate_ (node2);
9646 realtype = TREE_TYPE (TYPE_FIELDS (type));
9647 a = save_expr (ffecom_1 (REALPART_EXPR, realtype,
9648 node1));
9649 b = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
9650 node1));
9651 c = save_expr (ffecom_1 (REALPART_EXPR, realtype,
9652 node2));
9653 d = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
9654 node2));
9655 item =
9656 ffecom_2 (COMPLEX_EXPR, type,
9657 ffecom_2 (MINUS_EXPR, realtype,
9658 ffecom_2 (MULT_EXPR, realtype,
9659 a,
9660 c),
9661 ffecom_2 (MULT_EXPR, realtype,
9662 b,
9663 d)),
9664 ffecom_2 (PLUS_EXPR, realtype,
9665 ffecom_2 (MULT_EXPR, realtype,
9666 a,
9667 d),
9668 ffecom_2 (MULT_EXPR, realtype,
9669 c,
9670 b)));
9671 break;
9672
9673 case EQ_EXPR:
9674 if ((TREE_CODE (node1) != RECORD_TYPE)
9675 && (TREE_CODE (node2) != RECORD_TYPE))
9676 {
9677 item = build (code, type, node1, node2);
9678 break;
9679 }
9680 assert (TREE_CODE (node1) == RECORD_TYPE);
9681 assert (TREE_CODE (node2) == RECORD_TYPE);
9682 node1 = ffecom_stabilize_aggregate_ (node1);
9683 node2 = ffecom_stabilize_aggregate_ (node2);
9684 realtype = TREE_TYPE (TYPE_FIELDS (type));
9685 item =
9686 ffecom_2 (TRUTH_ANDIF_EXPR, type,
9687 ffecom_2 (code, type,
9688 ffecom_1 (REALPART_EXPR, realtype,
9689 node1),
9690 ffecom_1 (REALPART_EXPR, realtype,
9691 node2)),
9692 ffecom_2 (code, type,
9693 ffecom_1 (IMAGPART_EXPR, realtype,
9694 node1),
9695 ffecom_1 (IMAGPART_EXPR, realtype,
9696 node2)));
9697 break;
9698
9699 case NE_EXPR:
9700 if ((TREE_CODE (node1) != RECORD_TYPE)
9701 && (TREE_CODE (node2) != RECORD_TYPE))
9702 {
9703 item = build (code, type, node1, node2);
9704 break;
9705 }
9706 assert (TREE_CODE (node1) == RECORD_TYPE);
9707 assert (TREE_CODE (node2) == RECORD_TYPE);
9708 node1 = ffecom_stabilize_aggregate_ (node1);
9709 node2 = ffecom_stabilize_aggregate_ (node2);
9710 realtype = TREE_TYPE (TYPE_FIELDS (type));
9711 item =
9712 ffecom_2 (TRUTH_ORIF_EXPR, type,
9713 ffecom_2 (code, type,
9714 ffecom_1 (REALPART_EXPR, realtype,
9715 node1),
9716 ffecom_1 (REALPART_EXPR, realtype,
9717 node2)),
9718 ffecom_2 (code, type,
9719 ffecom_1 (IMAGPART_EXPR, realtype,
9720 node1),
9721 ffecom_1 (IMAGPART_EXPR, realtype,
9722 node2)));
9723 break;
9724
9725 default:
9726 item = build (code, type, node1, node2);
9727 break;
9728 }
9729
9730 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2))
9731 TREE_SIDE_EFFECTS (item) = 1;
9732 return fold (item);
9733 }
9734
9735 /* ffecom_2pass_advise_entrypoint -- Advise that there's this entrypoint
9736
9737 ffesymbol s; // the ENTRY point itself
9738 if (ffecom_2pass_advise_entrypoint(s))
9739 // the ENTRY point has been accepted
9740
9741 Does whatever compiler needs to do when it learns about the entrypoint,
9742 like determine the return type of the master function, count the
9743 number of entrypoints, etc. Returns FALSE if the return type is
9744 not compatible with the return type(s) of other entrypoint(s).
9745
9746 NOTE: for every call to this fn that returns TRUE, _do_entrypoint must
9747 later (after _finish_progunit) be called with the same entrypoint(s)
9748 as passed to this fn for which TRUE was returned.
9749
9750 03-Jan-92 JCB 2.0
9751 Return FALSE if the return type conflicts with previous entrypoints. */
9752
9753 bool
ffecom_2pass_advise_entrypoint(ffesymbol entry)9754 ffecom_2pass_advise_entrypoint (ffesymbol entry)
9755 {
9756 ffebld list; /* opITEM. */
9757 ffebld mlist; /* opITEM. */
9758 ffebld plist; /* opITEM. */
9759 ffebld arg; /* ffebld_head(opITEM). */
9760 ffebld item; /* opITEM. */
9761 ffesymbol s; /* ffebld_symter(arg). */
9762 ffeinfoBasictype bt = ffesymbol_basictype (entry);
9763 ffeinfoKindtype kt = ffesymbol_kindtype (entry);
9764 ffetargetCharacterSize size = ffesymbol_size (entry);
9765 bool ok;
9766
9767 if (ffecom_num_entrypoints_ == 0)
9768 { /* First entrypoint, make list of main
9769 arglist's dummies. */
9770 assert (ffecom_primary_entry_ != NULL);
9771
9772 ffecom_master_bt_ = ffesymbol_basictype (ffecom_primary_entry_);
9773 ffecom_master_kt_ = ffesymbol_kindtype (ffecom_primary_entry_);
9774 ffecom_master_size_ = ffesymbol_size (ffecom_primary_entry_);
9775
9776 for (plist = NULL, list = ffesymbol_dummyargs (ffecom_primary_entry_);
9777 list != NULL;
9778 list = ffebld_trail (list))
9779 {
9780 arg = ffebld_head (list);
9781 if (ffebld_op (arg) != FFEBLD_opSYMTER)
9782 continue; /* Alternate return or some such thing. */
9783 item = ffebld_new_item (arg, NULL);
9784 if (plist == NULL)
9785 ffecom_master_arglist_ = item;
9786 else
9787 ffebld_set_trail (plist, item);
9788 plist = item;
9789 }
9790 }
9791
9792 /* If necessary, scan entry arglist for alternate returns. Do this scan
9793 apparently redundantly (it's done below to UNIONize the arglists) so
9794 that we don't complain about RETURN 1 if an offending ENTRY is the only
9795 one with an alternate return. */
9796
9797 if (!ffecom_is_altreturning_)
9798 {
9799 for (list = ffesymbol_dummyargs (entry);
9800 list != NULL;
9801 list = ffebld_trail (list))
9802 {
9803 arg = ffebld_head (list);
9804 if (ffebld_op (arg) == FFEBLD_opSTAR)
9805 {
9806 ffecom_is_altreturning_ = TRUE;
9807 break;
9808 }
9809 }
9810 }
9811
9812 /* Now check type compatibility. */
9813
9814 switch (ffecom_master_bt_)
9815 {
9816 case FFEINFO_basictypeNONE:
9817 ok = (bt != FFEINFO_basictypeCHARACTER);
9818 break;
9819
9820 case FFEINFO_basictypeCHARACTER:
9821 ok
9822 = (bt == FFEINFO_basictypeCHARACTER)
9823 && (kt == ffecom_master_kt_)
9824 && (size == ffecom_master_size_);
9825 break;
9826
9827 case FFEINFO_basictypeANY:
9828 return FALSE; /* Just don't bother. */
9829
9830 default:
9831 if (bt == FFEINFO_basictypeCHARACTER)
9832 {
9833 ok = FALSE;
9834 break;
9835 }
9836 ok = TRUE;
9837 if ((bt != ffecom_master_bt_) || (kt != ffecom_master_kt_))
9838 {
9839 ffecom_master_bt_ = FFEINFO_basictypeNONE;
9840 ffecom_master_kt_ = FFEINFO_kindtypeNONE;
9841 }
9842 break;
9843 }
9844
9845 if (!ok)
9846 {
9847 ffebad_start (FFEBAD_ENTRY_CONFLICTS);
9848 ffest_ffebad_here_current_stmt (0);
9849 ffebad_finish ();
9850 return FALSE; /* Can't handle entrypoint. */
9851 }
9852
9853 /* Entrypoint type compatible with previous types. */
9854
9855 ++ffecom_num_entrypoints_;
9856
9857 /* Master-arg-list = UNION(Master-arg-list,entry-arg-list). */
9858
9859 for (list = ffesymbol_dummyargs (entry);
9860 list != NULL;
9861 list = ffebld_trail (list))
9862 {
9863 arg = ffebld_head (list);
9864 if (ffebld_op (arg) != FFEBLD_opSYMTER)
9865 continue; /* Alternate return or some such thing. */
9866 s = ffebld_symter (arg);
9867 for (plist = NULL, mlist = ffecom_master_arglist_;
9868 mlist != NULL;
9869 plist = mlist, mlist = ffebld_trail (mlist))
9870 { /* plist points to previous item for easy
9871 appending of arg. */
9872 if (ffebld_symter (ffebld_head (mlist)) == s)
9873 break; /* Already have this arg in the master list. */
9874 }
9875 if (mlist != NULL)
9876 continue; /* Already have this arg in the master list. */
9877
9878 /* Append this arg to the master list. */
9879
9880 item = ffebld_new_item (arg, NULL);
9881 if (plist == NULL)
9882 ffecom_master_arglist_ = item;
9883 else
9884 ffebld_set_trail (plist, item);
9885 }
9886
9887 return TRUE;
9888 }
9889
9890 /* ffecom_2pass_do_entrypoint -- Do compilation of entrypoint
9891
9892 ffesymbol s; // the ENTRY point itself
9893 ffecom_2pass_do_entrypoint(s);
9894
9895 Does whatever compiler needs to do to make the entrypoint actually
9896 happen. Must be called for each entrypoint after
9897 ffecom_finish_progunit is called. */
9898
9899 void
ffecom_2pass_do_entrypoint(ffesymbol entry)9900 ffecom_2pass_do_entrypoint (ffesymbol entry)
9901 {
9902 static int mfn_num = 0;
9903 static int ent_num;
9904
9905 if (mfn_num != ffecom_num_fns_)
9906 { /* First entrypoint for this program unit. */
9907 ent_num = 1;
9908 mfn_num = ffecom_num_fns_;
9909 ffecom_do_entry_ (ffecom_primary_entry_, 0);
9910 }
9911 else
9912 ++ent_num;
9913
9914 --ffecom_num_entrypoints_;
9915
9916 ffecom_do_entry_ (entry, ent_num);
9917 }
9918
9919 /* Essentially does a "fold (build (code, type, node1, node2))" while
9920 checking for certain housekeeping things. Always sets
9921 TREE_SIDE_EFFECTS. */
9922
9923 tree
ffecom_2s(enum tree_code code,tree type,tree node1,tree node2)9924 ffecom_2s (enum tree_code code, tree type, tree node1,
9925 tree node2)
9926 {
9927 tree item;
9928
9929 if ((node1 == error_mark_node)
9930 || (node2 == error_mark_node)
9931 || (type == error_mark_node))
9932 return error_mark_node;
9933
9934 item = build (code, type, node1, node2);
9935 TREE_SIDE_EFFECTS (item) = 1;
9936 return fold (item);
9937 }
9938
9939 /* Essentially does a "fold (build (code, type, node1, node2, node3))" while
9940 checking for certain housekeeping things. */
9941
9942 tree
ffecom_3(enum tree_code code,tree type,tree node1,tree node2,tree node3)9943 ffecom_3 (enum tree_code code, tree type, tree node1,
9944 tree node2, tree node3)
9945 {
9946 tree item;
9947
9948 if ((node1 == error_mark_node)
9949 || (node2 == error_mark_node)
9950 || (node3 == error_mark_node)
9951 || (type == error_mark_node))
9952 return error_mark_node;
9953
9954 item = build (code, type, node1, node2, node3);
9955 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2)
9956 || (node3 != NULL_TREE && TREE_SIDE_EFFECTS (node3)))
9957 TREE_SIDE_EFFECTS (item) = 1;
9958 return fold (item);
9959 }
9960
9961 /* Essentially does a "fold (build (code, type, node1, node2, node3))" while
9962 checking for certain housekeeping things. Always sets
9963 TREE_SIDE_EFFECTS. */
9964
9965 tree
ffecom_3s(enum tree_code code,tree type,tree node1,tree node2,tree node3)9966 ffecom_3s (enum tree_code code, tree type, tree node1,
9967 tree node2, tree node3)
9968 {
9969 tree item;
9970
9971 if ((node1 == error_mark_node)
9972 || (node2 == error_mark_node)
9973 || (node3 == error_mark_node)
9974 || (type == error_mark_node))
9975 return error_mark_node;
9976
9977 item = build (code, type, node1, node2, node3);
9978 TREE_SIDE_EFFECTS (item) = 1;
9979 return fold (item);
9980 }
9981
9982 /* ffecom_arg_expr -- Transform argument expr into gcc tree
9983
9984 See use by ffecom_list_expr.
9985
9986 If expression is NULL, returns an integer zero tree. If it is not
9987 a CHARACTER expression, returns whatever ffecom_expr
9988 returns and sets the length return value to NULL_TREE. Otherwise
9989 generates code to evaluate the character expression, returns the proper
9990 pointer to the result, but does NOT set the length return value to a tree
9991 that specifies the length of the result. (In other words, the length
9992 variable is always set to NULL_TREE, because a length is never passed.)
9993
9994 21-Dec-91 JCB 1.1
9995 Don't set returned length, since nobody needs it (yet; someday if
9996 we allow CHARACTER*(*) dummies to statement functions, we'll need
9997 it). */
9998
9999 tree
ffecom_arg_expr(ffebld expr,tree * length)10000 ffecom_arg_expr (ffebld expr, tree *length)
10001 {
10002 tree ign;
10003
10004 *length = NULL_TREE;
10005
10006 if (expr == NULL)
10007 return integer_zero_node;
10008
10009 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10010 return ffecom_expr (expr);
10011
10012 return ffecom_arg_ptr_to_expr (expr, &ign);
10013 }
10014
10015 /* Transform expression into constant argument-pointer-to-expression tree.
10016
10017 If the expression can be transformed into a argument-pointer-to-expression
10018 tree that is constant, that is done, and the tree returned. Else
10019 NULL_TREE is returned.
10020
10021 That way, a caller can attempt to provide compile-time initialization
10022 of a variable and, if that fails, *then* choose to start a new block
10023 and resort to using temporaries, as appropriate. */
10024
10025 tree
ffecom_arg_ptr_to_const_expr(ffebld expr,tree * length)10026 ffecom_arg_ptr_to_const_expr (ffebld expr, tree *length)
10027 {
10028 if (! expr)
10029 return integer_zero_node;
10030
10031 if (ffebld_op (expr) == FFEBLD_opANY)
10032 {
10033 if (length)
10034 *length = error_mark_node;
10035 return error_mark_node;
10036 }
10037
10038 if (ffebld_arity (expr) == 0
10039 && (ffebld_op (expr) != FFEBLD_opSYMTER
10040 || ffebld_where (expr) == FFEINFO_whereCOMMON
10041 || ffebld_where (expr) == FFEINFO_whereGLOBAL
10042 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
10043 {
10044 tree t;
10045
10046 t = ffecom_arg_ptr_to_expr (expr, length);
10047 assert (TREE_CONSTANT (t));
10048 assert (! length || TREE_CONSTANT (*length));
10049 return t;
10050 }
10051
10052 if (length
10053 && ffebld_size (expr) != FFETARGET_charactersizeNONE)
10054 *length = build_int_2 (ffebld_size (expr), 0);
10055 else if (length)
10056 *length = NULL_TREE;
10057 return NULL_TREE;
10058 }
10059
10060 /* ffecom_arg_ptr_to_expr -- Transform argument expr into gcc tree
10061
10062 See use by ffecom_list_ptr_to_expr.
10063
10064 If expression is NULL, returns an integer zero tree. If it is not
10065 a CHARACTER expression, returns whatever ffecom_ptr_to_expr
10066 returns and sets the length return value to NULL_TREE. Otherwise
10067 generates code to evaluate the character expression, returns the proper
10068 pointer to the result, AND sets the length return value to a tree that
10069 specifies the length of the result.
10070
10071 If the length argument is NULL, this is a slightly special
10072 case of building a FORMAT expression, that is, an expression that
10073 will be used at run time without regard to length. For the current
10074 implementation, which uses the libf2c library, this means it is nice
10075 to append a null byte to the end of the expression, where feasible,
10076 to make sure any diagnostic about the FORMAT string terminates at
10077 some useful point.
10078
10079 For now, treat %REF(char-expr) as the same as char-expr with a NULL
10080 length argument. This might even be seen as a feature, if a null
10081 byte can always be appended. */
10082
10083 tree
ffecom_arg_ptr_to_expr(ffebld expr,tree * length)10084 ffecom_arg_ptr_to_expr (ffebld expr, tree *length)
10085 {
10086 tree item;
10087 tree ign_length;
10088 ffecomConcatList_ catlist;
10089
10090 if (length != NULL)
10091 *length = NULL_TREE;
10092
10093 if (expr == NULL)
10094 return integer_zero_node;
10095
10096 switch (ffebld_op (expr))
10097 {
10098 case FFEBLD_opPERCENT_VAL:
10099 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10100 return ffecom_expr (ffebld_left (expr));
10101 {
10102 tree temp_exp;
10103 tree temp_length;
10104
10105 temp_exp = ffecom_arg_ptr_to_expr (ffebld_left (expr), &temp_length);
10106 if (temp_exp == error_mark_node)
10107 return error_mark_node;
10108
10109 return ffecom_1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (temp_exp)),
10110 temp_exp);
10111 }
10112
10113 case FFEBLD_opPERCENT_REF:
10114 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10115 return ffecom_ptr_to_expr (ffebld_left (expr));
10116 if (length != NULL)
10117 {
10118 ign_length = NULL_TREE;
10119 length = &ign_length;
10120 }
10121 expr = ffebld_left (expr);
10122 break;
10123
10124 case FFEBLD_opPERCENT_DESCR:
10125 switch (ffeinfo_basictype (ffebld_info (expr)))
10126 {
10127 #ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10128 case FFEINFO_basictypeHOLLERITH:
10129 #endif
10130 case FFEINFO_basictypeCHARACTER:
10131 break; /* Passed by descriptor anyway. */
10132
10133 default:
10134 item = ffecom_ptr_to_expr (expr);
10135 if (item != error_mark_node)
10136 *length = TYPE_SIZE (TREE_TYPE (TREE_TYPE (item)));
10137 break;
10138 }
10139 break;
10140
10141 default:
10142 break;
10143 }
10144
10145 #ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10146 if ((ffeinfo_basictype (ffebld_info (expr)) == FFEINFO_basictypeHOLLERITH)
10147 && (length != NULL))
10148 { /* Pass Hollerith by descriptor. */
10149 ffetargetHollerith h;
10150
10151 assert (ffebld_op (expr) == FFEBLD_opCONTER);
10152 h = ffebld_cu_val_hollerith (ffebld_constant_union
10153 (ffebld_conter (expr)));
10154 *length
10155 = build_int_2 (h.length, 0);
10156 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10157 }
10158 #endif
10159
10160 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10161 return ffecom_ptr_to_expr (expr);
10162
10163 assert (ffeinfo_kindtype (ffebld_info (expr))
10164 == FFEINFO_kindtypeCHARACTER1);
10165
10166 while (ffebld_op (expr) == FFEBLD_opPAREN)
10167 expr = ffebld_left (expr);
10168
10169 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
10170 switch (ffecom_concat_list_count_ (catlist))
10171 {
10172 case 0: /* Shouldn't happen, but in case it does... */
10173 if (length != NULL)
10174 {
10175 *length = ffecom_f2c_ftnlen_zero_node;
10176 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10177 }
10178 ffecom_concat_list_kill_ (catlist);
10179 return null_pointer_node;
10180
10181 case 1: /* The (fairly) easy case. */
10182 if (length == NULL)
10183 ffecom_char_args_with_null_ (&item, &ign_length,
10184 ffecom_concat_list_expr_ (catlist, 0));
10185 else
10186 ffecom_char_args_ (&item, length,
10187 ffecom_concat_list_expr_ (catlist, 0));
10188 ffecom_concat_list_kill_ (catlist);
10189 assert (item != NULL_TREE);
10190 return item;
10191
10192 default: /* Must actually concatenate things. */
10193 break;
10194 }
10195
10196 {
10197 int count = ffecom_concat_list_count_ (catlist);
10198 int i;
10199 tree lengths;
10200 tree items;
10201 tree length_array;
10202 tree item_array;
10203 tree citem;
10204 tree clength;
10205 tree temporary;
10206 tree num;
10207 tree known_length;
10208 ffetargetCharacterSize sz;
10209
10210 sz = ffecom_concat_list_maxlen_ (catlist);
10211 /* ~~Kludge! */
10212 assert (sz != FFETARGET_charactersizeNONE);
10213
10214 {
10215 tree hook;
10216
10217 hook = ffebld_nonter_hook (expr);
10218 assert (hook);
10219 assert (TREE_CODE (hook) == TREE_VEC);
10220 assert (TREE_VEC_LENGTH (hook) == 3);
10221 length_array = lengths = TREE_VEC_ELT (hook, 0);
10222 item_array = items = TREE_VEC_ELT (hook, 1);
10223 temporary = TREE_VEC_ELT (hook, 2);
10224 }
10225
10226 known_length = ffecom_f2c_ftnlen_zero_node;
10227
10228 for (i = 0; i < count; ++i)
10229 {
10230 if ((i == count)
10231 && (length == NULL))
10232 ffecom_char_args_with_null_ (&citem, &clength,
10233 ffecom_concat_list_expr_ (catlist, i));
10234 else
10235 ffecom_char_args_ (&citem, &clength,
10236 ffecom_concat_list_expr_ (catlist, i));
10237 if ((citem == error_mark_node)
10238 || (clength == error_mark_node))
10239 {
10240 ffecom_concat_list_kill_ (catlist);
10241 *length = error_mark_node;
10242 return error_mark_node;
10243 }
10244
10245 items
10246 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
10247 ffecom_modify (void_type_node,
10248 ffecom_2 (ARRAY_REF,
10249 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
10250 item_array,
10251 build_int_2 (i, 0)),
10252 citem),
10253 items);
10254 clength = ffecom_save_tree (clength);
10255 if (length != NULL)
10256 known_length
10257 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
10258 known_length,
10259 clength);
10260 lengths
10261 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
10262 ffecom_modify (void_type_node,
10263 ffecom_2 (ARRAY_REF,
10264 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
10265 length_array,
10266 build_int_2 (i, 0)),
10267 clength),
10268 lengths);
10269 }
10270
10271 temporary = ffecom_1 (ADDR_EXPR,
10272 build_pointer_type (TREE_TYPE (temporary)),
10273 temporary);
10274
10275 item = build_tree_list (NULL_TREE, temporary);
10276 TREE_CHAIN (item)
10277 = build_tree_list (NULL_TREE,
10278 ffecom_1 (ADDR_EXPR,
10279 build_pointer_type (TREE_TYPE (items)),
10280 items));
10281 TREE_CHAIN (TREE_CHAIN (item))
10282 = build_tree_list (NULL_TREE,
10283 ffecom_1 (ADDR_EXPR,
10284 build_pointer_type (TREE_TYPE (lengths)),
10285 lengths));
10286 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
10287 = build_tree_list
10288 (NULL_TREE,
10289 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
10290 convert (ffecom_f2c_ftnlen_type_node,
10291 build_int_2 (count, 0))));
10292 num = build_int_2 (sz, 0);
10293 TREE_TYPE (num) = ffecom_f2c_ftnlen_type_node;
10294 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item))))
10295 = build_tree_list (NULL_TREE, num);
10296
10297 item = ffecom_call_gfrt (FFECOM_gfrtCAT, item, NULL_TREE);
10298 TREE_SIDE_EFFECTS (item) = 1;
10299 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (temporary),
10300 item,
10301 temporary);
10302
10303 if (length != NULL)
10304 *length = known_length;
10305 }
10306
10307 ffecom_concat_list_kill_ (catlist);
10308 assert (item != NULL_TREE);
10309 return item;
10310 }
10311
10312 /* Generate call to run-time function.
10313
10314 The first arg is the GNU Fortran Run-Time function index, the second
10315 arg is the list of arguments to pass to it. Returned is the expression
10316 (WITHOUT TREE_SIDE_EFFECTS set!) that makes the call and returns the
10317 result (which may be void). */
10318
10319 tree
ffecom_call_gfrt(ffecomGfrt ix,tree args,tree hook)10320 ffecom_call_gfrt (ffecomGfrt ix, tree args, tree hook)
10321 {
10322 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
10323 ffecom_gfrt_kindtype (ix),
10324 ffe_is_f2c_library () && ffecom_gfrt_complex_[ix],
10325 NULL_TREE, args, NULL_TREE, NULL,
10326 NULL, NULL_TREE, TRUE, hook);
10327 }
10328
10329 /* Transform constant-union to tree. */
10330
10331 tree
ffecom_constantunion(ffebldConstantUnion * cu,ffeinfoBasictype bt,ffeinfoKindtype kt,tree tree_type)10332 ffecom_constantunion (ffebldConstantUnion *cu, ffeinfoBasictype bt,
10333 ffeinfoKindtype kt, tree tree_type)
10334 {
10335 tree item;
10336
10337 switch (bt)
10338 {
10339 case FFEINFO_basictypeINTEGER:
10340 {
10341 int val;
10342
10343 switch (kt)
10344 {
10345 #if FFETARGET_okINTEGER1
10346 case FFEINFO_kindtypeINTEGER1:
10347 val = ffebld_cu_val_integer1 (*cu);
10348 break;
10349 #endif
10350
10351 #if FFETARGET_okINTEGER2
10352 case FFEINFO_kindtypeINTEGER2:
10353 val = ffebld_cu_val_integer2 (*cu);
10354 break;
10355 #endif
10356
10357 #if FFETARGET_okINTEGER3
10358 case FFEINFO_kindtypeINTEGER3:
10359 val = ffebld_cu_val_integer3 (*cu);
10360 break;
10361 #endif
10362
10363 #if FFETARGET_okINTEGER4
10364 case FFEINFO_kindtypeINTEGER4:
10365 val = ffebld_cu_val_integer4 (*cu);
10366 break;
10367 #endif
10368
10369 default:
10370 assert ("bad INTEGER constant kind type" == NULL);
10371 /* Fall through. */
10372 case FFEINFO_kindtypeANY:
10373 return error_mark_node;
10374 }
10375 item = build_int_2 (val, (val < 0) ? -1 : 0);
10376 TREE_TYPE (item) = tree_type;
10377 }
10378 break;
10379
10380 case FFEINFO_basictypeLOGICAL:
10381 {
10382 int val;
10383
10384 switch (kt)
10385 {
10386 #if FFETARGET_okLOGICAL1
10387 case FFEINFO_kindtypeLOGICAL1:
10388 val = ffebld_cu_val_logical1 (*cu);
10389 break;
10390 #endif
10391
10392 #if FFETARGET_okLOGICAL2
10393 case FFEINFO_kindtypeLOGICAL2:
10394 val = ffebld_cu_val_logical2 (*cu);
10395 break;
10396 #endif
10397
10398 #if FFETARGET_okLOGICAL3
10399 case FFEINFO_kindtypeLOGICAL3:
10400 val = ffebld_cu_val_logical3 (*cu);
10401 break;
10402 #endif
10403
10404 #if FFETARGET_okLOGICAL4
10405 case FFEINFO_kindtypeLOGICAL4:
10406 val = ffebld_cu_val_logical4 (*cu);
10407 break;
10408 #endif
10409
10410 default:
10411 assert ("bad LOGICAL constant kind type" == NULL);
10412 /* Fall through. */
10413 case FFEINFO_kindtypeANY:
10414 return error_mark_node;
10415 }
10416 item = build_int_2 (val, (val < 0) ? -1 : 0);
10417 TREE_TYPE (item) = tree_type;
10418 }
10419 break;
10420
10421 case FFEINFO_basictypeREAL:
10422 {
10423 REAL_VALUE_TYPE val;
10424
10425 switch (kt)
10426 {
10427 #if FFETARGET_okREAL1
10428 case FFEINFO_kindtypeREAL1:
10429 val = ffetarget_value_real1 (ffebld_cu_val_real1 (*cu));
10430 break;
10431 #endif
10432
10433 #if FFETARGET_okREAL2
10434 case FFEINFO_kindtypeREAL2:
10435 val = ffetarget_value_real2 (ffebld_cu_val_real2 (*cu));
10436 break;
10437 #endif
10438
10439 #if FFETARGET_okREAL3
10440 case FFEINFO_kindtypeREAL3:
10441 val = ffetarget_value_real3 (ffebld_cu_val_real3 (*cu));
10442 break;
10443 #endif
10444
10445 #if FFETARGET_okREAL4
10446 case FFEINFO_kindtypeREAL4:
10447 val = ffetarget_value_real4 (ffebld_cu_val_real4 (*cu));
10448 break;
10449 #endif
10450
10451 default:
10452 assert ("bad REAL constant kind type" == NULL);
10453 /* Fall through. */
10454 case FFEINFO_kindtypeANY:
10455 return error_mark_node;
10456 }
10457 item = build_real (tree_type, val);
10458 }
10459 break;
10460
10461 case FFEINFO_basictypeCOMPLEX:
10462 {
10463 REAL_VALUE_TYPE real;
10464 REAL_VALUE_TYPE imag;
10465 tree el_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
10466
10467 switch (kt)
10468 {
10469 #if FFETARGET_okCOMPLEX1
10470 case FFEINFO_kindtypeREAL1:
10471 real = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).real);
10472 imag = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).imaginary);
10473 break;
10474 #endif
10475
10476 #if FFETARGET_okCOMPLEX2
10477 case FFEINFO_kindtypeREAL2:
10478 real = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).real);
10479 imag = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).imaginary);
10480 break;
10481 #endif
10482
10483 #if FFETARGET_okCOMPLEX3
10484 case FFEINFO_kindtypeREAL3:
10485 real = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).real);
10486 imag = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).imaginary);
10487 break;
10488 #endif
10489
10490 #if FFETARGET_okCOMPLEX4
10491 case FFEINFO_kindtypeREAL4:
10492 real = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).real);
10493 imag = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).imaginary);
10494 break;
10495 #endif
10496
10497 default:
10498 assert ("bad REAL constant kind type" == NULL);
10499 /* Fall through. */
10500 case FFEINFO_kindtypeANY:
10501 return error_mark_node;
10502 }
10503 item = ffecom_build_complex_constant_ (tree_type,
10504 build_real (el_type, real),
10505 build_real (el_type, imag));
10506 }
10507 break;
10508
10509 case FFEINFO_basictypeCHARACTER:
10510 { /* Happens only in DATA and similar contexts. */
10511 ffetargetCharacter1 val;
10512
10513 switch (kt)
10514 {
10515 #if FFETARGET_okCHARACTER1
10516 case FFEINFO_kindtypeLOGICAL1:
10517 val = ffebld_cu_val_character1 (*cu);
10518 break;
10519 #endif
10520
10521 default:
10522 assert ("bad CHARACTER constant kind type" == NULL);
10523 /* Fall through. */
10524 case FFEINFO_kindtypeANY:
10525 return error_mark_node;
10526 }
10527 item = build_string (ffetarget_length_character1 (val),
10528 ffetarget_text_character1 (val));
10529 TREE_TYPE (item)
10530 = build_type_variant (build_array_type (char_type_node,
10531 build_range_type
10532 (integer_type_node,
10533 integer_one_node,
10534 build_int_2
10535 (ffetarget_length_character1
10536 (val), 0))),
10537 1, 0);
10538 }
10539 break;
10540
10541 case FFEINFO_basictypeHOLLERITH:
10542 {
10543 ffetargetHollerith h;
10544
10545 h = ffebld_cu_val_hollerith (*cu);
10546
10547 /* If not at least as wide as default INTEGER, widen it. */
10548 if (h.length >= FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE)
10549 item = build_string (h.length, h.text);
10550 else
10551 {
10552 char str[FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE];
10553
10554 memcpy (str, h.text, h.length);
10555 memset (&str[h.length], ' ',
10556 FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE
10557 - h.length);
10558 item = build_string (FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE,
10559 str);
10560 }
10561 TREE_TYPE (item)
10562 = build_type_variant (build_array_type (char_type_node,
10563 build_range_type
10564 (integer_type_node,
10565 integer_one_node,
10566 build_int_2
10567 (h.length, 0))),
10568 1, 0);
10569 }
10570 break;
10571
10572 case FFEINFO_basictypeTYPELESS:
10573 {
10574 ffetargetInteger1 ival;
10575 ffetargetTypeless tless;
10576 ffebad error;
10577
10578 tless = ffebld_cu_val_typeless (*cu);
10579 error = ffetarget_convert_integer1_typeless (&ival, tless);
10580 assert (error == FFEBAD);
10581
10582 item = build_int_2 ((int) ival, 0);
10583 }
10584 break;
10585
10586 default:
10587 assert ("not yet on constant type" == NULL);
10588 /* Fall through. */
10589 case FFEINFO_basictypeANY:
10590 return error_mark_node;
10591 }
10592
10593 TREE_CONSTANT (item) = 1;
10594
10595 return item;
10596 }
10597
10598 /* Transform constant-union to tree, with the type known. */
10599
10600 tree
ffecom_constantunion_with_type(ffebldConstantUnion * cu,tree tree_type,ffebldConst ct)10601 ffecom_constantunion_with_type (ffebldConstantUnion *cu,
10602 tree tree_type, ffebldConst ct)
10603 {
10604 tree item;
10605
10606 int val;
10607
10608 switch (ct)
10609 {
10610 #if FFETARGET_okINTEGER1
10611 case FFEBLD_constINTEGER1:
10612 val = ffebld_cu_val_integer1 (*cu);
10613 item = build_int_2 (val, (val < 0) ? -1 : 0);
10614 break;
10615 #endif
10616 #if FFETARGET_okINTEGER2
10617 case FFEBLD_constINTEGER2:
10618 val = ffebld_cu_val_integer2 (*cu);
10619 item = build_int_2 (val, (val < 0) ? -1 : 0);
10620 break;
10621 #endif
10622 #if FFETARGET_okINTEGER3
10623 case FFEBLD_constINTEGER3:
10624 val = ffebld_cu_val_integer3 (*cu);
10625 item = build_int_2 (val, (val < 0) ? -1 : 0);
10626 break;
10627 #endif
10628 #if FFETARGET_okINTEGER4
10629 case FFEBLD_constINTEGER4:
10630 val = ffebld_cu_val_integer4 (*cu);
10631 item = build_int_2 (val, (val < 0) ? -1 : 0);
10632 break;
10633 #endif
10634 #if FFETARGET_okLOGICAL1
10635 case FFEBLD_constLOGICAL1:
10636 val = ffebld_cu_val_logical1 (*cu);
10637 item = build_int_2 (val, (val < 0) ? -1 : 0);
10638 break;
10639 #endif
10640 #if FFETARGET_okLOGICAL2
10641 case FFEBLD_constLOGICAL2:
10642 val = ffebld_cu_val_logical2 (*cu);
10643 item = build_int_2 (val, (val < 0) ? -1 : 0);
10644 break;
10645 #endif
10646 #if FFETARGET_okLOGICAL3
10647 case FFEBLD_constLOGICAL3:
10648 val = ffebld_cu_val_logical3 (*cu);
10649 item = build_int_2 (val, (val < 0) ? -1 : 0);
10650 break;
10651 #endif
10652 #if FFETARGET_okLOGICAL4
10653 case FFEBLD_constLOGICAL4:
10654 val = ffebld_cu_val_logical4 (*cu);
10655 item = build_int_2 (val, (val < 0) ? -1 : 0);
10656 break;
10657 #endif
10658 default:
10659 assert ("constant type not supported"==NULL);
10660 return error_mark_node;
10661 break;
10662 }
10663
10664 TREE_TYPE (item) = tree_type;
10665
10666 TREE_CONSTANT (item) = 1;
10667
10668 return item;
10669 }
10670 /* Transform expression into constant tree.
10671
10672 If the expression can be transformed into a tree that is constant,
10673 that is done, and the tree returned. Else NULL_TREE is returned.
10674
10675 That way, a caller can attempt to provide compile-time initialization
10676 of a variable and, if that fails, *then* choose to start a new block
10677 and resort to using temporaries, as appropriate. */
10678
10679 tree
ffecom_const_expr(ffebld expr)10680 ffecom_const_expr (ffebld expr)
10681 {
10682 if (! expr)
10683 return integer_zero_node;
10684
10685 if (ffebld_op (expr) == FFEBLD_opANY)
10686 return error_mark_node;
10687
10688 if (ffebld_arity (expr) == 0
10689 && (ffebld_op (expr) != FFEBLD_opSYMTER
10690 #if NEWCOMMON
10691 /* ~~Enable once common/equivalence is handled properly? */
10692 || ffebld_where (expr) == FFEINFO_whereCOMMON
10693 #endif
10694 || ffebld_where (expr) == FFEINFO_whereGLOBAL
10695 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
10696 {
10697 tree t;
10698
10699 t = ffecom_expr (expr);
10700 assert (TREE_CONSTANT (t));
10701 return t;
10702 }
10703
10704 return NULL_TREE;
10705 }
10706
10707 /* Handy way to make a field in a struct/union. */
10708
10709 tree
ffecom_decl_field(tree context,tree prevfield,const char * name,tree type)10710 ffecom_decl_field (tree context, tree prevfield,
10711 const char *name, tree type)
10712 {
10713 tree field;
10714
10715 field = build_decl (FIELD_DECL, get_identifier (name), type);
10716 DECL_CONTEXT (field) = context;
10717 DECL_ALIGN (field) = 0;
10718 DECL_USER_ALIGN (field) = 0;
10719 if (prevfield != NULL_TREE)
10720 TREE_CHAIN (prevfield) = field;
10721
10722 return field;
10723 }
10724
10725 void
ffecom_close_include(FILE * f)10726 ffecom_close_include (FILE *f)
10727 {
10728 ffecom_close_include_ (f);
10729 }
10730
10731 int
ffecom_decode_include_option(char * spec)10732 ffecom_decode_include_option (char *spec)
10733 {
10734 return ffecom_decode_include_option_ (spec);
10735 }
10736
10737 /* End a compound statement (block). */
10738
10739 tree
ffecom_end_compstmt(void)10740 ffecom_end_compstmt (void)
10741 {
10742 return bison_rule_compstmt_ ();
10743 }
10744
10745 /* ffecom_end_transition -- Perform end transition on all symbols
10746
10747 ffecom_end_transition();
10748
10749 Calls ffecom_sym_end_transition for each global and local symbol. */
10750
10751 void
ffecom_end_transition()10752 ffecom_end_transition ()
10753 {
10754 ffebld item;
10755
10756 if (ffe_is_ffedebug ())
10757 fprintf (dmpout, "; end_stmt_transition\n");
10758
10759 ffecom_list_blockdata_ = NULL;
10760 ffecom_list_common_ = NULL;
10761
10762 ffesymbol_drive (ffecom_sym_end_transition);
10763 if (ffe_is_ffedebug ())
10764 {
10765 ffestorag_report ();
10766 }
10767
10768 ffecom_start_progunit_ ();
10769
10770 for (item = ffecom_list_blockdata_;
10771 item != NULL;
10772 item = ffebld_trail (item))
10773 {
10774 ffebld callee;
10775 ffesymbol s;
10776 tree dt;
10777 tree t;
10778 tree var;
10779 static int number = 0;
10780
10781 callee = ffebld_head (item);
10782 s = ffebld_symter (callee);
10783 t = ffesymbol_hook (s).decl_tree;
10784 if (t == NULL_TREE)
10785 {
10786 s = ffecom_sym_transform_ (s);
10787 t = ffesymbol_hook (s).decl_tree;
10788 }
10789
10790 dt = build_pointer_type (TREE_TYPE (t));
10791
10792 var = build_decl (VAR_DECL,
10793 ffecom_get_invented_identifier ("__g77_forceload_%d",
10794 number++),
10795 dt);
10796 DECL_EXTERNAL (var) = 0;
10797 TREE_STATIC (var) = 1;
10798 TREE_PUBLIC (var) = 0;
10799 DECL_INITIAL (var) = error_mark_node;
10800 TREE_USED (var) = 1;
10801
10802 var = start_decl (var, FALSE);
10803
10804 t = ffecom_1 (ADDR_EXPR, dt, t);
10805
10806 finish_decl (var, t, FALSE);
10807 }
10808
10809 /* This handles any COMMON areas that weren't referenced but have, for
10810 example, important initial data. */
10811
10812 for (item = ffecom_list_common_;
10813 item != NULL;
10814 item = ffebld_trail (item))
10815 ffecom_transform_common_ (ffebld_symter (ffebld_head (item)));
10816
10817 ffecom_list_common_ = NULL;
10818 }
10819
10820 /* ffecom_exec_transition -- Perform exec transition on all symbols
10821
10822 ffecom_exec_transition();
10823
10824 Calls ffecom_sym_exec_transition for each global and local symbol.
10825 Make sure error updating not inhibited. */
10826
10827 void
ffecom_exec_transition()10828 ffecom_exec_transition ()
10829 {
10830 bool inhibited;
10831
10832 if (ffe_is_ffedebug ())
10833 fprintf (dmpout, "; exec_stmt_transition\n");
10834
10835 inhibited = ffebad_inhibit ();
10836 ffebad_set_inhibit (FALSE);
10837
10838 ffesymbol_drive (ffecom_sym_exec_transition); /* Don't retract! */
10839 ffeequiv_exec_transition (); /* Handle all pending EQUIVALENCEs. */
10840 if (ffe_is_ffedebug ())
10841 {
10842 ffestorag_report ();
10843 }
10844
10845 if (inhibited)
10846 ffebad_set_inhibit (TRUE);
10847 }
10848
10849 /* Handle assignment statement.
10850
10851 Convert dest and source using ffecom_expr, then join them
10852 with an ASSIGN op and pass the whole thing to expand_expr_stmt. */
10853
10854 void
ffecom_expand_let_stmt(ffebld dest,ffebld source)10855 ffecom_expand_let_stmt (ffebld dest, ffebld source)
10856 {
10857 tree dest_tree;
10858 tree dest_length;
10859 tree source_tree;
10860 tree expr_tree;
10861
10862 if (ffeinfo_basictype (ffebld_info (dest)) != FFEINFO_basictypeCHARACTER)
10863 {
10864 bool dest_used;
10865 tree assign_temp;
10866
10867 /* This attempts to replicate the test below, but must not be
10868 true when the test below is false. (Always err on the side
10869 of creating unused temporaries, to avoid ICEs.) */
10870 if (ffebld_op (dest) != FFEBLD_opSYMTER
10871 || ((dest_tree = ffesymbol_hook (ffebld_symter (dest)).decl_tree)
10872 && (TREE_CODE (dest_tree) != VAR_DECL
10873 || TREE_ADDRESSABLE (dest_tree))))
10874 {
10875 ffecom_prepare_expr_ (source, dest);
10876 dest_used = TRUE;
10877 }
10878 else
10879 {
10880 ffecom_prepare_expr_ (source, NULL);
10881 dest_used = FALSE;
10882 }
10883
10884 ffecom_prepare_expr_w (NULL_TREE, dest);
10885
10886 /* For COMPLEX assignment like C1=C2, if partial overlap is possible,
10887 create a temporary through which the assignment is to take place,
10888 since MODIFY_EXPR doesn't handle partial overlap properly. */
10889 if (ffebld_basictype (dest) == FFEINFO_basictypeCOMPLEX
10890 && ffecom_possible_partial_overlap_ (dest, source))
10891 {
10892 assign_temp = ffecom_make_tempvar ("complex_let",
10893 ffecom_tree_type
10894 [ffebld_basictype (dest)]
10895 [ffebld_kindtype (dest)],
10896 FFETARGET_charactersizeNONE,
10897 -1);
10898 }
10899 else
10900 assign_temp = NULL_TREE;
10901
10902 ffecom_prepare_end ();
10903
10904 dest_tree = ffecom_expr_w (NULL_TREE, dest);
10905 if (dest_tree == error_mark_node)
10906 return;
10907
10908 if ((TREE_CODE (dest_tree) != VAR_DECL)
10909 || TREE_ADDRESSABLE (dest_tree))
10910 source_tree = ffecom_expr_ (source, dest_tree, dest, &dest_used,
10911 FALSE, FALSE);
10912 else
10913 {
10914 assert (! dest_used);
10915 dest_used = FALSE;
10916 source_tree = ffecom_expr (source);
10917 }
10918 if (source_tree == error_mark_node)
10919 return;
10920
10921 if (dest_used)
10922 expr_tree = source_tree;
10923 else if (assign_temp)
10924 {
10925 #ifdef MOVE_EXPR
10926 /* The back end understands a conceptual move (evaluate source;
10927 store into dest), so use that, in case it can determine
10928 that it is going to use, say, two registers as temporaries
10929 anyway. So don't use the temp (and someday avoid generating
10930 it, once this code starts triggering regularly). */
10931 expr_tree = ffecom_2s (MOVE_EXPR, void_type_node,
10932 dest_tree,
10933 source_tree);
10934 #else
10935 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
10936 assign_temp,
10937 source_tree);
10938 expand_expr_stmt (expr_tree);
10939 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
10940 dest_tree,
10941 assign_temp);
10942 #endif
10943 }
10944 else
10945 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
10946 dest_tree,
10947 source_tree);
10948
10949 expand_expr_stmt (expr_tree);
10950 return;
10951 }
10952
10953 ffecom_prepare_let_char_ (ffebld_size_known (dest), source);
10954 ffecom_prepare_expr_w (NULL_TREE, dest);
10955
10956 ffecom_prepare_end ();
10957
10958 ffecom_char_args_ (&dest_tree, &dest_length, dest);
10959 ffecom_let_char_ (dest_tree, dest_length, ffebld_size_known (dest),
10960 source);
10961 }
10962
10963 /* ffecom_expr -- Transform expr into gcc tree
10964
10965 tree t;
10966 ffebld expr; // FFE expression.
10967 tree = ffecom_expr(expr);
10968
10969 Recursive descent on expr while making corresponding tree nodes and
10970 attaching type info and such. */
10971
10972 tree
ffecom_expr(ffebld expr)10973 ffecom_expr (ffebld expr)
10974 {
10975 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, FALSE, FALSE);
10976 }
10977
10978 /* Like ffecom_expr, but return tree usable for assigned GOTO or FORMAT. */
10979
10980 tree
ffecom_expr_assign(ffebld expr)10981 ffecom_expr_assign (ffebld expr)
10982 {
10983 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
10984 }
10985
10986 /* Like ffecom_expr_rw, but return tree usable for ASSIGN. */
10987
10988 tree
ffecom_expr_assign_w(ffebld expr)10989 ffecom_expr_assign_w (ffebld expr)
10990 {
10991 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
10992 }
10993
10994 /* Transform expr for use as into read/write tree and stabilize the
10995 reference. Not for use on CHARACTER expressions.
10996
10997 Recursive descent on expr while making corresponding tree nodes and
10998 attaching type info and such. */
10999
11000 tree
ffecom_expr_rw(tree type,ffebld expr)11001 ffecom_expr_rw (tree type, ffebld expr)
11002 {
11003 assert (expr != NULL);
11004 /* Different target types not yet supported. */
11005 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
11006
11007 return stabilize_reference (ffecom_expr (expr));
11008 }
11009
11010 /* Transform expr for use as into write tree and stabilize the
11011 reference. Not for use on CHARACTER expressions.
11012
11013 Recursive descent on expr while making corresponding tree nodes and
11014 attaching type info and such. */
11015
11016 tree
ffecom_expr_w(tree type,ffebld expr)11017 ffecom_expr_w (tree type, ffebld expr)
11018 {
11019 assert (expr != NULL);
11020 /* Different target types not yet supported. */
11021 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
11022
11023 return stabilize_reference (ffecom_expr (expr));
11024 }
11025
11026 /* Do global stuff. */
11027
11028 void
ffecom_finish_compile()11029 ffecom_finish_compile ()
11030 {
11031 assert (ffecom_outer_function_decl_ == NULL_TREE);
11032 assert (current_function_decl == NULL_TREE);
11033
11034 ffeglobal_drive (ffecom_finish_global_);
11035 }
11036
11037 /* Public entry point for front end to access finish_decl. */
11038
11039 void
ffecom_finish_decl(tree decl,tree init,bool is_top_level)11040 ffecom_finish_decl (tree decl, tree init, bool is_top_level)
11041 {
11042 assert (!is_top_level);
11043 finish_decl (decl, init, FALSE);
11044 }
11045
11046 /* Finish a program unit. */
11047
11048 void
ffecom_finish_progunit()11049 ffecom_finish_progunit ()
11050 {
11051 ffecom_end_compstmt ();
11052
11053 ffecom_previous_function_decl_ = current_function_decl;
11054 ffecom_which_entrypoint_decl_ = NULL_TREE;
11055
11056 finish_function (0);
11057 }
11058
11059 /* Wrapper for get_identifier. pattern is sprintf-like. */
11060
11061 tree
ffecom_get_invented_identifier(const char * pattern,...)11062 ffecom_get_invented_identifier (const char *pattern, ...)
11063 {
11064 tree decl;
11065 char *nam;
11066 va_list ap;
11067
11068 va_start (ap, pattern);
11069 if (vasprintf (&nam, pattern, ap) == 0)
11070 abort ();
11071 va_end (ap);
11072 decl = get_identifier (nam);
11073 free (nam);
11074 IDENTIFIER_INVENTED (decl) = 1;
11075 return decl;
11076 }
11077
11078 ffeinfoBasictype
ffecom_gfrt_basictype(ffecomGfrt gfrt)11079 ffecom_gfrt_basictype (ffecomGfrt gfrt)
11080 {
11081 assert (gfrt < FFECOM_gfrt);
11082
11083 switch (ffecom_gfrt_type_[gfrt])
11084 {
11085 case FFECOM_rttypeVOID_:
11086 case FFECOM_rttypeVOIDSTAR_:
11087 return FFEINFO_basictypeNONE;
11088
11089 case FFECOM_rttypeFTNINT_:
11090 return FFEINFO_basictypeINTEGER;
11091
11092 case FFECOM_rttypeINTEGER_:
11093 return FFEINFO_basictypeINTEGER;
11094
11095 case FFECOM_rttypeLONGINT_:
11096 return FFEINFO_basictypeINTEGER;
11097
11098 case FFECOM_rttypeLOGICAL_:
11099 return FFEINFO_basictypeLOGICAL;
11100
11101 case FFECOM_rttypeREAL_F2C_:
11102 case FFECOM_rttypeREAL_GNU_:
11103 return FFEINFO_basictypeREAL;
11104
11105 case FFECOM_rttypeCOMPLEX_F2C_:
11106 case FFECOM_rttypeCOMPLEX_GNU_:
11107 return FFEINFO_basictypeCOMPLEX;
11108
11109 case FFECOM_rttypeDOUBLE_:
11110 case FFECOM_rttypeDOUBLEREAL_:
11111 return FFEINFO_basictypeREAL;
11112
11113 case FFECOM_rttypeDBLCMPLX_F2C_:
11114 case FFECOM_rttypeDBLCMPLX_GNU_:
11115 return FFEINFO_basictypeCOMPLEX;
11116
11117 case FFECOM_rttypeCHARACTER_:
11118 return FFEINFO_basictypeCHARACTER;
11119
11120 default:
11121 return FFEINFO_basictypeANY;
11122 }
11123 }
11124
11125 ffeinfoKindtype
ffecom_gfrt_kindtype(ffecomGfrt gfrt)11126 ffecom_gfrt_kindtype (ffecomGfrt gfrt)
11127 {
11128 assert (gfrt < FFECOM_gfrt);
11129
11130 switch (ffecom_gfrt_type_[gfrt])
11131 {
11132 case FFECOM_rttypeVOID_:
11133 case FFECOM_rttypeVOIDSTAR_:
11134 return FFEINFO_kindtypeNONE;
11135
11136 case FFECOM_rttypeFTNINT_:
11137 return FFEINFO_kindtypeINTEGER1;
11138
11139 case FFECOM_rttypeINTEGER_:
11140 return FFEINFO_kindtypeINTEGER1;
11141
11142 case FFECOM_rttypeLONGINT_:
11143 return FFEINFO_kindtypeINTEGER4;
11144
11145 case FFECOM_rttypeLOGICAL_:
11146 return FFEINFO_kindtypeLOGICAL1;
11147
11148 case FFECOM_rttypeREAL_F2C_:
11149 case FFECOM_rttypeREAL_GNU_:
11150 return FFEINFO_kindtypeREAL1;
11151
11152 case FFECOM_rttypeCOMPLEX_F2C_:
11153 case FFECOM_rttypeCOMPLEX_GNU_:
11154 return FFEINFO_kindtypeREAL1;
11155
11156 case FFECOM_rttypeDOUBLE_:
11157 case FFECOM_rttypeDOUBLEREAL_:
11158 return FFEINFO_kindtypeREAL2;
11159
11160 case FFECOM_rttypeDBLCMPLX_F2C_:
11161 case FFECOM_rttypeDBLCMPLX_GNU_:
11162 return FFEINFO_kindtypeREAL2;
11163
11164 case FFECOM_rttypeCHARACTER_:
11165 return FFEINFO_kindtypeCHARACTER1;
11166
11167 default:
11168 return FFEINFO_kindtypeANY;
11169 }
11170 }
11171
11172 void
ffecom_init_0()11173 ffecom_init_0 ()
11174 {
11175 tree endlink;
11176 int i;
11177 int j;
11178 tree t;
11179 tree field;
11180 ffetype type;
11181 ffetype base_type;
11182 tree double_ftype_double;
11183 tree float_ftype_float;
11184 tree ldouble_ftype_ldouble;
11185 tree ffecom_tree_ptr_to_fun_type_void;
11186
11187 /* This block of code comes from the now-obsolete cktyps.c. It checks
11188 whether the compiler environment is buggy in known ways, some of which
11189 would, if not explicitly checked here, result in subtle bugs in g77. */
11190
11191 if (ffe_is_do_internal_checks ())
11192 {
11193 static const char names[][12]
11194 =
11195 {"bar", "bletch", "foo", "foobar"};
11196 const char *name;
11197 unsigned long ul;
11198 double fl;
11199
11200 name = bsearch ("foo", &names[0], ARRAY_SIZE (names), sizeof (names[0]),
11201 (int (*)(const void *, const void *)) strcmp);
11202 if (name != &names[2][0])
11203 {
11204 assert ("bsearch doesn't work, #define FFEPROJ_BSEARCH 0 in proj.h"
11205 == NULL);
11206 abort ();
11207 }
11208
11209 ul = strtoul ("123456789", NULL, 10);
11210 if (ul != 123456789L)
11211 {
11212 assert ("strtoul doesn't have enough range, #define FFEPROJ_STRTOUL 0\
11213 in proj.h" == NULL);
11214 abort ();
11215 }
11216
11217 fl = atof ("56.789");
11218 if ((fl < 56.788) || (fl > 56.79))
11219 {
11220 assert ("atof not type double, fix your #include <stdio.h>"
11221 == NULL);
11222 abort ();
11223 }
11224 }
11225
11226 ffecom_outer_function_decl_ = NULL_TREE;
11227 current_function_decl = NULL_TREE;
11228 named_labels = NULL_TREE;
11229 current_binding_level = NULL_BINDING_LEVEL;
11230 free_binding_level = NULL_BINDING_LEVEL;
11231 /* Make the binding_level structure for global names. */
11232 pushlevel (0);
11233 global_binding_level = current_binding_level;
11234 current_binding_level->prep_state = 2;
11235
11236 build_common_tree_nodes (1);
11237
11238 /* Define `int' and `char' first so that dbx will output them first. */
11239 pushdecl (build_decl (TYPE_DECL, get_identifier ("int"),
11240 integer_type_node));
11241 /* CHARACTER*1 is unsigned in ICHAR contexts. */
11242 char_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
11243 pushdecl (build_decl (TYPE_DECL, get_identifier ("char"),
11244 char_type_node));
11245 pushdecl (build_decl (TYPE_DECL, get_identifier ("long int"),
11246 long_integer_type_node));
11247 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned int"),
11248 unsigned_type_node));
11249 pushdecl (build_decl (TYPE_DECL, get_identifier ("long unsigned int"),
11250 long_unsigned_type_node));
11251 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long int"),
11252 long_long_integer_type_node));
11253 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"),
11254 long_long_unsigned_type_node));
11255 pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"),
11256 short_integer_type_node));
11257 pushdecl (build_decl (TYPE_DECL, get_identifier ("short unsigned int"),
11258 short_unsigned_type_node));
11259
11260 /* Set the sizetype before we make other types. This *should* be the
11261 first type we create. */
11262
11263 set_sizetype
11264 (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))));
11265 ffecom_typesize_pointer_
11266 = TREE_INT_CST_LOW (TYPE_SIZE (sizetype)) / BITS_PER_UNIT;
11267
11268 build_common_tree_nodes_2 (0);
11269
11270 /* Define both `signed char' and `unsigned char'. */
11271 pushdecl (build_decl (TYPE_DECL, get_identifier ("signed char"),
11272 signed_char_type_node));
11273
11274 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned char"),
11275 unsigned_char_type_node));
11276
11277 pushdecl (build_decl (TYPE_DECL, get_identifier ("float"),
11278 float_type_node));
11279 pushdecl (build_decl (TYPE_DECL, get_identifier ("double"),
11280 double_type_node));
11281 pushdecl (build_decl (TYPE_DECL, get_identifier ("long double"),
11282 long_double_type_node));
11283
11284 /* For now, override what build_common_tree_nodes has done. */
11285 complex_integer_type_node = ffecom_make_complex_type_ (integer_type_node);
11286 complex_float_type_node = ffecom_make_complex_type_ (float_type_node);
11287 complex_double_type_node = ffecom_make_complex_type_ (double_type_node);
11288 complex_long_double_type_node
11289 = ffecom_make_complex_type_ (long_double_type_node);
11290
11291 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"),
11292 complex_integer_type_node));
11293 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"),
11294 complex_float_type_node));
11295 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"),
11296 complex_double_type_node));
11297 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"),
11298 complex_long_double_type_node));
11299
11300 pushdecl (build_decl (TYPE_DECL, get_identifier ("void"),
11301 void_type_node));
11302 /* We are not going to have real types in C with less than byte alignment,
11303 so we might as well not have any types that claim to have it. */
11304 TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
11305 TYPE_USER_ALIGN (void_type_node) = 0;
11306
11307 string_type_node = build_pointer_type (char_type_node);
11308
11309 ffecom_tree_fun_type_void
11310 = build_function_type (void_type_node, NULL_TREE);
11311
11312 ffecom_tree_ptr_to_fun_type_void
11313 = build_pointer_type (ffecom_tree_fun_type_void);
11314
11315 endlink = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
11316
11317 float_ftype_float
11318 = build_function_type (float_type_node,
11319 tree_cons (NULL_TREE, float_type_node, endlink));
11320
11321 double_ftype_double
11322 = build_function_type (double_type_node,
11323 tree_cons (NULL_TREE, double_type_node, endlink));
11324
11325 ldouble_ftype_ldouble
11326 = build_function_type (long_double_type_node,
11327 tree_cons (NULL_TREE, long_double_type_node,
11328 endlink));
11329
11330 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11331 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11332 {
11333 ffecom_tree_type[i][j] = NULL_TREE;
11334 ffecom_tree_fun_type[i][j] = NULL_TREE;
11335 ffecom_tree_ptr_to_fun_type[i][j] = NULL_TREE;
11336 ffecom_f2c_typecode_[i][j] = -1;
11337 }
11338
11339 /* Set up standard g77 types. Note that INTEGER and LOGICAL are set
11340 to size FLOAT_TYPE_SIZE because they have to be the same size as
11341 REAL, which also is FLOAT_TYPE_SIZE, according to the standard.
11342 Compiler options and other such stuff that change the ways these
11343 types are set should not affect this particular setup. */
11344
11345 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1]
11346 = t = make_signed_type (FLOAT_TYPE_SIZE);
11347 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer"),
11348 t));
11349 type = ffetype_new ();
11350 base_type = type;
11351 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER1,
11352 type);
11353 ffetype_set_ams (type,
11354 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11355 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11356 ffetype_set_star (base_type,
11357 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11358 type);
11359 ffetype_set_kind (base_type, 1, type);
11360 ffecom_typesize_integer1_ = ffetype_size (type);
11361 assert (ffetype_size (type) == sizeof (ffetargetInteger1));
11362
11363 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER1]
11364 = t = make_unsigned_type (FLOAT_TYPE_SIZE); /* HOLLERITH means unsigned. */
11365 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned"),
11366 t));
11367
11368 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER2]
11369 = t = make_signed_type (CHAR_TYPE_SIZE);
11370 pushdecl (build_decl (TYPE_DECL, get_identifier ("byte"),
11371 t));
11372 type = ffetype_new ();
11373 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER2,
11374 type);
11375 ffetype_set_ams (type,
11376 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11377 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11378 ffetype_set_star (base_type,
11379 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11380 type);
11381 ffetype_set_kind (base_type, 3, type);
11382 assert (ffetype_size (type) == sizeof (ffetargetInteger2));
11383
11384 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER2]
11385 = t = make_unsigned_type (CHAR_TYPE_SIZE);
11386 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned byte"),
11387 t));
11388
11389 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER3]
11390 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11391 pushdecl (build_decl (TYPE_DECL, get_identifier ("word"),
11392 t));
11393 type = ffetype_new ();
11394 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER3,
11395 type);
11396 ffetype_set_ams (type,
11397 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11398 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11399 ffetype_set_star (base_type,
11400 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11401 type);
11402 ffetype_set_kind (base_type, 6, type);
11403 assert (ffetype_size (type) == sizeof (ffetargetInteger3));
11404
11405 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER3]
11406 = t = make_unsigned_type (CHAR_TYPE_SIZE * 2);
11407 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned word"),
11408 t));
11409
11410 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER4]
11411 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11412 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer4"),
11413 t));
11414 type = ffetype_new ();
11415 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER4,
11416 type);
11417 ffetype_set_ams (type,
11418 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11419 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11420 ffetype_set_star (base_type,
11421 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11422 type);
11423 ffetype_set_kind (base_type, 2, type);
11424 assert (ffetype_size (type) == sizeof (ffetargetInteger4));
11425
11426 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER4]
11427 = t = make_unsigned_type (FLOAT_TYPE_SIZE * 2);
11428 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned4"),
11429 t));
11430
11431 #if 0
11432 if (ffe_is_do_internal_checks ()
11433 && LONG_TYPE_SIZE != FLOAT_TYPE_SIZE
11434 && LONG_TYPE_SIZE != CHAR_TYPE_SIZE
11435 && LONG_TYPE_SIZE != SHORT_TYPE_SIZE
11436 && LONG_TYPE_SIZE != LONG_LONG_TYPE_SIZE)
11437 {
11438 fprintf (stderr, "Sorry, no g77 support for LONG_TYPE_SIZE (%d bits) yet.\n",
11439 LONG_TYPE_SIZE);
11440 }
11441 #endif
11442
11443 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL1]
11444 = t = make_signed_type (FLOAT_TYPE_SIZE);
11445 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical"),
11446 t));
11447 type = ffetype_new ();
11448 base_type = type;
11449 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL1,
11450 type);
11451 ffetype_set_ams (type,
11452 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11453 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11454 ffetype_set_star (base_type,
11455 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11456 type);
11457 ffetype_set_kind (base_type, 1, type);
11458 assert (ffetype_size (type) == sizeof (ffetargetLogical1));
11459
11460 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL2]
11461 = t = make_signed_type (CHAR_TYPE_SIZE);
11462 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical2"),
11463 t));
11464 type = ffetype_new ();
11465 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL2,
11466 type);
11467 ffetype_set_ams (type,
11468 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11469 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11470 ffetype_set_star (base_type,
11471 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11472 type);
11473 ffetype_set_kind (base_type, 3, type);
11474 assert (ffetype_size (type) == sizeof (ffetargetLogical2));
11475
11476 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL3]
11477 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11478 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical3"),
11479 t));
11480 type = ffetype_new ();
11481 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL3,
11482 type);
11483 ffetype_set_ams (type,
11484 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11485 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11486 ffetype_set_star (base_type,
11487 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11488 type);
11489 ffetype_set_kind (base_type, 6, type);
11490 assert (ffetype_size (type) == sizeof (ffetargetLogical3));
11491
11492 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL4]
11493 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11494 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical4"),
11495 t));
11496 type = ffetype_new ();
11497 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL4,
11498 type);
11499 ffetype_set_ams (type,
11500 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11501 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11502 ffetype_set_star (base_type,
11503 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11504 type);
11505 ffetype_set_kind (base_type, 2, type);
11506 assert (ffetype_size (type) == sizeof (ffetargetLogical4));
11507
11508 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
11509 = t = make_node (REAL_TYPE);
11510 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE;
11511 pushdecl (build_decl (TYPE_DECL, get_identifier ("real"),
11512 t));
11513 layout_type (t);
11514 type = ffetype_new ();
11515 base_type = type;
11516 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREAL1,
11517 type);
11518 ffetype_set_ams (type,
11519 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11520 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11521 ffetype_set_star (base_type,
11522 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11523 type);
11524 ffetype_set_kind (base_type, 1, type);
11525 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
11526 = FFETARGET_f2cTYREAL;
11527 assert (ffetype_size (type) == sizeof (ffetargetReal1));
11528
11529 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREALDOUBLE]
11530 = t = make_node (REAL_TYPE);
11531 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE * 2; /* Always twice REAL. */
11532 pushdecl (build_decl (TYPE_DECL, get_identifier ("double precision"),
11533 t));
11534 layout_type (t);
11535 type = ffetype_new ();
11536 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREALDOUBLE,
11537 type);
11538 ffetype_set_ams (type,
11539 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11540 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11541 ffetype_set_star (base_type,
11542 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11543 type);
11544 ffetype_set_kind (base_type, 2, type);
11545 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]
11546 = FFETARGET_f2cTYDREAL;
11547 assert (ffetype_size (type) == sizeof (ffetargetReal2));
11548
11549 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
11550 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]);
11551 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex"),
11552 t));
11553 type = ffetype_new ();
11554 base_type = type;
11555 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREAL1,
11556 type);
11557 ffetype_set_ams (type,
11558 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11559 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11560 ffetype_set_star (base_type,
11561 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11562 type);
11563 ffetype_set_kind (base_type, 1, type);
11564 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
11565 = FFETARGET_f2cTYCOMPLEX;
11566 assert (ffetype_size (type) == sizeof (ffetargetComplex1));
11567
11568 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREALDOUBLE]
11569 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]);
11570 pushdecl (build_decl (TYPE_DECL, get_identifier ("double complex"),
11571 t));
11572 type = ffetype_new ();
11573 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREALDOUBLE,
11574 type);
11575 ffetype_set_ams (type,
11576 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11577 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11578 ffetype_set_star (base_type,
11579 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11580 type);
11581 ffetype_set_kind (base_type, 2,
11582 type);
11583 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL2]
11584 = FFETARGET_f2cTYDCOMPLEX;
11585 assert (ffetype_size (type) == sizeof (ffetargetComplex2));
11586
11587 /* Make function and ptr-to-function types for non-CHARACTER types. */
11588
11589 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11590 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11591 {
11592 if ((t = ffecom_tree_type[i][j]) != NULL_TREE)
11593 {
11594 if (i == FFEINFO_basictypeINTEGER)
11595 {
11596 /* Figure out the smallest INTEGER type that can hold
11597 a pointer on this machine. */
11598 if (GET_MODE_SIZE (TYPE_MODE (t))
11599 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
11600 {
11601 if ((ffecom_pointer_kind_ == FFEINFO_kindtypeNONE)
11602 || (GET_MODE_SIZE (TYPE_MODE (ffecom_tree_type[i][ffecom_pointer_kind_]))
11603 > GET_MODE_SIZE (TYPE_MODE (t))))
11604 ffecom_pointer_kind_ = j;
11605 }
11606 }
11607 else if (i == FFEINFO_basictypeCOMPLEX)
11608 t = void_type_node;
11609 /* For f2c compatibility, REAL functions are really
11610 implemented as DOUBLE PRECISION. */
11611 else if ((i == FFEINFO_basictypeREAL)
11612 && (j == FFEINFO_kindtypeREAL1))
11613 t = ffecom_tree_type
11614 [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2];
11615
11616 t = ffecom_tree_fun_type[i][j] = build_function_type (t,
11617 NULL_TREE);
11618 ffecom_tree_ptr_to_fun_type[i][j] = build_pointer_type (t);
11619 }
11620 }
11621
11622 /* Set up pointer types. */
11623
11624 if (ffecom_pointer_kind_ == FFEINFO_basictypeNONE)
11625 fatal_error ("no INTEGER type can hold a pointer on this configuration");
11626 else if (0 && ffe_is_do_internal_checks ())
11627 fprintf (stderr, "Pointer type kt=%d\n", ffecom_pointer_kind_);
11628 ffetype_set_kind (ffeinfo_type (FFEINFO_basictypeINTEGER,
11629 FFEINFO_kindtypeINTEGERDEFAULT),
11630 7,
11631 ffeinfo_type (FFEINFO_basictypeINTEGER,
11632 ffecom_pointer_kind_));
11633
11634 if (ffe_is_ugly_assign ())
11635 ffecom_label_kind_ = ffecom_pointer_kind_; /* Require ASSIGN etc to this. */
11636 else
11637 ffecom_label_kind_ = FFEINFO_kindtypeINTEGERDEFAULT;
11638 if (0 && ffe_is_do_internal_checks ())
11639 fprintf (stderr, "Label type kt=%d\n", ffecom_label_kind_);
11640
11641 ffecom_integer_type_node
11642 = ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1];
11643 ffecom_integer_zero_node = convert (ffecom_integer_type_node,
11644 integer_zero_node);
11645 ffecom_integer_one_node = convert (ffecom_integer_type_node,
11646 integer_one_node);
11647
11648 /* Yes, the "FLOAT_TYPE_SIZE" references below are intentional.
11649 Turns out that by TYLONG, runtime/libI77/lio.h really means
11650 "whatever size an ftnint is". For consistency and sanity,
11651 com.h and runtime/f2c.h.in agree that flag, ftnint, and ftlen
11652 all are INTEGER, which we also make out of whatever back-end
11653 integer type is FLOAT_TYPE_SIZE bits wide. This change, from
11654 LONG_TYPE_SIZE, for TYLONG and TYLOGICAL, was necessary to
11655 accommodate machines like the Alpha. Note that this suggests
11656 f2c and libf2c are missing a distinction perhaps needed on
11657 some machines between "int" and "long int". -- burley 0.5.5 950215 */
11658
11659 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, FLOAT_TYPE_SIZE,
11660 FFETARGET_f2cTYLONG);
11661 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, SHORT_TYPE_SIZE,
11662 FFETARGET_f2cTYSHORT);
11663 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, CHAR_TYPE_SIZE,
11664 FFETARGET_f2cTYINT1);
11665 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, LONG_LONG_TYPE_SIZE,
11666 FFETARGET_f2cTYQUAD);
11667 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, FLOAT_TYPE_SIZE,
11668 FFETARGET_f2cTYLOGICAL);
11669 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, SHORT_TYPE_SIZE,
11670 FFETARGET_f2cTYLOGICAL2);
11671 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, CHAR_TYPE_SIZE,
11672 FFETARGET_f2cTYLOGICAL1);
11673 /* ~~~Not really such a type in libf2c, e.g. I/O support? */
11674 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, LONG_LONG_TYPE_SIZE,
11675 FFETARGET_f2cTYQUAD);
11676
11677 /* CHARACTER stuff is all special-cased, so it is not handled in the above
11678 loop. CHARACTER items are built as arrays of unsigned char. */
11679
11680 ffecom_tree_type[FFEINFO_basictypeCHARACTER]
11681 [FFEINFO_kindtypeCHARACTER1] = t = char_type_node;
11682 type = ffetype_new ();
11683 base_type = type;
11684 ffeinfo_set_type (FFEINFO_basictypeCHARACTER,
11685 FFEINFO_kindtypeCHARACTER1,
11686 type);
11687 ffetype_set_ams (type,
11688 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11689 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11690 ffetype_set_kind (base_type, 1, type);
11691 assert (ffetype_size (type)
11692 == sizeof (((ffetargetCharacter1) { 0, NULL }).text[0]));
11693
11694 ffecom_tree_fun_type[FFEINFO_basictypeCHARACTER]
11695 [FFEINFO_kindtypeCHARACTER1] = ffecom_tree_fun_type_void;
11696 ffecom_tree_ptr_to_fun_type[FFEINFO_basictypeCHARACTER]
11697 [FFEINFO_kindtypeCHARACTER1]
11698 = ffecom_tree_ptr_to_fun_type_void;
11699 ffecom_f2c_typecode_[FFEINFO_basictypeCHARACTER][FFEINFO_kindtypeCHARACTER1]
11700 = FFETARGET_f2cTYCHAR;
11701
11702 ffecom_f2c_typecode_[FFEINFO_basictypeANY][FFEINFO_kindtypeANY]
11703 = 0;
11704
11705 /* Make multi-return-value type and fields. */
11706
11707 ffecom_multi_type_node_ = make_node (UNION_TYPE);
11708
11709 field = NULL_TREE;
11710
11711 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11712 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11713 {
11714 char name[30];
11715
11716 if (ffecom_tree_type[i][j] == NULL_TREE)
11717 continue; /* Not supported. */
11718 sprintf (&name[0], "bt_%s_kt_%s",
11719 ffeinfo_basictype_string ((ffeinfoBasictype) i),
11720 ffeinfo_kindtype_string ((ffeinfoKindtype) j));
11721 ffecom_multi_fields_[i][j] = build_decl (FIELD_DECL,
11722 get_identifier (name),
11723 ffecom_tree_type[i][j]);
11724 DECL_CONTEXT (ffecom_multi_fields_[i][j])
11725 = ffecom_multi_type_node_;
11726 DECL_ALIGN (ffecom_multi_fields_[i][j]) = 0;
11727 DECL_USER_ALIGN (ffecom_multi_fields_[i][j]) = 0;
11728 TREE_CHAIN (ffecom_multi_fields_[i][j]) = field;
11729 field = ffecom_multi_fields_[i][j];
11730 }
11731
11732 TYPE_FIELDS (ffecom_multi_type_node_) = field;
11733 layout_type (ffecom_multi_type_node_);
11734
11735 /* Subroutines usually return integer because they might have alternate
11736 returns. */
11737
11738 ffecom_tree_subr_type
11739 = build_function_type (integer_type_node, NULL_TREE);
11740 ffecom_tree_ptr_to_subr_type
11741 = build_pointer_type (ffecom_tree_subr_type);
11742 ffecom_tree_blockdata_type
11743 = build_function_type (void_type_node, NULL_TREE);
11744
11745 builtin_function ("__builtin_sqrtf", float_ftype_float,
11746 BUILT_IN_SQRTF, BUILT_IN_NORMAL, "sqrtf", NULL_TREE);
11747 builtin_function ("__builtin_sqrt", double_ftype_double,
11748 BUILT_IN_SQRT, BUILT_IN_NORMAL, "sqrt", NULL_TREE);
11749 builtin_function ("__builtin_sqrtl", ldouble_ftype_ldouble,
11750 BUILT_IN_SQRTL, BUILT_IN_NORMAL, "sqrtl", NULL_TREE);
11751 builtin_function ("__builtin_sinf", float_ftype_float,
11752 BUILT_IN_SINF, BUILT_IN_NORMAL, "sinf", NULL_TREE);
11753 builtin_function ("__builtin_sin", double_ftype_double,
11754 BUILT_IN_SIN, BUILT_IN_NORMAL, "sin", NULL_TREE);
11755 builtin_function ("__builtin_sinl", ldouble_ftype_ldouble,
11756 BUILT_IN_SINL, BUILT_IN_NORMAL, "sinl", NULL_TREE);
11757 builtin_function ("__builtin_cosf", float_ftype_float,
11758 BUILT_IN_COSF, BUILT_IN_NORMAL, "cosf", NULL_TREE);
11759 builtin_function ("__builtin_cos", double_ftype_double,
11760 BUILT_IN_COS, BUILT_IN_NORMAL, "cos", NULL_TREE);
11761 builtin_function ("__builtin_cosl", ldouble_ftype_ldouble,
11762 BUILT_IN_COSL, BUILT_IN_NORMAL, "cosl", NULL_TREE);
11763
11764 pedantic_lvalues = FALSE;
11765
11766 ffecom_f2c_make_type_ (&ffecom_f2c_integer_type_node,
11767 FFECOM_f2cINTEGER,
11768 "integer");
11769 ffecom_f2c_make_type_ (&ffecom_f2c_address_type_node,
11770 FFECOM_f2cADDRESS,
11771 "address");
11772 ffecom_f2c_make_type_ (&ffecom_f2c_real_type_node,
11773 FFECOM_f2cREAL,
11774 "real");
11775 ffecom_f2c_make_type_ (&ffecom_f2c_doublereal_type_node,
11776 FFECOM_f2cDOUBLEREAL,
11777 "doublereal");
11778 ffecom_f2c_make_type_ (&ffecom_f2c_complex_type_node,
11779 FFECOM_f2cCOMPLEX,
11780 "complex");
11781 ffecom_f2c_make_type_ (&ffecom_f2c_doublecomplex_type_node,
11782 FFECOM_f2cDOUBLECOMPLEX,
11783 "doublecomplex");
11784 ffecom_f2c_make_type_ (&ffecom_f2c_longint_type_node,
11785 FFECOM_f2cLONGINT,
11786 "longint");
11787 ffecom_f2c_make_type_ (&ffecom_f2c_logical_type_node,
11788 FFECOM_f2cLOGICAL,
11789 "logical");
11790 ffecom_f2c_make_type_ (&ffecom_f2c_flag_type_node,
11791 FFECOM_f2cFLAG,
11792 "flag");
11793 ffecom_f2c_make_type_ (&ffecom_f2c_ftnlen_type_node,
11794 FFECOM_f2cFTNLEN,
11795 "ftnlen");
11796 ffecom_f2c_make_type_ (&ffecom_f2c_ftnint_type_node,
11797 FFECOM_f2cFTNINT,
11798 "ftnint");
11799
11800 ffecom_f2c_ftnlen_zero_node
11801 = convert (ffecom_f2c_ftnlen_type_node, integer_zero_node);
11802
11803 ffecom_f2c_ftnlen_one_node
11804 = convert (ffecom_f2c_ftnlen_type_node, integer_one_node);
11805
11806 ffecom_f2c_ftnlen_two_node = build_int_2 (2, 0);
11807 TREE_TYPE (ffecom_f2c_ftnlen_two_node) = ffecom_integer_type_node;
11808
11809 ffecom_f2c_ptr_to_ftnlen_type_node
11810 = build_pointer_type (ffecom_f2c_ftnlen_type_node);
11811
11812 ffecom_f2c_ptr_to_ftnint_type_node
11813 = build_pointer_type (ffecom_f2c_ftnint_type_node);
11814
11815 ffecom_f2c_ptr_to_integer_type_node
11816 = build_pointer_type (ffecom_f2c_integer_type_node);
11817
11818 ffecom_f2c_ptr_to_real_type_node
11819 = build_pointer_type (ffecom_f2c_real_type_node);
11820
11821 ffecom_float_zero_ = build_real (float_type_node, dconst0);
11822 ffecom_double_zero_ = build_real (double_type_node, dconst0);
11823 {
11824 REAL_VALUE_TYPE point_5;
11825
11826 REAL_ARITHMETIC (point_5, RDIV_EXPR, dconst1, dconst2);
11827 ffecom_float_half_ = build_real (float_type_node, point_5);
11828 ffecom_double_half_ = build_real (double_type_node, point_5);
11829 }
11830
11831 /* Do "extern int xargc;". */
11832
11833 ffecom_tree_xargc_ = build_decl (VAR_DECL,
11834 get_identifier ("f__xargc"),
11835 integer_type_node);
11836 DECL_EXTERNAL (ffecom_tree_xargc_) = 1;
11837 TREE_STATIC (ffecom_tree_xargc_) = 1;
11838 TREE_PUBLIC (ffecom_tree_xargc_) = 1;
11839 ffecom_tree_xargc_ = start_decl (ffecom_tree_xargc_, FALSE);
11840 finish_decl (ffecom_tree_xargc_, NULL_TREE, FALSE);
11841
11842 #if 0 /* This is being fixed, and seems to be working now. */
11843 if ((FLOAT_TYPE_SIZE != 32)
11844 || (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))) != 32))
11845 {
11846 warning ("configuration: REAL, INTEGER, and LOGICAL are %d bits wide,",
11847 (int) FLOAT_TYPE_SIZE);
11848 warning ("and pointers are %d bits wide, but g77 doesn't yet work",
11849 (int) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))));
11850 warning ("properly unless they all are 32 bits wide");
11851 warning ("Please keep this in mind before you report bugs.");
11852 }
11853 #endif
11854
11855 #if 0 /* Code in ste.c that would crash has been commented out. */
11856 if (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
11857 < TYPE_PRECISION (string_type_node))
11858 /* I/O will probably crash. */
11859 warning ("configuration: char * holds %d bits, but ftnlen only %d",
11860 TYPE_PRECISION (string_type_node),
11861 TYPE_PRECISION (ffecom_f2c_ftnlen_type_node));
11862 #endif
11863
11864 #if 0 /* ASSIGN-related stuff has been changed to accommodate this. */
11865 if (TYPE_PRECISION (ffecom_integer_type_node)
11866 < TYPE_PRECISION (string_type_node))
11867 /* ASSIGN 10 TO I will crash. */
11868 warning ("configuration: char * holds %d bits, but INTEGER only %d --\n\
11869 ASSIGN statement might fail",
11870 TYPE_PRECISION (string_type_node),
11871 TYPE_PRECISION (ffecom_integer_type_node));
11872 #endif
11873 }
11874
11875 /* ffecom_init_2 -- Initialize
11876
11877 ffecom_init_2(); */
11878
11879 void
ffecom_init_2()11880 ffecom_init_2 ()
11881 {
11882 assert (ffecom_outer_function_decl_ == NULL_TREE);
11883 assert (current_function_decl == NULL_TREE);
11884 assert (ffecom_which_entrypoint_decl_ == NULL_TREE);
11885
11886 ffecom_master_arglist_ = NULL;
11887 ++ffecom_num_fns_;
11888 ffecom_primary_entry_ = NULL;
11889 ffecom_is_altreturning_ = FALSE;
11890 ffecom_func_result_ = NULL_TREE;
11891 ffecom_multi_retval_ = NULL_TREE;
11892 }
11893
11894 /* ffecom_list_expr -- Transform list of exprs into gcc tree
11895
11896 tree t;
11897 ffebld expr; // FFE opITEM list.
11898 tree = ffecom_list_expr(expr);
11899
11900 List of actual args is transformed into corresponding gcc backend list. */
11901
11902 tree
ffecom_list_expr(ffebld expr)11903 ffecom_list_expr (ffebld expr)
11904 {
11905 tree list;
11906 tree *plist = &list;
11907 tree trail = NULL_TREE; /* Append char length args here. */
11908 tree *ptrail = &trail;
11909 tree length;
11910
11911 while (expr != NULL)
11912 {
11913 tree texpr = ffecom_arg_expr (ffebld_head (expr), &length);
11914
11915 if (texpr == error_mark_node)
11916 return error_mark_node;
11917
11918 *plist = build_tree_list (NULL_TREE, texpr);
11919 plist = &TREE_CHAIN (*plist);
11920 expr = ffebld_trail (expr);
11921 if (length != NULL_TREE)
11922 {
11923 *ptrail = build_tree_list (NULL_TREE, length);
11924 ptrail = &TREE_CHAIN (*ptrail);
11925 }
11926 }
11927
11928 *plist = trail;
11929
11930 return list;
11931 }
11932
11933 /* ffecom_list_ptr_to_expr -- Transform list of exprs into gcc tree
11934
11935 tree t;
11936 ffebld expr; // FFE opITEM list.
11937 tree = ffecom_list_ptr_to_expr(expr);
11938
11939 List of actual args is transformed into corresponding gcc backend list for
11940 use in calling an external procedure (vs. a statement function). */
11941
11942 tree
ffecom_list_ptr_to_expr(ffebld expr)11943 ffecom_list_ptr_to_expr (ffebld expr)
11944 {
11945 tree list;
11946 tree *plist = &list;
11947 tree trail = NULL_TREE; /* Append char length args here. */
11948 tree *ptrail = &trail;
11949 tree length;
11950
11951 while (expr != NULL)
11952 {
11953 tree texpr = ffecom_arg_ptr_to_expr (ffebld_head (expr), &length);
11954
11955 if (texpr == error_mark_node)
11956 return error_mark_node;
11957
11958 *plist = build_tree_list (NULL_TREE, texpr);
11959 plist = &TREE_CHAIN (*plist);
11960 expr = ffebld_trail (expr);
11961 if (length != NULL_TREE)
11962 {
11963 *ptrail = build_tree_list (NULL_TREE, length);
11964 ptrail = &TREE_CHAIN (*ptrail);
11965 }
11966 }
11967
11968 *plist = trail;
11969
11970 return list;
11971 }
11972
11973 /* Obtain gcc's LABEL_DECL tree for label. */
11974
11975 tree
ffecom_lookup_label(ffelab label)11976 ffecom_lookup_label (ffelab label)
11977 {
11978 tree glabel;
11979
11980 if (ffelab_hook (label) == NULL_TREE)
11981 {
11982 char labelname[16];
11983
11984 switch (ffelab_type (label))
11985 {
11986 case FFELAB_typeLOOPEND:
11987 case FFELAB_typeNOTLOOP:
11988 case FFELAB_typeENDIF:
11989 sprintf (labelname, "%" ffelabValue_f "u", ffelab_value (label));
11990 glabel = build_decl (LABEL_DECL, get_identifier (labelname),
11991 void_type_node);
11992 DECL_CONTEXT (glabel) = current_function_decl;
11993 DECL_MODE (glabel) = VOIDmode;
11994 break;
11995
11996 case FFELAB_typeFORMAT:
11997 glabel = build_decl (VAR_DECL,
11998 ffecom_get_invented_identifier
11999 ("__g77_format_%d", (int) ffelab_value (label)),
12000 build_type_variant (build_array_type
12001 (char_type_node,
12002 NULL_TREE),
12003 1, 0));
12004 TREE_CONSTANT (glabel) = 1;
12005 TREE_STATIC (glabel) = 1;
12006 DECL_CONTEXT (glabel) = current_function_decl;
12007 DECL_INITIAL (glabel) = NULL;
12008 make_decl_rtl (glabel, NULL);
12009 expand_decl (glabel);
12010
12011 ffecom_save_tree_forever (glabel);
12012
12013 break;
12014
12015 case FFELAB_typeANY:
12016 glabel = error_mark_node;
12017 break;
12018
12019 default:
12020 assert ("bad label type" == NULL);
12021 glabel = NULL;
12022 break;
12023 }
12024 ffelab_set_hook (label, glabel);
12025 }
12026 else
12027 {
12028 glabel = ffelab_hook (label);
12029 }
12030
12031 return glabel;
12032 }
12033
12034 /* Stabilizes the arguments. Don't use this if the lhs and rhs come from
12035 a single source specification (as in the fourth argument of MVBITS).
12036 If the type is NULL_TREE, the type of lhs is used to make the type of
12037 the MODIFY_EXPR. */
12038
12039 tree
ffecom_modify(tree newtype,tree lhs,tree rhs)12040 ffecom_modify (tree newtype, tree lhs,
12041 tree rhs)
12042 {
12043 if (lhs == error_mark_node || rhs == error_mark_node)
12044 return error_mark_node;
12045
12046 if (newtype == NULL_TREE)
12047 newtype = TREE_TYPE (lhs);
12048
12049 if (TREE_SIDE_EFFECTS (lhs))
12050 lhs = stabilize_reference (lhs);
12051
12052 return ffecom_2s (MODIFY_EXPR, newtype, lhs, rhs);
12053 }
12054
12055 /* Register source file name. */
12056
12057 void
ffecom_file(const char * name)12058 ffecom_file (const char *name)
12059 {
12060 ffecom_file_ (name);
12061 }
12062
12063 /* ffecom_notify_init_storage -- An aggregate storage is now fully init'ed
12064
12065 ffestorag st;
12066 ffecom_notify_init_storage(st);
12067
12068 Gets called when all possible units in an aggregate storage area (a LOCAL
12069 with equivalences or a COMMON) have been initialized. The initialization
12070 info either is in ffestorag_init or, if that is NULL,
12071 ffestorag_accretion:
12072
12073 ffestorag_init may contain an opCONTER or opARRTER. opCONTER may occur
12074 even for an array if the array is one element in length!
12075
12076 ffestorag_accretion will contain an opACCTER. It is much like an
12077 opARRTER except it has an ffebit object in it instead of just a size.
12078 The back end can use the info in the ffebit object, if it wants, to
12079 reduce the amount of actual initialization, but in any case it should
12080 kill the ffebit object when done. Also, set accretion to NULL but
12081 init to a non-NULL value.
12082
12083 After performing initialization, DO NOT set init to NULL, because that'll
12084 tell the front end it is ok for more initialization to happen. Instead,
12085 set init to an opANY expression or some such thing that you can use to
12086 tell that you've already initialized the object.
12087
12088 27-Oct-91 JCB 1.1
12089 Support two-pass FFE. */
12090
12091 void
ffecom_notify_init_storage(ffestorag st)12092 ffecom_notify_init_storage (ffestorag st)
12093 {
12094 ffebld init; /* The initialization expression. */
12095
12096 if (ffestorag_init (st) == NULL)
12097 {
12098 init = ffestorag_accretion (st);
12099 assert (init != NULL);
12100 ffestorag_set_accretion (st, NULL);
12101 ffestorag_set_accretes (st, 0);
12102 ffestorag_set_init (st, init);
12103 }
12104 }
12105
12106 /* ffecom_notify_init_symbol -- A symbol is now fully init'ed
12107
12108 ffesymbol s;
12109 ffecom_notify_init_symbol(s);
12110
12111 Gets called when all possible units in a symbol (not placed in COMMON
12112 or involved in EQUIVALENCE, unless it as yet has no ffestorag object)
12113 have been initialized. The initialization info either is in
12114 ffesymbol_init or, if that is NULL, ffesymbol_accretion:
12115
12116 ffesymbol_init may contain an opCONTER or opARRTER. opCONTER may occur
12117 even for an array if the array is one element in length!
12118
12119 ffesymbol_accretion will contain an opACCTER. It is much like an
12120 opARRTER except it has an ffebit object in it instead of just a size.
12121 The back end can use the info in the ffebit object, if it wants, to
12122 reduce the amount of actual initialization, but in any case it should
12123 kill the ffebit object when done. Also, set accretion to NULL but
12124 init to a non-NULL value.
12125
12126 After performing initialization, DO NOT set init to NULL, because that'll
12127 tell the front end it is ok for more initialization to happen. Instead,
12128 set init to an opANY expression or some such thing that you can use to
12129 tell that you've already initialized the object.
12130
12131 27-Oct-91 JCB 1.1
12132 Support two-pass FFE. */
12133
12134 void
ffecom_notify_init_symbol(ffesymbol s)12135 ffecom_notify_init_symbol (ffesymbol s)
12136 {
12137 ffebld init; /* The initialization expression. */
12138
12139 if (ffesymbol_storage (s) == NULL)
12140 return; /* Do nothing until COMMON/EQUIVALENCE
12141 possibilities checked. */
12142
12143 if ((ffesymbol_init (s) == NULL)
12144 && ((init = ffesymbol_accretion (s)) != NULL))
12145 {
12146 ffesymbol_set_accretion (s, NULL);
12147 ffesymbol_set_accretes (s, 0);
12148 ffesymbol_set_init (s, init);
12149 }
12150 }
12151
12152 /* ffecom_notify_primary_entry -- Learn which is the primary entry point
12153
12154 ffesymbol s;
12155 ffecom_notify_primary_entry(s);
12156
12157 Gets called when implicit or explicit PROGRAM statement seen or when
12158 FUNCTION, SUBROUTINE, or BLOCK DATA statement seen, with the primary
12159 global symbol that serves as the entry point. */
12160
12161 void
ffecom_notify_primary_entry(ffesymbol s)12162 ffecom_notify_primary_entry (ffesymbol s)
12163 {
12164 ffecom_primary_entry_ = s;
12165 ffecom_primary_entry_kind_ = ffesymbol_kind (s);
12166
12167 if ((ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
12168 || (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE))
12169 ffecom_primary_entry_is_proc_ = TRUE;
12170 else
12171 ffecom_primary_entry_is_proc_ = FALSE;
12172
12173 if (!ffe_is_silent ())
12174 {
12175 if (ffecom_primary_entry_kind_ == FFEINFO_kindPROGRAM)
12176 fprintf (stderr, "%s:\n", ffesymbol_text (s));
12177 else
12178 fprintf (stderr, " %s:\n", ffesymbol_text (s));
12179 }
12180
12181 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
12182 {
12183 ffebld list;
12184 ffebld arg;
12185
12186 for (list = ffesymbol_dummyargs (s);
12187 list != NULL;
12188 list = ffebld_trail (list))
12189 {
12190 arg = ffebld_head (list);
12191 if (ffebld_op (arg) == FFEBLD_opSTAR)
12192 {
12193 ffecom_is_altreturning_ = TRUE;
12194 break;
12195 }
12196 }
12197 }
12198 }
12199
12200 FILE *
ffecom_open_include(char * name,ffewhereLine l,ffewhereColumn c)12201 ffecom_open_include (char *name, ffewhereLine l, ffewhereColumn c)
12202 {
12203 return ffecom_open_include_ (name, l, c);
12204 }
12205
12206 /* ffecom_ptr_to_expr -- Transform expr into gcc tree with & in front
12207
12208 tree t;
12209 ffebld expr; // FFE expression.
12210 tree = ffecom_ptr_to_expr(expr);
12211
12212 Like ffecom_expr, but sticks address-of in front of most things. */
12213
12214 tree
ffecom_ptr_to_expr(ffebld expr)12215 ffecom_ptr_to_expr (ffebld expr)
12216 {
12217 tree item;
12218 ffeinfoBasictype bt;
12219 ffeinfoKindtype kt;
12220 ffesymbol s;
12221
12222 assert (expr != NULL);
12223
12224 switch (ffebld_op (expr))
12225 {
12226 case FFEBLD_opSYMTER:
12227 s = ffebld_symter (expr);
12228 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
12229 {
12230 ffecomGfrt ix;
12231
12232 ix = ffeintrin_gfrt_indirect (ffebld_symter_implementation (expr));
12233 assert (ix != FFECOM_gfrt);
12234 if ((item = ffecom_gfrt_[ix]) == NULL_TREE)
12235 {
12236 ffecom_make_gfrt_ (ix);
12237 item = ffecom_gfrt_[ix];
12238 }
12239 }
12240 else
12241 {
12242 item = ffesymbol_hook (s).decl_tree;
12243 if (item == NULL_TREE)
12244 {
12245 s = ffecom_sym_transform_ (s);
12246 item = ffesymbol_hook (s).decl_tree;
12247 }
12248 }
12249 assert (item != NULL);
12250 if (item == error_mark_node)
12251 return item;
12252 if (!ffesymbol_hook (s).addr)
12253 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12254 item);
12255 return item;
12256
12257 case FFEBLD_opARRAYREF:
12258 return ffecom_arrayref_ (NULL_TREE, expr, 1);
12259
12260 case FFEBLD_opCONTER:
12261
12262 bt = ffeinfo_basictype (ffebld_info (expr));
12263 kt = ffeinfo_kindtype (ffebld_info (expr));
12264
12265 item = ffecom_constantunion (&ffebld_constant_union
12266 (ffebld_conter (expr)), bt, kt,
12267 ffecom_tree_type[bt][kt]);
12268 if (item == error_mark_node)
12269 return error_mark_node;
12270 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12271 item);
12272 return item;
12273
12274 case FFEBLD_opANY:
12275 return error_mark_node;
12276
12277 default:
12278 bt = ffeinfo_basictype (ffebld_info (expr));
12279 kt = ffeinfo_kindtype (ffebld_info (expr));
12280
12281 item = ffecom_expr (expr);
12282 if (item == error_mark_node)
12283 return error_mark_node;
12284
12285 /* The back end currently optimizes a bit too zealously for us, in that
12286 we fail JCB001 if the following block of code is omitted. It checks
12287 to see if the transformed expression is a symbol or array reference,
12288 and encloses it in a SAVE_EXPR if that is the case. */
12289
12290 STRIP_NOPS (item);
12291 if ((TREE_CODE (item) == VAR_DECL)
12292 || (TREE_CODE (item) == PARM_DECL)
12293 || (TREE_CODE (item) == RESULT_DECL)
12294 || (TREE_CODE (item) == INDIRECT_REF)
12295 || (TREE_CODE (item) == ARRAY_REF)
12296 || (TREE_CODE (item) == COMPONENT_REF)
12297 #ifdef OFFSET_REF
12298 || (TREE_CODE (item) == OFFSET_REF)
12299 #endif
12300 || (TREE_CODE (item) == BUFFER_REF)
12301 || (TREE_CODE (item) == REALPART_EXPR)
12302 || (TREE_CODE (item) == IMAGPART_EXPR))
12303 {
12304 item = ffecom_save_tree (item);
12305 }
12306
12307 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12308 item);
12309 return item;
12310 }
12311
12312 assert ("fall-through error" == NULL);
12313 return error_mark_node;
12314 }
12315
12316 /* Obtain a temp var with given data type.
12317
12318 size is FFETARGET_charactersizeNONE for a non-CHARACTER type
12319 or >= 0 for a CHARACTER type.
12320
12321 elements is -1 for a scalar or > 0 for an array of type. */
12322
12323 tree
ffecom_make_tempvar(const char * commentary,tree type,ffetargetCharacterSize size,int elements)12324 ffecom_make_tempvar (const char *commentary, tree type,
12325 ffetargetCharacterSize size, int elements)
12326 {
12327 tree t;
12328 static int mynumber;
12329
12330 assert (current_binding_level->prep_state < 2);
12331
12332 if (type == error_mark_node)
12333 return error_mark_node;
12334
12335 if (size != FFETARGET_charactersizeNONE)
12336 type = build_array_type (type,
12337 build_range_type (ffecom_f2c_ftnlen_type_node,
12338 ffecom_f2c_ftnlen_one_node,
12339 build_int_2 (size, 0)));
12340 if (elements != -1)
12341 type = build_array_type (type,
12342 build_range_type (integer_type_node,
12343 integer_zero_node,
12344 build_int_2 (elements - 1,
12345 0)));
12346 t = build_decl (VAR_DECL,
12347 ffecom_get_invented_identifier ("__g77_%s_%d",
12348 commentary,
12349 mynumber++),
12350 type);
12351
12352 t = start_decl (t, FALSE);
12353 finish_decl (t, NULL_TREE, FALSE);
12354
12355 return t;
12356 }
12357
12358 /* Prepare argument pointer to expression.
12359
12360 Like ffecom_prepare_expr, except for expressions to be evaluated
12361 via ffecom_arg_ptr_to_expr. */
12362
12363 void
ffecom_prepare_arg_ptr_to_expr(ffebld expr)12364 ffecom_prepare_arg_ptr_to_expr (ffebld expr)
12365 {
12366 /* ~~For now, it seems to be the same thing. */
12367 ffecom_prepare_expr (expr);
12368 return;
12369 }
12370
12371 /* End of preparations. */
12372
12373 bool
ffecom_prepare_end(void)12374 ffecom_prepare_end (void)
12375 {
12376 int prep_state = current_binding_level->prep_state;
12377
12378 assert (prep_state < 2);
12379 current_binding_level->prep_state = 2;
12380
12381 return (prep_state == 1) ? TRUE : FALSE;
12382 }
12383
12384 /* Prepare expression.
12385
12386 This is called before any code is generated for the current block.
12387 It scans the expression, declares any temporaries that might be needed
12388 during evaluation of the expression, and stores those temporaries in
12389 the appropriate "hook" fields of the expression. `dest', if not NULL,
12390 specifies the destination that ffecom_expr_ will see, in case that
12391 helps avoid generating unused temporaries.
12392
12393 ~~Improve to avoid allocating unused temporaries by taking `dest'
12394 into account vis-a-vis aliasing requirements of complex/character
12395 functions. */
12396
12397 void
ffecom_prepare_expr_(ffebld expr,ffebld dest UNUSED)12398 ffecom_prepare_expr_ (ffebld expr, ffebld dest UNUSED)
12399 {
12400 ffeinfoBasictype bt;
12401 ffeinfoKindtype kt;
12402 ffetargetCharacterSize sz;
12403 tree tempvar = NULL_TREE;
12404
12405 assert (current_binding_level->prep_state < 2);
12406
12407 if (! expr)
12408 return;
12409
12410 bt = ffeinfo_basictype (ffebld_info (expr));
12411 kt = ffeinfo_kindtype (ffebld_info (expr));
12412 sz = ffeinfo_size (ffebld_info (expr));
12413
12414 /* Generate whatever temporaries are needed to represent the result
12415 of the expression. */
12416
12417 if (bt == FFEINFO_basictypeCHARACTER)
12418 {
12419 while (ffebld_op (expr) == FFEBLD_opPAREN)
12420 expr = ffebld_left (expr);
12421 }
12422
12423 switch (ffebld_op (expr))
12424 {
12425 default:
12426 /* Don't make temps for SYMTER, CONTER, etc. */
12427 if (ffebld_arity (expr) == 0)
12428 break;
12429
12430 switch (bt)
12431 {
12432 case FFEINFO_basictypeCOMPLEX:
12433 if (ffebld_op (expr) == FFEBLD_opFUNCREF)
12434 {
12435 ffesymbol s;
12436
12437 if (ffebld_op (ffebld_left (expr)) != FFEBLD_opSYMTER)
12438 break;
12439
12440 s = ffebld_symter (ffebld_left (expr));
12441 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT
12442 || (ffesymbol_where (s) != FFEINFO_whereINTRINSIC
12443 && ! ffesymbol_is_f2c (s))
12444 || (ffesymbol_where (s) == FFEINFO_whereINTRINSIC
12445 && ! ffe_is_f2c_library ()))
12446 break;
12447 }
12448 else if (ffebld_op (expr) == FFEBLD_opPOWER)
12449 {
12450 /* Requires special treatment. There's no POW_CC function
12451 in libg2c, so POW_ZZ is used, which means we always
12452 need a double-complex temp, not a single-complex. */
12453 kt = FFEINFO_kindtypeREAL2;
12454 }
12455 else if (ffebld_op (expr) != FFEBLD_opDIVIDE)
12456 /* The other ops don't need temps for complex operands. */
12457 break;
12458
12459 /* ~~~Avoid making temps for some intrinsics, such as AIMAG(C),
12460 REAL(C). See 19990325-0.f, routine `check', for cases. */
12461 tempvar = ffecom_make_tempvar ("complex",
12462 ffecom_tree_type
12463 [FFEINFO_basictypeCOMPLEX][kt],
12464 FFETARGET_charactersizeNONE,
12465 -1);
12466 break;
12467
12468 case FFEINFO_basictypeCHARACTER:
12469 if (ffebld_op (expr) != FFEBLD_opFUNCREF)
12470 break;
12471
12472 if (sz == FFETARGET_charactersizeNONE)
12473 /* ~~Kludge alert! This should someday be fixed. */
12474 sz = 24;
12475
12476 tempvar = ffecom_make_tempvar ("char", char_type_node, sz, -1);
12477 break;
12478
12479 default:
12480 break;
12481 }
12482 break;
12483
12484 case FFEBLD_opCONCATENATE:
12485 {
12486 /* This gets special handling, because only one set of temps
12487 is needed for a tree of these -- the tree is treated as
12488 a flattened list of concatenations when generating code. */
12489
12490 ffecomConcatList_ catlist;
12491 tree ltmp, itmp, result;
12492 int count;
12493 int i;
12494
12495 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
12496 count = ffecom_concat_list_count_ (catlist);
12497
12498 if (count >= 2)
12499 {
12500 ltmp
12501 = ffecom_make_tempvar ("concat_len",
12502 ffecom_f2c_ftnlen_type_node,
12503 FFETARGET_charactersizeNONE, count);
12504 itmp
12505 = ffecom_make_tempvar ("concat_item",
12506 ffecom_f2c_address_type_node,
12507 FFETARGET_charactersizeNONE, count);
12508 result
12509 = ffecom_make_tempvar ("concat_res",
12510 char_type_node,
12511 ffecom_concat_list_maxlen_ (catlist),
12512 -1);
12513
12514 tempvar = make_tree_vec (3);
12515 TREE_VEC_ELT (tempvar, 0) = ltmp;
12516 TREE_VEC_ELT (tempvar, 1) = itmp;
12517 TREE_VEC_ELT (tempvar, 2) = result;
12518 }
12519
12520 for (i = 0; i < count; ++i)
12521 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist,
12522 i));
12523
12524 ffecom_concat_list_kill_ (catlist);
12525
12526 if (tempvar)
12527 {
12528 ffebld_nonter_set_hook (expr, tempvar);
12529 current_binding_level->prep_state = 1;
12530 }
12531 }
12532 return;
12533
12534 case FFEBLD_opCONVERT:
12535 if (bt == FFEINFO_basictypeCHARACTER
12536 && ((ffebld_size_known (ffebld_left (expr))
12537 == FFETARGET_charactersizeNONE)
12538 || (ffebld_size_known (ffebld_left (expr)) >= sz)))
12539 tempvar = ffecom_make_tempvar ("convert", char_type_node, sz, -1);
12540 break;
12541 }
12542
12543 if (tempvar)
12544 {
12545 ffebld_nonter_set_hook (expr, tempvar);
12546 current_binding_level->prep_state = 1;
12547 }
12548
12549 /* Prepare subexpressions for this expr. */
12550
12551 switch (ffebld_op (expr))
12552 {
12553 case FFEBLD_opPERCENT_LOC:
12554 ffecom_prepare_ptr_to_expr (ffebld_left (expr));
12555 break;
12556
12557 case FFEBLD_opPERCENT_VAL:
12558 case FFEBLD_opPERCENT_REF:
12559 ffecom_prepare_expr (ffebld_left (expr));
12560 break;
12561
12562 case FFEBLD_opPERCENT_DESCR:
12563 ffecom_prepare_arg_ptr_to_expr (ffebld_left (expr));
12564 break;
12565
12566 case FFEBLD_opITEM:
12567 {
12568 ffebld item;
12569
12570 for (item = expr;
12571 item != NULL;
12572 item = ffebld_trail (item))
12573 if (ffebld_head (item) != NULL)
12574 ffecom_prepare_expr (ffebld_head (item));
12575 }
12576 break;
12577
12578 default:
12579 /* Need to handle character conversion specially. */
12580 switch (ffebld_arity (expr))
12581 {
12582 case 2:
12583 ffecom_prepare_expr (ffebld_left (expr));
12584 ffecom_prepare_expr (ffebld_right (expr));
12585 break;
12586
12587 case 1:
12588 ffecom_prepare_expr (ffebld_left (expr));
12589 break;
12590
12591 default:
12592 break;
12593 }
12594 }
12595
12596 return;
12597 }
12598
12599 /* Prepare expression for reading and writing.
12600
12601 Like ffecom_prepare_expr, except for expressions to be evaluated
12602 via ffecom_expr_rw. */
12603
12604 void
ffecom_prepare_expr_rw(tree type,ffebld expr)12605 ffecom_prepare_expr_rw (tree type, ffebld expr)
12606 {
12607 /* This is all we support for now. */
12608 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
12609
12610 /* ~~For now, it seems to be the same thing. */
12611 ffecom_prepare_expr (expr);
12612 return;
12613 }
12614
12615 /* Prepare expression for writing.
12616
12617 Like ffecom_prepare_expr, except for expressions to be evaluated
12618 via ffecom_expr_w. */
12619
12620 void
ffecom_prepare_expr_w(tree type,ffebld expr)12621 ffecom_prepare_expr_w (tree type, ffebld expr)
12622 {
12623 /* This is all we support for now. */
12624 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
12625
12626 /* ~~For now, it seems to be the same thing. */
12627 ffecom_prepare_expr (expr);
12628 return;
12629 }
12630
12631 /* Prepare expression for returning.
12632
12633 Like ffecom_prepare_expr, except for expressions to be evaluated
12634 via ffecom_return_expr. */
12635
12636 void
ffecom_prepare_return_expr(ffebld expr)12637 ffecom_prepare_return_expr (ffebld expr)
12638 {
12639 assert (current_binding_level->prep_state < 2);
12640
12641 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE
12642 && ffecom_is_altreturning_
12643 && expr != NULL)
12644 ffecom_prepare_expr (expr);
12645 }
12646
12647 /* Prepare pointer to expression.
12648
12649 Like ffecom_prepare_expr, except for expressions to be evaluated
12650 via ffecom_ptr_to_expr. */
12651
12652 void
ffecom_prepare_ptr_to_expr(ffebld expr)12653 ffecom_prepare_ptr_to_expr (ffebld expr)
12654 {
12655 /* ~~For now, it seems to be the same thing. */
12656 ffecom_prepare_expr (expr);
12657 return;
12658 }
12659
12660 /* Transform expression into constant pointer-to-expression tree.
12661
12662 If the expression can be transformed into a pointer-to-expression tree
12663 that is constant, that is done, and the tree returned. Else NULL_TREE
12664 is returned.
12665
12666 That way, a caller can attempt to provide compile-time initialization
12667 of a variable and, if that fails, *then* choose to start a new block
12668 and resort to using temporaries, as appropriate. */
12669
12670 tree
ffecom_ptr_to_const_expr(ffebld expr)12671 ffecom_ptr_to_const_expr (ffebld expr)
12672 {
12673 if (! expr)
12674 return integer_zero_node;
12675
12676 if (ffebld_op (expr) == FFEBLD_opANY)
12677 return error_mark_node;
12678
12679 if (ffebld_arity (expr) == 0
12680 && (ffebld_op (expr) != FFEBLD_opSYMTER
12681 || ffebld_where (expr) == FFEINFO_whereCOMMON
12682 || ffebld_where (expr) == FFEINFO_whereGLOBAL
12683 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
12684 {
12685 tree t;
12686
12687 t = ffecom_ptr_to_expr (expr);
12688 assert (TREE_CONSTANT (t));
12689 return t;
12690 }
12691
12692 return NULL_TREE;
12693 }
12694
12695 /* ffecom_return_expr -- Returns return-value expr given alt return expr
12696
12697 tree rtn; // NULL_TREE means use expand_null_return()
12698 ffebld expr; // NULL if no alt return expr to RETURN stmt
12699 rtn = ffecom_return_expr(expr);
12700
12701 Based on the program unit type and other info (like return function
12702 type, return master function type when alternate ENTRY points,
12703 whether subroutine has any alternate RETURN points, etc), returns the
12704 appropriate expression to be returned to the caller, or NULL_TREE
12705 meaning no return value or the caller expects it to be returned somewhere
12706 else (which is handled by other parts of this module). */
12707
12708 tree
ffecom_return_expr(ffebld expr)12709 ffecom_return_expr (ffebld expr)
12710 {
12711 tree rtn;
12712
12713 switch (ffecom_primary_entry_kind_)
12714 {
12715 case FFEINFO_kindPROGRAM:
12716 case FFEINFO_kindBLOCKDATA:
12717 rtn = NULL_TREE;
12718 break;
12719
12720 case FFEINFO_kindSUBROUTINE:
12721 if (!ffecom_is_altreturning_)
12722 rtn = NULL_TREE; /* No alt returns, never an expr. */
12723 else if (expr == NULL)
12724 rtn = integer_zero_node;
12725 else
12726 rtn = ffecom_expr (expr);
12727 break;
12728
12729 case FFEINFO_kindFUNCTION:
12730 if ((ffecom_multi_retval_ != NULL_TREE)
12731 || (ffesymbol_basictype (ffecom_primary_entry_)
12732 == FFEINFO_basictypeCHARACTER)
12733 || ((ffesymbol_basictype (ffecom_primary_entry_)
12734 == FFEINFO_basictypeCOMPLEX)
12735 && (ffecom_num_entrypoints_ == 0)
12736 && ffesymbol_is_f2c (ffecom_primary_entry_)))
12737 { /* Value is returned by direct assignment
12738 into (implicit) dummy. */
12739 rtn = NULL_TREE;
12740 break;
12741 }
12742 rtn = ffecom_func_result_;
12743 #if 0
12744 /* Spurious error if RETURN happens before first reference! So elide
12745 this code. In particular, for debugging registry, rtn should always
12746 be non-null after all, but TREE_USED won't be set until we encounter
12747 a reference in the code. Perfectly okay (but weird) code that,
12748 e.g., has "GOTO 20;10 RETURN;20 RTN=0;GOTO 10", would result in
12749 this diagnostic for no reason. Have people use -O -Wuninitialized
12750 and leave it to the back end to find obviously weird cases. */
12751
12752 /* Used to "assert(rtn != NULL_TREE);" here, but it's kind of a valid
12753 situation; if the return value has never been referenced, it won't
12754 have a tree under 2pass mode. */
12755 if ((rtn == NULL_TREE)
12756 || !TREE_USED (rtn))
12757 {
12758 ffebad_start (FFEBAD_RETURN_VALUE_UNSET);
12759 ffebad_here (0, ffesymbol_where_line (ffecom_primary_entry_),
12760 ffesymbol_where_column (ffecom_primary_entry_));
12761 ffebad_string (ffesymbol_text (ffesymbol_funcresult
12762 (ffecom_primary_entry_)));
12763 ffebad_finish ();
12764 }
12765 #endif
12766 break;
12767
12768 default:
12769 assert ("bad unit kind" == NULL);
12770 case FFEINFO_kindANY:
12771 rtn = error_mark_node;
12772 break;
12773 }
12774
12775 return rtn;
12776 }
12777
12778 /* Do save_expr only if tree is not error_mark_node. */
12779
12780 tree
ffecom_save_tree(tree t)12781 ffecom_save_tree (tree t)
12782 {
12783 return save_expr (t);
12784 }
12785
12786 /* Start a compound statement (block). */
12787
12788 void
ffecom_start_compstmt(void)12789 ffecom_start_compstmt (void)
12790 {
12791 bison_rule_pushlevel_ ();
12792 }
12793
12794 /* Public entry point for front end to access start_decl. */
12795
12796 tree
ffecom_start_decl(tree decl,bool is_initialized)12797 ffecom_start_decl (tree decl, bool is_initialized)
12798 {
12799 DECL_INITIAL (decl) = is_initialized ? error_mark_node : NULL_TREE;
12800 return start_decl (decl, FALSE);
12801 }
12802
12803 /* ffecom_sym_commit -- Symbol's state being committed to reality
12804
12805 ffesymbol s;
12806 ffecom_sym_commit(s);
12807
12808 Does whatever the backend needs when a symbol is committed after having
12809 been backtrackable for a period of time. */
12810
12811 void
ffecom_sym_commit(ffesymbol s UNUSED)12812 ffecom_sym_commit (ffesymbol s UNUSED)
12813 {
12814 assert (!ffesymbol_retractable ());
12815 }
12816
12817 /* ffecom_sym_end_transition -- Perform end transition on all symbols
12818
12819 ffecom_sym_end_transition();
12820
12821 Does backend-specific stuff and also calls ffest_sym_end_transition
12822 to do the necessary FFE stuff.
12823
12824 Backtracking is never enabled when this fn is called, so don't worry
12825 about it. */
12826
12827 ffesymbol
ffecom_sym_end_transition(ffesymbol s)12828 ffecom_sym_end_transition (ffesymbol s)
12829 {
12830 ffestorag st;
12831
12832 assert (!ffesymbol_retractable ());
12833
12834 s = ffest_sym_end_transition (s);
12835
12836 if ((ffesymbol_kind (s) == FFEINFO_kindBLOCKDATA)
12837 && (ffesymbol_where (s) == FFEINFO_whereGLOBAL))
12838 {
12839 ffecom_list_blockdata_
12840 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
12841 FFEINTRIN_specNONE,
12842 FFEINTRIN_impNONE),
12843 ffecom_list_blockdata_);
12844 }
12845
12846 /* This is where we finally notice that a symbol has partial initialization
12847 and finalize it. */
12848
12849 if (ffesymbol_accretion (s) != NULL)
12850 {
12851 assert (ffesymbol_init (s) == NULL);
12852 ffecom_notify_init_symbol (s);
12853 }
12854 else if (((st = ffesymbol_storage (s)) != NULL)
12855 && ((st = ffestorag_parent (st)) != NULL)
12856 && (ffestorag_accretion (st) != NULL))
12857 {
12858 assert (ffestorag_init (st) == NULL);
12859 ffecom_notify_init_storage (st);
12860 }
12861
12862 if ((ffesymbol_kind (s) == FFEINFO_kindCOMMON)
12863 && (ffesymbol_where (s) == FFEINFO_whereLOCAL)
12864 && (ffesymbol_storage (s) != NULL))
12865 {
12866 ffecom_list_common_
12867 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
12868 FFEINTRIN_specNONE,
12869 FFEINTRIN_impNONE),
12870 ffecom_list_common_);
12871 }
12872
12873 return s;
12874 }
12875
12876 /* ffecom_sym_exec_transition -- Perform exec transition on all symbols
12877
12878 ffecom_sym_exec_transition();
12879
12880 Does backend-specific stuff and also calls ffest_sym_exec_transition
12881 to do the necessary FFE stuff.
12882
12883 See the long-winded description in ffecom_sym_learned for info
12884 on handling the situation where backtracking is inhibited. */
12885
12886 ffesymbol
ffecom_sym_exec_transition(ffesymbol s)12887 ffecom_sym_exec_transition (ffesymbol s)
12888 {
12889 s = ffest_sym_exec_transition (s);
12890
12891 return s;
12892 }
12893
12894 /* ffecom_sym_learned -- Initial or more info gained on symbol after exec
12895
12896 ffesymbol s;
12897 s = ffecom_sym_learned(s);
12898
12899 Called when a new symbol is seen after the exec transition or when more
12900 info (perhaps) is gained for an UNCERTAIN symbol. The symbol state when
12901 it arrives here is that all its latest info is updated already, so its
12902 state may be UNCERTAIN or UNDERSTOOD, it might already have the hook
12903 field filled in if its gone through here or exec_transition first, and
12904 so on.
12905
12906 The backend probably wants to check ffesymbol_retractable() to see if
12907 backtracking is in effect. If so, the FFE's changes to the symbol may
12908 be retracted (undone) or committed (ratified), at which time the
12909 appropriate ffecom_sym_retract or _commit function will be called
12910 for that function.
12911
12912 If the backend has its own backtracking mechanism, great, use it so that
12913 committal is a simple operation. Though it doesn't make much difference,
12914 I suppose: the reason for tentative symbol evolution in the FFE is to
12915 enable error detection in weird incorrect statements early and to disable
12916 incorrect error detection on a correct statement. The backend is not
12917 likely to introduce any information that'll get involved in these
12918 considerations, so it is probably just fine that the implementation
12919 model for this fn and for _exec_transition is to not do anything
12920 (besides the required FFE stuff) if ffesymbol_retractable() returns TRUE
12921 and instead wait until ffecom_sym_commit is called (which it never
12922 will be as long as we're using ambiguity-detecting statement analysis in
12923 the FFE, which we are initially to shake out the code, but don't depend
12924 on this), otherwise go ahead and do whatever is needed.
12925
12926 In essence, then, when this fn and _exec_transition get called while
12927 backtracking is enabled, a general mechanism would be to flag which (or
12928 both) of these were called (and in what order? neat question as to what
12929 might happen that I'm too lame to think through right now) and then when
12930 _commit is called reproduce the original calling sequence, if any, for
12931 the two fns (at which point backtracking will, of course, be disabled). */
12932
12933 ffesymbol
ffecom_sym_learned(ffesymbol s)12934 ffecom_sym_learned (ffesymbol s)
12935 {
12936 ffestorag_exec_layout (s);
12937
12938 return s;
12939 }
12940
12941 /* ffecom_sym_retract -- Symbol's state being retracted from reality
12942
12943 ffesymbol s;
12944 ffecom_sym_retract(s);
12945
12946 Does whatever the backend needs when a symbol is retracted after having
12947 been backtrackable for a period of time. */
12948
12949 void
ffecom_sym_retract(ffesymbol s UNUSED)12950 ffecom_sym_retract (ffesymbol s UNUSED)
12951 {
12952 assert (!ffesymbol_retractable ());
12953
12954 #if 0 /* GCC doesn't commit any backtrackable sins,
12955 so nothing needed here. */
12956 switch (ffesymbol_hook (s).state)
12957 {
12958 case 0: /* nothing happened yet. */
12959 break;
12960
12961 case 1: /* exec transition happened. */
12962 break;
12963
12964 case 2: /* learned happened. */
12965 break;
12966
12967 case 3: /* learned then exec. */
12968 break;
12969
12970 case 4: /* exec then learned. */
12971 break;
12972
12973 default:
12974 assert ("bad hook state" == NULL);
12975 break;
12976 }
12977 #endif
12978 }
12979
12980 /* Create temporary gcc label. */
12981
12982 tree
ffecom_temp_label()12983 ffecom_temp_label ()
12984 {
12985 tree glabel;
12986 static int mynumber = 0;
12987
12988 glabel = build_decl (LABEL_DECL,
12989 ffecom_get_invented_identifier ("__g77_label_%d",
12990 mynumber++),
12991 void_type_node);
12992 DECL_CONTEXT (glabel) = current_function_decl;
12993 DECL_MODE (glabel) = VOIDmode;
12994
12995 return glabel;
12996 }
12997
12998 /* Return an expression that is usable as an arg in a conditional context
12999 (IF, DO WHILE, .NOT., and so on).
13000
13001 Use the one provided for the back end as of >2.6.0. */
13002
13003 tree
ffecom_truth_value(tree expr)13004 ffecom_truth_value (tree expr)
13005 {
13006 return ffe_truthvalue_conversion (expr);
13007 }
13008
13009 /* Return the inversion of a truth value (the inversion of what
13010 ffecom_truth_value builds).
13011
13012 Apparently invert_truthvalue, which is properly in the back end, is
13013 enough for now, so just use it. */
13014
13015 tree
ffecom_truth_value_invert(tree expr)13016 ffecom_truth_value_invert (tree expr)
13017 {
13018 return invert_truthvalue (ffecom_truth_value (expr));
13019 }
13020
13021 /* Return the tree that is the type of the expression, as would be
13022 returned in TREE_TYPE(ffecom_expr(expr)), without otherwise
13023 transforming the expression, generating temporaries, etc. */
13024
13025 tree
ffecom_type_expr(ffebld expr)13026 ffecom_type_expr (ffebld expr)
13027 {
13028 ffeinfoBasictype bt;
13029 ffeinfoKindtype kt;
13030 tree tree_type;
13031
13032 assert (expr != NULL);
13033
13034 bt = ffeinfo_basictype (ffebld_info (expr));
13035 kt = ffeinfo_kindtype (ffebld_info (expr));
13036 tree_type = ffecom_tree_type[bt][kt];
13037
13038 switch (ffebld_op (expr))
13039 {
13040 case FFEBLD_opCONTER:
13041 case FFEBLD_opSYMTER:
13042 case FFEBLD_opARRAYREF:
13043 case FFEBLD_opUPLUS:
13044 case FFEBLD_opPAREN:
13045 case FFEBLD_opUMINUS:
13046 case FFEBLD_opADD:
13047 case FFEBLD_opSUBTRACT:
13048 case FFEBLD_opMULTIPLY:
13049 case FFEBLD_opDIVIDE:
13050 case FFEBLD_opPOWER:
13051 case FFEBLD_opNOT:
13052 case FFEBLD_opFUNCREF:
13053 case FFEBLD_opSUBRREF:
13054 case FFEBLD_opAND:
13055 case FFEBLD_opOR:
13056 case FFEBLD_opXOR:
13057 case FFEBLD_opNEQV:
13058 case FFEBLD_opEQV:
13059 case FFEBLD_opCONVERT:
13060 case FFEBLD_opLT:
13061 case FFEBLD_opLE:
13062 case FFEBLD_opEQ:
13063 case FFEBLD_opNE:
13064 case FFEBLD_opGT:
13065 case FFEBLD_opGE:
13066 case FFEBLD_opPERCENT_LOC:
13067 return tree_type;
13068
13069 case FFEBLD_opACCTER:
13070 case FFEBLD_opARRTER:
13071 case FFEBLD_opITEM:
13072 case FFEBLD_opSTAR:
13073 case FFEBLD_opBOUNDS:
13074 case FFEBLD_opREPEAT:
13075 case FFEBLD_opLABTER:
13076 case FFEBLD_opLABTOK:
13077 case FFEBLD_opIMPDO:
13078 case FFEBLD_opCONCATENATE:
13079 case FFEBLD_opSUBSTR:
13080 default:
13081 assert ("bad op for ffecom_type_expr" == NULL);
13082 /* Fall through. */
13083 case FFEBLD_opANY:
13084 return error_mark_node;
13085 }
13086 }
13087
13088 /* Return PARM_DECL for arg#1 of master fn containing alternate ENTRY points
13089
13090 If the PARM_DECL already exists, return it, else create it. It's an
13091 integer_type_node argument for the master function that implements a
13092 subroutine or function with more than one entrypoint and is bound at
13093 run time with the entrypoint number (0 for SUBROUTINE/FUNCTION, 1 for
13094 first ENTRY statement, and so on). */
13095
13096 tree
ffecom_which_entrypoint_decl()13097 ffecom_which_entrypoint_decl ()
13098 {
13099 assert (ffecom_which_entrypoint_decl_ != NULL_TREE);
13100
13101 return ffecom_which_entrypoint_decl_;
13102 }
13103
13104 /* The following sections consists of private and public functions
13105 that have the same names and perform roughly the same functions
13106 as counterparts in the C front end. Changes in the C front end
13107 might affect how things should be done here. Only functions
13108 needed by the back end should be public here; the rest should
13109 be private (static in the C sense). Functions needed by other
13110 g77 front-end modules should be accessed by them via public
13111 ffecom_* names, which should themselves call private versions
13112 in this section so the private versions are easy to recognize
13113 when upgrading to a new gcc and finding interesting changes
13114 in the front end.
13115
13116 Functions named after rule "foo:" in c-parse.y are named
13117 "bison_rule_foo_" so they are easy to find. */
13118
13119 static void
bison_rule_pushlevel_()13120 bison_rule_pushlevel_ ()
13121 {
13122 emit_line_note (input_filename, lineno);
13123 pushlevel (0);
13124 clear_last_expr ();
13125 expand_start_bindings (0);
13126 }
13127
13128 static tree
bison_rule_compstmt_()13129 bison_rule_compstmt_ ()
13130 {
13131 tree t;
13132 int keep = kept_level_p ();
13133
13134 /* Make the temps go away. */
13135 if (! keep)
13136 current_binding_level->names = NULL_TREE;
13137
13138 emit_line_note (input_filename, lineno);
13139 expand_end_bindings (getdecls (), keep, 0);
13140 t = poplevel (keep, 1, 0);
13141
13142 return t;
13143 }
13144
13145 /* Return a definition for a builtin function named NAME and whose data type
13146 is TYPE. TYPE should be a function type with argument types.
13147 FUNCTION_CODE tells later passes how to compile calls to this function.
13148 See tree.h for its possible values.
13149
13150 If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
13151 the name to be called if we can't opencode the function. If
13152 ATTRS is nonzero, use that for the function's attribute list. */
13153
13154 tree
builtin_function(const char * name,tree type,int function_code,enum built_in_class class,const char * library_name,tree attrs ATTRIBUTE_UNUSED)13155 builtin_function (const char *name, tree type, int function_code,
13156 enum built_in_class class,
13157 const char *library_name,
13158 tree attrs ATTRIBUTE_UNUSED)
13159 {
13160 tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
13161 DECL_EXTERNAL (decl) = 1;
13162 TREE_PUBLIC (decl) = 1;
13163 if (library_name)
13164 SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
13165 make_decl_rtl (decl, NULL);
13166 pushdecl (decl);
13167 DECL_BUILT_IN_CLASS (decl) = class;
13168 DECL_FUNCTION_CODE (decl) = function_code;
13169
13170 return decl;
13171 }
13172
13173 /* Handle when a new declaration NEWDECL
13174 has the same name as an old one OLDDECL
13175 in the same binding contour.
13176 Prints an error message if appropriate.
13177
13178 If safely possible, alter OLDDECL to look like NEWDECL, and return 1.
13179 Otherwise, return 0. */
13180
13181 static int
duplicate_decls(tree newdecl,tree olddecl)13182 duplicate_decls (tree newdecl, tree olddecl)
13183 {
13184 int types_match = 1;
13185 int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
13186 && DECL_INITIAL (newdecl) != 0);
13187 tree oldtype = TREE_TYPE (olddecl);
13188 tree newtype = TREE_TYPE (newdecl);
13189
13190 if (olddecl == newdecl)
13191 return 1;
13192
13193 if (TREE_CODE (newtype) == ERROR_MARK
13194 || TREE_CODE (oldtype) == ERROR_MARK)
13195 types_match = 0;
13196
13197 /* New decl is completely inconsistent with the old one =>
13198 tell caller to replace the old one.
13199 This is always an error except in the case of shadowing a builtin. */
13200 if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
13201 return 0;
13202
13203 /* For real parm decl following a forward decl,
13204 return 1 so old decl will be reused. */
13205 if (types_match && TREE_CODE (newdecl) == PARM_DECL
13206 && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
13207 return 1;
13208
13209 /* The new declaration is the same kind of object as the old one.
13210 The declarations may partially match. Print warnings if they don't
13211 match enough. Ultimately, copy most of the information from the new
13212 decl to the old one, and keep using the old one. */
13213
13214 if (TREE_CODE (olddecl) == FUNCTION_DECL
13215 && DECL_BUILT_IN (olddecl))
13216 {
13217 /* A function declaration for a built-in function. */
13218 if (!TREE_PUBLIC (newdecl))
13219 return 0;
13220 else if (!types_match)
13221 {
13222 /* Accept the return type of the new declaration if same modes. */
13223 tree oldreturntype = TREE_TYPE (TREE_TYPE (olddecl));
13224 tree newreturntype = TREE_TYPE (TREE_TYPE (newdecl));
13225
13226 if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
13227 {
13228 /* Function types may be shared, so we can't just modify
13229 the return type of olddecl's function type. */
13230 tree newtype
13231 = build_function_type (newreturntype,
13232 TYPE_ARG_TYPES (TREE_TYPE (olddecl)));
13233
13234 types_match = 1;
13235 if (types_match)
13236 TREE_TYPE (olddecl) = newtype;
13237 }
13238 }
13239 if (!types_match)
13240 return 0;
13241 }
13242 else if (TREE_CODE (olddecl) == FUNCTION_DECL
13243 && DECL_SOURCE_LINE (olddecl) == 0)
13244 {
13245 /* A function declaration for a predeclared function
13246 that isn't actually built in. */
13247 if (!TREE_PUBLIC (newdecl))
13248 return 0;
13249 else if (!types_match)
13250 {
13251 /* If the types don't match, preserve volatility indication.
13252 Later on, we will discard everything else about the
13253 default declaration. */
13254 TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
13255 }
13256 }
13257
13258 /* Copy all the DECL_... slots specified in the new decl
13259 except for any that we copy here from the old type.
13260
13261 Past this point, we don't change OLDTYPE and NEWTYPE
13262 even if we change the types of NEWDECL and OLDDECL. */
13263
13264 if (types_match)
13265 {
13266 /* Merge the data types specified in the two decls. */
13267 if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
13268 TREE_TYPE (newdecl)
13269 = TREE_TYPE (olddecl)
13270 = TREE_TYPE (newdecl);
13271
13272 /* Lay the type out, unless already done. */
13273 if (oldtype != TREE_TYPE (newdecl))
13274 {
13275 if (TREE_TYPE (newdecl) != error_mark_node)
13276 layout_type (TREE_TYPE (newdecl));
13277 if (TREE_CODE (newdecl) != FUNCTION_DECL
13278 && TREE_CODE (newdecl) != TYPE_DECL
13279 && TREE_CODE (newdecl) != CONST_DECL)
13280 layout_decl (newdecl, 0);
13281 }
13282 else
13283 {
13284 /* Since the type is OLDDECL's, make OLDDECL's size go with. */
13285 DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
13286 DECL_SIZE_UNIT (newdecl) = DECL_SIZE_UNIT (olddecl);
13287 if (TREE_CODE (olddecl) != FUNCTION_DECL)
13288 if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
13289 {
13290 DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
13291 DECL_USER_ALIGN (newdecl) |= DECL_USER_ALIGN (olddecl);
13292 }
13293 }
13294
13295 /* Keep the old rtl since we can safely use it. */
13296 COPY_DECL_RTL (olddecl, newdecl);
13297
13298 /* Merge the type qualifiers. */
13299 if (DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl)
13300 && !TREE_THIS_VOLATILE (newdecl))
13301 TREE_THIS_VOLATILE (olddecl) = 0;
13302 if (TREE_READONLY (newdecl))
13303 TREE_READONLY (olddecl) = 1;
13304 if (TREE_THIS_VOLATILE (newdecl))
13305 {
13306 TREE_THIS_VOLATILE (olddecl) = 1;
13307 if (TREE_CODE (newdecl) == VAR_DECL)
13308 make_var_volatile (newdecl);
13309 }
13310
13311 /* Keep source location of definition rather than declaration.
13312 Likewise, keep decl at outer scope. */
13313 if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
13314 || (DECL_CONTEXT (newdecl) != 0 && DECL_CONTEXT (olddecl) == 0))
13315 {
13316 DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
13317 DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl);
13318
13319 if (DECL_CONTEXT (olddecl) == 0
13320 && TREE_CODE (newdecl) != FUNCTION_DECL)
13321 DECL_CONTEXT (newdecl) = 0;
13322 }
13323
13324 /* Merge the unused-warning information. */
13325 if (DECL_IN_SYSTEM_HEADER (olddecl))
13326 DECL_IN_SYSTEM_HEADER (newdecl) = 1;
13327 else if (DECL_IN_SYSTEM_HEADER (newdecl))
13328 DECL_IN_SYSTEM_HEADER (olddecl) = 1;
13329
13330 /* Merge the initialization information. */
13331 if (DECL_INITIAL (newdecl) == 0)
13332 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
13333
13334 /* Merge the section attribute.
13335 We want to issue an error if the sections conflict but that must be
13336 done later in decl_attributes since we are called before attributes
13337 are assigned. */
13338 if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
13339 DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
13340
13341 if (TREE_CODE (newdecl) == FUNCTION_DECL)
13342 {
13343 DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
13344 DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
13345 }
13346 }
13347 /* If cannot merge, then use the new type and qualifiers,
13348 and don't preserve the old rtl. */
13349 else
13350 {
13351 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
13352 TREE_READONLY (olddecl) = TREE_READONLY (newdecl);
13353 TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl);
13354 TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl);
13355 }
13356
13357 /* Merge the storage class information. */
13358 /* For functions, static overrides non-static. */
13359 if (TREE_CODE (newdecl) == FUNCTION_DECL)
13360 {
13361 TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
13362 /* This is since we don't automatically
13363 copy the attributes of NEWDECL into OLDDECL. */
13364 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
13365 /* If this clears `static', clear it in the identifier too. */
13366 if (! TREE_PUBLIC (olddecl))
13367 TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
13368 }
13369 if (DECL_EXTERNAL (newdecl))
13370 {
13371 TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
13372 DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
13373 /* An extern decl does not override previous storage class. */
13374 TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
13375 }
13376 else
13377 {
13378 TREE_STATIC (olddecl) = TREE_STATIC (newdecl);
13379 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
13380 }
13381
13382 /* If either decl says `inline', this fn is inline,
13383 unless its definition was passed already. */
13384 if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
13385 DECL_INLINE (olddecl) = 1;
13386 DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
13387
13388 /* Get rid of any built-in function if new arg types don't match it
13389 or if we have a function definition. */
13390 if (TREE_CODE (newdecl) == FUNCTION_DECL
13391 && DECL_BUILT_IN (olddecl)
13392 && (!types_match || new_is_definition))
13393 {
13394 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
13395 DECL_BUILT_IN_CLASS (olddecl) = NOT_BUILT_IN;
13396 }
13397
13398 /* If redeclaring a builtin function, and not a definition,
13399 it stays built in.
13400 Also preserve various other info from the definition. */
13401 if (TREE_CODE (newdecl) == FUNCTION_DECL && !new_is_definition)
13402 {
13403 if (DECL_BUILT_IN (olddecl))
13404 {
13405 DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
13406 DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
13407 }
13408
13409 DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
13410 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
13411 DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
13412 DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
13413 }
13414
13415 /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
13416 But preserve olddecl's DECL_UID. */
13417 {
13418 register unsigned olddecl_uid = DECL_UID (olddecl);
13419
13420 memcpy ((char *) olddecl + sizeof (struct tree_common),
13421 (char *) newdecl + sizeof (struct tree_common),
13422 sizeof (struct tree_decl) - sizeof (struct tree_common));
13423 DECL_UID (olddecl) = olddecl_uid;
13424 }
13425
13426 return 1;
13427 }
13428
13429 /* Finish processing of a declaration;
13430 install its initial value.
13431 If the length of an array type is not known before,
13432 it must be determined now, from the initial value, or it is an error. */
13433
13434 static void
finish_decl(tree decl,tree init,bool is_top_level)13435 finish_decl (tree decl, tree init, bool is_top_level)
13436 {
13437 register tree type = TREE_TYPE (decl);
13438 int was_incomplete = (DECL_SIZE (decl) == 0);
13439 bool at_top_level = (current_binding_level == global_binding_level);
13440 bool top_level = is_top_level || at_top_level;
13441
13442 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
13443 level anyway. */
13444 assert (!is_top_level || !at_top_level);
13445
13446 if (TREE_CODE (decl) == PARM_DECL)
13447 assert (init == NULL_TREE);
13448 /* Remember that PARM_DECL doesn't have a DECL_INITIAL field per se -- it
13449 overlaps DECL_ARG_TYPE. */
13450 else if (init == NULL_TREE)
13451 assert (DECL_INITIAL (decl) == NULL_TREE);
13452 else
13453 assert (DECL_INITIAL (decl) == error_mark_node);
13454
13455 if (init != NULL_TREE)
13456 {
13457 if (TREE_CODE (decl) != TYPE_DECL)
13458 DECL_INITIAL (decl) = init;
13459 else
13460 {
13461 /* typedef foo = bar; store the type of bar as the type of foo. */
13462 TREE_TYPE (decl) = TREE_TYPE (init);
13463 DECL_INITIAL (decl) = init = 0;
13464 }
13465 }
13466
13467 /* Deduce size of array from initialization, if not already known */
13468
13469 if (TREE_CODE (type) == ARRAY_TYPE
13470 && TYPE_DOMAIN (type) == 0
13471 && TREE_CODE (decl) != TYPE_DECL)
13472 {
13473 assert (top_level);
13474 assert (was_incomplete);
13475
13476 layout_decl (decl, 0);
13477 }
13478
13479 if (TREE_CODE (decl) == VAR_DECL)
13480 {
13481 if (DECL_SIZE (decl) == NULL_TREE
13482 && TYPE_SIZE (TREE_TYPE (decl)) != NULL_TREE)
13483 layout_decl (decl, 0);
13484
13485 if (DECL_SIZE (decl) == NULL_TREE
13486 && (TREE_STATIC (decl)
13487 ?
13488 /* A static variable with an incomplete type is an error if it is
13489 initialized. Also if it is not file scope. Otherwise, let it
13490 through, but if it is not `extern' then it may cause an error
13491 message later. */
13492 (DECL_INITIAL (decl) != 0 || DECL_CONTEXT (decl) != 0)
13493 :
13494 /* An automatic variable with an incomplete type is an error. */
13495 !DECL_EXTERNAL (decl)))
13496 {
13497 assert ("storage size not known" == NULL);
13498 abort ();
13499 }
13500
13501 if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
13502 && (DECL_SIZE (decl) != 0)
13503 && (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST))
13504 {
13505 assert ("storage size not constant" == NULL);
13506 abort ();
13507 }
13508 }
13509
13510 /* Output the assembler code and/or RTL code for variables and functions,
13511 unless the type is an undefined structure or union. If not, it will get
13512 done when the type is completed. */
13513
13514 if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
13515 {
13516 rest_of_decl_compilation (decl, NULL,
13517 DECL_CONTEXT (decl) == 0,
13518 0);
13519
13520 if (DECL_CONTEXT (decl) != 0)
13521 {
13522 /* Recompute the RTL of a local array now if it used to be an
13523 incomplete type. */
13524 if (was_incomplete
13525 && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
13526 {
13527 /* If we used it already as memory, it must stay in memory. */
13528 TREE_ADDRESSABLE (decl) = TREE_USED (decl);
13529 /* If it's still incomplete now, no init will save it. */
13530 if (DECL_SIZE (decl) == 0)
13531 DECL_INITIAL (decl) = 0;
13532 expand_decl (decl);
13533 }
13534 /* Compute and store the initial value. */
13535 if (TREE_CODE (decl) != FUNCTION_DECL)
13536 expand_decl_init (decl);
13537 }
13538 }
13539 else if (TREE_CODE (decl) == TYPE_DECL)
13540 {
13541 rest_of_decl_compilation (decl, NULL,
13542 DECL_CONTEXT (decl) == 0,
13543 0);
13544 }
13545
13546 /* At the end of a declaration, throw away any variable type sizes of types
13547 defined inside that declaration. There is no use computing them in the
13548 following function definition. */
13549 if (current_binding_level == global_binding_level)
13550 get_pending_sizes ();
13551 }
13552
13553 /* Finish up a function declaration and compile that function
13554 all the way to assembler language output. The free the storage
13555 for the function definition.
13556
13557 This is called after parsing the body of the function definition.
13558
13559 NESTED is nonzero if the function being finished is nested in another. */
13560
13561 static void
finish_function(int nested)13562 finish_function (int nested)
13563 {
13564 register tree fndecl = current_function_decl;
13565
13566 assert (fndecl != NULL_TREE);
13567 if (TREE_CODE (fndecl) != ERROR_MARK)
13568 {
13569 if (nested)
13570 assert (DECL_CONTEXT (fndecl) != NULL_TREE);
13571 else
13572 assert (DECL_CONTEXT (fndecl) == NULL_TREE);
13573 }
13574
13575 /* TREE_READONLY (fndecl) = 1;
13576 This caused &foo to be of type ptr-to-const-function
13577 which then got a warning when stored in a ptr-to-function variable. */
13578
13579 poplevel (1, 0, 1);
13580
13581 if (TREE_CODE (fndecl) != ERROR_MARK)
13582 {
13583 BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
13584
13585 /* Must mark the RESULT_DECL as being in this function. */
13586
13587 DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
13588
13589 /* Obey `register' declarations if `setjmp' is called in this fn. */
13590 /* Generate rtl for function exit. */
13591 expand_function_end (input_filename, lineno, 0);
13592
13593 /* If this is a nested function, protect the local variables in the stack
13594 above us from being collected while we're compiling this function. */
13595 if (nested)
13596 ggc_push_context ();
13597
13598 /* Run the optimizers and output the assembler code for this function. */
13599 rest_of_compilation (fndecl);
13600
13601 /* Undo the GC context switch. */
13602 if (nested)
13603 ggc_pop_context ();
13604 }
13605
13606 if (TREE_CODE (fndecl) != ERROR_MARK
13607 && !nested
13608 && DECL_SAVED_INSNS (fndecl) == 0)
13609 {
13610 /* Stop pointing to the local nodes about to be freed. */
13611 /* But DECL_INITIAL must remain nonzero so we know this was an actual
13612 function definition. */
13613 /* For a nested function, this is done in pop_f_function_context. */
13614 /* If rest_of_compilation set this to 0, leave it 0. */
13615 if (DECL_INITIAL (fndecl) != 0)
13616 DECL_INITIAL (fndecl) = error_mark_node;
13617 DECL_ARGUMENTS (fndecl) = 0;
13618 }
13619
13620 if (!nested)
13621 {
13622 /* Let the error reporting routines know that we're outside a function.
13623 For a nested function, this value is used in pop_c_function_context
13624 and then reset via pop_function_context. */
13625 ffecom_outer_function_decl_ = current_function_decl = NULL;
13626 }
13627 }
13628
13629 /* Plug-in replacement for identifying the name of a decl and, for a
13630 function, what we call it in diagnostics. For now, "program unit"
13631 should suffice, since it's a bit of a hassle to figure out which
13632 of several kinds of things it is. Note that it could conceivably
13633 be a statement function, which probably isn't really a program unit
13634 per se, but if that comes up, it should be easy to check (being a
13635 nested function and all). */
13636
13637 static const char *
ffe_printable_name(tree decl,int v)13638 ffe_printable_name (tree decl, int v)
13639 {
13640 /* Just to keep GCC quiet about the unused variable.
13641 In theory, differing values of V should produce different
13642 output. */
13643 switch (v)
13644 {
13645 default:
13646 if (TREE_CODE (decl) == ERROR_MARK)
13647 return "erroneous code";
13648 return IDENTIFIER_POINTER (DECL_NAME (decl));
13649 }
13650 }
13651
13652 /* g77's function to print out name of current function that caused
13653 an error. */
13654
13655 static void
ffe_print_error_function(diagnostic_context * context,const char * file)13656 ffe_print_error_function (diagnostic_context *context __attribute__((unused)),
13657 const char *file)
13658 {
13659 static ffeglobal last_g = NULL;
13660 static ffesymbol last_s = NULL;
13661 ffeglobal g;
13662 ffesymbol s;
13663 const char *kind;
13664
13665 if ((ffecom_primary_entry_ == NULL)
13666 || (ffesymbol_global (ffecom_primary_entry_) == NULL))
13667 {
13668 g = NULL;
13669 s = NULL;
13670 kind = NULL;
13671 }
13672 else
13673 {
13674 g = ffesymbol_global (ffecom_primary_entry_);
13675 if (ffecom_nested_entry_ == NULL)
13676 {
13677 s = ffecom_primary_entry_;
13678 kind = _(ffeinfo_kind_message (ffesymbol_kind (s)));
13679 }
13680 else
13681 {
13682 s = ffecom_nested_entry_;
13683 kind = _("In statement function");
13684 }
13685 }
13686
13687 if ((last_g != g) || (last_s != s))
13688 {
13689 if (file)
13690 fprintf (stderr, "%s: ", file);
13691
13692 if (s == NULL)
13693 fprintf (stderr, _("Outside of any program unit:\n"));
13694 else
13695 {
13696 const char *name = ffesymbol_text (s);
13697
13698 fprintf (stderr, "%s `%s':\n", kind, name);
13699 }
13700
13701 last_g = g;
13702 last_s = s;
13703 }
13704 }
13705
13706 /* Similar to `lookup_name' but look only at current binding level. */
13707
13708 static tree
lookup_name_current_level(tree name)13709 lookup_name_current_level (tree name)
13710 {
13711 register tree t;
13712
13713 if (current_binding_level == global_binding_level)
13714 return IDENTIFIER_GLOBAL_VALUE (name);
13715
13716 if (IDENTIFIER_LOCAL_VALUE (name) == 0)
13717 return 0;
13718
13719 for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
13720 if (DECL_NAME (t) == name)
13721 break;
13722
13723 return t;
13724 }
13725
13726 /* Create a new `struct f_binding_level'. */
13727
13728 static struct f_binding_level *
make_binding_level()13729 make_binding_level ()
13730 {
13731 /* NOSTRICT */
13732 return ggc_alloc (sizeof (struct f_binding_level));
13733 }
13734
13735 /* Save and restore the variables in this file and elsewhere
13736 that keep track of the progress of compilation of the current function.
13737 Used for nested functions. */
13738
13739 struct f_function
13740 {
13741 struct f_function *next;
13742 tree named_labels;
13743 tree shadowed_labels;
13744 struct f_binding_level *binding_level;
13745 };
13746
13747 struct f_function *f_function_chain;
13748
13749 /* Restore the variables used during compilation of a C function. */
13750
13751 static void
pop_f_function_context()13752 pop_f_function_context ()
13753 {
13754 struct f_function *p = f_function_chain;
13755 tree link;
13756
13757 /* Bring back all the labels that were shadowed. */
13758 for (link = shadowed_labels; link; link = TREE_CHAIN (link))
13759 if (DECL_NAME (TREE_VALUE (link)) != 0)
13760 IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)))
13761 = TREE_VALUE (link);
13762
13763 if (current_function_decl != error_mark_node
13764 && DECL_SAVED_INSNS (current_function_decl) == 0)
13765 {
13766 /* Stop pointing to the local nodes about to be freed. */
13767 /* But DECL_INITIAL must remain nonzero so we know this was an actual
13768 function definition. */
13769 DECL_INITIAL (current_function_decl) = error_mark_node;
13770 DECL_ARGUMENTS (current_function_decl) = 0;
13771 }
13772
13773 pop_function_context ();
13774
13775 f_function_chain = p->next;
13776
13777 named_labels = p->named_labels;
13778 shadowed_labels = p->shadowed_labels;
13779 current_binding_level = p->binding_level;
13780
13781 free (p);
13782 }
13783
13784 /* Save and reinitialize the variables
13785 used during compilation of a C function. */
13786
13787 static void
push_f_function_context()13788 push_f_function_context ()
13789 {
13790 struct f_function *p
13791 = (struct f_function *) xmalloc (sizeof (struct f_function));
13792
13793 push_function_context ();
13794
13795 p->next = f_function_chain;
13796 f_function_chain = p;
13797
13798 p->named_labels = named_labels;
13799 p->shadowed_labels = shadowed_labels;
13800 p->binding_level = current_binding_level;
13801 }
13802
13803 static void
push_parm_decl(tree parm)13804 push_parm_decl (tree parm)
13805 {
13806 int old_immediate_size_expand = immediate_size_expand;
13807
13808 /* Don't try computing parm sizes now -- wait till fn is called. */
13809
13810 immediate_size_expand = 0;
13811
13812 /* Fill in arg stuff. */
13813
13814 DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
13815 DECL_ARG_TYPE_AS_WRITTEN (parm) = TREE_TYPE (parm);
13816 TREE_READONLY (parm) = 1; /* All implementation args are read-only. */
13817
13818 parm = pushdecl (parm);
13819
13820 immediate_size_expand = old_immediate_size_expand;
13821
13822 finish_decl (parm, NULL_TREE, FALSE);
13823 }
13824
13825 /* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, if appropriate. */
13826
13827 static tree
pushdecl_top_level(x)13828 pushdecl_top_level (x)
13829 tree x;
13830 {
13831 register tree t;
13832 register struct f_binding_level *b = current_binding_level;
13833 register tree f = current_function_decl;
13834
13835 current_binding_level = global_binding_level;
13836 current_function_decl = NULL_TREE;
13837 t = pushdecl (x);
13838 current_binding_level = b;
13839 current_function_decl = f;
13840 return t;
13841 }
13842
13843 /* Store the list of declarations of the current level.
13844 This is done for the parameter declarations of a function being defined,
13845 after they are modified in the light of any missing parameters. */
13846
13847 static tree
storedecls(decls)13848 storedecls (decls)
13849 tree decls;
13850 {
13851 return current_binding_level->names = decls;
13852 }
13853
13854 /* Store the parameter declarations into the current function declaration.
13855 This is called after parsing the parameter declarations, before
13856 digesting the body of the function.
13857
13858 For an old-style definition, modify the function's type
13859 to specify at least the number of arguments. */
13860
13861 static void
store_parm_decls(int is_main_program UNUSED)13862 store_parm_decls (int is_main_program UNUSED)
13863 {
13864 register tree fndecl = current_function_decl;
13865
13866 if (fndecl == error_mark_node)
13867 return;
13868
13869 /* This is a chain of PARM_DECLs from old-style parm declarations. */
13870 DECL_ARGUMENTS (fndecl) = storedecls (nreverse (getdecls ()));
13871
13872 /* Initialize the RTL code for the function. */
13873
13874 init_function_start (fndecl, input_filename, lineno);
13875
13876 /* Set up parameters and prepare for return, for the function. */
13877
13878 expand_function_start (fndecl, 0);
13879 }
13880
13881 static tree
start_decl(tree decl,bool is_top_level)13882 start_decl (tree decl, bool is_top_level)
13883 {
13884 register tree tem;
13885 bool at_top_level = (current_binding_level == global_binding_level);
13886 bool top_level = is_top_level || at_top_level;
13887
13888 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
13889 level anyway. */
13890 assert (!is_top_level || !at_top_level);
13891
13892 if (DECL_INITIAL (decl) != NULL_TREE)
13893 {
13894 assert (DECL_INITIAL (decl) == error_mark_node);
13895 assert (!DECL_EXTERNAL (decl));
13896 }
13897 else if (top_level)
13898 assert ((TREE_STATIC (decl) == 1) || DECL_EXTERNAL (decl) == 1);
13899
13900 /* For Fortran, we by default put things in .common when possible. */
13901 DECL_COMMON (decl) = 1;
13902
13903 /* Add this decl to the current binding level. TEM may equal DECL or it may
13904 be a previous decl of the same name. */
13905 if (is_top_level)
13906 tem = pushdecl_top_level (decl);
13907 else
13908 tem = pushdecl (decl);
13909
13910 /* For a local variable, define the RTL now. */
13911 if (!top_level
13912 /* But not if this is a duplicate decl and we preserved the rtl from the
13913 previous one (which may or may not happen). */
13914 && !DECL_RTL_SET_P (tem))
13915 {
13916 if (TYPE_SIZE (TREE_TYPE (tem)) != 0)
13917 expand_decl (tem);
13918 else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
13919 && DECL_INITIAL (tem) != 0)
13920 expand_decl (tem);
13921 }
13922
13923 return tem;
13924 }
13925
13926 /* Create the FUNCTION_DECL for a function definition.
13927 DECLSPECS and DECLARATOR are the parts of the declaration;
13928 they describe the function's name and the type it returns,
13929 but twisted together in a fashion that parallels the syntax of C.
13930
13931 This function creates a binding context for the function body
13932 as well as setting up the FUNCTION_DECL in current_function_decl.
13933
13934 Returns 1 on success. If the DECLARATOR is not suitable for a function
13935 (it defines a datum instead), we return 0, which tells
13936 ffe_parse_file to report a parse error.
13937
13938 NESTED is nonzero for a function nested within another function. */
13939
13940 static void
start_function(tree name,tree type,int nested,int public)13941 start_function (tree name, tree type, int nested, int public)
13942 {
13943 tree decl1;
13944 tree restype;
13945 int old_immediate_size_expand = immediate_size_expand;
13946
13947 named_labels = 0;
13948 shadowed_labels = 0;
13949
13950 /* Don't expand any sizes in the return type of the function. */
13951 immediate_size_expand = 0;
13952
13953 if (nested)
13954 {
13955 assert (!public);
13956 assert (current_function_decl != NULL_TREE);
13957 assert (DECL_CONTEXT (current_function_decl) == NULL_TREE);
13958 }
13959 else
13960 {
13961 assert (current_function_decl == NULL_TREE);
13962 }
13963
13964 if (TREE_CODE (type) == ERROR_MARK)
13965 decl1 = current_function_decl = error_mark_node;
13966 else
13967 {
13968 decl1 = build_decl (FUNCTION_DECL,
13969 name,
13970 type);
13971 TREE_PUBLIC (decl1) = public ? 1 : 0;
13972 if (nested)
13973 DECL_INLINE (decl1) = 1;
13974 TREE_STATIC (decl1) = 1;
13975 DECL_EXTERNAL (decl1) = 0;
13976
13977 announce_function (decl1);
13978
13979 /* Make the init_value nonzero so pushdecl knows this is not tentative.
13980 error_mark_node is replaced below (in poplevel) with the BLOCK. */
13981 DECL_INITIAL (decl1) = error_mark_node;
13982
13983 /* Record the decl so that the function name is defined. If we already have
13984 a decl for this name, and it is a FUNCTION_DECL, use the old decl. */
13985
13986 current_function_decl = pushdecl (decl1);
13987 }
13988
13989 if (!nested)
13990 ffecom_outer_function_decl_ = current_function_decl;
13991
13992 pushlevel (0);
13993 current_binding_level->prep_state = 2;
13994
13995 if (TREE_CODE (current_function_decl) != ERROR_MARK)
13996 {
13997 make_decl_rtl (current_function_decl, NULL);
13998
13999 restype = TREE_TYPE (TREE_TYPE (current_function_decl));
14000 DECL_RESULT (current_function_decl)
14001 = build_decl (RESULT_DECL, NULL_TREE, restype);
14002 }
14003
14004 if (!nested && (TREE_CODE (current_function_decl) != ERROR_MARK))
14005 TREE_ADDRESSABLE (current_function_decl) = 1;
14006
14007 immediate_size_expand = old_immediate_size_expand;
14008 }
14009
14010 /* Here are the public functions the GNU back end needs. */
14011
14012 tree
convert(type,expr)14013 convert (type, expr)
14014 tree type, expr;
14015 {
14016 register tree e = expr;
14017 register enum tree_code code = TREE_CODE (type);
14018
14019 if (type == TREE_TYPE (e)
14020 || TREE_CODE (e) == ERROR_MARK)
14021 return e;
14022 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
14023 return fold (build1 (NOP_EXPR, type, e));
14024 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
14025 || code == ERROR_MARK)
14026 return error_mark_node;
14027 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
14028 {
14029 assert ("void value not ignored as it ought to be" == NULL);
14030 return error_mark_node;
14031 }
14032 if (code == VOID_TYPE)
14033 return build1 (CONVERT_EXPR, type, e);
14034 if ((code != RECORD_TYPE)
14035 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
14036 e = ffecom_1 (REALPART_EXPR, TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e))),
14037 e);
14038 if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
14039 return fold (convert_to_integer (type, e));
14040 if (code == POINTER_TYPE)
14041 return fold (convert_to_pointer (type, e));
14042 if (code == REAL_TYPE)
14043 return fold (convert_to_real (type, e));
14044 if (code == COMPLEX_TYPE)
14045 return fold (convert_to_complex (type, e));
14046 if (code == RECORD_TYPE)
14047 return fold (ffecom_convert_to_complex_ (type, e));
14048
14049 assert ("conversion to non-scalar type requested" == NULL);
14050 return error_mark_node;
14051 }
14052
14053 /* Return the list of declarations of the current level.
14054 Note that this list is in reverse order unless/until
14055 you nreverse it; and when you do nreverse it, you must
14056 store the result back using `storedecls' or you will lose. */
14057
14058 tree
getdecls()14059 getdecls ()
14060 {
14061 return current_binding_level->names;
14062 }
14063
14064 /* Nonzero if we are currently in the global binding level. */
14065
14066 int
global_bindings_p()14067 global_bindings_p ()
14068 {
14069 return current_binding_level == global_binding_level;
14070 }
14071
14072 static void
ffecom_init_decl_processing()14073 ffecom_init_decl_processing ()
14074 {
14075 malloc_init ();
14076
14077 ffe_init_0 ();
14078 }
14079
14080 /* Delete the node BLOCK from the current binding level.
14081 This is used for the block inside a stmt expr ({...})
14082 so that the block can be reinserted where appropriate. */
14083
14084 static void
delete_block(block)14085 delete_block (block)
14086 tree block;
14087 {
14088 tree t;
14089 if (current_binding_level->blocks == block)
14090 current_binding_level->blocks = TREE_CHAIN (block);
14091 for (t = current_binding_level->blocks; t;)
14092 {
14093 if (TREE_CHAIN (t) == block)
14094 TREE_CHAIN (t) = TREE_CHAIN (block);
14095 else
14096 t = TREE_CHAIN (t);
14097 }
14098 TREE_CHAIN (block) = NULL;
14099 /* Clear TREE_USED which is always set by poplevel.
14100 The flag is set again if insert_block is called. */
14101 TREE_USED (block) = 0;
14102 }
14103
14104 void
insert_block(block)14105 insert_block (block)
14106 tree block;
14107 {
14108 TREE_USED (block) = 1;
14109 current_binding_level->blocks
14110 = chainon (current_binding_level->blocks, block);
14111 }
14112
14113 /* Each front end provides its own. */
14114 static const char *ffe_init PARAMS ((const char *));
14115 static void ffe_finish PARAMS ((void));
14116 static void ffe_init_options PARAMS ((void));
14117 static void ffe_print_identifier PARAMS ((FILE *, tree, int));
14118
14119 struct language_function GTY(())
14120 {
14121 int unused;
14122 };
14123
14124 #undef LANG_HOOKS_NAME
14125 #define LANG_HOOKS_NAME "GNU F77"
14126 #undef LANG_HOOKS_INIT
14127 #define LANG_HOOKS_INIT ffe_init
14128 #undef LANG_HOOKS_FINISH
14129 #define LANG_HOOKS_FINISH ffe_finish
14130 #undef LANG_HOOKS_INIT_OPTIONS
14131 #define LANG_HOOKS_INIT_OPTIONS ffe_init_options
14132 #undef LANG_HOOKS_DECODE_OPTION
14133 #define LANG_HOOKS_DECODE_OPTION ffe_decode_option
14134 #undef LANG_HOOKS_PARSE_FILE
14135 #define LANG_HOOKS_PARSE_FILE ffe_parse_file
14136 #undef LANG_HOOKS_MARK_ADDRESSABLE
14137 #define LANG_HOOKS_MARK_ADDRESSABLE ffe_mark_addressable
14138 #undef LANG_HOOKS_PRINT_IDENTIFIER
14139 #define LANG_HOOKS_PRINT_IDENTIFIER ffe_print_identifier
14140 #undef LANG_HOOKS_DECL_PRINTABLE_NAME
14141 #define LANG_HOOKS_DECL_PRINTABLE_NAME ffe_printable_name
14142 #undef LANG_HOOKS_PRINT_ERROR_FUNCTION
14143 #define LANG_HOOKS_PRINT_ERROR_FUNCTION ffe_print_error_function
14144 #undef LANG_HOOKS_TRUTHVALUE_CONVERSION
14145 #define LANG_HOOKS_TRUTHVALUE_CONVERSION ffe_truthvalue_conversion
14146
14147 #undef LANG_HOOKS_TYPE_FOR_MODE
14148 #define LANG_HOOKS_TYPE_FOR_MODE ffe_type_for_mode
14149 #undef LANG_HOOKS_TYPE_FOR_SIZE
14150 #define LANG_HOOKS_TYPE_FOR_SIZE ffe_type_for_size
14151 #undef LANG_HOOKS_SIGNED_TYPE
14152 #define LANG_HOOKS_SIGNED_TYPE ffe_signed_type
14153 #undef LANG_HOOKS_UNSIGNED_TYPE
14154 #define LANG_HOOKS_UNSIGNED_TYPE ffe_unsigned_type
14155 #undef LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE
14156 #define LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE ffe_signed_or_unsigned_type
14157
14158 /* We do not wish to use alias-set based aliasing at all. Used in the
14159 extreme (every object with its own set, with equivalences recorded) it
14160 might be helpful, but there are problems when it comes to inlining. We
14161 get on ok with flag_argument_noalias, and alias-set aliasing does
14162 currently limit how stack slots can be reused, which is a lose. */
14163 #undef LANG_HOOKS_GET_ALIAS_SET
14164 #define LANG_HOOKS_GET_ALIAS_SET hook_get_alias_set_0
14165
14166 const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
14167
14168 /* Table indexed by tree code giving a string containing a character
14169 classifying the tree code. Possibilities are
14170 t, d, s, c, r, <, 1, 2 and e. See tree.def for details. */
14171
14172 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
14173
14174 const char tree_code_type[] = {
14175 #include "tree.def"
14176 };
14177 #undef DEFTREECODE
14178
14179 /* Table indexed by tree code giving number of expression
14180 operands beyond the fixed part of the node structure.
14181 Not used for types or decls. */
14182
14183 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
14184
14185 const unsigned char tree_code_length[] = {
14186 #include "tree.def"
14187 };
14188 #undef DEFTREECODE
14189
14190 /* Names of tree components.
14191 Used for printing out the tree and error messages. */
14192 #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
14193
14194 const char *const tree_code_name[] = {
14195 #include "tree.def"
14196 };
14197 #undef DEFTREECODE
14198
14199 static const char *
ffe_init(filename)14200 ffe_init (filename)
14201 const char *filename;
14202 {
14203 /* Open input file. */
14204 if (filename == 0 || !strcmp (filename, "-"))
14205 {
14206 finput = stdin;
14207 filename = "stdin";
14208 }
14209 else
14210 finput = fopen (filename, "r");
14211 if (finput == 0)
14212 fatal_io_error ("can't open %s", filename);
14213
14214 #ifdef IO_BUFFER_SIZE
14215 setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);
14216 #endif
14217
14218 ffecom_init_decl_processing ();
14219
14220 /* If the file is output from cpp, it should contain a first line
14221 `# 1 "real-filename"', and the current design of gcc (toplev.c
14222 in particular and the way it sets up information relied on by
14223 INCLUDE) requires that we read this now, and store the
14224 "real-filename" info in master_input_filename. Ask the lexer
14225 to try doing this. */
14226 ffelex_hash_kludge (finput);
14227
14228 /* FIXME: The ffelex_hash_kludge code needs to be cleaned up to
14229 return the new file name. */
14230 if (main_input_filename)
14231 filename = main_input_filename;
14232
14233 return filename;
14234 }
14235
14236 static void
ffe_finish()14237 ffe_finish ()
14238 {
14239 ffe_terminate_0 ();
14240
14241 if (ffe_is_ffedebug ())
14242 malloc_pool_display (malloc_pool_image ());
14243
14244 fclose (finput);
14245 }
14246
14247 static void
ffe_init_options()14248 ffe_init_options ()
14249 {
14250 /* Set default options for Fortran. */
14251 flag_move_all_movables = 1;
14252 flag_reduce_all_givs = 1;
14253 flag_argument_noalias = 2;
14254 flag_merge_constants = 2;
14255 flag_errno_math = 0;
14256 flag_complex_divide_method = 1;
14257 }
14258
14259 static bool
ffe_mark_addressable(exp)14260 ffe_mark_addressable (exp)
14261 tree exp;
14262 {
14263 register tree x = exp;
14264 while (1)
14265 switch (TREE_CODE (x))
14266 {
14267 case ADDR_EXPR:
14268 case COMPONENT_REF:
14269 case ARRAY_REF:
14270 x = TREE_OPERAND (x, 0);
14271 break;
14272
14273 case CONSTRUCTOR:
14274 TREE_ADDRESSABLE (x) = 1;
14275 return true;
14276
14277 case VAR_DECL:
14278 case CONST_DECL:
14279 case PARM_DECL:
14280 case RESULT_DECL:
14281 if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)
14282 && DECL_NONLOCAL (x))
14283 {
14284 if (TREE_PUBLIC (x))
14285 {
14286 assert ("address of global register var requested" == NULL);
14287 return false;
14288 }
14289 assert ("address of register variable requested" == NULL);
14290 }
14291 else if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x))
14292 {
14293 if (TREE_PUBLIC (x))
14294 {
14295 assert ("address of global register var requested" == NULL);
14296 return false;
14297 }
14298 assert ("address of register var requested" == NULL);
14299 }
14300 put_var_into_stack (x, /*rescan=*/true);
14301
14302 /* drops in */
14303 case FUNCTION_DECL:
14304 TREE_ADDRESSABLE (x) = 1;
14305 #if 0 /* poplevel deals with this now. */
14306 if (DECL_CONTEXT (x) == 0)
14307 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
14308 #endif
14309
14310 default:
14311 return true;
14312 }
14313 }
14314
14315 /* Exit a binding level.
14316 Pop the level off, and restore the state of the identifier-decl mappings
14317 that were in effect when this level was entered.
14318
14319 If KEEP is nonzero, this level had explicit declarations, so
14320 and create a "block" (a BLOCK node) for the level
14321 to record its declarations and subblocks for symbol table output.
14322
14323 If FUNCTIONBODY is nonzero, this level is the body of a function,
14324 so create a block as if KEEP were set and also clear out all
14325 label names.
14326
14327 If REVERSE is nonzero, reverse the order of decls before putting
14328 them into the BLOCK. */
14329
14330 tree
poplevel(keep,reverse,functionbody)14331 poplevel (keep, reverse, functionbody)
14332 int keep;
14333 int reverse;
14334 int functionbody;
14335 {
14336 register tree link;
14337 /* The chain of decls was accumulated in reverse order.
14338 Put it into forward order, just for cleanliness. */
14339 tree decls;
14340 tree subblocks = current_binding_level->blocks;
14341 tree block = 0;
14342 tree decl;
14343 int block_previously_created;
14344
14345 /* Get the decls in the order they were written.
14346 Usually current_binding_level->names is in reverse order.
14347 But parameter decls were previously put in forward order. */
14348
14349 if (reverse)
14350 current_binding_level->names
14351 = decls = nreverse (current_binding_level->names);
14352 else
14353 decls = current_binding_level->names;
14354
14355 /* Output any nested inline functions within this block
14356 if they weren't already output. */
14357
14358 for (decl = decls; decl; decl = TREE_CHAIN (decl))
14359 if (TREE_CODE (decl) == FUNCTION_DECL
14360 && ! TREE_ASM_WRITTEN (decl)
14361 && DECL_INITIAL (decl) != 0
14362 && TREE_ADDRESSABLE (decl))
14363 {
14364 /* If this decl was copied from a file-scope decl
14365 on account of a block-scope extern decl,
14366 propagate TREE_ADDRESSABLE to the file-scope decl.
14367
14368 DECL_ABSTRACT_ORIGIN can be set to itself if warn_return_type is
14369 true, since then the decl goes through save_for_inline_copying. */
14370 if (DECL_ABSTRACT_ORIGIN (decl) != 0
14371 && DECL_ABSTRACT_ORIGIN (decl) != decl)
14372 TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
14373 else if (DECL_SAVED_INSNS (decl) != 0)
14374 {
14375 push_function_context ();
14376 output_inline_function (decl);
14377 pop_function_context ();
14378 }
14379 }
14380
14381 /* If there were any declarations or structure tags in that level,
14382 or if this level is a function body,
14383 create a BLOCK to record them for the life of this function. */
14384
14385 block = 0;
14386 block_previously_created = (current_binding_level->this_block != 0);
14387 if (block_previously_created)
14388 block = current_binding_level->this_block;
14389 else if (keep || functionbody)
14390 block = make_node (BLOCK);
14391 if (block != 0)
14392 {
14393 BLOCK_VARS (block) = decls;
14394 BLOCK_SUBBLOCKS (block) = subblocks;
14395 }
14396
14397 /* In each subblock, record that this is its superior. */
14398
14399 for (link = subblocks; link; link = TREE_CHAIN (link))
14400 BLOCK_SUPERCONTEXT (link) = block;
14401
14402 /* Clear out the meanings of the local variables of this level. */
14403
14404 for (link = decls; link; link = TREE_CHAIN (link))
14405 {
14406 if (DECL_NAME (link) != 0)
14407 {
14408 /* If the ident. was used or addressed via a local extern decl,
14409 don't forget that fact. */
14410 if (DECL_EXTERNAL (link))
14411 {
14412 if (TREE_USED (link))
14413 TREE_USED (DECL_NAME (link)) = 1;
14414 if (TREE_ADDRESSABLE (link))
14415 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
14416 }
14417 IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0;
14418 }
14419 }
14420
14421 /* If the level being exited is the top level of a function,
14422 check over all the labels, and clear out the current
14423 (function local) meanings of their names. */
14424
14425 if (functionbody)
14426 {
14427 /* If this is the top level block of a function,
14428 the vars are the function's parameters.
14429 Don't leave them in the BLOCK because they are
14430 found in the FUNCTION_DECL instead. */
14431
14432 BLOCK_VARS (block) = 0;
14433 }
14434
14435 /* Pop the current level, and free the structure for reuse. */
14436
14437 {
14438 register struct f_binding_level *level = current_binding_level;
14439 current_binding_level = current_binding_level->level_chain;
14440
14441 level->level_chain = free_binding_level;
14442 free_binding_level = level;
14443 }
14444
14445 /* Dispose of the block that we just made inside some higher level. */
14446 if (functionbody
14447 && current_function_decl != error_mark_node)
14448 DECL_INITIAL (current_function_decl) = block;
14449 else if (block)
14450 {
14451 if (!block_previously_created)
14452 current_binding_level->blocks
14453 = chainon (current_binding_level->blocks, block);
14454 }
14455 /* If we did not make a block for the level just exited,
14456 any blocks made for inner levels
14457 (since they cannot be recorded as subblocks in that level)
14458 must be carried forward so they will later become subblocks
14459 of something else. */
14460 else if (subblocks)
14461 current_binding_level->blocks
14462 = chainon (current_binding_level->blocks, subblocks);
14463
14464 if (block)
14465 TREE_USED (block) = 1;
14466 return block;
14467 }
14468
14469 static void
ffe_print_identifier(file,node,indent)14470 ffe_print_identifier (file, node, indent)
14471 FILE *file;
14472 tree node;
14473 int indent;
14474 {
14475 print_node (file, "global", IDENTIFIER_GLOBAL_VALUE (node), indent + 4);
14476 print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4);
14477 }
14478
14479 /* Record a decl-node X as belonging to the current lexical scope.
14480 Check for errors (such as an incompatible declaration for the same
14481 name already seen in the same scope).
14482
14483 Returns either X or an old decl for the same name.
14484 If an old decl is returned, it may have been smashed
14485 to agree with what X says. */
14486
14487 tree
pushdecl(x)14488 pushdecl (x)
14489 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
kept_level_p()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
pushlevel(tag_transparent)14622 pushlevel (tag_transparent)
14623 int tag_transparent;
14624 {
14625 register struct f_binding_level *newlevel = NULL_BINDING_LEVEL;
14626
14627 assert (! tag_transparent);
14628
14629 if (current_binding_level == global_binding_level)
14630 {
14631 named_labels = 0;
14632 }
14633
14634 /* Reuse or create a struct for this binding level. */
14635
14636 if (free_binding_level)
14637 {
14638 newlevel = free_binding_level;
14639 free_binding_level = free_binding_level->level_chain;
14640 }
14641 else
14642 {
14643 newlevel = make_binding_level ();
14644 }
14645
14646 /* Add this level to the front of the chain (stack) of levels that
14647 are active. */
14648
14649 *newlevel = clear_binding_level;
14650 newlevel->level_chain = current_binding_level;
14651 current_binding_level = newlevel;
14652 }
14653
14654 /* Set the BLOCK node for the innermost scope
14655 (the one we are currently in). */
14656
14657 void
set_block(block)14658 set_block (block)
14659 register tree block;
14660 {
14661 current_binding_level->this_block = block;
14662 current_binding_level->names = chainon (current_binding_level->names,
14663 BLOCK_VARS (block));
14664 current_binding_level->blocks = chainon (current_binding_level->blocks,
14665 BLOCK_SUBBLOCKS (block));
14666 }
14667
14668 static tree
ffe_signed_or_unsigned_type(unsignedp,type)14669 ffe_signed_or_unsigned_type (unsignedp, type)
14670 int unsignedp;
14671 tree type;
14672 {
14673 tree type2;
14674
14675 if (! INTEGRAL_TYPE_P (type))
14676 return type;
14677 if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
14678 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
14679 if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
14680 return unsignedp ? unsigned_type_node : integer_type_node;
14681 if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node))
14682 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
14683 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node))
14684 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
14685 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node))
14686 return (unsignedp ? long_long_unsigned_type_node
14687 : long_long_integer_type_node);
14688
14689 type2 = ffe_type_for_size (TYPE_PRECISION (type), unsignedp);
14690 if (type2 == NULL_TREE)
14691 return type;
14692
14693 return type2;
14694 }
14695
14696 static tree
ffe_signed_type(type)14697 ffe_signed_type (type)
14698 tree type;
14699 {
14700 tree type1 = TYPE_MAIN_VARIANT (type);
14701 ffeinfoKindtype kt;
14702 tree type2;
14703
14704 if (type1 == unsigned_char_type_node || type1 == char_type_node)
14705 return signed_char_type_node;
14706 if (type1 == unsigned_type_node)
14707 return integer_type_node;
14708 if (type1 == short_unsigned_type_node)
14709 return short_integer_type_node;
14710 if (type1 == long_unsigned_type_node)
14711 return long_integer_type_node;
14712 if (type1 == long_long_unsigned_type_node)
14713 return long_long_integer_type_node;
14714 #if 0 /* gcc/c-* files only */
14715 if (type1 == unsigned_intDI_type_node)
14716 return intDI_type_node;
14717 if (type1 == unsigned_intSI_type_node)
14718 return intSI_type_node;
14719 if (type1 == unsigned_intHI_type_node)
14720 return intHI_type_node;
14721 if (type1 == unsigned_intQI_type_node)
14722 return intQI_type_node;
14723 #endif
14724
14725 type2 = ffe_type_for_size (TYPE_PRECISION (type1), 0);
14726 if (type2 != NULL_TREE)
14727 return type2;
14728
14729 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
14730 {
14731 type2 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
14732
14733 if (type1 == type2)
14734 return ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
14735 }
14736
14737 return type;
14738 }
14739
14740 /* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
14741 or validate its data type for an `if' or `while' statement or ?..: exp.
14742
14743 This preparation consists of taking the ordinary
14744 representation of an expression expr and producing a valid tree
14745 boolean expression describing whether expr is nonzero. We could
14746 simply always do build_binary_op (NE_EXPR, expr, integer_zero_node, 1),
14747 but we optimize comparisons, &&, ||, and !.
14748
14749 The resulting type should always be `integer_type_node'. */
14750
14751 static tree
ffe_truthvalue_conversion(expr)14752 ffe_truthvalue_conversion (expr)
14753 tree expr;
14754 {
14755 if (TREE_CODE (expr) == ERROR_MARK)
14756 return expr;
14757
14758 #if 0 /* This appears to be wrong for C++. */
14759 /* These really should return error_mark_node after 2.4 is stable.
14760 But not all callers handle ERROR_MARK properly. */
14761 switch (TREE_CODE (TREE_TYPE (expr)))
14762 {
14763 case RECORD_TYPE:
14764 error ("struct type value used where scalar is required");
14765 return integer_zero_node;
14766
14767 case UNION_TYPE:
14768 error ("union type value used where scalar is required");
14769 return integer_zero_node;
14770
14771 case ARRAY_TYPE:
14772 error ("array type value used where scalar is required");
14773 return integer_zero_node;
14774
14775 default:
14776 break;
14777 }
14778 #endif /* 0 */
14779
14780 switch (TREE_CODE (expr))
14781 {
14782 /* It is simpler and generates better code to have only TRUTH_*_EXPR
14783 or comparison expressions as truth values at this level. */
14784 #if 0
14785 case COMPONENT_REF:
14786 /* A one-bit unsigned bit-field is already acceptable. */
14787 if (1 == TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (expr, 1)))
14788 && TREE_UNSIGNED (TREE_OPERAND (expr, 1)))
14789 return expr;
14790 break;
14791 #endif
14792
14793 case EQ_EXPR:
14794 /* It is simpler and generates better code to have only TRUTH_*_EXPR
14795 or comparison expressions as truth values at this level. */
14796 #if 0
14797 if (integer_zerop (TREE_OPERAND (expr, 1)))
14798 return build_unary_op (TRUTH_NOT_EXPR, TREE_OPERAND (expr, 0), 0);
14799 #endif
14800 case NE_EXPR: case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
14801 case TRUTH_ANDIF_EXPR:
14802 case TRUTH_ORIF_EXPR:
14803 case TRUTH_AND_EXPR:
14804 case TRUTH_OR_EXPR:
14805 case TRUTH_XOR_EXPR:
14806 TREE_TYPE (expr) = integer_type_node;
14807 return expr;
14808
14809 case ERROR_MARK:
14810 return expr;
14811
14812 case INTEGER_CST:
14813 return integer_zerop (expr) ? integer_zero_node : integer_one_node;
14814
14815 case REAL_CST:
14816 return real_zerop (expr) ? integer_zero_node : integer_one_node;
14817
14818 case ADDR_EXPR:
14819 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0)))
14820 return build (COMPOUND_EXPR, integer_type_node,
14821 TREE_OPERAND (expr, 0), integer_one_node);
14822 else
14823 return integer_one_node;
14824
14825 case COMPLEX_EXPR:
14826 return ffecom_2 ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
14827 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
14828 integer_type_node,
14829 ffe_truthvalue_conversion (TREE_OPERAND (expr, 0)),
14830 ffe_truthvalue_conversion (TREE_OPERAND (expr, 1)));
14831
14832 case NEGATE_EXPR:
14833 case ABS_EXPR:
14834 case FLOAT_EXPR:
14835 case FFS_EXPR:
14836 /* These don't change whether an object is nonzero or zero. */
14837 return ffe_truthvalue_conversion (TREE_OPERAND (expr, 0));
14838
14839 case LROTATE_EXPR:
14840 case RROTATE_EXPR:
14841 /* These don't change whether an object is zero or nonzero, but
14842 we can't ignore them if their second arg has side-effects. */
14843 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
14844 return build (COMPOUND_EXPR, integer_type_node, TREE_OPERAND (expr, 1),
14845 ffe_truthvalue_conversion (TREE_OPERAND (expr, 0)));
14846 else
14847 return ffe_truthvalue_conversion (TREE_OPERAND (expr, 0));
14848
14849 case COND_EXPR:
14850 {
14851 /* Distribute the conversion into the arms of a COND_EXPR. */
14852 tree arg1 = TREE_OPERAND (expr, 1);
14853 tree arg2 = TREE_OPERAND (expr, 2);
14854 if (! VOID_TYPE_P (TREE_TYPE (arg1)))
14855 arg1 = ffe_truthvalue_conversion (arg1);
14856 if (! VOID_TYPE_P (TREE_TYPE (arg2)))
14857 arg2 = ffe_truthvalue_conversion (arg2);
14858 return fold (build (COND_EXPR, integer_type_node,
14859 TREE_OPERAND (expr, 0), arg1, arg2));
14860 }
14861
14862 case CONVERT_EXPR:
14863 /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
14864 since that affects how `default_conversion' will behave. */
14865 if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE
14866 || TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
14867 break;
14868 /* fall through... */
14869 case NOP_EXPR:
14870 /* If this is widening the argument, we can ignore it. */
14871 if (TYPE_PRECISION (TREE_TYPE (expr))
14872 >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
14873 return ffe_truthvalue_conversion (TREE_OPERAND (expr, 0));
14874 break;
14875
14876 case MINUS_EXPR:
14877 /* With IEEE arithmetic, x - x may not equal 0, so we can't optimize
14878 this case. */
14879 if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
14880 && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE)
14881 break;
14882 /* fall through... */
14883 case BIT_XOR_EXPR:
14884 /* This and MINUS_EXPR can be changed into a comparison of the
14885 two objects. */
14886 if (TREE_TYPE (TREE_OPERAND (expr, 0))
14887 == TREE_TYPE (TREE_OPERAND (expr, 1)))
14888 return ffecom_2 (NE_EXPR, integer_type_node,
14889 TREE_OPERAND (expr, 0),
14890 TREE_OPERAND (expr, 1));
14891 return ffecom_2 (NE_EXPR, integer_type_node,
14892 TREE_OPERAND (expr, 0),
14893 fold (build1 (NOP_EXPR,
14894 TREE_TYPE (TREE_OPERAND (expr, 0)),
14895 TREE_OPERAND (expr, 1))));
14896
14897 case BIT_AND_EXPR:
14898 if (integer_onep (TREE_OPERAND (expr, 1)))
14899 return expr;
14900 break;
14901
14902 case MODIFY_EXPR:
14903 #if 0 /* No such thing in Fortran. */
14904 if (warn_parentheses && C_EXP_ORIGINAL_CODE (expr) == MODIFY_EXPR)
14905 warning ("suggest parentheses around assignment used as truth value");
14906 #endif
14907 break;
14908
14909 default:
14910 break;
14911 }
14912
14913 if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
14914 return (ffecom_2
14915 ((TREE_SIDE_EFFECTS (expr)
14916 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
14917 integer_type_node,
14918 ffe_truthvalue_conversion (ffecom_1 (REALPART_EXPR,
14919 TREE_TYPE (TREE_TYPE (expr)),
14920 expr)),
14921 ffe_truthvalue_conversion (ffecom_1 (IMAGPART_EXPR,
14922 TREE_TYPE (TREE_TYPE (expr)),
14923 expr))));
14924
14925 return ffecom_2 (NE_EXPR, integer_type_node,
14926 expr,
14927 convert (TREE_TYPE (expr), integer_zero_node));
14928 }
14929
14930 static tree
ffe_type_for_mode(mode,unsignedp)14931 ffe_type_for_mode (mode, unsignedp)
14932 enum machine_mode mode;
14933 int unsignedp;
14934 {
14935 int i;
14936 int j;
14937 tree t;
14938
14939 if (mode == TYPE_MODE (integer_type_node))
14940 return unsignedp ? unsigned_type_node : integer_type_node;
14941
14942 if (mode == TYPE_MODE (signed_char_type_node))
14943 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
14944
14945 if (mode == TYPE_MODE (short_integer_type_node))
14946 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
14947
14948 if (mode == TYPE_MODE (long_integer_type_node))
14949 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
14950
14951 if (mode == TYPE_MODE (long_long_integer_type_node))
14952 return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
14953
14954 #if HOST_BITS_PER_WIDE_INT >= 64
14955 if (mode == TYPE_MODE (intTI_type_node))
14956 return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
14957 #endif
14958
14959 if (mode == TYPE_MODE (float_type_node))
14960 return float_type_node;
14961
14962 if (mode == TYPE_MODE (double_type_node))
14963 return double_type_node;
14964
14965 if (mode == TYPE_MODE (long_double_type_node))
14966 return long_double_type_node;
14967
14968 if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
14969 return build_pointer_type (char_type_node);
14970
14971 if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
14972 return build_pointer_type (integer_type_node);
14973
14974 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
14975 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
14976 {
14977 if (((t = ffecom_tree_type[i][j]) != NULL_TREE)
14978 && (mode == TYPE_MODE (t)))
14979 {
14980 if ((i == FFEINFO_basictypeINTEGER) && unsignedp)
14981 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][j];
14982 else
14983 return t;
14984 }
14985 }
14986
14987 return 0;
14988 }
14989
14990 static tree
ffe_type_for_size(bits,unsignedp)14991 ffe_type_for_size (bits, unsignedp)
14992 unsigned bits;
14993 int unsignedp;
14994 {
14995 ffeinfoKindtype kt;
14996 tree type_node;
14997
14998 if (bits == TYPE_PRECISION (integer_type_node))
14999 return unsignedp ? unsigned_type_node : integer_type_node;
15000
15001 if (bits == TYPE_PRECISION (signed_char_type_node))
15002 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15003
15004 if (bits == TYPE_PRECISION (short_integer_type_node))
15005 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15006
15007 if (bits == TYPE_PRECISION (long_integer_type_node))
15008 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15009
15010 if (bits == TYPE_PRECISION (long_long_integer_type_node))
15011 return (unsignedp ? long_long_unsigned_type_node
15012 : long_long_integer_type_node);
15013
15014 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15015 {
15016 type_node = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15017
15018 if ((type_node != NULL_TREE) && (bits == TYPE_PRECISION (type_node)))
15019 return unsignedp ? ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt]
15020 : type_node;
15021 }
15022
15023 return 0;
15024 }
15025
15026 static tree
ffe_unsigned_type(type)15027 ffe_unsigned_type (type)
15028 tree type;
15029 {
15030 tree type1 = TYPE_MAIN_VARIANT (type);
15031 ffeinfoKindtype kt;
15032 tree type2;
15033
15034 if (type1 == signed_char_type_node || type1 == char_type_node)
15035 return unsigned_char_type_node;
15036 if (type1 == integer_type_node)
15037 return unsigned_type_node;
15038 if (type1 == short_integer_type_node)
15039 return short_unsigned_type_node;
15040 if (type1 == long_integer_type_node)
15041 return long_unsigned_type_node;
15042 if (type1 == long_long_integer_type_node)
15043 return long_long_unsigned_type_node;
15044 #if 0 /* gcc/c-* files only */
15045 if (type1 == intDI_type_node)
15046 return unsigned_intDI_type_node;
15047 if (type1 == intSI_type_node)
15048 return unsigned_intSI_type_node;
15049 if (type1 == intHI_type_node)
15050 return unsigned_intHI_type_node;
15051 if (type1 == intQI_type_node)
15052 return unsigned_intQI_type_node;
15053 #endif
15054
15055 type2 = ffe_type_for_size (TYPE_PRECISION (type1), 1);
15056 if (type2 != NULL_TREE)
15057 return type2;
15058
15059 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15060 {
15061 type2 = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15062
15063 if (type1 == type2)
15064 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
15065 }
15066
15067 return type;
15068 }
15069
15070 /* From gcc/cccp.c, the code to handle -I. */
15071
15072 /* Skip leading "./" from a directory name.
15073 This may yield the empty string, which represents the current directory. */
15074
15075 static const char *
skip_redundant_dir_prefix(const char * dir)15076 skip_redundant_dir_prefix (const char *dir)
15077 {
15078 while (dir[0] == '.' && dir[1] == '/')
15079 for (dir += 2; *dir == '/'; dir++)
15080 continue;
15081 if (dir[0] == '.' && !dir[1])
15082 dir++;
15083 return dir;
15084 }
15085
15086 /* The file_name_map structure holds a mapping of file names for a
15087 particular directory. This mapping is read from the file named
15088 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
15089 map filenames on a file system with severe filename restrictions,
15090 such as DOS. The format of the file name map file is just a series
15091 of lines with two tokens on each line. The first token is the name
15092 to map, and the second token is the actual name to use. */
15093
15094 struct file_name_map
15095 {
15096 struct file_name_map *map_next;
15097 char *map_from;
15098 char *map_to;
15099 };
15100
15101 #define FILE_NAME_MAP_FILE "header.gcc"
15102
15103 /* Current maximum length of directory names in the search path
15104 for include files. (Altered as we get more of them.) */
15105
15106 static int max_include_len = 0;
15107
15108 struct file_name_list
15109 {
15110 struct file_name_list *next;
15111 char *fname;
15112 /* Mapping of file names for this directory. */
15113 struct file_name_map *name_map;
15114 /* Nonzero if name_map is valid. */
15115 int got_name_map;
15116 };
15117
15118 static struct file_name_list *include = NULL; /* First dir to search */
15119 static struct file_name_list *last_include = NULL; /* Last in chain */
15120
15121 /* I/O buffer structure.
15122 The `fname' field is nonzero for source files and #include files
15123 and for the dummy text used for -D and -U.
15124 It is zero for rescanning results of macro expansion
15125 and for expanding macro arguments. */
15126 #define INPUT_STACK_MAX 400
15127 static struct file_buf {
15128 const char *fname;
15129 /* Filename specified with #line command. */
15130 const char *nominal_fname;
15131 /* Record where in the search path this file was found.
15132 For #include_next. */
15133 struct file_name_list *dir;
15134 ffewhereLine line;
15135 ffewhereColumn column;
15136 } instack[INPUT_STACK_MAX];
15137
15138 static int last_error_tick = 0; /* Incremented each time we print it. */
15139 static int input_file_stack_tick = 0; /* Incremented when status changes. */
15140
15141 /* Current nesting level of input sources.
15142 `instack[indepth]' is the level currently being read. */
15143 static int indepth = -1;
15144
15145 typedef struct file_buf FILE_BUF;
15146
15147 /* Nonzero means -I- has been seen,
15148 so don't look for #include "foo" the source-file directory. */
15149 static int ignore_srcdir;
15150
15151 #ifndef INCLUDE_LEN_FUDGE
15152 #define INCLUDE_LEN_FUDGE 0
15153 #endif
15154
15155 static void append_include_chain (struct file_name_list *first,
15156 struct file_name_list *last);
15157 static FILE *open_include_file (char *filename,
15158 struct file_name_list *searchptr);
15159 static void print_containing_files (ffebadSeverity sev);
15160 static char *read_filename_string (int ch, FILE *f);
15161 static struct file_name_map *read_name_map (const char *dirname);
15162
15163 /* Append a chain of `struct file_name_list's
15164 to the end of the main include chain.
15165 FIRST is the beginning of the chain to append, and LAST is the end. */
15166
15167 static void
append_include_chain(first,last)15168 append_include_chain (first, last)
15169 struct file_name_list *first, *last;
15170 {
15171 struct file_name_list *dir;
15172
15173 if (!first || !last)
15174 return;
15175
15176 if (include == 0)
15177 include = first;
15178 else
15179 last_include->next = first;
15180
15181 for (dir = first; ; dir = dir->next) {
15182 int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE;
15183 if (len > max_include_len)
15184 max_include_len = len;
15185 if (dir == last)
15186 break;
15187 }
15188
15189 last->next = NULL;
15190 last_include = last;
15191 }
15192
15193 /* Try to open include file FILENAME. SEARCHPTR is the directory
15194 being tried from the include file search path. This function maps
15195 filenames on file systems based on information read by
15196 read_name_map. */
15197
15198 static FILE *
open_include_file(filename,searchptr)15199 open_include_file (filename, searchptr)
15200 char *filename;
15201 struct file_name_list *searchptr;
15202 {
15203 register struct file_name_map *map;
15204 register char *from;
15205 char *p, *dir;
15206
15207 if (searchptr && ! searchptr->got_name_map)
15208 {
15209 searchptr->name_map = read_name_map (searchptr->fname
15210 ? searchptr->fname : ".");
15211 searchptr->got_name_map = 1;
15212 }
15213
15214 /* First check the mapping for the directory we are using. */
15215 if (searchptr && searchptr->name_map)
15216 {
15217 from = filename;
15218 if (searchptr->fname)
15219 from += strlen (searchptr->fname) + 1;
15220 for (map = searchptr->name_map; map; map = map->map_next)
15221 {
15222 if (! strcmp (map->map_from, from))
15223 {
15224 /* Found a match. */
15225 return fopen (map->map_to, "r");
15226 }
15227 }
15228 }
15229
15230 /* Try to find a mapping file for the particular directory we are
15231 looking in. Thus #include <sys/types.h> will look up sys/types.h
15232 in /usr/include/header.gcc and look up types.h in
15233 /usr/include/sys/header.gcc. */
15234 p = strrchr (filename, '/');
15235 #ifdef DIR_SEPARATOR
15236 if (! p) p = strrchr (filename, DIR_SEPARATOR);
15237 else {
15238 char *tmp = strrchr (filename, DIR_SEPARATOR);
15239 if (tmp != NULL && tmp > p) p = tmp;
15240 }
15241 #endif
15242 if (! p)
15243 p = filename;
15244 if (searchptr
15245 && searchptr->fname
15246 && strlen (searchptr->fname) == (size_t) (p - filename)
15247 && ! strncmp (searchptr->fname, filename, (int) (p - filename)))
15248 {
15249 /* FILENAME is in SEARCHPTR, which we've already checked. */
15250 return fopen (filename, "r");
15251 }
15252
15253 if (p == filename)
15254 {
15255 from = filename;
15256 map = read_name_map (".");
15257 }
15258 else
15259 {
15260 dir = (char *) xmalloc (p - filename + 1);
15261 memcpy (dir, filename, p - filename);
15262 dir[p - filename] = '\0';
15263 from = p + 1;
15264 map = read_name_map (dir);
15265 free (dir);
15266 }
15267 for (; map; map = map->map_next)
15268 if (! strcmp (map->map_from, from))
15269 return fopen (map->map_to, "r");
15270
15271 return fopen (filename, "r");
15272 }
15273
15274 /* Print the file names and line numbers of the #include
15275 commands which led to the current file. */
15276
15277 static void
print_containing_files(ffebadSeverity sev)15278 print_containing_files (ffebadSeverity sev)
15279 {
15280 FILE_BUF *ip = NULL;
15281 int i;
15282 int first = 1;
15283 const char *str1;
15284 const char *str2;
15285
15286 /* If stack of files hasn't changed since we last printed
15287 this info, don't repeat it. */
15288 if (last_error_tick == input_file_stack_tick)
15289 return;
15290
15291 for (i = indepth; i >= 0; i--)
15292 if (instack[i].fname != NULL) {
15293 ip = &instack[i];
15294 break;
15295 }
15296
15297 /* Give up if we don't find a source file. */
15298 if (ip == NULL)
15299 return;
15300
15301 /* Find the other, outer source files. */
15302 for (i--; i >= 0; i--)
15303 if (instack[i].fname != NULL)
15304 {
15305 ip = &instack[i];
15306 if (first)
15307 {
15308 first = 0;
15309 str1 = "In file included";
15310 }
15311 else
15312 {
15313 str1 = "... ...";
15314 }
15315
15316 if (i == 1)
15317 str2 = ":";
15318 else
15319 str2 = "";
15320
15321 /* xgettext:no-c-format */
15322 ffebad_start_msg ("%A from %B at %0%C", sev);
15323 ffebad_here (0, ip->line, ip->column);
15324 ffebad_string (str1);
15325 ffebad_string (ip->nominal_fname);
15326 ffebad_string (str2);
15327 ffebad_finish ();
15328 }
15329
15330 /* Record we have printed the status as of this time. */
15331 last_error_tick = input_file_stack_tick;
15332 }
15333
15334 /* Read a space delimited string of unlimited length from a stdio
15335 file. */
15336
15337 static char *
read_filename_string(ch,f)15338 read_filename_string (ch, f)
15339 int ch;
15340 FILE *f;
15341 {
15342 char *alloc, *set;
15343 int len;
15344
15345 len = 20;
15346 set = alloc = xmalloc (len + 1);
15347 if (! ISSPACE (ch))
15348 {
15349 *set++ = ch;
15350 while ((ch = getc (f)) != EOF && ! ISSPACE (ch))
15351 {
15352 if (set - alloc == len)
15353 {
15354 len *= 2;
15355 alloc = xrealloc (alloc, len + 1);
15356 set = alloc + len / 2;
15357 }
15358 *set++ = ch;
15359 }
15360 }
15361 *set = '\0';
15362 ungetc (ch, f);
15363 return alloc;
15364 }
15365
15366 /* Read the file name map file for DIRNAME. */
15367
15368 static struct file_name_map *
read_name_map(dirname)15369 read_name_map (dirname)
15370 const char *dirname;
15371 {
15372 /* This structure holds a linked list of file name maps, one per
15373 directory. */
15374 struct file_name_map_list
15375 {
15376 struct file_name_map_list *map_list_next;
15377 char *map_list_name;
15378 struct file_name_map *map_list_map;
15379 };
15380 static struct file_name_map_list *map_list;
15381 register struct file_name_map_list *map_list_ptr;
15382 char *name;
15383 FILE *f;
15384 size_t dirlen;
15385 int separator_needed;
15386
15387 dirname = skip_redundant_dir_prefix (dirname);
15388
15389 for (map_list_ptr = map_list; map_list_ptr;
15390 map_list_ptr = map_list_ptr->map_list_next)
15391 if (! strcmp (map_list_ptr->map_list_name, dirname))
15392 return map_list_ptr->map_list_map;
15393
15394 map_list_ptr = ((struct file_name_map_list *)
15395 xmalloc (sizeof (struct file_name_map_list)));
15396 map_list_ptr->map_list_name = xstrdup (dirname);
15397 map_list_ptr->map_list_map = NULL;
15398
15399 dirlen = strlen (dirname);
15400 separator_needed = dirlen != 0 && dirname[dirlen - 1] != '/';
15401 if (separator_needed)
15402 name = concat (dirname, "/", FILE_NAME_MAP_FILE, NULL);
15403 else
15404 name = concat (dirname, FILE_NAME_MAP_FILE, NULL);
15405 f = fopen (name, "r");
15406 free (name);
15407 if (!f)
15408 map_list_ptr->map_list_map = NULL;
15409 else
15410 {
15411 int ch;
15412
15413 while ((ch = getc (f)) != EOF)
15414 {
15415 char *from, *to;
15416 struct file_name_map *ptr;
15417
15418 if (ISSPACE (ch))
15419 continue;
15420 from = read_filename_string (ch, f);
15421 while ((ch = getc (f)) != EOF && ISSPACE (ch) && ch != '\n')
15422 ;
15423 to = read_filename_string (ch, f);
15424
15425 ptr = ((struct file_name_map *)
15426 xmalloc (sizeof (struct file_name_map)));
15427 ptr->map_from = from;
15428
15429 /* Make the real filename absolute. */
15430 if (*to == '/')
15431 ptr->map_to = to;
15432 else
15433 {
15434 if (separator_needed)
15435 ptr->map_to = concat (dirname, "/", to, NULL);
15436 else
15437 ptr->map_to = concat (dirname, to, NULL);
15438 free (to);
15439 }
15440
15441 ptr->map_next = map_list_ptr->map_list_map;
15442 map_list_ptr->map_list_map = ptr;
15443
15444 while ((ch = getc (f)) != '\n')
15445 if (ch == EOF)
15446 break;
15447 }
15448 fclose (f);
15449 }
15450
15451 map_list_ptr->map_list_next = map_list;
15452 map_list = map_list_ptr;
15453
15454 return map_list_ptr->map_list_map;
15455 }
15456
15457 static void
ffecom_file_(const char * name)15458 ffecom_file_ (const char *name)
15459 {
15460 FILE_BUF *fp;
15461
15462 /* Do partial setup of input buffer for the sake of generating
15463 early #line directives (when -g is in effect). */
15464
15465 fp = &instack[++indepth];
15466 memset ((char *) fp, 0, sizeof (FILE_BUF));
15467 if (name == NULL)
15468 name = "";
15469 fp->nominal_fname = fp->fname = name;
15470 }
15471
15472 static void
ffecom_close_include_(FILE * f)15473 ffecom_close_include_ (FILE *f)
15474 {
15475 fclose (f);
15476
15477 indepth--;
15478 input_file_stack_tick++;
15479
15480 ffewhere_line_kill (instack[indepth].line);
15481 ffewhere_column_kill (instack[indepth].column);
15482 }
15483
15484 static int
ffecom_decode_include_option_(char * spec)15485 ffecom_decode_include_option_ (char *spec)
15486 {
15487 struct file_name_list *dirtmp;
15488
15489 if (! ignore_srcdir && !strcmp (spec, "-"))
15490 ignore_srcdir = 1;
15491 else
15492 {
15493 dirtmp = (struct file_name_list *)
15494 xmalloc (sizeof (struct file_name_list));
15495 dirtmp->next = 0; /* New one goes on the end */
15496 dirtmp->fname = spec;
15497 dirtmp->got_name_map = 0;
15498 if (spec[0] == 0)
15499 error ("directory name must immediately follow -I");
15500 else
15501 append_include_chain (dirtmp, dirtmp);
15502 }
15503 return 1;
15504 }
15505
15506 /* Open INCLUDEd file. */
15507
15508 static FILE *
ffecom_open_include_(char * name,ffewhereLine l,ffewhereColumn c)15509 ffecom_open_include_ (char *name, ffewhereLine l, ffewhereColumn c)
15510 {
15511 char *fbeg = name;
15512 size_t flen = strlen (fbeg);
15513 struct file_name_list *search_start = include; /* Chain of dirs to search */
15514 struct file_name_list dsp[1]; /* First in chain, if #include "..." */
15515 struct file_name_list *searchptr = 0;
15516 char *fname; /* Dynamically allocated fname buffer */
15517 FILE *f;
15518 FILE_BUF *fp;
15519
15520 if (flen == 0)
15521 return NULL;
15522
15523 dsp[0].fname = NULL;
15524
15525 /* If -I- was specified, don't search current dir, only spec'd ones. */
15526 if (!ignore_srcdir)
15527 {
15528 for (fp = &instack[indepth]; fp >= instack; fp--)
15529 {
15530 int n;
15531 char *ep;
15532 const char *nam;
15533
15534 if ((nam = fp->nominal_fname) != NULL)
15535 {
15536 /* Found a named file. Figure out dir of the file,
15537 and put it in front of the search list. */
15538 dsp[0].next = search_start;
15539 search_start = dsp;
15540 #ifndef VMS
15541 ep = strrchr (nam, '/');
15542 #ifdef DIR_SEPARATOR
15543 if (ep == NULL) ep = strrchr (nam, DIR_SEPARATOR);
15544 else {
15545 char *tmp = strrchr (nam, DIR_SEPARATOR);
15546 if (tmp != NULL && tmp > ep) ep = tmp;
15547 }
15548 #endif
15549 #else /* VMS */
15550 ep = strrchr (nam, ']');
15551 if (ep == NULL) ep = strrchr (nam, '>');
15552 if (ep == NULL) ep = strrchr (nam, ':');
15553 if (ep != NULL) ep++;
15554 #endif /* VMS */
15555 if (ep != NULL)
15556 {
15557 n = ep - nam;
15558 dsp[0].fname = (char *) xmalloc (n + 1);
15559 strncpy (dsp[0].fname, nam, n);
15560 dsp[0].fname[n] = '\0';
15561 if (n + INCLUDE_LEN_FUDGE > max_include_len)
15562 max_include_len = n + INCLUDE_LEN_FUDGE;
15563 }
15564 else
15565 dsp[0].fname = NULL; /* Current directory */
15566 dsp[0].got_name_map = 0;
15567 break;
15568 }
15569 }
15570 }
15571
15572 /* Allocate this permanently, because it gets stored in the definitions
15573 of macros. */
15574 fname = xmalloc (max_include_len + flen + 4);
15575 /* + 2 above for slash and terminating null. */
15576 /* + 2 added for '.h' on VMS (to support '#include filename') (NOT USED
15577 for g77 yet). */
15578
15579 /* If specified file name is absolute, just open it. */
15580
15581 if (*fbeg == '/'
15582 #ifdef DIR_SEPARATOR
15583 || *fbeg == DIR_SEPARATOR
15584 #endif
15585 )
15586 {
15587 strncpy (fname, (char *) fbeg, flen);
15588 fname[flen] = 0;
15589 f = open_include_file (fname, NULL);
15590 }
15591 else
15592 {
15593 f = NULL;
15594
15595 /* Search directory path, trying to open the file.
15596 Copy each filename tried into FNAME. */
15597
15598 for (searchptr = search_start; searchptr; searchptr = searchptr->next)
15599 {
15600 if (searchptr->fname)
15601 {
15602 /* The empty string in a search path is ignored.
15603 This makes it possible to turn off entirely
15604 a standard piece of the list. */
15605 if (searchptr->fname[0] == 0)
15606 continue;
15607 strcpy (fname, skip_redundant_dir_prefix (searchptr->fname));
15608 if (fname[0] && fname[strlen (fname) - 1] != '/')
15609 strcat (fname, "/");
15610 fname[strlen (fname) + flen] = 0;
15611 }
15612 else
15613 fname[0] = 0;
15614
15615 strncat (fname, fbeg, flen);
15616 #ifdef VMS
15617 /* Change this 1/2 Unix 1/2 VMS file specification into a
15618 full VMS file specification */
15619 if (searchptr->fname && (searchptr->fname[0] != 0))
15620 {
15621 /* Fix up the filename */
15622 hack_vms_include_specification (fname);
15623 }
15624 else
15625 {
15626 /* This is a normal VMS filespec, so use it unchanged. */
15627 strncpy (fname, (char *) fbeg, flen);
15628 fname[flen] = 0;
15629 #if 0 /* Not for g77. */
15630 /* if it's '#include filename', add the missing .h */
15631 if (strchr (fname, '.') == NULL)
15632 strcat (fname, ".h");
15633 #endif
15634 }
15635 #endif /* VMS */
15636 f = open_include_file (fname, searchptr);
15637 #ifdef EACCES
15638 if (f == NULL && errno == EACCES)
15639 {
15640 print_containing_files (FFEBAD_severityWARNING);
15641 /* xgettext:no-c-format */
15642 ffebad_start_msg ("At %0, INCLUDE file %A exists, but is not readable",
15643 FFEBAD_severityWARNING);
15644 ffebad_string (fname);
15645 ffebad_here (0, l, c);
15646 ffebad_finish ();
15647 }
15648 #endif
15649 if (f != NULL)
15650 break;
15651 }
15652 }
15653
15654 if (f == NULL)
15655 {
15656 /* A file that was not found. */
15657
15658 strncpy (fname, (char *) fbeg, flen);
15659 fname[flen] = 0;
15660 print_containing_files (ffebad_severity (FFEBAD_OPEN_INCLUDE));
15661 ffebad_start (FFEBAD_OPEN_INCLUDE);
15662 ffebad_here (0, l, c);
15663 ffebad_string (fname);
15664 ffebad_finish ();
15665 }
15666
15667 if (dsp[0].fname != NULL)
15668 free (dsp[0].fname);
15669
15670 if (f == NULL)
15671 return NULL;
15672
15673 if (indepth >= (INPUT_STACK_MAX - 1))
15674 {
15675 print_containing_files (FFEBAD_severityFATAL);
15676 /* xgettext:no-c-format */
15677 ffebad_start_msg ("At %0, INCLUDE nesting too deep",
15678 FFEBAD_severityFATAL);
15679 ffebad_string (fname);
15680 ffebad_here (0, l, c);
15681 ffebad_finish ();
15682 return NULL;
15683 }
15684
15685 instack[indepth].line = ffewhere_line_use (l);
15686 instack[indepth].column = ffewhere_column_use (c);
15687
15688 fp = &instack[indepth + 1];
15689 memset ((char *) fp, 0, sizeof (FILE_BUF));
15690 fp->nominal_fname = fp->fname = fname;
15691 fp->dir = searchptr;
15692
15693 indepth++;
15694 input_file_stack_tick++;
15695
15696 return f;
15697 }
15698
15699 /**INDENT* (Do not reformat this comment even with -fca option.)
15700 Data-gathering files: Given the source file listed below, compiled with
15701 f2c I obtained the output file listed after that, and from the output
15702 file I derived the above code.
15703
15704 -------- (begin input file to f2c)
15705 implicit none
15706 character*10 A1,A2
15707 complex C1,C2
15708 integer I1,I2
15709 real R1,R2
15710 double precision D1,D2
15711 C
15712 call getem(A1,A2,C1,C2,I1,I2,R1,R2,D1,D2)
15713 c /
15714 call fooI(I1/I2)
15715 call fooR(R1/I1)
15716 call fooD(D1/I1)
15717 call fooC(C1/I1)
15718 call fooR(R1/R2)
15719 call fooD(R1/D1)
15720 call fooD(D1/D2)
15721 call fooD(D1/R1)
15722 call fooC(C1/C2)
15723 call fooC(C1/R1)
15724 call fooZ(C1/D1)
15725 c **
15726 call fooI(I1**I2)
15727 call fooR(R1**I1)
15728 call fooD(D1**I1)
15729 call fooC(C1**I1)
15730 call fooR(R1**R2)
15731 call fooD(R1**D1)
15732 call fooD(D1**D2)
15733 call fooD(D1**R1)
15734 call fooC(C1**C2)
15735 call fooC(C1**R1)
15736 call fooZ(C1**D1)
15737 c FFEINTRIN_impABS
15738 call fooR(ABS(R1))
15739 c FFEINTRIN_impACOS
15740 call fooR(ACOS(R1))
15741 c FFEINTRIN_impAIMAG
15742 call fooR(AIMAG(C1))
15743 c FFEINTRIN_impAINT
15744 call fooR(AINT(R1))
15745 c FFEINTRIN_impALOG
15746 call fooR(ALOG(R1))
15747 c FFEINTRIN_impALOG10
15748 call fooR(ALOG10(R1))
15749 c FFEINTRIN_impAMAX0
15750 call fooR(AMAX0(I1,I2))
15751 c FFEINTRIN_impAMAX1
15752 call fooR(AMAX1(R1,R2))
15753 c FFEINTRIN_impAMIN0
15754 call fooR(AMIN0(I1,I2))
15755 c FFEINTRIN_impAMIN1
15756 call fooR(AMIN1(R1,R2))
15757 c FFEINTRIN_impAMOD
15758 call fooR(AMOD(R1,R2))
15759 c FFEINTRIN_impANINT
15760 call fooR(ANINT(R1))
15761 c FFEINTRIN_impASIN
15762 call fooR(ASIN(R1))
15763 c FFEINTRIN_impATAN
15764 call fooR(ATAN(R1))
15765 c FFEINTRIN_impATAN2
15766 call fooR(ATAN2(R1,R2))
15767 c FFEINTRIN_impCABS
15768 call fooR(CABS(C1))
15769 c FFEINTRIN_impCCOS
15770 call fooC(CCOS(C1))
15771 c FFEINTRIN_impCEXP
15772 call fooC(CEXP(C1))
15773 c FFEINTRIN_impCHAR
15774 call fooA(CHAR(I1))
15775 c FFEINTRIN_impCLOG
15776 call fooC(CLOG(C1))
15777 c FFEINTRIN_impCONJG
15778 call fooC(CONJG(C1))
15779 c FFEINTRIN_impCOS
15780 call fooR(COS(R1))
15781 c FFEINTRIN_impCOSH
15782 call fooR(COSH(R1))
15783 c FFEINTRIN_impCSIN
15784 call fooC(CSIN(C1))
15785 c FFEINTRIN_impCSQRT
15786 call fooC(CSQRT(C1))
15787 c FFEINTRIN_impDABS
15788 call fooD(DABS(D1))
15789 c FFEINTRIN_impDACOS
15790 call fooD(DACOS(D1))
15791 c FFEINTRIN_impDASIN
15792 call fooD(DASIN(D1))
15793 c FFEINTRIN_impDATAN
15794 call fooD(DATAN(D1))
15795 c FFEINTRIN_impDATAN2
15796 call fooD(DATAN2(D1,D2))
15797 c FFEINTRIN_impDCOS
15798 call fooD(DCOS(D1))
15799 c FFEINTRIN_impDCOSH
15800 call fooD(DCOSH(D1))
15801 c FFEINTRIN_impDDIM
15802 call fooD(DDIM(D1,D2))
15803 c FFEINTRIN_impDEXP
15804 call fooD(DEXP(D1))
15805 c FFEINTRIN_impDIM
15806 call fooR(DIM(R1,R2))
15807 c FFEINTRIN_impDINT
15808 call fooD(DINT(D1))
15809 c FFEINTRIN_impDLOG
15810 call fooD(DLOG(D1))
15811 c FFEINTRIN_impDLOG10
15812 call fooD(DLOG10(D1))
15813 c FFEINTRIN_impDMAX1
15814 call fooD(DMAX1(D1,D2))
15815 c FFEINTRIN_impDMIN1
15816 call fooD(DMIN1(D1,D2))
15817 c FFEINTRIN_impDMOD
15818 call fooD(DMOD(D1,D2))
15819 c FFEINTRIN_impDNINT
15820 call fooD(DNINT(D1))
15821 c FFEINTRIN_impDPROD
15822 call fooD(DPROD(R1,R2))
15823 c FFEINTRIN_impDSIGN
15824 call fooD(DSIGN(D1,D2))
15825 c FFEINTRIN_impDSIN
15826 call fooD(DSIN(D1))
15827 c FFEINTRIN_impDSINH
15828 call fooD(DSINH(D1))
15829 c FFEINTRIN_impDSQRT
15830 call fooD(DSQRT(D1))
15831 c FFEINTRIN_impDTAN
15832 call fooD(DTAN(D1))
15833 c FFEINTRIN_impDTANH
15834 call fooD(DTANH(D1))
15835 c FFEINTRIN_impEXP
15836 call fooR(EXP(R1))
15837 c FFEINTRIN_impIABS
15838 call fooI(IABS(I1))
15839 c FFEINTRIN_impICHAR
15840 call fooI(ICHAR(A1))
15841 c FFEINTRIN_impIDIM
15842 call fooI(IDIM(I1,I2))
15843 c FFEINTRIN_impIDNINT
15844 call fooI(IDNINT(D1))
15845 c FFEINTRIN_impINDEX
15846 call fooI(INDEX(A1,A2))
15847 c FFEINTRIN_impISIGN
15848 call fooI(ISIGN(I1,I2))
15849 c FFEINTRIN_impLEN
15850 call fooI(LEN(A1))
15851 c FFEINTRIN_impLGE
15852 call fooL(LGE(A1,A2))
15853 c FFEINTRIN_impLGT
15854 call fooL(LGT(A1,A2))
15855 c FFEINTRIN_impLLE
15856 call fooL(LLE(A1,A2))
15857 c FFEINTRIN_impLLT
15858 call fooL(LLT(A1,A2))
15859 c FFEINTRIN_impMAX0
15860 call fooI(MAX0(I1,I2))
15861 c FFEINTRIN_impMAX1
15862 call fooI(MAX1(R1,R2))
15863 c FFEINTRIN_impMIN0
15864 call fooI(MIN0(I1,I2))
15865 c FFEINTRIN_impMIN1
15866 call fooI(MIN1(R1,R2))
15867 c FFEINTRIN_impMOD
15868 call fooI(MOD(I1,I2))
15869 c FFEINTRIN_impNINT
15870 call fooI(NINT(R1))
15871 c FFEINTRIN_impSIGN
15872 call fooR(SIGN(R1,R2))
15873 c FFEINTRIN_impSIN
15874 call fooR(SIN(R1))
15875 c FFEINTRIN_impSINH
15876 call fooR(SINH(R1))
15877 c FFEINTRIN_impSQRT
15878 call fooR(SQRT(R1))
15879 c FFEINTRIN_impTAN
15880 call fooR(TAN(R1))
15881 c FFEINTRIN_impTANH
15882 call fooR(TANH(R1))
15883 c FFEINTRIN_imp_CMPLX_C
15884 call fooC(cmplx(C1,C2))
15885 c FFEINTRIN_imp_CMPLX_D
15886 call fooZ(cmplx(D1,D2))
15887 c FFEINTRIN_imp_CMPLX_I
15888 call fooC(cmplx(I1,I2))
15889 c FFEINTRIN_imp_CMPLX_R
15890 call fooC(cmplx(R1,R2))
15891 c FFEINTRIN_imp_DBLE_C
15892 call fooD(dble(C1))
15893 c FFEINTRIN_imp_DBLE_D
15894 call fooD(dble(D1))
15895 c FFEINTRIN_imp_DBLE_I
15896 call fooD(dble(I1))
15897 c FFEINTRIN_imp_DBLE_R
15898 call fooD(dble(R1))
15899 c FFEINTRIN_imp_INT_C
15900 call fooI(int(C1))
15901 c FFEINTRIN_imp_INT_D
15902 call fooI(int(D1))
15903 c FFEINTRIN_imp_INT_I
15904 call fooI(int(I1))
15905 c FFEINTRIN_imp_INT_R
15906 call fooI(int(R1))
15907 c FFEINTRIN_imp_REAL_C
15908 call fooR(real(C1))
15909 c FFEINTRIN_imp_REAL_D
15910 call fooR(real(D1))
15911 c FFEINTRIN_imp_REAL_I
15912 call fooR(real(I1))
15913 c FFEINTRIN_imp_REAL_R
15914 call fooR(real(R1))
15915 c
15916 c FFEINTRIN_imp_INT_D:
15917 c
15918 c FFEINTRIN_specIDINT
15919 call fooI(IDINT(D1))
15920 c
15921 c FFEINTRIN_imp_INT_R:
15922 c
15923 c FFEINTRIN_specIFIX
15924 call fooI(IFIX(R1))
15925 c FFEINTRIN_specINT
15926 call fooI(INT(R1))
15927 c
15928 c FFEINTRIN_imp_REAL_D:
15929 c
15930 c FFEINTRIN_specSNGL
15931 call fooR(SNGL(D1))
15932 c
15933 c FFEINTRIN_imp_REAL_I:
15934 c
15935 c FFEINTRIN_specFLOAT
15936 call fooR(FLOAT(I1))
15937 c FFEINTRIN_specREAL
15938 call fooR(REAL(I1))
15939 c
15940 end
15941 -------- (end input file to f2c)
15942
15943 -------- (begin output from providing above input file as input to:
15944 -------- `f2c | gcc -E -C - | sed -e "s:/[*]*://:g" -e "s:[*]*[/]://:g" \
15945 -------- -e "s:^#.*$::g"')
15946
15947 // -- translated by f2c (version 19950223).
15948 You must link the resulting object file with the libraries:
15949 -lf2c -lm (in that order)
15950 //
15951
15952
15953 // f2c.h -- Standard Fortran to C header file //
15954
15955 /// barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed."
15956
15957 - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) //
15958
15959
15960
15961
15962 // F2C_INTEGER will normally be `int' but would be `long' on 16-bit systems //
15963 // we assume short, float are OK //
15964 typedef long int // long int // integer;
15965 typedef char *address;
15966 typedef short int shortint;
15967 typedef float real;
15968 typedef double doublereal;
15969 typedef struct { real r, i; } complex;
15970 typedef struct { doublereal r, i; } doublecomplex;
15971 typedef long int // long int // logical;
15972 typedef short int shortlogical;
15973 typedef char logical1;
15974 typedef char integer1;
15975 // typedef long long longint; // // system-dependent //
15976
15977
15978
15979
15980 // Extern is for use with -E //
15981
15982
15983
15984
15985 // I/O stuff //
15986
15987
15988
15989
15990
15991
15992
15993
15994 typedef long int // int or long int // flag;
15995 typedef long int // int or long int // ftnlen;
15996 typedef long int // int or long int // ftnint;
15997
15998
15999 //external read, write//
16000 typedef struct
16001 { flag cierr;
16002 ftnint ciunit;
16003 flag ciend;
16004 char *cifmt;
16005 ftnint cirec;
16006 } cilist;
16007
16008 //internal read, write//
16009 typedef struct
16010 { flag icierr;
16011 char *iciunit;
16012 flag iciend;
16013 char *icifmt;
16014 ftnint icirlen;
16015 ftnint icirnum;
16016 } icilist;
16017
16018 //open//
16019 typedef struct
16020 { flag oerr;
16021 ftnint ounit;
16022 char *ofnm;
16023 ftnlen ofnmlen;
16024 char *osta;
16025 char *oacc;
16026 char *ofm;
16027 ftnint orl;
16028 char *oblnk;
16029 } olist;
16030
16031 //close//
16032 typedef struct
16033 { flag cerr;
16034 ftnint cunit;
16035 char *csta;
16036 } cllist;
16037
16038 //rewind, backspace, endfile//
16039 typedef struct
16040 { flag aerr;
16041 ftnint aunit;
16042 } alist;
16043
16044 // inquire //
16045 typedef struct
16046 { flag inerr;
16047 ftnint inunit;
16048 char *infile;
16049 ftnlen infilen;
16050 ftnint *inex; //parameters in standard's order//
16051 ftnint *inopen;
16052 ftnint *innum;
16053 ftnint *innamed;
16054 char *inname;
16055 ftnlen innamlen;
16056 char *inacc;
16057 ftnlen inacclen;
16058 char *inseq;
16059 ftnlen inseqlen;
16060 char *indir;
16061 ftnlen indirlen;
16062 char *infmt;
16063 ftnlen infmtlen;
16064 char *inform;
16065 ftnint informlen;
16066 char *inunf;
16067 ftnlen inunflen;
16068 ftnint *inrecl;
16069 ftnint *innrec;
16070 char *inblank;
16071 ftnlen inblanklen;
16072 } inlist;
16073
16074
16075
16076 union Multitype { // for multiple entry points //
16077 integer1 g;
16078 shortint h;
16079 integer i;
16080 // longint j; //
16081 real r;
16082 doublereal d;
16083 complex c;
16084 doublecomplex z;
16085 };
16086
16087 typedef union Multitype Multitype;
16088
16089 typedef long Long; // No longer used; formerly in Namelist //
16090
16091 struct Vardesc { // for Namelist //
16092 char *name;
16093 char *addr;
16094 ftnlen *dims;
16095 int type;
16096 };
16097 typedef struct Vardesc Vardesc;
16098
16099 struct Namelist {
16100 char *name;
16101 Vardesc **vars;
16102 int nvars;
16103 };
16104 typedef struct Namelist Namelist;
16105
16106
16107
16108
16109
16110
16111
16112
16113 // procedure parameter types for -A and -C++ //
16114
16115
16116
16117
16118 typedef int // Unknown procedure type // (*U_fp)();
16119 typedef shortint (*J_fp)();
16120 typedef integer (*I_fp)();
16121 typedef real (*R_fp)();
16122 typedef doublereal (*D_fp)(), (*E_fp)();
16123 typedef // Complex // void (*C_fp)();
16124 typedef // Double Complex // void (*Z_fp)();
16125 typedef logical (*L_fp)();
16126 typedef shortlogical (*K_fp)();
16127 typedef // Character // void (*H_fp)();
16128 typedef // Subroutine // int (*S_fp)();
16129
16130 // E_fp is for real functions when -R is not specified //
16131 typedef void C_f; // complex function //
16132 typedef void H_f; // character function //
16133 typedef void Z_f; // double complex function //
16134 typedef doublereal E_f; // real function with -R not specified //
16135
16136 // undef any lower-case symbols that your C compiler predefines, e.g.: //
16137
16138
16139 // (No such symbols should be defined in a strict ANSI C compiler.
16140 We can avoid trouble with f2c-translated code by using
16141 gcc -ansi.) //
16142
16143
16144
16145
16146
16147
16148
16149
16150
16151
16152
16153
16154
16155
16156
16157
16158
16159
16160
16161
16162
16163
16164
16165 // Main program // MAIN__()
16166 {
16167 // System generated locals //
16168 integer i__1;
16169 real r__1, r__2;
16170 doublereal d__1, d__2;
16171 complex q__1;
16172 doublecomplex z__1, z__2, z__3;
16173 logical L__1;
16174 char ch__1[1];
16175
16176 // Builtin functions //
16177 void c_div();
16178 integer pow_ii();
16179 double pow_ri(), pow_di();
16180 void pow_ci();
16181 double pow_dd();
16182 void pow_zz();
16183 double acos(), r_imag(), r_int(), log(), r_lg10(), r_mod(), r_nint(),
16184 asin(), atan(), atan2(), c_abs();
16185 void c_cos(), c_exp(), c_log(), r_cnjg();
16186 double cos(), cosh();
16187 void c_sin(), c_sqrt();
16188 double d_dim(), exp(), r_dim(), d_int(), d_lg10(), d_mod(), d_nint(),
16189 d_sign(), sin(), sinh(), sqrt(), tan(), tanh();
16190 integer i_dim(), i_dnnt(), i_indx(), i_sign(), i_len();
16191 logical l_ge(), l_gt(), l_le(), l_lt();
16192 integer i_nint();
16193 double r_sign();
16194
16195 // Local variables //
16196 extern // Subroutine // int fooa_(), fooc_(), food_(), fooi_(), foor_(),
16197 fool_(), fooz_(), getem_();
16198 static char a1[10], a2[10];
16199 static complex c1, c2;
16200 static doublereal d1, d2;
16201 static integer i1, i2;
16202 static real r1, r2;
16203
16204
16205 getem_(a1, a2, &c1, &c2, &i1, &i2, &r1, &r2, &d1, &d2, 10L, 10L);
16206 // / //
16207 i__1 = i1 / i2;
16208 fooi_(&i__1);
16209 r__1 = r1 / i1;
16210 foor_(&r__1);
16211 d__1 = d1 / i1;
16212 food_(&d__1);
16213 d__1 = (doublereal) i1;
16214 q__1.r = c1.r / d__1, q__1.i = c1.i / d__1;
16215 fooc_(&q__1);
16216 r__1 = r1 / r2;
16217 foor_(&r__1);
16218 d__1 = r1 / d1;
16219 food_(&d__1);
16220 d__1 = d1 / d2;
16221 food_(&d__1);
16222 d__1 = d1 / r1;
16223 food_(&d__1);
16224 c_div(&q__1, &c1, &c2);
16225 fooc_(&q__1);
16226 q__1.r = c1.r / r1, q__1.i = c1.i / r1;
16227 fooc_(&q__1);
16228 z__1.r = c1.r / d1, z__1.i = c1.i / d1;
16229 fooz_(&z__1);
16230 // ** //
16231 i__1 = pow_ii(&i1, &i2);
16232 fooi_(&i__1);
16233 r__1 = pow_ri(&r1, &i1);
16234 foor_(&r__1);
16235 d__1 = pow_di(&d1, &i1);
16236 food_(&d__1);
16237 pow_ci(&q__1, &c1, &i1);
16238 fooc_(&q__1);
16239 d__1 = (doublereal) r1;
16240 d__2 = (doublereal) r2;
16241 r__1 = pow_dd(&d__1, &d__2);
16242 foor_(&r__1);
16243 d__2 = (doublereal) r1;
16244 d__1 = pow_dd(&d__2, &d1);
16245 food_(&d__1);
16246 d__1 = pow_dd(&d1, &d2);
16247 food_(&d__1);
16248 d__2 = (doublereal) r1;
16249 d__1 = pow_dd(&d1, &d__2);
16250 food_(&d__1);
16251 z__2.r = c1.r, z__2.i = c1.i;
16252 z__3.r = c2.r, z__3.i = c2.i;
16253 pow_zz(&z__1, &z__2, &z__3);
16254 q__1.r = z__1.r, q__1.i = z__1.i;
16255 fooc_(&q__1);
16256 z__2.r = c1.r, z__2.i = c1.i;
16257 z__3.r = r1, z__3.i = 0.;
16258 pow_zz(&z__1, &z__2, &z__3);
16259 q__1.r = z__1.r, q__1.i = z__1.i;
16260 fooc_(&q__1);
16261 z__2.r = c1.r, z__2.i = c1.i;
16262 z__3.r = d1, z__3.i = 0.;
16263 pow_zz(&z__1, &z__2, &z__3);
16264 fooz_(&z__1);
16265 // FFEINTRIN_impABS //
16266 r__1 = (doublereal)(( r1 ) >= 0 ? ( r1 ) : -( r1 )) ;
16267 foor_(&r__1);
16268 // FFEINTRIN_impACOS //
16269 r__1 = acos(r1);
16270 foor_(&r__1);
16271 // FFEINTRIN_impAIMAG //
16272 r__1 = r_imag(&c1);
16273 foor_(&r__1);
16274 // FFEINTRIN_impAINT //
16275 r__1 = r_int(&r1);
16276 foor_(&r__1);
16277 // FFEINTRIN_impALOG //
16278 r__1 = log(r1);
16279 foor_(&r__1);
16280 // FFEINTRIN_impALOG10 //
16281 r__1 = r_lg10(&r1);
16282 foor_(&r__1);
16283 // FFEINTRIN_impAMAX0 //
16284 r__1 = (real) (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
16285 foor_(&r__1);
16286 // FFEINTRIN_impAMAX1 //
16287 r__1 = (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
16288 foor_(&r__1);
16289 // FFEINTRIN_impAMIN0 //
16290 r__1 = (real) (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
16291 foor_(&r__1);
16292 // FFEINTRIN_impAMIN1 //
16293 r__1 = (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
16294 foor_(&r__1);
16295 // FFEINTRIN_impAMOD //
16296 r__1 = r_mod(&r1, &r2);
16297 foor_(&r__1);
16298 // FFEINTRIN_impANINT //
16299 r__1 = r_nint(&r1);
16300 foor_(&r__1);
16301 // FFEINTRIN_impASIN //
16302 r__1 = asin(r1);
16303 foor_(&r__1);
16304 // FFEINTRIN_impATAN //
16305 r__1 = atan(r1);
16306 foor_(&r__1);
16307 // FFEINTRIN_impATAN2 //
16308 r__1 = atan2(r1, r2);
16309 foor_(&r__1);
16310 // FFEINTRIN_impCABS //
16311 r__1 = c_abs(&c1);
16312 foor_(&r__1);
16313 // FFEINTRIN_impCCOS //
16314 c_cos(&q__1, &c1);
16315 fooc_(&q__1);
16316 // FFEINTRIN_impCEXP //
16317 c_exp(&q__1, &c1);
16318 fooc_(&q__1);
16319 // FFEINTRIN_impCHAR //
16320 *(unsigned char *)&ch__1[0] = i1;
16321 fooa_(ch__1, 1L);
16322 // FFEINTRIN_impCLOG //
16323 c_log(&q__1, &c1);
16324 fooc_(&q__1);
16325 // FFEINTRIN_impCONJG //
16326 r_cnjg(&q__1, &c1);
16327 fooc_(&q__1);
16328 // FFEINTRIN_impCOS //
16329 r__1 = cos(r1);
16330 foor_(&r__1);
16331 // FFEINTRIN_impCOSH //
16332 r__1 = cosh(r1);
16333 foor_(&r__1);
16334 // FFEINTRIN_impCSIN //
16335 c_sin(&q__1, &c1);
16336 fooc_(&q__1);
16337 // FFEINTRIN_impCSQRT //
16338 c_sqrt(&q__1, &c1);
16339 fooc_(&q__1);
16340 // FFEINTRIN_impDABS //
16341 d__1 = (( d1 ) >= 0 ? ( d1 ) : -( d1 )) ;
16342 food_(&d__1);
16343 // FFEINTRIN_impDACOS //
16344 d__1 = acos(d1);
16345 food_(&d__1);
16346 // FFEINTRIN_impDASIN //
16347 d__1 = asin(d1);
16348 food_(&d__1);
16349 // FFEINTRIN_impDATAN //
16350 d__1 = atan(d1);
16351 food_(&d__1);
16352 // FFEINTRIN_impDATAN2 //
16353 d__1 = atan2(d1, d2);
16354 food_(&d__1);
16355 // FFEINTRIN_impDCOS //
16356 d__1 = cos(d1);
16357 food_(&d__1);
16358 // FFEINTRIN_impDCOSH //
16359 d__1 = cosh(d1);
16360 food_(&d__1);
16361 // FFEINTRIN_impDDIM //
16362 d__1 = d_dim(&d1, &d2);
16363 food_(&d__1);
16364 // FFEINTRIN_impDEXP //
16365 d__1 = exp(d1);
16366 food_(&d__1);
16367 // FFEINTRIN_impDIM //
16368 r__1 = r_dim(&r1, &r2);
16369 foor_(&r__1);
16370 // FFEINTRIN_impDINT //
16371 d__1 = d_int(&d1);
16372 food_(&d__1);
16373 // FFEINTRIN_impDLOG //
16374 d__1 = log(d1);
16375 food_(&d__1);
16376 // FFEINTRIN_impDLOG10 //
16377 d__1 = d_lg10(&d1);
16378 food_(&d__1);
16379 // FFEINTRIN_impDMAX1 //
16380 d__1 = (( d1 ) >= ( d2 ) ? ( d1 ) : ( d2 )) ;
16381 food_(&d__1);
16382 // FFEINTRIN_impDMIN1 //
16383 d__1 = (( d1 ) <= ( d2 ) ? ( d1 ) : ( d2 )) ;
16384 food_(&d__1);
16385 // FFEINTRIN_impDMOD //
16386 d__1 = d_mod(&d1, &d2);
16387 food_(&d__1);
16388 // FFEINTRIN_impDNINT //
16389 d__1 = d_nint(&d1);
16390 food_(&d__1);
16391 // FFEINTRIN_impDPROD //
16392 d__1 = (doublereal) r1 * r2;
16393 food_(&d__1);
16394 // FFEINTRIN_impDSIGN //
16395 d__1 = d_sign(&d1, &d2);
16396 food_(&d__1);
16397 // FFEINTRIN_impDSIN //
16398 d__1 = sin(d1);
16399 food_(&d__1);
16400 // FFEINTRIN_impDSINH //
16401 d__1 = sinh(d1);
16402 food_(&d__1);
16403 // FFEINTRIN_impDSQRT //
16404 d__1 = sqrt(d1);
16405 food_(&d__1);
16406 // FFEINTRIN_impDTAN //
16407 d__1 = tan(d1);
16408 food_(&d__1);
16409 // FFEINTRIN_impDTANH //
16410 d__1 = tanh(d1);
16411 food_(&d__1);
16412 // FFEINTRIN_impEXP //
16413 r__1 = exp(r1);
16414 foor_(&r__1);
16415 // FFEINTRIN_impIABS //
16416 i__1 = (( i1 ) >= 0 ? ( i1 ) : -( i1 )) ;
16417 fooi_(&i__1);
16418 // FFEINTRIN_impICHAR //
16419 i__1 = *(unsigned char *)a1;
16420 fooi_(&i__1);
16421 // FFEINTRIN_impIDIM //
16422 i__1 = i_dim(&i1, &i2);
16423 fooi_(&i__1);
16424 // FFEINTRIN_impIDNINT //
16425 i__1 = i_dnnt(&d1);
16426 fooi_(&i__1);
16427 // FFEINTRIN_impINDEX //
16428 i__1 = i_indx(a1, a2, 10L, 10L);
16429 fooi_(&i__1);
16430 // FFEINTRIN_impISIGN //
16431 i__1 = i_sign(&i1, &i2);
16432 fooi_(&i__1);
16433 // FFEINTRIN_impLEN //
16434 i__1 = i_len(a1, 10L);
16435 fooi_(&i__1);
16436 // FFEINTRIN_impLGE //
16437 L__1 = l_ge(a1, a2, 10L, 10L);
16438 fool_(&L__1);
16439 // FFEINTRIN_impLGT //
16440 L__1 = l_gt(a1, a2, 10L, 10L);
16441 fool_(&L__1);
16442 // FFEINTRIN_impLLE //
16443 L__1 = l_le(a1, a2, 10L, 10L);
16444 fool_(&L__1);
16445 // FFEINTRIN_impLLT //
16446 L__1 = l_lt(a1, a2, 10L, 10L);
16447 fool_(&L__1);
16448 // FFEINTRIN_impMAX0 //
16449 i__1 = (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
16450 fooi_(&i__1);
16451 // FFEINTRIN_impMAX1 //
16452 i__1 = (integer) (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
16453 fooi_(&i__1);
16454 // FFEINTRIN_impMIN0 //
16455 i__1 = (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
16456 fooi_(&i__1);
16457 // FFEINTRIN_impMIN1 //
16458 i__1 = (integer) (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
16459 fooi_(&i__1);
16460 // FFEINTRIN_impMOD //
16461 i__1 = i1 % i2;
16462 fooi_(&i__1);
16463 // FFEINTRIN_impNINT //
16464 i__1 = i_nint(&r1);
16465 fooi_(&i__1);
16466 // FFEINTRIN_impSIGN //
16467 r__1 = r_sign(&r1, &r2);
16468 foor_(&r__1);
16469 // FFEINTRIN_impSIN //
16470 r__1 = sin(r1);
16471 foor_(&r__1);
16472 // FFEINTRIN_impSINH //
16473 r__1 = sinh(r1);
16474 foor_(&r__1);
16475 // FFEINTRIN_impSQRT //
16476 r__1 = sqrt(r1);
16477 foor_(&r__1);
16478 // FFEINTRIN_impTAN //
16479 r__1 = tan(r1);
16480 foor_(&r__1);
16481 // FFEINTRIN_impTANH //
16482 r__1 = tanh(r1);
16483 foor_(&r__1);
16484 // FFEINTRIN_imp_CMPLX_C //
16485 r__1 = c1.r;
16486 r__2 = c2.r;
16487 q__1.r = r__1, q__1.i = r__2;
16488 fooc_(&q__1);
16489 // FFEINTRIN_imp_CMPLX_D //
16490 z__1.r = d1, z__1.i = d2;
16491 fooz_(&z__1);
16492 // FFEINTRIN_imp_CMPLX_I //
16493 r__1 = (real) i1;
16494 r__2 = (real) i2;
16495 q__1.r = r__1, q__1.i = r__2;
16496 fooc_(&q__1);
16497 // FFEINTRIN_imp_CMPLX_R //
16498 q__1.r = r1, q__1.i = r2;
16499 fooc_(&q__1);
16500 // FFEINTRIN_imp_DBLE_C //
16501 d__1 = (doublereal) c1.r;
16502 food_(&d__1);
16503 // FFEINTRIN_imp_DBLE_D //
16504 d__1 = d1;
16505 food_(&d__1);
16506 // FFEINTRIN_imp_DBLE_I //
16507 d__1 = (doublereal) i1;
16508 food_(&d__1);
16509 // FFEINTRIN_imp_DBLE_R //
16510 d__1 = (doublereal) r1;
16511 food_(&d__1);
16512 // FFEINTRIN_imp_INT_C //
16513 i__1 = (integer) c1.r;
16514 fooi_(&i__1);
16515 // FFEINTRIN_imp_INT_D //
16516 i__1 = (integer) d1;
16517 fooi_(&i__1);
16518 // FFEINTRIN_imp_INT_I //
16519 i__1 = i1;
16520 fooi_(&i__1);
16521 // FFEINTRIN_imp_INT_R //
16522 i__1 = (integer) r1;
16523 fooi_(&i__1);
16524 // FFEINTRIN_imp_REAL_C //
16525 r__1 = c1.r;
16526 foor_(&r__1);
16527 // FFEINTRIN_imp_REAL_D //
16528 r__1 = (real) d1;
16529 foor_(&r__1);
16530 // FFEINTRIN_imp_REAL_I //
16531 r__1 = (real) i1;
16532 foor_(&r__1);
16533 // FFEINTRIN_imp_REAL_R //
16534 r__1 = r1;
16535 foor_(&r__1);
16536
16537 // FFEINTRIN_imp_INT_D: //
16538
16539 // FFEINTRIN_specIDINT //
16540 i__1 = (integer) d1;
16541 fooi_(&i__1);
16542
16543 // FFEINTRIN_imp_INT_R: //
16544
16545 // FFEINTRIN_specIFIX //
16546 i__1 = (integer) r1;
16547 fooi_(&i__1);
16548 // FFEINTRIN_specINT //
16549 i__1 = (integer) r1;
16550 fooi_(&i__1);
16551
16552 // FFEINTRIN_imp_REAL_D: //
16553
16554 // FFEINTRIN_specSNGL //
16555 r__1 = (real) d1;
16556 foor_(&r__1);
16557
16558 // FFEINTRIN_imp_REAL_I: //
16559
16560 // FFEINTRIN_specFLOAT //
16561 r__1 = (real) i1;
16562 foor_(&r__1);
16563 // FFEINTRIN_specREAL //
16564 r__1 = (real) i1;
16565 foor_(&r__1);
16566
16567 } // MAIN__ //
16568
16569 -------- (end output file from f2c)
16570
16571 */
16572
16573 #include "gt-f-com.h"
16574 #include "gtype-f.h"
16575