* config/ia64/fde-glibc.c (_GNU_SOURCE): Define to 1 instead of
[official-gcc.git] / gcc / f / com.c
blob535ddbb87e865892885b6346cb4e1efab839341d
1 /* com.c -- Implementation File (module.c template V1.0)
2 Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
3 Free Software Foundation, Inc.
4 Contributed by James Craig Burley.
6 This file is part of GNU Fortran.
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.
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.
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.
23 Related Modules:
24 None
26 Description:
27 Contains compiler-specific functions.
29 Modifications:
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.
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:
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)
53 g77 has a set of functions that somewhat parallels the gcc front end
54 when it comes to building decls:
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 ();
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);
81 /* Include files. */
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"
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 */
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"
140 /* Externals defined here. */
142 /* Stream for reading from the input file. */
143 FILE *finput;
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). */
152 tree string_type_node;
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. */
159 static GTY(()) tree ffecom_tree_fun_type_void;
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];
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. */
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;
177 static GTY(()) tree ffecom_tree_xargc_;
179 ffecomSymbol ffecom_symbol_null_
182 NULL_TREE,
183 NULL_TREE,
184 NULL_TREE,
185 NULL_TREE,
186 false
188 ffeinfoKindtype ffecom_pointer_kind_ = FFEINFO_basictypeNONE;
189 ffeinfoKindtype ffecom_label_kind_ = FFEINFO_basictypeNONE;
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;
211 /* Simple definitions and enumerations. */
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
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. */
223 #if FFECOM_sizeMAXSTACKITEM == 0
224 #undef FFECOM_sizeMAXSTACKITEM
225 #endif
227 typedef enum
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_;
247 /* Internal typedefs. */
249 typedef struct _ffecom_concat_list_ ffecomConcatList_;
251 /* Private include files. */
254 /* Internal structure definitions. */
256 struct _ffecom_concat_list_
258 ffebld *exprs;
259 int count;
260 int max;
261 ffetargetCharacterSize minlen;
262 ffetargetCharacterSize maxlen;
265 /* Static functions (internal). */
267 static tree ffe_type_for_mode (enum machine_mode, int);
268 static tree ffe_type_for_size (unsigned int, int);
269 static tree ffe_unsigned_type (tree);
270 static tree ffe_signed_type (tree);
271 static tree ffe_signed_or_unsigned_type (int, tree);
272 static bool ffe_mark_addressable (tree);
273 static tree ffe_truthvalue_conversion (tree);
274 static void ffecom_init_decl_processing (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);
368 /* These are static functions that parallel those found in the C front
369 end and thus have the same names. */
371 static tree bison_rule_compstmt_ (void);
372 static void bison_rule_pushlevel_ (void);
373 static void delete_block (tree block);
374 static int duplicate_decls (tree newdecl, tree olddecl);
375 static void finish_decl (tree decl, tree init, bool is_top_level);
376 static void finish_function (int nested);
377 static const char *ffe_printable_name (tree decl, int v);
378 static void ffe_print_error_function (diagnostic_context *, const char *);
379 static tree lookup_name_current_level (tree name);
380 static struct f_binding_level *make_binding_level (void);
381 static void pop_f_function_context (void);
382 static void push_f_function_context (void);
383 static void push_parm_decl (tree parm);
384 static tree pushdecl_top_level (tree decl);
385 static int kept_level_p (void);
386 static tree storedecls (tree decls);
387 static void store_parm_decls (int is_main_program);
388 static tree start_decl (tree decl, bool is_top_level);
389 static void start_function (tree name, tree type, int nested, int public);
390 static void ffecom_file_ (const char *name);
391 static void ffecom_close_include_ (FILE *f);
392 static FILE *ffecom_open_include_ (char *name, ffewhereLine l,
393 ffewhereColumn c);
395 /* Static objects accessed by functions in this module. */
397 static ffesymbol ffecom_primary_entry_ = NULL;
398 static ffesymbol ffecom_nested_entry_ = NULL;
399 static ffeinfoKind ffecom_primary_entry_kind_;
400 static bool ffecom_primary_entry_is_proc_;
401 static GTY(()) tree ffecom_outer_function_decl_;
402 static GTY(()) tree ffecom_previous_function_decl_;
403 static GTY(()) tree ffecom_which_entrypoint_decl_;
404 static GTY(()) tree ffecom_float_zero_;
405 static GTY(()) tree ffecom_float_half_;
406 static GTY(()) tree ffecom_double_zero_;
407 static GTY(()) tree ffecom_double_half_;
408 static GTY(()) tree ffecom_func_result_;/* For functions. */
409 static GTY(()) tree ffecom_func_length_;/* For CHARACTER fns. */
410 static ffebld ffecom_list_blockdata_;
411 static ffebld ffecom_list_common_;
412 static ffebld ffecom_master_arglist_;
413 static ffeinfoBasictype ffecom_master_bt_;
414 static ffeinfoKindtype ffecom_master_kt_;
415 static ffetargetCharacterSize ffecom_master_size_;
416 static int ffecom_num_fns_ = 0;
417 static int ffecom_num_entrypoints_ = 0;
418 static bool ffecom_is_altreturning_ = FALSE;
419 static GTY(()) tree ffecom_multi_type_node_;
420 static GTY(()) tree ffecom_multi_retval_;
421 static GTY(()) tree
422 ffecom_multi_fields_[FFEINFO_basictype][FFEINFO_kindtype];
423 static bool ffecom_member_namelisted_; /* _member_phase1_ namelisted? */
424 static bool ffecom_doing_entry_ = FALSE;
425 static bool ffecom_transform_only_dummies_ = FALSE;
426 static int ffecom_typesize_pointer_;
427 static int ffecom_typesize_integer1_;
429 /* Holds pointer-to-function expressions. */
431 static GTY(()) tree ffecom_gfrt_[FFECOM_gfrt];
433 /* Holds the external names of the functions. */
435 static const char *const ffecom_gfrt_name_[FFECOM_gfrt]
438 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) NAME,
439 #include "com-rt.def"
440 #undef DEFGFRT
443 /* Whether the function returns. */
445 static const bool ffecom_gfrt_volatile_[FFECOM_gfrt]
448 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) VOLATILE,
449 #include "com-rt.def"
450 #undef DEFGFRT
453 /* Whether the function returns type complex. */
455 static const bool ffecom_gfrt_complex_[FFECOM_gfrt]
458 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) COMPLEX,
459 #include "com-rt.def"
460 #undef DEFGFRT
463 /* Whether the function is const
464 (i.e., has no side effects and only depends on its arguments). */
466 static const bool ffecom_gfrt_const_[FFECOM_gfrt]
469 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) CONST,
470 #include "com-rt.def"
471 #undef DEFGFRT
474 /* Type code for the function return value. */
476 static const ffecomRttype_ ffecom_gfrt_type_[FFECOM_gfrt]
479 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) TYPE,
480 #include "com-rt.def"
481 #undef DEFGFRT
484 /* String of codes for the function's arguments. */
486 static const char *const ffecom_gfrt_argstring_[FFECOM_gfrt]
489 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) ARGS,
490 #include "com-rt.def"
491 #undef DEFGFRT
494 /* Internal macros. */
496 /* We let tm.h override the types used here, to handle trivial differences
497 such as the choice of unsigned int or long unsigned int for size_t.
498 When machines start needing nontrivial differences in the size type,
499 it would be best to do something here to figure out automatically
500 from other information what type to use. */
502 #ifndef SIZE_TYPE
503 #define SIZE_TYPE "long unsigned int"
504 #endif
506 #define ffecom_concat_list_count_(catlist) ((catlist).count)
507 #define ffecom_concat_list_expr_(catlist,i) ((catlist).exprs[(i)])
508 #define ffecom_concat_list_maxlen_(catlist) ((catlist).maxlen)
509 #define ffecom_concat_list_minlen_(catlist) ((catlist).minlen)
511 #define ffecom_char_args_(i,l,e) ffecom_char_args_x_((i),(l),(e),FALSE)
512 #define ffecom_char_args_with_null_(i,l,e) ffecom_char_args_x_((i),(l),(e),TRUE)
514 /* For each binding contour we allocate a binding_level structure
515 * which records the names defined in that contour.
516 * Contours include:
517 * 0) the global one
518 * 1) one for each function definition,
519 * where internal declarations of the parameters appear.
521 * The current meaning of a name can be found by searching the levels from
522 * the current one out to the global one.
525 /* Note that the information in the `names' component of the global contour
526 is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
528 struct f_binding_level GTY(())
530 /* A chain of _DECL nodes for all variables, constants, functions,
531 and typedef types. These are in the reverse of the order supplied.
533 tree names;
535 /* For each level (except not the global one),
536 a chain of BLOCK nodes for all the levels
537 that were entered and exited one level down. */
538 tree blocks;
540 /* The BLOCK node for this level, if one has been preallocated.
541 If 0, the BLOCK is allocated (if needed) when the level is popped. */
542 tree this_block;
544 /* The binding level which this one is contained in (inherits from). */
545 struct f_binding_level *level_chain;
547 /* 0: no ffecom_prepare_* functions called at this level yet;
548 1: ffecom_prepare* functions called, except not ffecom_prepare_end;
549 2: ffecom_prepare_end called. */
550 int prep_state;
553 #define NULL_BINDING_LEVEL (struct f_binding_level *) NULL
555 /* The binding level currently in effect. */
557 static GTY(()) struct f_binding_level *current_binding_level;
559 /* A chain of binding_level structures awaiting reuse. */
561 static GTY((deletable (""))) struct f_binding_level *free_binding_level;
563 /* The outermost binding level, for names of file scope.
564 This is created when the compiler is started and exists
565 through the entire run. */
567 static struct f_binding_level *global_binding_level;
569 /* Binding level structures are initialized by copying this one. */
571 static const struct f_binding_level clear_binding_level
573 {NULL, NULL, NULL, NULL_BINDING_LEVEL, 0};
575 /* Language-dependent contents of an identifier. */
577 struct lang_identifier GTY(())
579 struct tree_identifier common;
580 tree global_value;
581 tree local_value;
582 tree label_value;
583 bool invented;
586 /* Macros for access to language-specific slots in an identifier. */
587 /* Each of these slots contains a DECL node or null. */
589 /* This represents the value which the identifier has in the
590 file-scope namespace. */
591 #define IDENTIFIER_GLOBAL_VALUE(NODE) \
592 (((struct lang_identifier *)(NODE))->global_value)
593 /* This represents the value which the identifier has in the current
594 scope. */
595 #define IDENTIFIER_LOCAL_VALUE(NODE) \
596 (((struct lang_identifier *)(NODE))->local_value)
597 /* This represents the value which the identifier has as a label in
598 the current label scope. */
599 #define IDENTIFIER_LABEL_VALUE(NODE) \
600 (((struct lang_identifier *)(NODE))->label_value)
601 /* This is nonzero if the identifier was "made up" by g77 code. */
602 #define IDENTIFIER_INVENTED(NODE) \
603 (((struct lang_identifier *)(NODE))->invented)
605 /* The resulting tree type. */
606 union lang_tree_node
607 GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
608 chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
610 union tree_node GTY ((tag ("0"),
611 desc ("tree_node_structure (&%h)")))
612 generic;
613 struct lang_identifier GTY ((tag ("1"))) identifier;
616 /* Fortran doesn't use either of these. */
617 struct lang_decl GTY(())
620 struct lang_type GTY(())
624 /* In identifiers, C uses the following fields in a special way:
625 TREE_PUBLIC to record that there was a previous local extern decl.
626 TREE_USED to record that such a decl was used.
627 TREE_ADDRESSABLE to record that the address of such a decl was used. */
629 /* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
630 that have names. Here so we can clear out their names' definitions
631 at the end of the function. */
633 static GTY(()) tree named_labels;
635 /* A list of LABEL_DECLs from outer contexts that are currently shadowed. */
637 static GTY(()) tree shadowed_labels;
639 /* Return the subscript expression, modified to do range-checking.
641 `array' is the array to be checked against.
642 `element' is the subscript expression to check.
643 `dim' is the dimension number (starting at 0).
644 `total_dims' is the total number of dimensions (0 for CHARACTER substring).
647 static tree
648 ffecom_subscript_check_ (tree array, tree element, int dim, int total_dims,
649 const char *array_name)
651 tree low = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
652 tree high = TYPE_MAX_VALUE (TYPE_DOMAIN (array));
653 tree cond;
654 tree die;
655 tree args;
657 if (element == error_mark_node)
658 return element;
660 if (TREE_TYPE (low) != TREE_TYPE (element))
662 if (TYPE_PRECISION (TREE_TYPE (low))
663 > TYPE_PRECISION (TREE_TYPE (element)))
664 element = convert (TREE_TYPE (low), element);
665 else
667 low = convert (TREE_TYPE (element), low);
668 if (high)
669 high = convert (TREE_TYPE (element), high);
673 element = ffecom_save_tree (element);
674 if (total_dims == 0)
676 /* Special handling for substring range checks. Fortran allows the
677 end subscript < begin subscript, which means that expressions like
678 string(1:0) are valid (and yield a null string). In view of this,
679 enforce two simpler conditions:
680 1) element<=high for end-substring;
681 2) element>=low for start-substring.
682 Run-time character movement will enforce remaining conditions.
684 More complicated checks would be better, but present structure only
685 provides one index element at a time, so it is not possible to
686 enforce a check of both i and j in string(i:j). If it were, the
687 complete set of rules would read,
688 if ( ((j<i) && ((low<=i<=high) || (low<=j<=high))) ||
689 ((low<=i<=high) && (low<=j<=high)) )
690 ok ;
691 else
692 range error ;
694 if (dim)
695 cond = ffecom_2 (LE_EXPR, integer_type_node, element, high);
696 else
697 cond = ffecom_2 (LE_EXPR, integer_type_node, low, element);
699 else
701 /* Array reference substring range checking. */
703 cond = ffecom_2 (LE_EXPR, integer_type_node,
704 low,
705 element);
706 if (high)
708 cond = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
709 cond,
710 ffecom_2 (LE_EXPR, integer_type_node,
711 element,
712 high));
717 int len;
718 char *proc;
719 char *var;
720 tree arg3;
721 tree arg2;
722 tree arg1;
723 tree arg4;
725 switch (total_dims)
727 case 0:
728 var = concat (array_name, "[", (dim ? "end" : "start"),
729 "-substring]", NULL);
730 len = strlen (var) + 1;
731 arg1 = build_string (len, var);
732 free (var);
733 break;
735 case 1:
736 len = strlen (array_name) + 1;
737 arg1 = build_string (len, array_name);
738 break;
740 default:
741 var = xmalloc (strlen (array_name) + 40);
742 sprintf (var, "%s[subscript-%d-of-%d]",
743 array_name,
744 dim + 1, total_dims);
745 len = strlen (var) + 1;
746 arg1 = build_string (len, var);
747 free (var);
748 break;
751 TREE_TYPE (arg1)
752 = build_type_variant (build_array_type (char_type_node,
753 build_range_type
754 (integer_type_node,
755 integer_one_node,
756 build_int_2 (len, 0))),
757 1, 0);
758 TREE_CONSTANT (arg1) = 1;
759 TREE_STATIC (arg1) = 1;
760 arg1 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg1)),
761 arg1);
763 /* s_rnge adds one to the element to print it, so bias against
764 that -- want to print a faithful *subscript* value. */
765 arg2 = convert (ffecom_f2c_ftnint_type_node,
766 ffecom_2 (MINUS_EXPR,
767 TREE_TYPE (element),
768 element,
769 convert (TREE_TYPE (element),
770 integer_one_node)));
772 proc = concat (input_filename, "/",
773 IDENTIFIER_POINTER (DECL_NAME (current_function_decl)),
774 NULL);
775 len = strlen (proc) + 1;
776 arg3 = build_string (len, proc);
778 free (proc);
780 TREE_TYPE (arg3)
781 = build_type_variant (build_array_type (char_type_node,
782 build_range_type
783 (integer_type_node,
784 integer_one_node,
785 build_int_2 (len, 0))),
786 1, 0);
787 TREE_CONSTANT (arg3) = 1;
788 TREE_STATIC (arg3) = 1;
789 arg3 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg3)),
790 arg3);
792 arg4 = convert (ffecom_f2c_ftnint_type_node,
793 build_int_2 (input_line, 0));
795 arg1 = build_tree_list (NULL_TREE, arg1);
796 arg2 = build_tree_list (NULL_TREE, arg2);
797 arg3 = build_tree_list (NULL_TREE, arg3);
798 arg4 = build_tree_list (NULL_TREE, arg4);
799 TREE_CHAIN (arg3) = arg4;
800 TREE_CHAIN (arg2) = arg3;
801 TREE_CHAIN (arg1) = arg2;
803 args = arg1;
805 die = ffecom_call_gfrt (FFECOM_gfrtRANGE,
806 args, NULL_TREE);
807 TREE_SIDE_EFFECTS (die) = 1;
808 die = convert (void_type_node, die);
810 element = ffecom_3 (COND_EXPR,
811 TREE_TYPE (element),
812 cond,
813 element,
814 die);
816 return element;
819 /* Return the computed element of an array reference.
821 `item' is NULL_TREE, or the transformed pointer to the array.
822 `expr' is the original opARRAYREF expression, which is transformed
823 if `item' is NULL_TREE.
824 `want_ptr' is nonzero if a pointer to the element, instead of
825 the element itself, is to be returned. */
827 static tree
828 ffecom_arrayref_ (tree item, ffebld expr, int want_ptr)
830 ffebld dims[FFECOM_dimensionsMAX];
831 int i;
832 int total_dims;
833 int flatten = ffe_is_flatten_arrays ();
834 int need_ptr;
835 tree array;
836 tree element;
837 tree tree_type;
838 tree tree_type_x;
839 const char *array_name;
840 ffetype type;
841 ffebld list;
843 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER)
844 array_name = ffesymbol_text (ffebld_symter (ffebld_left (expr)));
845 else
846 array_name = "[expr?]";
848 /* Build up ARRAY_REFs in reverse order (since we're column major
849 here in Fortran land). */
851 for (i = 0, list = ffebld_right (expr);
852 list != NULL;
853 ++i, list = ffebld_trail (list))
855 dims[i] = ffebld_head (list);
856 type = ffeinfo_type (ffebld_basictype (dims[i]),
857 ffebld_kindtype (dims[i]));
858 if (! flatten
859 && ffecom_typesize_pointer_ > ffecom_typesize_integer1_
860 && ffetype_size (type) > ffecom_typesize_integer1_)
861 /* E.g. ARRAY(INDEX), given INTEGER*8 INDEX, on a system with 64-bit
862 pointers and 32-bit integers. Do the full 64-bit pointer
863 arithmetic, for codes using arrays for nonstandard heap-like
864 work. */
865 flatten = 1;
868 total_dims = i;
870 need_ptr = want_ptr || flatten;
872 if (! item)
874 if (need_ptr)
875 item = ffecom_ptr_to_expr (ffebld_left (expr));
876 else
877 item = ffecom_expr (ffebld_left (expr));
879 if (item == error_mark_node)
880 return item;
882 if (ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereFLEETING
883 && ! ffe_mark_addressable (item))
884 return error_mark_node;
887 if (item == error_mark_node)
888 return item;
890 if (need_ptr)
892 tree min;
894 for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
895 i >= 0;
896 --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
898 min = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
899 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
900 if (flag_bounds_check)
901 element = ffecom_subscript_check_ (array, element, i, total_dims,
902 array_name);
903 if (element == error_mark_node)
904 return element;
906 /* Widen integral arithmetic as desired while preserving
907 signedness. */
908 tree_type = TREE_TYPE (element);
909 tree_type_x = tree_type;
910 if (tree_type
911 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
912 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
913 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
915 if (TREE_TYPE (min) != tree_type_x)
916 min = convert (tree_type_x, min);
917 if (TREE_TYPE (element) != tree_type_x)
918 element = convert (tree_type_x, element);
920 item = ffecom_2 (PLUS_EXPR,
921 build_pointer_type (TREE_TYPE (array)),
922 item,
923 size_binop (MULT_EXPR,
924 size_in_bytes (TREE_TYPE (array)),
925 convert (sizetype,
926 fold (build (MINUS_EXPR,
927 tree_type_x,
928 element, min)))));
930 if (! want_ptr)
932 item = ffecom_1 (INDIRECT_REF,
933 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
934 item);
937 else
939 for (--i;
940 i >= 0;
941 --i)
943 array = TYPE_MAIN_VARIANT (TREE_TYPE (item));
945 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
946 if (flag_bounds_check)
947 element = ffecom_subscript_check_ (array, element, i, total_dims,
948 array_name);
949 if (element == error_mark_node)
950 return element;
952 /* Widen integral arithmetic as desired while preserving
953 signedness. */
954 tree_type = TREE_TYPE (element);
955 tree_type_x = tree_type;
956 if (tree_type
957 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
958 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
959 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
961 element = convert (tree_type_x, element);
963 item = ffecom_2 (ARRAY_REF,
964 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
965 item,
966 element);
970 return item;
973 /* This is like gcc's stabilize_reference -- in fact, most of the code
974 comes from that -- but it handles the situation where the reference
975 is going to have its subparts picked at, and it shouldn't change
976 (or trigger extra invocations of functions in the subtrees) due to
977 this. save_expr is a bit overzealous, because we don't need the
978 entire thing calculated and saved like a temp. So, for DECLs, no
979 change is needed, because these are stable aggregates, and ARRAY_REF
980 and such might well be stable too, but for things like calculations,
981 we do need to calculate a snapshot of a value before picking at it. */
983 static tree
984 ffecom_stabilize_aggregate_ (tree ref)
986 tree result;
987 enum tree_code code = TREE_CODE (ref);
989 switch (code)
991 case VAR_DECL:
992 case PARM_DECL:
993 case RESULT_DECL:
994 /* No action is needed in this case. */
995 return ref;
997 case NOP_EXPR:
998 case CONVERT_EXPR:
999 case FLOAT_EXPR:
1000 case FIX_TRUNC_EXPR:
1001 case FIX_FLOOR_EXPR:
1002 case FIX_ROUND_EXPR:
1003 case FIX_CEIL_EXPR:
1004 result = build_nt (code, stabilize_reference (TREE_OPERAND (ref, 0)));
1005 break;
1007 case INDIRECT_REF:
1008 result = build_nt (INDIRECT_REF,
1009 stabilize_reference_1 (TREE_OPERAND (ref, 0)));
1010 break;
1012 case COMPONENT_REF:
1013 result = build_nt (COMPONENT_REF,
1014 stabilize_reference (TREE_OPERAND (ref, 0)),
1015 TREE_OPERAND (ref, 1));
1016 break;
1018 case BIT_FIELD_REF:
1019 result = build_nt (BIT_FIELD_REF,
1020 stabilize_reference (TREE_OPERAND (ref, 0)),
1021 stabilize_reference_1 (TREE_OPERAND (ref, 1)),
1022 stabilize_reference_1 (TREE_OPERAND (ref, 2)));
1023 break;
1025 case ARRAY_REF:
1026 result = build_nt (ARRAY_REF,
1027 stabilize_reference (TREE_OPERAND (ref, 0)),
1028 stabilize_reference_1 (TREE_OPERAND (ref, 1)));
1029 break;
1031 case COMPOUND_EXPR:
1032 result = build_nt (COMPOUND_EXPR,
1033 stabilize_reference_1 (TREE_OPERAND (ref, 0)),
1034 stabilize_reference (TREE_OPERAND (ref, 1)));
1035 break;
1037 case RTL_EXPR:
1038 abort ();
1041 default:
1042 return save_expr (ref);
1044 case ERROR_MARK:
1045 return error_mark_node;
1048 TREE_TYPE (result) = TREE_TYPE (ref);
1049 TREE_READONLY (result) = TREE_READONLY (ref);
1050 TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (ref);
1051 TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (ref);
1053 return result;
1056 /* A rip-off of gcc's convert.c convert_to_complex function,
1057 reworked to handle complex implemented as C structures
1058 (RECORD_TYPE with two fields, real and imaginary `r' and `i'). */
1060 static tree
1061 ffecom_convert_to_complex_ (tree type, tree expr)
1063 register enum tree_code form = TREE_CODE (TREE_TYPE (expr));
1064 tree subtype;
1066 assert (TREE_CODE (type) == RECORD_TYPE);
1068 subtype = TREE_TYPE (TYPE_FIELDS (type));
1070 if (form == REAL_TYPE || form == INTEGER_TYPE || form == ENUMERAL_TYPE)
1072 expr = convert (subtype, expr);
1073 return ffecom_2 (COMPLEX_EXPR, type, expr,
1074 convert (subtype, integer_zero_node));
1077 if (form == RECORD_TYPE)
1079 tree elt_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr)));
1080 if (TYPE_MAIN_VARIANT (elt_type) == TYPE_MAIN_VARIANT (subtype))
1081 return expr;
1082 else
1084 expr = save_expr (expr);
1085 return ffecom_2 (COMPLEX_EXPR,
1086 type,
1087 convert (subtype,
1088 ffecom_1 (REALPART_EXPR,
1089 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1090 expr)),
1091 convert (subtype,
1092 ffecom_1 (IMAGPART_EXPR,
1093 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1094 expr)));
1098 if (form == POINTER_TYPE || form == REFERENCE_TYPE)
1099 error ("pointer value used where a complex was expected");
1100 else
1101 error ("aggregate value used where a complex was expected");
1103 return ffecom_2 (COMPLEX_EXPR, type,
1104 convert (subtype, integer_zero_node),
1105 convert (subtype, integer_zero_node));
1108 /* Like gcc's convert(), but crashes if widening might happen. */
1110 static tree
1111 ffecom_convert_narrow_ (tree type, tree expr)
1113 register tree e = expr;
1114 register enum tree_code code = TREE_CODE (type);
1116 if (type == TREE_TYPE (e)
1117 || TREE_CODE (e) == ERROR_MARK)
1118 return e;
1119 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1120 return fold (build1 (NOP_EXPR, type, e));
1121 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1122 || code == ERROR_MARK)
1123 return error_mark_node;
1124 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1126 assert ("void value not ignored as it ought to be" == NULL);
1127 return error_mark_node;
1129 assert (code != VOID_TYPE);
1130 if ((code != RECORD_TYPE)
1131 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1132 assert ("converting COMPLEX to REAL" == NULL);
1133 assert (code != ENUMERAL_TYPE);
1134 if (code == INTEGER_TYPE)
1136 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1137 && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)))
1138 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1139 && (TYPE_PRECISION (type)
1140 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
1141 return fold (convert_to_integer (type, e));
1143 if (code == POINTER_TYPE)
1145 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1146 return fold (convert_to_pointer (type, e));
1148 if (code == REAL_TYPE)
1150 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1151 assert (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)));
1152 return fold (convert_to_real (type, e));
1154 if (code == COMPLEX_TYPE)
1156 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1157 assert (TYPE_PRECISION (TREE_TYPE (type)) <= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1158 return fold (convert_to_complex (type, e));
1160 if (code == RECORD_TYPE)
1162 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
1163 /* Check that at least the first field name agrees. */
1164 assert (DECL_NAME (TYPE_FIELDS (type))
1165 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
1166 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1167 <= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
1168 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1169 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1170 return e;
1171 return fold (ffecom_convert_to_complex_ (type, e));
1174 assert ("conversion to non-scalar type requested" == NULL);
1175 return error_mark_node;
1178 /* Like gcc's convert(), but crashes if narrowing might happen. */
1180 static tree
1181 ffecom_convert_widen_ (tree type, tree expr)
1183 register tree e = expr;
1184 register enum tree_code code = TREE_CODE (type);
1186 if (type == TREE_TYPE (e)
1187 || TREE_CODE (e) == ERROR_MARK)
1188 return e;
1189 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1190 return fold (build1 (NOP_EXPR, type, e));
1191 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1192 || code == ERROR_MARK)
1193 return error_mark_node;
1194 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1196 assert ("void value not ignored as it ought to be" == NULL);
1197 return error_mark_node;
1199 assert (code != VOID_TYPE);
1200 if ((code != RECORD_TYPE)
1201 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1202 assert ("narrowing COMPLEX to REAL" == NULL);
1203 assert (code != ENUMERAL_TYPE);
1204 if (code == INTEGER_TYPE)
1206 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1207 && TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)))
1208 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1209 && (TYPE_PRECISION (type)
1210 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
1211 return fold (convert_to_integer (type, e));
1213 if (code == POINTER_TYPE)
1215 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1216 return fold (convert_to_pointer (type, e));
1218 if (code == REAL_TYPE)
1220 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1221 assert (TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)));
1222 return fold (convert_to_real (type, e));
1224 if (code == COMPLEX_TYPE)
1226 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1227 assert (TYPE_PRECISION (TREE_TYPE (type)) >= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1228 return fold (convert_to_complex (type, e));
1230 if (code == RECORD_TYPE)
1232 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
1233 /* Check that at least the first field name agrees. */
1234 assert (DECL_NAME (TYPE_FIELDS (type))
1235 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
1236 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1237 >= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
1238 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1239 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1240 return e;
1241 return fold (ffecom_convert_to_complex_ (type, e));
1244 assert ("conversion to non-scalar type requested" == NULL);
1245 return error_mark_node;
1248 /* Handles making a COMPLEX type, either the standard
1249 (but buggy?) gbe way, or the safer (but less elegant?)
1250 f2c way. */
1252 static tree
1253 ffecom_make_complex_type_ (tree subtype)
1255 tree type;
1256 tree realfield;
1257 tree imagfield;
1259 if (ffe_is_emulate_complex ())
1261 type = make_node (RECORD_TYPE);
1262 realfield = ffecom_decl_field (type, NULL_TREE, "r", subtype);
1263 imagfield = ffecom_decl_field (type, realfield, "i", subtype);
1264 TYPE_FIELDS (type) = realfield;
1265 layout_type (type);
1267 else
1269 type = make_node (COMPLEX_TYPE);
1270 TREE_TYPE (type) = subtype;
1271 layout_type (type);
1274 return type;
1277 /* Chooses either the gbe or the f2c way to build a
1278 complex constant. */
1280 static tree
1281 ffecom_build_complex_constant_ (tree type, tree realpart, tree imagpart)
1283 tree bothparts;
1285 if (ffe_is_emulate_complex ())
1287 bothparts = build_tree_list (TYPE_FIELDS (type), realpart);
1288 TREE_CHAIN (bothparts) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), imagpart);
1289 bothparts = build_constructor (type, bothparts);
1291 else
1293 bothparts = build_complex (type, realpart, imagpart);
1296 return bothparts;
1299 static tree
1300 ffecom_arglist_expr_ (const char *c, ffebld expr)
1302 tree list;
1303 tree *plist = &list;
1304 tree trail = NULL_TREE; /* Append char length args here. */
1305 tree *ptrail = &trail;
1306 tree length;
1307 ffebld exprh;
1308 tree item;
1309 bool ptr = FALSE;
1310 tree wanted = NULL_TREE;
1311 static const char zed[] = "0";
1313 if (c == NULL)
1314 c = &zed[0];
1316 while (expr != NULL)
1318 if (*c != '\0')
1320 ptr = FALSE;
1321 if (*c == '&')
1323 ptr = TRUE;
1324 ++c;
1326 switch (*(c++))
1328 case '\0':
1329 ptr = TRUE;
1330 wanted = NULL_TREE;
1331 break;
1333 case 'a':
1334 assert (ptr);
1335 wanted = NULL_TREE;
1336 break;
1338 case 'c':
1339 wanted = ffecom_f2c_complex_type_node;
1340 break;
1342 case 'd':
1343 wanted = ffecom_f2c_doublereal_type_node;
1344 break;
1346 case 'e':
1347 wanted = ffecom_f2c_doublecomplex_type_node;
1348 break;
1350 case 'f':
1351 wanted = ffecom_f2c_real_type_node;
1352 break;
1354 case 'i':
1355 wanted = ffecom_f2c_integer_type_node;
1356 break;
1358 case 'j':
1359 wanted = ffecom_f2c_longint_type_node;
1360 break;
1362 default:
1363 assert ("bad argstring code" == NULL);
1364 wanted = NULL_TREE;
1365 break;
1369 exprh = ffebld_head (expr);
1370 if (exprh == NULL)
1371 wanted = NULL_TREE;
1373 if ((wanted == NULL_TREE)
1374 || (ptr
1375 && (TYPE_MODE
1376 (ffecom_tree_type[ffeinfo_basictype (ffebld_info (exprh))]
1377 [ffeinfo_kindtype (ffebld_info (exprh))])
1378 == TYPE_MODE (wanted))))
1379 *plist
1380 = build_tree_list (NULL_TREE,
1381 ffecom_arg_ptr_to_expr (exprh,
1382 &length));
1383 else
1385 item = ffecom_arg_expr (exprh, &length);
1386 item = ffecom_convert_widen_ (wanted, item);
1387 if (ptr)
1389 item = ffecom_1 (ADDR_EXPR,
1390 build_pointer_type (TREE_TYPE (item)),
1391 item);
1393 *plist
1394 = build_tree_list (NULL_TREE,
1395 item);
1398 plist = &TREE_CHAIN (*plist);
1399 expr = ffebld_trail (expr);
1400 if (length != NULL_TREE)
1402 *ptrail = build_tree_list (NULL_TREE, length);
1403 ptrail = &TREE_CHAIN (*ptrail);
1407 /* We've run out of args in the call; if the implementation expects
1408 more, supply null pointers for them, which the implementation can
1409 check to see if an arg was omitted. */
1411 while (*c != '\0' && *c != '0')
1413 if (*c == '&')
1414 ++c;
1415 else
1416 assert ("missing arg to run-time routine!" == NULL);
1418 switch (*(c++))
1420 case '\0':
1421 case 'a':
1422 case 'c':
1423 case 'd':
1424 case 'e':
1425 case 'f':
1426 case 'i':
1427 case 'j':
1428 break;
1430 default:
1431 assert ("bad arg string code" == NULL);
1432 break;
1434 *plist
1435 = build_tree_list (NULL_TREE,
1436 null_pointer_node);
1437 plist = &TREE_CHAIN (*plist);
1440 *plist = trail;
1442 return list;
1445 static tree
1446 ffecom_widest_expr_type_ (ffebld list)
1448 ffebld item;
1449 ffebld widest = NULL;
1450 ffetype type;
1451 ffetype widest_type = NULL;
1452 tree t;
1454 for (; list != NULL; list = ffebld_trail (list))
1456 item = ffebld_head (list);
1457 if (item == NULL)
1458 continue;
1459 if ((widest != NULL)
1460 && (ffeinfo_basictype (ffebld_info (item))
1461 != ffeinfo_basictype (ffebld_info (widest))))
1462 continue;
1463 type = ffeinfo_type (ffeinfo_basictype (ffebld_info (item)),
1464 ffeinfo_kindtype (ffebld_info (item)));
1465 if ((widest == FFEINFO_kindtypeNONE)
1466 || (ffetype_size (type)
1467 > ffetype_size (widest_type)))
1469 widest = item;
1470 widest_type = type;
1474 assert (widest != NULL);
1475 t = ffecom_tree_type[ffeinfo_basictype (ffebld_info (widest))]
1476 [ffeinfo_kindtype (ffebld_info (widest))];
1477 assert (t != NULL_TREE);
1478 return t;
1481 /* Check whether a partial overlap between two expressions is possible.
1483 Can *starting* to write a portion of expr1 change the value
1484 computed (perhaps already, *partially*) by expr2?
1486 Currently, this is a concern only for a COMPLEX expr1. But if it
1487 isn't in COMMON or local EQUIVALENCE, since we don't support
1488 aliasing of arguments, it isn't a concern. */
1490 static bool
1491 ffecom_possible_partial_overlap_ (ffebld expr1, ffebld expr2 ATTRIBUTE_UNUSED)
1493 ffesymbol sym;
1494 ffestorag st;
1496 switch (ffebld_op (expr1))
1498 case FFEBLD_opSYMTER:
1499 sym = ffebld_symter (expr1);
1500 break;
1502 case FFEBLD_opARRAYREF:
1503 if (ffebld_op (ffebld_left (expr1)) != FFEBLD_opSYMTER)
1504 return FALSE;
1505 sym = ffebld_symter (ffebld_left (expr1));
1506 break;
1508 default:
1509 return FALSE;
1512 if (ffesymbol_where (sym) != FFEINFO_whereCOMMON
1513 && (ffesymbol_where (sym) != FFEINFO_whereLOCAL
1514 || ! (st = ffesymbol_storage (sym))
1515 || ! ffestorag_parent (st)))
1516 return FALSE;
1518 /* It's in COMMON or local EQUIVALENCE. */
1520 return TRUE;
1523 /* Check whether dest and source might overlap. ffebld versions of these
1524 might or might not be passed, will be NULL if not.
1526 The test is really whether source_tree is modifiable and, if modified,
1527 might overlap destination such that the value(s) in the destination might
1528 change before it is finally modified. dest_* are the canonized
1529 destination itself. */
1531 static bool
1532 ffecom_overlap_ (tree dest_decl, tree dest_offset, tree dest_size,
1533 tree source_tree, ffebld source UNUSED, bool scalar_arg)
1535 tree source_decl;
1536 tree source_offset;
1537 tree source_size;
1538 tree t;
1540 if (source_tree == NULL_TREE)
1541 return FALSE;
1543 switch (TREE_CODE (source_tree))
1545 case ERROR_MARK:
1546 case IDENTIFIER_NODE:
1547 case INTEGER_CST:
1548 case REAL_CST:
1549 case COMPLEX_CST:
1550 case STRING_CST:
1551 case CONST_DECL:
1552 case VAR_DECL:
1553 case RESULT_DECL:
1554 case FIELD_DECL:
1555 case MINUS_EXPR:
1556 case MULT_EXPR:
1557 case TRUNC_DIV_EXPR:
1558 case CEIL_DIV_EXPR:
1559 case FLOOR_DIV_EXPR:
1560 case ROUND_DIV_EXPR:
1561 case TRUNC_MOD_EXPR:
1562 case CEIL_MOD_EXPR:
1563 case FLOOR_MOD_EXPR:
1564 case ROUND_MOD_EXPR:
1565 case RDIV_EXPR:
1566 case EXACT_DIV_EXPR:
1567 case FIX_TRUNC_EXPR:
1568 case FIX_CEIL_EXPR:
1569 case FIX_FLOOR_EXPR:
1570 case FIX_ROUND_EXPR:
1571 case FLOAT_EXPR:
1572 case NEGATE_EXPR:
1573 case MIN_EXPR:
1574 case MAX_EXPR:
1575 case ABS_EXPR:
1576 case LSHIFT_EXPR:
1577 case RSHIFT_EXPR:
1578 case LROTATE_EXPR:
1579 case RROTATE_EXPR:
1580 case BIT_IOR_EXPR:
1581 case BIT_XOR_EXPR:
1582 case BIT_AND_EXPR:
1583 case BIT_NOT_EXPR:
1584 case TRUTH_ANDIF_EXPR:
1585 case TRUTH_ORIF_EXPR:
1586 case TRUTH_AND_EXPR:
1587 case TRUTH_OR_EXPR:
1588 case TRUTH_XOR_EXPR:
1589 case TRUTH_NOT_EXPR:
1590 case LT_EXPR:
1591 case LE_EXPR:
1592 case GT_EXPR:
1593 case GE_EXPR:
1594 case EQ_EXPR:
1595 case NE_EXPR:
1596 case COMPLEX_EXPR:
1597 case CONJ_EXPR:
1598 case REALPART_EXPR:
1599 case IMAGPART_EXPR:
1600 case LABEL_EXPR:
1601 case COMPONENT_REF:
1602 return FALSE;
1604 case COMPOUND_EXPR:
1605 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1606 TREE_OPERAND (source_tree, 1), NULL,
1607 scalar_arg);
1609 case MODIFY_EXPR:
1610 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1611 TREE_OPERAND (source_tree, 0), NULL,
1612 scalar_arg);
1614 case CONVERT_EXPR:
1615 case NOP_EXPR:
1616 case NON_LVALUE_EXPR:
1617 case PLUS_EXPR:
1618 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1619 return TRUE;
1621 ffecom_tree_canonize_ptr_ (&source_decl, &source_offset,
1622 source_tree);
1623 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1624 break;
1626 case COND_EXPR:
1627 return
1628 ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1629 TREE_OPERAND (source_tree, 1), NULL,
1630 scalar_arg)
1631 || ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1632 TREE_OPERAND (source_tree, 2), NULL,
1633 scalar_arg);
1636 case ADDR_EXPR:
1637 ffecom_tree_canonize_ref_ (&source_decl, &source_offset,
1638 &source_size,
1639 TREE_OPERAND (source_tree, 0));
1640 break;
1642 case PARM_DECL:
1643 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1644 return TRUE;
1646 source_decl = source_tree;
1647 source_offset = bitsize_zero_node;
1648 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1649 break;
1651 case SAVE_EXPR:
1652 case REFERENCE_EXPR:
1653 case PREDECREMENT_EXPR:
1654 case PREINCREMENT_EXPR:
1655 case POSTDECREMENT_EXPR:
1656 case POSTINCREMENT_EXPR:
1657 case INDIRECT_REF:
1658 case ARRAY_REF:
1659 case CALL_EXPR:
1660 default:
1661 return TRUE;
1664 /* Come here when source_decl, source_offset, and source_size filled
1665 in appropriately. */
1667 if (source_decl == NULL_TREE)
1668 return FALSE; /* No decl involved, so no overlap. */
1670 if (source_decl != dest_decl)
1671 return FALSE; /* Different decl, no overlap. */
1673 if (TREE_CODE (dest_size) == ERROR_MARK)
1674 return TRUE; /* Assignment into entire assumed-size
1675 array? Shouldn't happen.... */
1677 t = ffecom_2 (LE_EXPR, integer_type_node,
1678 ffecom_2 (PLUS_EXPR, TREE_TYPE (dest_offset),
1679 dest_offset,
1680 convert (TREE_TYPE (dest_offset),
1681 dest_size)),
1682 convert (TREE_TYPE (dest_offset),
1683 source_offset));
1685 if (integer_onep (t))
1686 return FALSE; /* Destination precedes source. */
1688 if (!scalar_arg
1689 || (source_size == NULL_TREE)
1690 || (TREE_CODE (source_size) == ERROR_MARK)
1691 || integer_zerop (source_size))
1692 return TRUE; /* No way to tell if dest follows source. */
1694 t = ffecom_2 (LE_EXPR, integer_type_node,
1695 ffecom_2 (PLUS_EXPR, TREE_TYPE (source_offset),
1696 source_offset,
1697 convert (TREE_TYPE (source_offset),
1698 source_size)),
1699 convert (TREE_TYPE (source_offset),
1700 dest_offset));
1702 if (integer_onep (t))
1703 return FALSE; /* Destination follows source. */
1705 return TRUE; /* Destination and source overlap. */
1708 /* Check whether dest might overlap any of a list of arguments or is
1709 in a COMMON area the callee might know about (and thus modify). */
1711 static bool
1712 ffecom_args_overlapping_ (tree dest_tree, ffebld dest UNUSED, tree args,
1713 tree callee_commons, bool scalar_args)
1715 tree arg;
1716 tree dest_decl;
1717 tree dest_offset;
1718 tree dest_size;
1720 ffecom_tree_canonize_ref_ (&dest_decl, &dest_offset, &dest_size,
1721 dest_tree);
1723 if (dest_decl == NULL_TREE)
1724 return FALSE; /* Seems unlikely! */
1726 /* If the decl cannot be determined reliably, or if its in COMMON
1727 and the callee isn't known to not futz with COMMON via other
1728 means, overlap might happen. */
1730 if ((TREE_CODE (dest_decl) == ERROR_MARK)
1731 || ((callee_commons != NULL_TREE)
1732 && TREE_PUBLIC (dest_decl)))
1733 return TRUE;
1735 for (; args != NULL_TREE; args = TREE_CHAIN (args))
1737 if (((arg = TREE_VALUE (args)) != NULL_TREE)
1738 && ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1739 arg, NULL, scalar_args))
1740 return TRUE;
1743 return FALSE;
1746 /* Build a string for a variable name as used by NAMELIST. This means that
1747 if we're using the f2c library, we build an uppercase string, since
1748 f2c does this. */
1750 static tree
1751 ffecom_build_f2c_string_ (int i, const char *s)
1753 if (!ffe_is_f2c_library ())
1754 return build_string (i, s);
1757 char *tmp;
1758 const char *p;
1759 char *q;
1760 char space[34];
1761 tree t;
1763 if (((size_t) i) > ARRAY_SIZE (space))
1764 tmp = malloc_new_ks (malloc_pool_image (), "f2c_string", i);
1765 else
1766 tmp = &space[0];
1768 for (p = s, q = tmp; *p != '\0'; ++p, ++q)
1769 *q = TOUPPER (*p);
1770 *q = '\0';
1772 t = build_string (i, tmp);
1774 if (((size_t) i) > ARRAY_SIZE (space))
1775 malloc_kill_ks (malloc_pool_image (), tmp, i);
1777 return t;
1781 /* Returns CALL_EXPR or equivalent with given type (pass NULL_TREE for
1782 type to just get whatever the function returns), handling the
1783 f2c value-returning convention, if required, by prepending
1784 to the arglist a pointer to a temporary to receive the return value. */
1786 static tree
1787 ffecom_call_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex, tree type,
1788 tree args, tree dest_tree, ffebld dest, bool *dest_used,
1789 tree callee_commons, bool scalar_args, tree hook)
1791 tree item;
1792 tree tempvar;
1794 if (dest_used != NULL)
1795 *dest_used = FALSE;
1797 if (is_f2c_complex)
1799 if ((dest_used == NULL)
1800 || (dest == NULL)
1801 || (ffeinfo_basictype (ffebld_info (dest))
1802 != FFEINFO_basictypeCOMPLEX)
1803 || (ffeinfo_kindtype (ffebld_info (dest)) != kt)
1804 || ((type != NULL_TREE) && (TREE_TYPE (dest_tree) != type))
1805 || ffecom_args_overlapping_ (dest_tree, dest, args,
1806 callee_commons,
1807 scalar_args))
1809 tempvar = hook;
1810 assert (tempvar);
1812 else
1814 *dest_used = TRUE;
1815 tempvar = dest_tree;
1816 type = NULL_TREE;
1819 item
1820 = build_tree_list (NULL_TREE,
1821 ffecom_1 (ADDR_EXPR,
1822 build_pointer_type (TREE_TYPE (tempvar)),
1823 tempvar));
1824 TREE_CHAIN (item) = args;
1826 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1827 item, NULL_TREE);
1829 if (tempvar != dest_tree)
1830 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item, tempvar);
1832 else
1833 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1834 args, NULL_TREE);
1836 if ((type != NULL_TREE) && (TREE_TYPE (item) != type))
1837 item = ffecom_convert_narrow_ (type, item);
1839 return item;
1842 /* Given two arguments, transform them and make a call to the given
1843 function via ffecom_call_. */
1845 static tree
1846 ffecom_call_binop_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1847 tree type, ffebld left, ffebld right, tree dest_tree,
1848 ffebld dest, bool *dest_used, tree callee_commons,
1849 bool scalar_args, bool ref, tree hook)
1851 tree left_tree;
1852 tree right_tree;
1853 tree left_length;
1854 tree right_length;
1856 if (ref)
1858 /* Pass arguments by reference. */
1859 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
1860 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
1862 else
1864 /* Pass arguments by value. */
1865 left_tree = ffecom_arg_expr (left, &left_length);
1866 right_tree = ffecom_arg_expr (right, &right_length);
1870 left_tree = build_tree_list (NULL_TREE, left_tree);
1871 right_tree = build_tree_list (NULL_TREE, right_tree);
1872 TREE_CHAIN (left_tree) = right_tree;
1874 if (left_length != NULL_TREE)
1876 left_length = build_tree_list (NULL_TREE, left_length);
1877 TREE_CHAIN (right_tree) = left_length;
1880 if (right_length != NULL_TREE)
1882 right_length = build_tree_list (NULL_TREE, right_length);
1883 if (left_length != NULL_TREE)
1884 TREE_CHAIN (left_length) = right_length;
1885 else
1886 TREE_CHAIN (right_tree) = right_length;
1889 return ffecom_call_ (fn, kt, is_f2c_complex, type, left_tree,
1890 dest_tree, dest, dest_used, callee_commons,
1891 scalar_args, hook);
1894 /* Return ptr/length args for char subexpression
1896 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
1897 subexpressions by constructing the appropriate trees for the ptr-to-
1898 character-text and length-of-character-text arguments in a calling
1899 sequence.
1901 Note that if with_null is TRUE, and the expression is an opCONTER,
1902 a null byte is appended to the string. */
1904 static void
1905 ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
1907 tree item;
1908 tree high;
1909 ffetargetCharacter1 val;
1910 ffetargetCharacterSize newlen;
1912 switch (ffebld_op (expr))
1914 case FFEBLD_opCONTER:
1915 val = ffebld_constant_character1 (ffebld_conter (expr));
1916 newlen = ffetarget_length_character1 (val);
1917 if (with_null)
1919 /* Begin FFETARGET-NULL-KLUDGE. */
1920 if (newlen != 0)
1921 ++newlen;
1923 *length = build_int_2 (newlen, 0);
1924 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
1925 high = build_int_2 (newlen, 0);
1926 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
1927 item = build_string (newlen,
1928 ffetarget_text_character1 (val));
1929 /* End FFETARGET-NULL-KLUDGE. */
1930 TREE_TYPE (item)
1931 = build_type_variant
1932 (build_array_type
1933 (char_type_node,
1934 build_range_type
1935 (ffecom_f2c_ftnlen_type_node,
1936 ffecom_f2c_ftnlen_one_node,
1937 high)),
1938 1, 0);
1939 TREE_CONSTANT (item) = 1;
1940 TREE_STATIC (item) = 1;
1941 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
1942 item);
1943 break;
1945 case FFEBLD_opSYMTER:
1947 ffesymbol s = ffebld_symter (expr);
1949 item = ffesymbol_hook (s).decl_tree;
1950 if (item == NULL_TREE)
1952 s = ffecom_sym_transform_ (s);
1953 item = ffesymbol_hook (s).decl_tree;
1955 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
1957 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
1958 *length = ffesymbol_hook (s).length_tree;
1959 else
1961 *length = build_int_2 (ffesymbol_size (s), 0);
1962 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
1965 else if (item == error_mark_node)
1966 *length = error_mark_node;
1967 else
1968 /* FFEINFO_kindFUNCTION. */
1969 *length = NULL_TREE;
1970 if (!ffesymbol_hook (s).addr
1971 && (item != error_mark_node))
1972 item = ffecom_1 (ADDR_EXPR,
1973 build_pointer_type (TREE_TYPE (item)),
1974 item);
1976 break;
1978 case FFEBLD_opARRAYREF:
1980 ffecom_char_args_ (&item, length, ffebld_left (expr));
1982 if (item == error_mark_node || *length == error_mark_node)
1984 item = *length = error_mark_node;
1985 break;
1988 item = ffecom_arrayref_ (item, expr, 1);
1990 break;
1992 case FFEBLD_opSUBSTR:
1994 ffebld start;
1995 ffebld end;
1996 ffebld thing = ffebld_right (expr);
1997 tree start_tree;
1998 tree end_tree;
1999 const char *char_name;
2000 ffebld left_symter;
2001 tree array;
2003 assert (ffebld_op (thing) == FFEBLD_opITEM);
2004 start = ffebld_head (thing);
2005 thing = ffebld_trail (thing);
2006 assert (ffebld_trail (thing) == NULL);
2007 end = ffebld_head (thing);
2009 /* Determine name for pretty-printing range-check errors. */
2010 for (left_symter = ffebld_left (expr);
2011 left_symter && ffebld_op (left_symter) == FFEBLD_opARRAYREF;
2012 left_symter = ffebld_left (left_symter))
2014 if (ffebld_op (left_symter) == FFEBLD_opSYMTER)
2015 char_name = ffesymbol_text (ffebld_symter (left_symter));
2016 else
2017 char_name = "[expr?]";
2019 ffecom_char_args_ (&item, length, ffebld_left (expr));
2021 if (item == error_mark_node || *length == error_mark_node)
2023 item = *length = error_mark_node;
2024 break;
2027 array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
2029 /* ~~~~Handle INTEGER*8 start/end, a la FFEBLD_opARRAYREF. */
2031 if (start == NULL)
2033 if (end == NULL)
2035 else
2037 end_tree = ffecom_expr (end);
2038 if (flag_bounds_check)
2039 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2040 char_name);
2041 end_tree = convert (ffecom_f2c_ftnlen_type_node,
2042 end_tree);
2044 if (end_tree == error_mark_node)
2046 item = *length = error_mark_node;
2047 break;
2050 *length = end_tree;
2053 else
2055 start_tree = ffecom_expr (start);
2056 if (flag_bounds_check)
2057 start_tree = ffecom_subscript_check_ (array, start_tree, 0, 0,
2058 char_name);
2059 start_tree = convert (ffecom_f2c_ftnlen_type_node,
2060 start_tree);
2062 if (start_tree == error_mark_node)
2064 item = *length = error_mark_node;
2065 break;
2068 start_tree = ffecom_save_tree (start_tree);
2070 item = ffecom_2 (PLUS_EXPR, TREE_TYPE (item),
2071 item,
2072 ffecom_2 (MINUS_EXPR,
2073 TREE_TYPE (start_tree),
2074 start_tree,
2075 ffecom_f2c_ftnlen_one_node));
2077 if (end == NULL)
2079 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2080 ffecom_f2c_ftnlen_one_node,
2081 ffecom_2 (MINUS_EXPR,
2082 ffecom_f2c_ftnlen_type_node,
2083 *length,
2084 start_tree));
2086 else
2088 end_tree = ffecom_expr (end);
2089 if (flag_bounds_check)
2090 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2091 char_name);
2092 end_tree = convert (ffecom_f2c_ftnlen_type_node,
2093 end_tree);
2095 if (end_tree == error_mark_node)
2097 item = *length = error_mark_node;
2098 break;
2101 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2102 ffecom_f2c_ftnlen_one_node,
2103 ffecom_2 (MINUS_EXPR,
2104 ffecom_f2c_ftnlen_type_node,
2105 end_tree, start_tree));
2109 break;
2111 case FFEBLD_opFUNCREF:
2113 ffesymbol s = ffebld_symter (ffebld_left (expr));
2114 tree tempvar;
2115 tree args;
2116 ffetargetCharacterSize size = ffeinfo_size (ffebld_info (expr));
2117 ffecomGfrt ix;
2119 if (size == FFETARGET_charactersizeNONE)
2120 /* ~~Kludge alert! This should someday be fixed. */
2121 size = 24;
2123 *length = build_int_2 (size, 0);
2124 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2126 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
2127 == FFEINFO_whereINTRINSIC)
2129 if (size == 1)
2131 /* Invocation of an intrinsic returning CHARACTER*1. */
2132 item = ffecom_expr_intrinsic_ (expr, NULL_TREE,
2133 NULL, NULL);
2134 break;
2136 ix = ffeintrin_gfrt_direct (ffebld_symter_implementation (ffebld_left (expr)));
2137 assert (ix != FFECOM_gfrt);
2138 item = ffecom_gfrt_tree_ (ix);
2140 else
2142 ix = FFECOM_gfrt;
2143 item = ffesymbol_hook (s).decl_tree;
2144 if (item == NULL_TREE)
2146 s = ffecom_sym_transform_ (s);
2147 item = ffesymbol_hook (s).decl_tree;
2149 if (item == error_mark_node)
2151 item = *length = error_mark_node;
2152 break;
2155 if (!ffesymbol_hook (s).addr)
2156 item = ffecom_1_fn (item);
2158 tempvar = ffebld_nonter_hook (expr);
2159 assert (tempvar);
2160 tempvar = ffecom_1 (ADDR_EXPR,
2161 build_pointer_type (TREE_TYPE (tempvar)),
2162 tempvar);
2164 args = build_tree_list (NULL_TREE, tempvar);
2166 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT) /* Sfunc args by value. */
2167 TREE_CHAIN (args) = ffecom_list_expr (ffebld_right (expr));
2168 else
2170 TREE_CHAIN (args) = build_tree_list (NULL_TREE, *length);
2171 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
2173 TREE_CHAIN (TREE_CHAIN (args))
2174 = ffecom_arglist_expr_ (ffecom_gfrt_args_ (ix),
2175 ffebld_right (expr));
2177 else
2179 TREE_CHAIN (TREE_CHAIN (args))
2180 = ffecom_list_ptr_to_expr (ffebld_right (expr));
2184 item = ffecom_3s (CALL_EXPR,
2185 TREE_TYPE (TREE_TYPE (TREE_TYPE (item))),
2186 item, args, NULL_TREE);
2187 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item,
2188 tempvar);
2190 break;
2192 case FFEBLD_opCONVERT:
2194 ffecom_char_args_ (&item, length, ffebld_left (expr));
2196 if (item == error_mark_node || *length == error_mark_node)
2198 item = *length = error_mark_node;
2199 break;
2202 if ((ffebld_size_known (ffebld_left (expr))
2203 == FFETARGET_charactersizeNONE)
2204 || (ffebld_size_known (ffebld_left (expr)) < (ffebld_size (expr))))
2205 { /* Possible blank-padding needed, copy into
2206 temporary. */
2207 tree tempvar;
2208 tree args;
2209 tree newlen;
2211 tempvar = ffebld_nonter_hook (expr);
2212 assert (tempvar);
2213 tempvar = ffecom_1 (ADDR_EXPR,
2214 build_pointer_type (TREE_TYPE (tempvar)),
2215 tempvar);
2217 newlen = build_int_2 (ffebld_size (expr), 0);
2218 TREE_TYPE (newlen) = ffecom_f2c_ftnlen_type_node;
2220 args = build_tree_list (NULL_TREE, tempvar);
2221 TREE_CHAIN (args) = build_tree_list (NULL_TREE, item);
2222 TREE_CHAIN (TREE_CHAIN (args)) = build_tree_list (NULL_TREE, newlen);
2223 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (args)))
2224 = build_tree_list (NULL_TREE, *length);
2226 item = ffecom_call_gfrt (FFECOM_gfrtCOPY, args, NULL_TREE);
2227 TREE_SIDE_EFFECTS (item) = 1;
2228 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), fold (item),
2229 tempvar);
2230 *length = newlen;
2232 else
2233 { /* Just truncate the length. */
2234 *length = build_int_2 (ffebld_size (expr), 0);
2235 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2237 break;
2239 default:
2240 assert ("bad op for single char arg expr" == NULL);
2241 item = NULL_TREE;
2242 break;
2245 *xitem = item;
2248 /* Check the size of the type to be sure it doesn't overflow the
2249 "portable" capacities of the compiler back end. `dummy' types
2250 can generally overflow the normal sizes as long as the computations
2251 themselves don't overflow. A particular target of the back end
2252 must still enforce its size requirements, though, and the back
2253 end takes care of this in stor-layout.c. */
2255 static tree
2256 ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy)
2258 if (TREE_CODE (type) == ERROR_MARK)
2259 return type;
2261 if (TYPE_SIZE (type) == NULL_TREE)
2262 return type;
2264 if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
2265 return type;
2267 /* An array is too large if size is negative or the type_size overflows
2268 or its "upper half" is larger than 3 (which would make the signed
2269 byte size and offset computations overflow). */
2271 if ((tree_int_cst_sgn (TYPE_SIZE (type)) < 0)
2272 || (!dummy && (TREE_INT_CST_HIGH (TYPE_SIZE (type)) > 3
2273 || TREE_OVERFLOW (TYPE_SIZE (type)))))
2275 ffebad_start (FFEBAD_ARRAY_LARGE);
2276 ffebad_string (ffesymbol_text (s));
2277 ffebad_here (0, ffesymbol_where_line (s), ffesymbol_where_column (s));
2278 ffebad_finish ();
2280 return error_mark_node;
2283 return type;
2286 /* Builds a length argument (PARM_DECL). Also wraps type in an array type
2287 where the dimension info is (1:size) where <size> is ffesymbol_size(s) if
2288 known, length_arg if not known (FFETARGET_charactersizeNONE). */
2290 static tree
2291 ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s)
2293 ffetargetCharacterSize sz = ffesymbol_size (s);
2294 tree highval;
2295 tree tlen;
2296 tree type = *xtype;
2298 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
2299 tlen = NULL_TREE; /* A statement function, no length passed. */
2300 else
2302 if (ffesymbol_where (s) == FFEINFO_whereDUMMY)
2303 tlen = ffecom_get_invented_identifier ("__g77_length_%s",
2304 ffesymbol_text (s));
2305 else
2306 tlen = ffecom_get_invented_identifier ("__g77_%s", "length");
2307 tlen = build_decl (PARM_DECL, tlen, ffecom_f2c_ftnlen_type_node);
2308 DECL_ARTIFICIAL (tlen) = 1;
2311 if (sz == FFETARGET_charactersizeNONE)
2313 assert (tlen != NULL_TREE);
2314 highval = variable_size (tlen);
2316 else
2318 highval = build_int_2 (sz, 0);
2319 TREE_TYPE (highval) = ffecom_f2c_ftnlen_type_node;
2322 type = build_array_type (type,
2323 build_range_type (ffecom_f2c_ftnlen_type_node,
2324 ffecom_f2c_ftnlen_one_node,
2325 highval));
2327 *xtype = type;
2328 return tlen;
2331 /* ffecom_concat_list_gather_ -- Gather list of concatenated string exprs
2333 ffecomConcatList_ catlist;
2334 ffebld expr; // expr of CHARACTER basictype.
2335 ffetargetCharacterSize max; // max chars to gather or _...NONE if no max
2336 catlist = ffecom_concat_list_gather_(catlist,expr,max);
2338 Scans expr for character subexpressions, updates and returns catlist
2339 accordingly. */
2341 static ffecomConcatList_
2342 ffecom_concat_list_gather_ (ffecomConcatList_ catlist, ffebld expr,
2343 ffetargetCharacterSize max)
2345 ffetargetCharacterSize sz;
2347 recurse:
2349 if (expr == NULL)
2350 return catlist;
2352 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen >= max))
2353 return catlist; /* Don't append any more items. */
2355 switch (ffebld_op (expr))
2357 case FFEBLD_opCONTER:
2358 case FFEBLD_opSYMTER:
2359 case FFEBLD_opARRAYREF:
2360 case FFEBLD_opFUNCREF:
2361 case FFEBLD_opSUBSTR:
2362 case FFEBLD_opCONVERT: /* Callers should strip this off beforehand
2363 if they don't need to preserve it. */
2364 if (catlist.count == catlist.max)
2365 { /* Make a (larger) list. */
2366 ffebld *newx;
2367 int newmax;
2369 newmax = (catlist.max == 0) ? 8 : catlist.max * 2;
2370 newx = malloc_new_ks (malloc_pool_image (), "catlist",
2371 newmax * sizeof (newx[0]));
2372 if (catlist.max != 0)
2374 memcpy (newx, catlist.exprs, catlist.max * sizeof (newx[0]));
2375 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2376 catlist.max * sizeof (newx[0]));
2378 catlist.max = newmax;
2379 catlist.exprs = newx;
2381 if ((sz = ffebld_size_known (expr)) != FFETARGET_charactersizeNONE)
2382 catlist.minlen += sz;
2383 else
2384 ++catlist.minlen; /* Not true for F90; can be 0 length. */
2385 if ((sz = ffebld_size_max (expr)) == FFETARGET_charactersizeNONE)
2386 catlist.maxlen = sz;
2387 else
2388 catlist.maxlen += sz;
2389 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen > max))
2390 { /* This item overlaps (or is beyond) the end
2391 of the destination. */
2392 switch (ffebld_op (expr))
2394 case FFEBLD_opCONTER:
2395 case FFEBLD_opSYMTER:
2396 case FFEBLD_opARRAYREF:
2397 case FFEBLD_opFUNCREF:
2398 case FFEBLD_opSUBSTR:
2399 /* ~~Do useful truncations here. */
2400 break;
2402 default:
2403 assert ("op changed or inconsistent switches!" == NULL);
2404 break;
2407 catlist.exprs[catlist.count++] = expr;
2408 return catlist;
2410 case FFEBLD_opPAREN:
2411 expr = ffebld_left (expr);
2412 goto recurse; /* :::::::::::::::::::: */
2414 case FFEBLD_opCONCATENATE:
2415 catlist = ffecom_concat_list_gather_ (catlist, ffebld_left (expr), max);
2416 expr = ffebld_right (expr);
2417 goto recurse; /* :::::::::::::::::::: */
2419 #if 0 /* Breaks passing small actual arg to larger
2420 dummy arg of sfunc */
2421 case FFEBLD_opCONVERT:
2422 expr = ffebld_left (expr);
2424 ffetargetCharacterSize cmax;
2426 cmax = catlist.len + ffebld_size_known (expr);
2428 if ((max == FFETARGET_charactersizeNONE) || (max > cmax))
2429 max = cmax;
2431 goto recurse; /* :::::::::::::::::::: */
2432 #endif
2434 case FFEBLD_opANY:
2435 return catlist;
2437 default:
2438 assert ("bad op in _gather_" == NULL);
2439 return catlist;
2443 /* ffecom_concat_list_kill_ -- Kill list of concatenated string exprs
2445 ffecomConcatList_ catlist;
2446 ffecom_concat_list_kill_(catlist);
2448 Anything allocated within the list info is deallocated. */
2450 static void
2451 ffecom_concat_list_kill_ (ffecomConcatList_ catlist)
2453 if (catlist.max != 0)
2454 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2455 catlist.max * sizeof (catlist.exprs[0]));
2458 /* Make list of concatenated string exprs.
2460 Returns a flattened list of concatenated subexpressions given a
2461 tree of such expressions. */
2463 static ffecomConcatList_
2464 ffecom_concat_list_new_ (ffebld expr, ffetargetCharacterSize max)
2466 ffecomConcatList_ catlist;
2468 catlist.maxlen = catlist.minlen = catlist.max = catlist.count = 0;
2469 return ffecom_concat_list_gather_ (catlist, expr, max);
2472 /* Provide some kind of useful info on member of aggregate area,
2473 since current g77/gcc technology does not provide debug info
2474 on these members. */
2476 static void
2477 ffecom_debug_kludge_ (tree aggr, const char *aggr_type, ffesymbol member,
2478 tree member_type UNUSED, ffetargetOffset offset)
2480 tree value;
2481 tree decl;
2482 int len;
2483 char *buff;
2484 char space[120];
2485 #if 0
2486 tree type_id;
2488 for (type_id = member_type;
2489 TREE_CODE (type_id) != IDENTIFIER_NODE;
2492 switch (TREE_CODE (type_id))
2494 case INTEGER_TYPE:
2495 case REAL_TYPE:
2496 type_id = TYPE_NAME (type_id);
2497 break;
2499 case ARRAY_TYPE:
2500 case COMPLEX_TYPE:
2501 type_id = TREE_TYPE (type_id);
2502 break;
2504 default:
2505 assert ("no IDENTIFIER_NODE for type!" == NULL);
2506 type_id = error_mark_node;
2507 break;
2510 #endif
2512 if (ffecom_transform_only_dummies_
2513 || !ffe_is_debug_kludge ())
2514 return; /* Can't do this yet, maybe later. */
2516 len = 60
2517 + strlen (aggr_type)
2518 + IDENTIFIER_LENGTH (DECL_NAME (aggr));
2519 #if 0
2520 + IDENTIFIER_LENGTH (type_id);
2521 #endif
2523 if (((size_t) len) >= ARRAY_SIZE (space))
2524 buff = malloc_new_ks (malloc_pool_image (), "debug_kludge", len + 1);
2525 else
2526 buff = &space[0];
2528 sprintf (&buff[0], "At (%s) `%s' plus %ld bytes",
2529 aggr_type,
2530 IDENTIFIER_POINTER (DECL_NAME (aggr)),
2531 (long int) offset);
2533 value = build_string (len, buff);
2534 TREE_TYPE (value)
2535 = build_type_variant (build_array_type (char_type_node,
2536 build_range_type
2537 (integer_type_node,
2538 integer_one_node,
2539 build_int_2 (strlen (buff), 0))),
2540 1, 0);
2541 decl = build_decl (VAR_DECL,
2542 ffecom_get_identifier_ (ffesymbol_text (member)),
2543 TREE_TYPE (value));
2544 TREE_CONSTANT (decl) = 1;
2545 TREE_STATIC (decl) = 1;
2546 DECL_INITIAL (decl) = error_mark_node;
2547 DECL_IN_SYSTEM_HEADER (decl) = 1; /* Don't let -Wunused complain. */
2548 decl = start_decl (decl, FALSE);
2549 finish_decl (decl, value, FALSE);
2551 if (buff != &space[0])
2552 malloc_kill_ks (malloc_pool_image (), buff, len + 1);
2555 /* ffecom_do_entry_ -- Do compilation of a particular entrypoint
2557 ffesymbol fn; // the SUBROUTINE, FUNCTION, or ENTRY symbol itself
2558 int i; // entry# for this entrypoint (used by master fn)
2559 ffecom_do_entrypoint_(s,i);
2561 Makes a public entry point that calls our private master fn (already
2562 compiled). */
2564 static void
2565 ffecom_do_entry_ (ffesymbol fn, int entrynum)
2567 ffebld item;
2568 tree type; /* Type of function. */
2569 tree multi_retval; /* Var holding return value (union). */
2570 tree result; /* Var holding result. */
2571 ffeinfoBasictype bt;
2572 ffeinfoKindtype kt;
2573 ffeglobal g;
2574 ffeglobalType gt;
2575 bool charfunc; /* All entry points return same type
2576 CHARACTER. */
2577 bool cmplxfunc; /* Use f2c way of returning COMPLEX. */
2578 bool multi; /* Master fn has multiple return types. */
2579 bool altreturning = FALSE; /* This entry point has alternate
2580 returns. */
2581 location_t old_loc = input_location;
2583 input_filename = ffesymbol_where_filename (fn);
2584 input_line = ffesymbol_where_filelinenum (fn);
2586 ffecom_doing_entry_ = TRUE; /* Don't bother with array dimensions. */
2588 switch (ffecom_primary_entry_kind_)
2590 case FFEINFO_kindFUNCTION:
2592 /* Determine actual return type for function. */
2594 gt = FFEGLOBAL_typeFUNC;
2595 bt = ffesymbol_basictype (fn);
2596 kt = ffesymbol_kindtype (fn);
2597 if (bt == FFEINFO_basictypeNONE)
2599 ffeimplic_establish_symbol (fn);
2600 if (ffesymbol_funcresult (fn) != NULL)
2601 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
2602 bt = ffesymbol_basictype (fn);
2603 kt = ffesymbol_kindtype (fn);
2606 if (bt == FFEINFO_basictypeCHARACTER)
2607 charfunc = TRUE, cmplxfunc = FALSE;
2608 else if ((bt == FFEINFO_basictypeCOMPLEX)
2609 && ffesymbol_is_f2c (fn))
2610 charfunc = FALSE, cmplxfunc = TRUE;
2611 else
2612 charfunc = cmplxfunc = FALSE;
2614 if (charfunc)
2615 type = ffecom_tree_fun_type_void;
2616 else if (ffesymbol_is_f2c (fn))
2617 type = ffecom_tree_fun_type[bt][kt];
2618 else
2619 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
2621 if ((type == NULL_TREE)
2622 || (TREE_TYPE (type) == NULL_TREE))
2623 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
2625 multi = (ffecom_master_bt_ == FFEINFO_basictypeNONE);
2626 break;
2628 case FFEINFO_kindSUBROUTINE:
2629 gt = FFEGLOBAL_typeSUBR;
2630 bt = FFEINFO_basictypeNONE;
2631 kt = FFEINFO_kindtypeNONE;
2632 if (ffecom_is_altreturning_)
2633 { /* Am _I_ altreturning? */
2634 for (item = ffesymbol_dummyargs (fn);
2635 item != NULL;
2636 item = ffebld_trail (item))
2638 if (ffebld_op (ffebld_head (item)) == FFEBLD_opSTAR)
2640 altreturning = TRUE;
2641 break;
2644 if (altreturning)
2645 type = ffecom_tree_subr_type;
2646 else
2647 type = ffecom_tree_fun_type_void;
2649 else
2650 type = ffecom_tree_fun_type_void;
2651 charfunc = FALSE;
2652 cmplxfunc = FALSE;
2653 multi = FALSE;
2654 break;
2656 default:
2657 assert ("say what??" == NULL);
2658 /* Fall through. */
2659 case FFEINFO_kindANY:
2660 gt = FFEGLOBAL_typeANY;
2661 bt = FFEINFO_basictypeNONE;
2662 kt = FFEINFO_kindtypeNONE;
2663 type = error_mark_node;
2664 charfunc = FALSE;
2665 cmplxfunc = FALSE;
2666 multi = FALSE;
2667 break;
2670 /* build_decl uses the current lineno and input_filename to set the decl
2671 source info. So, I've putzed with ffestd and ffeste code to update that
2672 source info to point to the appropriate statement just before calling
2673 ffecom_do_entrypoint (which calls this fn). */
2675 start_function (ffecom_get_external_identifier_ (fn),
2676 type,
2677 0, /* nested/inline */
2678 1); /* TREE_PUBLIC */
2680 if (((g = ffesymbol_global (fn)) != NULL)
2681 && ((ffeglobal_type (g) == gt)
2682 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
2684 ffeglobal_set_hook (g, current_function_decl);
2687 /* Reset args in master arg list so they get retransitioned. */
2689 for (item = ffecom_master_arglist_;
2690 item != NULL;
2691 item = ffebld_trail (item))
2693 ffebld arg;
2694 ffesymbol s;
2696 arg = ffebld_head (item);
2697 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2698 continue; /* Alternate return or some such thing. */
2699 s = ffebld_symter (arg);
2700 ffesymbol_hook (s).decl_tree = NULL_TREE;
2701 ffesymbol_hook (s).length_tree = NULL_TREE;
2704 /* Build dummy arg list for this entry point. */
2706 if (charfunc || cmplxfunc)
2707 { /* Prepend arg for where result goes. */
2708 tree type;
2709 tree length;
2711 if (charfunc)
2712 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
2713 else
2714 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
2716 result = ffecom_get_invented_identifier ("__g77_%s", "result");
2718 /* Make length arg _and_ enhance type info for CHAR arg itself. */
2720 if (charfunc)
2721 length = ffecom_char_enhance_arg_ (&type, fn);
2722 else
2723 length = NULL_TREE; /* Not ref'd if !charfunc. */
2725 type = build_pointer_type (type);
2726 result = build_decl (PARM_DECL, result, type);
2728 push_parm_decl (result);
2729 ffecom_func_result_ = result;
2731 if (charfunc)
2733 push_parm_decl (length);
2734 ffecom_func_length_ = length;
2737 else
2738 result = DECL_RESULT (current_function_decl);
2740 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (fn), FALSE);
2742 store_parm_decls (0);
2744 ffecom_start_compstmt ();
2745 /* Disallow temp vars at this level. */
2746 current_binding_level->prep_state = 2;
2748 /* Make local var to hold return type for multi-type master fn. */
2750 if (multi)
2752 multi_retval = ffecom_get_invented_identifier ("__g77_%s",
2753 "multi_retval");
2754 multi_retval = build_decl (VAR_DECL, multi_retval,
2755 ffecom_multi_type_node_);
2756 multi_retval = start_decl (multi_retval, FALSE);
2757 finish_decl (multi_retval, NULL_TREE, FALSE);
2759 else
2760 multi_retval = NULL_TREE; /* Not actually ref'd if !multi. */
2762 /* Here we emit the actual code for the entry point. */
2765 ffebld list;
2766 ffebld arg;
2767 ffesymbol s;
2768 tree arglist = NULL_TREE;
2769 tree *plist = &arglist;
2770 tree prepend;
2771 tree call;
2772 tree actarg;
2773 tree master_fn;
2775 /* Prepare actual arg list based on master arg list. */
2777 for (list = ffecom_master_arglist_;
2778 list != NULL;
2779 list = ffebld_trail (list))
2781 arg = ffebld_head (list);
2782 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2783 continue;
2784 s = ffebld_symter (arg);
2785 if (ffesymbol_hook (s).decl_tree == NULL_TREE
2786 || ffesymbol_hook (s).decl_tree == error_mark_node)
2787 actarg = null_pointer_node; /* We don't have this arg. */
2788 else
2789 actarg = ffesymbol_hook (s).decl_tree;
2790 *plist = build_tree_list (NULL_TREE, actarg);
2791 plist = &TREE_CHAIN (*plist);
2794 /* This code appends the length arguments for character
2795 variables/arrays. */
2797 for (list = ffecom_master_arglist_;
2798 list != NULL;
2799 list = ffebld_trail (list))
2801 arg = ffebld_head (list);
2802 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2803 continue;
2804 s = ffebld_symter (arg);
2805 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
2806 continue; /* Only looking for CHARACTER arguments. */
2807 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
2808 continue; /* Only looking for variables and arrays. */
2809 if (ffesymbol_hook (s).length_tree == NULL_TREE
2810 || ffesymbol_hook (s).length_tree == error_mark_node)
2811 actarg = ffecom_f2c_ftnlen_zero_node; /* We don't have this arg. */
2812 else
2813 actarg = ffesymbol_hook (s).length_tree;
2814 *plist = build_tree_list (NULL_TREE, actarg);
2815 plist = &TREE_CHAIN (*plist);
2818 /* Prepend character-value return info to actual arg list. */
2820 if (charfunc)
2822 prepend = build_tree_list (NULL_TREE, ffecom_func_result_);
2823 TREE_CHAIN (prepend)
2824 = build_tree_list (NULL_TREE, ffecom_func_length_);
2825 TREE_CHAIN (TREE_CHAIN (prepend)) = arglist;
2826 arglist = prepend;
2829 /* Prepend multi-type return value to actual arg list. */
2831 if (multi)
2833 prepend
2834 = build_tree_list (NULL_TREE,
2835 ffecom_1 (ADDR_EXPR,
2836 build_pointer_type (TREE_TYPE (multi_retval)),
2837 multi_retval));
2838 TREE_CHAIN (prepend) = arglist;
2839 arglist = prepend;
2842 /* Prepend my entry-point number to the actual arg list. */
2844 prepend = build_tree_list (NULL_TREE, build_int_2 (entrynum, 0));
2845 TREE_CHAIN (prepend) = arglist;
2846 arglist = prepend;
2848 /* Build the call to the master function. */
2850 master_fn = ffecom_1_fn (ffecom_previous_function_decl_);
2851 call = ffecom_3s (CALL_EXPR,
2852 TREE_TYPE (TREE_TYPE (TREE_TYPE (master_fn))),
2853 master_fn, arglist, NULL_TREE);
2855 /* Decide whether the master function is a function or subroutine, and
2856 handle the return value for my entry point. */
2858 if (charfunc || ((ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
2859 && !altreturning))
2861 expand_expr_stmt (call);
2862 expand_null_return ();
2864 else if (multi && cmplxfunc)
2866 expand_expr_stmt (call);
2867 result
2868 = ffecom_1 (INDIRECT_REF,
2869 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
2870 result);
2871 result = ffecom_modify (NULL_TREE, result,
2872 ffecom_2 (COMPONENT_REF, TREE_TYPE (result),
2873 multi_retval,
2874 ffecom_multi_fields_[bt][kt]));
2875 expand_expr_stmt (result);
2876 expand_null_return ();
2878 else if (multi)
2880 expand_expr_stmt (call);
2881 result
2882 = ffecom_modify (NULL_TREE, result,
2883 convert (TREE_TYPE (result),
2884 ffecom_2 (COMPONENT_REF,
2885 ffecom_tree_type[bt][kt],
2886 multi_retval,
2887 ffecom_multi_fields_[bt][kt])));
2888 expand_return (result);
2890 else if (cmplxfunc)
2892 result
2893 = ffecom_1 (INDIRECT_REF,
2894 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
2895 result);
2896 result = ffecom_modify (NULL_TREE, result, call);
2897 expand_expr_stmt (result);
2898 expand_null_return ();
2900 else
2902 result = ffecom_modify (NULL_TREE,
2903 result,
2904 convert (TREE_TYPE (result),
2905 call));
2906 expand_return (result);
2910 ffecom_end_compstmt ();
2912 finish_function (0);
2914 input_location = old_loc;
2916 ffecom_doing_entry_ = FALSE;
2919 /* Transform expr into gcc tree with possible destination
2921 Recursive descent on expr while making corresponding tree nodes and
2922 attaching type info and such. If destination supplied and compatible
2923 with temporary that would be made in certain cases, temporary isn't
2924 made, destination used instead, and dest_used flag set TRUE. */
2926 static tree
2927 ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest, bool *dest_used,
2928 bool assignp, bool widenp)
2930 tree item;
2931 tree list;
2932 tree args;
2933 ffeinfoBasictype bt;
2934 ffeinfoKindtype kt;
2935 tree t;
2936 tree dt; /* decl_tree for an ffesymbol. */
2937 tree tree_type, tree_type_x;
2938 tree left, right;
2939 ffesymbol s;
2940 enum tree_code code;
2942 assert (expr != NULL);
2944 if (dest_used != NULL)
2945 *dest_used = FALSE;
2947 bt = ffeinfo_basictype (ffebld_info (expr));
2948 kt = ffeinfo_kindtype (ffebld_info (expr));
2949 tree_type = ffecom_tree_type[bt][kt];
2951 /* Widen integral arithmetic as desired while preserving signedness. */
2952 tree_type_x = NULL_TREE;
2953 if (widenp && tree_type
2954 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
2955 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
2956 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
2958 switch (ffebld_op (expr))
2960 case FFEBLD_opACCTER:
2962 ffebitCount i;
2963 ffebit bits = ffebld_accter_bits (expr);
2964 ffetargetOffset source_offset = 0;
2965 ffetargetOffset dest_offset = ffebld_accter_pad (expr);
2966 tree purpose;
2968 assert (dest_offset == 0
2969 || (bt == FFEINFO_basictypeCHARACTER
2970 && kt == FFEINFO_kindtypeCHARACTER1));
2972 list = item = NULL;
2973 for (;;)
2975 ffebldConstantUnion cu;
2976 ffebitCount length;
2977 bool value;
2978 ffebldConstantArray ca = ffebld_accter (expr);
2980 ffebit_test (bits, source_offset, &value, &length);
2981 if (length == 0)
2982 break;
2984 if (value)
2986 for (i = 0; i < length; ++i)
2988 cu = ffebld_constantarray_get (ca, bt, kt,
2989 source_offset + i);
2991 t = ffecom_constantunion (&cu, bt, kt, tree_type);
2993 if (i == 0
2994 && dest_offset != 0)
2995 purpose = build_int_2 (dest_offset, 0);
2996 else
2997 purpose = NULL_TREE;
2999 if (list == NULL_TREE)
3000 list = item = build_tree_list (purpose, t);
3001 else
3003 TREE_CHAIN (item) = build_tree_list (purpose, t);
3004 item = TREE_CHAIN (item);
3008 source_offset += length;
3009 dest_offset += length;
3013 item = build_int_2 ((ffebld_accter_size (expr)
3014 + ffebld_accter_pad (expr)) - 1, 0);
3015 ffebit_kill (ffebld_accter_bits (expr));
3016 TREE_TYPE (item) = ffecom_integer_type_node;
3017 item
3018 = build_array_type
3019 (tree_type,
3020 build_range_type (ffecom_integer_type_node,
3021 ffecom_integer_zero_node,
3022 item));
3023 list = build_constructor (item, list);
3024 TREE_CONSTANT (list) = 1;
3025 TREE_STATIC (list) = 1;
3026 return list;
3028 case FFEBLD_opARRTER:
3030 ffetargetOffset i;
3032 list = NULL_TREE;
3033 if (ffebld_arrter_pad (expr) == 0)
3034 item = NULL_TREE;
3035 else
3037 assert (bt == FFEINFO_basictypeCHARACTER
3038 && kt == FFEINFO_kindtypeCHARACTER1);
3040 /* Becomes PURPOSE first time through loop. */
3041 item = build_int_2 (ffebld_arrter_pad (expr), 0);
3044 for (i = 0; i < ffebld_arrter_size (expr); ++i)
3046 ffebldConstantUnion cu
3047 = ffebld_constantarray_get (ffebld_arrter (expr), bt, kt, i);
3049 t = ffecom_constantunion (&cu, bt, kt, tree_type);
3051 if (list == NULL_TREE)
3052 /* Assume item is PURPOSE first time through loop. */
3053 list = item = build_tree_list (item, t);
3054 else
3056 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
3057 item = TREE_CHAIN (item);
3062 item = build_int_2 ((ffebld_arrter_size (expr)
3063 + ffebld_arrter_pad (expr)) - 1, 0);
3064 TREE_TYPE (item) = ffecom_integer_type_node;
3065 item
3066 = build_array_type
3067 (tree_type,
3068 build_range_type (ffecom_integer_type_node,
3069 ffecom_integer_zero_node,
3070 item));
3071 list = build_constructor (item, list);
3072 TREE_CONSTANT (list) = 1;
3073 TREE_STATIC (list) = 1;
3074 return list;
3076 case FFEBLD_opCONTER:
3077 assert (ffebld_conter_pad (expr) == 0);
3078 item
3079 = ffecom_constantunion (&ffebld_constant_union (ffebld_conter (expr)),
3080 bt, kt, tree_type);
3081 return item;
3083 case FFEBLD_opSYMTER:
3084 if ((ffebld_symter_generic (expr) != FFEINTRIN_genNONE)
3085 || (ffebld_symter_specific (expr) != FFEINTRIN_specNONE))
3086 return ffecom_ptr_to_expr (expr); /* Same as %REF(intrinsic). */
3087 s = ffebld_symter (expr);
3088 t = ffesymbol_hook (s).decl_tree;
3090 if (assignp)
3091 { /* ASSIGN'ed-label expr. */
3092 if (ffe_is_ugly_assign ())
3094 /* User explicitly wants ASSIGN'ed variables to be at the same
3095 memory address as the variables when used in non-ASSIGN
3096 contexts. That can make old, arcane, non-standard code
3097 work, but don't try to do it when a pointer wouldn't fit
3098 in the normal variable (take other approach, and warn,
3099 instead). */
3101 if (t == NULL_TREE)
3103 s = ffecom_sym_transform_ (s);
3104 t = ffesymbol_hook (s).decl_tree;
3105 assert (t != NULL_TREE);
3108 if (t == error_mark_node)
3109 return t;
3111 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (t)))
3112 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
3114 if (ffesymbol_hook (s).addr)
3115 t = ffecom_1 (INDIRECT_REF,
3116 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3117 return t;
3120 if (ffesymbol_hook (s).assign_tree == NULL_TREE)
3122 /* xgettext:no-c-format */
3123 ffebad_start_msg ("ASSIGN'ed label cannot fit into `%A' at %0 -- using wider sibling",
3124 FFEBAD_severityWARNING);
3125 ffebad_string (ffesymbol_text (s));
3126 ffebad_here (0, ffesymbol_where_line (s),
3127 ffesymbol_where_column (s));
3128 ffebad_finish ();
3132 /* Don't use the normal variable's tree for ASSIGN, though mark
3133 it as in the system header (housekeeping). Use an explicit,
3134 specially created sibling that is known to be wide enough
3135 to hold pointers to labels. */
3137 if (t != NULL_TREE
3138 && TREE_CODE (t) == VAR_DECL)
3139 DECL_IN_SYSTEM_HEADER (t) = 1; /* Don't let -Wunused complain. */
3141 t = ffesymbol_hook (s).assign_tree;
3142 if (t == NULL_TREE)
3144 s = ffecom_sym_transform_assign_ (s);
3145 t = ffesymbol_hook (s).assign_tree;
3146 assert (t != NULL_TREE);
3149 else
3151 if (t == NULL_TREE)
3153 s = ffecom_sym_transform_ (s);
3154 t = ffesymbol_hook (s).decl_tree;
3155 assert (t != NULL_TREE);
3157 if (ffesymbol_hook (s).addr)
3158 t = ffecom_1 (INDIRECT_REF,
3159 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3161 return t;
3163 case FFEBLD_opARRAYREF:
3164 return ffecom_arrayref_ (NULL_TREE, expr, 0);
3166 case FFEBLD_opUPLUS:
3167 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3168 return ffecom_1 (NOP_EXPR, tree_type, left);
3170 case FFEBLD_opPAREN:
3171 /* ~~~Make sure Fortran rules respected here */
3172 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3173 return ffecom_1 (NOP_EXPR, tree_type, left);
3175 case FFEBLD_opUMINUS:
3176 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3177 if (tree_type_x)
3179 tree_type = tree_type_x;
3180 left = convert (tree_type, left);
3182 return ffecom_1 (NEGATE_EXPR, tree_type, left);
3184 case FFEBLD_opADD:
3185 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3186 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3187 if (tree_type_x)
3189 tree_type = tree_type_x;
3190 left = convert (tree_type, left);
3191 right = convert (tree_type, right);
3193 return ffecom_2 (PLUS_EXPR, tree_type, left, right);
3195 case FFEBLD_opSUBTRACT:
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)
3200 tree_type = tree_type_x;
3201 left = convert (tree_type, left);
3202 right = convert (tree_type, right);
3204 return ffecom_2 (MINUS_EXPR, tree_type, left, right);
3206 case FFEBLD_opMULTIPLY:
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)
3211 tree_type = tree_type_x;
3212 left = convert (tree_type, left);
3213 right = convert (tree_type, right);
3215 return ffecom_2 (MULT_EXPR, tree_type, left, right);
3217 case FFEBLD_opDIVIDE:
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)
3222 tree_type = tree_type_x;
3223 left = convert (tree_type, left);
3224 right = convert (tree_type, right);
3226 return ffecom_tree_divide_ (tree_type, left, right,
3227 dest_tree, dest, dest_used,
3228 ffebld_nonter_hook (expr));
3230 case FFEBLD_opPOWER:
3232 ffebld left = ffebld_left (expr);
3233 ffebld right = ffebld_right (expr);
3234 ffecomGfrt code;
3235 ffeinfoKindtype rtkt;
3236 ffeinfoKindtype ltkt;
3237 bool ref = TRUE;
3239 switch (ffeinfo_basictype (ffebld_info (right)))
3242 case FFEINFO_basictypeINTEGER:
3243 if (1 || optimize)
3245 item = ffecom_expr_power_integer_ (expr);
3246 if (item != NULL_TREE)
3247 return item;
3250 rtkt = FFEINFO_kindtypeINTEGER1;
3251 switch (ffeinfo_basictype (ffebld_info (left)))
3253 case FFEINFO_basictypeINTEGER:
3254 if ((ffeinfo_kindtype (ffebld_info (left))
3255 == FFEINFO_kindtypeINTEGER4)
3256 || (ffeinfo_kindtype (ffebld_info (right))
3257 == FFEINFO_kindtypeINTEGER4))
3259 code = FFECOM_gfrtPOW_QQ;
3260 ltkt = FFEINFO_kindtypeINTEGER4;
3261 rtkt = FFEINFO_kindtypeINTEGER4;
3263 else
3265 code = FFECOM_gfrtPOW_II;
3266 ltkt = FFEINFO_kindtypeINTEGER1;
3268 break;
3270 case FFEINFO_basictypeREAL:
3271 if (ffeinfo_kindtype (ffebld_info (left))
3272 == FFEINFO_kindtypeREAL1)
3274 code = FFECOM_gfrtPOW_RI;
3275 ltkt = FFEINFO_kindtypeREAL1;
3277 else
3279 code = FFECOM_gfrtPOW_DI;
3280 ltkt = FFEINFO_kindtypeREAL2;
3282 break;
3284 case FFEINFO_basictypeCOMPLEX:
3285 if (ffeinfo_kindtype (ffebld_info (left))
3286 == FFEINFO_kindtypeREAL1)
3288 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
3289 ltkt = FFEINFO_kindtypeREAL1;
3291 else
3293 code = FFECOM_gfrtPOW_ZI; /* Overlapping result okay. */
3294 ltkt = FFEINFO_kindtypeREAL2;
3296 break;
3298 default:
3299 assert ("bad pow_*i" == NULL);
3300 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
3301 ltkt = FFEINFO_kindtypeREAL1;
3302 break;
3304 if (ffeinfo_kindtype (ffebld_info (left)) != ltkt)
3305 left = ffeexpr_convert (left, NULL, NULL,
3306 ffeinfo_basictype (ffebld_info (left)),
3307 ltkt, 0,
3308 FFETARGET_charactersizeNONE,
3309 FFEEXPR_contextLET);
3310 if (ffeinfo_kindtype (ffebld_info (right)) != rtkt)
3311 right = ffeexpr_convert (right, NULL, NULL,
3312 FFEINFO_basictypeINTEGER,
3313 rtkt, 0,
3314 FFETARGET_charactersizeNONE,
3315 FFEEXPR_contextLET);
3316 break;
3318 case FFEINFO_basictypeREAL:
3319 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3320 left = ffeexpr_convert (left, NULL, NULL, FFEINFO_basictypeREAL,
3321 FFEINFO_kindtypeREALDOUBLE, 0,
3322 FFETARGET_charactersizeNONE,
3323 FFEEXPR_contextLET);
3324 if (ffeinfo_kindtype (ffebld_info (right))
3325 == FFEINFO_kindtypeREAL1)
3326 right = ffeexpr_convert (right, NULL, NULL,
3327 FFEINFO_basictypeREAL,
3328 FFEINFO_kindtypeREALDOUBLE, 0,
3329 FFETARGET_charactersizeNONE,
3330 FFEEXPR_contextLET);
3331 /* We used to call FFECOM_gfrtPOW_DD here,
3332 which passes arguments by reference. */
3333 code = FFECOM_gfrtL_POW;
3334 /* Pass arguments by value. */
3335 ref = FALSE;
3336 break;
3338 case FFEINFO_basictypeCOMPLEX:
3339 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3340 left = ffeexpr_convert (left, NULL, NULL,
3341 FFEINFO_basictypeCOMPLEX,
3342 FFEINFO_kindtypeREALDOUBLE, 0,
3343 FFETARGET_charactersizeNONE,
3344 FFEEXPR_contextLET);
3345 if (ffeinfo_kindtype (ffebld_info (right))
3346 == FFEINFO_kindtypeREAL1)
3347 right = ffeexpr_convert (right, NULL, NULL,
3348 FFEINFO_basictypeCOMPLEX,
3349 FFEINFO_kindtypeREALDOUBLE, 0,
3350 FFETARGET_charactersizeNONE,
3351 FFEEXPR_contextLET);
3352 code = FFECOM_gfrtPOW_ZZ; /* Overlapping result okay. */
3353 ref = TRUE; /* Pass arguments by reference. */
3354 break;
3356 default:
3357 assert ("bad pow_x*" == NULL);
3358 code = FFECOM_gfrtPOW_II;
3359 break;
3361 return ffecom_call_binop_ (ffecom_gfrt_tree_ (code),
3362 ffecom_gfrt_kindtype (code),
3363 (ffe_is_f2c_library ()
3364 && ffecom_gfrt_complex_[code]),
3365 tree_type, left, right,
3366 dest_tree, dest, dest_used,
3367 NULL_TREE, FALSE, ref,
3368 ffebld_nonter_hook (expr));
3371 case FFEBLD_opNOT:
3372 switch (bt)
3374 case FFEINFO_basictypeLOGICAL:
3375 item = ffecom_truth_value_invert (ffecom_expr (ffebld_left (expr)));
3376 return convert (tree_type, item);
3378 case FFEINFO_basictypeINTEGER:
3379 return ffecom_1 (BIT_NOT_EXPR, tree_type,
3380 ffecom_expr (ffebld_left (expr)));
3382 default:
3383 assert ("NOT bad basictype" == NULL);
3384 /* Fall through. */
3385 case FFEINFO_basictypeANY:
3386 return error_mark_node;
3388 break;
3390 case FFEBLD_opFUNCREF:
3391 assert (ffeinfo_basictype (ffebld_info (expr))
3392 != FFEINFO_basictypeCHARACTER);
3393 /* Fall through. */
3394 case FFEBLD_opSUBRREF:
3395 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
3396 == FFEINFO_whereINTRINSIC)
3397 { /* Invocation of an intrinsic. */
3398 item = ffecom_expr_intrinsic_ (expr, dest_tree, dest,
3399 dest_used);
3400 return item;
3402 s = ffebld_symter (ffebld_left (expr));
3403 dt = ffesymbol_hook (s).decl_tree;
3404 if (dt == NULL_TREE)
3406 s = ffecom_sym_transform_ (s);
3407 dt = ffesymbol_hook (s).decl_tree;
3409 if (dt == error_mark_node)
3410 return dt;
3412 if (ffesymbol_hook (s).addr)
3413 item = dt;
3414 else
3415 item = ffecom_1_fn (dt);
3417 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
3418 args = ffecom_list_expr (ffebld_right (expr));
3419 else
3420 args = ffecom_list_ptr_to_expr (ffebld_right (expr));
3422 if (args == error_mark_node)
3423 return error_mark_node;
3425 item = ffecom_call_ (item, kt,
3426 ffesymbol_is_f2c (s)
3427 && (bt == FFEINFO_basictypeCOMPLEX)
3428 && (ffesymbol_where (s)
3429 != FFEINFO_whereCONSTANT),
3430 tree_type,
3431 args,
3432 dest_tree, dest, dest_used,
3433 error_mark_node, FALSE,
3434 ffebld_nonter_hook (expr));
3435 TREE_SIDE_EFFECTS (item) = 1;
3436 return item;
3438 case FFEBLD_opAND:
3439 switch (bt)
3441 case FFEINFO_basictypeLOGICAL:
3442 item
3443 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3444 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3445 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3446 return convert (tree_type, item);
3448 case FFEINFO_basictypeINTEGER:
3449 return ffecom_2 (BIT_AND_EXPR, tree_type,
3450 ffecom_expr (ffebld_left (expr)),
3451 ffecom_expr (ffebld_right (expr)));
3453 default:
3454 assert ("AND bad basictype" == NULL);
3455 /* Fall through. */
3456 case FFEINFO_basictypeANY:
3457 return error_mark_node;
3459 break;
3461 case FFEBLD_opOR:
3462 switch (bt)
3464 case FFEINFO_basictypeLOGICAL:
3465 item
3466 = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
3467 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3468 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3469 return convert (tree_type, item);
3471 case FFEINFO_basictypeINTEGER:
3472 return ffecom_2 (BIT_IOR_EXPR, tree_type,
3473 ffecom_expr (ffebld_left (expr)),
3474 ffecom_expr (ffebld_right (expr)));
3476 default:
3477 assert ("OR bad basictype" == NULL);
3478 /* Fall through. */
3479 case FFEINFO_basictypeANY:
3480 return error_mark_node;
3482 break;
3484 case FFEBLD_opXOR:
3485 case FFEBLD_opNEQV:
3486 switch (bt)
3488 case FFEINFO_basictypeLOGICAL:
3489 item
3490 = ffecom_2 (NE_EXPR, integer_type_node,
3491 ffecom_expr (ffebld_left (expr)),
3492 ffecom_expr (ffebld_right (expr)));
3493 return convert (tree_type, ffecom_truth_value (item));
3495 case FFEINFO_basictypeINTEGER:
3496 return ffecom_2 (BIT_XOR_EXPR, tree_type,
3497 ffecom_expr (ffebld_left (expr)),
3498 ffecom_expr (ffebld_right (expr)));
3500 default:
3501 assert ("XOR/NEQV bad basictype" == NULL);
3502 /* Fall through. */
3503 case FFEINFO_basictypeANY:
3504 return error_mark_node;
3506 break;
3508 case FFEBLD_opEQV:
3509 switch (bt)
3511 case FFEINFO_basictypeLOGICAL:
3512 item
3513 = ffecom_2 (EQ_EXPR, integer_type_node,
3514 ffecom_expr (ffebld_left (expr)),
3515 ffecom_expr (ffebld_right (expr)));
3516 return convert (tree_type, ffecom_truth_value (item));
3518 case FFEINFO_basictypeINTEGER:
3519 return
3520 ffecom_1 (BIT_NOT_EXPR, tree_type,
3521 ffecom_2 (BIT_XOR_EXPR, tree_type,
3522 ffecom_expr (ffebld_left (expr)),
3523 ffecom_expr (ffebld_right (expr))));
3525 default:
3526 assert ("EQV bad basictype" == NULL);
3527 /* Fall through. */
3528 case FFEINFO_basictypeANY:
3529 return error_mark_node;
3531 break;
3533 case FFEBLD_opCONVERT:
3534 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opANY)
3535 return error_mark_node;
3537 switch (bt)
3539 case FFEINFO_basictypeLOGICAL:
3540 case FFEINFO_basictypeINTEGER:
3541 case FFEINFO_basictypeREAL:
3542 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3544 case FFEINFO_basictypeCOMPLEX:
3545 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3547 case FFEINFO_basictypeINTEGER:
3548 case FFEINFO_basictypeLOGICAL:
3549 case FFEINFO_basictypeREAL:
3550 item = ffecom_expr (ffebld_left (expr));
3551 if (item == error_mark_node)
3552 return error_mark_node;
3553 /* convert() takes care of converting to the subtype first,
3554 at least in gcc-2.7.2. */
3555 item = convert (tree_type, item);
3556 return item;
3558 case FFEINFO_basictypeCOMPLEX:
3559 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3561 default:
3562 assert ("CONVERT COMPLEX bad basictype" == NULL);
3563 /* Fall through. */
3564 case FFEINFO_basictypeANY:
3565 return error_mark_node;
3567 break;
3569 default:
3570 assert ("CONVERT bad basictype" == NULL);
3571 /* Fall through. */
3572 case FFEINFO_basictypeANY:
3573 return error_mark_node;
3575 break;
3577 case FFEBLD_opLT:
3578 code = LT_EXPR;
3579 goto relational; /* :::::::::::::::::::: */
3581 case FFEBLD_opLE:
3582 code = LE_EXPR;
3583 goto relational; /* :::::::::::::::::::: */
3585 case FFEBLD_opEQ:
3586 code = EQ_EXPR;
3587 goto relational; /* :::::::::::::::::::: */
3589 case FFEBLD_opNE:
3590 code = NE_EXPR;
3591 goto relational; /* :::::::::::::::::::: */
3593 case FFEBLD_opGT:
3594 code = GT_EXPR;
3595 goto relational; /* :::::::::::::::::::: */
3597 case FFEBLD_opGE:
3598 code = GE_EXPR;
3600 relational: /* :::::::::::::::::::: */
3601 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3603 case FFEINFO_basictypeLOGICAL:
3604 case FFEINFO_basictypeINTEGER:
3605 case FFEINFO_basictypeREAL:
3606 item = ffecom_2 (code, integer_type_node,
3607 ffecom_expr (ffebld_left (expr)),
3608 ffecom_expr (ffebld_right (expr)));
3609 return convert (tree_type, item);
3611 case FFEINFO_basictypeCOMPLEX:
3612 assert (code == EQ_EXPR || code == NE_EXPR);
3614 tree real_type;
3615 tree arg1 = ffecom_expr (ffebld_left (expr));
3616 tree arg2 = ffecom_expr (ffebld_right (expr));
3618 if (arg1 == error_mark_node || arg2 == error_mark_node)
3619 return error_mark_node;
3621 arg1 = ffecom_save_tree (arg1);
3622 arg2 = ffecom_save_tree (arg2);
3624 if (TREE_CODE (TREE_TYPE (arg1)) == COMPLEX_TYPE)
3626 real_type = TREE_TYPE (TREE_TYPE (arg1));
3627 assert (real_type == TREE_TYPE (TREE_TYPE (arg2)));
3629 else
3631 real_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg1)));
3632 assert (real_type == TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg2))));
3635 item
3636 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3637 ffecom_2 (EQ_EXPR, integer_type_node,
3638 ffecom_1 (REALPART_EXPR, real_type, arg1),
3639 ffecom_1 (REALPART_EXPR, real_type, arg2)),
3640 ffecom_2 (EQ_EXPR, integer_type_node,
3641 ffecom_1 (IMAGPART_EXPR, real_type, arg1),
3642 ffecom_1 (IMAGPART_EXPR, real_type,
3643 arg2)));
3644 if (code == EQ_EXPR)
3645 item = ffecom_truth_value (item);
3646 else
3647 item = ffecom_truth_value_invert (item);
3648 return convert (tree_type, item);
3651 case FFEINFO_basictypeCHARACTER:
3653 ffebld left = ffebld_left (expr);
3654 ffebld right = ffebld_right (expr);
3655 tree left_tree;
3656 tree right_tree;
3657 tree left_length;
3658 tree right_length;
3660 /* f2c run-time functions do the implicit blank-padding for us,
3661 so we don't usually have to implement blank-padding ourselves.
3662 (The exception is when we pass an argument to a separately
3663 compiled statement function -- if we know the arg is not the
3664 same length as the dummy, we must truncate or extend it. If
3665 we "inline" statement functions, that necessity goes away as
3666 well.)
3668 Strip off the CONVERT operators that blank-pad. (Truncation by
3669 CONVERT shouldn't happen here, but it can happen in
3670 assignments.) */
3672 while (ffebld_op (left) == FFEBLD_opCONVERT)
3673 left = ffebld_left (left);
3674 while (ffebld_op (right) == FFEBLD_opCONVERT)
3675 right = ffebld_left (right);
3677 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
3678 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
3680 if (left_tree == error_mark_node || left_length == error_mark_node
3681 || right_tree == error_mark_node
3682 || right_length == error_mark_node)
3683 return error_mark_node;
3685 if ((ffebld_size_known (left) == 1)
3686 && (ffebld_size_known (right) == 1))
3688 left_tree
3689 = ffecom_1 (INDIRECT_REF,
3690 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3691 left_tree);
3692 right_tree
3693 = ffecom_1 (INDIRECT_REF,
3694 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3695 right_tree);
3697 item
3698 = ffecom_2 (code, integer_type_node,
3699 ffecom_2 (ARRAY_REF,
3700 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3701 left_tree,
3702 integer_one_node),
3703 ffecom_2 (ARRAY_REF,
3704 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3705 right_tree,
3706 integer_one_node));
3708 else
3710 item = build_tree_list (NULL_TREE, left_tree);
3711 TREE_CHAIN (item) = build_tree_list (NULL_TREE, right_tree);
3712 TREE_CHAIN (TREE_CHAIN (item)) = build_tree_list (NULL_TREE,
3713 left_length);
3714 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
3715 = build_tree_list (NULL_TREE, right_length);
3716 item = ffecom_call_gfrt (FFECOM_gfrtCMP, item, NULL_TREE);
3717 item = ffecom_2 (code, integer_type_node,
3718 item,
3719 convert (TREE_TYPE (item),
3720 integer_zero_node));
3722 item = convert (tree_type, item);
3725 return item;
3727 default:
3728 assert ("relational bad basictype" == NULL);
3729 /* Fall through. */
3730 case FFEINFO_basictypeANY:
3731 return error_mark_node;
3733 break;
3735 case FFEBLD_opPERCENT_LOC:
3736 item = ffecom_arg_ptr_to_expr (ffebld_left (expr), &list);
3737 return convert (tree_type, item);
3739 case FFEBLD_opPERCENT_VAL:
3740 item = ffecom_arg_expr (ffebld_left (expr), &list);
3741 return convert (tree_type, item);
3743 case FFEBLD_opITEM:
3744 case FFEBLD_opSTAR:
3745 case FFEBLD_opBOUNDS:
3746 case FFEBLD_opREPEAT:
3747 case FFEBLD_opLABTER:
3748 case FFEBLD_opLABTOK:
3749 case FFEBLD_opIMPDO:
3750 case FFEBLD_opCONCATENATE:
3751 case FFEBLD_opSUBSTR:
3752 default:
3753 assert ("bad op" == NULL);
3754 /* Fall through. */
3755 case FFEBLD_opANY:
3756 return error_mark_node;
3759 #if 1
3760 assert ("didn't think anything got here anymore!!" == NULL);
3761 #else
3762 switch (ffebld_arity (expr))
3764 case 2:
3765 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3766 TREE_OPERAND (item, 1) = ffecom_expr (ffebld_right (expr));
3767 if (TREE_OPERAND (item, 0) == error_mark_node
3768 || TREE_OPERAND (item, 1) == error_mark_node)
3769 return error_mark_node;
3770 break;
3772 case 1:
3773 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3774 if (TREE_OPERAND (item, 0) == error_mark_node)
3775 return error_mark_node;
3776 break;
3778 default:
3779 break;
3782 return fold (item);
3783 #endif
3786 /* Returns the tree that does the intrinsic invocation.
3788 Note: this function applies only to intrinsics returning
3789 CHARACTER*1 or non-CHARACTER results, and to intrinsic
3790 subroutines. */
3792 static tree
3793 ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree, ffebld dest,
3794 bool *dest_used)
3796 tree expr_tree;
3797 tree saved_expr1; /* For those who need it. */
3798 tree saved_expr2; /* For those who need it. */
3799 ffeinfoBasictype bt;
3800 ffeinfoKindtype kt;
3801 tree tree_type;
3802 tree arg1_type;
3803 tree real_type; /* REAL type corresponding to COMPLEX. */
3804 tree tempvar;
3805 ffebld list = ffebld_right (expr); /* List of (some) args. */
3806 ffebld arg1; /* For handy reference. */
3807 ffebld arg2;
3808 ffebld arg3;
3809 ffeintrinImp codegen_imp;
3810 ffecomGfrt gfrt;
3812 assert (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER);
3814 if (dest_used != NULL)
3815 *dest_used = FALSE;
3817 bt = ffeinfo_basictype (ffebld_info (expr));
3818 kt = ffeinfo_kindtype (ffebld_info (expr));
3819 tree_type = ffecom_tree_type[bt][kt];
3821 if (list != NULL)
3823 arg1 = ffebld_head (list);
3824 if (arg1 != NULL && ffebld_op (arg1) == FFEBLD_opANY)
3825 return error_mark_node;
3826 if ((list = ffebld_trail (list)) != NULL)
3828 arg2 = ffebld_head (list);
3829 if (arg2 != NULL && ffebld_op (arg2) == FFEBLD_opANY)
3830 return error_mark_node;
3831 if ((list = ffebld_trail (list)) != NULL)
3833 arg3 = ffebld_head (list);
3834 if (arg3 != NULL && ffebld_op (arg3) == FFEBLD_opANY)
3835 return error_mark_node;
3837 else
3838 arg3 = NULL;
3840 else
3841 arg2 = arg3 = NULL;
3843 else
3844 arg1 = arg2 = arg3 = NULL;
3846 /* <list> ends up at the opITEM of the 3rd arg, or NULL if there are < 3
3847 args. This is used by the MAX/MIN expansions. */
3849 if (arg1 != NULL)
3850 arg1_type = ffecom_tree_type
3851 [ffeinfo_basictype (ffebld_info (arg1))]
3852 [ffeinfo_kindtype (ffebld_info (arg1))];
3853 else
3854 arg1_type = NULL_TREE; /* Really not needed, but might catch bugs
3855 here. */
3857 /* There are several ways for each of the cases in the following switch
3858 statements to exit (from simplest to use to most complicated):
3860 break; (when expr_tree == NULL)
3862 A standard call is made to the specific intrinsic just as if it had been
3863 passed in as a dummy procedure and called as any old procedure. This
3864 method can produce slower code but in some cases it's the easiest way for
3865 now. However, if a (presumably faster) direct call is available,
3866 that is used, so this is the easiest way in many more cases now.
3868 gfrt = FFECOM_gfrtWHATEVER;
3869 break;
3871 gfrt contains the gfrt index of a library function to call, passing the
3872 argument(s) by value rather than by reference. Used when a more
3873 careful choice of library function is needed than that provided
3874 by the vanilla `break;'.
3876 return expr_tree;
3878 The expr_tree has been completely set up and is ready to be returned
3879 as is. No further actions are taken. Use this when the tree is not
3880 in the simple form for one of the arity_n labels. */
3882 /* For info on how the switch statement cases were written, see the files
3883 enclosed in comments below the switch statement. */
3885 codegen_imp = ffebld_symter_implementation (ffebld_left (expr));
3886 gfrt = ffeintrin_gfrt_direct (codegen_imp);
3887 if (gfrt == FFECOM_gfrt)
3888 gfrt = ffeintrin_gfrt_indirect (codegen_imp);
3890 switch (codegen_imp)
3892 case FFEINTRIN_impABS:
3893 case FFEINTRIN_impCABS:
3894 case FFEINTRIN_impCDABS:
3895 case FFEINTRIN_impDABS:
3896 case FFEINTRIN_impIABS:
3897 if (ffeinfo_basictype (ffebld_info (arg1))
3898 == FFEINFO_basictypeCOMPLEX)
3900 if (kt == FFEINFO_kindtypeREAL1)
3901 gfrt = FFECOM_gfrtCABS;
3902 else if (kt == FFEINFO_kindtypeREAL2)
3903 gfrt = FFECOM_gfrtCDABS;
3904 break;
3906 return ffecom_1 (ABS_EXPR, tree_type,
3907 convert (tree_type, ffecom_expr (arg1)));
3909 case FFEINTRIN_impACOS:
3910 case FFEINTRIN_impDACOS:
3911 break;
3913 case FFEINTRIN_impAIMAG:
3914 case FFEINTRIN_impDIMAG:
3915 case FFEINTRIN_impIMAGPART:
3916 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
3917 arg1_type = TREE_TYPE (arg1_type);
3918 else
3919 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
3921 return
3922 convert (tree_type,
3923 ffecom_1 (IMAGPART_EXPR, arg1_type,
3924 ffecom_expr (arg1)));
3926 case FFEINTRIN_impAINT:
3927 case FFEINTRIN_impDINT:
3928 #if 0
3929 /* ~~Someday implement FIX_TRUNC_EXPR yielding same type as arg. */
3930 return ffecom_1 (FIX_TRUNC_EXPR, tree_type, ffecom_expr (arg1));
3931 #else /* in the meantime, must use floor to avoid range problems with ints */
3932 /* r__1 = r1 >= 0 ? floor(r1) : -floor(-r1); */
3933 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
3934 return
3935 convert (tree_type,
3936 ffecom_3 (COND_EXPR, double_type_node,
3937 ffecom_truth_value
3938 (ffecom_2 (GE_EXPR, integer_type_node,
3939 saved_expr1,
3940 convert (arg1_type,
3941 ffecom_float_zero_))),
3942 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
3943 build_tree_list (NULL_TREE,
3944 convert (double_type_node,
3945 saved_expr1)),
3946 NULL_TREE),
3947 ffecom_1 (NEGATE_EXPR, double_type_node,
3948 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
3949 build_tree_list (NULL_TREE,
3950 convert (double_type_node,
3951 ffecom_1 (NEGATE_EXPR,
3952 arg1_type,
3953 saved_expr1))),
3954 NULL_TREE)
3957 #endif
3959 case FFEINTRIN_impANINT:
3960 case FFEINTRIN_impDNINT:
3961 #if 0 /* This way of doing it won't handle real
3962 numbers of large magnitudes. */
3963 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
3964 expr_tree = convert (tree_type,
3965 convert (integer_type_node,
3966 ffecom_3 (COND_EXPR, tree_type,
3967 ffecom_truth_value
3968 (ffecom_2 (GE_EXPR,
3969 integer_type_node,
3970 saved_expr1,
3971 ffecom_float_zero_)),
3972 ffecom_2 (PLUS_EXPR,
3973 tree_type,
3974 saved_expr1,
3975 ffecom_float_half_),
3976 ffecom_2 (MINUS_EXPR,
3977 tree_type,
3978 saved_expr1,
3979 ffecom_float_half_))));
3980 return expr_tree;
3981 #else /* So we instead call floor. */
3982 /* r__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1) */
3983 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
3984 return
3985 convert (tree_type,
3986 ffecom_3 (COND_EXPR, double_type_node,
3987 ffecom_truth_value
3988 (ffecom_2 (GE_EXPR, integer_type_node,
3989 saved_expr1,
3990 convert (arg1_type,
3991 ffecom_float_zero_))),
3992 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
3993 build_tree_list (NULL_TREE,
3994 convert (double_type_node,
3995 ffecom_2 (PLUS_EXPR,
3996 arg1_type,
3997 saved_expr1,
3998 convert (arg1_type,
3999 ffecom_float_half_)))),
4000 NULL_TREE),
4001 ffecom_1 (NEGATE_EXPR, double_type_node,
4002 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4003 build_tree_list (NULL_TREE,
4004 convert (double_type_node,
4005 ffecom_2 (MINUS_EXPR,
4006 arg1_type,
4007 convert (arg1_type,
4008 ffecom_float_half_),
4009 saved_expr1))),
4010 NULL_TREE))
4013 #endif
4015 case FFEINTRIN_impASIN:
4016 case FFEINTRIN_impDASIN:
4017 case FFEINTRIN_impATAN:
4018 case FFEINTRIN_impDATAN:
4019 case FFEINTRIN_impATAN2:
4020 case FFEINTRIN_impDATAN2:
4021 break;
4023 case FFEINTRIN_impCHAR:
4024 case FFEINTRIN_impACHAR:
4025 tempvar = ffebld_nonter_hook (expr);
4026 assert (tempvar);
4028 tree tmv = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (tempvar)));
4030 expr_tree = ffecom_modify (tmv,
4031 ffecom_2 (ARRAY_REF, tmv, tempvar,
4032 integer_one_node),
4033 convert (tmv, ffecom_expr (arg1)));
4035 expr_tree = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar),
4036 expr_tree,
4037 tempvar);
4038 expr_tree = ffecom_1 (ADDR_EXPR,
4039 build_pointer_type (TREE_TYPE (expr_tree)),
4040 expr_tree);
4041 return expr_tree;
4043 case FFEINTRIN_impCMPLX:
4044 case FFEINTRIN_impDCMPLX:
4045 if (arg2 == NULL)
4046 return
4047 convert (tree_type, ffecom_expr (arg1));
4049 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4050 return
4051 ffecom_2 (COMPLEX_EXPR, tree_type,
4052 convert (real_type, ffecom_expr (arg1)),
4053 convert (real_type,
4054 ffecom_expr (arg2)));
4056 case FFEINTRIN_impCOMPLEX:
4057 return
4058 ffecom_2 (COMPLEX_EXPR, tree_type,
4059 ffecom_expr (arg1),
4060 ffecom_expr (arg2));
4062 case FFEINTRIN_impCONJG:
4063 case FFEINTRIN_impDCONJG:
4065 tree arg1_tree;
4067 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4068 arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4069 return
4070 ffecom_2 (COMPLEX_EXPR, tree_type,
4071 ffecom_1 (REALPART_EXPR, real_type, arg1_tree),
4072 ffecom_1 (NEGATE_EXPR, real_type,
4073 ffecom_1 (IMAGPART_EXPR, real_type, arg1_tree)));
4076 case FFEINTRIN_impCOS:
4077 case FFEINTRIN_impCCOS:
4078 case FFEINTRIN_impCDCOS:
4079 case FFEINTRIN_impDCOS:
4080 if (bt == FFEINFO_basictypeCOMPLEX)
4082 if (kt == FFEINFO_kindtypeREAL1)
4083 gfrt = FFECOM_gfrtCCOS; /* Overlapping result okay. */
4084 else if (kt == FFEINFO_kindtypeREAL2)
4085 gfrt = FFECOM_gfrtCDCOS; /* Overlapping result okay. */
4087 break;
4089 case FFEINTRIN_impCOSH:
4090 case FFEINTRIN_impDCOSH:
4091 break;
4093 case FFEINTRIN_impDBLE:
4094 case FFEINTRIN_impDFLOAT:
4095 case FFEINTRIN_impDREAL:
4096 case FFEINTRIN_impFLOAT:
4097 case FFEINTRIN_impIDINT:
4098 case FFEINTRIN_impIFIX:
4099 case FFEINTRIN_impINT2:
4100 case FFEINTRIN_impINT8:
4101 case FFEINTRIN_impINT:
4102 case FFEINTRIN_impLONG:
4103 case FFEINTRIN_impREAL:
4104 case FFEINTRIN_impSHORT:
4105 case FFEINTRIN_impSNGL:
4106 return convert (tree_type, ffecom_expr (arg1));
4108 case FFEINTRIN_impDIM:
4109 case FFEINTRIN_impDDIM:
4110 case FFEINTRIN_impIDIM:
4111 saved_expr1 = ffecom_save_tree (convert (tree_type,
4112 ffecom_expr (arg1)));
4113 saved_expr2 = ffecom_save_tree (convert (tree_type,
4114 ffecom_expr (arg2)));
4115 return
4116 ffecom_3 (COND_EXPR, tree_type,
4117 ffecom_truth_value
4118 (ffecom_2 (GT_EXPR, integer_type_node,
4119 saved_expr1,
4120 saved_expr2)),
4121 ffecom_2 (MINUS_EXPR, tree_type,
4122 saved_expr1,
4123 saved_expr2),
4124 convert (tree_type, ffecom_float_zero_));
4126 case FFEINTRIN_impDPROD:
4127 return
4128 ffecom_2 (MULT_EXPR, tree_type,
4129 convert (tree_type, ffecom_expr (arg1)),
4130 convert (tree_type, ffecom_expr (arg2)));
4132 case FFEINTRIN_impEXP:
4133 case FFEINTRIN_impCDEXP:
4134 case FFEINTRIN_impCEXP:
4135 case FFEINTRIN_impDEXP:
4136 if (bt == FFEINFO_basictypeCOMPLEX)
4138 if (kt == FFEINFO_kindtypeREAL1)
4139 gfrt = FFECOM_gfrtCEXP; /* Overlapping result okay. */
4140 else if (kt == FFEINFO_kindtypeREAL2)
4141 gfrt = FFECOM_gfrtCDEXP; /* Overlapping result okay. */
4143 break;
4145 case FFEINTRIN_impICHAR:
4146 case FFEINTRIN_impIACHAR:
4147 #if 0 /* The simple approach. */
4148 ffecom_char_args_ (&expr_tree, &saved_expr1 /* Ignored */ , arg1);
4149 expr_tree
4150 = ffecom_1 (INDIRECT_REF,
4151 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4152 expr_tree);
4153 expr_tree
4154 = ffecom_2 (ARRAY_REF,
4155 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4156 expr_tree,
4157 integer_one_node);
4158 return convert (tree_type, expr_tree);
4159 #else /* The more interesting (and more optimal) approach. */
4160 expr_tree = ffecom_intrinsic_ichar_ (tree_type, arg1, &saved_expr1);
4161 expr_tree = ffecom_3 (COND_EXPR, tree_type,
4162 saved_expr1,
4163 expr_tree,
4164 convert (tree_type, integer_zero_node));
4165 return expr_tree;
4166 #endif
4168 case FFEINTRIN_impINDEX:
4169 break;
4171 case FFEINTRIN_impLEN:
4172 #if 0
4173 break; /* The simple approach. */
4174 #else
4175 return ffecom_intrinsic_len_ (arg1); /* The more optimal approach. */
4176 #endif
4178 case FFEINTRIN_impLGE:
4179 case FFEINTRIN_impLGT:
4180 case FFEINTRIN_impLLE:
4181 case FFEINTRIN_impLLT:
4182 break;
4184 case FFEINTRIN_impLOG:
4185 case FFEINTRIN_impALOG:
4186 case FFEINTRIN_impCDLOG:
4187 case FFEINTRIN_impCLOG:
4188 case FFEINTRIN_impDLOG:
4189 if (bt == FFEINFO_basictypeCOMPLEX)
4191 if (kt == FFEINFO_kindtypeREAL1)
4192 gfrt = FFECOM_gfrtCLOG; /* Overlapping result okay. */
4193 else if (kt == FFEINFO_kindtypeREAL2)
4194 gfrt = FFECOM_gfrtCDLOG; /* Overlapping result okay. */
4196 break;
4198 case FFEINTRIN_impLOG10:
4199 case FFEINTRIN_impALOG10:
4200 case FFEINTRIN_impDLOG10:
4201 if (gfrt != FFECOM_gfrt)
4202 break; /* Already picked one, stick with it. */
4204 if (kt == FFEINFO_kindtypeREAL1)
4205 /* We used to call FFECOM_gfrtALOG10 here. */
4206 gfrt = FFECOM_gfrtL_LOG10;
4207 else if (kt == FFEINFO_kindtypeREAL2)
4208 /* We used to call FFECOM_gfrtDLOG10 here. */
4209 gfrt = FFECOM_gfrtL_LOG10;
4210 break;
4212 case FFEINTRIN_impMAX:
4213 case FFEINTRIN_impAMAX0:
4214 case FFEINTRIN_impAMAX1:
4215 case FFEINTRIN_impDMAX1:
4216 case FFEINTRIN_impMAX0:
4217 case FFEINTRIN_impMAX1:
4218 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4219 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4220 else
4221 arg1_type = tree_type;
4222 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4223 convert (arg1_type, ffecom_expr (arg1)),
4224 convert (arg1_type, ffecom_expr (arg2)));
4225 for (; list != NULL; list = ffebld_trail (list))
4227 if ((ffebld_head (list) == NULL)
4228 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4229 continue;
4230 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4231 expr_tree,
4232 convert (arg1_type,
4233 ffecom_expr (ffebld_head (list))));
4235 return convert (tree_type, expr_tree);
4237 case FFEINTRIN_impMIN:
4238 case FFEINTRIN_impAMIN0:
4239 case FFEINTRIN_impAMIN1:
4240 case FFEINTRIN_impDMIN1:
4241 case FFEINTRIN_impMIN0:
4242 case FFEINTRIN_impMIN1:
4243 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4244 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4245 else
4246 arg1_type = tree_type;
4247 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4248 convert (arg1_type, ffecom_expr (arg1)),
4249 convert (arg1_type, ffecom_expr (arg2)));
4250 for (; list != NULL; list = ffebld_trail (list))
4252 if ((ffebld_head (list) == NULL)
4253 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4254 continue;
4255 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4256 expr_tree,
4257 convert (arg1_type,
4258 ffecom_expr (ffebld_head (list))));
4260 return convert (tree_type, expr_tree);
4262 case FFEINTRIN_impMOD:
4263 case FFEINTRIN_impAMOD:
4264 case FFEINTRIN_impDMOD:
4265 if (bt != FFEINFO_basictypeREAL)
4266 return ffecom_2 (TRUNC_MOD_EXPR, tree_type,
4267 convert (tree_type, ffecom_expr (arg1)),
4268 convert (tree_type, ffecom_expr (arg2)));
4270 if (kt == FFEINFO_kindtypeREAL1)
4271 /* We used to call FFECOM_gfrtAMOD here. */
4272 gfrt = FFECOM_gfrtL_FMOD;
4273 else if (kt == FFEINFO_kindtypeREAL2)
4274 /* We used to call FFECOM_gfrtDMOD here. */
4275 gfrt = FFECOM_gfrtL_FMOD;
4276 break;
4278 case FFEINTRIN_impNINT:
4279 case FFEINTRIN_impIDNINT:
4280 #if 0
4281 /* ~~Ideally FIX_ROUND_EXPR would be implemented, but it ain't yet. */
4282 return ffecom_1 (FIX_ROUND_EXPR, tree_type, ffecom_expr (arg1));
4283 #else
4284 /* i__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1); */
4285 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4286 return
4287 convert (ffecom_integer_type_node,
4288 ffecom_3 (COND_EXPR, arg1_type,
4289 ffecom_truth_value
4290 (ffecom_2 (GE_EXPR, integer_type_node,
4291 saved_expr1,
4292 convert (arg1_type,
4293 ffecom_float_zero_))),
4294 ffecom_2 (PLUS_EXPR, arg1_type,
4295 saved_expr1,
4296 convert (arg1_type,
4297 ffecom_float_half_)),
4298 ffecom_2 (MINUS_EXPR, arg1_type,
4299 saved_expr1,
4300 convert (arg1_type,
4301 ffecom_float_half_))));
4302 #endif
4304 case FFEINTRIN_impSIGN:
4305 case FFEINTRIN_impDSIGN:
4306 case FFEINTRIN_impISIGN:
4308 tree arg2_tree = ffecom_expr (arg2);
4310 saved_expr1
4311 = ffecom_save_tree
4312 (ffecom_1 (ABS_EXPR, tree_type,
4313 convert (tree_type,
4314 ffecom_expr (arg1))));
4315 expr_tree
4316 = ffecom_3 (COND_EXPR, tree_type,
4317 ffecom_truth_value
4318 (ffecom_2 (GE_EXPR, integer_type_node,
4319 arg2_tree,
4320 convert (TREE_TYPE (arg2_tree),
4321 integer_zero_node))),
4322 saved_expr1,
4323 ffecom_1 (NEGATE_EXPR, tree_type, saved_expr1));
4324 /* Make sure SAVE_EXPRs get referenced early enough. */
4325 expr_tree
4326 = ffecom_2 (COMPOUND_EXPR, tree_type,
4327 convert (void_type_node, saved_expr1),
4328 expr_tree);
4330 return expr_tree;
4332 case FFEINTRIN_impSIN:
4333 case FFEINTRIN_impCDSIN:
4334 case FFEINTRIN_impCSIN:
4335 case FFEINTRIN_impDSIN:
4336 if (bt == FFEINFO_basictypeCOMPLEX)
4338 if (kt == FFEINFO_kindtypeREAL1)
4339 gfrt = FFECOM_gfrtCSIN; /* Overlapping result okay. */
4340 else if (kt == FFEINFO_kindtypeREAL2)
4341 gfrt = FFECOM_gfrtCDSIN; /* Overlapping result okay. */
4343 break;
4345 case FFEINTRIN_impSINH:
4346 case FFEINTRIN_impDSINH:
4347 break;
4349 case FFEINTRIN_impSQRT:
4350 case FFEINTRIN_impCDSQRT:
4351 case FFEINTRIN_impCSQRT:
4352 case FFEINTRIN_impDSQRT:
4353 if (bt == FFEINFO_basictypeCOMPLEX)
4355 if (kt == FFEINFO_kindtypeREAL1)
4356 gfrt = FFECOM_gfrtCSQRT; /* Overlapping result okay. */
4357 else if (kt == FFEINFO_kindtypeREAL2)
4358 gfrt = FFECOM_gfrtCDSQRT; /* Overlapping result okay. */
4360 break;
4362 case FFEINTRIN_impTAN:
4363 case FFEINTRIN_impDTAN:
4364 case FFEINTRIN_impTANH:
4365 case FFEINTRIN_impDTANH:
4366 break;
4368 case FFEINTRIN_impREALPART:
4369 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4370 arg1_type = TREE_TYPE (arg1_type);
4371 else
4372 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4374 return
4375 convert (tree_type,
4376 ffecom_1 (REALPART_EXPR, arg1_type,
4377 ffecom_expr (arg1)));
4379 case FFEINTRIN_impIAND:
4380 case FFEINTRIN_impAND:
4381 return ffecom_2 (BIT_AND_EXPR, tree_type,
4382 convert (tree_type,
4383 ffecom_expr (arg1)),
4384 convert (tree_type,
4385 ffecom_expr (arg2)));
4387 case FFEINTRIN_impIOR:
4388 case FFEINTRIN_impOR:
4389 return ffecom_2 (BIT_IOR_EXPR, tree_type,
4390 convert (tree_type,
4391 ffecom_expr (arg1)),
4392 convert (tree_type,
4393 ffecom_expr (arg2)));
4395 case FFEINTRIN_impIEOR:
4396 case FFEINTRIN_impXOR:
4397 return ffecom_2 (BIT_XOR_EXPR, tree_type,
4398 convert (tree_type,
4399 ffecom_expr (arg1)),
4400 convert (tree_type,
4401 ffecom_expr (arg2)));
4403 case FFEINTRIN_impLSHIFT:
4404 return ffecom_2 (LSHIFT_EXPR, tree_type,
4405 ffecom_expr (arg1),
4406 convert (integer_type_node,
4407 ffecom_expr (arg2)));
4409 case FFEINTRIN_impRSHIFT:
4410 return ffecom_2 (RSHIFT_EXPR, tree_type,
4411 ffecom_expr (arg1),
4412 convert (integer_type_node,
4413 ffecom_expr (arg2)));
4415 case FFEINTRIN_impNOT:
4416 return ffecom_1 (BIT_NOT_EXPR, tree_type, ffecom_expr (arg1));
4418 case FFEINTRIN_impBIT_SIZE:
4419 return convert (tree_type, TYPE_SIZE (arg1_type));
4421 case FFEINTRIN_impBTEST:
4423 ffetargetLogical1 target_true;
4424 ffetargetLogical1 target_false;
4425 tree true_tree;
4426 tree false_tree;
4428 ffetarget_logical1 (&target_true, TRUE);
4429 ffetarget_logical1 (&target_false, FALSE);
4430 if (target_true == 1)
4431 true_tree = convert (tree_type, integer_one_node);
4432 else
4433 true_tree = convert (tree_type, build_int_2 (target_true, 0));
4434 if (target_false == 0)
4435 false_tree = convert (tree_type, integer_zero_node);
4436 else
4437 false_tree = convert (tree_type, build_int_2 (target_false, 0));
4439 return
4440 ffecom_3 (COND_EXPR, tree_type,
4441 ffecom_truth_value
4442 (ffecom_2 (EQ_EXPR, integer_type_node,
4443 ffecom_2 (BIT_AND_EXPR, arg1_type,
4444 ffecom_expr (arg1),
4445 ffecom_2 (LSHIFT_EXPR, arg1_type,
4446 convert (arg1_type,
4447 integer_one_node),
4448 convert (integer_type_node,
4449 ffecom_expr (arg2)))),
4450 convert (arg1_type,
4451 integer_zero_node))),
4452 false_tree,
4453 true_tree);
4456 case FFEINTRIN_impIBCLR:
4457 return
4458 ffecom_2 (BIT_AND_EXPR, tree_type,
4459 ffecom_expr (arg1),
4460 ffecom_1 (BIT_NOT_EXPR, tree_type,
4461 ffecom_2 (LSHIFT_EXPR, tree_type,
4462 convert (tree_type,
4463 integer_one_node),
4464 convert (integer_type_node,
4465 ffecom_expr (arg2)))));
4467 case FFEINTRIN_impIBITS:
4469 tree arg3_tree = ffecom_save_tree (convert (integer_type_node,
4470 ffecom_expr (arg3)));
4471 tree uns_type
4472 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4474 expr_tree
4475 = ffecom_2 (BIT_AND_EXPR, tree_type,
4476 ffecom_2 (RSHIFT_EXPR, tree_type,
4477 ffecom_expr (arg1),
4478 convert (integer_type_node,
4479 ffecom_expr (arg2))),
4480 convert (tree_type,
4481 ffecom_2 (RSHIFT_EXPR, uns_type,
4482 ffecom_1 (BIT_NOT_EXPR,
4483 uns_type,
4484 convert (uns_type,
4485 integer_zero_node)),
4486 ffecom_2 (MINUS_EXPR,
4487 integer_type_node,
4488 TYPE_SIZE (uns_type),
4489 arg3_tree))));
4490 /* Fix up, because the RSHIFT_EXPR above can't shift over TYPE_SIZE. */
4491 expr_tree
4492 = ffecom_3 (COND_EXPR, tree_type,
4493 ffecom_truth_value
4494 (ffecom_2 (NE_EXPR, integer_type_node,
4495 arg3_tree,
4496 integer_zero_node)),
4497 expr_tree,
4498 convert (tree_type, integer_zero_node));
4500 return expr_tree;
4502 case FFEINTRIN_impIBSET:
4503 return
4504 ffecom_2 (BIT_IOR_EXPR, tree_type,
4505 ffecom_expr (arg1),
4506 ffecom_2 (LSHIFT_EXPR, tree_type,
4507 convert (tree_type, integer_one_node),
4508 convert (integer_type_node,
4509 ffecom_expr (arg2))));
4511 case FFEINTRIN_impISHFT:
4513 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4514 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4515 ffecom_expr (arg2)));
4516 tree uns_type
4517 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4519 expr_tree
4520 = ffecom_3 (COND_EXPR, tree_type,
4521 ffecom_truth_value
4522 (ffecom_2 (GE_EXPR, integer_type_node,
4523 arg2_tree,
4524 integer_zero_node)),
4525 ffecom_2 (LSHIFT_EXPR, tree_type,
4526 arg1_tree,
4527 arg2_tree),
4528 convert (tree_type,
4529 ffecom_2 (RSHIFT_EXPR, uns_type,
4530 convert (uns_type, arg1_tree),
4531 ffecom_1 (NEGATE_EXPR,
4532 integer_type_node,
4533 arg2_tree))));
4534 /* Fix up, because {L|R}SHIFT_EXPR don't go over TYPE_SIZE bounds. */
4535 expr_tree
4536 = ffecom_3 (COND_EXPR, tree_type,
4537 ffecom_truth_value
4538 (ffecom_2 (NE_EXPR, integer_type_node,
4539 ffecom_1 (ABS_EXPR,
4540 integer_type_node,
4541 arg2_tree),
4542 TYPE_SIZE (uns_type))),
4543 expr_tree,
4544 convert (tree_type, integer_zero_node));
4545 /* Make sure SAVE_EXPRs get referenced early enough. */
4546 expr_tree
4547 = ffecom_2 (COMPOUND_EXPR, tree_type,
4548 convert (void_type_node, arg1_tree),
4549 ffecom_2 (COMPOUND_EXPR, tree_type,
4550 convert (void_type_node, arg2_tree),
4551 expr_tree));
4553 return expr_tree;
4555 case FFEINTRIN_impISHFTC:
4557 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4558 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4559 ffecom_expr (arg2)));
4560 tree arg3_tree = (arg3 == NULL) ? TYPE_SIZE (tree_type)
4561 : ffecom_save_tree (convert (integer_type_node, ffecom_expr (arg3)));
4562 tree shift_neg;
4563 tree shift_pos;
4564 tree mask_arg1;
4565 tree masked_arg1;
4566 tree uns_type
4567 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4569 mask_arg1
4570 = ffecom_2 (LSHIFT_EXPR, tree_type,
4571 ffecom_1 (BIT_NOT_EXPR, tree_type,
4572 convert (tree_type, integer_zero_node)),
4573 arg3_tree);
4574 /* Fix up, because LSHIFT_EXPR above can't shift over TYPE_SIZE. */
4575 mask_arg1
4576 = ffecom_3 (COND_EXPR, tree_type,
4577 ffecom_truth_value
4578 (ffecom_2 (NE_EXPR, integer_type_node,
4579 arg3_tree,
4580 TYPE_SIZE (uns_type))),
4581 mask_arg1,
4582 convert (tree_type, integer_zero_node));
4583 mask_arg1 = ffecom_save_tree (mask_arg1);
4584 masked_arg1
4585 = ffecom_2 (BIT_AND_EXPR, tree_type,
4586 arg1_tree,
4587 ffecom_1 (BIT_NOT_EXPR, tree_type,
4588 mask_arg1));
4589 masked_arg1 = ffecom_save_tree (masked_arg1);
4590 shift_neg
4591 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4592 convert (tree_type,
4593 ffecom_2 (RSHIFT_EXPR, uns_type,
4594 convert (uns_type, masked_arg1),
4595 ffecom_1 (NEGATE_EXPR,
4596 integer_type_node,
4597 arg2_tree))),
4598 ffecom_2 (LSHIFT_EXPR, tree_type,
4599 arg1_tree,
4600 ffecom_2 (PLUS_EXPR, integer_type_node,
4601 arg2_tree,
4602 arg3_tree)));
4603 shift_pos
4604 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4605 ffecom_2 (LSHIFT_EXPR, tree_type,
4606 arg1_tree,
4607 arg2_tree),
4608 convert (tree_type,
4609 ffecom_2 (RSHIFT_EXPR, uns_type,
4610 convert (uns_type, masked_arg1),
4611 ffecom_2 (MINUS_EXPR,
4612 integer_type_node,
4613 arg3_tree,
4614 arg2_tree))));
4615 expr_tree
4616 = ffecom_3 (COND_EXPR, tree_type,
4617 ffecom_truth_value
4618 (ffecom_2 (LT_EXPR, integer_type_node,
4619 arg2_tree,
4620 integer_zero_node)),
4621 shift_neg,
4622 shift_pos);
4623 expr_tree
4624 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4625 ffecom_2 (BIT_AND_EXPR, tree_type,
4626 mask_arg1,
4627 arg1_tree),
4628 ffecom_2 (BIT_AND_EXPR, tree_type,
4629 ffecom_1 (BIT_NOT_EXPR, tree_type,
4630 mask_arg1),
4631 expr_tree));
4632 expr_tree
4633 = ffecom_3 (COND_EXPR, tree_type,
4634 ffecom_truth_value
4635 (ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
4636 ffecom_2 (EQ_EXPR, integer_type_node,
4637 ffecom_1 (ABS_EXPR,
4638 integer_type_node,
4639 arg2_tree),
4640 arg3_tree),
4641 ffecom_2 (EQ_EXPR, integer_type_node,
4642 arg2_tree,
4643 integer_zero_node))),
4644 arg1_tree,
4645 expr_tree);
4646 /* Make sure SAVE_EXPRs get referenced early enough. */
4647 expr_tree
4648 = ffecom_2 (COMPOUND_EXPR, tree_type,
4649 convert (void_type_node, arg1_tree),
4650 ffecom_2 (COMPOUND_EXPR, tree_type,
4651 convert (void_type_node, arg2_tree),
4652 ffecom_2 (COMPOUND_EXPR, tree_type,
4653 convert (void_type_node,
4654 mask_arg1),
4655 ffecom_2 (COMPOUND_EXPR, tree_type,
4656 convert (void_type_node,
4657 masked_arg1),
4658 expr_tree))));
4659 expr_tree
4660 = ffecom_2 (COMPOUND_EXPR, tree_type,
4661 convert (void_type_node,
4662 arg3_tree),
4663 expr_tree);
4665 return expr_tree;
4667 case FFEINTRIN_impLOC:
4669 tree arg1_tree = ffecom_expr (arg1);
4671 expr_tree
4672 = convert (tree_type,
4673 ffecom_1 (ADDR_EXPR,
4674 build_pointer_type (TREE_TYPE (arg1_tree)),
4675 arg1_tree));
4677 return expr_tree;
4679 case FFEINTRIN_impMVBITS:
4681 tree arg1_tree;
4682 tree arg2_tree;
4683 tree arg3_tree;
4684 ffebld arg4 = ffebld_head (ffebld_trail (list));
4685 tree arg4_tree;
4686 tree arg4_type;
4687 ffebld arg5 = ffebld_head (ffebld_trail (ffebld_trail (list)));
4688 tree arg5_tree;
4689 tree prep_arg1;
4690 tree prep_arg4;
4691 tree arg5_plus_arg3;
4693 arg2_tree = convert (integer_type_node,
4694 ffecom_expr (arg2));
4695 arg3_tree = ffecom_save_tree (convert (integer_type_node,
4696 ffecom_expr (arg3)));
4697 arg4_tree = ffecom_expr_rw (NULL_TREE, arg4);
4698 arg4_type = TREE_TYPE (arg4_tree);
4700 arg1_tree = ffecom_save_tree (convert (arg4_type,
4701 ffecom_expr (arg1)));
4703 arg5_tree = ffecom_save_tree (convert (integer_type_node,
4704 ffecom_expr (arg5)));
4706 prep_arg1
4707 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4708 ffecom_2 (BIT_AND_EXPR, arg4_type,
4709 ffecom_2 (RSHIFT_EXPR, arg4_type,
4710 arg1_tree,
4711 arg2_tree),
4712 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4713 ffecom_2 (LSHIFT_EXPR, arg4_type,
4714 ffecom_1 (BIT_NOT_EXPR,
4715 arg4_type,
4716 convert
4717 (arg4_type,
4718 integer_zero_node)),
4719 arg3_tree))),
4720 arg5_tree);
4721 arg5_plus_arg3
4722 = ffecom_save_tree (ffecom_2 (PLUS_EXPR, arg4_type,
4723 arg5_tree,
4724 arg3_tree));
4725 prep_arg4
4726 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4727 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4728 convert (arg4_type,
4729 integer_zero_node)),
4730 arg5_plus_arg3);
4731 /* Fix up, because LSHIFT_EXPR above can't shift over TYPE_SIZE. */
4732 prep_arg4
4733 = ffecom_3 (COND_EXPR, arg4_type,
4734 ffecom_truth_value
4735 (ffecom_2 (NE_EXPR, integer_type_node,
4736 arg5_plus_arg3,
4737 convert (TREE_TYPE (arg5_plus_arg3),
4738 TYPE_SIZE (arg4_type)))),
4739 prep_arg4,
4740 convert (arg4_type, integer_zero_node));
4741 prep_arg4
4742 = ffecom_2 (BIT_AND_EXPR, arg4_type,
4743 arg4_tree,
4744 ffecom_2 (BIT_IOR_EXPR, arg4_type,
4745 prep_arg4,
4746 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4747 ffecom_2 (LSHIFT_EXPR, arg4_type,
4748 ffecom_1 (BIT_NOT_EXPR,
4749 arg4_type,
4750 convert
4751 (arg4_type,
4752 integer_zero_node)),
4753 arg5_tree))));
4754 prep_arg1
4755 = ffecom_2 (BIT_IOR_EXPR, arg4_type,
4756 prep_arg1,
4757 prep_arg4);
4758 /* Fix up (twice), because LSHIFT_EXPR above
4759 can't shift over TYPE_SIZE. */
4760 prep_arg1
4761 = ffecom_3 (COND_EXPR, arg4_type,
4762 ffecom_truth_value
4763 (ffecom_2 (NE_EXPR, integer_type_node,
4764 arg3_tree,
4765 convert (TREE_TYPE (arg3_tree),
4766 integer_zero_node))),
4767 prep_arg1,
4768 arg4_tree);
4769 prep_arg1
4770 = ffecom_3 (COND_EXPR, arg4_type,
4771 ffecom_truth_value
4772 (ffecom_2 (NE_EXPR, integer_type_node,
4773 arg3_tree,
4774 convert (TREE_TYPE (arg3_tree),
4775 TYPE_SIZE (arg4_type)))),
4776 prep_arg1,
4777 arg1_tree);
4778 expr_tree
4779 = ffecom_2s (MODIFY_EXPR, void_type_node,
4780 arg4_tree,
4781 prep_arg1);
4782 /* Make sure SAVE_EXPRs get referenced early enough. */
4783 expr_tree
4784 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4785 arg1_tree,
4786 ffecom_2 (COMPOUND_EXPR, void_type_node,
4787 arg3_tree,
4788 ffecom_2 (COMPOUND_EXPR, void_type_node,
4789 arg5_tree,
4790 ffecom_2 (COMPOUND_EXPR, void_type_node,
4791 arg5_plus_arg3,
4792 expr_tree))));
4793 expr_tree
4794 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4795 arg4_tree,
4796 expr_tree);
4799 return expr_tree;
4801 case FFEINTRIN_impDERF:
4802 case FFEINTRIN_impERF:
4803 case FFEINTRIN_impDERFC:
4804 case FFEINTRIN_impERFC:
4805 break;
4807 case FFEINTRIN_impIARGC:
4808 /* extern int xargc; i__1 = xargc - 1; */
4809 expr_tree = ffecom_2 (MINUS_EXPR, TREE_TYPE (ffecom_tree_xargc_),
4810 ffecom_tree_xargc_,
4811 convert (TREE_TYPE (ffecom_tree_xargc_),
4812 integer_one_node));
4813 return expr_tree;
4815 case FFEINTRIN_impSIGNAL_func:
4816 case FFEINTRIN_impSIGNAL_subr:
4818 tree arg1_tree;
4819 tree arg2_tree;
4820 tree arg3_tree;
4822 arg1_tree = convert (ffecom_f2c_integer_type_node,
4823 ffecom_expr (arg1));
4824 arg1_tree = ffecom_1 (ADDR_EXPR,
4825 build_pointer_type (TREE_TYPE (arg1_tree)),
4826 arg1_tree);
4828 /* Pass procedure as a pointer to it, anything else by value. */
4829 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4830 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4831 else
4832 arg2_tree = ffecom_ptr_to_expr (arg2);
4833 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4834 arg2_tree);
4836 if (arg3 != NULL)
4837 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
4838 else
4839 arg3_tree = NULL_TREE;
4841 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4842 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4843 TREE_CHAIN (arg1_tree) = arg2_tree;
4845 expr_tree
4846 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4847 ffecom_gfrt_kindtype (gfrt),
4848 FALSE,
4849 ((codegen_imp == FFEINTRIN_impSIGNAL_subr) ?
4850 NULL_TREE :
4851 tree_type),
4852 arg1_tree,
4853 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4854 ffebld_nonter_hook (expr));
4856 if (arg3_tree != NULL_TREE)
4857 expr_tree
4858 = ffecom_modify (NULL_TREE, arg3_tree,
4859 convert (TREE_TYPE (arg3_tree),
4860 expr_tree));
4862 return expr_tree;
4864 case FFEINTRIN_impALARM:
4866 tree arg1_tree;
4867 tree arg2_tree;
4868 tree arg3_tree;
4870 arg1_tree = convert (ffecom_f2c_integer_type_node,
4871 ffecom_expr (arg1));
4872 arg1_tree = ffecom_1 (ADDR_EXPR,
4873 build_pointer_type (TREE_TYPE (arg1_tree)),
4874 arg1_tree);
4876 /* Pass procedure as a pointer to it, anything else by value. */
4877 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4878 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4879 else
4880 arg2_tree = ffecom_ptr_to_expr (arg2);
4881 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4882 arg2_tree);
4884 if (arg3 != NULL)
4885 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
4886 else
4887 arg3_tree = NULL_TREE;
4889 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4890 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4891 TREE_CHAIN (arg1_tree) = arg2_tree;
4893 expr_tree
4894 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4895 ffecom_gfrt_kindtype (gfrt),
4896 FALSE,
4897 NULL_TREE,
4898 arg1_tree,
4899 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4900 ffebld_nonter_hook (expr));
4902 if (arg3_tree != NULL_TREE)
4903 expr_tree
4904 = ffecom_modify (NULL_TREE, arg3_tree,
4905 convert (TREE_TYPE (arg3_tree),
4906 expr_tree));
4908 return expr_tree;
4910 case FFEINTRIN_impCHDIR_subr:
4911 case FFEINTRIN_impFDATE_subr:
4912 case FFEINTRIN_impFGET_subr:
4913 case FFEINTRIN_impFPUT_subr:
4914 case FFEINTRIN_impGETCWD_subr:
4915 case FFEINTRIN_impHOSTNM_subr:
4916 case FFEINTRIN_impSYSTEM_subr:
4917 case FFEINTRIN_impUNLINK_subr:
4919 tree arg1_len = integer_zero_node;
4920 tree arg1_tree;
4921 tree arg2_tree;
4923 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
4925 if (arg2 != NULL)
4926 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
4927 else
4928 arg2_tree = NULL_TREE;
4930 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4931 arg1_len = build_tree_list (NULL_TREE, arg1_len);
4932 TREE_CHAIN (arg1_tree) = arg1_len;
4934 expr_tree
4935 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4936 ffecom_gfrt_kindtype (gfrt),
4937 FALSE,
4938 NULL_TREE,
4939 arg1_tree,
4940 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4941 ffebld_nonter_hook (expr));
4943 if (arg2_tree != NULL_TREE)
4944 expr_tree
4945 = ffecom_modify (NULL_TREE, arg2_tree,
4946 convert (TREE_TYPE (arg2_tree),
4947 expr_tree));
4949 return expr_tree;
4951 case FFEINTRIN_impEXIT:
4952 if (arg1 != NULL)
4953 break;
4955 expr_tree = build_tree_list (NULL_TREE,
4956 ffecom_1 (ADDR_EXPR,
4957 build_pointer_type
4958 (ffecom_integer_type_node),
4959 integer_zero_node));
4961 return
4962 ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4963 ffecom_gfrt_kindtype (gfrt),
4964 FALSE,
4965 void_type_node,
4966 expr_tree,
4967 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4968 ffebld_nonter_hook (expr));
4970 case FFEINTRIN_impFLUSH:
4971 if (arg1 == NULL)
4972 gfrt = FFECOM_gfrtFLUSH;
4973 else
4974 gfrt = FFECOM_gfrtFLUSH1;
4975 break;
4977 case FFEINTRIN_impCHMOD_subr:
4978 case FFEINTRIN_impLINK_subr:
4979 case FFEINTRIN_impRENAME_subr:
4980 case FFEINTRIN_impSYMLNK_subr:
4982 tree arg1_len = integer_zero_node;
4983 tree arg1_tree;
4984 tree arg2_len = integer_zero_node;
4985 tree arg2_tree;
4986 tree arg3_tree;
4988 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
4989 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
4990 if (arg3 != NULL)
4991 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
4992 else
4993 arg3_tree = NULL_TREE;
4995 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4996 arg1_len = build_tree_list (NULL_TREE, arg1_len);
4997 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4998 arg2_len = build_tree_list (NULL_TREE, arg2_len);
4999 TREE_CHAIN (arg1_tree) = arg2_tree;
5000 TREE_CHAIN (arg2_tree) = arg1_len;
5001 TREE_CHAIN (arg1_len) = arg2_len;
5002 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5003 ffecom_gfrt_kindtype (gfrt),
5004 FALSE,
5005 NULL_TREE,
5006 arg1_tree,
5007 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5008 ffebld_nonter_hook (expr));
5009 if (arg3_tree != NULL_TREE)
5010 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5011 convert (TREE_TYPE (arg3_tree),
5012 expr_tree));
5014 return expr_tree;
5016 case FFEINTRIN_impLSTAT_subr:
5017 case FFEINTRIN_impSTAT_subr:
5019 tree arg1_len = integer_zero_node;
5020 tree arg1_tree;
5021 tree arg2_tree;
5022 tree arg3_tree;
5024 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5026 arg2_tree = ffecom_ptr_to_expr (arg2);
5028 if (arg3 != NULL)
5029 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5030 else
5031 arg3_tree = NULL_TREE;
5033 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5034 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5035 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5036 TREE_CHAIN (arg1_tree) = arg2_tree;
5037 TREE_CHAIN (arg2_tree) = arg1_len;
5038 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5039 ffecom_gfrt_kindtype (gfrt),
5040 FALSE,
5041 NULL_TREE,
5042 arg1_tree,
5043 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5044 ffebld_nonter_hook (expr));
5045 if (arg3_tree != NULL_TREE)
5046 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5047 convert (TREE_TYPE (arg3_tree),
5048 expr_tree));
5050 return expr_tree;
5052 case FFEINTRIN_impFGETC_subr:
5053 case FFEINTRIN_impFPUTC_subr:
5055 tree arg1_tree;
5056 tree arg2_tree;
5057 tree arg2_len = integer_zero_node;
5058 tree arg3_tree;
5060 arg1_tree = convert (ffecom_f2c_integer_type_node,
5061 ffecom_expr (arg1));
5062 arg1_tree = ffecom_1 (ADDR_EXPR,
5063 build_pointer_type (TREE_TYPE (arg1_tree)),
5064 arg1_tree);
5066 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
5067 if (arg3 != NULL)
5068 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5069 else
5070 arg3_tree = NULL_TREE;
5072 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5073 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5074 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5075 TREE_CHAIN (arg1_tree) = arg2_tree;
5076 TREE_CHAIN (arg2_tree) = arg2_len;
5078 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5079 ffecom_gfrt_kindtype (gfrt),
5080 FALSE,
5081 NULL_TREE,
5082 arg1_tree,
5083 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5084 ffebld_nonter_hook (expr));
5085 if (arg3_tree != NULL_TREE)
5086 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5087 convert (TREE_TYPE (arg3_tree),
5088 expr_tree));
5090 return expr_tree;
5092 case FFEINTRIN_impFSTAT_subr:
5094 tree arg1_tree;
5095 tree arg2_tree;
5096 tree arg3_tree;
5098 arg1_tree = convert (ffecom_f2c_integer_type_node,
5099 ffecom_expr (arg1));
5100 arg1_tree = ffecom_1 (ADDR_EXPR,
5101 build_pointer_type (TREE_TYPE (arg1_tree)),
5102 arg1_tree);
5104 arg2_tree = convert (ffecom_f2c_ptr_to_integer_type_node,
5105 ffecom_ptr_to_expr (arg2));
5107 if (arg3 == NULL)
5108 arg3_tree = NULL_TREE;
5109 else
5110 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5112 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5113 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5114 TREE_CHAIN (arg1_tree) = arg2_tree;
5115 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5116 ffecom_gfrt_kindtype (gfrt),
5117 FALSE,
5118 NULL_TREE,
5119 arg1_tree,
5120 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5121 ffebld_nonter_hook (expr));
5122 if (arg3_tree != NULL_TREE) {
5123 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5124 convert (TREE_TYPE (arg3_tree),
5125 expr_tree));
5128 return expr_tree;
5130 case FFEINTRIN_impKILL_subr:
5132 tree arg1_tree;
5133 tree arg2_tree;
5134 tree arg3_tree;
5136 arg1_tree = convert (ffecom_f2c_integer_type_node,
5137 ffecom_expr (arg1));
5138 arg1_tree = ffecom_1 (ADDR_EXPR,
5139 build_pointer_type (TREE_TYPE (arg1_tree)),
5140 arg1_tree);
5142 arg2_tree = convert (ffecom_f2c_integer_type_node,
5143 ffecom_expr (arg2));
5144 arg2_tree = ffecom_1 (ADDR_EXPR,
5145 build_pointer_type (TREE_TYPE (arg2_tree)),
5146 arg2_tree);
5148 if (arg3 == NULL)
5149 arg3_tree = NULL_TREE;
5150 else
5151 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5153 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5154 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5155 TREE_CHAIN (arg1_tree) = arg2_tree;
5156 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5157 ffecom_gfrt_kindtype (gfrt),
5158 FALSE,
5159 NULL_TREE,
5160 arg1_tree,
5161 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5162 ffebld_nonter_hook (expr));
5163 if (arg3_tree != NULL_TREE) {
5164 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5165 convert (TREE_TYPE (arg3_tree),
5166 expr_tree));
5169 return expr_tree;
5171 case FFEINTRIN_impCTIME_subr:
5172 case FFEINTRIN_impTTYNAM_subr:
5174 tree arg1_len = integer_zero_node;
5175 tree arg1_tree;
5176 tree arg2_tree;
5178 arg1_tree = ffecom_arg_ptr_to_expr (arg2, &arg1_len);
5180 arg2_tree = convert (((codegen_imp == FFEINTRIN_impCTIME_subr) ?
5181 ffecom_f2c_longint_type_node :
5182 ffecom_f2c_integer_type_node),
5183 ffecom_expr (arg1));
5184 arg2_tree = ffecom_1 (ADDR_EXPR,
5185 build_pointer_type (TREE_TYPE (arg2_tree)),
5186 arg2_tree);
5188 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5189 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5190 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5191 TREE_CHAIN (arg1_len) = arg2_tree;
5192 TREE_CHAIN (arg1_tree) = arg1_len;
5194 expr_tree
5195 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5196 ffecom_gfrt_kindtype (gfrt),
5197 FALSE,
5198 NULL_TREE,
5199 arg1_tree,
5200 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5201 ffebld_nonter_hook (expr));
5202 TREE_SIDE_EFFECTS (expr_tree) = 1;
5204 return expr_tree;
5206 case FFEINTRIN_impIRAND:
5207 case FFEINTRIN_impRAND:
5208 /* Arg defaults to 0 (normal random case) */
5210 tree arg1_tree;
5212 if (arg1 == NULL)
5213 arg1_tree = ffecom_integer_zero_node;
5214 else
5215 arg1_tree = ffecom_expr (arg1);
5216 arg1_tree = convert (ffecom_f2c_integer_type_node,
5217 arg1_tree);
5218 arg1_tree = ffecom_1 (ADDR_EXPR,
5219 build_pointer_type (TREE_TYPE (arg1_tree)),
5220 arg1_tree);
5221 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5223 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5224 ffecom_gfrt_kindtype (gfrt),
5225 FALSE,
5226 ((codegen_imp == FFEINTRIN_impIRAND) ?
5227 ffecom_f2c_integer_type_node :
5228 ffecom_f2c_real_type_node),
5229 arg1_tree,
5230 dest_tree, dest, dest_used,
5231 NULL_TREE, TRUE,
5232 ffebld_nonter_hook (expr));
5234 return expr_tree;
5236 case FFEINTRIN_impFTELL_subr:
5237 case FFEINTRIN_impUMASK_subr:
5239 tree arg1_tree;
5240 tree arg2_tree;
5242 arg1_tree = convert (ffecom_f2c_integer_type_node,
5243 ffecom_expr (arg1));
5244 arg1_tree = ffecom_1 (ADDR_EXPR,
5245 build_pointer_type (TREE_TYPE (arg1_tree)),
5246 arg1_tree);
5248 if (arg2 == NULL)
5249 arg2_tree = NULL_TREE;
5250 else
5251 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
5253 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5254 ffecom_gfrt_kindtype (gfrt),
5255 FALSE,
5256 NULL_TREE,
5257 build_tree_list (NULL_TREE, arg1_tree),
5258 NULL_TREE, NULL, NULL, NULL_TREE,
5259 TRUE,
5260 ffebld_nonter_hook (expr));
5261 if (arg2_tree != NULL_TREE) {
5262 expr_tree = ffecom_modify (NULL_TREE, arg2_tree,
5263 convert (TREE_TYPE (arg2_tree),
5264 expr_tree));
5267 return expr_tree;
5269 case FFEINTRIN_impCPU_TIME:
5270 case FFEINTRIN_impSECOND_subr:
5272 tree arg1_tree;
5274 arg1_tree = ffecom_expr_w (NULL_TREE, arg1);
5276 expr_tree
5277 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5278 ffecom_gfrt_kindtype (gfrt),
5279 FALSE,
5280 NULL_TREE,
5281 NULL_TREE,
5282 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5283 ffebld_nonter_hook (expr));
5285 expr_tree
5286 = ffecom_modify (NULL_TREE, arg1_tree,
5287 convert (TREE_TYPE (arg1_tree),
5288 expr_tree));
5290 return expr_tree;
5292 case FFEINTRIN_impDTIME_subr:
5293 case FFEINTRIN_impETIME_subr:
5295 tree arg1_tree;
5296 tree result_tree;
5298 result_tree = ffecom_expr_w (NULL_TREE, arg2);
5300 arg1_tree = ffecom_ptr_to_expr (arg1);
5302 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5303 ffecom_gfrt_kindtype (gfrt),
5304 FALSE,
5305 NULL_TREE,
5306 build_tree_list (NULL_TREE, arg1_tree),
5307 NULL_TREE, NULL, NULL, NULL_TREE,
5308 TRUE,
5309 ffebld_nonter_hook (expr));
5310 expr_tree = ffecom_modify (NULL_TREE, result_tree,
5311 convert (TREE_TYPE (result_tree),
5312 expr_tree));
5314 return expr_tree;
5316 /* Straightforward calls of libf2c routines: */
5317 case FFEINTRIN_impABORT:
5318 case FFEINTRIN_impACCESS:
5319 case FFEINTRIN_impBESJ0:
5320 case FFEINTRIN_impBESJ1:
5321 case FFEINTRIN_impBESJN:
5322 case FFEINTRIN_impBESY0:
5323 case FFEINTRIN_impBESY1:
5324 case FFEINTRIN_impBESYN:
5325 case FFEINTRIN_impCHDIR_func:
5326 case FFEINTRIN_impCHMOD_func:
5327 case FFEINTRIN_impDATE:
5328 case FFEINTRIN_impDATE_AND_TIME:
5329 case FFEINTRIN_impDBESJ0:
5330 case FFEINTRIN_impDBESJ1:
5331 case FFEINTRIN_impDBESJN:
5332 case FFEINTRIN_impDBESY0:
5333 case FFEINTRIN_impDBESY1:
5334 case FFEINTRIN_impDBESYN:
5335 case FFEINTRIN_impDTIME_func:
5336 case FFEINTRIN_impETIME_func:
5337 case FFEINTRIN_impFGETC_func:
5338 case FFEINTRIN_impFGET_func:
5339 case FFEINTRIN_impFNUM:
5340 case FFEINTRIN_impFPUTC_func:
5341 case FFEINTRIN_impFPUT_func:
5342 case FFEINTRIN_impFSEEK:
5343 case FFEINTRIN_impFSTAT_func:
5344 case FFEINTRIN_impFTELL_func:
5345 case FFEINTRIN_impGERROR:
5346 case FFEINTRIN_impGETARG:
5347 case FFEINTRIN_impGETCWD_func:
5348 case FFEINTRIN_impGETENV:
5349 case FFEINTRIN_impGETGID:
5350 case FFEINTRIN_impGETLOG:
5351 case FFEINTRIN_impGETPID:
5352 case FFEINTRIN_impGETUID:
5353 case FFEINTRIN_impGMTIME:
5354 case FFEINTRIN_impHOSTNM_func:
5355 case FFEINTRIN_impIDATE_unix:
5356 case FFEINTRIN_impIDATE_vxt:
5357 case FFEINTRIN_impIERRNO:
5358 case FFEINTRIN_impISATTY:
5359 case FFEINTRIN_impITIME:
5360 case FFEINTRIN_impKILL_func:
5361 case FFEINTRIN_impLINK_func:
5362 case FFEINTRIN_impLNBLNK:
5363 case FFEINTRIN_impLSTAT_func:
5364 case FFEINTRIN_impLTIME:
5365 case FFEINTRIN_impMCLOCK8:
5366 case FFEINTRIN_impMCLOCK:
5367 case FFEINTRIN_impPERROR:
5368 case FFEINTRIN_impRENAME_func:
5369 case FFEINTRIN_impSECNDS:
5370 case FFEINTRIN_impSECOND_func:
5371 case FFEINTRIN_impSLEEP:
5372 case FFEINTRIN_impSRAND:
5373 case FFEINTRIN_impSTAT_func:
5374 case FFEINTRIN_impSYMLNK_func:
5375 case FFEINTRIN_impSYSTEM_CLOCK:
5376 case FFEINTRIN_impSYSTEM_func:
5377 case FFEINTRIN_impTIME8:
5378 case FFEINTRIN_impTIME_unix:
5379 case FFEINTRIN_impTIME_vxt:
5380 case FFEINTRIN_impUMASK_func:
5381 case FFEINTRIN_impUNLINK_func:
5382 break;
5384 case FFEINTRIN_impCTIME_func: /* CHARACTER functions not handled here. */
5385 case FFEINTRIN_impFDATE_func: /* CHARACTER functions not handled here. */
5386 case FFEINTRIN_impTTYNAM_func: /* CHARACTER functions not handled here. */
5387 case FFEINTRIN_impNONE:
5388 case FFEINTRIN_imp: /* Hush up gcc warning. */
5389 fprintf (stderr, "No %s implementation.\n",
5390 ffeintrin_name_implementation (ffebld_symter_implementation (ffebld_left (expr))));
5391 assert ("unimplemented intrinsic" == NULL);
5392 return error_mark_node;
5395 assert (gfrt != FFECOM_gfrt); /* Must have an implementation! */
5397 expr_tree = ffecom_arglist_expr_ (ffecom_gfrt_args_ (gfrt),
5398 ffebld_right (expr));
5400 return ffecom_call_ (ffecom_gfrt_tree_ (gfrt), ffecom_gfrt_kindtype (gfrt),
5401 (ffe_is_f2c_library () && ffecom_gfrt_complex_[gfrt]),
5402 tree_type,
5403 expr_tree, dest_tree, dest, dest_used,
5404 NULL_TREE, TRUE,
5405 ffebld_nonter_hook (expr));
5407 /* See bottom of this file for f2c transforms used to determine
5408 many of the above implementations. The info seems to confuse
5409 Emacs's C mode indentation, which is why it's been moved to
5410 the bottom of this source file. */
5413 /* For power (exponentiation) where right-hand operand is type INTEGER,
5414 generate in-line code to do it the fast way (which, if the operand
5415 is a constant, might just mean a series of multiplies). */
5417 static tree
5418 ffecom_expr_power_integer_ (ffebld expr)
5420 tree l = ffecom_expr (ffebld_left (expr));
5421 tree r = ffecom_expr (ffebld_right (expr));
5422 tree ltype = TREE_TYPE (l);
5423 tree rtype = TREE_TYPE (r);
5424 tree result = NULL_TREE;
5426 if (l == error_mark_node
5427 || r == error_mark_node)
5428 return error_mark_node;
5430 if (TREE_CODE (r) == INTEGER_CST)
5432 int sgn = tree_int_cst_sgn (r);
5434 if (sgn == 0)
5435 return convert (ltype, integer_one_node);
5437 if ((TREE_CODE (ltype) == INTEGER_TYPE)
5438 && (sgn < 0))
5440 /* Reciprocal of integer is either 0, -1, or 1, so after
5441 calculating that (which we leave to the back end to do
5442 or not do optimally), don't bother with any multiplying. */
5444 result = ffecom_tree_divide_ (ltype,
5445 convert (ltype, integer_one_node),
5447 NULL_TREE, NULL, NULL, NULL_TREE);
5448 r = ffecom_1 (NEGATE_EXPR,
5449 rtype,
5451 if ((TREE_INT_CST_LOW (r) & 1) == 0)
5452 result = ffecom_1 (ABS_EXPR, rtype,
5453 result);
5456 /* Generate appropriate series of multiplies, preceded
5457 by divide if the exponent is negative. */
5459 l = save_expr (l);
5461 if (sgn < 0)
5463 l = ffecom_tree_divide_ (ltype,
5464 convert (ltype, integer_one_node),
5466 NULL_TREE, NULL, NULL,
5467 ffebld_nonter_hook (expr));
5468 r = ffecom_1 (NEGATE_EXPR, rtype, r);
5469 assert (TREE_CODE (r) == INTEGER_CST);
5471 if (tree_int_cst_sgn (r) < 0)
5472 { /* The "most negative" number. */
5473 r = ffecom_1 (NEGATE_EXPR, rtype,
5474 ffecom_2 (RSHIFT_EXPR, rtype,
5476 integer_one_node));
5477 l = save_expr (l);
5478 l = ffecom_2 (MULT_EXPR, ltype,
5484 for (;;)
5486 if (TREE_INT_CST_LOW (r) & 1)
5488 if (result == NULL_TREE)
5489 result = l;
5490 else
5491 result = ffecom_2 (MULT_EXPR, ltype,
5492 result,
5496 r = ffecom_2 (RSHIFT_EXPR, rtype,
5498 integer_one_node);
5499 if (integer_zerop (r))
5500 break;
5501 assert (TREE_CODE (r) == INTEGER_CST);
5503 l = save_expr (l);
5504 l = ffecom_2 (MULT_EXPR, ltype,
5508 return result;
5511 /* Though rhs isn't a constant, in-line code cannot be expanded
5512 while transforming dummies
5513 because the back end cannot be easily convinced to generate
5514 stores (MODIFY_EXPR), handle temporaries, and so on before
5515 all the appropriate rtx's have been generated for things like
5516 dummy args referenced in rhs -- which doesn't happen until
5517 store_parm_decls() is called (expand_function_start, I believe,
5518 does the actual rtx-stuffing of PARM_DECLs).
5520 So, in this case, let the caller generate the call to the
5521 run-time-library function to evaluate the power for us. */
5523 if (ffecom_transform_only_dummies_)
5524 return NULL_TREE;
5526 /* Right-hand operand not a constant, expand in-line code to figure
5527 out how to do the multiplies, &c.
5529 The returned expression is expressed this way in GNU C, where l and
5530 r are the "inputs":
5532 ({ typeof (r) rtmp = r;
5533 typeof (l) ltmp = l;
5534 typeof (l) result;
5536 if (rtmp == 0)
5537 result = 1;
5538 else
5540 if ((basetypeof (l) == basetypeof (int))
5541 && (rtmp < 0))
5543 result = ((typeof (l)) 1) / ltmp;
5544 if ((ltmp < 0) && (((-rtmp) & 1) == 0))
5545 result = -result;
5547 else
5549 result = 1;
5550 if ((basetypeof (l) != basetypeof (int))
5551 && (rtmp < 0))
5553 ltmp = ((typeof (l)) 1) / ltmp;
5554 rtmp = -rtmp;
5555 if (rtmp < 0)
5557 rtmp = -(rtmp >> 1);
5558 ltmp *= ltmp;
5561 for (;;)
5563 if (rtmp & 1)
5564 result *= ltmp;
5565 if ((rtmp >>= 1) == 0)
5566 break;
5567 ltmp *= ltmp;
5571 result;
5574 Note that some of the above is compile-time collapsable, such as
5575 the first part of the if statements that checks the base type of
5576 l against int. The if statements are phrased that way to suggest
5577 an easy way to generate the if/else constructs here, knowing that
5578 the back end should (and probably does) eliminate the resulting
5579 dead code (either the int case or the non-int case), something
5580 it couldn't do without the redundant phrasing, requiring explicit
5581 dead-code elimination here, which would be kind of difficult to
5582 read. */
5585 tree rtmp;
5586 tree ltmp;
5587 tree divide;
5588 tree basetypeof_l_is_int;
5589 tree se;
5590 tree t;
5592 basetypeof_l_is_int
5593 = build_int_2 ((TREE_CODE (ltype) == INTEGER_TYPE), 0);
5595 se = expand_start_stmt_expr (/*has_scope=*/1);
5597 ffecom_start_compstmt ();
5599 rtmp = ffecom_make_tempvar ("power_r", rtype,
5600 FFETARGET_charactersizeNONE, -1);
5601 ltmp = ffecom_make_tempvar ("power_l", ltype,
5602 FFETARGET_charactersizeNONE, -1);
5603 result = ffecom_make_tempvar ("power_res", ltype,
5604 FFETARGET_charactersizeNONE, -1);
5605 if (TREE_CODE (ltype) == COMPLEX_TYPE
5606 || TREE_CODE (ltype) == RECORD_TYPE)
5607 divide = ffecom_make_tempvar ("power_div", ltype,
5608 FFETARGET_charactersizeNONE, -1);
5609 else
5610 divide = NULL_TREE;
5612 expand_expr_stmt (ffecom_modify (void_type_node,
5613 rtmp,
5614 r));
5615 expand_expr_stmt (ffecom_modify (void_type_node,
5616 ltmp,
5617 l));
5618 expand_start_cond (ffecom_truth_value
5619 (ffecom_2 (EQ_EXPR, integer_type_node,
5620 rtmp,
5621 convert (rtype, integer_zero_node))),
5623 expand_expr_stmt (ffecom_modify (void_type_node,
5624 result,
5625 convert (ltype, integer_one_node)));
5626 expand_start_else ();
5627 if (! integer_zerop (basetypeof_l_is_int))
5629 expand_start_cond (ffecom_2 (LT_EXPR, integer_type_node,
5630 rtmp,
5631 convert (rtype,
5632 integer_zero_node)),
5634 expand_expr_stmt (ffecom_modify (void_type_node,
5635 result,
5636 ffecom_tree_divide_
5637 (ltype,
5638 convert (ltype, integer_one_node),
5639 ltmp,
5640 NULL_TREE, NULL, NULL,
5641 divide)));
5642 expand_start_cond (ffecom_truth_value
5643 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5644 ffecom_2 (LT_EXPR, integer_type_node,
5645 ltmp,
5646 convert (ltype,
5647 integer_zero_node)),
5648 ffecom_2 (EQ_EXPR, integer_type_node,
5649 ffecom_2 (BIT_AND_EXPR,
5650 rtype,
5651 ffecom_1 (NEGATE_EXPR,
5652 rtype,
5653 rtmp),
5654 convert (rtype,
5655 integer_one_node)),
5656 convert (rtype,
5657 integer_zero_node)))),
5659 expand_expr_stmt (ffecom_modify (void_type_node,
5660 result,
5661 ffecom_1 (NEGATE_EXPR,
5662 ltype,
5663 result)));
5664 expand_end_cond ();
5665 expand_start_else ();
5667 expand_expr_stmt (ffecom_modify (void_type_node,
5668 result,
5669 convert (ltype, integer_one_node)));
5670 expand_start_cond (ffecom_truth_value
5671 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5672 ffecom_truth_value_invert
5673 (basetypeof_l_is_int),
5674 ffecom_2 (LT_EXPR, integer_type_node,
5675 rtmp,
5676 convert (rtype,
5677 integer_zero_node)))),
5679 expand_expr_stmt (ffecom_modify (void_type_node,
5680 ltmp,
5681 ffecom_tree_divide_
5682 (ltype,
5683 convert (ltype, integer_one_node),
5684 ltmp,
5685 NULL_TREE, NULL, NULL,
5686 divide)));
5687 expand_expr_stmt (ffecom_modify (void_type_node,
5688 rtmp,
5689 ffecom_1 (NEGATE_EXPR, rtype,
5690 rtmp)));
5691 expand_start_cond (ffecom_truth_value
5692 (ffecom_2 (LT_EXPR, integer_type_node,
5693 rtmp,
5694 convert (rtype, integer_zero_node))),
5696 expand_expr_stmt (ffecom_modify (void_type_node,
5697 rtmp,
5698 ffecom_1 (NEGATE_EXPR, rtype,
5699 ffecom_2 (RSHIFT_EXPR,
5700 rtype,
5701 rtmp,
5702 integer_one_node))));
5703 expand_expr_stmt (ffecom_modify (void_type_node,
5704 ltmp,
5705 ffecom_2 (MULT_EXPR, ltype,
5706 ltmp,
5707 ltmp)));
5708 expand_end_cond ();
5709 expand_end_cond ();
5710 expand_start_loop (1);
5711 expand_start_cond (ffecom_truth_value
5712 (ffecom_2 (BIT_AND_EXPR, rtype,
5713 rtmp,
5714 convert (rtype, integer_one_node))),
5716 expand_expr_stmt (ffecom_modify (void_type_node,
5717 result,
5718 ffecom_2 (MULT_EXPR, ltype,
5719 result,
5720 ltmp)));
5721 expand_end_cond ();
5722 expand_exit_loop_if_false (NULL,
5723 ffecom_truth_value
5724 (ffecom_modify (rtype,
5725 rtmp,
5726 ffecom_2 (RSHIFT_EXPR,
5727 rtype,
5728 rtmp,
5729 integer_one_node))));
5730 expand_expr_stmt (ffecom_modify (void_type_node,
5731 ltmp,
5732 ffecom_2 (MULT_EXPR, ltype,
5733 ltmp,
5734 ltmp)));
5735 expand_end_loop ();
5736 expand_end_cond ();
5737 if (!integer_zerop (basetypeof_l_is_int))
5738 expand_end_cond ();
5739 expand_expr_stmt (result);
5741 t = ffecom_end_compstmt ();
5743 result = expand_end_stmt_expr (se);
5745 /* This code comes from c-parse.in, after its expand_end_stmt_expr. */
5747 if (TREE_CODE (t) == BLOCK)
5749 /* Make a BIND_EXPR for the BLOCK already made. */
5750 result = build (BIND_EXPR, TREE_TYPE (result),
5751 NULL_TREE, result, t);
5752 /* Remove the block from the tree at this point.
5753 It gets put back at the proper place
5754 when the BIND_EXPR is expanded. */
5755 delete_block (t);
5757 else
5758 result = t;
5761 return result;
5764 /* ffecom_expr_transform_ -- Transform symbols in expr
5766 ffebld expr; // FFE expression.
5767 ffecom_expr_transform_ (expr);
5769 Recursive descent on expr while transforming any untransformed SYMTERs. */
5771 static void
5772 ffecom_expr_transform_ (ffebld expr)
5774 tree t;
5775 ffesymbol s;
5777 tail_recurse:
5779 if (expr == NULL)
5780 return;
5782 switch (ffebld_op (expr))
5784 case FFEBLD_opSYMTER:
5785 s = ffebld_symter (expr);
5786 t = ffesymbol_hook (s).decl_tree;
5787 if ((t == NULL_TREE)
5788 && ((ffesymbol_kind (s) != FFEINFO_kindNONE)
5789 || ((ffesymbol_where (s) != FFEINFO_whereNONE)
5790 && (ffesymbol_where (s) != FFEINFO_whereINTRINSIC))))
5792 s = ffecom_sym_transform_ (s);
5793 t = ffesymbol_hook (s).decl_tree; /* Sfunc expr non-dummy,
5794 DIMENSION expr? */
5796 break; /* Ok if (t == NULL) here. */
5798 case FFEBLD_opITEM:
5799 ffecom_expr_transform_ (ffebld_head (expr));
5800 expr = ffebld_trail (expr);
5801 goto tail_recurse; /* :::::::::::::::::::: */
5803 default:
5804 break;
5807 switch (ffebld_arity (expr))
5809 case 2:
5810 ffecom_expr_transform_ (ffebld_left (expr));
5811 expr = ffebld_right (expr);
5812 goto tail_recurse; /* :::::::::::::::::::: */
5814 case 1:
5815 expr = ffebld_left (expr);
5816 goto tail_recurse; /* :::::::::::::::::::: */
5818 default:
5819 break;
5822 return;
5825 /* Make a type based on info in live f2c.h file. */
5827 static void
5828 ffecom_f2c_make_type_ (tree *type, int tcode, const char *name)
5830 switch (tcode)
5832 case FFECOM_f2ccodeCHAR:
5833 *type = make_signed_type (CHAR_TYPE_SIZE);
5834 break;
5836 case FFECOM_f2ccodeSHORT:
5837 *type = make_signed_type (SHORT_TYPE_SIZE);
5838 break;
5840 case FFECOM_f2ccodeINT:
5841 *type = make_signed_type (INT_TYPE_SIZE);
5842 break;
5844 case FFECOM_f2ccodeLONG:
5845 *type = make_signed_type (LONG_TYPE_SIZE);
5846 break;
5848 case FFECOM_f2ccodeLONGLONG:
5849 *type = make_signed_type (LONG_LONG_TYPE_SIZE);
5850 break;
5852 case FFECOM_f2ccodeCHARPTR:
5853 *type = build_pointer_type (DEFAULT_SIGNED_CHAR
5854 ? signed_char_type_node
5855 : unsigned_char_type_node);
5856 break;
5858 case FFECOM_f2ccodeFLOAT:
5859 *type = make_node (REAL_TYPE);
5860 TYPE_PRECISION (*type) = FLOAT_TYPE_SIZE;
5861 layout_type (*type);
5862 break;
5864 case FFECOM_f2ccodeDOUBLE:
5865 *type = make_node (REAL_TYPE);
5866 TYPE_PRECISION (*type) = DOUBLE_TYPE_SIZE;
5867 layout_type (*type);
5868 break;
5870 case FFECOM_f2ccodeLONGDOUBLE:
5871 *type = make_node (REAL_TYPE);
5872 TYPE_PRECISION (*type) = LONG_DOUBLE_TYPE_SIZE;
5873 layout_type (*type);
5874 break;
5876 case FFECOM_f2ccodeTWOREALS:
5877 *type = ffecom_make_complex_type_ (ffecom_f2c_real_type_node);
5878 break;
5880 case FFECOM_f2ccodeTWODOUBLEREALS:
5881 *type = ffecom_make_complex_type_ (ffecom_f2c_doublereal_type_node);
5882 break;
5884 default:
5885 assert ("unexpected FFECOM_f2ccodeXYZZY!" == NULL);
5886 *type = error_mark_node;
5887 return;
5890 pushdecl (build_decl (TYPE_DECL,
5891 ffecom_get_invented_identifier ("__g77_f2c_%s", name),
5892 *type));
5895 /* Set the f2c list-directed-I/O code for whatever (integral) type has the
5896 given size. */
5898 static void
5899 ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size, int code)
5901 int j;
5902 tree t;
5904 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
5905 if ((t = ffecom_tree_type[bt][j]) != NULL_TREE
5906 && compare_tree_int (TYPE_SIZE (t), size) == 0)
5908 assert (code != -1);
5909 ffecom_f2c_typecode_[bt][j] = code;
5910 code = -1;
5914 /* Finish up globals after doing all program units in file
5916 Need to handle only uninitialized COMMON areas. */
5918 static ffeglobal
5919 ffecom_finish_global_ (ffeglobal global)
5921 tree cbtype;
5922 tree cbt;
5923 tree size;
5925 if (ffeglobal_type (global) != FFEGLOBAL_typeCOMMON)
5926 return global;
5928 if (ffeglobal_common_init (global))
5929 return global;
5931 cbt = ffeglobal_hook (global);
5932 if ((cbt == NULL_TREE)
5933 || !ffeglobal_common_have_size (global))
5934 return global; /* No need to make common, never ref'd. */
5936 DECL_EXTERNAL (cbt) = 0;
5938 /* Give the array a size now. */
5940 size = build_int_2 ((ffeglobal_common_size (global)
5941 + ffeglobal_common_pad (global)) - 1,
5944 cbtype = TREE_TYPE (cbt);
5945 TYPE_DOMAIN (cbtype) = build_range_type (integer_type_node,
5946 integer_zero_node,
5947 size);
5948 if (!TREE_TYPE (size))
5949 TREE_TYPE (size) = TYPE_DOMAIN (cbtype);
5950 layout_type (cbtype);
5952 cbt = start_decl (cbt, FALSE);
5953 assert (cbt == ffeglobal_hook (global));
5955 finish_decl (cbt, NULL_TREE, FALSE);
5957 return global;
5960 /* Finish up any untransformed symbols. */
5962 static ffesymbol
5963 ffecom_finish_symbol_transform_ (ffesymbol s)
5965 if ((s == NULL) || (TREE_CODE (current_function_decl) == ERROR_MARK))
5966 return s;
5968 /* It's easy to know to transform an untransformed symbol, to make sure
5969 we put out debugging info for it. But COMMON variables, unlike
5970 EQUIVALENCE ones, aren't given declarations in addition to the
5971 tree expressions that specify offsets, because COMMON variables
5972 can be referenced in the outer scope where only dummy arguments
5973 (PARM_DECLs) should really be seen. To be safe, just don't do any
5974 VAR_DECLs for COMMON variables when we transform them for real
5975 use, and therefore we do all the VAR_DECL creating here. */
5977 if (ffesymbol_hook (s).decl_tree == NULL_TREE)
5979 if (ffesymbol_kind (s) != FFEINFO_kindNONE
5980 || (ffesymbol_where (s) != FFEINFO_whereNONE
5981 && ffesymbol_where (s) != FFEINFO_whereINTRINSIC
5982 && ffesymbol_where (s) != FFEINFO_whereDUMMY))
5983 /* Not transformed, and not CHARACTER*(*), and not a dummy
5984 argument, which can happen only if the entry point names
5985 it "rides in on" are all invalidated for other reasons. */
5986 s = ffecom_sym_transform_ (s);
5989 if ((ffesymbol_where (s) == FFEINFO_whereCOMMON)
5990 && (ffesymbol_hook (s).decl_tree != error_mark_node))
5992 /* This isn't working, at least for dbxout. The .s file looks
5993 okay to me (burley), but in gdb 4.9 at least, the variables
5994 appear to reside somewhere outside of the common area, so
5995 it doesn't make sense to mislead anyone by generating the info
5996 on those variables until this is fixed. NOTE: Same problem
5997 with EQUIVALENCE, sadly...see similar #if later. */
5998 ffecom_member_phase2_ (ffesymbol_storage (ffesymbol_common (s)),
5999 ffesymbol_storage (s));
6002 return s;
6005 /* Append underscore(s) to name before calling get_identifier. "us"
6006 is nonzero if the name already contains an underscore and thus
6007 needs two underscores appended. */
6009 static tree
6010 ffecom_get_appended_identifier_ (char us, const char *name)
6012 int i;
6013 char *newname;
6014 tree id;
6016 newname = xmalloc ((i = strlen (name)) + 1
6017 + ffe_is_underscoring ()
6018 + us);
6019 memcpy (newname, name, i);
6020 newname[i] = '_';
6021 newname[i + us] = '_';
6022 newname[i + 1 + us] = '\0';
6023 id = get_identifier (newname);
6025 free (newname);
6027 return id;
6030 /* Decide whether to append underscore to name before calling
6031 get_identifier. */
6033 static tree
6034 ffecom_get_external_identifier_ (ffesymbol s)
6036 char us;
6037 const char *name = ffesymbol_text (s);
6039 /* If name is a built-in name, just return it as is. */
6041 if (!ffe_is_underscoring ()
6042 || (strcmp (name, FFETARGET_nameBLANK_COMMON) == 0)
6043 || (strcmp (name, FFETARGET_nameUNNAMED_MAIN) == 0)
6044 || (strcmp (name, FFETARGET_nameUNNAMED_BLOCK_DATA) == 0))
6045 return get_identifier (name);
6047 us = ffe_is_second_underscore ()
6048 ? (strchr (name, '_') != NULL)
6049 : 0;
6051 return ffecom_get_appended_identifier_ (us, name);
6054 /* Decide whether to append underscore to internal name before calling
6055 get_identifier.
6057 This is for non-external, top-function-context names only. Transform
6058 identifier so it doesn't conflict with the transformed result
6059 of using a _different_ external name. E.g. if "CALL FOO" is
6060 transformed into "FOO_();", then the variable in "FOO_ = 3"
6061 must be transformed into something that does not conflict, since
6062 these two things should be independent.
6064 The transformation is as follows. If the name does not contain
6065 an underscore, there is no possible conflict, so just return.
6066 If the name does contain an underscore, then transform it just
6067 like we transform an external identifier. */
6069 static tree
6070 ffecom_get_identifier_ (const char *name)
6072 /* If name does not contain an underscore, just return it as is. */
6074 if (!ffe_is_underscoring ()
6075 || (strchr (name, '_') == NULL))
6076 return get_identifier (name);
6078 return ffecom_get_appended_identifier_ (ffe_is_second_underscore (),
6079 name);
6082 /* ffecom_gen_sfuncdef_ -- Generate definition of statement function
6084 tree t;
6085 ffesymbol s; // kindFUNCTION, whereIMMEDIATE.
6086 t = ffecom_gen_sfuncdef_(s,ffesymbol_basictype(s),
6087 ffesymbol_kindtype(s));
6089 Call after setting up containing function and getting trees for all
6090 other symbols. */
6092 static tree
6093 ffecom_gen_sfuncdef_ (ffesymbol s, ffeinfoBasictype bt, ffeinfoKindtype kt)
6095 ffebld expr = ffesymbol_sfexpr (s);
6096 tree type;
6097 tree func;
6098 tree result;
6099 bool charfunc = (bt == FFEINFO_basictypeCHARACTER);
6100 static bool recurse = FALSE;
6101 location_t old_loc = input_location;
6103 ffecom_nested_entry_ = s;
6105 /* For now, we don't have a handy pointer to where the sfunc is actually
6106 defined, though that should be easy to add to an ffesymbol. (The
6107 token/where info available might well point to the place where the type
6108 of the sfunc is declared, especially if that precedes the place where
6109 the sfunc itself is defined, which is typically the case.) We should
6110 put out a null pointer rather than point somewhere wrong, but I want to
6111 see how it works at this point. */
6113 input_filename = ffesymbol_where_filename (s);
6114 input_line = ffesymbol_where_filelinenum (s);
6116 /* Pretransform the expression so any newly discovered things belong to the
6117 outer program unit, not to the statement function. */
6119 ffecom_expr_transform_ (expr);
6121 /* Make sure no recursive invocation of this fn (a specific case of failing
6122 to pretransform an sfunc's expression, i.e. where its expression
6123 references another untransformed sfunc) happens. */
6125 assert (!recurse);
6126 recurse = TRUE;
6128 push_f_function_context ();
6130 if (charfunc)
6131 type = void_type_node;
6132 else
6134 type = ffecom_tree_type[bt][kt];
6135 if (type == NULL_TREE)
6136 type = integer_type_node; /* _sym_exec_transition reports
6137 error. */
6140 start_function (ffecom_get_identifier_ (ffesymbol_text (s)),
6141 build_function_type (type, NULL_TREE),
6142 1, /* nested/inline */
6143 0); /* TREE_PUBLIC */
6145 /* We don't worry about COMPLEX return values here, because this is
6146 entirely internal to our code, and gcc has the ability to return COMPLEX
6147 directly as a value. */
6149 if (charfunc)
6150 { /* Prepend arg for where result goes. */
6151 tree type;
6153 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
6155 result = ffecom_get_invented_identifier ("__g77_%s", "result");
6157 ffecom_char_enhance_arg_ (&type, s); /* Ignore returned length. */
6159 type = build_pointer_type (type);
6160 result = build_decl (PARM_DECL, result, type);
6162 push_parm_decl (result);
6164 else
6165 result = NULL_TREE; /* Not ref'd if !charfunc. */
6167 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (s), TRUE);
6169 store_parm_decls (0);
6171 ffecom_start_compstmt ();
6173 if (expr != NULL)
6175 if (charfunc)
6177 ffetargetCharacterSize sz = ffesymbol_size (s);
6178 tree result_length;
6180 result_length = build_int_2 (sz, 0);
6181 TREE_TYPE (result_length) = ffecom_f2c_ftnlen_type_node;
6183 ffecom_prepare_let_char_ (sz, expr);
6185 ffecom_prepare_end ();
6187 ffecom_let_char_ (result, result_length, sz, expr);
6188 expand_null_return ();
6190 else
6192 ffecom_prepare_expr (expr);
6194 ffecom_prepare_end ();
6196 expand_return (ffecom_modify (NULL_TREE,
6197 DECL_RESULT (current_function_decl),
6198 ffecom_expr (expr)));
6202 ffecom_end_compstmt ();
6204 func = current_function_decl;
6205 finish_function (1);
6207 pop_f_function_context ();
6209 recurse = FALSE;
6211 input_location = old_loc;
6213 ffecom_nested_entry_ = NULL;
6215 return func;
6218 static const char *
6219 ffecom_gfrt_args_ (ffecomGfrt ix)
6221 return ffecom_gfrt_argstring_[ix];
6224 static tree
6225 ffecom_gfrt_tree_ (ffecomGfrt ix)
6227 if (ffecom_gfrt_[ix] == NULL_TREE)
6228 ffecom_make_gfrt_ (ix);
6230 return ffecom_1 (ADDR_EXPR,
6231 build_pointer_type (TREE_TYPE (ffecom_gfrt_[ix])),
6232 ffecom_gfrt_[ix]);
6235 /* Return initialize-to-zero expression for this VAR_DECL. */
6237 /* A somewhat evil way to prevent the garbage collector
6238 from collecting 'tree' structures. */
6239 #define NUM_TRACKED_CHUNK 63
6240 struct tree_ggc_tracker GTY(())
6242 struct tree_ggc_tracker *next;
6243 tree trees[NUM_TRACKED_CHUNK];
6245 static GTY(()) struct tree_ggc_tracker *tracker_head;
6247 void
6248 ffecom_save_tree_forever (tree t)
6250 int i;
6251 if (tracker_head != NULL)
6252 for (i = 0; i < NUM_TRACKED_CHUNK; i++)
6253 if (tracker_head->trees[i] == NULL)
6255 tracker_head->trees[i] = t;
6256 return;
6260 /* Need to allocate a new block. */
6261 struct tree_ggc_tracker *old_head = tracker_head;
6263 tracker_head = ggc_alloc (sizeof (*tracker_head));
6264 tracker_head->next = old_head;
6265 tracker_head->trees[0] = t;
6266 for (i = 1; i < NUM_TRACKED_CHUNK; i++)
6267 tracker_head->trees[i] = NULL;
6271 static tree
6272 ffecom_init_zero_ (tree decl)
6274 tree init;
6275 int incremental = TREE_STATIC (decl);
6276 tree type = TREE_TYPE (decl);
6278 if (incremental)
6280 make_decl_rtl (decl, NULL);
6281 assemble_variable (decl, TREE_PUBLIC (decl) ? 1 : 0, 0, 1);
6284 if ((TREE_CODE (type) != ARRAY_TYPE)
6285 && (TREE_CODE (type) != RECORD_TYPE)
6286 && (TREE_CODE (type) != UNION_TYPE)
6287 && !incremental)
6288 init = convert (type, integer_zero_node);
6289 else if (!incremental)
6291 init = build_constructor (type, NULL_TREE);
6292 TREE_CONSTANT (init) = 1;
6293 TREE_STATIC (init) = 1;
6295 else
6297 assemble_zeros (int_size_in_bytes (type));
6298 init = error_mark_node;
6301 return init;
6304 static tree
6305 ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg, tree *maybe_tree)
6307 tree expr_tree;
6308 tree length_tree;
6310 switch (ffebld_op (arg))
6312 case FFEBLD_opCONTER: /* For F90, check 0-length. */
6313 if (ffetarget_length_character1
6314 (ffebld_constant_character1
6315 (ffebld_conter (arg))) == 0)
6317 *maybe_tree = integer_zero_node;
6318 return convert (tree_type, integer_zero_node);
6321 *maybe_tree = integer_one_node;
6322 expr_tree = build_int_2 (*ffetarget_text_character1
6323 (ffebld_constant_character1
6324 (ffebld_conter (arg))),
6326 TREE_TYPE (expr_tree) = tree_type;
6327 return expr_tree;
6329 case FFEBLD_opSYMTER:
6330 case FFEBLD_opARRAYREF:
6331 case FFEBLD_opFUNCREF:
6332 case FFEBLD_opSUBSTR:
6333 ffecom_char_args_ (&expr_tree, &length_tree, arg);
6335 if ((expr_tree == error_mark_node)
6336 || (length_tree == error_mark_node))
6338 *maybe_tree = error_mark_node;
6339 return error_mark_node;
6342 if (integer_zerop (length_tree))
6344 *maybe_tree = integer_zero_node;
6345 return convert (tree_type, integer_zero_node);
6348 expr_tree
6349 = ffecom_1 (INDIRECT_REF,
6350 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6351 expr_tree);
6352 expr_tree
6353 = ffecom_2 (ARRAY_REF,
6354 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6355 expr_tree,
6356 integer_one_node);
6357 expr_tree = convert (tree_type, expr_tree);
6359 if (TREE_CODE (length_tree) == INTEGER_CST)
6360 *maybe_tree = integer_one_node;
6361 else /* Must check length at run time. */
6362 *maybe_tree
6363 = ffecom_truth_value
6364 (ffecom_2 (GT_EXPR, integer_type_node,
6365 length_tree,
6366 ffecom_f2c_ftnlen_zero_node));
6367 return expr_tree;
6369 case FFEBLD_opPAREN:
6370 case FFEBLD_opCONVERT:
6371 if (ffeinfo_size (ffebld_info (arg)) == 0)
6373 *maybe_tree = integer_zero_node;
6374 return convert (tree_type, integer_zero_node);
6376 return ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6377 maybe_tree);
6379 case FFEBLD_opCONCATENATE:
6381 tree maybe_left;
6382 tree maybe_right;
6383 tree expr_left;
6384 tree expr_right;
6386 expr_left = ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6387 &maybe_left);
6388 expr_right = ffecom_intrinsic_ichar_ (tree_type, ffebld_right (arg),
6389 &maybe_right);
6390 *maybe_tree = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
6391 maybe_left,
6392 maybe_right);
6393 expr_tree = ffecom_3 (COND_EXPR, tree_type,
6394 maybe_left,
6395 expr_left,
6396 expr_right);
6397 return expr_tree;
6400 default:
6401 assert ("bad op in ICHAR" == NULL);
6402 return error_mark_node;
6406 /* ffecom_intrinsic_len_ -- Return length info for char arg (LEN())
6408 tree length_arg;
6409 ffebld expr;
6410 length_arg = ffecom_intrinsic_len_ (expr);
6412 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
6413 subexpressions by constructing the appropriate tree for the
6414 length-of-character-text argument in a calling sequence. */
6416 static tree
6417 ffecom_intrinsic_len_ (ffebld expr)
6419 ffetargetCharacter1 val;
6420 tree length;
6422 switch (ffebld_op (expr))
6424 case FFEBLD_opCONTER:
6425 val = ffebld_constant_character1 (ffebld_conter (expr));
6426 length = build_int_2 (ffetarget_length_character1 (val), 0);
6427 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6428 break;
6430 case FFEBLD_opSYMTER:
6432 ffesymbol s = ffebld_symter (expr);
6433 tree item;
6435 item = ffesymbol_hook (s).decl_tree;
6436 if (item == NULL_TREE)
6438 s = ffecom_sym_transform_ (s);
6439 item = ffesymbol_hook (s).decl_tree;
6441 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
6443 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
6444 length = ffesymbol_hook (s).length_tree;
6445 else
6447 length = build_int_2 (ffesymbol_size (s), 0);
6448 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6451 else if (item == error_mark_node)
6452 length = error_mark_node;
6453 else /* FFEINFO_kindFUNCTION: */
6454 length = NULL_TREE;
6456 break;
6458 case FFEBLD_opARRAYREF:
6459 length = ffecom_intrinsic_len_ (ffebld_left (expr));
6460 break;
6462 case FFEBLD_opSUBSTR:
6464 ffebld start;
6465 ffebld end;
6466 ffebld thing = ffebld_right (expr);
6467 tree start_tree;
6468 tree end_tree;
6470 assert (ffebld_op (thing) == FFEBLD_opITEM);
6471 start = ffebld_head (thing);
6472 thing = ffebld_trail (thing);
6473 assert (ffebld_trail (thing) == NULL);
6474 end = ffebld_head (thing);
6476 length = ffecom_intrinsic_len_ (ffebld_left (expr));
6478 if (length == error_mark_node)
6479 break;
6481 if (start == NULL)
6483 if (end == NULL)
6485 else
6487 length = convert (ffecom_f2c_ftnlen_type_node,
6488 ffecom_expr (end));
6491 else
6493 start_tree = convert (ffecom_f2c_ftnlen_type_node,
6494 ffecom_expr (start));
6496 if (start_tree == error_mark_node)
6498 length = error_mark_node;
6499 break;
6502 if (end == NULL)
6504 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6505 ffecom_f2c_ftnlen_one_node,
6506 ffecom_2 (MINUS_EXPR,
6507 ffecom_f2c_ftnlen_type_node,
6508 length,
6509 start_tree));
6511 else
6513 end_tree = convert (ffecom_f2c_ftnlen_type_node,
6514 ffecom_expr (end));
6516 if (end_tree == error_mark_node)
6518 length = error_mark_node;
6519 break;
6522 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6523 ffecom_f2c_ftnlen_one_node,
6524 ffecom_2 (MINUS_EXPR,
6525 ffecom_f2c_ftnlen_type_node,
6526 end_tree, start_tree));
6530 break;
6532 case FFEBLD_opCONCATENATE:
6533 length
6534 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6535 ffecom_intrinsic_len_ (ffebld_left (expr)),
6536 ffecom_intrinsic_len_ (ffebld_right (expr)));
6537 break;
6539 case FFEBLD_opFUNCREF:
6540 case FFEBLD_opCONVERT:
6541 length = build_int_2 (ffebld_size (expr), 0);
6542 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6543 break;
6545 default:
6546 assert ("bad op for single char arg expr" == NULL);
6547 length = ffecom_f2c_ftnlen_zero_node;
6548 break;
6551 assert (length != NULL_TREE);
6553 return length;
6556 /* Handle CHARACTER assignments.
6558 Generates code to do the assignment. Used by ordinary assignment
6559 statement handler ffecom_let_stmt and by statement-function
6560 handler to generate code for a statement function. */
6562 static void
6563 ffecom_let_char_ (tree dest_tree, tree dest_length,
6564 ffetargetCharacterSize dest_size, ffebld source)
6566 ffecomConcatList_ catlist;
6567 tree source_length;
6568 tree source_tree;
6569 tree expr_tree;
6571 if ((dest_tree == error_mark_node)
6572 || (dest_length == error_mark_node))
6573 return;
6575 assert (dest_tree != NULL_TREE);
6576 assert (dest_length != NULL_TREE);
6578 /* Source might be an opCONVERT, which just means it is a different size
6579 than the destination. Since the underlying implementation here handles
6580 that (directly or via the s_copy or s_cat run-time-library functions),
6581 we don't need the "convenience" of an opCONVERT that tells us to
6582 truncate or blank-pad, particularly since the resulting implementation
6583 would probably be slower than otherwise. */
6585 while (ffebld_op (source) == FFEBLD_opCONVERT)
6586 source = ffebld_left (source);
6588 catlist = ffecom_concat_list_new_ (source, dest_size);
6589 switch (ffecom_concat_list_count_ (catlist))
6591 case 0: /* Shouldn't happen, but in case it does... */
6592 ffecom_concat_list_kill_ (catlist);
6593 source_tree = null_pointer_node;
6594 source_length = ffecom_f2c_ftnlen_zero_node;
6595 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6596 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6597 TREE_CHAIN (TREE_CHAIN (expr_tree))
6598 = build_tree_list (NULL_TREE, dest_length);
6599 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6600 = build_tree_list (NULL_TREE, source_length);
6602 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6603 TREE_SIDE_EFFECTS (expr_tree) = 1;
6605 expand_expr_stmt (expr_tree);
6607 return;
6609 case 1: /* The (fairly) easy case. */
6610 ffecom_char_args_ (&source_tree, &source_length,
6611 ffecom_concat_list_expr_ (catlist, 0));
6612 ffecom_concat_list_kill_ (catlist);
6613 assert (source_tree != NULL_TREE);
6614 assert (source_length != NULL_TREE);
6616 if ((source_tree == error_mark_node)
6617 || (source_length == error_mark_node))
6618 return;
6620 if (dest_size == 1)
6622 dest_tree
6623 = ffecom_1 (INDIRECT_REF,
6624 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6625 (dest_tree))),
6626 dest_tree);
6627 dest_tree
6628 = ffecom_2 (ARRAY_REF,
6629 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6630 (dest_tree))),
6631 dest_tree,
6632 integer_one_node);
6633 source_tree
6634 = ffecom_1 (INDIRECT_REF,
6635 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6636 (source_tree))),
6637 source_tree);
6638 source_tree
6639 = ffecom_2 (ARRAY_REF,
6640 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6641 (source_tree))),
6642 source_tree,
6643 integer_one_node);
6645 expr_tree = ffecom_modify (void_type_node, dest_tree, source_tree);
6647 expand_expr_stmt (expr_tree);
6649 return;
6652 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6653 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6654 TREE_CHAIN (TREE_CHAIN (expr_tree))
6655 = build_tree_list (NULL_TREE, dest_length);
6656 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6657 = build_tree_list (NULL_TREE, source_length);
6659 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6660 TREE_SIDE_EFFECTS (expr_tree) = 1;
6662 expand_expr_stmt (expr_tree);
6664 return;
6666 default: /* Must actually concatenate things. */
6667 break;
6670 /* Heavy-duty concatenation. */
6673 int count = ffecom_concat_list_count_ (catlist);
6674 int i;
6675 tree lengths;
6676 tree items;
6677 tree length_array;
6678 tree item_array;
6679 tree citem;
6680 tree clength;
6683 tree hook;
6685 hook = ffebld_nonter_hook (source);
6686 assert (hook);
6687 assert (TREE_CODE (hook) == TREE_VEC);
6688 assert (TREE_VEC_LENGTH (hook) == 2);
6689 length_array = lengths = TREE_VEC_ELT (hook, 0);
6690 item_array = items = TREE_VEC_ELT (hook, 1);
6693 for (i = 0; i < count; ++i)
6695 ffecom_char_args_ (&citem, &clength,
6696 ffecom_concat_list_expr_ (catlist, i));
6697 if ((citem == error_mark_node)
6698 || (clength == error_mark_node))
6700 ffecom_concat_list_kill_ (catlist);
6701 return;
6704 items
6705 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
6706 ffecom_modify (void_type_node,
6707 ffecom_2 (ARRAY_REF,
6708 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
6709 item_array,
6710 build_int_2 (i, 0)),
6711 citem),
6712 items);
6713 lengths
6714 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
6715 ffecom_modify (void_type_node,
6716 ffecom_2 (ARRAY_REF,
6717 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
6718 length_array,
6719 build_int_2 (i, 0)),
6720 clength),
6721 lengths);
6724 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6725 TREE_CHAIN (expr_tree)
6726 = build_tree_list (NULL_TREE,
6727 ffecom_1 (ADDR_EXPR,
6728 build_pointer_type (TREE_TYPE (items)),
6729 items));
6730 TREE_CHAIN (TREE_CHAIN (expr_tree))
6731 = build_tree_list (NULL_TREE,
6732 ffecom_1 (ADDR_EXPR,
6733 build_pointer_type (TREE_TYPE (lengths)),
6734 lengths));
6735 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6736 = build_tree_list
6737 (NULL_TREE,
6738 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
6739 convert (ffecom_f2c_ftnlen_type_node,
6740 build_int_2 (count, 0))));
6741 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree))))
6742 = build_tree_list (NULL_TREE, dest_length);
6744 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCAT, expr_tree, NULL_TREE);
6745 TREE_SIDE_EFFECTS (expr_tree) = 1;
6747 expand_expr_stmt (expr_tree);
6750 ffecom_concat_list_kill_ (catlist);
6753 /* ffecom_make_gfrt_ -- Make initial info for run-time routine
6755 ffecomGfrt ix;
6756 ffecom_make_gfrt_(ix);
6758 Assumes gfrt_[ix] is NULL_TREE, and replaces it with the FUNCTION_DECL
6759 for the indicated run-time routine (ix). */
6761 static void
6762 ffecom_make_gfrt_ (ffecomGfrt ix)
6764 tree t;
6765 tree ttype;
6767 switch (ffecom_gfrt_type_[ix])
6769 case FFECOM_rttypeVOID_:
6770 ttype = void_type_node;
6771 break;
6773 case FFECOM_rttypeVOIDSTAR_:
6774 ttype = TREE_TYPE (null_pointer_node); /* `void *'. */
6775 break;
6777 case FFECOM_rttypeFTNINT_:
6778 ttype = ffecom_f2c_ftnint_type_node;
6779 break;
6781 case FFECOM_rttypeINTEGER_:
6782 ttype = ffecom_f2c_integer_type_node;
6783 break;
6785 case FFECOM_rttypeLONGINT_:
6786 ttype = ffecom_f2c_longint_type_node;
6787 break;
6789 case FFECOM_rttypeLOGICAL_:
6790 ttype = ffecom_f2c_logical_type_node;
6791 break;
6793 case FFECOM_rttypeREAL_F2C_:
6794 ttype = double_type_node;
6795 break;
6797 case FFECOM_rttypeREAL_GNU_:
6798 ttype = float_type_node;
6799 break;
6801 case FFECOM_rttypeCOMPLEX_F2C_:
6802 ttype = void_type_node;
6803 break;
6805 case FFECOM_rttypeCOMPLEX_GNU_:
6806 ttype = ffecom_f2c_complex_type_node;
6807 break;
6809 case FFECOM_rttypeDOUBLE_:
6810 ttype = double_type_node;
6811 break;
6813 case FFECOM_rttypeDOUBLEREAL_:
6814 ttype = ffecom_f2c_doublereal_type_node;
6815 break;
6817 case FFECOM_rttypeDBLCMPLX_F2C_:
6818 ttype = void_type_node;
6819 break;
6821 case FFECOM_rttypeDBLCMPLX_GNU_:
6822 ttype = ffecom_f2c_doublecomplex_type_node;
6823 break;
6825 case FFECOM_rttypeCHARACTER_:
6826 ttype = void_type_node;
6827 break;
6829 default:
6830 ttype = NULL;
6831 assert ("bad rttype" == NULL);
6832 break;
6835 ttype = build_function_type (ttype, NULL_TREE);
6836 t = build_decl (FUNCTION_DECL,
6837 get_identifier (ffecom_gfrt_name_[ix]),
6838 ttype);
6839 DECL_EXTERNAL (t) = 1;
6840 TREE_READONLY (t) = ffecom_gfrt_const_[ix] ? 1 : 0;
6841 TREE_PUBLIC (t) = 1;
6842 TREE_THIS_VOLATILE (t) = ffecom_gfrt_volatile_[ix] ? 1 : 0;
6844 /* Sanity check: A function that's const cannot be volatile. */
6846 assert (ffecom_gfrt_const_[ix] ? !ffecom_gfrt_volatile_[ix] : 1);
6848 /* Sanity check: A function that's const cannot return complex. */
6850 assert (ffecom_gfrt_const_[ix] ? !ffecom_gfrt_complex_[ix] : 1);
6852 t = start_decl (t, TRUE);
6854 finish_decl (t, NULL_TREE, TRUE);
6856 ffecom_gfrt_[ix] = t;
6859 /* Phase 1 pass over each member of a COMMON/EQUIVALENCE group. */
6861 static void
6862 ffecom_member_phase1_ (ffestorag mst UNUSED, ffestorag st)
6864 ffesymbol s = ffestorag_symbol (st);
6866 if (ffesymbol_namelisted (s))
6867 ffecom_member_namelisted_ = TRUE;
6870 /* Phase 2 pass over each member of a COMMON/EQUIVALENCE group. Declare
6871 the member so debugger will see it. Otherwise nobody should be
6872 referencing the member. */
6874 static void
6875 ffecom_member_phase2_ (ffestorag mst, ffestorag st)
6877 ffesymbol s;
6878 tree t;
6879 tree mt;
6880 tree type;
6882 if ((mst == NULL)
6883 || ((mt = ffestorag_hook (mst)) == NULL)
6884 || (mt == error_mark_node))
6885 return;
6887 if ((st == NULL)
6888 || ((s = ffestorag_symbol (st)) == NULL))
6889 return;
6891 type = ffecom_type_localvar_ (s,
6892 ffesymbol_basictype (s),
6893 ffesymbol_kindtype (s));
6894 if (type == error_mark_node)
6895 return;
6897 t = build_decl (VAR_DECL,
6898 ffecom_get_identifier_ (ffesymbol_text (s)),
6899 type);
6901 TREE_STATIC (t) = TREE_STATIC (mt);
6902 DECL_INITIAL (t) = NULL_TREE;
6903 TREE_ASM_WRITTEN (t) = 1;
6904 TREE_USED (t) = 1;
6906 SET_DECL_RTL (t,
6907 gen_rtx (MEM, TYPE_MODE (type),
6908 plus_constant (XEXP (DECL_RTL (mt), 0),
6909 ffestorag_modulo (mst)
6910 + ffestorag_offset (st)
6911 - ffestorag_offset (mst))));
6913 t = start_decl (t, FALSE);
6915 finish_decl (t, NULL_TREE, FALSE);
6918 /* Prepare source expression for assignment into a destination perhaps known
6919 to be of a specific size. */
6921 static void
6922 ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size, ffebld source)
6924 ffecomConcatList_ catlist;
6925 int count;
6926 int i;
6927 tree ltmp;
6928 tree itmp;
6929 tree tempvar = NULL_TREE;
6931 while (ffebld_op (source) == FFEBLD_opCONVERT)
6932 source = ffebld_left (source);
6934 catlist = ffecom_concat_list_new_ (source, dest_size);
6935 count = ffecom_concat_list_count_ (catlist);
6937 if (count >= 2)
6939 ltmp
6940 = ffecom_make_tempvar ("let_char_len", ffecom_f2c_ftnlen_type_node,
6941 FFETARGET_charactersizeNONE, count);
6942 itmp
6943 = ffecom_make_tempvar ("let_char_item", ffecom_f2c_address_type_node,
6944 FFETARGET_charactersizeNONE, count);
6946 tempvar = make_tree_vec (2);
6947 TREE_VEC_ELT (tempvar, 0) = ltmp;
6948 TREE_VEC_ELT (tempvar, 1) = itmp;
6951 for (i = 0; i < count; ++i)
6952 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist, i));
6954 ffecom_concat_list_kill_ (catlist);
6956 if (tempvar)
6958 ffebld_nonter_set_hook (source, tempvar);
6959 current_binding_level->prep_state = 1;
6963 /* ffecom_push_dummy_decls_ -- Transform dummy args, push parm decls in order
6965 Ignores STAR (alternate-return) dummies. All other get exec-transitioned
6966 (which generates their trees) and then their trees get push_parm_decl'd.
6968 The second arg is TRUE if the dummies are for a statement function, in
6969 which case lengths are not pushed for character arguments (since they are
6970 always known by both the caller and the callee, though the code allows
6971 for someday permitting CHAR*(*) stmtfunc dummies). */
6973 static void
6974 ffecom_push_dummy_decls_ (ffebld dummy_list, bool stmtfunc)
6976 ffebld dummy;
6977 ffebld dumlist;
6978 ffesymbol s;
6979 tree parm;
6981 ffecom_transform_only_dummies_ = TRUE;
6983 /* First push the parms corresponding to actual dummy "contents". */
6985 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
6987 dummy = ffebld_head (dumlist);
6988 switch (ffebld_op (dummy))
6990 case FFEBLD_opSTAR:
6991 case FFEBLD_opANY:
6992 continue; /* Forget alternate returns. */
6994 default:
6995 break;
6997 assert (ffebld_op (dummy) == FFEBLD_opSYMTER);
6998 s = ffebld_symter (dummy);
6999 parm = ffesymbol_hook (s).decl_tree;
7000 if (parm == NULL_TREE)
7002 s = ffecom_sym_transform_ (s);
7003 parm = ffesymbol_hook (s).decl_tree;
7004 assert (parm != NULL_TREE);
7006 if (parm != error_mark_node)
7007 push_parm_decl (parm);
7010 /* Then, for CHARACTER dummies, push the parms giving their lengths. */
7012 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7014 dummy = ffebld_head (dumlist);
7015 switch (ffebld_op (dummy))
7017 case FFEBLD_opSTAR:
7018 case FFEBLD_opANY:
7019 continue; /* Forget alternate returns, they mean
7020 NOTHING! */
7022 default:
7023 break;
7025 s = ffebld_symter (dummy);
7026 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
7027 continue; /* Only looking for CHARACTER arguments. */
7028 if (stmtfunc && (ffesymbol_size (s) != FFETARGET_charactersizeNONE))
7029 continue; /* Stmtfunc arg with known size needs no
7030 length param. */
7031 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
7032 continue; /* Only looking for variables and arrays. */
7033 parm = ffesymbol_hook (s).length_tree;
7034 assert (parm != NULL_TREE);
7035 if (parm != error_mark_node)
7036 push_parm_decl (parm);
7039 ffecom_transform_only_dummies_ = FALSE;
7042 /* ffecom_start_progunit_ -- Beginning of program unit
7044 Does GNU back end stuff necessary to teach it about the start of its
7045 equivalent of a Fortran program unit. */
7047 static void
7048 ffecom_start_progunit_ (void)
7050 ffesymbol fn = ffecom_primary_entry_;
7051 ffebld arglist;
7052 tree id; /* Identifier (name) of function. */
7053 tree type; /* Type of function. */
7054 tree result; /* Result of function. */
7055 ffeinfoBasictype bt;
7056 ffeinfoKindtype kt;
7057 ffeglobal g;
7058 ffeglobalType gt;
7059 ffeglobalType egt = FFEGLOBAL_type;
7060 bool charfunc;
7061 bool cmplxfunc;
7062 bool altentries = (ffecom_num_entrypoints_ != 0);
7063 bool multi
7064 = altentries
7065 && (ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
7066 && (ffecom_master_bt_ == FFEINFO_basictypeNONE);
7067 bool main_program = FALSE;
7068 location_t old_loc = input_location;
7070 assert (fn != NULL);
7071 assert (ffesymbol_hook (fn).decl_tree == NULL_TREE);
7073 input_filename = ffesymbol_where_filename (fn);
7074 input_line = ffesymbol_where_filelinenum (fn);
7076 switch (ffecom_primary_entry_kind_)
7078 case FFEINFO_kindPROGRAM:
7079 main_program = TRUE;
7080 gt = FFEGLOBAL_typeMAIN;
7081 bt = FFEINFO_basictypeNONE;
7082 kt = FFEINFO_kindtypeNONE;
7083 type = ffecom_tree_fun_type_void;
7084 charfunc = FALSE;
7085 cmplxfunc = FALSE;
7086 break;
7088 case FFEINFO_kindBLOCKDATA:
7089 gt = FFEGLOBAL_typeBDATA;
7090 bt = FFEINFO_basictypeNONE;
7091 kt = FFEINFO_kindtypeNONE;
7092 type = ffecom_tree_fun_type_void;
7093 charfunc = FALSE;
7094 cmplxfunc = FALSE;
7095 break;
7097 case FFEINFO_kindFUNCTION:
7098 gt = FFEGLOBAL_typeFUNC;
7099 egt = FFEGLOBAL_typeEXT;
7100 bt = ffesymbol_basictype (fn);
7101 kt = ffesymbol_kindtype (fn);
7102 if (bt == FFEINFO_basictypeNONE)
7104 ffeimplic_establish_symbol (fn);
7105 if (ffesymbol_funcresult (fn) != NULL)
7106 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
7107 bt = ffesymbol_basictype (fn);
7108 kt = ffesymbol_kindtype (fn);
7111 if (multi)
7112 charfunc = cmplxfunc = FALSE;
7113 else if (bt == FFEINFO_basictypeCHARACTER)
7114 charfunc = TRUE, cmplxfunc = FALSE;
7115 else if ((bt == FFEINFO_basictypeCOMPLEX)
7116 && ffesymbol_is_f2c (fn)
7117 && !altentries)
7118 charfunc = FALSE, cmplxfunc = TRUE;
7119 else
7120 charfunc = cmplxfunc = FALSE;
7122 if (multi || charfunc)
7123 type = ffecom_tree_fun_type_void;
7124 else if (ffesymbol_is_f2c (fn) && !altentries)
7125 type = ffecom_tree_fun_type[bt][kt];
7126 else
7127 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
7129 if ((type == NULL_TREE)
7130 || (TREE_TYPE (type) == NULL_TREE))
7131 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
7132 break;
7134 case FFEINFO_kindSUBROUTINE:
7135 gt = FFEGLOBAL_typeSUBR;
7136 egt = FFEGLOBAL_typeEXT;
7137 bt = FFEINFO_basictypeNONE;
7138 kt = FFEINFO_kindtypeNONE;
7139 if (ffecom_is_altreturning_)
7140 type = ffecom_tree_subr_type;
7141 else
7142 type = ffecom_tree_fun_type_void;
7143 charfunc = FALSE;
7144 cmplxfunc = FALSE;
7145 break;
7147 default:
7148 assert ("say what??" == NULL);
7149 /* Fall through. */
7150 case FFEINFO_kindANY:
7151 gt = FFEGLOBAL_typeANY;
7152 bt = FFEINFO_basictypeNONE;
7153 kt = FFEINFO_kindtypeNONE;
7154 type = error_mark_node;
7155 charfunc = FALSE;
7156 cmplxfunc = FALSE;
7157 break;
7160 if (altentries)
7162 id = ffecom_get_invented_identifier ("__g77_masterfun_%s",
7163 ffesymbol_text (fn));
7165 #if FFETARGET_isENFORCED_MAIN
7166 else if (main_program)
7167 id = get_identifier (FFETARGET_nameENFORCED_MAIN_NAME);
7168 #endif
7169 else
7170 id = ffecom_get_external_identifier_ (fn);
7172 start_function (id,
7173 type,
7174 0, /* nested/inline */
7175 !altentries); /* TREE_PUBLIC */
7177 TREE_USED (current_function_decl) = 1; /* Avoid spurious warning if altentries. */
7179 if (!altentries
7180 && ((g = ffesymbol_global (fn)) != NULL)
7181 && ((ffeglobal_type (g) == gt)
7182 || (ffeglobal_type (g) == egt)))
7184 ffeglobal_set_hook (g, current_function_decl);
7187 /* Arg handling needs exec-transitioned ffesymbols to work with. But
7188 exec-transitioning needs current_function_decl to be filled in. So we
7189 do these things in two phases. */
7191 if (altentries)
7192 { /* 1st arg identifies which entrypoint. */
7193 ffecom_which_entrypoint_decl_
7194 = build_decl (PARM_DECL,
7195 ffecom_get_invented_identifier ("__g77_%s",
7196 "which_entrypoint"),
7197 integer_type_node);
7198 push_parm_decl (ffecom_which_entrypoint_decl_);
7201 if (charfunc
7202 || cmplxfunc
7203 || multi)
7204 { /* Arg for result (return value). */
7205 tree type;
7206 tree length;
7208 if (charfunc)
7209 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
7210 else if (cmplxfunc)
7211 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
7212 else
7213 type = ffecom_multi_type_node_;
7215 result = ffecom_get_invented_identifier ("__g77_%s", "result");
7217 /* Make length arg _and_ enhance type info for CHAR arg itself. */
7219 if (charfunc)
7220 length = ffecom_char_enhance_arg_ (&type, fn);
7221 else
7222 length = NULL_TREE; /* Not ref'd if !charfunc. */
7224 type = build_pointer_type (type);
7225 result = build_decl (PARM_DECL, result, type);
7227 push_parm_decl (result);
7228 if (multi)
7229 ffecom_multi_retval_ = result;
7230 else
7231 ffecom_func_result_ = result;
7233 if (charfunc)
7235 push_parm_decl (length);
7236 ffecom_func_length_ = length;
7240 if (ffecom_primary_entry_is_proc_)
7242 if (altentries)
7243 arglist = ffecom_master_arglist_;
7244 else
7245 arglist = ffesymbol_dummyargs (fn);
7246 ffecom_push_dummy_decls_ (arglist, FALSE);
7249 if (TREE_CODE (current_function_decl) != ERROR_MARK)
7250 store_parm_decls (main_program ? 1 : 0);
7252 ffecom_start_compstmt ();
7253 /* Disallow temp vars at this level. */
7254 current_binding_level->prep_state = 2;
7256 input_location = old_loc;
7258 /* This handles any symbols still untransformed, in case -g specified.
7259 This used to be done in ffecom_finish_progunit, but it turns out to
7260 be necessary to do it here so that statement functions are
7261 expanded before code. But don't bother for BLOCK DATA. */
7263 if (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
7264 ffesymbol_drive (ffecom_finish_symbol_transform_);
7267 /* ffecom_sym_transform_ -- Transform FFE sym into backend sym
7269 ffesymbol s;
7270 ffecom_sym_transform_(s);
7272 The ffesymbol_hook info for s is updated with appropriate backend info
7273 on the symbol. */
7275 static ffesymbol
7276 ffecom_sym_transform_ (ffesymbol s)
7278 tree t; /* Transformed thingy. */
7279 tree tlen; /* Length if CHAR*(*). */
7280 bool addr; /* Is t the address of the thingy? */
7281 ffeinfoBasictype bt;
7282 ffeinfoKindtype kt;
7283 ffeglobal g;
7284 location_t old_loc = input_location;
7286 /* Must ensure special ASSIGN variables are declared at top of outermost
7287 block, else they'll end up in the innermost block when their first
7288 ASSIGN is seen, which leaves them out of scope when they're the
7289 subject of a GOTO or I/O statement.
7291 We make this variable even if -fugly-assign. Just let it go unused,
7292 in case it turns out there are cases where we really want to use this
7293 variable anyway (e.g. ASSIGN to INTEGER*2 variable). */
7295 if (! ffecom_transform_only_dummies_
7296 && ffesymbol_assigned (s)
7297 && ! ffesymbol_hook (s).assign_tree)
7298 s = ffecom_sym_transform_assign_ (s);
7300 if (ffesymbol_sfdummyparent (s) == NULL)
7302 input_filename = ffesymbol_where_filename (s);
7303 input_line = ffesymbol_where_filelinenum (s);
7305 else
7307 ffesymbol sf = ffesymbol_sfdummyparent (s);
7309 input_filename = ffesymbol_where_filename (sf);
7310 input_line = ffesymbol_where_filelinenum (sf);
7313 bt = ffeinfo_basictype (ffebld_info (s));
7314 kt = ffeinfo_kindtype (ffebld_info (s));
7316 t = NULL_TREE;
7317 tlen = NULL_TREE;
7318 addr = FALSE;
7320 switch (ffesymbol_kind (s))
7322 case FFEINFO_kindNONE:
7323 switch (ffesymbol_where (s))
7325 case FFEINFO_whereDUMMY: /* Subroutine or function. */
7326 assert (ffecom_transform_only_dummies_);
7328 /* Before 0.4, this could be ENTITY/DUMMY, but see
7329 ffestu_sym_end_transition -- no longer true (in particular, if
7330 it could be an ENTITY, it _will_ be made one, so that
7331 possibility won't come through here). So we never make length
7332 arg for CHARACTER type. */
7334 t = build_decl (PARM_DECL,
7335 ffecom_get_identifier_ (ffesymbol_text (s)),
7336 ffecom_tree_ptr_to_subr_type);
7337 DECL_ARTIFICIAL (t) = 1;
7338 addr = TRUE;
7339 break;
7341 case FFEINFO_whereGLOBAL: /* Subroutine or function. */
7342 assert (!ffecom_transform_only_dummies_);
7344 if (((g = ffesymbol_global (s)) != NULL)
7345 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7346 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7347 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
7348 && (ffeglobal_hook (g) != NULL_TREE)
7349 && ffe_is_globals ())
7351 t = ffeglobal_hook (g);
7352 break;
7355 t = build_decl (FUNCTION_DECL,
7356 ffecom_get_external_identifier_ (s),
7357 ffecom_tree_subr_type); /* Assume subr. */
7358 DECL_EXTERNAL (t) = 1;
7359 TREE_PUBLIC (t) = 1;
7361 t = start_decl (t, FALSE);
7362 finish_decl (t, NULL_TREE, FALSE);
7364 if ((g != NULL)
7365 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7366 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7367 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
7368 ffeglobal_set_hook (g, t);
7370 ffecom_save_tree_forever (t);
7372 break;
7374 default:
7375 assert ("NONE where unexpected" == NULL);
7376 /* Fall through. */
7377 case FFEINFO_whereANY:
7378 break;
7380 break;
7382 case FFEINFO_kindENTITY:
7383 switch (ffeinfo_where (ffesymbol_info (s)))
7386 case FFEINFO_whereCONSTANT:
7387 /* ~~Debugging info needed? */
7388 assert (!ffecom_transform_only_dummies_);
7389 t = error_mark_node; /* Shouldn't ever see this in expr. */
7390 break;
7392 case FFEINFO_whereLOCAL:
7393 assert (!ffecom_transform_only_dummies_);
7396 ffestorag st = ffesymbol_storage (s);
7397 tree type;
7399 type = ffecom_type_localvar_ (s, bt, kt);
7401 if (type == error_mark_node)
7403 t = error_mark_node;
7404 break;
7407 if ((st != NULL)
7408 && (ffestorag_size (st) == 0))
7410 t = error_mark_node;
7411 break;
7414 if ((st != NULL)
7415 && (ffestorag_parent (st) != NULL))
7416 { /* Child of EQUIVALENCE parent. */
7417 ffestorag est;
7418 tree et;
7419 ffetargetOffset offset;
7421 est = ffestorag_parent (st);
7422 ffecom_transform_equiv_ (est);
7424 et = ffestorag_hook (est);
7425 assert (et != NULL_TREE);
7427 if (! TREE_STATIC (et))
7428 put_var_into_stack (et, /*rescan=*/true);
7430 offset = ffestorag_modulo (est)
7431 + ffestorag_offset (ffesymbol_storage (s))
7432 - ffestorag_offset (est);
7434 ffecom_debug_kludge_ (et, "EQUIVALENCE", s, type, offset);
7436 /* (t_type *) (((char *) &et) + offset) */
7438 t = convert (string_type_node, /* (char *) */
7439 ffecom_1 (ADDR_EXPR,
7440 build_pointer_type (TREE_TYPE (et)),
7441 et));
7442 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
7444 build_int_2 (offset, 0));
7445 t = convert (build_pointer_type (type),
7447 TREE_CONSTANT (t) = staticp (et);
7449 addr = TRUE;
7451 else
7453 tree initexpr;
7454 bool init = ffesymbol_is_init (s);
7456 t = build_decl (VAR_DECL,
7457 ffecom_get_identifier_ (ffesymbol_text (s)),
7458 type);
7460 if (init
7461 || ffesymbol_namelisted (s)
7462 #ifdef FFECOM_sizeMAXSTACKITEM
7463 || ((st != NULL)
7464 && (ffestorag_size (st) > FFECOM_sizeMAXSTACKITEM))
7465 #endif
7466 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
7467 && (ffecom_primary_entry_kind_
7468 != FFEINFO_kindBLOCKDATA)
7469 && (ffesymbol_is_save (s) || ffe_is_saveall ())))
7470 TREE_STATIC (t) = !ffesymbol_attr (s, FFESYMBOL_attrADJUSTABLE);
7471 else
7472 TREE_STATIC (t) = 0; /* No need to make static. */
7474 if (init || ffe_is_init_local_zero ())
7475 DECL_INITIAL (t) = error_mark_node;
7477 /* Keep -Wunused from complaining about var if it
7478 is used as sfunc arg or DATA implied-DO. */
7479 if (ffesymbol_attrs (s) & FFESYMBOL_attrsSFARG)
7480 DECL_IN_SYSTEM_HEADER (t) = 1;
7482 t = start_decl (t, FALSE);
7484 if (init)
7486 if (ffesymbol_init (s) != NULL)
7487 initexpr = ffecom_expr (ffesymbol_init (s));
7488 else
7489 initexpr = ffecom_init_zero_ (t);
7491 else if (ffe_is_init_local_zero ())
7492 initexpr = ffecom_init_zero_ (t);
7493 else
7494 initexpr = NULL_TREE; /* Not ref'd if !init. */
7496 finish_decl (t, initexpr, FALSE);
7498 if (st != NULL && DECL_SIZE (t) != error_mark_node)
7500 assert (TREE_CODE (DECL_SIZE_UNIT (t)) == INTEGER_CST);
7501 assert (0 == compare_tree_int (DECL_SIZE_UNIT (t),
7502 ffestorag_size (st)));
7506 break;
7508 case FFEINFO_whereRESULT:
7509 assert (!ffecom_transform_only_dummies_);
7511 if (bt == FFEINFO_basictypeCHARACTER)
7512 { /* Result is already in list of dummies, use
7513 it (& length). */
7514 t = ffecom_func_result_;
7515 tlen = ffecom_func_length_;
7516 addr = TRUE;
7517 break;
7519 if ((ffecom_num_entrypoints_ == 0)
7520 && (bt == FFEINFO_basictypeCOMPLEX)
7521 && (ffesymbol_is_f2c (ffecom_primary_entry_)))
7522 { /* Result is already in list of dummies, use
7523 it. */
7524 t = ffecom_func_result_;
7525 addr = TRUE;
7526 break;
7528 if (ffecom_func_result_ != NULL_TREE)
7530 t = ffecom_func_result_;
7531 break;
7533 if ((ffecom_num_entrypoints_ != 0)
7534 && (ffecom_master_bt_ == FFEINFO_basictypeNONE))
7536 assert (ffecom_multi_retval_ != NULL_TREE);
7537 t = ffecom_1 (INDIRECT_REF, ffecom_multi_type_node_,
7538 ffecom_multi_retval_);
7539 t = ffecom_2 (COMPONENT_REF, ffecom_tree_type[bt][kt],
7540 t, ffecom_multi_fields_[bt][kt]);
7542 break;
7545 t = build_decl (VAR_DECL,
7546 ffecom_get_identifier_ (ffesymbol_text (s)),
7547 ffecom_tree_type[bt][kt]);
7548 TREE_STATIC (t) = 0; /* Put result on stack. */
7549 t = start_decl (t, FALSE);
7550 finish_decl (t, NULL_TREE, FALSE);
7552 ffecom_func_result_ = t;
7554 break;
7556 case FFEINFO_whereDUMMY:
7558 tree type;
7559 ffebld dl;
7560 ffebld dim;
7561 tree low;
7562 tree high;
7563 tree old_sizes;
7564 bool adjustable = FALSE; /* Conditionally adjustable? */
7566 type = ffecom_tree_type[bt][kt];
7567 if (ffesymbol_sfdummyparent (s) != NULL)
7569 if (current_function_decl == ffecom_outer_function_decl_)
7570 { /* Exec transition before sfunc
7571 context; get it later. */
7572 break;
7574 t = ffecom_get_identifier_ (ffesymbol_text
7575 (ffesymbol_sfdummyparent (s)));
7577 else
7578 t = ffecom_get_identifier_ (ffesymbol_text (s));
7580 assert (ffecom_transform_only_dummies_);
7582 old_sizes = get_pending_sizes ();
7583 put_pending_sizes (old_sizes);
7585 if (bt == FFEINFO_basictypeCHARACTER)
7586 tlen = ffecom_char_enhance_arg_ (&type, s);
7587 type = ffecom_check_size_overflow_ (s, type, TRUE);
7589 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
7591 if (type == error_mark_node)
7592 break;
7594 dim = ffebld_head (dl);
7595 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
7596 if ((ffebld_left (dim) == NULL) || ffecom_doing_entry_)
7597 low = ffecom_integer_one_node;
7598 else
7599 low = ffecom_expr (ffebld_left (dim));
7600 assert (ffebld_right (dim) != NULL);
7601 if ((ffebld_op (ffebld_right (dim)) == FFEBLD_opSTAR)
7602 || ffecom_doing_entry_)
7604 /* Used to just do high=low. But for ffecom_tree_
7605 canonize_ref_, it probably is important to correctly
7606 assess the size. E.g. given COMPLEX C(*),CFUNC and
7607 C(2)=CFUNC(C), overlap can happen, while it can't
7608 for, say, C(1)=CFUNC(C(2)). */
7609 /* Even more recently used to set to INT_MAX, but that
7610 broke when some overflow checking went into the back
7611 end. Now we just leave the upper bound unspecified. */
7612 high = NULL;
7614 else
7615 high = ffecom_expr (ffebld_right (dim));
7617 /* Determine whether array is conditionally adjustable,
7618 to decide whether back-end magic is needed.
7620 Normally the front end uses the back-end function
7621 variable_size to wrap SAVE_EXPR's around expressions
7622 affecting the size/shape of an array so that the
7623 size/shape info doesn't change during execution
7624 of the compiled code even though variables and
7625 functions referenced in those expressions might.
7627 variable_size also makes sure those saved expressions
7628 get evaluated immediately upon entry to the
7629 compiled procedure -- the front end normally doesn't
7630 have to worry about that.
7632 However, there is a problem with this that affects
7633 g77's implementation of entry points, and that is
7634 that it is _not_ true that each invocation of the
7635 compiled procedure is permitted to evaluate
7636 array size/shape info -- because it is possible
7637 that, for some invocations, that info is invalid (in
7638 which case it is "promised" -- i.e. a violation of
7639 the Fortran standard -- that the compiled code
7640 won't reference the array or its size/shape
7641 during that particular invocation).
7643 To phrase this in C terms, consider this gcc function:
7645 void foo (int *n, float (*a)[*n])
7647 // a is "pointer to array ...", fyi.
7650 Suppose that, for some invocations, it is permitted
7651 for a caller of foo to do this:
7653 foo (NULL, NULL);
7655 Now the _written_ code for foo can take such a call
7656 into account by either testing explicitly for whether
7657 (a == NULL) || (n == NULL) -- presumably it is
7658 not permitted to reference *a in various fashions
7659 if (n == NULL) I suppose -- or it can avoid it by
7660 looking at other info (other arguments, static/global
7661 data, etc.).
7663 However, this won't work in gcc 2.5.8 because it'll
7664 automatically emit the code to save the "*n"
7665 expression, which'll yield a NULL dereference for
7666 the "foo (NULL, NULL)" call, something the code
7667 for foo cannot prevent.
7669 g77 definitely needs to avoid executing such
7670 code anytime the pointer to the adjustable array
7671 is NULL, because even if its bounds expressions
7672 don't have any references to possible "absent"
7673 variables like "*n" -- say all variable references
7674 are to COMMON variables, i.e. global (though in C,
7675 local static could actually make sense) -- the
7676 expressions could yield other run-time problems
7677 for allowably "dead" values in those variables.
7679 For example, let's consider a more complicated
7680 version of foo:
7682 extern int i;
7683 extern int j;
7685 void foo (float (*a)[i/j])
7690 The above is (essentially) quite valid for Fortran
7691 but, again, for a call like "foo (NULL);", it is
7692 permitted for i and j to be undefined when the
7693 call is made. If j happened to be zero, for
7694 example, emitting the code to evaluate "i/j"
7695 could result in a run-time error.
7697 Offhand, though I don't have my F77 or F90
7698 standards handy, it might even be valid for a
7699 bounds expression to contain a function reference,
7700 in which case I doubt it is permitted for an
7701 implementation to invoke that function in the
7702 Fortran case involved here (invocation of an
7703 alternate ENTRY point that doesn't have the adjustable
7704 array as one of its arguments).
7706 So, the code that the compiler would normally emit
7707 to preevaluate the size/shape info for an
7708 adjustable array _must not_ be executed at run time
7709 in certain cases. Specifically, for Fortran,
7710 the case is when the pointer to the adjustable
7711 array == NULL. (For gnu-ish C, it might be nice
7712 for the source code itself to specify an expression
7713 that, if TRUE, inhibits execution of the code. Or
7714 reverse the sense for elegance.)
7716 (Note that g77 could use a different test than NULL,
7717 actually, since it happens to always pass an
7718 integer to the called function that specifies which
7719 entry point is being invoked. Hmm, this might
7720 solve the next problem.)
7722 One way a user could, I suppose, write "foo" so
7723 it works is to insert COND_EXPR's for the
7724 size/shape info so the dangerous stuff isn't
7725 actually done, as in:
7727 void foo (int *n, float (*a)[(a == NULL) ? 0 : *n])
7732 The next problem is that the front end needs to
7733 be able to tell the back end about the array's
7734 decl _before_ it tells it about the conditional
7735 expression to inhibit evaluation of size/shape info,
7736 as shown above.
7738 To solve this, the front end needs to be able
7739 to give the back end the expression to inhibit
7740 generation of the preevaluation code _after_
7741 it makes the decl for the adjustable array.
7743 Until then, the above example using the COND_EXPR
7744 doesn't pass muster with gcc because the "(a == NULL)"
7745 part has a reference to "a", which is still
7746 undefined at that point.
7748 g77 will therefore use a different mechanism in the
7749 meantime. */
7751 if (!adjustable
7752 && ((TREE_CODE (low) != INTEGER_CST)
7753 || (high && TREE_CODE (high) != INTEGER_CST)))
7754 adjustable = TRUE;
7756 #if 0 /* Old approach -- see below. */
7757 if (TREE_CODE (low) != INTEGER_CST)
7758 low = ffecom_3 (COND_EXPR, integer_type_node,
7759 ffecom_adjarray_passed_ (s),
7760 low,
7761 ffecom_integer_zero_node);
7763 if (high && TREE_CODE (high) != INTEGER_CST)
7764 high = ffecom_3 (COND_EXPR, integer_type_node,
7765 ffecom_adjarray_passed_ (s),
7766 high,
7767 ffecom_integer_zero_node);
7768 #endif
7770 /* ~~~gcc/stor-layout.c (layout_type) should do this,
7771 probably. Fixes 950302-1.f. */
7773 if (TREE_CODE (low) != INTEGER_CST)
7774 low = variable_size (low);
7776 /* ~~~Similarly, this fixes dumb0.f. The C front end
7777 does this, which is why dumb0.c would work. */
7779 if (high && TREE_CODE (high) != INTEGER_CST)
7780 high = variable_size (high);
7782 type
7783 = build_array_type
7784 (type,
7785 build_range_type (ffecom_integer_type_node,
7786 low, high));
7787 type = ffecom_check_size_overflow_ (s, type, TRUE);
7790 if (type == error_mark_node)
7792 t = error_mark_node;
7793 break;
7796 if ((ffesymbol_sfdummyparent (s) == NULL)
7797 || (ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER))
7799 type = build_pointer_type (type);
7800 addr = TRUE;
7803 t = build_decl (PARM_DECL, t, type);
7804 DECL_ARTIFICIAL (t) = 1;
7806 /* If this arg is present in every entry point's list of
7807 dummy args, then we're done. */
7809 if (ffesymbol_numentries (s)
7810 == (ffecom_num_entrypoints_ + 1))
7811 break;
7813 #if 1
7815 /* If variable_size in stor-layout has been called during
7816 the above, then get_pending_sizes should have the
7817 yet-to-be-evaluated saved expressions pending.
7818 Make the whole lot of them get emitted, conditionally
7819 on whether the array decl ("t" above) is not NULL. */
7822 tree sizes = get_pending_sizes ();
7823 tree tem;
7825 for (tem = sizes;
7826 tem != old_sizes;
7827 tem = TREE_CHAIN (tem))
7829 tree temv = TREE_VALUE (tem);
7831 if (sizes == tem)
7832 sizes = temv;
7833 else
7834 sizes
7835 = ffecom_2 (COMPOUND_EXPR,
7836 TREE_TYPE (sizes),
7837 temv,
7838 sizes);
7841 if (sizes != tem)
7843 sizes
7844 = ffecom_3 (COND_EXPR,
7845 TREE_TYPE (sizes),
7846 ffecom_2 (NE_EXPR,
7847 integer_type_node,
7849 null_pointer_node),
7850 sizes,
7851 convert (TREE_TYPE (sizes),
7852 integer_zero_node));
7853 sizes = ffecom_save_tree (sizes);
7855 sizes
7856 = tree_cons (NULL_TREE, sizes, tem);
7859 if (sizes)
7860 put_pending_sizes (sizes);
7863 #else
7864 #if 0
7865 if (adjustable
7866 && (ffesymbol_numentries (s)
7867 != ffecom_num_entrypoints_ + 1))
7868 DECL_SOMETHING (t)
7869 = ffecom_2 (NE_EXPR, integer_type_node,
7871 null_pointer_node);
7872 #else
7873 #if 0
7874 if (adjustable
7875 && (ffesymbol_numentries (s)
7876 != ffecom_num_entrypoints_ + 1))
7878 ffebad_start (FFEBAD_MISSING_ADJARRAY_UNSUPPORTED);
7879 ffebad_here (0, ffesymbol_where_line (s),
7880 ffesymbol_where_column (s));
7881 ffebad_string (ffesymbol_text (s));
7882 ffebad_finish ();
7884 #endif
7885 #endif
7886 #endif
7888 break;
7890 case FFEINFO_whereCOMMON:
7892 ffesymbol cs;
7893 ffeglobal cg;
7894 tree ct;
7895 ffestorag st = ffesymbol_storage (s);
7896 tree type;
7898 cs = ffesymbol_common (s); /* The COMMON area itself. */
7899 if (st != NULL) /* Else not laid out. */
7901 ffecom_transform_common_ (cs);
7902 st = ffesymbol_storage (s);
7905 type = ffecom_type_localvar_ (s, bt, kt);
7907 cg = ffesymbol_global (cs); /* The global COMMON info. */
7908 if ((cg == NULL)
7909 || (ffeglobal_type (cg) != FFEGLOBAL_typeCOMMON))
7910 ct = NULL_TREE;
7911 else
7912 ct = ffeglobal_hook (cg); /* The common area's tree. */
7914 if ((ct == NULL_TREE)
7915 || (st == NULL)
7916 || (type == error_mark_node))
7917 t = error_mark_node;
7918 else
7920 ffetargetOffset offset;
7921 ffestorag cst;
7922 tree toffset;
7924 cst = ffestorag_parent (st);
7925 assert (cst == ffesymbol_storage (cs));
7927 offset = ffestorag_modulo (cst)
7928 + ffestorag_offset (st)
7929 - ffestorag_offset (cst);
7931 ffecom_debug_kludge_ (ct, "COMMON", s, type, offset);
7933 /* (t_type *) (((char *) &ct) + offset) */
7935 t = convert (string_type_node, /* (char *) */
7936 ffecom_1 (ADDR_EXPR,
7937 build_pointer_type (TREE_TYPE (ct)),
7938 ct));
7939 toffset = build_int_2 (offset, 0);
7940 TREE_TYPE (toffset) = ssizetype;
7941 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
7942 t, toffset);
7943 t = convert (build_pointer_type (type),
7945 TREE_CONSTANT (t) = 1;
7947 addr = TRUE;
7950 break;
7952 case FFEINFO_whereIMMEDIATE:
7953 case FFEINFO_whereGLOBAL:
7954 case FFEINFO_whereFLEETING:
7955 case FFEINFO_whereFLEETING_CADDR:
7956 case FFEINFO_whereFLEETING_IADDR:
7957 case FFEINFO_whereINTRINSIC:
7958 case FFEINFO_whereCONSTANT_SUBOBJECT:
7959 default:
7960 assert ("ENTITY where unheard of" == NULL);
7961 /* Fall through. */
7962 case FFEINFO_whereANY:
7963 t = error_mark_node;
7964 break;
7966 break;
7968 case FFEINFO_kindFUNCTION:
7969 switch (ffeinfo_where (ffesymbol_info (s)))
7971 case FFEINFO_whereLOCAL: /* Me. */
7972 assert (!ffecom_transform_only_dummies_);
7973 t = current_function_decl;
7974 break;
7976 case FFEINFO_whereGLOBAL:
7977 assert (!ffecom_transform_only_dummies_);
7979 if (((g = ffesymbol_global (s)) != NULL)
7980 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7981 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
7982 && (ffeglobal_hook (g) != NULL_TREE)
7983 && ffe_is_globals ())
7985 t = ffeglobal_hook (g);
7986 break;
7989 if (ffesymbol_is_f2c (s)
7990 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
7991 t = ffecom_tree_fun_type[bt][kt];
7992 else
7993 t = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
7995 t = build_decl (FUNCTION_DECL,
7996 ffecom_get_external_identifier_ (s),
7998 DECL_EXTERNAL (t) = 1;
7999 TREE_PUBLIC (t) = 1;
8001 t = start_decl (t, FALSE);
8002 finish_decl (t, NULL_TREE, FALSE);
8004 if ((g != NULL)
8005 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8006 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8007 ffeglobal_set_hook (g, t);
8009 ffecom_save_tree_forever (t);
8011 break;
8013 case FFEINFO_whereDUMMY:
8014 assert (ffecom_transform_only_dummies_);
8016 if (ffesymbol_is_f2c (s)
8017 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8018 t = ffecom_tree_ptr_to_fun_type[bt][kt];
8019 else
8020 t = build_pointer_type
8021 (build_function_type (ffecom_tree_type[bt][kt], NULL_TREE));
8023 t = build_decl (PARM_DECL,
8024 ffecom_get_identifier_ (ffesymbol_text (s)),
8026 DECL_ARTIFICIAL (t) = 1;
8027 addr = TRUE;
8028 break;
8030 case FFEINFO_whereCONSTANT: /* Statement function. */
8031 assert (!ffecom_transform_only_dummies_);
8032 t = ffecom_gen_sfuncdef_ (s, bt, kt);
8033 break;
8035 case FFEINFO_whereINTRINSIC:
8036 assert (!ffecom_transform_only_dummies_);
8037 break; /* Let actual references generate their
8038 decls. */
8040 default:
8041 assert ("FUNCTION where unheard of" == NULL);
8042 /* Fall through. */
8043 case FFEINFO_whereANY:
8044 t = error_mark_node;
8045 break;
8047 break;
8049 case FFEINFO_kindSUBROUTINE:
8050 switch (ffeinfo_where (ffesymbol_info (s)))
8052 case FFEINFO_whereLOCAL: /* Me. */
8053 assert (!ffecom_transform_only_dummies_);
8054 t = current_function_decl;
8055 break;
8057 case FFEINFO_whereGLOBAL:
8058 assert (!ffecom_transform_only_dummies_);
8060 if (((g = ffesymbol_global (s)) != NULL)
8061 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8062 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8063 && (ffeglobal_hook (g) != NULL_TREE)
8064 && ffe_is_globals ())
8066 t = ffeglobal_hook (g);
8067 break;
8070 t = build_decl (FUNCTION_DECL,
8071 ffecom_get_external_identifier_ (s),
8072 ffecom_tree_subr_type);
8073 DECL_EXTERNAL (t) = 1;
8074 TREE_PUBLIC (t) = 1;
8076 t = start_decl (t, ffe_is_globals ());
8077 finish_decl (t, NULL_TREE, ffe_is_globals ());
8079 if ((g != NULL)
8080 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8081 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8082 ffeglobal_set_hook (g, t);
8084 ffecom_save_tree_forever (t);
8086 break;
8088 case FFEINFO_whereDUMMY:
8089 assert (ffecom_transform_only_dummies_);
8091 t = build_decl (PARM_DECL,
8092 ffecom_get_identifier_ (ffesymbol_text (s)),
8093 ffecom_tree_ptr_to_subr_type);
8094 DECL_ARTIFICIAL (t) = 1;
8095 addr = TRUE;
8096 break;
8098 case FFEINFO_whereINTRINSIC:
8099 assert (!ffecom_transform_only_dummies_);
8100 break; /* Let actual references generate their
8101 decls. */
8103 default:
8104 assert ("SUBROUTINE where unheard of" == NULL);
8105 /* Fall through. */
8106 case FFEINFO_whereANY:
8107 t = error_mark_node;
8108 break;
8110 break;
8112 case FFEINFO_kindPROGRAM:
8113 switch (ffeinfo_where (ffesymbol_info (s)))
8115 case FFEINFO_whereLOCAL: /* Me. */
8116 assert (!ffecom_transform_only_dummies_);
8117 t = current_function_decl;
8118 break;
8120 case FFEINFO_whereCOMMON:
8121 case FFEINFO_whereDUMMY:
8122 case FFEINFO_whereGLOBAL:
8123 case FFEINFO_whereRESULT:
8124 case FFEINFO_whereFLEETING:
8125 case FFEINFO_whereFLEETING_CADDR:
8126 case FFEINFO_whereFLEETING_IADDR:
8127 case FFEINFO_whereIMMEDIATE:
8128 case FFEINFO_whereINTRINSIC:
8129 case FFEINFO_whereCONSTANT:
8130 case FFEINFO_whereCONSTANT_SUBOBJECT:
8131 default:
8132 assert ("PROGRAM where unheard of" == NULL);
8133 /* Fall through. */
8134 case FFEINFO_whereANY:
8135 t = error_mark_node;
8136 break;
8138 break;
8140 case FFEINFO_kindBLOCKDATA:
8141 switch (ffeinfo_where (ffesymbol_info (s)))
8143 case FFEINFO_whereLOCAL: /* Me. */
8144 assert (!ffecom_transform_only_dummies_);
8145 t = current_function_decl;
8146 break;
8148 case FFEINFO_whereGLOBAL:
8149 assert (!ffecom_transform_only_dummies_);
8151 t = build_decl (FUNCTION_DECL,
8152 ffecom_get_external_identifier_ (s),
8153 ffecom_tree_blockdata_type);
8154 DECL_EXTERNAL (t) = 1;
8155 TREE_PUBLIC (t) = 1;
8157 t = start_decl (t, FALSE);
8158 finish_decl (t, NULL_TREE, FALSE);
8160 ffecom_save_tree_forever (t);
8162 break;
8164 case FFEINFO_whereCOMMON:
8165 case FFEINFO_whereDUMMY:
8166 case FFEINFO_whereRESULT:
8167 case FFEINFO_whereFLEETING:
8168 case FFEINFO_whereFLEETING_CADDR:
8169 case FFEINFO_whereFLEETING_IADDR:
8170 case FFEINFO_whereIMMEDIATE:
8171 case FFEINFO_whereINTRINSIC:
8172 case FFEINFO_whereCONSTANT:
8173 case FFEINFO_whereCONSTANT_SUBOBJECT:
8174 default:
8175 assert ("BLOCKDATA where unheard of" == NULL);
8176 /* Fall through. */
8177 case FFEINFO_whereANY:
8178 t = error_mark_node;
8179 break;
8181 break;
8183 case FFEINFO_kindCOMMON:
8184 switch (ffeinfo_where (ffesymbol_info (s)))
8186 case FFEINFO_whereLOCAL:
8187 assert (!ffecom_transform_only_dummies_);
8188 ffecom_transform_common_ (s);
8189 break;
8191 case FFEINFO_whereNONE:
8192 case FFEINFO_whereCOMMON:
8193 case FFEINFO_whereDUMMY:
8194 case FFEINFO_whereGLOBAL:
8195 case FFEINFO_whereRESULT:
8196 case FFEINFO_whereFLEETING:
8197 case FFEINFO_whereFLEETING_CADDR:
8198 case FFEINFO_whereFLEETING_IADDR:
8199 case FFEINFO_whereIMMEDIATE:
8200 case FFEINFO_whereINTRINSIC:
8201 case FFEINFO_whereCONSTANT:
8202 case FFEINFO_whereCONSTANT_SUBOBJECT:
8203 default:
8204 assert ("COMMON where unheard of" == NULL);
8205 /* Fall through. */
8206 case FFEINFO_whereANY:
8207 t = error_mark_node;
8208 break;
8210 break;
8212 case FFEINFO_kindCONSTRUCT:
8213 switch (ffeinfo_where (ffesymbol_info (s)))
8215 case FFEINFO_whereLOCAL:
8216 assert (!ffecom_transform_only_dummies_);
8217 break;
8219 case FFEINFO_whereNONE:
8220 case FFEINFO_whereCOMMON:
8221 case FFEINFO_whereDUMMY:
8222 case FFEINFO_whereGLOBAL:
8223 case FFEINFO_whereRESULT:
8224 case FFEINFO_whereFLEETING:
8225 case FFEINFO_whereFLEETING_CADDR:
8226 case FFEINFO_whereFLEETING_IADDR:
8227 case FFEINFO_whereIMMEDIATE:
8228 case FFEINFO_whereINTRINSIC:
8229 case FFEINFO_whereCONSTANT:
8230 case FFEINFO_whereCONSTANT_SUBOBJECT:
8231 default:
8232 assert ("CONSTRUCT where unheard of" == NULL);
8233 /* Fall through. */
8234 case FFEINFO_whereANY:
8235 t = error_mark_node;
8236 break;
8238 break;
8240 case FFEINFO_kindNAMELIST:
8241 switch (ffeinfo_where (ffesymbol_info (s)))
8243 case FFEINFO_whereLOCAL:
8244 assert (!ffecom_transform_only_dummies_);
8245 t = ffecom_transform_namelist_ (s);
8246 break;
8248 case FFEINFO_whereNONE:
8249 case FFEINFO_whereCOMMON:
8250 case FFEINFO_whereDUMMY:
8251 case FFEINFO_whereGLOBAL:
8252 case FFEINFO_whereRESULT:
8253 case FFEINFO_whereFLEETING:
8254 case FFEINFO_whereFLEETING_CADDR:
8255 case FFEINFO_whereFLEETING_IADDR:
8256 case FFEINFO_whereIMMEDIATE:
8257 case FFEINFO_whereINTRINSIC:
8258 case FFEINFO_whereCONSTANT:
8259 case FFEINFO_whereCONSTANT_SUBOBJECT:
8260 default:
8261 assert ("NAMELIST where unheard of" == NULL);
8262 /* Fall through. */
8263 case FFEINFO_whereANY:
8264 t = error_mark_node;
8265 break;
8267 break;
8269 default:
8270 assert ("kind unheard of" == NULL);
8271 /* Fall through. */
8272 case FFEINFO_kindANY:
8273 t = error_mark_node;
8274 break;
8277 ffesymbol_hook (s).decl_tree = t;
8278 ffesymbol_hook (s).length_tree = tlen;
8279 ffesymbol_hook (s).addr = addr;
8281 input_location = old_loc;
8283 return s;
8286 /* Transform into ASSIGNable symbol.
8288 Symbol has already been transformed, but for whatever reason, the
8289 resulting decl_tree has been deemed not usable for an ASSIGN target.
8290 (E.g. it isn't wide enough to hold a pointer.) So, here we invent
8291 another local symbol of type void * and stuff that in the assign_tree
8292 argument. The F77/F90 standards allow this implementation. */
8294 static ffesymbol
8295 ffecom_sym_transform_assign_ (ffesymbol s)
8297 tree t; /* Transformed thingy. */
8298 location_t old_loc = input_location;
8300 if (ffesymbol_sfdummyparent (s) == NULL)
8302 input_filename = ffesymbol_where_filename (s);
8303 input_line = ffesymbol_where_filelinenum (s);
8305 else
8307 ffesymbol sf = ffesymbol_sfdummyparent (s);
8309 input_filename = ffesymbol_where_filename (sf);
8310 input_line = ffesymbol_where_filelinenum (sf);
8313 assert (!ffecom_transform_only_dummies_);
8315 t = build_decl (VAR_DECL,
8316 ffecom_get_invented_identifier ("__g77_ASSIGN_%s",
8317 ffesymbol_text (s)),
8318 TREE_TYPE (null_pointer_node));
8320 switch (ffesymbol_where (s))
8322 case FFEINFO_whereLOCAL:
8323 /* Unlike for regular vars, SAVE status is easy to determine for
8324 ASSIGNed vars, since there's no initialization, there's no
8325 effective storage association (so "SAVE J" does not apply to
8326 K even given "EQUIVALENCE (J,K)"), there's no size issue
8327 to worry about, etc. */
8328 if ((ffesymbol_is_save (s) || ffe_is_saveall ())
8329 && (ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8330 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA))
8331 TREE_STATIC (t) = 1; /* SAVEd in proc, make static. */
8332 else
8333 TREE_STATIC (t) = 0; /* No need to make static. */
8334 break;
8336 case FFEINFO_whereCOMMON:
8337 TREE_STATIC (t) = 1; /* Assume COMMONs always SAVEd. */
8338 break;
8340 case FFEINFO_whereDUMMY:
8341 /* Note that twinning a DUMMY means the caller won't see
8342 the ASSIGNed value. But both F77 and F90 allow implementations
8343 to do this, i.e. disallow Fortran code that would try and
8344 take advantage of actually putting a label into a variable
8345 via a dummy argument (or any other storage association, for
8346 that matter). */
8347 TREE_STATIC (t) = 0;
8348 break;
8350 default:
8351 TREE_STATIC (t) = 0;
8352 break;
8355 t = start_decl (t, FALSE);
8356 finish_decl (t, NULL_TREE, FALSE);
8358 ffesymbol_hook (s).assign_tree = t;
8360 input_location = old_loc;
8362 return s;
8365 /* Implement COMMON area in back end.
8367 Because COMMON-based variables can be referenced in the dimension
8368 expressions of dummy (adjustable) arrays, and because dummies
8369 (in the gcc back end) need to be put in the outer binding level
8370 of a function (which has two binding levels, the outer holding
8371 the dummies and the inner holding the other vars), special care
8372 must be taken to handle COMMON areas.
8374 The current strategy is basically to always tell the back end about
8375 the COMMON area as a top-level external reference to just a block
8376 of storage of the master type of that area (e.g. integer, real,
8377 character, whatever -- not a structure). As a distinct action,
8378 if initial values are provided, tell the back end about the area
8379 as a top-level non-external (initialized) area and remember not to
8380 allow further initialization or expansion of the area. Meanwhile,
8381 if no initialization happens at all, tell the back end about
8382 the largest size we've seen declared so the space does get reserved.
8383 (This function doesn't handle all that stuff, but it does some
8384 of the important things.)
8386 Meanwhile, for COMMON variables themselves, just keep creating
8387 references like *((float *) (&common_area + offset)) each time
8388 we reference the variable. In other words, don't make a VAR_DECL
8389 or any kind of component reference (like we used to do before 0.4),
8390 though we might do that as well just for debugging purposes (and
8391 stuff the rtl with the appropriate offset expression). */
8393 static void
8394 ffecom_transform_common_ (ffesymbol s)
8396 ffestorag st = ffesymbol_storage (s);
8397 ffeglobal g = ffesymbol_global (s);
8398 tree cbt;
8399 tree cbtype;
8400 tree init;
8401 tree high;
8402 bool is_init = ffestorag_is_init (st);
8404 assert (st != NULL);
8406 if ((g == NULL)
8407 || (ffeglobal_type (g) != FFEGLOBAL_typeCOMMON))
8408 return;
8410 /* First update the size of the area in global terms. */
8412 ffeglobal_size_common (s, ffestorag_size (st));
8414 if (!ffeglobal_common_init (g))
8415 is_init = FALSE; /* No explicit init, don't let erroneous joins init. */
8417 cbt = ffeglobal_hook (g);
8419 /* If we already have declared this common block for a previous program
8420 unit, and either we already initialized it or we don't have new
8421 initialization for it, just return what we have without changing it. */
8423 if ((cbt != NULL_TREE)
8424 && (!is_init
8425 || !DECL_EXTERNAL (cbt)))
8427 if (st->hook == NULL) ffestorag_set_hook (st, cbt);
8428 return;
8431 /* Process inits. */
8433 if (is_init)
8435 if (ffestorag_init (st) != NULL)
8437 ffebld sexp;
8439 /* Set the padding for the expression, so ffecom_expr
8440 knows to insert that many zeros. */
8441 switch (ffebld_op (sexp = ffestorag_init (st)))
8443 case FFEBLD_opCONTER:
8444 ffebld_conter_set_pad (sexp, ffestorag_modulo (st));
8445 break;
8447 case FFEBLD_opARRTER:
8448 ffebld_arrter_set_pad (sexp, ffestorag_modulo (st));
8449 break;
8451 case FFEBLD_opACCTER:
8452 ffebld_accter_set_pad (sexp, ffestorag_modulo (st));
8453 break;
8455 default:
8456 assert ("bad op for cmn init (pad)" == NULL);
8457 break;
8460 init = ffecom_expr (sexp);
8461 if (init == error_mark_node)
8462 { /* Hopefully the back end complained! */
8463 init = NULL_TREE;
8464 if (cbt != NULL_TREE)
8465 return;
8468 else
8469 init = error_mark_node;
8471 else
8472 init = NULL_TREE;
8474 /* cbtype must be permanently allocated! */
8476 /* Allocate the MAX of the areas so far, seen filewide. */
8477 high = build_int_2 ((ffeglobal_common_size (g)
8478 + ffeglobal_common_pad (g)) - 1, 0);
8479 TREE_TYPE (high) = ffecom_integer_type_node;
8481 if (init)
8482 cbtype = build_array_type (char_type_node,
8483 build_range_type (integer_type_node,
8484 integer_zero_node,
8485 high));
8486 else
8487 cbtype = build_array_type (char_type_node, NULL_TREE);
8489 if (cbt == NULL_TREE)
8492 = build_decl (VAR_DECL,
8493 ffecom_get_external_identifier_ (s),
8494 cbtype);
8495 TREE_STATIC (cbt) = 1;
8496 TREE_PUBLIC (cbt) = 1;
8498 else
8500 assert (is_init);
8501 TREE_TYPE (cbt) = cbtype;
8503 DECL_EXTERNAL (cbt) = init ? 0 : 1;
8504 DECL_INITIAL (cbt) = init ? error_mark_node : NULL_TREE;
8506 cbt = start_decl (cbt, TRUE);
8507 if (ffeglobal_hook (g) != NULL)
8508 assert (cbt == ffeglobal_hook (g));
8510 assert (!init || !DECL_EXTERNAL (cbt));
8512 /* Make sure that any type can live in COMMON and be referenced
8513 without getting a bus error. We could pick the most restrictive
8514 alignment of all entities actually placed in the COMMON, but
8515 this seems easy enough. */
8517 DECL_ALIGN (cbt) = BIGGEST_ALIGNMENT;
8518 DECL_USER_ALIGN (cbt) = 0;
8520 if (is_init && (ffestorag_init (st) == NULL))
8521 init = ffecom_init_zero_ (cbt);
8523 finish_decl (cbt, init, TRUE);
8525 if (is_init)
8526 ffestorag_set_init (st, ffebld_new_any ());
8528 if (init)
8530 assert (DECL_SIZE_UNIT (cbt) != NULL_TREE);
8531 assert (TREE_CODE (DECL_SIZE_UNIT (cbt)) == INTEGER_CST);
8532 assert (0 == compare_tree_int (DECL_SIZE_UNIT (cbt),
8533 (ffeglobal_common_size (g)
8534 + ffeglobal_common_pad (g))));
8537 ffeglobal_set_hook (g, cbt);
8539 ffestorag_set_hook (st, cbt);
8541 ffecom_save_tree_forever (cbt);
8544 /* Make master area for local EQUIVALENCE. */
8546 static void
8547 ffecom_transform_equiv_ (ffestorag eqst)
8549 tree eqt;
8550 tree eqtype;
8551 tree init;
8552 tree high;
8553 bool is_init = ffestorag_is_init (eqst);
8555 assert (eqst != NULL);
8557 eqt = ffestorag_hook (eqst);
8559 if (eqt != NULL_TREE)
8560 return;
8562 /* Process inits. */
8564 if (is_init)
8566 if (ffestorag_init (eqst) != NULL)
8568 ffebld sexp;
8570 /* Set the padding for the expression, so ffecom_expr
8571 knows to insert that many zeros. */
8572 switch (ffebld_op (sexp = ffestorag_init (eqst)))
8574 case FFEBLD_opCONTER:
8575 ffebld_conter_set_pad (sexp, ffestorag_modulo (eqst));
8576 break;
8578 case FFEBLD_opARRTER:
8579 ffebld_arrter_set_pad (sexp, ffestorag_modulo (eqst));
8580 break;
8582 case FFEBLD_opACCTER:
8583 ffebld_accter_set_pad (sexp, ffestorag_modulo (eqst));
8584 break;
8586 default:
8587 assert ("bad op for eqv init (pad)" == NULL);
8588 break;
8591 init = ffecom_expr (sexp);
8592 if (init == error_mark_node)
8593 init = NULL_TREE; /* Hopefully the back end complained! */
8595 else
8596 init = error_mark_node;
8598 else if (ffe_is_init_local_zero ())
8599 init = error_mark_node;
8600 else
8601 init = NULL_TREE;
8603 ffecom_member_namelisted_ = FALSE;
8604 ffestorag_drive (ffestorag_list_equivs (eqst),
8605 &ffecom_member_phase1_,
8606 eqst);
8608 high = build_int_2 ((ffestorag_size (eqst)
8609 + ffestorag_modulo (eqst)) - 1, 0);
8610 TREE_TYPE (high) = ffecom_integer_type_node;
8612 eqtype = build_array_type (char_type_node,
8613 build_range_type (ffecom_integer_type_node,
8614 ffecom_integer_zero_node,
8615 high));
8617 eqt = build_decl (VAR_DECL,
8618 ffecom_get_invented_identifier ("__g77_equiv_%s",
8619 ffesymbol_text
8620 (ffestorag_symbol (eqst))),
8621 eqtype);
8622 DECL_EXTERNAL (eqt) = 0;
8623 if (is_init
8624 || ffecom_member_namelisted_
8625 #ifdef FFECOM_sizeMAXSTACKITEM
8626 || (ffestorag_size (eqst) > FFECOM_sizeMAXSTACKITEM)
8627 #endif
8628 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8629 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
8630 && (ffestorag_is_save (eqst) || ffe_is_saveall ())))
8631 TREE_STATIC (eqt) = 1;
8632 else
8633 TREE_STATIC (eqt) = 0;
8634 TREE_PUBLIC (eqt) = 0;
8635 TREE_ADDRESSABLE (eqt) = 1; /* Ensure non-register allocation */
8636 DECL_CONTEXT (eqt) = current_function_decl;
8637 if (init)
8638 DECL_INITIAL (eqt) = error_mark_node;
8639 else
8640 DECL_INITIAL (eqt) = NULL_TREE;
8642 eqt = start_decl (eqt, FALSE);
8644 /* Make sure that any type can live in EQUIVALENCE and be referenced
8645 without getting a bus error. We could pick the most restrictive
8646 alignment of all entities actually placed in the EQUIVALENCE, but
8647 this seems easy enough. */
8649 DECL_ALIGN (eqt) = BIGGEST_ALIGNMENT;
8650 DECL_USER_ALIGN (eqt) = 0;
8652 if ((!is_init && ffe_is_init_local_zero ())
8653 || (is_init && (ffestorag_init (eqst) == NULL)))
8654 init = ffecom_init_zero_ (eqt);
8656 finish_decl (eqt, init, FALSE);
8658 if (is_init)
8659 ffestorag_set_init (eqst, ffebld_new_any ());
8662 assert (TREE_CODE (DECL_SIZE_UNIT (eqt)) == INTEGER_CST);
8663 assert (0 == compare_tree_int (DECL_SIZE_UNIT (eqt),
8664 (ffestorag_size (eqst)
8665 + ffestorag_modulo (eqst))));
8668 ffestorag_set_hook (eqst, eqt);
8670 ffestorag_drive (ffestorag_list_equivs (eqst),
8671 &ffecom_member_phase2_,
8672 eqst);
8675 /* Implement NAMELIST in back end. See f2c/format.c for more info. */
8677 static tree
8678 ffecom_transform_namelist_ (ffesymbol s)
8680 tree nmlt;
8681 tree nmltype = ffecom_type_namelist_ ();
8682 tree nmlinits;
8683 tree nameinit;
8684 tree varsinit;
8685 tree nvarsinit;
8686 tree field;
8687 tree high;
8688 int i;
8689 static int mynumber = 0;
8691 nmlt = build_decl (VAR_DECL,
8692 ffecom_get_invented_identifier ("__g77_namelist_%d",
8693 mynumber++),
8694 nmltype);
8695 TREE_STATIC (nmlt) = 1;
8696 DECL_INITIAL (nmlt) = error_mark_node;
8698 nmlt = start_decl (nmlt, FALSE);
8700 /* Process inits. */
8702 i = strlen (ffesymbol_text (s));
8704 high = build_int_2 (i, 0);
8705 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
8707 nameinit = ffecom_build_f2c_string_ (i + 1,
8708 ffesymbol_text (s));
8709 TREE_TYPE (nameinit)
8710 = build_type_variant
8711 (build_array_type
8712 (char_type_node,
8713 build_range_type (ffecom_f2c_ftnlen_type_node,
8714 ffecom_f2c_ftnlen_one_node,
8715 high)),
8716 1, 0);
8717 TREE_CONSTANT (nameinit) = 1;
8718 TREE_STATIC (nameinit) = 1;
8719 nameinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (nameinit)),
8720 nameinit);
8722 varsinit = ffecom_vardesc_array_ (s);
8723 varsinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (varsinit)),
8724 varsinit);
8725 TREE_CONSTANT (varsinit) = 1;
8726 TREE_STATIC (varsinit) = 1;
8729 ffebld b;
8731 for (i = 0, b = ffesymbol_namelist (s); b != NULL; b = ffebld_trail (b))
8732 ++i;
8734 nvarsinit = build_int_2 (i, 0);
8735 TREE_TYPE (nvarsinit) = integer_type_node;
8736 TREE_CONSTANT (nvarsinit) = 1;
8737 TREE_STATIC (nvarsinit) = 1;
8739 nmlinits = build_tree_list ((field = TYPE_FIELDS (nmltype)), nameinit);
8740 TREE_CHAIN (nmlinits) = build_tree_list ((field = TREE_CHAIN (field)),
8741 varsinit);
8742 TREE_CHAIN (TREE_CHAIN (nmlinits))
8743 = build_tree_list ((field = TREE_CHAIN (field)), nvarsinit);
8745 nmlinits = build_constructor (nmltype, nmlinits);
8746 TREE_CONSTANT (nmlinits) = 1;
8747 TREE_STATIC (nmlinits) = 1;
8749 finish_decl (nmlt, nmlinits, FALSE);
8751 nmlt = ffecom_1 (ADDR_EXPR, build_pointer_type (nmltype), nmlt);
8753 return nmlt;
8756 /* A subroutine of ffecom_tree_canonize_ref_. The incoming tree is
8757 analyzed on the assumption it is calculating a pointer to be
8758 indirected through. It must return the proper decl and offset,
8759 taking into account different units of measurements for offsets. */
8761 static void
8762 ffecom_tree_canonize_ptr_ (tree *decl, tree *offset, tree t)
8764 switch (TREE_CODE (t))
8766 case NOP_EXPR:
8767 case CONVERT_EXPR:
8768 case NON_LVALUE_EXPR:
8769 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
8770 break;
8772 case PLUS_EXPR:
8773 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
8774 if ((*decl == NULL_TREE)
8775 || (*decl == error_mark_node))
8776 break;
8778 if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST)
8780 /* An offset into COMMON. */
8781 *offset = fold (build (PLUS_EXPR, TREE_TYPE (*offset),
8782 *offset, TREE_OPERAND (t, 1)));
8783 /* Convert offset (presumably in bytes) into canonical units
8784 (presumably bits). */
8785 *offset = size_binop (MULT_EXPR,
8786 convert (bitsizetype, *offset),
8787 TYPE_SIZE (TREE_TYPE (TREE_TYPE (t))));
8788 break;
8790 /* Not a COMMON reference, so an unrecognized pattern. */
8791 *decl = error_mark_node;
8792 break;
8794 case PARM_DECL:
8795 *decl = t;
8796 *offset = bitsize_zero_node;
8797 break;
8799 case ADDR_EXPR:
8800 if (TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL)
8802 /* A reference to COMMON. */
8803 *decl = TREE_OPERAND (t, 0);
8804 *offset = bitsize_zero_node;
8805 break;
8807 /* Fall through. */
8808 default:
8809 /* Not a COMMON reference, so an unrecognized pattern. */
8810 *decl = error_mark_node;
8811 break;
8815 /* Given a tree that is possibly intended for use as an lvalue, return
8816 information representing a canonical view of that tree as a decl, an
8817 offset into that decl, and a size for the lvalue.
8819 If there's no applicable decl, NULL_TREE is returned for the decl,
8820 and the other fields are left undefined.
8822 If the tree doesn't fit the recognizable forms, an ERROR_MARK node
8823 is returned for the decl, and the other fields are left undefined.
8825 Otherwise, the decl returned currently is either a VAR_DECL or a
8826 PARM_DECL.
8828 The offset returned is always valid, but of course not necessarily
8829 a constant, and not necessarily converted into the appropriate
8830 type, leaving that up to the caller (so as to avoid that overhead
8831 if the decls being looked at are different anyway).
8833 If the size cannot be determined (e.g. an adjustable array),
8834 an ERROR_MARK node is returned for the size. Otherwise, the
8835 size returned is valid, not necessarily a constant, and not
8836 necessarily converted into the appropriate type as with the
8837 offset.
8839 Note that the offset and size expressions are expressed in the
8840 base storage units (usually bits) rather than in the units of
8841 the type of the decl, because two decls with different types
8842 might overlap but with apparently non-overlapping array offsets,
8843 whereas converting the array offsets to consistant offsets will
8844 reveal the overlap. */
8846 static void
8847 ffecom_tree_canonize_ref_ (tree *decl, tree *offset, tree *size, tree t)
8849 /* The default path is to report a nonexistant decl. */
8850 *decl = NULL_TREE;
8852 if (t == NULL_TREE)
8853 return;
8855 switch (TREE_CODE (t))
8857 case ERROR_MARK:
8858 case IDENTIFIER_NODE:
8859 case INTEGER_CST:
8860 case REAL_CST:
8861 case COMPLEX_CST:
8862 case STRING_CST:
8863 case CONST_DECL:
8864 case PLUS_EXPR:
8865 case MINUS_EXPR:
8866 case MULT_EXPR:
8867 case TRUNC_DIV_EXPR:
8868 case CEIL_DIV_EXPR:
8869 case FLOOR_DIV_EXPR:
8870 case ROUND_DIV_EXPR:
8871 case TRUNC_MOD_EXPR:
8872 case CEIL_MOD_EXPR:
8873 case FLOOR_MOD_EXPR:
8874 case ROUND_MOD_EXPR:
8875 case RDIV_EXPR:
8876 case EXACT_DIV_EXPR:
8877 case FIX_TRUNC_EXPR:
8878 case FIX_CEIL_EXPR:
8879 case FIX_FLOOR_EXPR:
8880 case FIX_ROUND_EXPR:
8881 case FLOAT_EXPR:
8882 case NEGATE_EXPR:
8883 case MIN_EXPR:
8884 case MAX_EXPR:
8885 case ABS_EXPR:
8886 case LSHIFT_EXPR:
8887 case RSHIFT_EXPR:
8888 case LROTATE_EXPR:
8889 case RROTATE_EXPR:
8890 case BIT_IOR_EXPR:
8891 case BIT_XOR_EXPR:
8892 case BIT_AND_EXPR:
8893 case BIT_NOT_EXPR:
8894 case TRUTH_ANDIF_EXPR:
8895 case TRUTH_ORIF_EXPR:
8896 case TRUTH_AND_EXPR:
8897 case TRUTH_OR_EXPR:
8898 case TRUTH_XOR_EXPR:
8899 case TRUTH_NOT_EXPR:
8900 case LT_EXPR:
8901 case LE_EXPR:
8902 case GT_EXPR:
8903 case GE_EXPR:
8904 case EQ_EXPR:
8905 case NE_EXPR:
8906 case COMPLEX_EXPR:
8907 case CONJ_EXPR:
8908 case REALPART_EXPR:
8909 case IMAGPART_EXPR:
8910 case LABEL_EXPR:
8911 case COMPONENT_REF:
8912 case COMPOUND_EXPR:
8913 case ADDR_EXPR:
8914 return;
8916 case VAR_DECL:
8917 case PARM_DECL:
8918 *decl = t;
8919 *offset = bitsize_zero_node;
8920 *size = TYPE_SIZE (TREE_TYPE (t));
8921 return;
8923 case ARRAY_REF:
8925 tree array = TREE_OPERAND (t, 0);
8926 tree element = TREE_OPERAND (t, 1);
8927 tree init_offset;
8929 if ((array == NULL_TREE)
8930 || (element == NULL_TREE))
8932 *decl = error_mark_node;
8933 return;
8936 ffecom_tree_canonize_ref_ (decl, &init_offset, size,
8937 array);
8938 if ((*decl == NULL_TREE)
8939 || (*decl == error_mark_node))
8940 return;
8942 /* Calculate ((element - base) * NBBY) + init_offset. */
8943 *offset = fold (build (MINUS_EXPR, TREE_TYPE (element),
8944 element,
8945 TYPE_MIN_VALUE (TYPE_DOMAIN
8946 (TREE_TYPE (array)))));
8948 *offset = size_binop (MULT_EXPR,
8949 convert (bitsizetype, *offset),
8950 TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))));
8952 *offset = size_binop (PLUS_EXPR, init_offset, *offset);
8954 *size = TYPE_SIZE (TREE_TYPE (t));
8955 return;
8958 case INDIRECT_REF:
8960 /* Most of this code is to handle references to COMMON. And so
8961 far that is useful only for calling library functions, since
8962 external (user) functions might reference common areas. But
8963 even calling an external function, it's worthwhile to decode
8964 COMMON references because if not storing into COMMON, we don't
8965 want COMMON-based arguments to gratuitously force use of a
8966 temporary. */
8968 *size = TYPE_SIZE (TREE_TYPE (t));
8970 ffecom_tree_canonize_ptr_ (decl, offset,
8971 TREE_OPERAND (t, 0));
8973 return;
8975 case CONVERT_EXPR:
8976 case NOP_EXPR:
8977 case MODIFY_EXPR:
8978 case NON_LVALUE_EXPR:
8979 case RESULT_DECL:
8980 case FIELD_DECL:
8981 case COND_EXPR: /* More cases than we can handle. */
8982 case SAVE_EXPR:
8983 case REFERENCE_EXPR:
8984 case PREDECREMENT_EXPR:
8985 case PREINCREMENT_EXPR:
8986 case POSTDECREMENT_EXPR:
8987 case POSTINCREMENT_EXPR:
8988 case CALL_EXPR:
8989 default:
8990 *decl = error_mark_node;
8991 return;
8995 /* Do divide operation appropriate to type of operands. */
8997 static tree
8998 ffecom_tree_divide_ (tree tree_type, tree left, tree right, tree dest_tree,
8999 ffebld dest, bool *dest_used, tree hook)
9001 if ((left == error_mark_node)
9002 || (right == error_mark_node))
9003 return error_mark_node;
9005 switch (TREE_CODE (tree_type))
9007 case INTEGER_TYPE:
9008 return ffecom_2 (TRUNC_DIV_EXPR, tree_type,
9009 left,
9010 right);
9012 case COMPLEX_TYPE:
9013 if (! optimize_size)
9014 return ffecom_2 (RDIV_EXPR, tree_type,
9015 left,
9016 right);
9018 ffecomGfrt ix;
9020 if (TREE_TYPE (tree_type)
9021 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9022 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9023 else
9024 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
9026 left = ffecom_1 (ADDR_EXPR,
9027 build_pointer_type (TREE_TYPE (left)),
9028 left);
9029 left = build_tree_list (NULL_TREE, left);
9030 right = ffecom_1 (ADDR_EXPR,
9031 build_pointer_type (TREE_TYPE (right)),
9032 right);
9033 right = build_tree_list (NULL_TREE, right);
9034 TREE_CHAIN (left) = right;
9036 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9037 ffecom_gfrt_kindtype (ix),
9038 ffe_is_f2c_library (),
9039 tree_type,
9040 left,
9041 dest_tree, dest, dest_used,
9042 NULL_TREE, TRUE, hook);
9044 break;
9046 case RECORD_TYPE:
9048 ffecomGfrt ix;
9050 if (TREE_TYPE (TYPE_FIELDS (tree_type))
9051 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9052 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9053 else
9054 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
9056 left = ffecom_1 (ADDR_EXPR,
9057 build_pointer_type (TREE_TYPE (left)),
9058 left);
9059 left = build_tree_list (NULL_TREE, left);
9060 right = ffecom_1 (ADDR_EXPR,
9061 build_pointer_type (TREE_TYPE (right)),
9062 right);
9063 right = build_tree_list (NULL_TREE, right);
9064 TREE_CHAIN (left) = right;
9066 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9067 ffecom_gfrt_kindtype (ix),
9068 ffe_is_f2c_library (),
9069 tree_type,
9070 left,
9071 dest_tree, dest, dest_used,
9072 NULL_TREE, TRUE, hook);
9074 break;
9076 default:
9077 return ffecom_2 (RDIV_EXPR, tree_type,
9078 left,
9079 right);
9083 /* Build type info for non-dummy variable. */
9085 static tree
9086 ffecom_type_localvar_ (ffesymbol s, ffeinfoBasictype bt, ffeinfoKindtype kt)
9088 tree type;
9089 ffebld dl;
9090 ffebld dim;
9091 tree lowt;
9092 tree hight;
9094 type = ffecom_tree_type[bt][kt];
9095 if (bt == FFEINFO_basictypeCHARACTER)
9097 hight = build_int_2 (ffesymbol_size (s), 0);
9098 TREE_TYPE (hight) = ffecom_f2c_ftnlen_type_node;
9100 type
9101 = build_array_type
9102 (type,
9103 build_range_type (ffecom_f2c_ftnlen_type_node,
9104 ffecom_f2c_ftnlen_one_node,
9105 hight));
9106 type = ffecom_check_size_overflow_ (s, type, FALSE);
9109 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
9111 if (type == error_mark_node)
9112 break;
9114 dim = ffebld_head (dl);
9115 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
9117 if (ffebld_left (dim) == NULL)
9118 lowt = integer_one_node;
9119 else
9120 lowt = ffecom_expr (ffebld_left (dim));
9122 if (TREE_CODE (lowt) != INTEGER_CST)
9123 lowt = variable_size (lowt);
9125 assert (ffebld_right (dim) != NULL);
9126 hight = ffecom_expr (ffebld_right (dim));
9128 if (TREE_CODE (hight) != INTEGER_CST)
9129 hight = variable_size (hight);
9131 type = build_array_type (type,
9132 build_range_type (ffecom_integer_type_node,
9133 lowt, hight));
9134 type = ffecom_check_size_overflow_ (s, type, FALSE);
9137 return type;
9140 /* Build Namelist type. */
9142 static GTY(()) tree ffecom_type_namelist_var;
9143 static tree
9144 ffecom_type_namelist_ (void)
9146 if (ffecom_type_namelist_var == NULL_TREE)
9148 tree namefield, varsfield, nvarsfield, vardesctype, type;
9150 vardesctype = ffecom_type_vardesc_ ();
9152 type = make_node (RECORD_TYPE);
9154 vardesctype = build_pointer_type (build_pointer_type (vardesctype));
9156 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9157 string_type_node);
9158 varsfield = ffecom_decl_field (type, namefield, "vars", vardesctype);
9159 nvarsfield = ffecom_decl_field (type, varsfield, "nvars",
9160 integer_type_node);
9162 TYPE_FIELDS (type) = namefield;
9163 layout_type (type);
9165 ffecom_type_namelist_var = type;
9168 return ffecom_type_namelist_var;
9171 /* Build Vardesc type. */
9173 static GTY(()) tree ffecom_type_vardesc_var;
9174 static tree
9175 ffecom_type_vardesc_ (void)
9177 if (ffecom_type_vardesc_var == NULL_TREE)
9179 tree namefield, addrfield, dimsfield, typefield, type;
9180 type = make_node (RECORD_TYPE);
9182 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9183 string_type_node);
9184 addrfield = ffecom_decl_field (type, namefield, "addr",
9185 string_type_node);
9186 dimsfield = ffecom_decl_field (type, addrfield, "dims",
9187 ffecom_f2c_ptr_to_ftnlen_type_node);
9188 typefield = ffecom_decl_field (type, dimsfield, "type",
9189 integer_type_node);
9191 TYPE_FIELDS (type) = namefield;
9192 layout_type (type);
9194 ffecom_type_vardesc_var = type;
9197 return ffecom_type_vardesc_var;
9200 static tree
9201 ffecom_vardesc_ (ffebld expr)
9203 ffesymbol s;
9205 assert (ffebld_op (expr) == FFEBLD_opSYMTER);
9206 s = ffebld_symter (expr);
9208 if (ffesymbol_hook (s).vardesc_tree == NULL_TREE)
9210 int i;
9211 tree vardesctype = ffecom_type_vardesc_ ();
9212 tree var;
9213 tree nameinit;
9214 tree dimsinit;
9215 tree addrinit;
9216 tree typeinit;
9217 tree field;
9218 tree varinits;
9219 static int mynumber = 0;
9221 var = build_decl (VAR_DECL,
9222 ffecom_get_invented_identifier ("__g77_vardesc_%d",
9223 mynumber++),
9224 vardesctype);
9225 TREE_STATIC (var) = 1;
9226 DECL_INITIAL (var) = error_mark_node;
9228 var = start_decl (var, FALSE);
9230 /* Process inits. */
9232 nameinit = ffecom_build_f2c_string_ ((i = strlen (ffesymbol_text (s)))
9233 + 1,
9234 ffesymbol_text (s));
9235 TREE_TYPE (nameinit)
9236 = build_type_variant
9237 (build_array_type
9238 (char_type_node,
9239 build_range_type (integer_type_node,
9240 integer_one_node,
9241 build_int_2 (i, 0))),
9242 1, 0);
9243 TREE_CONSTANT (nameinit) = 1;
9244 TREE_STATIC (nameinit) = 1;
9245 nameinit = ffecom_1 (ADDR_EXPR,
9246 build_pointer_type (TREE_TYPE (nameinit)),
9247 nameinit);
9249 addrinit = ffecom_arg_ptr_to_expr (expr, &typeinit);
9251 dimsinit = ffecom_vardesc_dims_ (s);
9253 if (typeinit == NULL_TREE)
9255 ffeinfoBasictype bt = ffesymbol_basictype (s);
9256 ffeinfoKindtype kt = ffesymbol_kindtype (s);
9257 int tc = ffecom_f2c_typecode (bt, kt);
9259 assert (tc != -1);
9260 typeinit = build_int_2 (tc, (tc < 0) ? -1 : 0);
9262 else
9263 typeinit = ffecom_1 (NEGATE_EXPR, TREE_TYPE (typeinit), typeinit);
9265 varinits = build_tree_list ((field = TYPE_FIELDS (vardesctype)),
9266 nameinit);
9267 TREE_CHAIN (varinits) = build_tree_list ((field = TREE_CHAIN (field)),
9268 addrinit);
9269 TREE_CHAIN (TREE_CHAIN (varinits))
9270 = build_tree_list ((field = TREE_CHAIN (field)), dimsinit);
9271 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (varinits)))
9272 = build_tree_list ((field = TREE_CHAIN (field)), typeinit);
9274 varinits = build_constructor (vardesctype, varinits);
9275 TREE_CONSTANT (varinits) = 1;
9276 TREE_STATIC (varinits) = 1;
9278 finish_decl (var, varinits, FALSE);
9280 var = ffecom_1 (ADDR_EXPR, build_pointer_type (vardesctype), var);
9282 ffesymbol_hook (s).vardesc_tree = var;
9285 return ffesymbol_hook (s).vardesc_tree;
9288 static tree
9289 ffecom_vardesc_array_ (ffesymbol s)
9291 ffebld b;
9292 tree list;
9293 tree item = NULL_TREE;
9294 tree var;
9295 int i;
9296 static int mynumber = 0;
9298 for (i = 0, list = NULL_TREE, b = ffesymbol_namelist (s);
9299 b != NULL;
9300 b = ffebld_trail (b), ++i)
9302 tree t;
9304 t = ffecom_vardesc_ (ffebld_head (b));
9306 if (list == NULL_TREE)
9307 list = item = build_tree_list (NULL_TREE, t);
9308 else
9310 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9311 item = TREE_CHAIN (item);
9315 item = build_array_type (build_pointer_type (ffecom_type_vardesc_ ()),
9316 build_range_type (integer_type_node,
9317 integer_one_node,
9318 build_int_2 (i, 0)));
9319 list = build_constructor (item, list);
9320 TREE_CONSTANT (list) = 1;
9321 TREE_STATIC (list) = 1;
9323 var = ffecom_get_invented_identifier ("__g77_vardesc_array_%d", mynumber++);
9324 var = build_decl (VAR_DECL, var, item);
9325 TREE_STATIC (var) = 1;
9326 DECL_INITIAL (var) = error_mark_node;
9327 var = start_decl (var, FALSE);
9328 finish_decl (var, list, FALSE);
9330 return var;
9333 static tree
9334 ffecom_vardesc_dims_ (ffesymbol s)
9336 if (ffesymbol_dims (s) == NULL)
9337 return convert (ffecom_f2c_ptr_to_ftnlen_type_node,
9338 integer_zero_node);
9341 ffebld b;
9342 ffebld e;
9343 tree list;
9344 tree backlist;
9345 tree item = NULL_TREE;
9346 tree var;
9347 tree numdim;
9348 tree numelem;
9349 tree baseoff = NULL_TREE;
9350 static int mynumber = 0;
9352 numdim = build_int_2 ((int) ffesymbol_rank (s), 0);
9353 TREE_TYPE (numdim) = ffecom_f2c_ftnlen_type_node;
9355 numelem = ffecom_expr (ffesymbol_arraysize (s));
9356 TREE_TYPE (numelem) = ffecom_f2c_ftnlen_type_node;
9358 list = NULL_TREE;
9359 backlist = NULL_TREE;
9360 for (b = ffesymbol_dims (s), e = ffesymbol_extents (s);
9361 b != NULL;
9362 b = ffebld_trail (b), e = ffebld_trail (e))
9364 tree t;
9365 tree low;
9366 tree back;
9368 if (ffebld_trail (b) == NULL)
9369 t = NULL_TREE;
9370 else
9372 t = convert (ffecom_f2c_ftnlen_type_node,
9373 ffecom_expr (ffebld_head (e)));
9375 if (list == NULL_TREE)
9376 list = item = build_tree_list (NULL_TREE, t);
9377 else
9379 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9380 item = TREE_CHAIN (item);
9384 if (ffebld_left (ffebld_head (b)) == NULL)
9385 low = ffecom_integer_one_node;
9386 else
9387 low = ffecom_expr (ffebld_left (ffebld_head (b)));
9388 low = convert (ffecom_f2c_ftnlen_type_node, low);
9390 back = build_tree_list (low, t);
9391 TREE_CHAIN (back) = backlist;
9392 backlist = back;
9395 for (item = backlist; item != NULL_TREE; item = TREE_CHAIN (item))
9397 if (TREE_VALUE (item) == NULL_TREE)
9398 baseoff = TREE_PURPOSE (item);
9399 else
9400 baseoff = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
9401 TREE_PURPOSE (item),
9402 ffecom_2 (MULT_EXPR,
9403 ffecom_f2c_ftnlen_type_node,
9404 TREE_VALUE (item),
9405 baseoff));
9408 /* backlist now dead, along with all TREE_PURPOSEs on it. */
9410 baseoff = build_tree_list (NULL_TREE, baseoff);
9411 TREE_CHAIN (baseoff) = list;
9413 numelem = build_tree_list (NULL_TREE, numelem);
9414 TREE_CHAIN (numelem) = baseoff;
9416 numdim = build_tree_list (NULL_TREE, numdim);
9417 TREE_CHAIN (numdim) = numelem;
9419 item = build_array_type (ffecom_f2c_ftnlen_type_node,
9420 build_range_type (integer_type_node,
9421 integer_zero_node,
9422 build_int_2
9423 ((int) ffesymbol_rank (s)
9424 + 2, 0)));
9425 list = build_constructor (item, numdim);
9426 TREE_CONSTANT (list) = 1;
9427 TREE_STATIC (list) = 1;
9429 var = ffecom_get_invented_identifier ("__g77_dims_%d", mynumber++);
9430 var = build_decl (VAR_DECL, var, item);
9431 TREE_STATIC (var) = 1;
9432 DECL_INITIAL (var) = error_mark_node;
9433 var = start_decl (var, FALSE);
9434 finish_decl (var, list, FALSE);
9436 var = ffecom_1 (ADDR_EXPR, build_pointer_type (item), var);
9438 return var;
9442 /* Essentially does a "fold (build1 (code, type, node))" while checking
9443 for certain housekeeping things.
9445 NOTE: for building an ADDR_EXPR around a FUNCTION_DECL, use
9446 ffecom_1_fn instead. */
9448 tree
9449 ffecom_1 (enum tree_code code, tree type, tree node)
9451 tree item;
9453 if ((node == error_mark_node)
9454 || (type == error_mark_node))
9455 return error_mark_node;
9457 if (code == ADDR_EXPR)
9459 if (!ffe_mark_addressable (node))
9460 assert ("can't mark_addressable this node!" == NULL);
9463 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
9465 tree realtype;
9467 case REALPART_EXPR:
9468 item = build (COMPONENT_REF, type, node, TYPE_FIELDS (TREE_TYPE (node)));
9469 break;
9471 case IMAGPART_EXPR:
9472 item = build (COMPONENT_REF, type, node, TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (node))));
9473 break;
9476 case NEGATE_EXPR:
9477 if (TREE_CODE (type) != RECORD_TYPE)
9479 item = build1 (code, type, node);
9480 break;
9482 node = ffecom_stabilize_aggregate_ (node);
9483 realtype = TREE_TYPE (TYPE_FIELDS (type));
9484 item =
9485 ffecom_2 (COMPLEX_EXPR, type,
9486 ffecom_1 (NEGATE_EXPR, realtype,
9487 ffecom_1 (REALPART_EXPR, realtype,
9488 node)),
9489 ffecom_1 (NEGATE_EXPR, realtype,
9490 ffecom_1 (IMAGPART_EXPR, realtype,
9491 node)));
9492 break;
9494 default:
9495 item = build1 (code, type, node);
9496 break;
9499 if (TREE_SIDE_EFFECTS (node))
9500 TREE_SIDE_EFFECTS (item) = 1;
9501 if (code == ADDR_EXPR && staticp (node))
9502 TREE_CONSTANT (item) = 1;
9503 else if (code == INDIRECT_REF)
9504 TREE_READONLY (item) = TYPE_READONLY (type);
9505 return fold (item);
9508 /* Like ffecom_1 (ADDR_EXPR, TREE_TYPE (node), node), except
9509 handles TREE_CODE (node) == FUNCTION_DECL. In particular,
9510 does not set TREE_ADDRESSABLE (because calling an inline
9511 function does not mean the function needs to be separately
9512 compiled). */
9514 tree
9515 ffecom_1_fn (tree node)
9517 tree item;
9518 tree type;
9520 if (node == error_mark_node)
9521 return error_mark_node;
9523 type = build_type_variant (TREE_TYPE (node),
9524 TREE_READONLY (node),
9525 TREE_THIS_VOLATILE (node));
9526 item = build1 (ADDR_EXPR,
9527 build_pointer_type (type), node);
9528 if (TREE_SIDE_EFFECTS (node))
9529 TREE_SIDE_EFFECTS (item) = 1;
9530 if (staticp (node))
9531 TREE_CONSTANT (item) = 1;
9532 return fold (item);
9535 /* Essentially does a "fold (build (code, type, node1, node2))" while
9536 checking for certain housekeeping things. */
9538 tree
9539 ffecom_2 (enum tree_code code, tree type, tree node1, tree node2)
9541 tree item;
9543 if ((node1 == error_mark_node)
9544 || (node2 == error_mark_node)
9545 || (type == error_mark_node))
9546 return error_mark_node;
9548 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
9550 tree a, b, c, d, realtype;
9552 case CONJ_EXPR:
9553 assert ("no CONJ_EXPR support yet" == NULL);
9554 return error_mark_node;
9556 case COMPLEX_EXPR:
9557 item = build_tree_list (TYPE_FIELDS (type), node1);
9558 TREE_CHAIN (item) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), node2);
9559 item = build_constructor (type, item);
9560 break;
9562 case PLUS_EXPR:
9563 if (TREE_CODE (type) != RECORD_TYPE)
9565 item = build (code, type, node1, node2);
9566 break;
9568 node1 = ffecom_stabilize_aggregate_ (node1);
9569 node2 = ffecom_stabilize_aggregate_ (node2);
9570 realtype = TREE_TYPE (TYPE_FIELDS (type));
9571 item =
9572 ffecom_2 (COMPLEX_EXPR, type,
9573 ffecom_2 (PLUS_EXPR, realtype,
9574 ffecom_1 (REALPART_EXPR, realtype,
9575 node1),
9576 ffecom_1 (REALPART_EXPR, realtype,
9577 node2)),
9578 ffecom_2 (PLUS_EXPR, realtype,
9579 ffecom_1 (IMAGPART_EXPR, realtype,
9580 node1),
9581 ffecom_1 (IMAGPART_EXPR, realtype,
9582 node2)));
9583 break;
9585 case MINUS_EXPR:
9586 if (TREE_CODE (type) != RECORD_TYPE)
9588 item = build (code, type, node1, node2);
9589 break;
9591 node1 = ffecom_stabilize_aggregate_ (node1);
9592 node2 = ffecom_stabilize_aggregate_ (node2);
9593 realtype = TREE_TYPE (TYPE_FIELDS (type));
9594 item =
9595 ffecom_2 (COMPLEX_EXPR, type,
9596 ffecom_2 (MINUS_EXPR, realtype,
9597 ffecom_1 (REALPART_EXPR, realtype,
9598 node1),
9599 ffecom_1 (REALPART_EXPR, realtype,
9600 node2)),
9601 ffecom_2 (MINUS_EXPR, realtype,
9602 ffecom_1 (IMAGPART_EXPR, realtype,
9603 node1),
9604 ffecom_1 (IMAGPART_EXPR, realtype,
9605 node2)));
9606 break;
9608 case MULT_EXPR:
9609 if (TREE_CODE (type) != RECORD_TYPE)
9611 item = build (code, type, node1, node2);
9612 break;
9614 node1 = ffecom_stabilize_aggregate_ (node1);
9615 node2 = ffecom_stabilize_aggregate_ (node2);
9616 realtype = TREE_TYPE (TYPE_FIELDS (type));
9617 a = save_expr (ffecom_1 (REALPART_EXPR, realtype,
9618 node1));
9619 b = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
9620 node1));
9621 c = save_expr (ffecom_1 (REALPART_EXPR, realtype,
9622 node2));
9623 d = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
9624 node2));
9625 item =
9626 ffecom_2 (COMPLEX_EXPR, type,
9627 ffecom_2 (MINUS_EXPR, realtype,
9628 ffecom_2 (MULT_EXPR, realtype,
9631 ffecom_2 (MULT_EXPR, realtype,
9633 d)),
9634 ffecom_2 (PLUS_EXPR, realtype,
9635 ffecom_2 (MULT_EXPR, realtype,
9638 ffecom_2 (MULT_EXPR, realtype,
9640 b)));
9641 break;
9643 case EQ_EXPR:
9644 if ((TREE_CODE (node1) != RECORD_TYPE)
9645 && (TREE_CODE (node2) != RECORD_TYPE))
9647 item = build (code, type, node1, node2);
9648 break;
9650 assert (TREE_CODE (node1) == RECORD_TYPE);
9651 assert (TREE_CODE (node2) == RECORD_TYPE);
9652 node1 = ffecom_stabilize_aggregate_ (node1);
9653 node2 = ffecom_stabilize_aggregate_ (node2);
9654 realtype = TREE_TYPE (TYPE_FIELDS (type));
9655 item =
9656 ffecom_2 (TRUTH_ANDIF_EXPR, type,
9657 ffecom_2 (code, type,
9658 ffecom_1 (REALPART_EXPR, realtype,
9659 node1),
9660 ffecom_1 (REALPART_EXPR, realtype,
9661 node2)),
9662 ffecom_2 (code, type,
9663 ffecom_1 (IMAGPART_EXPR, realtype,
9664 node1),
9665 ffecom_1 (IMAGPART_EXPR, realtype,
9666 node2)));
9667 break;
9669 case NE_EXPR:
9670 if ((TREE_CODE (node1) != RECORD_TYPE)
9671 && (TREE_CODE (node2) != RECORD_TYPE))
9673 item = build (code, type, node1, node2);
9674 break;
9676 assert (TREE_CODE (node1) == RECORD_TYPE);
9677 assert (TREE_CODE (node2) == RECORD_TYPE);
9678 node1 = ffecom_stabilize_aggregate_ (node1);
9679 node2 = ffecom_stabilize_aggregate_ (node2);
9680 realtype = TREE_TYPE (TYPE_FIELDS (type));
9681 item =
9682 ffecom_2 (TRUTH_ORIF_EXPR, type,
9683 ffecom_2 (code, type,
9684 ffecom_1 (REALPART_EXPR, realtype,
9685 node1),
9686 ffecom_1 (REALPART_EXPR, realtype,
9687 node2)),
9688 ffecom_2 (code, type,
9689 ffecom_1 (IMAGPART_EXPR, realtype,
9690 node1),
9691 ffecom_1 (IMAGPART_EXPR, realtype,
9692 node2)));
9693 break;
9695 default:
9696 item = build (code, type, node1, node2);
9697 break;
9700 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2))
9701 TREE_SIDE_EFFECTS (item) = 1;
9702 return fold (item);
9705 /* ffecom_2pass_advise_entrypoint -- Advise that there's this entrypoint
9707 ffesymbol s; // the ENTRY point itself
9708 if (ffecom_2pass_advise_entrypoint(s))
9709 // the ENTRY point has been accepted
9711 Does whatever compiler needs to do when it learns about the entrypoint,
9712 like determine the return type of the master function, count the
9713 number of entrypoints, etc. Returns FALSE if the return type is
9714 not compatible with the return type(s) of other entrypoint(s).
9716 NOTE: for every call to this fn that returns TRUE, _do_entrypoint must
9717 later (after _finish_progunit) be called with the same entrypoint(s)
9718 as passed to this fn for which TRUE was returned.
9720 03-Jan-92 JCB 2.0
9721 Return FALSE if the return type conflicts with previous entrypoints. */
9723 bool
9724 ffecom_2pass_advise_entrypoint (ffesymbol entry)
9726 ffebld list; /* opITEM. */
9727 ffebld mlist; /* opITEM. */
9728 ffebld plist; /* opITEM. */
9729 ffebld arg; /* ffebld_head(opITEM). */
9730 ffebld item; /* opITEM. */
9731 ffesymbol s; /* ffebld_symter(arg). */
9732 ffeinfoBasictype bt = ffesymbol_basictype (entry);
9733 ffeinfoKindtype kt = ffesymbol_kindtype (entry);
9734 ffetargetCharacterSize size = ffesymbol_size (entry);
9735 bool ok;
9737 if (ffecom_num_entrypoints_ == 0)
9738 { /* First entrypoint, make list of main
9739 arglist's dummies. */
9740 assert (ffecom_primary_entry_ != NULL);
9742 ffecom_master_bt_ = ffesymbol_basictype (ffecom_primary_entry_);
9743 ffecom_master_kt_ = ffesymbol_kindtype (ffecom_primary_entry_);
9744 ffecom_master_size_ = ffesymbol_size (ffecom_primary_entry_);
9746 for (plist = NULL, list = ffesymbol_dummyargs (ffecom_primary_entry_);
9747 list != NULL;
9748 list = ffebld_trail (list))
9750 arg = ffebld_head (list);
9751 if (ffebld_op (arg) != FFEBLD_opSYMTER)
9752 continue; /* Alternate return or some such thing. */
9753 item = ffebld_new_item (arg, NULL);
9754 if (plist == NULL)
9755 ffecom_master_arglist_ = item;
9756 else
9757 ffebld_set_trail (plist, item);
9758 plist = item;
9762 /* If necessary, scan entry arglist for alternate returns. Do this scan
9763 apparently redundantly (it's done below to UNIONize the arglists) so
9764 that we don't complain about RETURN 1 if an offending ENTRY is the only
9765 one with an alternate return. */
9767 if (!ffecom_is_altreturning_)
9769 for (list = ffesymbol_dummyargs (entry);
9770 list != NULL;
9771 list = ffebld_trail (list))
9773 arg = ffebld_head (list);
9774 if (ffebld_op (arg) == FFEBLD_opSTAR)
9776 ffecom_is_altreturning_ = TRUE;
9777 break;
9782 /* Now check type compatibility. */
9784 switch (ffecom_master_bt_)
9786 case FFEINFO_basictypeNONE:
9787 ok = (bt != FFEINFO_basictypeCHARACTER);
9788 break;
9790 case FFEINFO_basictypeCHARACTER:
9792 = (bt == FFEINFO_basictypeCHARACTER)
9793 && (kt == ffecom_master_kt_)
9794 && (size == ffecom_master_size_);
9795 break;
9797 case FFEINFO_basictypeANY:
9798 return FALSE; /* Just don't bother. */
9800 default:
9801 if (bt == FFEINFO_basictypeCHARACTER)
9803 ok = FALSE;
9804 break;
9806 ok = TRUE;
9807 if ((bt != ffecom_master_bt_) || (kt != ffecom_master_kt_))
9809 ffecom_master_bt_ = FFEINFO_basictypeNONE;
9810 ffecom_master_kt_ = FFEINFO_kindtypeNONE;
9812 break;
9815 if (!ok)
9817 ffebad_start (FFEBAD_ENTRY_CONFLICTS);
9818 ffest_ffebad_here_current_stmt (0);
9819 ffebad_finish ();
9820 return FALSE; /* Can't handle entrypoint. */
9823 /* Entrypoint type compatible with previous types. */
9825 ++ffecom_num_entrypoints_;
9827 /* Master-arg-list = UNION(Master-arg-list,entry-arg-list). */
9829 for (list = ffesymbol_dummyargs (entry);
9830 list != NULL;
9831 list = ffebld_trail (list))
9833 arg = ffebld_head (list);
9834 if (ffebld_op (arg) != FFEBLD_opSYMTER)
9835 continue; /* Alternate return or some such thing. */
9836 s = ffebld_symter (arg);
9837 for (plist = NULL, mlist = ffecom_master_arglist_;
9838 mlist != NULL;
9839 plist = mlist, mlist = ffebld_trail (mlist))
9840 { /* plist points to previous item for easy
9841 appending of arg. */
9842 if (ffebld_symter (ffebld_head (mlist)) == s)
9843 break; /* Already have this arg in the master list. */
9845 if (mlist != NULL)
9846 continue; /* Already have this arg in the master list. */
9848 /* Append this arg to the master list. */
9850 item = ffebld_new_item (arg, NULL);
9851 if (plist == NULL)
9852 ffecom_master_arglist_ = item;
9853 else
9854 ffebld_set_trail (plist, item);
9857 return TRUE;
9860 /* ffecom_2pass_do_entrypoint -- Do compilation of entrypoint
9862 ffesymbol s; // the ENTRY point itself
9863 ffecom_2pass_do_entrypoint(s);
9865 Does whatever compiler needs to do to make the entrypoint actually
9866 happen. Must be called for each entrypoint after
9867 ffecom_finish_progunit is called. */
9869 void
9870 ffecom_2pass_do_entrypoint (ffesymbol entry)
9872 static int mfn_num = 0;
9873 static int ent_num;
9875 if (mfn_num != ffecom_num_fns_)
9876 { /* First entrypoint for this program unit. */
9877 ent_num = 1;
9878 mfn_num = ffecom_num_fns_;
9879 ffecom_do_entry_ (ffecom_primary_entry_, 0);
9881 else
9882 ++ent_num;
9884 --ffecom_num_entrypoints_;
9886 ffecom_do_entry_ (entry, ent_num);
9889 /* Essentially does a "fold (build (code, type, node1, node2))" while
9890 checking for certain housekeeping things. Always sets
9891 TREE_SIDE_EFFECTS. */
9893 tree
9894 ffecom_2s (enum tree_code code, tree type, tree node1, tree node2)
9896 tree item;
9898 if ((node1 == error_mark_node)
9899 || (node2 == error_mark_node)
9900 || (type == error_mark_node))
9901 return error_mark_node;
9903 item = build (code, type, node1, node2);
9904 TREE_SIDE_EFFECTS (item) = 1;
9905 return fold (item);
9908 /* Essentially does a "fold (build (code, type, node1, node2, node3))" while
9909 checking for certain housekeeping things. */
9911 tree
9912 ffecom_3 (enum tree_code code, tree type, tree node1, tree node2, tree node3)
9914 tree item;
9916 if ((node1 == error_mark_node)
9917 || (node2 == error_mark_node)
9918 || (node3 == error_mark_node)
9919 || (type == error_mark_node))
9920 return error_mark_node;
9922 item = build (code, type, node1, node2, node3);
9923 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2)
9924 || (node3 != NULL_TREE && TREE_SIDE_EFFECTS (node3)))
9925 TREE_SIDE_EFFECTS (item) = 1;
9926 return fold (item);
9929 /* Essentially does a "fold (build (code, type, node1, node2, node3))" while
9930 checking for certain housekeeping things. Always sets
9931 TREE_SIDE_EFFECTS. */
9933 tree
9934 ffecom_3s (enum tree_code code, tree type, tree node1, tree node2, tree node3)
9936 tree item;
9938 if ((node1 == error_mark_node)
9939 || (node2 == error_mark_node)
9940 || (node3 == error_mark_node)
9941 || (type == error_mark_node))
9942 return error_mark_node;
9944 item = build (code, type, node1, node2, node3);
9945 TREE_SIDE_EFFECTS (item) = 1;
9946 return fold (item);
9949 /* ffecom_arg_expr -- Transform argument expr into gcc tree
9951 See use by ffecom_list_expr.
9953 If expression is NULL, returns an integer zero tree. If it is not
9954 a CHARACTER expression, returns whatever ffecom_expr
9955 returns and sets the length return value to NULL_TREE. Otherwise
9956 generates code to evaluate the character expression, returns the proper
9957 pointer to the result, but does NOT set the length return value to a tree
9958 that specifies the length of the result. (In other words, the length
9959 variable is always set to NULL_TREE, because a length is never passed.)
9961 21-Dec-91 JCB 1.1
9962 Don't set returned length, since nobody needs it (yet; someday if
9963 we allow CHARACTER*(*) dummies to statement functions, we'll need
9964 it). */
9966 tree
9967 ffecom_arg_expr (ffebld expr, tree *length)
9969 tree ign;
9971 *length = NULL_TREE;
9973 if (expr == NULL)
9974 return integer_zero_node;
9976 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
9977 return ffecom_expr (expr);
9979 return ffecom_arg_ptr_to_expr (expr, &ign);
9982 /* Transform expression into constant argument-pointer-to-expression tree.
9984 If the expression can be transformed into a argument-pointer-to-expression
9985 tree that is constant, that is done, and the tree returned. Else
9986 NULL_TREE is returned.
9988 That way, a caller can attempt to provide compile-time initialization
9989 of a variable and, if that fails, *then* choose to start a new block
9990 and resort to using temporaries, as appropriate. */
9992 tree
9993 ffecom_arg_ptr_to_const_expr (ffebld expr, tree *length)
9995 if (! expr)
9996 return integer_zero_node;
9998 if (ffebld_op (expr) == FFEBLD_opANY)
10000 if (length)
10001 *length = error_mark_node;
10002 return error_mark_node;
10005 if (ffebld_arity (expr) == 0
10006 && (ffebld_op (expr) != FFEBLD_opSYMTER
10007 || ffebld_where (expr) == FFEINFO_whereCOMMON
10008 || ffebld_where (expr) == FFEINFO_whereGLOBAL
10009 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
10011 tree t;
10013 t = ffecom_arg_ptr_to_expr (expr, length);
10014 assert (TREE_CONSTANT (t));
10015 assert (! length || TREE_CONSTANT (*length));
10016 return t;
10019 if (length
10020 && ffebld_size (expr) != FFETARGET_charactersizeNONE)
10021 *length = build_int_2 (ffebld_size (expr), 0);
10022 else if (length)
10023 *length = NULL_TREE;
10024 return NULL_TREE;
10027 /* ffecom_arg_ptr_to_expr -- Transform argument expr into gcc tree
10029 See use by ffecom_list_ptr_to_expr.
10031 If expression is NULL, returns an integer zero tree. If it is not
10032 a CHARACTER expression, returns whatever ffecom_ptr_to_expr
10033 returns and sets the length return value to NULL_TREE. Otherwise
10034 generates code to evaluate the character expression, returns the proper
10035 pointer to the result, AND sets the length return value to a tree that
10036 specifies the length of the result.
10038 If the length argument is NULL, this is a slightly special
10039 case of building a FORMAT expression, that is, an expression that
10040 will be used at run time without regard to length. For the current
10041 implementation, which uses the libf2c library, this means it is nice
10042 to append a null byte to the end of the expression, where feasible,
10043 to make sure any diagnostic about the FORMAT string terminates at
10044 some useful point.
10046 For now, treat %REF(char-expr) as the same as char-expr with a NULL
10047 length argument. This might even be seen as a feature, if a null
10048 byte can always be appended. */
10050 tree
10051 ffecom_arg_ptr_to_expr (ffebld expr, tree *length)
10053 tree item;
10054 tree ign_length;
10055 ffecomConcatList_ catlist;
10057 if (length != NULL)
10058 *length = NULL_TREE;
10060 if (expr == NULL)
10061 return integer_zero_node;
10063 switch (ffebld_op (expr))
10065 case FFEBLD_opPERCENT_VAL:
10066 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10067 return ffecom_expr (ffebld_left (expr));
10069 tree temp_exp;
10070 tree temp_length;
10072 temp_exp = ffecom_arg_ptr_to_expr (ffebld_left (expr), &temp_length);
10073 if (temp_exp == error_mark_node)
10074 return error_mark_node;
10076 return ffecom_1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (temp_exp)),
10077 temp_exp);
10080 case FFEBLD_opPERCENT_REF:
10081 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10082 return ffecom_ptr_to_expr (ffebld_left (expr));
10083 if (length != NULL)
10085 ign_length = NULL_TREE;
10086 length = &ign_length;
10088 expr = ffebld_left (expr);
10089 break;
10091 case FFEBLD_opPERCENT_DESCR:
10092 switch (ffeinfo_basictype (ffebld_info (expr)))
10094 case FFEINFO_basictypeCHARACTER:
10095 break; /* Passed by descriptor anyway. */
10097 default:
10098 item = ffecom_ptr_to_expr (expr);
10099 if (item != error_mark_node)
10100 *length = TYPE_SIZE (TREE_TYPE (TREE_TYPE (item)));
10101 break;
10103 break;
10105 default:
10106 break;
10109 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10110 return ffecom_ptr_to_expr (expr);
10112 assert (ffeinfo_kindtype (ffebld_info (expr))
10113 == FFEINFO_kindtypeCHARACTER1);
10115 while (ffebld_op (expr) == FFEBLD_opPAREN)
10116 expr = ffebld_left (expr);
10118 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
10119 switch (ffecom_concat_list_count_ (catlist))
10121 case 0: /* Shouldn't happen, but in case it does... */
10122 if (length != NULL)
10124 *length = ffecom_f2c_ftnlen_zero_node;
10125 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10127 ffecom_concat_list_kill_ (catlist);
10128 return null_pointer_node;
10130 case 1: /* The (fairly) easy case. */
10131 if (length == NULL)
10132 ffecom_char_args_with_null_ (&item, &ign_length,
10133 ffecom_concat_list_expr_ (catlist, 0));
10134 else
10135 ffecom_char_args_ (&item, length,
10136 ffecom_concat_list_expr_ (catlist, 0));
10137 ffecom_concat_list_kill_ (catlist);
10138 assert (item != NULL_TREE);
10139 return item;
10141 default: /* Must actually concatenate things. */
10142 break;
10146 int count = ffecom_concat_list_count_ (catlist);
10147 int i;
10148 tree lengths;
10149 tree items;
10150 tree length_array;
10151 tree item_array;
10152 tree citem;
10153 tree clength;
10154 tree temporary;
10155 tree num;
10156 tree known_length;
10157 ffetargetCharacterSize sz;
10159 sz = ffecom_concat_list_maxlen_ (catlist);
10160 /* ~~Kludge! */
10161 assert (sz != FFETARGET_charactersizeNONE);
10164 tree hook;
10166 hook = ffebld_nonter_hook (expr);
10167 assert (hook);
10168 assert (TREE_CODE (hook) == TREE_VEC);
10169 assert (TREE_VEC_LENGTH (hook) == 3);
10170 length_array = lengths = TREE_VEC_ELT (hook, 0);
10171 item_array = items = TREE_VEC_ELT (hook, 1);
10172 temporary = TREE_VEC_ELT (hook, 2);
10175 known_length = ffecom_f2c_ftnlen_zero_node;
10177 for (i = 0; i < count; ++i)
10179 if ((i == count)
10180 && (length == NULL))
10181 ffecom_char_args_with_null_ (&citem, &clength,
10182 ffecom_concat_list_expr_ (catlist, i));
10183 else
10184 ffecom_char_args_ (&citem, &clength,
10185 ffecom_concat_list_expr_ (catlist, i));
10186 if ((citem == error_mark_node)
10187 || (clength == error_mark_node))
10189 ffecom_concat_list_kill_ (catlist);
10190 *length = error_mark_node;
10191 return error_mark_node;
10194 items
10195 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
10196 ffecom_modify (void_type_node,
10197 ffecom_2 (ARRAY_REF,
10198 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
10199 item_array,
10200 build_int_2 (i, 0)),
10201 citem),
10202 items);
10203 clength = ffecom_save_tree (clength);
10204 if (length != NULL)
10205 known_length
10206 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
10207 known_length,
10208 clength);
10209 lengths
10210 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
10211 ffecom_modify (void_type_node,
10212 ffecom_2 (ARRAY_REF,
10213 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
10214 length_array,
10215 build_int_2 (i, 0)),
10216 clength),
10217 lengths);
10220 temporary = ffecom_1 (ADDR_EXPR,
10221 build_pointer_type (TREE_TYPE (temporary)),
10222 temporary);
10224 item = build_tree_list (NULL_TREE, temporary);
10225 TREE_CHAIN (item)
10226 = build_tree_list (NULL_TREE,
10227 ffecom_1 (ADDR_EXPR,
10228 build_pointer_type (TREE_TYPE (items)),
10229 items));
10230 TREE_CHAIN (TREE_CHAIN (item))
10231 = build_tree_list (NULL_TREE,
10232 ffecom_1 (ADDR_EXPR,
10233 build_pointer_type (TREE_TYPE (lengths)),
10234 lengths));
10235 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
10236 = build_tree_list
10237 (NULL_TREE,
10238 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
10239 convert (ffecom_f2c_ftnlen_type_node,
10240 build_int_2 (count, 0))));
10241 num = build_int_2 (sz, 0);
10242 TREE_TYPE (num) = ffecom_f2c_ftnlen_type_node;
10243 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item))))
10244 = build_tree_list (NULL_TREE, num);
10246 item = ffecom_call_gfrt (FFECOM_gfrtCAT, item, NULL_TREE);
10247 TREE_SIDE_EFFECTS (item) = 1;
10248 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (temporary),
10249 item,
10250 temporary);
10252 if (length != NULL)
10253 *length = known_length;
10256 ffecom_concat_list_kill_ (catlist);
10257 assert (item != NULL_TREE);
10258 return item;
10261 /* Generate call to run-time function.
10263 The first arg is the GNU Fortran Run-Time function index, the second
10264 arg is the list of arguments to pass to it. Returned is the expression
10265 (WITHOUT TREE_SIDE_EFFECTS set!) that makes the call and returns the
10266 result (which may be void). */
10268 tree
10269 ffecom_call_gfrt (ffecomGfrt ix, tree args, tree hook)
10271 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
10272 ffecom_gfrt_kindtype (ix),
10273 ffe_is_f2c_library () && ffecom_gfrt_complex_[ix],
10274 NULL_TREE, args, NULL_TREE, NULL,
10275 NULL, NULL_TREE, TRUE, hook);
10278 /* Transform constant-union to tree. */
10280 tree
10281 ffecom_constantunion (ffebldConstantUnion *cu, ffeinfoBasictype bt,
10282 ffeinfoKindtype kt, tree tree_type)
10284 tree item;
10286 switch (bt)
10288 case FFEINFO_basictypeINTEGER:
10290 HOST_WIDE_INT hi, lo;
10292 switch (kt)
10294 #if FFETARGET_okINTEGER1
10295 case FFEINFO_kindtypeINTEGER1:
10296 lo = ffebld_cu_val_integer1 (*cu);
10297 hi = (lo < 0) ? -1 : 0;
10298 break;
10299 #endif
10301 #if FFETARGET_okINTEGER2
10302 case FFEINFO_kindtypeINTEGER2:
10303 lo = ffebld_cu_val_integer2 (*cu);
10304 hi = (lo < 0) ? -1 : 0;
10305 break;
10306 #endif
10308 #if FFETARGET_okINTEGER3
10309 case FFEINFO_kindtypeINTEGER3:
10310 lo = ffebld_cu_val_integer3 (*cu);
10311 hi = (lo < 0) ? -1 : 0;
10312 break;
10313 #endif
10315 #if FFETARGET_okINTEGER4
10316 case FFEINFO_kindtypeINTEGER4:
10317 #if HOST_BITS_PER_LONGLONG > HOST_BITS_PER_WIDE_INT
10319 long long int big = ffebld_cu_val_integer4 (*cu);
10320 hi = (HOST_WIDE_INT) (big >> HOST_BITS_PER_WIDE_INT);
10321 lo = (HOST_WIDE_INT) big;
10323 #else
10324 lo = ffebld_cu_val_integer4 (*cu);
10325 hi = (lo < 0) ? -1 : 0;
10326 #endif
10327 break;
10328 #endif
10330 default:
10331 assert ("bad INTEGER constant kind type" == NULL);
10332 /* Fall through. */
10333 case FFEINFO_kindtypeANY:
10334 return error_mark_node;
10336 item = build_int_2 (lo, hi);
10337 TREE_TYPE (item) = tree_type;
10339 break;
10341 case FFEINFO_basictypeLOGICAL:
10343 int val;
10345 switch (kt)
10347 #if FFETARGET_okLOGICAL1
10348 case FFEINFO_kindtypeLOGICAL1:
10349 val = ffebld_cu_val_logical1 (*cu);
10350 break;
10351 #endif
10353 #if FFETARGET_okLOGICAL2
10354 case FFEINFO_kindtypeLOGICAL2:
10355 val = ffebld_cu_val_logical2 (*cu);
10356 break;
10357 #endif
10359 #if FFETARGET_okLOGICAL3
10360 case FFEINFO_kindtypeLOGICAL3:
10361 val = ffebld_cu_val_logical3 (*cu);
10362 break;
10363 #endif
10365 #if FFETARGET_okLOGICAL4
10366 case FFEINFO_kindtypeLOGICAL4:
10367 val = ffebld_cu_val_logical4 (*cu);
10368 break;
10369 #endif
10371 default:
10372 assert ("bad LOGICAL constant kind type" == NULL);
10373 /* Fall through. */
10374 case FFEINFO_kindtypeANY:
10375 return error_mark_node;
10377 item = build_int_2 (val, (val < 0) ? -1 : 0);
10378 TREE_TYPE (item) = tree_type;
10380 break;
10382 case FFEINFO_basictypeREAL:
10384 REAL_VALUE_TYPE val;
10386 switch (kt)
10388 #if FFETARGET_okREAL1
10389 case FFEINFO_kindtypeREAL1:
10390 val = ffetarget_value_real1 (ffebld_cu_val_real1 (*cu));
10391 break;
10392 #endif
10394 #if FFETARGET_okREAL2
10395 case FFEINFO_kindtypeREAL2:
10396 val = ffetarget_value_real2 (ffebld_cu_val_real2 (*cu));
10397 break;
10398 #endif
10400 #if FFETARGET_okREAL3
10401 case FFEINFO_kindtypeREAL3:
10402 val = ffetarget_value_real3 (ffebld_cu_val_real3 (*cu));
10403 break;
10404 #endif
10406 default:
10407 assert ("bad REAL constant kind type" == NULL);
10408 /* Fall through. */
10409 case FFEINFO_kindtypeANY:
10410 return error_mark_node;
10412 item = build_real (tree_type, val);
10414 break;
10416 case FFEINFO_basictypeCOMPLEX:
10418 REAL_VALUE_TYPE real;
10419 REAL_VALUE_TYPE imag;
10420 tree el_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
10422 switch (kt)
10424 #if FFETARGET_okCOMPLEX1
10425 case FFEINFO_kindtypeREAL1:
10426 real = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).real);
10427 imag = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).imaginary);
10428 break;
10429 #endif
10431 #if FFETARGET_okCOMPLEX2
10432 case FFEINFO_kindtypeREAL2:
10433 real = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).real);
10434 imag = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).imaginary);
10435 break;
10436 #endif
10438 #if FFETARGET_okCOMPLEX3
10439 case FFEINFO_kindtypeREAL3:
10440 real = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).real);
10441 imag = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).imaginary);
10442 break;
10443 #endif
10445 default:
10446 assert ("bad REAL constant kind type" == NULL);
10447 /* Fall through. */
10448 case FFEINFO_kindtypeANY:
10449 return error_mark_node;
10451 item = ffecom_build_complex_constant_ (tree_type,
10452 build_real (el_type, real),
10453 build_real (el_type, imag));
10455 break;
10457 case FFEINFO_basictypeCHARACTER:
10458 { /* Happens only in DATA and similar contexts. */
10459 ffetargetCharacter1 val;
10461 switch (kt)
10463 #if FFETARGET_okCHARACTER1
10464 case FFEINFO_kindtypeLOGICAL1:
10465 val = ffebld_cu_val_character1 (*cu);
10466 break;
10467 #endif
10469 default:
10470 assert ("bad CHARACTER constant kind type" == NULL);
10471 /* Fall through. */
10472 case FFEINFO_kindtypeANY:
10473 return error_mark_node;
10475 item = build_string (ffetarget_length_character1 (val),
10476 ffetarget_text_character1 (val));
10477 TREE_TYPE (item)
10478 = build_type_variant (build_array_type (char_type_node,
10479 build_range_type
10480 (integer_type_node,
10481 integer_one_node,
10482 build_int_2
10483 (ffetarget_length_character1
10484 (val), 0))),
10485 1, 0);
10487 break;
10489 case FFEINFO_basictypeHOLLERITH:
10491 ffetargetHollerith h;
10493 h = ffebld_cu_val_hollerith (*cu);
10495 /* If not at least as wide as default INTEGER, widen it. */
10496 if (h.length >= FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE)
10497 item = build_string (h.length, h.text);
10498 else
10500 char str[FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE];
10502 memcpy (str, h.text, h.length);
10503 memset (&str[h.length], ' ',
10504 FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE
10505 - h.length);
10506 item = build_string (FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE,
10507 str);
10509 TREE_TYPE (item)
10510 = build_type_variant (build_array_type (char_type_node,
10511 build_range_type
10512 (integer_type_node,
10513 integer_one_node,
10514 build_int_2
10515 (h.length, 0))),
10516 1, 0);
10518 break;
10520 case FFEINFO_basictypeTYPELESS:
10522 ffetargetInteger1 ival;
10523 ffetargetTypeless tless;
10524 ffebad error;
10526 tless = ffebld_cu_val_typeless (*cu);
10527 error = ffetarget_convert_integer1_typeless (&ival, tless);
10528 assert (error == FFEBAD);
10530 item = build_int_2 ((int) ival, 0);
10532 break;
10534 default:
10535 assert ("not yet on constant type" == NULL);
10536 /* Fall through. */
10537 case FFEINFO_basictypeANY:
10538 return error_mark_node;
10541 TREE_CONSTANT (item) = 1;
10543 return item;
10546 /* Transform constant-union to tree, with the type known. */
10548 tree
10549 ffecom_constantunion_with_type (ffebldConstantUnion *cu, tree tree_type,
10550 ffebldConst ct)
10552 tree item;
10554 int val;
10556 switch (ct)
10558 #if FFETARGET_okINTEGER1
10559 case FFEBLD_constINTEGER1:
10560 val = ffebld_cu_val_integer1 (*cu);
10561 item = build_int_2 (val, (val < 0) ? -1 : 0);
10562 break;
10563 #endif
10564 #if FFETARGET_okINTEGER2
10565 case FFEBLD_constINTEGER2:
10566 val = ffebld_cu_val_integer2 (*cu);
10567 item = build_int_2 (val, (val < 0) ? -1 : 0);
10568 break;
10569 #endif
10570 #if FFETARGET_okINTEGER3
10571 case FFEBLD_constINTEGER3:
10572 val = ffebld_cu_val_integer3 (*cu);
10573 item = build_int_2 (val, (val < 0) ? -1 : 0);
10574 break;
10575 #endif
10576 #if FFETARGET_okINTEGER4
10577 case FFEBLD_constINTEGER4:
10578 #if HOST_BITS_PER_LONGLONG > HOST_BITS_PER_WIDE_INT
10580 long long int big = ffebld_cu_val_integer4 (*cu);
10581 item = build_int_2 ((HOST_WIDE_INT) big,
10582 (HOST_WIDE_INT)
10583 (big >> HOST_BITS_PER_WIDE_INT));
10585 #else
10586 val = ffebld_cu_val_integer4 (*cu);
10587 item = build_int_2 (val, (val < 0) ? -1 : 0);
10588 #endif
10589 break;
10590 #endif
10591 #if FFETARGET_okLOGICAL1
10592 case FFEBLD_constLOGICAL1:
10593 val = ffebld_cu_val_logical1 (*cu);
10594 item = build_int_2 (val, (val < 0) ? -1 : 0);
10595 break;
10596 #endif
10597 #if FFETARGET_okLOGICAL2
10598 case FFEBLD_constLOGICAL2:
10599 val = ffebld_cu_val_logical2 (*cu);
10600 item = build_int_2 (val, (val < 0) ? -1 : 0);
10601 break;
10602 #endif
10603 #if FFETARGET_okLOGICAL3
10604 case FFEBLD_constLOGICAL3:
10605 val = ffebld_cu_val_logical3 (*cu);
10606 item = build_int_2 (val, (val < 0) ? -1 : 0);
10607 break;
10608 #endif
10609 #if FFETARGET_okLOGICAL4
10610 case FFEBLD_constLOGICAL4:
10611 val = ffebld_cu_val_logical4 (*cu);
10612 item = build_int_2 (val, (val < 0) ? -1 : 0);
10613 break;
10614 #endif
10615 default:
10616 assert ("constant type not supported"==NULL);
10617 return error_mark_node;
10618 break;
10621 TREE_TYPE (item) = tree_type;
10623 TREE_CONSTANT (item) = 1;
10625 return item;
10627 /* Transform expression into constant tree.
10629 If the expression can be transformed into a tree that is constant,
10630 that is done, and the tree returned. Else NULL_TREE is returned.
10632 That way, a caller can attempt to provide compile-time initialization
10633 of a variable and, if that fails, *then* choose to start a new block
10634 and resort to using temporaries, as appropriate. */
10636 tree
10637 ffecom_const_expr (ffebld expr)
10639 if (! expr)
10640 return integer_zero_node;
10642 if (ffebld_op (expr) == FFEBLD_opANY)
10643 return error_mark_node;
10645 if (ffebld_arity (expr) == 0
10646 && (ffebld_op (expr) != FFEBLD_opSYMTER
10647 || ffebld_where (expr) == FFEINFO_whereGLOBAL
10648 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
10650 tree t;
10652 t = ffecom_expr (expr);
10653 assert (TREE_CONSTANT (t));
10654 return t;
10657 return NULL_TREE;
10660 /* Handy way to make a field in a struct/union. */
10662 tree
10663 ffecom_decl_field (tree context, tree prevfield, const char *name, tree type)
10665 tree field;
10667 field = build_decl (FIELD_DECL, get_identifier (name), type);
10668 DECL_CONTEXT (field) = context;
10669 DECL_ALIGN (field) = 0;
10670 DECL_USER_ALIGN (field) = 0;
10671 if (prevfield != NULL_TREE)
10672 TREE_CHAIN (prevfield) = field;
10674 return field;
10677 void
10678 ffecom_close_include (FILE *f)
10680 ffecom_close_include_ (f);
10683 /* End a compound statement (block). */
10685 tree
10686 ffecom_end_compstmt (void)
10688 return bison_rule_compstmt_ ();
10691 /* ffecom_end_transition -- Perform end transition on all symbols
10693 ffecom_end_transition();
10695 Calls ffecom_sym_end_transition for each global and local symbol. */
10697 void
10698 ffecom_end_transition (void)
10700 ffebld item;
10702 if (ffe_is_ffedebug ())
10703 fprintf (dmpout, "; end_stmt_transition\n");
10705 ffecom_list_blockdata_ = NULL;
10706 ffecom_list_common_ = NULL;
10708 ffesymbol_drive (ffecom_sym_end_transition);
10709 if (ffe_is_ffedebug ())
10711 ffestorag_report ();
10714 ffecom_start_progunit_ ();
10716 for (item = ffecom_list_blockdata_;
10717 item != NULL;
10718 item = ffebld_trail (item))
10720 ffebld callee;
10721 ffesymbol s;
10722 tree dt;
10723 tree t;
10724 tree var;
10725 static int number = 0;
10727 callee = ffebld_head (item);
10728 s = ffebld_symter (callee);
10729 t = ffesymbol_hook (s).decl_tree;
10730 if (t == NULL_TREE)
10732 s = ffecom_sym_transform_ (s);
10733 t = ffesymbol_hook (s).decl_tree;
10736 dt = build_pointer_type (TREE_TYPE (t));
10738 var = build_decl (VAR_DECL,
10739 ffecom_get_invented_identifier ("__g77_forceload_%d",
10740 number++),
10741 dt);
10742 DECL_EXTERNAL (var) = 0;
10743 TREE_STATIC (var) = 1;
10744 TREE_PUBLIC (var) = 0;
10745 DECL_INITIAL (var) = error_mark_node;
10746 TREE_USED (var) = 1;
10748 var = start_decl (var, FALSE);
10750 t = ffecom_1 (ADDR_EXPR, dt, t);
10752 finish_decl (var, t, FALSE);
10755 /* This handles any COMMON areas that weren't referenced but have, for
10756 example, important initial data. */
10758 for (item = ffecom_list_common_;
10759 item != NULL;
10760 item = ffebld_trail (item))
10761 ffecom_transform_common_ (ffebld_symter (ffebld_head (item)));
10763 ffecom_list_common_ = NULL;
10766 /* ffecom_exec_transition -- Perform exec transition on all symbols
10768 ffecom_exec_transition();
10770 Calls ffecom_sym_exec_transition for each global and local symbol.
10771 Make sure error updating not inhibited. */
10773 void
10774 ffecom_exec_transition (void)
10776 bool inhibited;
10778 if (ffe_is_ffedebug ())
10779 fprintf (dmpout, "; exec_stmt_transition\n");
10781 inhibited = ffebad_inhibit ();
10782 ffebad_set_inhibit (FALSE);
10784 ffesymbol_drive (ffecom_sym_exec_transition); /* Don't retract! */
10785 ffeequiv_exec_transition (); /* Handle all pending EQUIVALENCEs. */
10786 if (ffe_is_ffedebug ())
10788 ffestorag_report ();
10791 if (inhibited)
10792 ffebad_set_inhibit (TRUE);
10795 /* Handle assignment statement.
10797 Convert dest and source using ffecom_expr, then join them
10798 with an ASSIGN op and pass the whole thing to expand_expr_stmt. */
10800 void
10801 ffecom_expand_let_stmt (ffebld dest, ffebld source)
10803 tree dest_tree;
10804 tree dest_length;
10805 tree source_tree;
10806 tree expr_tree;
10808 if (ffeinfo_basictype (ffebld_info (dest)) != FFEINFO_basictypeCHARACTER)
10810 bool dest_used;
10811 tree assign_temp;
10813 /* This attempts to replicate the test below, but must not be
10814 true when the test below is false. (Always err on the side
10815 of creating unused temporaries, to avoid ICEs.) */
10816 if (ffebld_op (dest) != FFEBLD_opSYMTER
10817 || ((dest_tree = ffesymbol_hook (ffebld_symter (dest)).decl_tree)
10818 && (TREE_CODE (dest_tree) != VAR_DECL
10819 || TREE_ADDRESSABLE (dest_tree))))
10821 ffecom_prepare_expr_ (source, dest);
10822 dest_used = TRUE;
10824 else
10826 ffecom_prepare_expr_ (source, NULL);
10827 dest_used = FALSE;
10830 ffecom_prepare_expr_w (NULL_TREE, dest);
10832 /* For COMPLEX assignment like C1=C2, if partial overlap is possible,
10833 create a temporary through which the assignment is to take place,
10834 since MODIFY_EXPR doesn't handle partial overlap properly. */
10835 if (ffebld_basictype (dest) == FFEINFO_basictypeCOMPLEX
10836 && ffecom_possible_partial_overlap_ (dest, source))
10838 assign_temp = ffecom_make_tempvar ("complex_let",
10839 ffecom_tree_type
10840 [ffebld_basictype (dest)]
10841 [ffebld_kindtype (dest)],
10842 FFETARGET_charactersizeNONE,
10843 -1);
10845 else
10846 assign_temp = NULL_TREE;
10848 ffecom_prepare_end ();
10850 dest_tree = ffecom_expr_w (NULL_TREE, dest);
10851 if (dest_tree == error_mark_node)
10852 return;
10854 if ((TREE_CODE (dest_tree) != VAR_DECL)
10855 || TREE_ADDRESSABLE (dest_tree))
10856 source_tree = ffecom_expr_ (source, dest_tree, dest, &dest_used,
10857 FALSE, FALSE);
10858 else
10860 assert (! dest_used);
10861 dest_used = FALSE;
10862 source_tree = ffecom_expr (source);
10864 if (source_tree == error_mark_node)
10865 return;
10867 if (dest_used)
10868 expr_tree = source_tree;
10869 else if (assign_temp)
10871 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
10872 assign_temp,
10873 source_tree);
10874 expand_expr_stmt (expr_tree);
10875 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
10876 dest_tree,
10877 assign_temp);
10879 else
10880 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
10881 dest_tree,
10882 source_tree);
10884 expand_expr_stmt (expr_tree);
10885 return;
10888 ffecom_prepare_let_char_ (ffebld_size_known (dest), source);
10889 ffecom_prepare_expr_w (NULL_TREE, dest);
10891 ffecom_prepare_end ();
10893 ffecom_char_args_ (&dest_tree, &dest_length, dest);
10894 ffecom_let_char_ (dest_tree, dest_length, ffebld_size_known (dest),
10895 source);
10898 /* ffecom_expr -- Transform expr into gcc tree
10900 tree t;
10901 ffebld expr; // FFE expression.
10902 tree = ffecom_expr(expr);
10904 Recursive descent on expr while making corresponding tree nodes and
10905 attaching type info and such. */
10907 tree
10908 ffecom_expr (ffebld expr)
10910 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, FALSE, FALSE);
10913 /* Like ffecom_expr, but return tree usable for assigned GOTO or FORMAT. */
10915 tree
10916 ffecom_expr_assign (ffebld expr)
10918 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
10921 /* Like ffecom_expr_rw, but return tree usable for ASSIGN. */
10923 tree
10924 ffecom_expr_assign_w (ffebld expr)
10926 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
10929 /* Transform expr for use as into read/write tree and stabilize the
10930 reference. Not for use on CHARACTER expressions.
10932 Recursive descent on expr while making corresponding tree nodes and
10933 attaching type info and such. */
10935 tree
10936 ffecom_expr_rw (tree type, ffebld expr)
10938 assert (expr != NULL);
10939 /* Different target types not yet supported. */
10940 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
10942 return stabilize_reference (ffecom_expr (expr));
10945 /* Transform expr for use as into write tree and stabilize the
10946 reference. Not for use on CHARACTER expressions.
10948 Recursive descent on expr while making corresponding tree nodes and
10949 attaching type info and such. */
10951 tree
10952 ffecom_expr_w (tree type, ffebld expr)
10954 assert (expr != NULL);
10955 /* Different target types not yet supported. */
10956 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
10958 return stabilize_reference (ffecom_expr (expr));
10961 /* Do global stuff. */
10963 void
10964 ffecom_finish_compile (void)
10966 assert (ffecom_outer_function_decl_ == NULL_TREE);
10967 assert (current_function_decl == NULL_TREE);
10969 ffeglobal_drive (ffecom_finish_global_);
10972 /* Public entry point for front end to access finish_decl. */
10974 void
10975 ffecom_finish_decl (tree decl, tree init, bool is_top_level)
10977 assert (!is_top_level);
10978 finish_decl (decl, init, FALSE);
10981 /* Finish a program unit. */
10983 void
10984 ffecom_finish_progunit (void)
10986 ffecom_end_compstmt ();
10988 ffecom_previous_function_decl_ = current_function_decl;
10989 ffecom_which_entrypoint_decl_ = NULL_TREE;
10991 finish_function (0);
10994 /* Wrapper for get_identifier. pattern is sprintf-like. */
10996 tree
10997 ffecom_get_invented_identifier (const char *pattern, ...)
10999 tree decl;
11000 char *nam;
11001 va_list ap;
11003 va_start (ap, pattern);
11004 if (vasprintf (&nam, pattern, ap) == 0)
11005 abort ();
11006 va_end (ap);
11007 decl = get_identifier (nam);
11008 free (nam);
11009 IDENTIFIER_INVENTED (decl) = 1;
11010 return decl;
11013 ffeinfoBasictype
11014 ffecom_gfrt_basictype (ffecomGfrt gfrt)
11016 assert (gfrt < FFECOM_gfrt);
11018 switch (ffecom_gfrt_type_[gfrt])
11020 case FFECOM_rttypeVOID_:
11021 case FFECOM_rttypeVOIDSTAR_:
11022 return FFEINFO_basictypeNONE;
11024 case FFECOM_rttypeFTNINT_:
11025 return FFEINFO_basictypeINTEGER;
11027 case FFECOM_rttypeINTEGER_:
11028 return FFEINFO_basictypeINTEGER;
11030 case FFECOM_rttypeLONGINT_:
11031 return FFEINFO_basictypeINTEGER;
11033 case FFECOM_rttypeLOGICAL_:
11034 return FFEINFO_basictypeLOGICAL;
11036 case FFECOM_rttypeREAL_F2C_:
11037 case FFECOM_rttypeREAL_GNU_:
11038 return FFEINFO_basictypeREAL;
11040 case FFECOM_rttypeCOMPLEX_F2C_:
11041 case FFECOM_rttypeCOMPLEX_GNU_:
11042 return FFEINFO_basictypeCOMPLEX;
11044 case FFECOM_rttypeDOUBLE_:
11045 case FFECOM_rttypeDOUBLEREAL_:
11046 return FFEINFO_basictypeREAL;
11048 case FFECOM_rttypeDBLCMPLX_F2C_:
11049 case FFECOM_rttypeDBLCMPLX_GNU_:
11050 return FFEINFO_basictypeCOMPLEX;
11052 case FFECOM_rttypeCHARACTER_:
11053 return FFEINFO_basictypeCHARACTER;
11055 default:
11056 return FFEINFO_basictypeANY;
11060 ffeinfoKindtype
11061 ffecom_gfrt_kindtype (ffecomGfrt gfrt)
11063 assert (gfrt < FFECOM_gfrt);
11065 switch (ffecom_gfrt_type_[gfrt])
11067 case FFECOM_rttypeVOID_:
11068 case FFECOM_rttypeVOIDSTAR_:
11069 return FFEINFO_kindtypeNONE;
11071 case FFECOM_rttypeFTNINT_:
11072 return FFEINFO_kindtypeINTEGER1;
11074 case FFECOM_rttypeINTEGER_:
11075 return FFEINFO_kindtypeINTEGER1;
11077 case FFECOM_rttypeLONGINT_:
11078 return FFEINFO_kindtypeINTEGER4;
11080 case FFECOM_rttypeLOGICAL_:
11081 return FFEINFO_kindtypeLOGICAL1;
11083 case FFECOM_rttypeREAL_F2C_:
11084 case FFECOM_rttypeREAL_GNU_:
11085 return FFEINFO_kindtypeREAL1;
11087 case FFECOM_rttypeCOMPLEX_F2C_:
11088 case FFECOM_rttypeCOMPLEX_GNU_:
11089 return FFEINFO_kindtypeREAL1;
11091 case FFECOM_rttypeDOUBLE_:
11092 case FFECOM_rttypeDOUBLEREAL_:
11093 return FFEINFO_kindtypeREAL2;
11095 case FFECOM_rttypeDBLCMPLX_F2C_:
11096 case FFECOM_rttypeDBLCMPLX_GNU_:
11097 return FFEINFO_kindtypeREAL2;
11099 case FFECOM_rttypeCHARACTER_:
11100 return FFEINFO_kindtypeCHARACTER1;
11102 default:
11103 return FFEINFO_kindtypeANY;
11107 void
11108 ffecom_init_0 (void)
11110 tree endlink;
11111 int i;
11112 int j;
11113 tree t;
11114 tree field;
11115 ffetype type;
11116 ffetype base_type;
11117 tree double_ftype_double, double_ftype_double_double;
11118 tree float_ftype_float, float_ftype_float_float;
11119 tree ldouble_ftype_ldouble, ldouble_ftype_ldouble_ldouble;
11120 tree ffecom_tree_ptr_to_fun_type_void;
11122 /* This block of code comes from the now-obsolete cktyps.c. It checks
11123 whether the compiler environment is buggy in known ways, some of which
11124 would, if not explicitly checked here, result in subtle bugs in g77. */
11126 if (ffe_is_do_internal_checks ())
11128 static const char names[][12]
11130 {"bar", "bletch", "foo", "foobar"};
11131 const char *name;
11132 unsigned long ul;
11133 double fl;
11135 name = bsearch ("foo", &names[0], ARRAY_SIZE (names), sizeof (names[0]),
11136 (int (*)(const void *, const void *)) strcmp);
11137 if (name != &names[2][0])
11139 assert ("bsearch doesn't work, #define FFEPROJ_BSEARCH 0 in proj.h"
11140 == NULL);
11141 abort ();
11144 ul = strtoul ("123456789", NULL, 10);
11145 if (ul != 123456789L)
11147 assert ("strtoul doesn't have enough range, #define FFEPROJ_STRTOUL 0\
11148 in proj.h" == NULL);
11149 abort ();
11152 fl = atof ("56.789");
11153 if ((fl < 56.788) || (fl > 56.79))
11155 assert ("atof not type double, fix your #include <stdio.h>"
11156 == NULL);
11157 abort ();
11161 ffecom_outer_function_decl_ = NULL_TREE;
11162 current_function_decl = NULL_TREE;
11163 named_labels = NULL_TREE;
11164 current_binding_level = NULL_BINDING_LEVEL;
11165 free_binding_level = NULL_BINDING_LEVEL;
11166 /* Make the binding_level structure for global names. */
11167 pushlevel (0);
11168 global_binding_level = current_binding_level;
11169 current_binding_level->prep_state = 2;
11171 build_common_tree_nodes (1);
11173 /* Define `int' and `char' first so that dbx will output them first. */
11174 pushdecl (build_decl (TYPE_DECL, get_identifier ("int"),
11175 integer_type_node));
11176 /* CHARACTER*1 is unsigned in ICHAR contexts. */
11177 char_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
11178 pushdecl (build_decl (TYPE_DECL, get_identifier ("char"),
11179 char_type_node));
11180 pushdecl (build_decl (TYPE_DECL, get_identifier ("long int"),
11181 long_integer_type_node));
11182 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned int"),
11183 unsigned_type_node));
11184 pushdecl (build_decl (TYPE_DECL, get_identifier ("long unsigned int"),
11185 long_unsigned_type_node));
11186 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long int"),
11187 long_long_integer_type_node));
11188 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"),
11189 long_long_unsigned_type_node));
11190 pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"),
11191 short_integer_type_node));
11192 pushdecl (build_decl (TYPE_DECL, get_identifier ("short unsigned int"),
11193 short_unsigned_type_node));
11195 /* Set the sizetype before we make other types. This *should* be the
11196 first type we create. */
11198 set_sizetype
11199 (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))));
11200 ffecom_typesize_pointer_
11201 = TREE_INT_CST_LOW (TYPE_SIZE (sizetype)) / BITS_PER_UNIT;
11203 build_common_tree_nodes_2 (0);
11205 /* Define both `signed char' and `unsigned char'. */
11206 pushdecl (build_decl (TYPE_DECL, get_identifier ("signed char"),
11207 signed_char_type_node));
11209 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned char"),
11210 unsigned_char_type_node));
11212 pushdecl (build_decl (TYPE_DECL, get_identifier ("float"),
11213 float_type_node));
11214 pushdecl (build_decl (TYPE_DECL, get_identifier ("double"),
11215 double_type_node));
11216 pushdecl (build_decl (TYPE_DECL, get_identifier ("long double"),
11217 long_double_type_node));
11219 /* For now, override what build_common_tree_nodes has done. */
11220 complex_integer_type_node = ffecom_make_complex_type_ (integer_type_node);
11221 complex_float_type_node = ffecom_make_complex_type_ (float_type_node);
11222 complex_double_type_node = ffecom_make_complex_type_ (double_type_node);
11223 complex_long_double_type_node
11224 = ffecom_make_complex_type_ (long_double_type_node);
11226 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"),
11227 complex_integer_type_node));
11228 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"),
11229 complex_float_type_node));
11230 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"),
11231 complex_double_type_node));
11232 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"),
11233 complex_long_double_type_node));
11235 pushdecl (build_decl (TYPE_DECL, get_identifier ("void"),
11236 void_type_node));
11237 /* We are not going to have real types in C with less than byte alignment,
11238 so we might as well not have any types that claim to have it. */
11239 TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
11240 TYPE_USER_ALIGN (void_type_node) = 0;
11242 string_type_node = build_pointer_type (char_type_node);
11244 ffecom_tree_fun_type_void
11245 = build_function_type (void_type_node, NULL_TREE);
11247 ffecom_tree_ptr_to_fun_type_void
11248 = build_pointer_type (ffecom_tree_fun_type_void);
11250 endlink = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
11252 t = tree_cons (NULL_TREE, float_type_node, endlink);
11253 float_ftype_float = build_function_type (float_type_node, t);
11254 t = tree_cons (NULL_TREE, float_type_node, t);
11255 float_ftype_float_float = build_function_type (float_type_node, t);
11257 t = tree_cons (NULL_TREE, double_type_node, endlink);
11258 double_ftype_double = build_function_type (double_type_node, t);
11259 t = tree_cons (NULL_TREE, double_type_node, t);
11260 double_ftype_double_double = build_function_type (double_type_node, t);
11262 t = tree_cons (NULL_TREE, long_double_type_node, endlink);
11263 ldouble_ftype_ldouble = build_function_type (long_double_type_node, t);
11264 t = tree_cons (NULL_TREE, long_double_type_node, t);
11265 ldouble_ftype_ldouble_ldouble = build_function_type (long_double_type_node,
11268 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11269 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11271 ffecom_tree_type[i][j] = NULL_TREE;
11272 ffecom_tree_fun_type[i][j] = NULL_TREE;
11273 ffecom_tree_ptr_to_fun_type[i][j] = NULL_TREE;
11274 ffecom_f2c_typecode_[i][j] = -1;
11277 /* Set up standard g77 types. Note that INTEGER and LOGICAL are set
11278 to size FLOAT_TYPE_SIZE because they have to be the same size as
11279 REAL, which also is FLOAT_TYPE_SIZE, according to the standard.
11280 Compiler options and other such stuff that change the ways these
11281 types are set should not affect this particular setup. */
11283 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1]
11284 = t = make_signed_type (FLOAT_TYPE_SIZE);
11285 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer"),
11286 t));
11287 type = ffetype_new ();
11288 base_type = type;
11289 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER1,
11290 type);
11291 ffetype_set_ams (type,
11292 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11293 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11294 ffetype_set_star (base_type,
11295 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11296 type);
11297 ffetype_set_kind (base_type, 1, type);
11298 ffecom_typesize_integer1_ = ffetype_size (type);
11299 assert (ffetype_size (type) == sizeof (ffetargetInteger1));
11301 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER1]
11302 = t = make_unsigned_type (FLOAT_TYPE_SIZE); /* HOLLERITH means unsigned. */
11303 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned"),
11304 t));
11306 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER2]
11307 = t = make_signed_type (CHAR_TYPE_SIZE);
11308 pushdecl (build_decl (TYPE_DECL, get_identifier ("byte"),
11309 t));
11310 type = ffetype_new ();
11311 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER2,
11312 type);
11313 ffetype_set_ams (type,
11314 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11315 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11316 ffetype_set_star (base_type,
11317 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11318 type);
11319 ffetype_set_kind (base_type, 3, type);
11320 assert (ffetype_size (type) == sizeof (ffetargetInteger2));
11322 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER2]
11323 = t = make_unsigned_type (CHAR_TYPE_SIZE);
11324 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned byte"),
11325 t));
11327 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER3]
11328 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11329 pushdecl (build_decl (TYPE_DECL, get_identifier ("word"),
11330 t));
11331 type = ffetype_new ();
11332 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER3,
11333 type);
11334 ffetype_set_ams (type,
11335 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11336 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11337 ffetype_set_star (base_type,
11338 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11339 type);
11340 ffetype_set_kind (base_type, 6, type);
11341 assert (ffetype_size (type) == sizeof (ffetargetInteger3));
11343 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER3]
11344 = t = make_unsigned_type (CHAR_TYPE_SIZE * 2);
11345 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned word"),
11346 t));
11348 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER4]
11349 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11350 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer4"),
11351 t));
11352 type = ffetype_new ();
11353 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER4,
11354 type);
11355 ffetype_set_ams (type,
11356 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11357 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11358 ffetype_set_star (base_type,
11359 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11360 type);
11361 ffetype_set_kind (base_type, 2, type);
11362 assert (ffetype_size (type) == sizeof (ffetargetInteger4));
11364 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER4]
11365 = t = make_unsigned_type (FLOAT_TYPE_SIZE * 2);
11366 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned4"),
11367 t));
11369 #if 0
11370 if (ffe_is_do_internal_checks ()
11371 && LONG_TYPE_SIZE != FLOAT_TYPE_SIZE
11372 && LONG_TYPE_SIZE != CHAR_TYPE_SIZE
11373 && LONG_TYPE_SIZE != SHORT_TYPE_SIZE
11374 && LONG_TYPE_SIZE != LONG_LONG_TYPE_SIZE)
11376 fprintf (stderr, "Sorry, no g77 support for LONG_TYPE_SIZE (%d bits) yet.\n",
11377 LONG_TYPE_SIZE);
11379 #endif
11381 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL1]
11382 = t = make_signed_type (FLOAT_TYPE_SIZE);
11383 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical"),
11384 t));
11385 type = ffetype_new ();
11386 base_type = type;
11387 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL1,
11388 type);
11389 ffetype_set_ams (type,
11390 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11391 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11392 ffetype_set_star (base_type,
11393 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11394 type);
11395 ffetype_set_kind (base_type, 1, type);
11396 assert (ffetype_size (type) == sizeof (ffetargetLogical1));
11398 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL2]
11399 = t = make_signed_type (CHAR_TYPE_SIZE);
11400 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical2"),
11401 t));
11402 type = ffetype_new ();
11403 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL2,
11404 type);
11405 ffetype_set_ams (type,
11406 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11407 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11408 ffetype_set_star (base_type,
11409 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11410 type);
11411 ffetype_set_kind (base_type, 3, type);
11412 assert (ffetype_size (type) == sizeof (ffetargetLogical2));
11414 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL3]
11415 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11416 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical3"),
11417 t));
11418 type = ffetype_new ();
11419 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL3,
11420 type);
11421 ffetype_set_ams (type,
11422 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11423 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11424 ffetype_set_star (base_type,
11425 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11426 type);
11427 ffetype_set_kind (base_type, 6, type);
11428 assert (ffetype_size (type) == sizeof (ffetargetLogical3));
11430 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL4]
11431 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11432 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical4"),
11433 t));
11434 type = ffetype_new ();
11435 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL4,
11436 type);
11437 ffetype_set_ams (type,
11438 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11439 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11440 ffetype_set_star (base_type,
11441 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11442 type);
11443 ffetype_set_kind (base_type, 2, type);
11444 assert (ffetype_size (type) == sizeof (ffetargetLogical4));
11446 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
11447 = t = make_node (REAL_TYPE);
11448 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE;
11449 pushdecl (build_decl (TYPE_DECL, get_identifier ("real"),
11450 t));
11451 layout_type (t);
11452 type = ffetype_new ();
11453 base_type = type;
11454 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREAL1,
11455 type);
11456 ffetype_set_ams (type,
11457 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11458 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11459 ffetype_set_star (base_type,
11460 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11461 type);
11462 ffetype_set_kind (base_type, 1, type);
11463 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
11464 = FFETARGET_f2cTYREAL;
11465 assert (ffetype_size (type) == sizeof (ffetargetReal1));
11467 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREALDOUBLE]
11468 = t = make_node (REAL_TYPE);
11469 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE * 2; /* Always twice REAL. */
11470 pushdecl (build_decl (TYPE_DECL, get_identifier ("double precision"),
11471 t));
11472 layout_type (t);
11473 type = ffetype_new ();
11474 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREALDOUBLE,
11475 type);
11476 ffetype_set_ams (type,
11477 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11478 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11479 ffetype_set_star (base_type,
11480 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11481 type);
11482 ffetype_set_kind (base_type, 2, type);
11483 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]
11484 = FFETARGET_f2cTYDREAL;
11485 assert (ffetype_size (type) == sizeof (ffetargetReal2));
11487 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
11488 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]);
11489 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex"),
11490 t));
11491 type = ffetype_new ();
11492 base_type = type;
11493 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREAL1,
11494 type);
11495 ffetype_set_ams (type,
11496 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11497 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11498 ffetype_set_star (base_type,
11499 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11500 type);
11501 ffetype_set_kind (base_type, 1, type);
11502 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
11503 = FFETARGET_f2cTYCOMPLEX;
11504 assert (ffetype_size (type) == sizeof (ffetargetComplex1));
11506 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREALDOUBLE]
11507 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]);
11508 pushdecl (build_decl (TYPE_DECL, get_identifier ("double complex"),
11509 t));
11510 type = ffetype_new ();
11511 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREALDOUBLE,
11512 type);
11513 ffetype_set_ams (type,
11514 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11515 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11516 ffetype_set_star (base_type,
11517 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11518 type);
11519 ffetype_set_kind (base_type, 2,
11520 type);
11521 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL2]
11522 = FFETARGET_f2cTYDCOMPLEX;
11523 assert (ffetype_size (type) == sizeof (ffetargetComplex2));
11525 /* Make function and ptr-to-function types for non-CHARACTER types. */
11527 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11528 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11530 if ((t = ffecom_tree_type[i][j]) != NULL_TREE)
11532 if (i == FFEINFO_basictypeINTEGER)
11534 /* Figure out the smallest INTEGER type that can hold
11535 a pointer on this machine. */
11536 if (GET_MODE_SIZE (TYPE_MODE (t))
11537 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
11539 if ((ffecom_pointer_kind_ == FFEINFO_kindtypeNONE)
11540 || (GET_MODE_SIZE (TYPE_MODE (ffecom_tree_type[i][ffecom_pointer_kind_]))
11541 > GET_MODE_SIZE (TYPE_MODE (t))))
11542 ffecom_pointer_kind_ = j;
11545 else if (i == FFEINFO_basictypeCOMPLEX)
11546 t = void_type_node;
11547 /* For f2c compatibility, REAL functions are really
11548 implemented as DOUBLE PRECISION. */
11549 else if ((i == FFEINFO_basictypeREAL)
11550 && (j == FFEINFO_kindtypeREAL1))
11551 t = ffecom_tree_type
11552 [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2];
11554 t = ffecom_tree_fun_type[i][j] = build_function_type (t,
11555 NULL_TREE);
11556 ffecom_tree_ptr_to_fun_type[i][j] = build_pointer_type (t);
11560 /* Set up pointer types. */
11562 if (ffecom_pointer_kind_ == FFEINFO_basictypeNONE)
11563 fatal_error ("no INTEGER type can hold a pointer on this configuration");
11564 else if (0 && ffe_is_do_internal_checks ())
11565 fprintf (stderr, "Pointer type kt=%d\n", ffecom_pointer_kind_);
11566 ffetype_set_kind (ffeinfo_type (FFEINFO_basictypeINTEGER,
11567 FFEINFO_kindtypeINTEGERDEFAULT),
11569 ffeinfo_type (FFEINFO_basictypeINTEGER,
11570 ffecom_pointer_kind_));
11572 if (ffe_is_ugly_assign ())
11573 ffecom_label_kind_ = ffecom_pointer_kind_; /* Require ASSIGN etc to this. */
11574 else
11575 ffecom_label_kind_ = FFEINFO_kindtypeINTEGERDEFAULT;
11576 if (0 && ffe_is_do_internal_checks ())
11577 fprintf (stderr, "Label type kt=%d\n", ffecom_label_kind_);
11579 ffecom_integer_type_node
11580 = ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1];
11581 ffecom_integer_zero_node = convert (ffecom_integer_type_node,
11582 integer_zero_node);
11583 ffecom_integer_one_node = convert (ffecom_integer_type_node,
11584 integer_one_node);
11586 /* Yes, the "FLOAT_TYPE_SIZE" references below are intentional.
11587 Turns out that by TYLONG, runtime/libI77/lio.h really means
11588 "whatever size an ftnint is". For consistency and sanity,
11589 com.h and runtime/f2c.h.in agree that flag, ftnint, and ftlen
11590 all are INTEGER, which we also make out of whatever back-end
11591 integer type is FLOAT_TYPE_SIZE bits wide. This change, from
11592 LONG_TYPE_SIZE, for TYLONG and TYLOGICAL, was necessary to
11593 accommodate machines like the Alpha. Note that this suggests
11594 f2c and libf2c are missing a distinction perhaps needed on
11595 some machines between "int" and "long int". -- burley 0.5.5 950215 */
11597 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, FLOAT_TYPE_SIZE,
11598 FFETARGET_f2cTYLONG);
11599 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, SHORT_TYPE_SIZE,
11600 FFETARGET_f2cTYSHORT);
11601 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, CHAR_TYPE_SIZE,
11602 FFETARGET_f2cTYINT1);
11603 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, LONG_LONG_TYPE_SIZE,
11604 FFETARGET_f2cTYQUAD);
11605 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, FLOAT_TYPE_SIZE,
11606 FFETARGET_f2cTYLOGICAL);
11607 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, SHORT_TYPE_SIZE,
11608 FFETARGET_f2cTYLOGICAL2);
11609 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, CHAR_TYPE_SIZE,
11610 FFETARGET_f2cTYLOGICAL1);
11611 /* ~~~Not really such a type in libf2c, e.g. I/O support? */
11612 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, LONG_LONG_TYPE_SIZE,
11613 FFETARGET_f2cTYQUAD);
11615 /* CHARACTER stuff is all special-cased, so it is not handled in the above
11616 loop. CHARACTER items are built as arrays of unsigned char. */
11618 ffecom_tree_type[FFEINFO_basictypeCHARACTER]
11619 [FFEINFO_kindtypeCHARACTER1] = t = char_type_node;
11620 type = ffetype_new ();
11621 base_type = type;
11622 ffeinfo_set_type (FFEINFO_basictypeCHARACTER,
11623 FFEINFO_kindtypeCHARACTER1,
11624 type);
11625 ffetype_set_ams (type,
11626 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11627 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11628 ffetype_set_kind (base_type, 1, type);
11629 assert (ffetype_size (type)
11630 == sizeof (((ffetargetCharacter1) { 0, NULL }).text[0]));
11632 ffecom_tree_fun_type[FFEINFO_basictypeCHARACTER]
11633 [FFEINFO_kindtypeCHARACTER1] = ffecom_tree_fun_type_void;
11634 ffecom_tree_ptr_to_fun_type[FFEINFO_basictypeCHARACTER]
11635 [FFEINFO_kindtypeCHARACTER1]
11636 = ffecom_tree_ptr_to_fun_type_void;
11637 ffecom_f2c_typecode_[FFEINFO_basictypeCHARACTER][FFEINFO_kindtypeCHARACTER1]
11638 = FFETARGET_f2cTYCHAR;
11640 ffecom_f2c_typecode_[FFEINFO_basictypeANY][FFEINFO_kindtypeANY]
11641 = 0;
11643 /* Make multi-return-value type and fields. */
11645 ffecom_multi_type_node_ = make_node (UNION_TYPE);
11647 field = NULL_TREE;
11649 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11650 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11652 char name[30];
11654 if (ffecom_tree_type[i][j] == NULL_TREE)
11655 continue; /* Not supported. */
11656 sprintf (&name[0], "bt_%s_kt_%s",
11657 ffeinfo_basictype_string ((ffeinfoBasictype) i),
11658 ffeinfo_kindtype_string ((ffeinfoKindtype) j));
11659 ffecom_multi_fields_[i][j] = build_decl (FIELD_DECL,
11660 get_identifier (name),
11661 ffecom_tree_type[i][j]);
11662 DECL_CONTEXT (ffecom_multi_fields_[i][j])
11663 = ffecom_multi_type_node_;
11664 DECL_ALIGN (ffecom_multi_fields_[i][j]) = 0;
11665 DECL_USER_ALIGN (ffecom_multi_fields_[i][j]) = 0;
11666 TREE_CHAIN (ffecom_multi_fields_[i][j]) = field;
11667 field = ffecom_multi_fields_[i][j];
11670 TYPE_FIELDS (ffecom_multi_type_node_) = field;
11671 layout_type (ffecom_multi_type_node_);
11673 /* Subroutines usually return integer because they might have alternate
11674 returns. */
11676 ffecom_tree_subr_type
11677 = build_function_type (integer_type_node, NULL_TREE);
11678 ffecom_tree_ptr_to_subr_type
11679 = build_pointer_type (ffecom_tree_subr_type);
11680 ffecom_tree_blockdata_type
11681 = build_function_type (void_type_node, NULL_TREE);
11683 builtin_function ("__builtin_atanf", float_ftype_float,
11684 BUILT_IN_ATANF, BUILT_IN_NORMAL, "atanf", NULL_TREE);
11685 builtin_function ("__builtin_atan", double_ftype_double,
11686 BUILT_IN_ATAN, BUILT_IN_NORMAL, "atan", NULL_TREE);
11687 builtin_function ("__builtin_atanl", ldouble_ftype_ldouble,
11688 BUILT_IN_ATANL, BUILT_IN_NORMAL, "atanl", NULL_TREE);
11690 builtin_function ("__builtin_atan2f", float_ftype_float_float,
11691 BUILT_IN_ATAN2F, BUILT_IN_NORMAL, "atan2f", NULL_TREE);
11692 builtin_function ("__builtin_atan2", double_ftype_double_double,
11693 BUILT_IN_ATAN2, BUILT_IN_NORMAL, "atan2", NULL_TREE);
11694 builtin_function ("__builtin_atan2l", ldouble_ftype_ldouble_ldouble,
11695 BUILT_IN_ATAN2L, BUILT_IN_NORMAL, "atan2l", NULL_TREE);
11697 builtin_function ("__builtin_cosf", float_ftype_float,
11698 BUILT_IN_COSF, BUILT_IN_NORMAL, "cosf", NULL_TREE);
11699 builtin_function ("__builtin_cos", double_ftype_double,
11700 BUILT_IN_COS, BUILT_IN_NORMAL, "cos", NULL_TREE);
11701 builtin_function ("__builtin_cosl", ldouble_ftype_ldouble,
11702 BUILT_IN_COSL, BUILT_IN_NORMAL, "cosl", NULL_TREE);
11704 builtin_function ("__builtin_expf", float_ftype_float,
11705 BUILT_IN_EXPF, BUILT_IN_NORMAL, "expf", NULL_TREE);
11706 builtin_function ("__builtin_exp", double_ftype_double,
11707 BUILT_IN_EXP, BUILT_IN_NORMAL, "exp", NULL_TREE);
11708 builtin_function ("__builtin_expl", ldouble_ftype_ldouble,
11709 BUILT_IN_EXPL, BUILT_IN_NORMAL, "expl", NULL_TREE);
11711 builtin_function ("__builtin_floorf", float_ftype_float,
11712 BUILT_IN_FLOORF, BUILT_IN_NORMAL, "floorf", NULL_TREE);
11713 builtin_function ("__builtin_floor", double_ftype_double,
11714 BUILT_IN_FLOOR, BUILT_IN_NORMAL, "floor", NULL_TREE);
11715 builtin_function ("__builtin_floorl", ldouble_ftype_ldouble,
11716 BUILT_IN_FLOORL, BUILT_IN_NORMAL, "floorl", NULL_TREE);
11718 builtin_function ("__builtin_fmodf", float_ftype_float_float,
11719 BUILT_IN_FMODF, BUILT_IN_NORMAL, "fmodf", NULL_TREE);
11720 builtin_function ("__builtin_fmod", double_ftype_double_double,
11721 BUILT_IN_FMOD, BUILT_IN_NORMAL, "fmod", NULL_TREE);
11722 builtin_function ("__builtin_fmodl", ldouble_ftype_ldouble_ldouble,
11723 BUILT_IN_FMODL, BUILT_IN_NORMAL, "fmodl", NULL_TREE);
11725 builtin_function ("__builtin_logf", float_ftype_float,
11726 BUILT_IN_LOGF, BUILT_IN_NORMAL, "logf", NULL_TREE);
11727 builtin_function ("__builtin_log", double_ftype_double,
11728 BUILT_IN_LOG, BUILT_IN_NORMAL, "log", NULL_TREE);
11729 builtin_function ("__builtin_logl", ldouble_ftype_ldouble,
11730 BUILT_IN_LOGL, BUILT_IN_NORMAL, "logl", NULL_TREE);
11732 builtin_function ("__builtin_powf", float_ftype_float_float,
11733 BUILT_IN_POWF, BUILT_IN_NORMAL, "powf", NULL_TREE);
11734 builtin_function ("__builtin_pow", double_ftype_double_double,
11735 BUILT_IN_POW, BUILT_IN_NORMAL, "pow", NULL_TREE);
11736 builtin_function ("__builtin_powl", ldouble_ftype_ldouble_ldouble,
11737 BUILT_IN_POWL, BUILT_IN_NORMAL, "powl", NULL_TREE);
11739 builtin_function ("__builtin_sinf", float_ftype_float,
11740 BUILT_IN_SINF, BUILT_IN_NORMAL, "sinf", NULL_TREE);
11741 builtin_function ("__builtin_sin", double_ftype_double,
11742 BUILT_IN_SIN, BUILT_IN_NORMAL, "sin", NULL_TREE);
11743 builtin_function ("__builtin_sinl", ldouble_ftype_ldouble,
11744 BUILT_IN_SINL, BUILT_IN_NORMAL, "sinl", NULL_TREE);
11746 builtin_function ("__builtin_sqrtf", float_ftype_float,
11747 BUILT_IN_SQRTF, BUILT_IN_NORMAL, "sqrtf", NULL_TREE);
11748 builtin_function ("__builtin_sqrt", double_ftype_double,
11749 BUILT_IN_SQRT, BUILT_IN_NORMAL, "sqrt", NULL_TREE);
11750 builtin_function ("__builtin_sqrtl", ldouble_ftype_ldouble,
11751 BUILT_IN_SQRTL, BUILT_IN_NORMAL, "sqrtl", NULL_TREE);
11753 builtin_function ("__builtin_tanf", float_ftype_float,
11754 BUILT_IN_TANF, BUILT_IN_NORMAL, "tanf", NULL_TREE);
11755 builtin_function ("__builtin_tan", double_ftype_double,
11756 BUILT_IN_TAN, BUILT_IN_NORMAL, "tan", NULL_TREE);
11757 builtin_function ("__builtin_tanl", ldouble_ftype_ldouble,
11758 BUILT_IN_TANL, BUILT_IN_NORMAL, "tanl", NULL_TREE);
11760 pedantic_lvalues = FALSE;
11762 ffecom_f2c_make_type_ (&ffecom_f2c_integer_type_node,
11763 FFECOM_f2cINTEGER,
11764 "integer");
11765 ffecom_f2c_make_type_ (&ffecom_f2c_address_type_node,
11766 FFECOM_f2cADDRESS,
11767 "address");
11768 ffecom_f2c_make_type_ (&ffecom_f2c_real_type_node,
11769 FFECOM_f2cREAL,
11770 "real");
11771 ffecom_f2c_make_type_ (&ffecom_f2c_doublereal_type_node,
11772 FFECOM_f2cDOUBLEREAL,
11773 "doublereal");
11774 ffecom_f2c_make_type_ (&ffecom_f2c_complex_type_node,
11775 FFECOM_f2cCOMPLEX,
11776 "complex");
11777 ffecom_f2c_make_type_ (&ffecom_f2c_doublecomplex_type_node,
11778 FFECOM_f2cDOUBLECOMPLEX,
11779 "doublecomplex");
11780 ffecom_f2c_make_type_ (&ffecom_f2c_longint_type_node,
11781 FFECOM_f2cLONGINT,
11782 "longint");
11783 ffecom_f2c_make_type_ (&ffecom_f2c_logical_type_node,
11784 FFECOM_f2cLOGICAL,
11785 "logical");
11786 ffecom_f2c_make_type_ (&ffecom_f2c_flag_type_node,
11787 FFECOM_f2cFLAG,
11788 "flag");
11789 ffecom_f2c_make_type_ (&ffecom_f2c_ftnlen_type_node,
11790 FFECOM_f2cFTNLEN,
11791 "ftnlen");
11792 ffecom_f2c_make_type_ (&ffecom_f2c_ftnint_type_node,
11793 FFECOM_f2cFTNINT,
11794 "ftnint");
11796 ffecom_f2c_ftnlen_zero_node
11797 = convert (ffecom_f2c_ftnlen_type_node, integer_zero_node);
11799 ffecom_f2c_ftnlen_one_node
11800 = convert (ffecom_f2c_ftnlen_type_node, integer_one_node);
11802 ffecom_f2c_ftnlen_two_node = build_int_2 (2, 0);
11803 TREE_TYPE (ffecom_f2c_ftnlen_two_node) = ffecom_integer_type_node;
11805 ffecom_f2c_ptr_to_ftnlen_type_node
11806 = build_pointer_type (ffecom_f2c_ftnlen_type_node);
11808 ffecom_f2c_ptr_to_ftnint_type_node
11809 = build_pointer_type (ffecom_f2c_ftnint_type_node);
11811 ffecom_f2c_ptr_to_integer_type_node
11812 = build_pointer_type (ffecom_f2c_integer_type_node);
11814 ffecom_f2c_ptr_to_real_type_node
11815 = build_pointer_type (ffecom_f2c_real_type_node);
11817 ffecom_float_zero_ = build_real (float_type_node, dconst0);
11818 ffecom_double_zero_ = build_real (double_type_node, dconst0);
11819 ffecom_float_half_ = build_real (float_type_node, dconsthalf);
11820 ffecom_double_half_ = build_real (double_type_node, dconsthalf);
11822 /* Do "extern int xargc;". */
11824 ffecom_tree_xargc_ = build_decl (VAR_DECL,
11825 get_identifier ("f__xargc"),
11826 integer_type_node);
11827 DECL_EXTERNAL (ffecom_tree_xargc_) = 1;
11828 TREE_STATIC (ffecom_tree_xargc_) = 1;
11829 TREE_PUBLIC (ffecom_tree_xargc_) = 1;
11830 ffecom_tree_xargc_ = start_decl (ffecom_tree_xargc_, FALSE);
11831 finish_decl (ffecom_tree_xargc_, NULL_TREE, FALSE);
11833 #if 0 /* This is being fixed, and seems to be working now. */
11834 if ((FLOAT_TYPE_SIZE != 32)
11835 || (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))) != 32))
11837 warning ("configuration: REAL, INTEGER, and LOGICAL are %d bits wide,",
11838 (int) FLOAT_TYPE_SIZE);
11839 warning ("and pointers are %d bits wide, but g77 doesn't yet work",
11840 (int) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))));
11841 warning ("properly unless they all are 32 bits wide");
11842 warning ("Please keep this in mind before you report bugs.");
11844 #endif
11846 #if 0 /* Code in ste.c that would crash has been commented out. */
11847 if (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
11848 < TYPE_PRECISION (string_type_node))
11849 /* I/O will probably crash. */
11850 warning ("configuration: char * holds %d bits, but ftnlen only %d",
11851 TYPE_PRECISION (string_type_node),
11852 TYPE_PRECISION (ffecom_f2c_ftnlen_type_node));
11853 #endif
11855 #if 0 /* ASSIGN-related stuff has been changed to accommodate this. */
11856 if (TYPE_PRECISION (ffecom_integer_type_node)
11857 < TYPE_PRECISION (string_type_node))
11858 /* ASSIGN 10 TO I will crash. */
11859 warning ("configuration: char * holds %d bits, but INTEGER only %d --\n\
11860 ASSIGN statement might fail",
11861 TYPE_PRECISION (string_type_node),
11862 TYPE_PRECISION (ffecom_integer_type_node));
11863 #endif
11866 /* ffecom_init_2 -- Initialize
11868 ffecom_init_2(); */
11870 void
11871 ffecom_init_2 (void)
11873 assert (ffecom_outer_function_decl_ == NULL_TREE);
11874 assert (current_function_decl == NULL_TREE);
11875 assert (ffecom_which_entrypoint_decl_ == NULL_TREE);
11877 ffecom_master_arglist_ = NULL;
11878 ++ffecom_num_fns_;
11879 ffecom_primary_entry_ = NULL;
11880 ffecom_is_altreturning_ = FALSE;
11881 ffecom_func_result_ = NULL_TREE;
11882 ffecom_multi_retval_ = NULL_TREE;
11885 /* ffecom_list_expr -- Transform list of exprs into gcc tree
11887 tree t;
11888 ffebld expr; // FFE opITEM list.
11889 tree = ffecom_list_expr(expr);
11891 List of actual args is transformed into corresponding gcc backend list. */
11893 tree
11894 ffecom_list_expr (ffebld expr)
11896 tree list;
11897 tree *plist = &list;
11898 tree trail = NULL_TREE; /* Append char length args here. */
11899 tree *ptrail = &trail;
11900 tree length;
11902 while (expr != NULL)
11904 tree texpr = ffecom_arg_expr (ffebld_head (expr), &length);
11906 if (texpr == error_mark_node)
11907 return error_mark_node;
11909 *plist = build_tree_list (NULL_TREE, texpr);
11910 plist = &TREE_CHAIN (*plist);
11911 expr = ffebld_trail (expr);
11912 if (length != NULL_TREE)
11914 *ptrail = build_tree_list (NULL_TREE, length);
11915 ptrail = &TREE_CHAIN (*ptrail);
11919 *plist = trail;
11921 return list;
11924 /* ffecom_list_ptr_to_expr -- Transform list of exprs into gcc tree
11926 tree t;
11927 ffebld expr; // FFE opITEM list.
11928 tree = ffecom_list_ptr_to_expr(expr);
11930 List of actual args is transformed into corresponding gcc backend list for
11931 use in calling an external procedure (vs. a statement function). */
11933 tree
11934 ffecom_list_ptr_to_expr (ffebld expr)
11936 tree list;
11937 tree *plist = &list;
11938 tree trail = NULL_TREE; /* Append char length args here. */
11939 tree *ptrail = &trail;
11940 tree length;
11942 while (expr != NULL)
11944 tree texpr = ffecom_arg_ptr_to_expr (ffebld_head (expr), &length);
11946 if (texpr == error_mark_node)
11947 return error_mark_node;
11949 *plist = build_tree_list (NULL_TREE, texpr);
11950 plist = &TREE_CHAIN (*plist);
11951 expr = ffebld_trail (expr);
11952 if (length != NULL_TREE)
11954 *ptrail = build_tree_list (NULL_TREE, length);
11955 ptrail = &TREE_CHAIN (*ptrail);
11959 *plist = trail;
11961 return list;
11964 /* Obtain gcc's LABEL_DECL tree for label. */
11966 tree
11967 ffecom_lookup_label (ffelab label)
11969 tree glabel;
11971 if (ffelab_hook (label) == NULL_TREE)
11973 char labelname[16];
11975 switch (ffelab_type (label))
11977 case FFELAB_typeLOOPEND:
11978 case FFELAB_typeNOTLOOP:
11979 case FFELAB_typeENDIF:
11980 sprintf (labelname, "%" ffelabValue_f "u", ffelab_value (label));
11981 glabel = build_decl (LABEL_DECL, get_identifier (labelname),
11982 void_type_node);
11983 DECL_CONTEXT (glabel) = current_function_decl;
11984 DECL_MODE (glabel) = VOIDmode;
11985 break;
11987 case FFELAB_typeFORMAT:
11988 glabel = build_decl (VAR_DECL,
11989 ffecom_get_invented_identifier
11990 ("__g77_format_%d", (int) ffelab_value (label)),
11991 build_type_variant (build_array_type
11992 (char_type_node,
11993 NULL_TREE),
11994 1, 0));
11995 TREE_CONSTANT (glabel) = 1;
11996 TREE_STATIC (glabel) = 1;
11997 DECL_CONTEXT (glabel) = current_function_decl;
11998 DECL_INITIAL (glabel) = NULL;
11999 make_decl_rtl (glabel, NULL);
12000 expand_decl (glabel);
12002 ffecom_save_tree_forever (glabel);
12004 break;
12006 case FFELAB_typeANY:
12007 glabel = error_mark_node;
12008 break;
12010 default:
12011 assert ("bad label type" == NULL);
12012 glabel = NULL;
12013 break;
12015 ffelab_set_hook (label, glabel);
12017 else
12019 glabel = ffelab_hook (label);
12022 return glabel;
12025 /* Stabilizes the arguments. Don't use this if the lhs and rhs come from
12026 a single source specification (as in the fourth argument of MVBITS).
12027 If the type is NULL_TREE, the type of lhs is used to make the type of
12028 the MODIFY_EXPR. */
12030 tree
12031 ffecom_modify (tree newtype, tree lhs, tree rhs)
12033 if (lhs == error_mark_node || rhs == error_mark_node)
12034 return error_mark_node;
12036 if (newtype == NULL_TREE)
12037 newtype = TREE_TYPE (lhs);
12039 if (TREE_SIDE_EFFECTS (lhs))
12040 lhs = stabilize_reference (lhs);
12042 return ffecom_2s (MODIFY_EXPR, newtype, lhs, rhs);
12045 /* Register source file name. */
12047 void
12048 ffecom_file (const char *name)
12050 ffecom_file_ (name);
12053 /* ffecom_notify_init_storage -- An aggregate storage is now fully init'ed
12055 ffestorag st;
12056 ffecom_notify_init_storage(st);
12058 Gets called when all possible units in an aggregate storage area (a LOCAL
12059 with equivalences or a COMMON) have been initialized. The initialization
12060 info either is in ffestorag_init or, if that is NULL,
12061 ffestorag_accretion:
12063 ffestorag_init may contain an opCONTER or opARRTER. opCONTER may occur
12064 even for an array if the array is one element in length!
12066 ffestorag_accretion will contain an opACCTER. It is much like an
12067 opARRTER except it has an ffebit object in it instead of just a size.
12068 The back end can use the info in the ffebit object, if it wants, to
12069 reduce the amount of actual initialization, but in any case it should
12070 kill the ffebit object when done. Also, set accretion to NULL but
12071 init to a non-NULL value.
12073 After performing initialization, DO NOT set init to NULL, because that'll
12074 tell the front end it is ok for more initialization to happen. Instead,
12075 set init to an opANY expression or some such thing that you can use to
12076 tell that you've already initialized the object.
12078 27-Oct-91 JCB 1.1
12079 Support two-pass FFE. */
12081 void
12082 ffecom_notify_init_storage (ffestorag st)
12084 ffebld init; /* The initialization expression. */
12086 if (ffestorag_init (st) == NULL)
12088 init = ffestorag_accretion (st);
12089 assert (init != NULL);
12090 ffestorag_set_accretion (st, NULL);
12091 ffestorag_set_accretes (st, 0);
12092 ffestorag_set_init (st, init);
12096 /* ffecom_notify_init_symbol -- A symbol is now fully init'ed
12098 ffesymbol s;
12099 ffecom_notify_init_symbol(s);
12101 Gets called when all possible units in a symbol (not placed in COMMON
12102 or involved in EQUIVALENCE, unless it as yet has no ffestorag object)
12103 have been initialized. The initialization info either is in
12104 ffesymbol_init or, if that is NULL, ffesymbol_accretion:
12106 ffesymbol_init may contain an opCONTER or opARRTER. opCONTER may occur
12107 even for an array if the array is one element in length!
12109 ffesymbol_accretion will contain an opACCTER. It is much like an
12110 opARRTER except it has an ffebit object in it instead of just a size.
12111 The back end can use the info in the ffebit object, if it wants, to
12112 reduce the amount of actual initialization, but in any case it should
12113 kill the ffebit object when done. Also, set accretion to NULL but
12114 init to a non-NULL value.
12116 After performing initialization, DO NOT set init to NULL, because that'll
12117 tell the front end it is ok for more initialization to happen. Instead,
12118 set init to an opANY expression or some such thing that you can use to
12119 tell that you've already initialized the object.
12121 27-Oct-91 JCB 1.1
12122 Support two-pass FFE. */
12124 void
12125 ffecom_notify_init_symbol (ffesymbol s)
12127 ffebld init; /* The initialization expression. */
12129 if (ffesymbol_storage (s) == NULL)
12130 return; /* Do nothing until COMMON/EQUIVALENCE
12131 possibilities checked. */
12133 if ((ffesymbol_init (s) == NULL)
12134 && ((init = ffesymbol_accretion (s)) != NULL))
12136 ffesymbol_set_accretion (s, NULL);
12137 ffesymbol_set_accretes (s, 0);
12138 ffesymbol_set_init (s, init);
12142 /* ffecom_notify_primary_entry -- Learn which is the primary entry point
12144 ffesymbol s;
12145 ffecom_notify_primary_entry(s);
12147 Gets called when implicit or explicit PROGRAM statement seen or when
12148 FUNCTION, SUBROUTINE, or BLOCK DATA statement seen, with the primary
12149 global symbol that serves as the entry point. */
12151 void
12152 ffecom_notify_primary_entry (ffesymbol s)
12154 ffecom_primary_entry_ = s;
12155 ffecom_primary_entry_kind_ = ffesymbol_kind (s);
12157 if ((ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
12158 || (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE))
12159 ffecom_primary_entry_is_proc_ = TRUE;
12160 else
12161 ffecom_primary_entry_is_proc_ = FALSE;
12163 if (!ffe_is_silent ())
12165 if (ffecom_primary_entry_kind_ == FFEINFO_kindPROGRAM)
12166 fprintf (stderr, "%s:\n", ffesymbol_text (s));
12167 else
12168 fprintf (stderr, " %s:\n", ffesymbol_text (s));
12171 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
12173 ffebld list;
12174 ffebld arg;
12176 for (list = ffesymbol_dummyargs (s);
12177 list != NULL;
12178 list = ffebld_trail (list))
12180 arg = ffebld_head (list);
12181 if (ffebld_op (arg) == FFEBLD_opSTAR)
12183 ffecom_is_altreturning_ = TRUE;
12184 break;
12190 FILE *
12191 ffecom_open_include (char *name, ffewhereLine l, ffewhereColumn c)
12193 return ffecom_open_include_ (name, l, c);
12196 /* ffecom_ptr_to_expr -- Transform expr into gcc tree with & in front
12198 tree t;
12199 ffebld expr; // FFE expression.
12200 tree = ffecom_ptr_to_expr(expr);
12202 Like ffecom_expr, but sticks address-of in front of most things. */
12204 tree
12205 ffecom_ptr_to_expr (ffebld expr)
12207 tree item;
12208 ffeinfoBasictype bt;
12209 ffeinfoKindtype kt;
12210 ffesymbol s;
12212 assert (expr != NULL);
12214 switch (ffebld_op (expr))
12216 case FFEBLD_opSYMTER:
12217 s = ffebld_symter (expr);
12218 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
12220 ffecomGfrt ix;
12222 ix = ffeintrin_gfrt_indirect (ffebld_symter_implementation (expr));
12223 assert (ix != FFECOM_gfrt);
12224 if ((item = ffecom_gfrt_[ix]) == NULL_TREE)
12226 ffecom_make_gfrt_ (ix);
12227 item = ffecom_gfrt_[ix];
12230 else
12232 item = ffesymbol_hook (s).decl_tree;
12233 if (item == NULL_TREE)
12235 s = ffecom_sym_transform_ (s);
12236 item = ffesymbol_hook (s).decl_tree;
12239 assert (item != NULL);
12240 if (item == error_mark_node)
12241 return item;
12242 if (!ffesymbol_hook (s).addr)
12243 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12244 item);
12245 return item;
12247 case FFEBLD_opARRAYREF:
12248 return ffecom_arrayref_ (NULL_TREE, expr, 1);
12250 case FFEBLD_opCONTER:
12252 bt = ffeinfo_basictype (ffebld_info (expr));
12253 kt = ffeinfo_kindtype (ffebld_info (expr));
12255 item = ffecom_constantunion (&ffebld_constant_union
12256 (ffebld_conter (expr)), bt, kt,
12257 ffecom_tree_type[bt][kt]);
12258 if (item == error_mark_node)
12259 return error_mark_node;
12260 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12261 item);
12262 return item;
12264 case FFEBLD_opANY:
12265 return error_mark_node;
12267 default:
12268 bt = ffeinfo_basictype (ffebld_info (expr));
12269 kt = ffeinfo_kindtype (ffebld_info (expr));
12271 item = ffecom_expr (expr);
12272 if (item == error_mark_node)
12273 return error_mark_node;
12275 /* The back end currently optimizes a bit too zealously for us, in that
12276 we fail JCB001 if the following block of code is omitted. It checks
12277 to see if the transformed expression is a symbol or array reference,
12278 and encloses it in a SAVE_EXPR if that is the case. */
12280 STRIP_NOPS (item);
12281 if ((TREE_CODE (item) == VAR_DECL)
12282 || (TREE_CODE (item) == PARM_DECL)
12283 || (TREE_CODE (item) == RESULT_DECL)
12284 || (TREE_CODE (item) == INDIRECT_REF)
12285 || (TREE_CODE (item) == ARRAY_REF)
12286 || (TREE_CODE (item) == COMPONENT_REF)
12287 #ifdef OFFSET_REF
12288 || (TREE_CODE (item) == OFFSET_REF)
12289 #endif
12290 || (TREE_CODE (item) == BUFFER_REF)
12291 || (TREE_CODE (item) == REALPART_EXPR)
12292 || (TREE_CODE (item) == IMAGPART_EXPR))
12294 item = ffecom_save_tree (item);
12297 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12298 item);
12299 return item;
12302 assert ("fall-through error" == NULL);
12303 return error_mark_node;
12306 /* Obtain a temp var with given data type.
12308 size is FFETARGET_charactersizeNONE for a non-CHARACTER type
12309 or >= 0 for a CHARACTER type.
12311 elements is -1 for a scalar or > 0 for an array of type. */
12313 tree
12314 ffecom_make_tempvar (const char *commentary, tree type,
12315 ffetargetCharacterSize size, int elements)
12317 tree t;
12318 static int mynumber;
12320 assert (current_binding_level->prep_state < 2);
12322 if (type == error_mark_node)
12323 return error_mark_node;
12325 if (size != FFETARGET_charactersizeNONE)
12326 type = build_array_type (type,
12327 build_range_type (ffecom_f2c_ftnlen_type_node,
12328 ffecom_f2c_ftnlen_one_node,
12329 build_int_2 (size, 0)));
12330 if (elements != -1)
12331 type = build_array_type (type,
12332 build_range_type (integer_type_node,
12333 integer_zero_node,
12334 build_int_2 (elements - 1,
12335 0)));
12336 t = build_decl (VAR_DECL,
12337 ffecom_get_invented_identifier ("__g77_%s_%d",
12338 commentary,
12339 mynumber++),
12340 type);
12342 t = start_decl (t, FALSE);
12343 finish_decl (t, NULL_TREE, FALSE);
12345 return t;
12348 /* Prepare argument pointer to expression.
12350 Like ffecom_prepare_expr, except for expressions to be evaluated
12351 via ffecom_arg_ptr_to_expr. */
12353 void
12354 ffecom_prepare_arg_ptr_to_expr (ffebld expr)
12356 /* ~~For now, it seems to be the same thing. */
12357 ffecom_prepare_expr (expr);
12358 return;
12361 /* End of preparations. */
12363 bool
12364 ffecom_prepare_end (void)
12366 int prep_state = current_binding_level->prep_state;
12368 assert (prep_state < 2);
12369 current_binding_level->prep_state = 2;
12371 return (prep_state == 1) ? TRUE : FALSE;
12374 /* Prepare expression.
12376 This is called before any code is generated for the current block.
12377 It scans the expression, declares any temporaries that might be needed
12378 during evaluation of the expression, and stores those temporaries in
12379 the appropriate "hook" fields of the expression. `dest', if not NULL,
12380 specifies the destination that ffecom_expr_ will see, in case that
12381 helps avoid generating unused temporaries.
12383 ~~Improve to avoid allocating unused temporaries by taking `dest'
12384 into account vis-a-vis aliasing requirements of complex/character
12385 functions. */
12387 void
12388 ffecom_prepare_expr_ (ffebld expr, ffebld dest UNUSED)
12390 ffeinfoBasictype bt;
12391 ffeinfoKindtype kt;
12392 ffetargetCharacterSize sz;
12393 tree tempvar = NULL_TREE;
12395 assert (current_binding_level->prep_state < 2);
12397 if (! expr)
12398 return;
12400 bt = ffeinfo_basictype (ffebld_info (expr));
12401 kt = ffeinfo_kindtype (ffebld_info (expr));
12402 sz = ffeinfo_size (ffebld_info (expr));
12404 /* Generate whatever temporaries are needed to represent the result
12405 of the expression. */
12407 if (bt == FFEINFO_basictypeCHARACTER)
12409 while (ffebld_op (expr) == FFEBLD_opPAREN)
12410 expr = ffebld_left (expr);
12413 switch (ffebld_op (expr))
12415 default:
12416 /* Don't make temps for SYMTER, CONTER, etc. */
12417 if (ffebld_arity (expr) == 0)
12418 break;
12420 switch (bt)
12422 case FFEINFO_basictypeCOMPLEX:
12423 if (ffebld_op (expr) == FFEBLD_opFUNCREF)
12425 ffesymbol s;
12427 if (ffebld_op (ffebld_left (expr)) != FFEBLD_opSYMTER)
12428 break;
12430 s = ffebld_symter (ffebld_left (expr));
12431 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT
12432 || (ffesymbol_where (s) != FFEINFO_whereINTRINSIC
12433 && ! ffesymbol_is_f2c (s))
12434 || (ffesymbol_where (s) == FFEINFO_whereINTRINSIC
12435 && ! ffe_is_f2c_library ()))
12436 break;
12438 else if (ffebld_op (expr) == FFEBLD_opPOWER)
12440 /* Requires special treatment. There's no POW_CC function
12441 in libg2c, so POW_ZZ is used, which means we always
12442 need a double-complex temp, not a single-complex. */
12443 kt = FFEINFO_kindtypeREAL2;
12445 else if (ffebld_op (expr) != FFEBLD_opDIVIDE)
12446 /* The other ops don't need temps for complex operands. */
12447 break;
12449 /* ~~~Avoid making temps for some intrinsics, such as AIMAG(C),
12450 REAL(C). See 19990325-0.f, routine `check', for cases. */
12451 tempvar = ffecom_make_tempvar ("complex",
12452 ffecom_tree_type
12453 [FFEINFO_basictypeCOMPLEX][kt],
12454 FFETARGET_charactersizeNONE,
12455 -1);
12456 break;
12458 case FFEINFO_basictypeCHARACTER:
12459 if (ffebld_op (expr) != FFEBLD_opFUNCREF)
12460 break;
12462 if (sz == FFETARGET_charactersizeNONE)
12463 /* ~~Kludge alert! This should someday be fixed. */
12464 sz = 24;
12466 tempvar = ffecom_make_tempvar ("char", char_type_node, sz, -1);
12467 break;
12469 default:
12470 break;
12472 break;
12474 case FFEBLD_opCONCATENATE:
12476 /* This gets special handling, because only one set of temps
12477 is needed for a tree of these -- the tree is treated as
12478 a flattened list of concatenations when generating code. */
12480 ffecomConcatList_ catlist;
12481 tree ltmp, itmp, result;
12482 int count;
12483 int i;
12485 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
12486 count = ffecom_concat_list_count_ (catlist);
12488 if (count >= 2)
12490 ltmp
12491 = ffecom_make_tempvar ("concat_len",
12492 ffecom_f2c_ftnlen_type_node,
12493 FFETARGET_charactersizeNONE, count);
12494 itmp
12495 = ffecom_make_tempvar ("concat_item",
12496 ffecom_f2c_address_type_node,
12497 FFETARGET_charactersizeNONE, count);
12498 result
12499 = ffecom_make_tempvar ("concat_res",
12500 char_type_node,
12501 ffecom_concat_list_maxlen_ (catlist),
12502 -1);
12504 tempvar = make_tree_vec (3);
12505 TREE_VEC_ELT (tempvar, 0) = ltmp;
12506 TREE_VEC_ELT (tempvar, 1) = itmp;
12507 TREE_VEC_ELT (tempvar, 2) = result;
12510 for (i = 0; i < count; ++i)
12511 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist,
12512 i));
12514 ffecom_concat_list_kill_ (catlist);
12516 if (tempvar)
12518 ffebld_nonter_set_hook (expr, tempvar);
12519 current_binding_level->prep_state = 1;
12522 return;
12524 case FFEBLD_opCONVERT:
12525 if (bt == FFEINFO_basictypeCHARACTER
12526 && ((ffebld_size_known (ffebld_left (expr))
12527 == FFETARGET_charactersizeNONE)
12528 || (ffebld_size_known (ffebld_left (expr)) >= sz)))
12529 tempvar = ffecom_make_tempvar ("convert", char_type_node, sz, -1);
12530 break;
12533 if (tempvar)
12535 ffebld_nonter_set_hook (expr, tempvar);
12536 current_binding_level->prep_state = 1;
12539 /* Prepare subexpressions for this expr. */
12541 switch (ffebld_op (expr))
12543 case FFEBLD_opPERCENT_LOC:
12544 ffecom_prepare_ptr_to_expr (ffebld_left (expr));
12545 break;
12547 case FFEBLD_opPERCENT_VAL:
12548 case FFEBLD_opPERCENT_REF:
12549 ffecom_prepare_expr (ffebld_left (expr));
12550 break;
12552 case FFEBLD_opPERCENT_DESCR:
12553 ffecom_prepare_arg_ptr_to_expr (ffebld_left (expr));
12554 break;
12556 case FFEBLD_opITEM:
12558 ffebld item;
12560 for (item = expr;
12561 item != NULL;
12562 item = ffebld_trail (item))
12563 if (ffebld_head (item) != NULL)
12564 ffecom_prepare_expr (ffebld_head (item));
12566 break;
12568 default:
12569 /* Need to handle character conversion specially. */
12570 switch (ffebld_arity (expr))
12572 case 2:
12573 ffecom_prepare_expr (ffebld_left (expr));
12574 ffecom_prepare_expr (ffebld_right (expr));
12575 break;
12577 case 1:
12578 ffecom_prepare_expr (ffebld_left (expr));
12579 break;
12581 default:
12582 break;
12586 return;
12589 /* Prepare expression for reading and writing.
12591 Like ffecom_prepare_expr, except for expressions to be evaluated
12592 via ffecom_expr_rw. */
12594 void
12595 ffecom_prepare_expr_rw (tree type, ffebld expr)
12597 /* This is all we support for now. */
12598 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
12600 /* ~~For now, it seems to be the same thing. */
12601 ffecom_prepare_expr (expr);
12602 return;
12605 /* Prepare expression for writing.
12607 Like ffecom_prepare_expr, except for expressions to be evaluated
12608 via ffecom_expr_w. */
12610 void
12611 ffecom_prepare_expr_w (tree type, ffebld expr)
12613 /* This is all we support for now. */
12614 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
12616 /* ~~For now, it seems to be the same thing. */
12617 ffecom_prepare_expr (expr);
12618 return;
12621 /* Prepare expression for returning.
12623 Like ffecom_prepare_expr, except for expressions to be evaluated
12624 via ffecom_return_expr. */
12626 void
12627 ffecom_prepare_return_expr (ffebld expr)
12629 assert (current_binding_level->prep_state < 2);
12631 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE
12632 && ffecom_is_altreturning_
12633 && expr != NULL)
12634 ffecom_prepare_expr (expr);
12637 /* Prepare pointer to expression.
12639 Like ffecom_prepare_expr, except for expressions to be evaluated
12640 via ffecom_ptr_to_expr. */
12642 void
12643 ffecom_prepare_ptr_to_expr (ffebld expr)
12645 /* ~~For now, it seems to be the same thing. */
12646 ffecom_prepare_expr (expr);
12647 return;
12650 /* Transform expression into constant pointer-to-expression tree.
12652 If the expression can be transformed into a pointer-to-expression tree
12653 that is constant, that is done, and the tree returned. Else NULL_TREE
12654 is returned.
12656 That way, a caller can attempt to provide compile-time initialization
12657 of a variable and, if that fails, *then* choose to start a new block
12658 and resort to using temporaries, as appropriate. */
12660 tree
12661 ffecom_ptr_to_const_expr (ffebld expr)
12663 if (! expr)
12664 return integer_zero_node;
12666 if (ffebld_op (expr) == FFEBLD_opANY)
12667 return error_mark_node;
12669 if (ffebld_arity (expr) == 0
12670 && (ffebld_op (expr) != FFEBLD_opSYMTER
12671 || ffebld_where (expr) == FFEINFO_whereCOMMON
12672 || ffebld_where (expr) == FFEINFO_whereGLOBAL
12673 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
12675 tree t;
12677 t = ffecom_ptr_to_expr (expr);
12678 assert (TREE_CONSTANT (t));
12679 return t;
12682 return NULL_TREE;
12685 /* ffecom_return_expr -- Returns return-value expr given alt return expr
12687 tree rtn; // NULL_TREE means use expand_null_return()
12688 ffebld expr; // NULL if no alt return expr to RETURN stmt
12689 rtn = ffecom_return_expr(expr);
12691 Based on the program unit type and other info (like return function
12692 type, return master function type when alternate ENTRY points,
12693 whether subroutine has any alternate RETURN points, etc), returns the
12694 appropriate expression to be returned to the caller, or NULL_TREE
12695 meaning no return value or the caller expects it to be returned somewhere
12696 else (which is handled by other parts of this module). */
12698 tree
12699 ffecom_return_expr (ffebld expr)
12701 tree rtn;
12703 switch (ffecom_primary_entry_kind_)
12705 case FFEINFO_kindPROGRAM:
12706 case FFEINFO_kindBLOCKDATA:
12707 rtn = NULL_TREE;
12708 break;
12710 case FFEINFO_kindSUBROUTINE:
12711 if (!ffecom_is_altreturning_)
12712 rtn = NULL_TREE; /* No alt returns, never an expr. */
12713 else if (expr == NULL)
12714 rtn = integer_zero_node;
12715 else
12716 rtn = ffecom_expr (expr);
12717 break;
12719 case FFEINFO_kindFUNCTION:
12720 if ((ffecom_multi_retval_ != NULL_TREE)
12721 || (ffesymbol_basictype (ffecom_primary_entry_)
12722 == FFEINFO_basictypeCHARACTER)
12723 || ((ffesymbol_basictype (ffecom_primary_entry_)
12724 == FFEINFO_basictypeCOMPLEX)
12725 && (ffecom_num_entrypoints_ == 0)
12726 && ffesymbol_is_f2c (ffecom_primary_entry_)))
12727 { /* Value is returned by direct assignment
12728 into (implicit) dummy. */
12729 rtn = NULL_TREE;
12730 break;
12732 rtn = ffecom_func_result_;
12733 #if 0
12734 /* Spurious error if RETURN happens before first reference! So elide
12735 this code. In particular, for debugging registry, rtn should always
12736 be non-null after all, but TREE_USED won't be set until we encounter
12737 a reference in the code. Perfectly okay (but weird) code that,
12738 e.g., has "GOTO 20;10 RETURN;20 RTN=0;GOTO 10", would result in
12739 this diagnostic for no reason. Have people use -O -Wuninitialized
12740 and leave it to the back end to find obviously weird cases. */
12742 /* Used to "assert(rtn != NULL_TREE);" here, but it's kind of a valid
12743 situation; if the return value has never been referenced, it won't
12744 have a tree under 2pass mode. */
12745 if ((rtn == NULL_TREE)
12746 || !TREE_USED (rtn))
12748 ffebad_start (FFEBAD_RETURN_VALUE_UNSET);
12749 ffebad_here (0, ffesymbol_where_line (ffecom_primary_entry_),
12750 ffesymbol_where_column (ffecom_primary_entry_));
12751 ffebad_string (ffesymbol_text (ffesymbol_funcresult
12752 (ffecom_primary_entry_)));
12753 ffebad_finish ();
12755 #endif
12756 break;
12758 default:
12759 assert ("bad unit kind" == NULL);
12760 case FFEINFO_kindANY:
12761 rtn = error_mark_node;
12762 break;
12765 return rtn;
12768 /* Do save_expr only if tree is not error_mark_node. */
12770 tree
12771 ffecom_save_tree (tree t)
12773 return save_expr (t);
12776 /* Start a compound statement (block). */
12778 void
12779 ffecom_start_compstmt (void)
12781 bison_rule_pushlevel_ ();
12784 /* Public entry point for front end to access start_decl. */
12786 tree
12787 ffecom_start_decl (tree decl, bool is_initialized)
12789 DECL_INITIAL (decl) = is_initialized ? error_mark_node : NULL_TREE;
12790 return start_decl (decl, FALSE);
12793 /* ffecom_sym_commit -- Symbol's state being committed to reality
12795 ffesymbol s;
12796 ffecom_sym_commit(s);
12798 Does whatever the backend needs when a symbol is committed after having
12799 been backtrackable for a period of time. */
12801 void
12802 ffecom_sym_commit (ffesymbol s UNUSED)
12804 assert (!ffesymbol_retractable ());
12807 /* ffecom_sym_end_transition -- Perform end transition on all symbols
12809 ffecom_sym_end_transition();
12811 Does backend-specific stuff and also calls ffest_sym_end_transition
12812 to do the necessary FFE stuff.
12814 Backtracking is never enabled when this fn is called, so don't worry
12815 about it. */
12817 ffesymbol
12818 ffecom_sym_end_transition (ffesymbol s)
12820 ffestorag st;
12822 assert (!ffesymbol_retractable ());
12824 s = ffest_sym_end_transition (s);
12826 if ((ffesymbol_kind (s) == FFEINFO_kindBLOCKDATA)
12827 && (ffesymbol_where (s) == FFEINFO_whereGLOBAL))
12829 ffecom_list_blockdata_
12830 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
12831 FFEINTRIN_specNONE,
12832 FFEINTRIN_impNONE),
12833 ffecom_list_blockdata_);
12836 /* This is where we finally notice that a symbol has partial initialization
12837 and finalize it. */
12839 if (ffesymbol_accretion (s) != NULL)
12841 assert (ffesymbol_init (s) == NULL);
12842 ffecom_notify_init_symbol (s);
12844 else if (((st = ffesymbol_storage (s)) != NULL)
12845 && ((st = ffestorag_parent (st)) != NULL)
12846 && (ffestorag_accretion (st) != NULL))
12848 assert (ffestorag_init (st) == NULL);
12849 ffecom_notify_init_storage (st);
12852 if ((ffesymbol_kind (s) == FFEINFO_kindCOMMON)
12853 && (ffesymbol_where (s) == FFEINFO_whereLOCAL)
12854 && (ffesymbol_storage (s) != NULL))
12856 ffecom_list_common_
12857 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
12858 FFEINTRIN_specNONE,
12859 FFEINTRIN_impNONE),
12860 ffecom_list_common_);
12863 return s;
12866 /* ffecom_sym_exec_transition -- Perform exec transition on all symbols
12868 ffecom_sym_exec_transition();
12870 Does backend-specific stuff and also calls ffest_sym_exec_transition
12871 to do the necessary FFE stuff.
12873 See the long-winded description in ffecom_sym_learned for info
12874 on handling the situation where backtracking is inhibited. */
12876 ffesymbol
12877 ffecom_sym_exec_transition (ffesymbol s)
12879 s = ffest_sym_exec_transition (s);
12881 return s;
12884 /* ffecom_sym_learned -- Initial or more info gained on symbol after exec
12886 ffesymbol s;
12887 s = ffecom_sym_learned(s);
12889 Called when a new symbol is seen after the exec transition or when more
12890 info (perhaps) is gained for an UNCERTAIN symbol. The symbol state when
12891 it arrives here is that all its latest info is updated already, so its
12892 state may be UNCERTAIN or UNDERSTOOD, it might already have the hook
12893 field filled in if its gone through here or exec_transition first, and
12894 so on.
12896 The backend probably wants to check ffesymbol_retractable() to see if
12897 backtracking is in effect. If so, the FFE's changes to the symbol may
12898 be retracted (undone) or committed (ratified), at which time the
12899 appropriate ffecom_sym_retract or _commit function will be called
12900 for that function.
12902 If the backend has its own backtracking mechanism, great, use it so that
12903 committal is a simple operation. Though it doesn't make much difference,
12904 I suppose: the reason for tentative symbol evolution in the FFE is to
12905 enable error detection in weird incorrect statements early and to disable
12906 incorrect error detection on a correct statement. The backend is not
12907 likely to introduce any information that'll get involved in these
12908 considerations, so it is probably just fine that the implementation
12909 model for this fn and for _exec_transition is to not do anything
12910 (besides the required FFE stuff) if ffesymbol_retractable() returns TRUE
12911 and instead wait until ffecom_sym_commit is called (which it never
12912 will be as long as we're using ambiguity-detecting statement analysis in
12913 the FFE, which we are initially to shake out the code, but don't depend
12914 on this), otherwise go ahead and do whatever is needed.
12916 In essence, then, when this fn and _exec_transition get called while
12917 backtracking is enabled, a general mechanism would be to flag which (or
12918 both) of these were called (and in what order? neat question as to what
12919 might happen that I'm too lame to think through right now) and then when
12920 _commit is called reproduce the original calling sequence, if any, for
12921 the two fns (at which point backtracking will, of course, be disabled). */
12923 ffesymbol
12924 ffecom_sym_learned (ffesymbol s)
12926 ffestorag_exec_layout (s);
12928 return s;
12931 /* ffecom_sym_retract -- Symbol's state being retracted from reality
12933 ffesymbol s;
12934 ffecom_sym_retract(s);
12936 Does whatever the backend needs when a symbol is retracted after having
12937 been backtrackable for a period of time. */
12939 void
12940 ffecom_sym_retract (ffesymbol s UNUSED)
12942 assert (!ffesymbol_retractable ());
12944 #if 0 /* GCC doesn't commit any backtrackable sins,
12945 so nothing needed here. */
12946 switch (ffesymbol_hook (s).state)
12948 case 0: /* nothing happened yet. */
12949 break;
12951 case 1: /* exec transition happened. */
12952 break;
12954 case 2: /* learned happened. */
12955 break;
12957 case 3: /* learned then exec. */
12958 break;
12960 case 4: /* exec then learned. */
12961 break;
12963 default:
12964 assert ("bad hook state" == NULL);
12965 break;
12967 #endif
12970 /* Create temporary gcc label. */
12972 tree
12973 ffecom_temp_label (void)
12975 tree glabel;
12976 static int mynumber = 0;
12978 glabel = build_decl (LABEL_DECL,
12979 ffecom_get_invented_identifier ("__g77_label_%d",
12980 mynumber++),
12981 void_type_node);
12982 DECL_CONTEXT (glabel) = current_function_decl;
12983 DECL_MODE (glabel) = VOIDmode;
12985 return glabel;
12988 /* Return an expression that is usable as an arg in a conditional context
12989 (IF, DO WHILE, .NOT., and so on).
12991 Use the one provided for the back end as of >2.6.0. */
12993 tree
12994 ffecom_truth_value (tree expr)
12996 return ffe_truthvalue_conversion (expr);
12999 /* Return the inversion of a truth value (the inversion of what
13000 ffecom_truth_value builds).
13002 Apparently invert_truthvalue, which is properly in the back end, is
13003 enough for now, so just use it. */
13005 tree
13006 ffecom_truth_value_invert (tree expr)
13008 return invert_truthvalue (ffecom_truth_value (expr));
13011 /* Return the tree that is the type of the expression, as would be
13012 returned in TREE_TYPE(ffecom_expr(expr)), without otherwise
13013 transforming the expression, generating temporaries, etc. */
13015 tree
13016 ffecom_type_expr (ffebld expr)
13018 ffeinfoBasictype bt;
13019 ffeinfoKindtype kt;
13020 tree tree_type;
13022 assert (expr != NULL);
13024 bt = ffeinfo_basictype (ffebld_info (expr));
13025 kt = ffeinfo_kindtype (ffebld_info (expr));
13026 tree_type = ffecom_tree_type[bt][kt];
13028 switch (ffebld_op (expr))
13030 case FFEBLD_opCONTER:
13031 case FFEBLD_opSYMTER:
13032 case FFEBLD_opARRAYREF:
13033 case FFEBLD_opUPLUS:
13034 case FFEBLD_opPAREN:
13035 case FFEBLD_opUMINUS:
13036 case FFEBLD_opADD:
13037 case FFEBLD_opSUBTRACT:
13038 case FFEBLD_opMULTIPLY:
13039 case FFEBLD_opDIVIDE:
13040 case FFEBLD_opPOWER:
13041 case FFEBLD_opNOT:
13042 case FFEBLD_opFUNCREF:
13043 case FFEBLD_opSUBRREF:
13044 case FFEBLD_opAND:
13045 case FFEBLD_opOR:
13046 case FFEBLD_opXOR:
13047 case FFEBLD_opNEQV:
13048 case FFEBLD_opEQV:
13049 case FFEBLD_opCONVERT:
13050 case FFEBLD_opLT:
13051 case FFEBLD_opLE:
13052 case FFEBLD_opEQ:
13053 case FFEBLD_opNE:
13054 case FFEBLD_opGT:
13055 case FFEBLD_opGE:
13056 case FFEBLD_opPERCENT_LOC:
13057 return tree_type;
13059 case FFEBLD_opACCTER:
13060 case FFEBLD_opARRTER:
13061 case FFEBLD_opITEM:
13062 case FFEBLD_opSTAR:
13063 case FFEBLD_opBOUNDS:
13064 case FFEBLD_opREPEAT:
13065 case FFEBLD_opLABTER:
13066 case FFEBLD_opLABTOK:
13067 case FFEBLD_opIMPDO:
13068 case FFEBLD_opCONCATENATE:
13069 case FFEBLD_opSUBSTR:
13070 default:
13071 assert ("bad op for ffecom_type_expr" == NULL);
13072 /* Fall through. */
13073 case FFEBLD_opANY:
13074 return error_mark_node;
13078 /* Return PARM_DECL for arg#1 of master fn containing alternate ENTRY points
13080 If the PARM_DECL already exists, return it, else create it. It's an
13081 integer_type_node argument for the master function that implements a
13082 subroutine or function with more than one entrypoint and is bound at
13083 run time with the entrypoint number (0 for SUBROUTINE/FUNCTION, 1 for
13084 first ENTRY statement, and so on). */
13086 tree
13087 ffecom_which_entrypoint_decl (void)
13089 assert (ffecom_which_entrypoint_decl_ != NULL_TREE);
13091 return ffecom_which_entrypoint_decl_;
13094 /* The following sections consists of private and public functions
13095 that have the same names and perform roughly the same functions
13096 as counterparts in the C front end. Changes in the C front end
13097 might affect how things should be done here. Only functions
13098 needed by the back end should be public here; the rest should
13099 be private (static in the C sense). Functions needed by other
13100 g77 front-end modules should be accessed by them via public
13101 ffecom_* names, which should themselves call private versions
13102 in this section so the private versions are easy to recognize
13103 when upgrading to a new gcc and finding interesting changes
13104 in the front end.
13106 Functions named after rule "foo:" in c-parse.y are named
13107 "bison_rule_foo_" so they are easy to find. */
13109 static void
13110 bison_rule_pushlevel_ (void)
13112 emit_line_note (input_location);
13113 pushlevel (0);
13114 clear_last_expr ();
13115 expand_start_bindings (0);
13118 static tree
13119 bison_rule_compstmt_ (void)
13121 tree t;
13122 int keep = kept_level_p ();
13124 /* Make the temps go away. */
13125 if (! keep)
13126 current_binding_level->names = NULL_TREE;
13128 emit_line_note (input_location);
13129 expand_end_bindings (getdecls (), keep, 0);
13130 t = poplevel (keep, 1, 0);
13132 return t;
13135 /* Return a definition for a builtin function named NAME and whose data type
13136 is TYPE. TYPE should be a function type with argument types.
13137 FUNCTION_CODE tells later passes how to compile calls to this function.
13138 See tree.h for its possible values.
13140 If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
13141 the name to be called if we can't opencode the function. If
13142 ATTRS is nonzero, use that for the function's attribute list. */
13144 tree
13145 builtin_function (const char *name, tree type, int function_code,
13146 enum built_in_class class, const char *library_name,
13147 tree attrs ATTRIBUTE_UNUSED)
13149 tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
13150 DECL_EXTERNAL (decl) = 1;
13151 TREE_PUBLIC (decl) = 1;
13152 if (library_name)
13153 SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
13154 make_decl_rtl (decl, NULL);
13155 pushdecl (decl);
13156 DECL_BUILT_IN_CLASS (decl) = class;
13157 DECL_FUNCTION_CODE (decl) = function_code;
13159 return decl;
13162 /* Handle when a new declaration NEWDECL
13163 has the same name as an old one OLDDECL
13164 in the same binding contour.
13165 Prints an error message if appropriate.
13167 If safely possible, alter OLDDECL to look like NEWDECL, and return 1.
13168 Otherwise, return 0. */
13170 static int
13171 duplicate_decls (tree newdecl, tree olddecl)
13173 int types_match = 1;
13174 int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
13175 && DECL_INITIAL (newdecl) != 0);
13176 tree oldtype = TREE_TYPE (olddecl);
13177 tree newtype = TREE_TYPE (newdecl);
13179 if (olddecl == newdecl)
13180 return 1;
13182 if (TREE_CODE (newtype) == ERROR_MARK
13183 || TREE_CODE (oldtype) == ERROR_MARK)
13184 types_match = 0;
13186 /* New decl is completely inconsistent with the old one =>
13187 tell caller to replace the old one.
13188 This is always an error except in the case of shadowing a builtin. */
13189 if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
13190 return 0;
13192 /* For real parm decl following a forward decl,
13193 return 1 so old decl will be reused. */
13194 if (types_match && TREE_CODE (newdecl) == PARM_DECL
13195 && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
13196 return 1;
13198 /* The new declaration is the same kind of object as the old one.
13199 The declarations may partially match. Print warnings if they don't
13200 match enough. Ultimately, copy most of the information from the new
13201 decl to the old one, and keep using the old one. */
13203 if (TREE_CODE (olddecl) == FUNCTION_DECL
13204 && DECL_BUILT_IN (olddecl))
13206 /* A function declaration for a built-in function. */
13207 if (!TREE_PUBLIC (newdecl))
13208 return 0;
13209 else if (!types_match)
13211 /* Accept the return type of the new declaration if same modes. */
13212 tree oldreturntype = TREE_TYPE (TREE_TYPE (olddecl));
13213 tree newreturntype = TREE_TYPE (TREE_TYPE (newdecl));
13215 if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
13217 /* Function types may be shared, so we can't just modify
13218 the return type of olddecl's function type. */
13219 tree newtype
13220 = build_function_type (newreturntype,
13221 TYPE_ARG_TYPES (TREE_TYPE (olddecl)));
13223 types_match = 1;
13224 if (types_match)
13225 TREE_TYPE (olddecl) = newtype;
13228 if (!types_match)
13229 return 0;
13231 else if (TREE_CODE (olddecl) == FUNCTION_DECL
13232 && DECL_SOURCE_LINE (olddecl) == 0)
13234 /* A function declaration for a predeclared function
13235 that isn't actually built in. */
13236 if (!TREE_PUBLIC (newdecl))
13237 return 0;
13238 else if (!types_match)
13240 /* If the types don't match, preserve volatility indication.
13241 Later on, we will discard everything else about the
13242 default declaration. */
13243 TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
13247 /* Copy all the DECL_... slots specified in the new decl
13248 except for any that we copy here from the old type.
13250 Past this point, we don't change OLDTYPE and NEWTYPE
13251 even if we change the types of NEWDECL and OLDDECL. */
13253 if (types_match)
13255 /* Merge the data types specified in the two decls. */
13256 if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
13257 TREE_TYPE (newdecl)
13258 = TREE_TYPE (olddecl)
13259 = TREE_TYPE (newdecl);
13261 /* Lay the type out, unless already done. */
13262 if (oldtype != TREE_TYPE (newdecl))
13264 if (TREE_TYPE (newdecl) != error_mark_node)
13265 layout_type (TREE_TYPE (newdecl));
13266 if (TREE_CODE (newdecl) != FUNCTION_DECL
13267 && TREE_CODE (newdecl) != TYPE_DECL
13268 && TREE_CODE (newdecl) != CONST_DECL)
13269 layout_decl (newdecl, 0);
13271 else
13273 /* Since the type is OLDDECL's, make OLDDECL's size go with. */
13274 DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
13275 DECL_SIZE_UNIT (newdecl) = DECL_SIZE_UNIT (olddecl);
13276 if (TREE_CODE (olddecl) != FUNCTION_DECL)
13277 if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
13279 DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
13280 DECL_USER_ALIGN (newdecl) |= DECL_USER_ALIGN (olddecl);
13284 /* Keep the old rtl since we can safely use it. */
13285 COPY_DECL_RTL (olddecl, newdecl);
13287 /* Merge the type qualifiers. */
13288 if (TREE_READONLY (newdecl))
13289 TREE_READONLY (olddecl) = 1;
13290 if (TREE_THIS_VOLATILE (newdecl))
13292 TREE_THIS_VOLATILE (olddecl) = 1;
13293 if (TREE_CODE (newdecl) == VAR_DECL)
13294 make_var_volatile (newdecl);
13297 /* Keep source location of definition rather than declaration.
13298 Likewise, keep decl at outer scope. */
13299 if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
13300 || (DECL_CONTEXT (newdecl) != 0 && DECL_CONTEXT (olddecl) == 0))
13302 DECL_SOURCE_LOCATION (newdecl) = DECL_SOURCE_LOCATION (olddecl);
13304 if (DECL_CONTEXT (olddecl) == 0
13305 && TREE_CODE (newdecl) != FUNCTION_DECL)
13306 DECL_CONTEXT (newdecl) = 0;
13309 /* Merge the unused-warning information. */
13310 if (DECL_IN_SYSTEM_HEADER (olddecl))
13311 DECL_IN_SYSTEM_HEADER (newdecl) = 1;
13312 else if (DECL_IN_SYSTEM_HEADER (newdecl))
13313 DECL_IN_SYSTEM_HEADER (olddecl) = 1;
13315 /* Merge the initialization information. */
13316 if (DECL_INITIAL (newdecl) == 0)
13317 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
13319 /* Merge the section attribute.
13320 We want to issue an error if the sections conflict but that must be
13321 done later in decl_attributes since we are called before attributes
13322 are assigned. */
13323 if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
13324 DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
13326 /* Copy the assembler name. */
13327 COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
13329 if (TREE_CODE (newdecl) == FUNCTION_DECL)
13331 DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
13332 DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
13333 TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
13334 TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
13335 DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
13336 DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl);
13339 /* If cannot merge, then use the new type and qualifiers,
13340 and don't preserve the old rtl. */
13341 else
13343 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
13344 TREE_READONLY (olddecl) = TREE_READONLY (newdecl);
13345 TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl);
13346 TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl);
13349 /* Merge the storage class information. */
13350 /* For functions, static overrides non-static. */
13351 if (TREE_CODE (newdecl) == FUNCTION_DECL)
13353 TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
13354 /* This is since we don't automatically
13355 copy the attributes of NEWDECL into OLDDECL. */
13356 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
13357 /* If this clears `static', clear it in the identifier too. */
13358 if (! TREE_PUBLIC (olddecl))
13359 TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
13361 if (DECL_EXTERNAL (newdecl))
13363 TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
13364 DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
13365 /* An extern decl does not override previous storage class. */
13366 TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
13368 else
13370 TREE_STATIC (olddecl) = TREE_STATIC (newdecl);
13371 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
13374 /* If either decl says `inline', this fn is inline,
13375 unless its definition was passed already. */
13376 if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
13377 DECL_INLINE (olddecl) = 1;
13378 DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
13380 /* Get rid of any built-in function if new arg types don't match it
13381 or if we have a function definition. */
13382 if (TREE_CODE (newdecl) == FUNCTION_DECL
13383 && DECL_BUILT_IN (olddecl)
13384 && (!types_match || new_is_definition))
13386 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
13387 DECL_BUILT_IN_CLASS (olddecl) = NOT_BUILT_IN;
13390 /* If redeclaring a builtin function, and not a definition,
13391 it stays built in.
13392 Also preserve various other info from the definition. */
13393 if (TREE_CODE (newdecl) == FUNCTION_DECL && !new_is_definition)
13395 if (DECL_BUILT_IN (olddecl))
13397 DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
13398 DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
13401 DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
13402 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
13403 DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
13404 DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
13407 /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
13408 But preserve olddecl's DECL_UID. */
13410 register unsigned olddecl_uid = DECL_UID (olddecl);
13412 memcpy ((char *) olddecl + sizeof (struct tree_common),
13413 (char *) newdecl + sizeof (struct tree_common),
13414 sizeof (struct tree_decl) - sizeof (struct tree_common));
13415 DECL_UID (olddecl) = olddecl_uid;
13418 return 1;
13421 /* Finish processing of a declaration;
13422 install its initial value.
13423 If the length of an array type is not known before,
13424 it must be determined now, from the initial value, or it is an error. */
13426 static void
13427 finish_decl (tree decl, tree init, bool is_top_level)
13429 register tree type = TREE_TYPE (decl);
13430 int was_incomplete = (DECL_SIZE (decl) == 0);
13431 bool at_top_level = (current_binding_level == global_binding_level);
13432 bool top_level = is_top_level || at_top_level;
13434 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
13435 level anyway. */
13436 assert (!is_top_level || !at_top_level);
13438 if (TREE_CODE (decl) == PARM_DECL)
13439 assert (init == NULL_TREE);
13440 /* Remember that PARM_DECL doesn't have a DECL_INITIAL field per se -- it
13441 overlaps DECL_ARG_TYPE. */
13442 else if (init == NULL_TREE)
13443 assert (DECL_INITIAL (decl) == NULL_TREE);
13444 else
13445 assert (DECL_INITIAL (decl) == error_mark_node);
13447 if (init != NULL_TREE)
13449 if (TREE_CODE (decl) != TYPE_DECL)
13450 DECL_INITIAL (decl) = init;
13451 else
13453 /* typedef foo = bar; store the type of bar as the type of foo. */
13454 TREE_TYPE (decl) = TREE_TYPE (init);
13455 DECL_INITIAL (decl) = init = 0;
13459 /* Deduce size of array from initialization, if not already known */
13461 if (TREE_CODE (type) == ARRAY_TYPE
13462 && TYPE_DOMAIN (type) == 0
13463 && TREE_CODE (decl) != TYPE_DECL)
13465 assert (top_level);
13466 assert (was_incomplete);
13468 layout_decl (decl, 0);
13471 if (TREE_CODE (decl) == VAR_DECL)
13473 if (DECL_SIZE (decl) == NULL_TREE
13474 && TYPE_SIZE (TREE_TYPE (decl)) != NULL_TREE)
13475 layout_decl (decl, 0);
13477 if (DECL_SIZE (decl) == NULL_TREE
13478 && (TREE_STATIC (decl)
13480 /* A static variable with an incomplete type is an error if it is
13481 initialized. Also if it is not file scope. Otherwise, let it
13482 through, but if it is not `extern' then it may cause an error
13483 message later. */
13484 (DECL_INITIAL (decl) != 0 || DECL_CONTEXT (decl) != 0)
13486 /* An automatic variable with an incomplete type is an error. */
13487 !DECL_EXTERNAL (decl)))
13489 assert ("storage size not known" == NULL);
13490 abort ();
13493 if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
13494 && (DECL_SIZE (decl) != 0)
13495 && (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST))
13497 assert ("storage size not constant" == NULL);
13498 abort ();
13502 /* Output the assembler code and/or RTL code for variables and functions,
13503 unless the type is an undefined structure or union. If not, it will get
13504 done when the type is completed. */
13506 if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
13508 rest_of_decl_compilation (decl, NULL,
13509 DECL_CONTEXT (decl) == 0,
13512 if (DECL_CONTEXT (decl) != 0)
13514 /* Recompute the RTL of a local array now if it used to be an
13515 incomplete type. */
13516 if (was_incomplete
13517 && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
13519 /* If we used it already as memory, it must stay in memory. */
13520 TREE_ADDRESSABLE (decl) = TREE_USED (decl);
13521 /* If it's still incomplete now, no init will save it. */
13522 if (DECL_SIZE (decl) == 0)
13523 DECL_INITIAL (decl) = 0;
13524 expand_decl (decl);
13526 /* Compute and store the initial value. */
13527 if (TREE_CODE (decl) != FUNCTION_DECL)
13528 expand_decl_init (decl);
13531 else if (TREE_CODE (decl) == TYPE_DECL)
13533 rest_of_decl_compilation (decl, NULL,
13534 DECL_CONTEXT (decl) == 0,
13538 /* At the end of a declaration, throw away any variable type sizes of types
13539 defined inside that declaration. There is no use computing them in the
13540 following function definition. */
13541 if (current_binding_level == global_binding_level)
13542 get_pending_sizes ();
13545 /* Finish up a function declaration and compile that function
13546 all the way to assembler language output. The free the storage
13547 for the function definition.
13549 This is called after parsing the body of the function definition.
13551 NESTED is nonzero if the function being finished is nested in another. */
13553 static void
13554 finish_function (int nested)
13556 register tree fndecl = current_function_decl;
13558 assert (fndecl != NULL_TREE);
13559 if (TREE_CODE (fndecl) != ERROR_MARK)
13561 if (nested)
13562 assert (DECL_CONTEXT (fndecl) != NULL_TREE);
13563 else
13564 assert (DECL_CONTEXT (fndecl) == NULL_TREE);
13567 /* TREE_READONLY (fndecl) = 1;
13568 This caused &foo to be of type ptr-to-const-function
13569 which then got a warning when stored in a ptr-to-function variable. */
13571 poplevel (1, 0, 1);
13573 if (TREE_CODE (fndecl) != ERROR_MARK)
13575 BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
13577 /* Must mark the RESULT_DECL as being in this function. */
13579 DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
13581 /* Obey `register' declarations if `setjmp' is called in this fn. */
13582 /* Generate rtl for function exit. */
13583 expand_function_end ();
13585 /* If this is a nested function, protect the local variables in the stack
13586 above us from being collected while we're compiling this function. */
13587 if (nested)
13588 ggc_push_context ();
13590 /* Run the optimizers and output the assembler code for this function. */
13591 rest_of_compilation (fndecl);
13593 /* Undo the GC context switch. */
13594 if (nested)
13595 ggc_pop_context ();
13598 if (TREE_CODE (fndecl) != ERROR_MARK
13599 && !nested
13600 && DECL_SAVED_INSNS (fndecl) == 0)
13602 /* Stop pointing to the local nodes about to be freed. */
13603 /* But DECL_INITIAL must remain nonzero so we know this was an actual
13604 function definition. */
13605 /* For a nested function, this is done in pop_f_function_context. */
13606 /* If rest_of_compilation set this to 0, leave it 0. */
13607 if (DECL_INITIAL (fndecl) != 0)
13608 DECL_INITIAL (fndecl) = error_mark_node;
13609 DECL_ARGUMENTS (fndecl) = 0;
13612 if (!nested)
13614 /* Let the error reporting routines know that we're outside a function.
13615 For a nested function, this value is used in pop_c_function_context
13616 and then reset via pop_function_context. */
13617 ffecom_outer_function_decl_ = current_function_decl = NULL;
13621 /* Plug-in replacement for identifying the name of a decl and, for a
13622 function, what we call it in diagnostics. For now, "program unit"
13623 should suffice, since it's a bit of a hassle to figure out which
13624 of several kinds of things it is. Note that it could conceivably
13625 be a statement function, which probably isn't really a program unit
13626 per se, but if that comes up, it should be easy to check (being a
13627 nested function and all). */
13629 static const char *
13630 ffe_printable_name (tree decl, int v)
13632 /* Just to keep GCC quiet about the unused variable.
13633 In theory, differing values of V should produce different
13634 output. */
13635 switch (v)
13637 default:
13638 if (TREE_CODE (decl) == ERROR_MARK)
13639 return "erroneous code";
13640 return IDENTIFIER_POINTER (DECL_NAME (decl));
13644 /* g77's function to print out name of current function that caused
13645 an error. */
13647 static void
13648 ffe_print_error_function (diagnostic_context *context __attribute__((unused)),
13649 const char *file)
13651 static ffeglobal last_g = NULL;
13652 static ffesymbol last_s = NULL;
13653 ffeglobal g;
13654 ffesymbol s;
13655 const char *kind;
13657 if ((ffecom_primary_entry_ == NULL)
13658 || (ffesymbol_global (ffecom_primary_entry_) == NULL))
13660 g = NULL;
13661 s = NULL;
13662 kind = NULL;
13664 else
13666 g = ffesymbol_global (ffecom_primary_entry_);
13667 if (ffecom_nested_entry_ == NULL)
13669 s = ffecom_primary_entry_;
13670 kind = _(ffeinfo_kind_message (ffesymbol_kind (s)));
13672 else
13674 s = ffecom_nested_entry_;
13675 kind = _("In statement function");
13679 if ((last_g != g) || (last_s != s))
13681 if (file)
13682 fprintf (stderr, "%s: ", file);
13684 if (s == NULL)
13685 fprintf (stderr, _("Outside of any program unit:\n"));
13686 else
13688 const char *name = ffesymbol_text (s);
13690 fprintf (stderr, "%s `%s':\n", kind, name);
13693 last_g = g;
13694 last_s = s;
13698 /* Similar to `lookup_name' but look only at current binding level. */
13700 static tree
13701 lookup_name_current_level (tree name)
13703 register tree t;
13705 if (current_binding_level == global_binding_level)
13706 return IDENTIFIER_GLOBAL_VALUE (name);
13708 if (IDENTIFIER_LOCAL_VALUE (name) == 0)
13709 return 0;
13711 for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
13712 if (DECL_NAME (t) == name)
13713 break;
13715 return t;
13718 /* Create a new `struct f_binding_level'. */
13720 static struct f_binding_level *
13721 make_binding_level (void)
13723 /* NOSTRICT */
13724 return ggc_alloc (sizeof (struct f_binding_level));
13727 /* Save and restore the variables in this file and elsewhere
13728 that keep track of the progress of compilation of the current function.
13729 Used for nested functions. */
13731 struct f_function
13733 struct f_function *next;
13734 tree named_labels;
13735 tree shadowed_labels;
13736 struct f_binding_level *binding_level;
13739 struct f_function *f_function_chain;
13741 /* Restore the variables used during compilation of a C function. */
13743 static void
13744 pop_f_function_context (void)
13746 struct f_function *p = f_function_chain;
13747 tree link;
13749 /* Bring back all the labels that were shadowed. */
13750 for (link = shadowed_labels; link; link = TREE_CHAIN (link))
13751 if (DECL_NAME (TREE_VALUE (link)) != 0)
13752 IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)))
13753 = TREE_VALUE (link);
13755 if (current_function_decl != error_mark_node
13756 && DECL_SAVED_INSNS (current_function_decl) == 0)
13758 /* Stop pointing to the local nodes about to be freed. */
13759 /* But DECL_INITIAL must remain nonzero so we know this was an actual
13760 function definition. */
13761 DECL_INITIAL (current_function_decl) = error_mark_node;
13762 DECL_ARGUMENTS (current_function_decl) = 0;
13765 pop_function_context ();
13767 f_function_chain = p->next;
13769 named_labels = p->named_labels;
13770 shadowed_labels = p->shadowed_labels;
13771 current_binding_level = p->binding_level;
13773 free (p);
13776 /* Save and reinitialize the variables
13777 used during compilation of a C function. */
13779 static void
13780 push_f_function_context (void)
13782 struct f_function *p = xmalloc (sizeof (struct f_function));
13784 push_function_context ();
13786 p->next = f_function_chain;
13787 f_function_chain = p;
13789 p->named_labels = named_labels;
13790 p->shadowed_labels = shadowed_labels;
13791 p->binding_level = current_binding_level;
13794 static void
13795 push_parm_decl (tree parm)
13797 int old_immediate_size_expand = immediate_size_expand;
13799 /* Don't try computing parm sizes now -- wait till fn is called. */
13801 immediate_size_expand = 0;
13803 /* Fill in arg stuff. */
13805 DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
13806 DECL_ARG_TYPE_AS_WRITTEN (parm) = TREE_TYPE (parm);
13807 TREE_READONLY (parm) = 1; /* All implementation args are read-only. */
13809 parm = pushdecl (parm);
13811 immediate_size_expand = old_immediate_size_expand;
13813 finish_decl (parm, NULL_TREE, FALSE);
13816 /* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, if appropriate. */
13818 static tree
13819 pushdecl_top_level (tree x)
13821 register tree t;
13822 register struct f_binding_level *b = current_binding_level;
13823 register tree f = current_function_decl;
13825 current_binding_level = global_binding_level;
13826 current_function_decl = NULL_TREE;
13827 t = pushdecl (x);
13828 current_binding_level = b;
13829 current_function_decl = f;
13830 return t;
13833 /* Store the list of declarations of the current level.
13834 This is done for the parameter declarations of a function being defined,
13835 after they are modified in the light of any missing parameters. */
13837 static tree
13838 storedecls (tree decls)
13840 return current_binding_level->names = decls;
13843 /* Store the parameter declarations into the current function declaration.
13844 This is called after parsing the parameter declarations, before
13845 digesting the body of the function.
13847 For an old-style definition, modify the function's type
13848 to specify at least the number of arguments. */
13850 static void
13851 store_parm_decls (int is_main_program UNUSED)
13853 register tree fndecl = current_function_decl;
13855 if (fndecl == error_mark_node)
13856 return;
13858 /* This is a chain of PARM_DECLs from old-style parm declarations. */
13859 DECL_ARGUMENTS (fndecl) = storedecls (nreverse (getdecls ()));
13861 /* Initialize the RTL code for the function. */
13862 init_function_start (fndecl);
13864 /* Set up parameters and prepare for return, for the function. */
13865 expand_function_start (fndecl, 0);
13868 static tree
13869 start_decl (tree decl, bool is_top_level)
13871 register tree tem;
13872 bool at_top_level = (current_binding_level == global_binding_level);
13873 bool top_level = is_top_level || at_top_level;
13875 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
13876 level anyway. */
13877 assert (!is_top_level || !at_top_level);
13879 if (DECL_INITIAL (decl) != NULL_TREE)
13881 assert (DECL_INITIAL (decl) == error_mark_node);
13882 assert (!DECL_EXTERNAL (decl));
13884 else if (top_level)
13885 assert ((TREE_STATIC (decl) == 1) || DECL_EXTERNAL (decl) == 1);
13887 /* For Fortran, we by default put things in .common when possible. */
13888 DECL_COMMON (decl) = 1;
13890 /* Add this decl to the current binding level. TEM may equal DECL or it may
13891 be a previous decl of the same name. */
13892 if (is_top_level)
13893 tem = pushdecl_top_level (decl);
13894 else
13895 tem = pushdecl (decl);
13897 /* For a local variable, define the RTL now. */
13898 if (!top_level
13899 /* But not if this is a duplicate decl and we preserved the rtl from the
13900 previous one (which may or may not happen). */
13901 && !DECL_RTL_SET_P (tem))
13903 if (TYPE_SIZE (TREE_TYPE (tem)) != 0)
13904 expand_decl (tem);
13905 else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
13906 && DECL_INITIAL (tem) != 0)
13907 expand_decl (tem);
13910 return tem;
13913 /* Create the FUNCTION_DECL for a function definition.
13914 DECLSPECS and DECLARATOR are the parts of the declaration;
13915 they describe the function's name and the type it returns,
13916 but twisted together in a fashion that parallels the syntax of C.
13918 This function creates a binding context for the function body
13919 as well as setting up the FUNCTION_DECL in current_function_decl.
13921 Returns 1 on success. If the DECLARATOR is not suitable for a function
13922 (it defines a datum instead), we return 0, which tells
13923 ffe_parse_file to report a parse error.
13925 NESTED is nonzero for a function nested within another function. */
13927 static void
13928 start_function (tree name, tree type, int nested, int public)
13930 tree decl1;
13931 tree restype;
13932 int old_immediate_size_expand = immediate_size_expand;
13934 named_labels = 0;
13935 shadowed_labels = 0;
13937 /* Don't expand any sizes in the return type of the function. */
13938 immediate_size_expand = 0;
13940 if (nested)
13942 assert (!public);
13943 assert (current_function_decl != NULL_TREE);
13944 assert (DECL_CONTEXT (current_function_decl) == NULL_TREE);
13946 else
13948 assert (current_function_decl == NULL_TREE);
13951 if (TREE_CODE (type) == ERROR_MARK)
13952 decl1 = current_function_decl = error_mark_node;
13953 else
13955 decl1 = build_decl (FUNCTION_DECL,
13956 name,
13957 type);
13958 TREE_PUBLIC (decl1) = public ? 1 : 0;
13959 if (nested)
13960 DECL_INLINE (decl1) = 1;
13961 TREE_STATIC (decl1) = 1;
13962 DECL_EXTERNAL (decl1) = 0;
13964 announce_function (decl1);
13966 /* Make the init_value nonzero so pushdecl knows this is not tentative.
13967 error_mark_node is replaced below (in poplevel) with the BLOCK. */
13968 DECL_INITIAL (decl1) = error_mark_node;
13970 /* Record the decl so that the function name is defined. If we already have
13971 a decl for this name, and it is a FUNCTION_DECL, use the old decl. */
13973 current_function_decl = pushdecl (decl1);
13976 if (!nested)
13977 ffecom_outer_function_decl_ = current_function_decl;
13979 pushlevel (0);
13980 current_binding_level->prep_state = 2;
13982 if (TREE_CODE (current_function_decl) != ERROR_MARK)
13984 make_decl_rtl (current_function_decl, NULL);
13986 restype = TREE_TYPE (TREE_TYPE (current_function_decl));
13987 DECL_RESULT (current_function_decl)
13988 = build_decl (RESULT_DECL, NULL_TREE, restype);
13991 if (!nested && (TREE_CODE (current_function_decl) != ERROR_MARK))
13992 TREE_ADDRESSABLE (current_function_decl) = 1;
13994 immediate_size_expand = old_immediate_size_expand;
13997 /* Here are the public functions the GNU back end needs. */
13999 tree
14000 convert (tree type, tree expr)
14002 register tree e = expr;
14003 register enum tree_code code = TREE_CODE (type);
14005 if (type == TREE_TYPE (e)
14006 || TREE_CODE (e) == ERROR_MARK)
14007 return e;
14008 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
14009 return fold (build1 (NOP_EXPR, type, e));
14010 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
14011 || code == ERROR_MARK)
14012 return error_mark_node;
14013 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
14015 assert ("void value not ignored as it ought to be" == NULL);
14016 return error_mark_node;
14018 if (code == VOID_TYPE)
14019 return build1 (CONVERT_EXPR, type, e);
14020 if ((code != RECORD_TYPE)
14021 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
14022 e = ffecom_1 (REALPART_EXPR, TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e))),
14024 if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
14025 return fold (convert_to_integer (type, e));
14026 if (code == POINTER_TYPE)
14027 return fold (convert_to_pointer (type, e));
14028 if (code == REAL_TYPE)
14029 return fold (convert_to_real (type, e));
14030 if (code == COMPLEX_TYPE)
14031 return fold (convert_to_complex (type, e));
14032 if (code == RECORD_TYPE)
14033 return fold (ffecom_convert_to_complex_ (type, e));
14035 assert ("conversion to non-scalar type requested" == NULL);
14036 return error_mark_node;
14039 /* Return the list of declarations of the current level.
14040 Note that this list is in reverse order unless/until
14041 you nreverse it; and when you do nreverse it, you must
14042 store the result back using `storedecls' or you will lose. */
14044 tree
14045 getdecls (void)
14047 return current_binding_level->names;
14050 /* Nonzero if we are currently in the global binding level. */
14053 global_bindings_p (void)
14055 return current_binding_level == global_binding_level;
14058 static void
14059 ffecom_init_decl_processing (void)
14061 malloc_init ();
14063 ffe_init_0 ();
14066 /* Delete the node BLOCK from the current binding level.
14067 This is used for the block inside a stmt expr ({...})
14068 so that the block can be reinserted where appropriate. */
14070 static void
14071 delete_block (tree block)
14073 tree t;
14074 if (current_binding_level->blocks == block)
14075 current_binding_level->blocks = TREE_CHAIN (block);
14076 for (t = current_binding_level->blocks; t;)
14078 if (TREE_CHAIN (t) == block)
14079 TREE_CHAIN (t) = TREE_CHAIN (block);
14080 else
14081 t = TREE_CHAIN (t);
14083 TREE_CHAIN (block) = NULL;
14084 /* Clear TREE_USED which is always set by poplevel.
14085 The flag is set again if insert_block is called. */
14086 TREE_USED (block) = 0;
14089 void
14090 insert_block (tree block)
14092 TREE_USED (block) = 1;
14093 current_binding_level->blocks
14094 = chainon (current_binding_level->blocks, block);
14097 /* Each front end provides its own. */
14098 static bool ffe_init (void);
14099 static void ffe_finish (void);
14100 static bool ffe_post_options (const char **);
14101 static void ffe_print_identifier (FILE *, tree, int);
14103 struct language_function GTY(())
14105 int unused;
14108 #undef LANG_HOOKS_NAME
14109 #define LANG_HOOKS_NAME "GNU F77"
14110 #undef LANG_HOOKS_INIT
14111 #define LANG_HOOKS_INIT ffe_init
14112 #undef LANG_HOOKS_FINISH
14113 #define LANG_HOOKS_FINISH ffe_finish
14114 #undef LANG_HOOKS_INIT_OPTIONS
14115 #define LANG_HOOKS_INIT_OPTIONS ffe_init_options
14116 #undef LANG_HOOKS_HANDLE_OPTION
14117 #define LANG_HOOKS_HANDLE_OPTION ffe_handle_option
14118 #undef LANG_HOOKS_POST_OPTIONS
14119 #define LANG_HOOKS_POST_OPTIONS ffe_post_options
14120 #undef LANG_HOOKS_PARSE_FILE
14121 #define LANG_HOOKS_PARSE_FILE ffe_parse_file
14122 #undef LANG_HOOKS_MARK_ADDRESSABLE
14123 #define LANG_HOOKS_MARK_ADDRESSABLE ffe_mark_addressable
14124 #undef LANG_HOOKS_PRINT_IDENTIFIER
14125 #define LANG_HOOKS_PRINT_IDENTIFIER ffe_print_identifier
14126 #undef LANG_HOOKS_DECL_PRINTABLE_NAME
14127 #define LANG_HOOKS_DECL_PRINTABLE_NAME ffe_printable_name
14128 #undef LANG_HOOKS_PRINT_ERROR_FUNCTION
14129 #define LANG_HOOKS_PRINT_ERROR_FUNCTION ffe_print_error_function
14130 #undef LANG_HOOKS_TRUTHVALUE_CONVERSION
14131 #define LANG_HOOKS_TRUTHVALUE_CONVERSION ffe_truthvalue_conversion
14133 #undef LANG_HOOKS_TYPE_FOR_MODE
14134 #define LANG_HOOKS_TYPE_FOR_MODE ffe_type_for_mode
14135 #undef LANG_HOOKS_TYPE_FOR_SIZE
14136 #define LANG_HOOKS_TYPE_FOR_SIZE ffe_type_for_size
14137 #undef LANG_HOOKS_SIGNED_TYPE
14138 #define LANG_HOOKS_SIGNED_TYPE ffe_signed_type
14139 #undef LANG_HOOKS_UNSIGNED_TYPE
14140 #define LANG_HOOKS_UNSIGNED_TYPE ffe_unsigned_type
14141 #undef LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE
14142 #define LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE ffe_signed_or_unsigned_type
14144 /* We do not wish to use alias-set based aliasing at all. Used in the
14145 extreme (every object with its own set, with equivalences recorded) it
14146 might be helpful, but there are problems when it comes to inlining. We
14147 get on ok with flag_argument_noalias, and alias-set aliasing does
14148 currently limit how stack slots can be reused, which is a lose. */
14149 #undef LANG_HOOKS_GET_ALIAS_SET
14150 #define LANG_HOOKS_GET_ALIAS_SET hook_get_alias_set_0
14152 const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
14154 /* Table indexed by tree code giving a string containing a character
14155 classifying the tree code. Possibilities are
14156 t, d, s, c, r, <, 1, 2 and e. See tree.def for details. */
14158 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
14160 const char tree_code_type[] = {
14161 #include "tree.def"
14163 #undef DEFTREECODE
14165 /* Table indexed by tree code giving number of expression
14166 operands beyond the fixed part of the node structure.
14167 Not used for types or decls. */
14169 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
14171 const unsigned char tree_code_length[] = {
14172 #include "tree.def"
14174 #undef DEFTREECODE
14176 /* Names of tree components.
14177 Used for printing out the tree and error messages. */
14178 #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
14180 const char *const tree_code_name[] = {
14181 #include "tree.def"
14183 #undef DEFTREECODE
14185 static bool
14186 ffe_post_options (const char **pfilename)
14188 const char *filename = *pfilename;
14190 /* Open input file. */
14191 if (filename == 0 || !strcmp (filename, "-"))
14193 finput = stdin;
14194 filename = "stdin";
14196 else
14197 finput = fopen (filename, "r");
14199 if (finput == 0)
14200 fatal_error ("can't open %s: %m", filename);
14202 return false;
14206 static bool
14207 ffe_init (void)
14209 #ifdef IO_BUFFER_SIZE
14210 setvbuf (finput, xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);
14211 #endif
14213 ffecom_init_decl_processing ();
14215 /* If the file is output from cpp, it should contain a first line
14216 `# 1 "real-filename"', and the current design of gcc (toplev.c
14217 in particular and the way it sets up information relied on by
14218 INCLUDE) requires that we read this now, and store the
14219 "real-filename" info in master_input_filename. Ask the lexer
14220 to try doing this. */
14221 ffelex_hash_kludge (finput);
14223 push_srcloc (input_filename, 0);
14225 /* FIXME: The ffelex_hash_kludge code needs to be cleaned up to
14226 set the new file name. Maybe in ffe_post_options. */
14227 return true;
14230 static void
14231 ffe_finish (void)
14233 ffe_terminate_0 ();
14235 if (ffe_is_ffedebug ())
14236 malloc_pool_display (malloc_pool_image ());
14238 fclose (finput);
14241 static bool
14242 ffe_mark_addressable (tree exp)
14244 register tree x = exp;
14245 while (1)
14246 switch (TREE_CODE (x))
14248 case ADDR_EXPR:
14249 case COMPONENT_REF:
14250 case ARRAY_REF:
14251 x = TREE_OPERAND (x, 0);
14252 break;
14254 case CONSTRUCTOR:
14255 TREE_ADDRESSABLE (x) = 1;
14256 return true;
14258 case VAR_DECL:
14259 case CONST_DECL:
14260 case PARM_DECL:
14261 case RESULT_DECL:
14262 if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)
14263 && DECL_NONLOCAL (x))
14265 if (TREE_PUBLIC (x))
14267 assert ("address of global register var requested" == NULL);
14268 return false;
14270 assert ("address of register variable requested" == NULL);
14272 else if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x))
14274 if (TREE_PUBLIC (x))
14276 assert ("address of global register var requested" == NULL);
14277 return false;
14279 assert ("address of register var requested" == NULL);
14281 put_var_into_stack (x, /*rescan=*/true);
14283 /* drops in */
14284 case FUNCTION_DECL:
14285 TREE_ADDRESSABLE (x) = 1;
14286 #if 0 /* poplevel deals with this now. */
14287 if (DECL_CONTEXT (x) == 0)
14288 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
14289 #endif
14291 default:
14292 return true;
14296 /* Exit a binding level.
14297 Pop the level off, and restore the state of the identifier-decl mappings
14298 that were in effect when this level was entered.
14300 If KEEP is nonzero, this level had explicit declarations, so
14301 and create a "block" (a BLOCK node) for the level
14302 to record its declarations and subblocks for symbol table output.
14304 If FUNCTIONBODY is nonzero, this level is the body of a function,
14305 so create a block as if KEEP were set and also clear out all
14306 label names.
14308 If REVERSE is nonzero, reverse the order of decls before putting
14309 them into the BLOCK. */
14311 tree
14312 poplevel (int keep, int reverse, int functionbody)
14314 register tree link;
14315 /* The chain of decls was accumulated in reverse order.
14316 Put it into forward order, just for cleanliness. */
14317 tree decls;
14318 tree subblocks = current_binding_level->blocks;
14319 tree block = 0;
14320 tree decl;
14321 int block_previously_created;
14323 /* Get the decls in the order they were written.
14324 Usually current_binding_level->names is in reverse order.
14325 But parameter decls were previously put in forward order. */
14327 if (reverse)
14328 current_binding_level->names
14329 = decls = nreverse (current_binding_level->names);
14330 else
14331 decls = current_binding_level->names;
14333 /* Output any nested inline functions within this block
14334 if they weren't already output. */
14336 for (decl = decls; decl; decl = TREE_CHAIN (decl))
14337 if (TREE_CODE (decl) == FUNCTION_DECL
14338 && ! TREE_ASM_WRITTEN (decl)
14339 && DECL_INITIAL (decl) != 0
14340 && TREE_ADDRESSABLE (decl))
14342 /* If this decl was copied from a file-scope decl
14343 on account of a block-scope extern decl,
14344 propagate TREE_ADDRESSABLE to the file-scope decl.
14346 DECL_ABSTRACT_ORIGIN can be set to itself if warn_return_type is
14347 true, since then the decl goes through save_for_inline_copying. */
14348 if (DECL_ABSTRACT_ORIGIN (decl) != 0
14349 && DECL_ABSTRACT_ORIGIN (decl) != decl)
14350 TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
14351 else if (DECL_SAVED_INSNS (decl) != 0)
14353 push_function_context ();
14354 output_inline_function (decl);
14355 pop_function_context ();
14359 /* If there were any declarations or structure tags in that level,
14360 or if this level is a function body,
14361 create a BLOCK to record them for the life of this function. */
14363 block = 0;
14364 block_previously_created = (current_binding_level->this_block != 0);
14365 if (block_previously_created)
14366 block = current_binding_level->this_block;
14367 else if (keep || functionbody)
14368 block = make_node (BLOCK);
14369 if (block != 0)
14371 BLOCK_VARS (block) = decls;
14372 BLOCK_SUBBLOCKS (block) = subblocks;
14375 /* In each subblock, record that this is its superior. */
14377 for (link = subblocks; link; link = TREE_CHAIN (link))
14378 BLOCK_SUPERCONTEXT (link) = block;
14380 /* Clear out the meanings of the local variables of this level. */
14382 for (link = decls; link; link = TREE_CHAIN (link))
14384 if (DECL_NAME (link) != 0)
14386 /* If the ident. was used or addressed via a local extern decl,
14387 don't forget that fact. */
14388 if (DECL_EXTERNAL (link))
14390 if (TREE_USED (link))
14391 TREE_USED (DECL_NAME (link)) = 1;
14392 if (TREE_ADDRESSABLE (link))
14393 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
14395 IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0;
14399 /* If the level being exited is the top level of a function,
14400 check over all the labels, and clear out the current
14401 (function local) meanings of their names. */
14403 if (functionbody)
14405 /* If this is the top level block of a function,
14406 the vars are the function's parameters.
14407 Don't leave them in the BLOCK because they are
14408 found in the FUNCTION_DECL instead. */
14410 BLOCK_VARS (block) = 0;
14413 /* Pop the current level, and free the structure for reuse. */
14416 register struct f_binding_level *level = current_binding_level;
14417 current_binding_level = current_binding_level->level_chain;
14419 level->level_chain = free_binding_level;
14420 free_binding_level = level;
14423 /* Dispose of the block that we just made inside some higher level. */
14424 if (functionbody
14425 && current_function_decl != error_mark_node)
14426 DECL_INITIAL (current_function_decl) = block;
14427 else if (block)
14429 if (!block_previously_created)
14430 current_binding_level->blocks
14431 = chainon (current_binding_level->blocks, block);
14433 /* If we did not make a block for the level just exited,
14434 any blocks made for inner levels
14435 (since they cannot be recorded as subblocks in that level)
14436 must be carried forward so they will later become subblocks
14437 of something else. */
14438 else if (subblocks)
14439 current_binding_level->blocks
14440 = chainon (current_binding_level->blocks, subblocks);
14442 if (block)
14443 TREE_USED (block) = 1;
14444 return block;
14447 static void
14448 ffe_print_identifier (FILE *file, tree node, int indent)
14450 print_node (file, "global", IDENTIFIER_GLOBAL_VALUE (node), indent + 4);
14451 print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4);
14454 /* Record a decl-node X as belonging to the current lexical scope.
14455 Check for errors (such as an incompatible declaration for the same
14456 name already seen in the same scope).
14458 Returns either X or an old decl for the same name.
14459 If an old decl is returned, it may have been smashed
14460 to agree with what X says. */
14462 tree
14463 pushdecl (tree x)
14465 register tree t;
14466 register tree name = DECL_NAME (x);
14467 register struct f_binding_level *b = current_binding_level;
14469 if ((TREE_CODE (x) == FUNCTION_DECL)
14470 && (DECL_INITIAL (x) == 0)
14471 && DECL_EXTERNAL (x))
14472 DECL_CONTEXT (x) = NULL_TREE;
14473 else
14474 DECL_CONTEXT (x) = current_function_decl;
14476 if (name)
14478 if (IDENTIFIER_INVENTED (name))
14480 DECL_ARTIFICIAL (x) = 1;
14481 DECL_IN_SYSTEM_HEADER (x) = 1;
14484 t = lookup_name_current_level (name);
14486 assert ((t == NULL_TREE) || (DECL_CONTEXT (x) == NULL_TREE));
14488 /* Don't push non-parms onto list for parms until we understand
14489 why we're doing this and whether it works. */
14491 assert ((b == global_binding_level)
14492 || !ffecom_transform_only_dummies_
14493 || TREE_CODE (x) == PARM_DECL);
14495 if ((t != NULL_TREE) && duplicate_decls (x, t))
14496 return t;
14498 /* If we are processing a typedef statement, generate a whole new
14499 ..._TYPE node (which will be just an variant of the existing
14500 ..._TYPE node with identical properties) and then install the
14501 TYPE_DECL node generated to represent the typedef name as the
14502 TYPE_NAME of this brand new (duplicate) ..._TYPE node.
14504 The whole point here is to end up with a situation where each and every
14505 ..._TYPE node the compiler creates will be uniquely associated with
14506 AT MOST one node representing a typedef name. This way, even though
14507 the compiler substitutes corresponding ..._TYPE nodes for TYPE_DECL
14508 (i.e. "typedef name") nodes very early on, later parts of the
14509 compiler can always do the reverse translation and get back the
14510 corresponding typedef name. For example, given:
14512 typedef struct S MY_TYPE; MY_TYPE object;
14514 Later parts of the compiler might only know that `object' was of type
14515 `struct S' if it were not for code just below. With this code
14516 however, later parts of the compiler see something like:
14518 struct S' == struct S typedef struct S' MY_TYPE; struct S' object;
14520 And they can then deduce (from the node for type struct S') that the
14521 original object declaration was:
14523 MY_TYPE object;
14525 Being able to do this is important for proper support of protoize, and
14526 also for generating precise symbolic debugging information which
14527 takes full account of the programmer's (typedef) vocabulary.
14529 Obviously, we don't want to generate a duplicate ..._TYPE node if the
14530 TYPE_DECL node that we are now processing really represents a
14531 standard built-in type.
14533 Since all standard types are effectively declared at line zero in the
14534 source file, we can easily check to see if we are working on a
14535 standard type by checking the current value of lineno. */
14537 if (TREE_CODE (x) == TYPE_DECL)
14539 if (DECL_SOURCE_LINE (x) == 0)
14541 if (TYPE_NAME (TREE_TYPE (x)) == 0)
14542 TYPE_NAME (TREE_TYPE (x)) = x;
14544 else if (TREE_TYPE (x) != error_mark_node)
14546 tree tt = TREE_TYPE (x);
14548 tt = build_type_copy (tt);
14549 TYPE_NAME (tt) = x;
14550 TREE_TYPE (x) = tt;
14554 /* This name is new in its binding level. Install the new declaration
14555 and return it. */
14556 if (b == global_binding_level)
14557 IDENTIFIER_GLOBAL_VALUE (name) = x;
14558 else
14559 IDENTIFIER_LOCAL_VALUE (name) = x;
14562 /* Put decls on list in reverse order. We will reverse them later if
14563 necessary. */
14564 TREE_CHAIN (x) = b->names;
14565 b->names = x;
14567 return x;
14570 /* Nonzero if the current level needs to have a BLOCK made. */
14572 static int
14573 kept_level_p (void)
14575 tree decl;
14577 for (decl = current_binding_level->names;
14578 decl;
14579 decl = TREE_CHAIN (decl))
14581 if (TREE_USED (decl) || TREE_CODE (decl) != VAR_DECL
14582 || (DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl)))
14583 /* Currently, there aren't supposed to be non-artificial names
14584 at other than the top block for a function -- they're
14585 believed to always be temps. But it's wise to check anyway. */
14586 return 1;
14588 return 0;
14591 /* Enter a new binding level.
14592 If TAG_TRANSPARENT is nonzero, do so only for the name space of variables,
14593 not for that of tags. */
14595 void
14596 pushlevel (int tag_transparent)
14598 register struct f_binding_level *newlevel = NULL_BINDING_LEVEL;
14600 assert (! tag_transparent);
14602 if (current_binding_level == global_binding_level)
14604 named_labels = 0;
14607 /* Reuse or create a struct for this binding level. */
14609 if (free_binding_level)
14611 newlevel = free_binding_level;
14612 free_binding_level = free_binding_level->level_chain;
14614 else
14616 newlevel = make_binding_level ();
14619 /* Add this level to the front of the chain (stack) of levels that
14620 are active. */
14622 *newlevel = clear_binding_level;
14623 newlevel->level_chain = current_binding_level;
14624 current_binding_level = newlevel;
14627 /* Set the BLOCK node for the innermost scope
14628 (the one we are currently in). */
14630 void
14631 set_block (tree block)
14633 current_binding_level->this_block = block;
14634 current_binding_level->names = chainon (current_binding_level->names,
14635 BLOCK_VARS (block));
14636 current_binding_level->blocks = chainon (current_binding_level->blocks,
14637 BLOCK_SUBBLOCKS (block));
14640 static tree
14641 ffe_signed_or_unsigned_type (int unsignedp, tree type)
14643 tree type2;
14645 if (! INTEGRAL_TYPE_P (type))
14646 return type;
14647 if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
14648 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
14649 if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
14650 return unsignedp ? unsigned_type_node : integer_type_node;
14651 if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node))
14652 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
14653 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node))
14654 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
14655 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node))
14656 return (unsignedp ? long_long_unsigned_type_node
14657 : long_long_integer_type_node);
14659 type2 = ffe_type_for_size (TYPE_PRECISION (type), unsignedp);
14660 if (type2 == NULL_TREE)
14661 return type;
14663 return type2;
14666 static tree
14667 ffe_signed_type (tree type)
14669 tree type1 = TYPE_MAIN_VARIANT (type);
14670 ffeinfoKindtype kt;
14671 tree type2;
14673 if (type1 == unsigned_char_type_node || type1 == char_type_node)
14674 return signed_char_type_node;
14675 if (type1 == unsigned_type_node)
14676 return integer_type_node;
14677 if (type1 == short_unsigned_type_node)
14678 return short_integer_type_node;
14679 if (type1 == long_unsigned_type_node)
14680 return long_integer_type_node;
14681 if (type1 == long_long_unsigned_type_node)
14682 return long_long_integer_type_node;
14683 #if 0 /* gcc/c-* files only */
14684 if (type1 == unsigned_intDI_type_node)
14685 return intDI_type_node;
14686 if (type1 == unsigned_intSI_type_node)
14687 return intSI_type_node;
14688 if (type1 == unsigned_intHI_type_node)
14689 return intHI_type_node;
14690 if (type1 == unsigned_intQI_type_node)
14691 return intQI_type_node;
14692 #endif
14694 type2 = ffe_type_for_size (TYPE_PRECISION (type1), 0);
14695 if (type2 != NULL_TREE)
14696 return type2;
14698 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
14700 type2 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
14702 if (type1 == type2)
14703 return ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
14706 return type;
14709 /* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
14710 or validate its data type for an `if' or `while' statement or ?..: exp.
14712 This preparation consists of taking the ordinary
14713 representation of an expression expr and producing a valid tree
14714 boolean expression describing whether expr is nonzero. We could
14715 simply always do build_binary_op (NE_EXPR, expr, integer_zero_node, 1),
14716 but we optimize comparisons, &&, ||, and !.
14718 The resulting type should always be `integer_type_node'. */
14720 static tree
14721 ffe_truthvalue_conversion (tree expr)
14723 if (TREE_CODE (expr) == ERROR_MARK)
14724 return expr;
14726 #if 0 /* This appears to be wrong for C++. */
14727 /* These really should return error_mark_node after 2.4 is stable.
14728 But not all callers handle ERROR_MARK properly. */
14729 switch (TREE_CODE (TREE_TYPE (expr)))
14731 case RECORD_TYPE:
14732 error ("struct type value used where scalar is required");
14733 return integer_zero_node;
14735 case UNION_TYPE:
14736 error ("union type value used where scalar is required");
14737 return integer_zero_node;
14739 case ARRAY_TYPE:
14740 error ("array type value used where scalar is required");
14741 return integer_zero_node;
14743 default:
14744 break;
14746 #endif /* 0 */
14748 switch (TREE_CODE (expr))
14750 /* It is simpler and generates better code to have only TRUTH_*_EXPR
14751 or comparison expressions as truth values at this level. */
14752 #if 0
14753 case COMPONENT_REF:
14754 /* A one-bit unsigned bit-field is already acceptable. */
14755 if (1 == TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (expr, 1)))
14756 && TREE_UNSIGNED (TREE_OPERAND (expr, 1)))
14757 return expr;
14758 break;
14759 #endif
14761 case EQ_EXPR:
14762 /* It is simpler and generates better code to have only TRUTH_*_EXPR
14763 or comparison expressions as truth values at this level. */
14764 #if 0
14765 if (integer_zerop (TREE_OPERAND (expr, 1)))
14766 return build_unary_op (TRUTH_NOT_EXPR, TREE_OPERAND (expr, 0), 0);
14767 #endif
14768 case NE_EXPR: case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
14769 case TRUTH_ANDIF_EXPR:
14770 case TRUTH_ORIF_EXPR:
14771 case TRUTH_AND_EXPR:
14772 case TRUTH_OR_EXPR:
14773 case TRUTH_XOR_EXPR:
14774 TREE_TYPE (expr) = integer_type_node;
14775 return expr;
14777 case ERROR_MARK:
14778 return expr;
14780 case INTEGER_CST:
14781 return integer_zerop (expr) ? integer_zero_node : integer_one_node;
14783 case REAL_CST:
14784 return real_zerop (expr) ? integer_zero_node : integer_one_node;
14786 case ADDR_EXPR:
14787 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0)))
14788 return build (COMPOUND_EXPR, integer_type_node,
14789 TREE_OPERAND (expr, 0), integer_one_node);
14790 else
14791 return integer_one_node;
14793 case COMPLEX_EXPR:
14794 return ffecom_2 ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
14795 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
14796 integer_type_node,
14797 ffe_truthvalue_conversion (TREE_OPERAND (expr, 0)),
14798 ffe_truthvalue_conversion (TREE_OPERAND (expr, 1)));
14800 case NEGATE_EXPR:
14801 case ABS_EXPR:
14802 case FLOAT_EXPR:
14803 /* These don't change whether an object is nonzero or zero. */
14804 return ffe_truthvalue_conversion (TREE_OPERAND (expr, 0));
14806 case LROTATE_EXPR:
14807 case RROTATE_EXPR:
14808 /* These don't change whether an object is zero or nonzero, but
14809 we can't ignore them if their second arg has side-effects. */
14810 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
14811 return build (COMPOUND_EXPR, integer_type_node, TREE_OPERAND (expr, 1),
14812 ffe_truthvalue_conversion (TREE_OPERAND (expr, 0)));
14813 else
14814 return ffe_truthvalue_conversion (TREE_OPERAND (expr, 0));
14816 case COND_EXPR:
14818 /* Distribute the conversion into the arms of a COND_EXPR. */
14819 tree arg1 = TREE_OPERAND (expr, 1);
14820 tree arg2 = TREE_OPERAND (expr, 2);
14821 if (! VOID_TYPE_P (TREE_TYPE (arg1)))
14822 arg1 = ffe_truthvalue_conversion (arg1);
14823 if (! VOID_TYPE_P (TREE_TYPE (arg2)))
14824 arg2 = ffe_truthvalue_conversion (arg2);
14825 return fold (build (COND_EXPR, integer_type_node,
14826 TREE_OPERAND (expr, 0), arg1, arg2));
14829 case CONVERT_EXPR:
14830 /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
14831 since that affects how `default_conversion' will behave. */
14832 if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE
14833 || TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
14834 break;
14835 /* fall through... */
14836 case NOP_EXPR:
14837 /* If this is widening the argument, we can ignore it. */
14838 if (TYPE_PRECISION (TREE_TYPE (expr))
14839 >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
14840 return ffe_truthvalue_conversion (TREE_OPERAND (expr, 0));
14841 break;
14843 case MINUS_EXPR:
14844 /* With IEEE arithmetic, x - x may not equal 0, so we can't optimize
14845 this case. */
14846 if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
14847 && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE)
14848 break;
14849 /* fall through... */
14850 case BIT_XOR_EXPR:
14851 /* This and MINUS_EXPR can be changed into a comparison of the
14852 two objects. */
14853 if (TREE_TYPE (TREE_OPERAND (expr, 0))
14854 == TREE_TYPE (TREE_OPERAND (expr, 1)))
14855 return ffecom_2 (NE_EXPR, integer_type_node,
14856 TREE_OPERAND (expr, 0),
14857 TREE_OPERAND (expr, 1));
14858 return ffecom_2 (NE_EXPR, integer_type_node,
14859 TREE_OPERAND (expr, 0),
14860 fold (build1 (NOP_EXPR,
14861 TREE_TYPE (TREE_OPERAND (expr, 0)),
14862 TREE_OPERAND (expr, 1))));
14864 case BIT_AND_EXPR:
14865 if (integer_onep (TREE_OPERAND (expr, 1)))
14866 return expr;
14867 break;
14869 case MODIFY_EXPR:
14870 #if 0 /* No such thing in Fortran. */
14871 if (warn_parentheses && C_EXP_ORIGINAL_CODE (expr) == MODIFY_EXPR)
14872 warning ("suggest parentheses around assignment used as truth value");
14873 #endif
14874 break;
14876 default:
14877 break;
14880 if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
14881 return (ffecom_2
14882 ((TREE_SIDE_EFFECTS (expr)
14883 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
14884 integer_type_node,
14885 ffe_truthvalue_conversion (ffecom_1 (REALPART_EXPR,
14886 TREE_TYPE (TREE_TYPE (expr)),
14887 expr)),
14888 ffe_truthvalue_conversion (ffecom_1 (IMAGPART_EXPR,
14889 TREE_TYPE (TREE_TYPE (expr)),
14890 expr))));
14892 return ffecom_2 (NE_EXPR, integer_type_node,
14893 expr,
14894 convert (TREE_TYPE (expr), integer_zero_node));
14897 static tree
14898 ffe_type_for_mode (enum machine_mode mode, int unsignedp)
14900 int i;
14901 int j;
14902 tree t;
14904 if (mode == TYPE_MODE (integer_type_node))
14905 return unsignedp ? unsigned_type_node : integer_type_node;
14907 if (mode == TYPE_MODE (signed_char_type_node))
14908 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
14910 if (mode == TYPE_MODE (short_integer_type_node))
14911 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
14913 if (mode == TYPE_MODE (long_integer_type_node))
14914 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
14916 if (mode == TYPE_MODE (long_long_integer_type_node))
14917 return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
14919 #if HOST_BITS_PER_WIDE_INT >= 64
14920 if (mode == TYPE_MODE (intTI_type_node))
14921 return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
14922 #endif
14924 if (mode == TYPE_MODE (float_type_node))
14925 return float_type_node;
14927 if (mode == TYPE_MODE (double_type_node))
14928 return double_type_node;
14930 if (mode == TYPE_MODE (long_double_type_node))
14931 return long_double_type_node;
14933 if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
14934 return build_pointer_type (char_type_node);
14936 if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
14937 return build_pointer_type (integer_type_node);
14939 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
14940 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
14942 if (((t = ffecom_tree_type[i][j]) != NULL_TREE)
14943 && (mode == TYPE_MODE (t)))
14945 if ((i == FFEINFO_basictypeINTEGER) && unsignedp)
14946 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][j];
14947 else
14948 return t;
14952 return 0;
14955 static tree
14956 ffe_type_for_size (unsigned bits, int unsignedp)
14958 ffeinfoKindtype kt;
14959 tree type_node;
14961 if (bits == TYPE_PRECISION (integer_type_node))
14962 return unsignedp ? unsigned_type_node : integer_type_node;
14964 if (bits == TYPE_PRECISION (signed_char_type_node))
14965 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
14967 if (bits == TYPE_PRECISION (short_integer_type_node))
14968 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
14970 if (bits == TYPE_PRECISION (long_integer_type_node))
14971 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
14973 if (bits == TYPE_PRECISION (long_long_integer_type_node))
14974 return (unsignedp ? long_long_unsigned_type_node
14975 : long_long_integer_type_node);
14977 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
14979 type_node = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
14981 if ((type_node != NULL_TREE) && (bits == TYPE_PRECISION (type_node)))
14982 return unsignedp ? ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt]
14983 : type_node;
14986 return 0;
14989 static tree
14990 ffe_unsigned_type (tree type)
14992 tree type1 = TYPE_MAIN_VARIANT (type);
14993 ffeinfoKindtype kt;
14994 tree type2;
14996 if (type1 == signed_char_type_node || type1 == char_type_node)
14997 return unsigned_char_type_node;
14998 if (type1 == integer_type_node)
14999 return unsigned_type_node;
15000 if (type1 == short_integer_type_node)
15001 return short_unsigned_type_node;
15002 if (type1 == long_integer_type_node)
15003 return long_unsigned_type_node;
15004 if (type1 == long_long_integer_type_node)
15005 return long_long_unsigned_type_node;
15006 #if 0 /* gcc/c-* files only */
15007 if (type1 == intDI_type_node)
15008 return unsigned_intDI_type_node;
15009 if (type1 == intSI_type_node)
15010 return unsigned_intSI_type_node;
15011 if (type1 == intHI_type_node)
15012 return unsigned_intHI_type_node;
15013 if (type1 == intQI_type_node)
15014 return unsigned_intQI_type_node;
15015 #endif
15017 type2 = ffe_type_for_size (TYPE_PRECISION (type1), 1);
15018 if (type2 != NULL_TREE)
15019 return type2;
15021 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15023 type2 = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15025 if (type1 == type2)
15026 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
15029 return type;
15032 /* From gcc/cccp.c, the code to handle -I. */
15034 /* Skip leading "./" from a directory name.
15035 This may yield the empty string, which represents the current directory. */
15037 static const char *
15038 skip_redundant_dir_prefix (const char *dir)
15040 while (dir[0] == '.' && dir[1] == '/')
15041 for (dir += 2; *dir == '/'; dir++)
15042 continue;
15043 if (dir[0] == '.' && !dir[1])
15044 dir++;
15045 return dir;
15048 /* The file_name_map structure holds a mapping of file names for a
15049 particular directory. This mapping is read from the file named
15050 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
15051 map filenames on a file system with severe filename restrictions,
15052 such as DOS. The format of the file name map file is just a series
15053 of lines with two tokens on each line. The first token is the name
15054 to map, and the second token is the actual name to use. */
15056 struct file_name_map
15058 struct file_name_map *map_next;
15059 char *map_from;
15060 char *map_to;
15063 #define FILE_NAME_MAP_FILE "header.gcc"
15065 /* Current maximum length of directory names in the search path
15066 for include files. (Altered as we get more of them.) */
15068 static int max_include_len = 0;
15070 struct file_name_list
15072 struct file_name_list *next;
15073 const char *fname;
15074 /* Mapping of file names for this directory. */
15075 struct file_name_map *name_map;
15076 /* Nonzero if name_map is valid. */
15077 int got_name_map;
15080 static struct file_name_list *include = NULL; /* First dir to search */
15081 static struct file_name_list *last_include = NULL; /* Last in chain */
15083 /* I/O buffer structure.
15084 The `fname' field is nonzero for source files and #include files
15085 and for the dummy text used for -D and -U.
15086 It is zero for rescanning results of macro expansion
15087 and for expanding macro arguments. */
15088 #define INPUT_STACK_MAX 400
15089 static struct file_buf {
15090 const char *fname;
15091 /* Filename specified with #line command. */
15092 const char *nominal_fname;
15093 /* Record where in the search path this file was found.
15094 For #include_next. */
15095 struct file_name_list *dir;
15096 ffewhereLine line;
15097 ffewhereColumn column;
15098 } instack[INPUT_STACK_MAX];
15100 static int last_error_tick = 0; /* Incremented each time we print it. */
15102 /* Current nesting level of input sources.
15103 `instack[indepth]' is the level currently being read. */
15104 static int indepth = -1;
15106 typedef struct file_buf FILE_BUF;
15108 /* Nonzero means -I- has been seen,
15109 so don't look for #include "foo" the source-file directory. */
15110 static int ignore_srcdir;
15112 #ifndef INCLUDE_LEN_FUDGE
15113 #define INCLUDE_LEN_FUDGE 0
15114 #endif
15116 static void append_include_chain (struct file_name_list *first,
15117 struct file_name_list *last);
15118 static FILE *open_include_file (char *filename,
15119 struct file_name_list *searchptr);
15120 static void print_containing_files (ffebadSeverity sev);
15121 static char *read_filename_string (int ch, FILE *f);
15122 static struct file_name_map *read_name_map (const char *dirname);
15124 /* Append a chain of `struct file_name_list's
15125 to the end of the main include chain.
15126 FIRST is the beginning of the chain to append, and LAST is the end. */
15128 static void
15129 append_include_chain (struct file_name_list *first,
15130 struct file_name_list *last)
15132 struct file_name_list *dir;
15134 if (!first || !last)
15135 return;
15137 if (include == 0)
15138 include = first;
15139 else
15140 last_include->next = first;
15142 for (dir = first; ; dir = dir->next) {
15143 int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE;
15144 if (len > max_include_len)
15145 max_include_len = len;
15146 if (dir == last)
15147 break;
15150 last->next = NULL;
15151 last_include = last;
15154 /* Try to open include file FILENAME. SEARCHPTR is the directory
15155 being tried from the include file search path. This function maps
15156 filenames on file systems based on information read by
15157 read_name_map. */
15159 static FILE *
15160 open_include_file (char *filename, struct file_name_list *searchptr)
15162 register struct file_name_map *map;
15163 register char *from;
15164 char *p, *dir;
15166 if (searchptr && ! searchptr->got_name_map)
15168 searchptr->name_map = read_name_map (searchptr->fname
15169 ? searchptr->fname : ".");
15170 searchptr->got_name_map = 1;
15173 /* First check the mapping for the directory we are using. */
15174 if (searchptr && searchptr->name_map)
15176 from = filename;
15177 if (searchptr->fname)
15178 from += strlen (searchptr->fname) + 1;
15179 for (map = searchptr->name_map; map; map = map->map_next)
15181 if (! strcmp (map->map_from, from))
15183 /* Found a match. */
15184 return fopen (map->map_to, "r");
15189 /* Try to find a mapping file for the particular directory we are
15190 looking in. Thus #include <sys/types.h> will look up sys/types.h
15191 in /usr/include/header.gcc and look up types.h in
15192 /usr/include/sys/header.gcc. */
15193 p = strrchr (filename, '/');
15194 #ifdef DIR_SEPARATOR
15195 if (! p) p = strrchr (filename, DIR_SEPARATOR);
15196 else {
15197 char *tmp = strrchr (filename, DIR_SEPARATOR);
15198 if (tmp != NULL && tmp > p) p = tmp;
15200 #endif
15201 if (! p)
15202 p = filename;
15203 if (searchptr
15204 && searchptr->fname
15205 && strlen (searchptr->fname) == (size_t) (p - filename)
15206 && ! strncmp (searchptr->fname, filename, (int) (p - filename)))
15208 /* FILENAME is in SEARCHPTR, which we've already checked. */
15209 return fopen (filename, "r");
15212 if (p == filename)
15214 from = filename;
15215 map = read_name_map (".");
15217 else
15219 dir = xmalloc (p - filename + 1);
15220 memcpy (dir, filename, p - filename);
15221 dir[p - filename] = '\0';
15222 from = p + 1;
15223 map = read_name_map (dir);
15224 free (dir);
15226 for (; map; map = map->map_next)
15227 if (! strcmp (map->map_from, from))
15228 return fopen (map->map_to, "r");
15230 return fopen (filename, "r");
15233 /* Print the file names and line numbers of the #include
15234 commands which led to the current file. */
15236 static void
15237 print_containing_files (ffebadSeverity sev)
15239 FILE_BUF *ip = NULL;
15240 int i;
15241 int first = 1;
15242 const char *str1;
15243 const char *str2;
15245 /* If stack of files hasn't changed since we last printed
15246 this info, don't repeat it. */
15247 if (last_error_tick == input_file_stack_tick)
15248 return;
15250 for (i = indepth; i >= 0; i--)
15251 if (instack[i].fname != NULL) {
15252 ip = &instack[i];
15253 break;
15256 /* Give up if we don't find a source file. */
15257 if (ip == NULL)
15258 return;
15260 /* Find the other, outer source files. */
15261 for (i--; i >= 0; i--)
15262 if (instack[i].fname != NULL)
15264 ip = &instack[i];
15265 if (first)
15267 first = 0;
15268 str1 = "In file included";
15270 else
15272 str1 = "... ...";
15275 if (i == 1)
15276 str2 = ":";
15277 else
15278 str2 = "";
15280 /* xgettext:no-c-format */
15281 ffebad_start_msg ("%A from %B at %0%C", sev);
15282 ffebad_here (0, ip->line, ip->column);
15283 ffebad_string (str1);
15284 ffebad_string (ip->nominal_fname);
15285 ffebad_string (str2);
15286 ffebad_finish ();
15289 /* Record we have printed the status as of this time. */
15290 last_error_tick = input_file_stack_tick;
15293 /* Read a space delimited string of unlimited length from a stdio
15294 file. */
15296 static char *
15297 read_filename_string (int ch, FILE *f)
15299 char *alloc, *set;
15300 int len;
15302 len = 20;
15303 set = alloc = xmalloc (len + 1);
15304 if (! ISSPACE (ch))
15306 *set++ = ch;
15307 while ((ch = getc (f)) != EOF && ! ISSPACE (ch))
15309 if (set - alloc == len)
15311 len *= 2;
15312 alloc = xrealloc (alloc, len + 1);
15313 set = alloc + len / 2;
15315 *set++ = ch;
15318 *set = '\0';
15319 ungetc (ch, f);
15320 return alloc;
15323 /* Read the file name map file for DIRNAME. */
15325 static struct file_name_map *
15326 read_name_map (const char *dirname)
15328 /* This structure holds a linked list of file name maps, one per
15329 directory. */
15330 struct file_name_map_list
15332 struct file_name_map_list *map_list_next;
15333 char *map_list_name;
15334 struct file_name_map *map_list_map;
15336 static struct file_name_map_list *map_list;
15337 register struct file_name_map_list *map_list_ptr;
15338 char *name;
15339 FILE *f;
15340 size_t dirlen;
15341 int separator_needed;
15343 dirname = skip_redundant_dir_prefix (dirname);
15345 for (map_list_ptr = map_list; map_list_ptr;
15346 map_list_ptr = map_list_ptr->map_list_next)
15347 if (! strcmp (map_list_ptr->map_list_name, dirname))
15348 return map_list_ptr->map_list_map;
15350 map_list_ptr = xmalloc (sizeof (struct file_name_map_list));
15351 map_list_ptr->map_list_name = xstrdup (dirname);
15352 map_list_ptr->map_list_map = NULL;
15354 dirlen = strlen (dirname);
15355 separator_needed = dirlen != 0 && dirname[dirlen - 1] != '/';
15356 if (separator_needed)
15357 name = concat (dirname, "/", FILE_NAME_MAP_FILE, NULL);
15358 else
15359 name = concat (dirname, FILE_NAME_MAP_FILE, NULL);
15360 f = fopen (name, "r");
15361 free (name);
15362 if (!f)
15363 map_list_ptr->map_list_map = NULL;
15364 else
15366 int ch;
15368 while ((ch = getc (f)) != EOF)
15370 char *from, *to;
15371 struct file_name_map *ptr;
15373 if (ISSPACE (ch))
15374 continue;
15375 from = read_filename_string (ch, f);
15376 while ((ch = getc (f)) != EOF && ISSPACE (ch) && ch != '\n')
15378 to = read_filename_string (ch, f);
15380 ptr = xmalloc (sizeof (struct file_name_map));
15381 ptr->map_from = from;
15383 /* Make the real filename absolute. */
15384 if (*to == '/')
15385 ptr->map_to = to;
15386 else
15388 if (separator_needed)
15389 ptr->map_to = concat (dirname, "/", to, NULL);
15390 else
15391 ptr->map_to = concat (dirname, to, NULL);
15392 free (to);
15395 ptr->map_next = map_list_ptr->map_list_map;
15396 map_list_ptr->map_list_map = ptr;
15398 while ((ch = getc (f)) != '\n')
15399 if (ch == EOF)
15400 break;
15402 fclose (f);
15405 map_list_ptr->map_list_next = map_list;
15406 map_list = map_list_ptr;
15408 return map_list_ptr->map_list_map;
15411 static void
15412 ffecom_file_ (const char *name)
15414 FILE_BUF *fp;
15416 /* Do partial setup of input buffer for the sake of generating
15417 early #line directives (when -g is in effect). */
15419 fp = &instack[++indepth];
15420 memset (fp, 0, sizeof (FILE_BUF));
15421 if (name == NULL)
15422 name = "";
15423 fp->nominal_fname = fp->fname = name;
15426 static void
15427 ffecom_close_include_ (FILE *f)
15429 fclose (f);
15431 indepth--;
15432 input_file_stack_tick++;
15434 ffewhere_line_kill (instack[indepth].line);
15435 ffewhere_column_kill (instack[indepth].column);
15438 void
15439 ffecom_decode_include_option (const char *dir)
15441 if (! ignore_srcdir && !strcmp (dir, "-"))
15442 ignore_srcdir = 1;
15443 else
15445 struct file_name_list *dirtmp
15446 = xmalloc (sizeof (struct file_name_list));
15447 dirtmp->next = 0; /* New one goes on the end */
15448 dirtmp->fname = dir;
15449 dirtmp->got_name_map = 0;
15450 append_include_chain (dirtmp, dirtmp);
15454 /* Open INCLUDEd file. */
15456 static FILE *
15457 ffecom_open_include_ (char *name, ffewhereLine l, ffewhereColumn c)
15459 char *fbeg = name;
15460 size_t flen = strlen (fbeg);
15461 struct file_name_list *search_start = include; /* Chain of dirs to search */
15462 struct file_name_list dsp[1]; /* First in chain, if #include "..." */
15463 struct file_name_list *searchptr = 0;
15464 char *fname; /* Dynamically allocated fname buffer */
15465 FILE *f;
15466 FILE_BUF *fp;
15468 if (flen == 0)
15469 return NULL;
15471 dsp[0].fname = NULL;
15473 /* If -I- was specified, don't search current dir, only spec'd ones. */
15474 if (!ignore_srcdir)
15476 for (fp = &instack[indepth]; fp >= instack; fp--)
15478 int n;
15479 char *ep;
15480 const char *nam;
15482 if ((nam = fp->nominal_fname) != NULL)
15484 /* Found a named file. Figure out dir of the file,
15485 and put it in front of the search list. */
15486 dsp[0].next = search_start;
15487 search_start = dsp;
15488 #ifndef VMS
15489 ep = strrchr (nam, '/');
15490 #ifdef DIR_SEPARATOR
15491 if (ep == NULL) ep = strrchr (nam, DIR_SEPARATOR);
15492 else {
15493 char *tmp = strrchr (nam, DIR_SEPARATOR);
15494 if (tmp != NULL && tmp > ep) ep = tmp;
15496 #endif
15497 #else /* VMS */
15498 ep = strrchr (nam, ']');
15499 if (ep == NULL) ep = strrchr (nam, '>');
15500 if (ep == NULL) ep = strrchr (nam, ':');
15501 if (ep != NULL) ep++;
15502 #endif /* VMS */
15503 if (ep != NULL)
15505 n = ep - nam;
15506 fname = xmalloc (n + 1);
15507 strncpy (fname, nam, n);
15508 fname[n] = '\0';
15509 dsp[0].fname = fname;
15510 if (n + INCLUDE_LEN_FUDGE > max_include_len)
15511 max_include_len = n + INCLUDE_LEN_FUDGE;
15513 else
15514 dsp[0].fname = NULL; /* Current directory */
15515 dsp[0].got_name_map = 0;
15516 break;
15521 /* Allocate this permanently, because it gets stored in the definitions
15522 of macros. */
15523 fname = xmalloc (max_include_len + flen + 4);
15524 /* + 2 above for slash and terminating null. */
15525 /* + 2 added for '.h' on VMS (to support '#include filename') (NOT USED
15526 for g77 yet). */
15528 /* If specified file name is absolute, just open it. */
15530 if (*fbeg == '/'
15531 #ifdef DIR_SEPARATOR
15532 || *fbeg == DIR_SEPARATOR
15533 #endif
15536 strncpy (fname, (char *) fbeg, flen);
15537 fname[flen] = 0;
15538 f = open_include_file (fname, NULL);
15540 else
15542 f = NULL;
15544 /* Search directory path, trying to open the file.
15545 Copy each filename tried into FNAME. */
15547 for (searchptr = search_start; searchptr; searchptr = searchptr->next)
15549 if (searchptr->fname)
15551 /* The empty string in a search path is ignored.
15552 This makes it possible to turn off entirely
15553 a standard piece of the list. */
15554 if (searchptr->fname[0] == 0)
15555 continue;
15556 strcpy (fname, skip_redundant_dir_prefix (searchptr->fname));
15557 if (fname[0] && fname[strlen (fname) - 1] != '/')
15558 strcat (fname, "/");
15559 fname[strlen (fname) + flen] = 0;
15561 else
15562 fname[0] = 0;
15564 strncat (fname, fbeg, flen);
15565 #ifdef VMS
15566 /* Change this 1/2 Unix 1/2 VMS file specification into a
15567 full VMS file specification */
15568 if (searchptr->fname && (searchptr->fname[0] != 0))
15570 /* Fix up the filename */
15571 hack_vms_include_specification (fname);
15573 else
15575 /* This is a normal VMS filespec, so use it unchanged. */
15576 strncpy (fname, (char *) fbeg, flen);
15577 fname[flen] = 0;
15578 #if 0 /* Not for g77. */
15579 /* if it's '#include filename', add the missing .h */
15580 if (strchr (fname, '.') == NULL)
15581 strcat (fname, ".h");
15582 #endif
15584 #endif /* VMS */
15585 f = open_include_file (fname, searchptr);
15586 #ifdef EACCES
15587 if (f == NULL && errno == EACCES)
15589 print_containing_files (FFEBAD_severityWARNING);
15590 /* xgettext:no-c-format */
15591 ffebad_start_msg ("At %0, INCLUDE file %A exists, but is not readable",
15592 FFEBAD_severityWARNING);
15593 ffebad_string (fname);
15594 ffebad_here (0, l, c);
15595 ffebad_finish ();
15597 #endif
15598 if (f != NULL)
15599 break;
15603 if (f == NULL)
15605 /* A file that was not found. */
15607 strncpy (fname, (char *) fbeg, flen);
15608 fname[flen] = 0;
15609 print_containing_files (ffebad_severity (FFEBAD_OPEN_INCLUDE));
15610 ffebad_start (FFEBAD_OPEN_INCLUDE);
15611 ffebad_here (0, l, c);
15612 ffebad_string (fname);
15613 ffebad_finish ();
15616 if (dsp[0].fname != NULL)
15617 free ((char *) dsp[0].fname);
15619 if (f == NULL)
15620 return NULL;
15622 if (indepth >= (INPUT_STACK_MAX - 1))
15624 print_containing_files (FFEBAD_severityFATAL);
15625 /* xgettext:no-c-format */
15626 ffebad_start_msg ("At %0, INCLUDE nesting too deep",
15627 FFEBAD_severityFATAL);
15628 ffebad_string (fname);
15629 ffebad_here (0, l, c);
15630 ffebad_finish ();
15631 return NULL;
15634 instack[indepth].line = ffewhere_line_use (l);
15635 instack[indepth].column = ffewhere_column_use (c);
15637 fp = &instack[indepth + 1];
15638 memset (fp, 0, sizeof (FILE_BUF));
15639 fp->nominal_fname = fp->fname = fname;
15640 fp->dir = searchptr;
15642 indepth++;
15643 input_file_stack_tick++;
15645 return f;
15648 /**INDENT* (Do not reformat this comment even with -fca option.)
15649 Data-gathering files: Given the source file listed below, compiled with
15650 f2c I obtained the output file listed after that, and from the output
15651 file I derived the above code.
15653 -------- (begin input file to f2c)
15654 implicit none
15655 character*10 A1,A2
15656 complex C1,C2
15657 integer I1,I2
15658 real R1,R2
15659 double precision D1,D2
15661 call getem(A1,A2,C1,C2,I1,I2,R1,R2,D1,D2)
15663 call fooI(I1/I2)
15664 call fooR(R1/I1)
15665 call fooD(D1/I1)
15666 call fooC(C1/I1)
15667 call fooR(R1/R2)
15668 call fooD(R1/D1)
15669 call fooD(D1/D2)
15670 call fooD(D1/R1)
15671 call fooC(C1/C2)
15672 call fooC(C1/R1)
15673 call fooZ(C1/D1)
15674 c **
15675 call fooI(I1**I2)
15676 call fooR(R1**I1)
15677 call fooD(D1**I1)
15678 call fooC(C1**I1)
15679 call fooR(R1**R2)
15680 call fooD(R1**D1)
15681 call fooD(D1**D2)
15682 call fooD(D1**R1)
15683 call fooC(C1**C2)
15684 call fooC(C1**R1)
15685 call fooZ(C1**D1)
15686 c FFEINTRIN_impABS
15687 call fooR(ABS(R1))
15688 c FFEINTRIN_impACOS
15689 call fooR(ACOS(R1))
15690 c FFEINTRIN_impAIMAG
15691 call fooR(AIMAG(C1))
15692 c FFEINTRIN_impAINT
15693 call fooR(AINT(R1))
15694 c FFEINTRIN_impALOG
15695 call fooR(ALOG(R1))
15696 c FFEINTRIN_impALOG10
15697 call fooR(ALOG10(R1))
15698 c FFEINTRIN_impAMAX0
15699 call fooR(AMAX0(I1,I2))
15700 c FFEINTRIN_impAMAX1
15701 call fooR(AMAX1(R1,R2))
15702 c FFEINTRIN_impAMIN0
15703 call fooR(AMIN0(I1,I2))
15704 c FFEINTRIN_impAMIN1
15705 call fooR(AMIN1(R1,R2))
15706 c FFEINTRIN_impAMOD
15707 call fooR(AMOD(R1,R2))
15708 c FFEINTRIN_impANINT
15709 call fooR(ANINT(R1))
15710 c FFEINTRIN_impASIN
15711 call fooR(ASIN(R1))
15712 c FFEINTRIN_impATAN
15713 call fooR(ATAN(R1))
15714 c FFEINTRIN_impATAN2
15715 call fooR(ATAN2(R1,R2))
15716 c FFEINTRIN_impCABS
15717 call fooR(CABS(C1))
15718 c FFEINTRIN_impCCOS
15719 call fooC(CCOS(C1))
15720 c FFEINTRIN_impCEXP
15721 call fooC(CEXP(C1))
15722 c FFEINTRIN_impCHAR
15723 call fooA(CHAR(I1))
15724 c FFEINTRIN_impCLOG
15725 call fooC(CLOG(C1))
15726 c FFEINTRIN_impCONJG
15727 call fooC(CONJG(C1))
15728 c FFEINTRIN_impCOS
15729 call fooR(COS(R1))
15730 c FFEINTRIN_impCOSH
15731 call fooR(COSH(R1))
15732 c FFEINTRIN_impCSIN
15733 call fooC(CSIN(C1))
15734 c FFEINTRIN_impCSQRT
15735 call fooC(CSQRT(C1))
15736 c FFEINTRIN_impDABS
15737 call fooD(DABS(D1))
15738 c FFEINTRIN_impDACOS
15739 call fooD(DACOS(D1))
15740 c FFEINTRIN_impDASIN
15741 call fooD(DASIN(D1))
15742 c FFEINTRIN_impDATAN
15743 call fooD(DATAN(D1))
15744 c FFEINTRIN_impDATAN2
15745 call fooD(DATAN2(D1,D2))
15746 c FFEINTRIN_impDCOS
15747 call fooD(DCOS(D1))
15748 c FFEINTRIN_impDCOSH
15749 call fooD(DCOSH(D1))
15750 c FFEINTRIN_impDDIM
15751 call fooD(DDIM(D1,D2))
15752 c FFEINTRIN_impDEXP
15753 call fooD(DEXP(D1))
15754 c FFEINTRIN_impDIM
15755 call fooR(DIM(R1,R2))
15756 c FFEINTRIN_impDINT
15757 call fooD(DINT(D1))
15758 c FFEINTRIN_impDLOG
15759 call fooD(DLOG(D1))
15760 c FFEINTRIN_impDLOG10
15761 call fooD(DLOG10(D1))
15762 c FFEINTRIN_impDMAX1
15763 call fooD(DMAX1(D1,D2))
15764 c FFEINTRIN_impDMIN1
15765 call fooD(DMIN1(D1,D2))
15766 c FFEINTRIN_impDMOD
15767 call fooD(DMOD(D1,D2))
15768 c FFEINTRIN_impDNINT
15769 call fooD(DNINT(D1))
15770 c FFEINTRIN_impDPROD
15771 call fooD(DPROD(R1,R2))
15772 c FFEINTRIN_impDSIGN
15773 call fooD(DSIGN(D1,D2))
15774 c FFEINTRIN_impDSIN
15775 call fooD(DSIN(D1))
15776 c FFEINTRIN_impDSINH
15777 call fooD(DSINH(D1))
15778 c FFEINTRIN_impDSQRT
15779 call fooD(DSQRT(D1))
15780 c FFEINTRIN_impDTAN
15781 call fooD(DTAN(D1))
15782 c FFEINTRIN_impDTANH
15783 call fooD(DTANH(D1))
15784 c FFEINTRIN_impEXP
15785 call fooR(EXP(R1))
15786 c FFEINTRIN_impIABS
15787 call fooI(IABS(I1))
15788 c FFEINTRIN_impICHAR
15789 call fooI(ICHAR(A1))
15790 c FFEINTRIN_impIDIM
15791 call fooI(IDIM(I1,I2))
15792 c FFEINTRIN_impIDNINT
15793 call fooI(IDNINT(D1))
15794 c FFEINTRIN_impINDEX
15795 call fooI(INDEX(A1,A2))
15796 c FFEINTRIN_impISIGN
15797 call fooI(ISIGN(I1,I2))
15798 c FFEINTRIN_impLEN
15799 call fooI(LEN(A1))
15800 c FFEINTRIN_impLGE
15801 call fooL(LGE(A1,A2))
15802 c FFEINTRIN_impLGT
15803 call fooL(LGT(A1,A2))
15804 c FFEINTRIN_impLLE
15805 call fooL(LLE(A1,A2))
15806 c FFEINTRIN_impLLT
15807 call fooL(LLT(A1,A2))
15808 c FFEINTRIN_impMAX0
15809 call fooI(MAX0(I1,I2))
15810 c FFEINTRIN_impMAX1
15811 call fooI(MAX1(R1,R2))
15812 c FFEINTRIN_impMIN0
15813 call fooI(MIN0(I1,I2))
15814 c FFEINTRIN_impMIN1
15815 call fooI(MIN1(R1,R2))
15816 c FFEINTRIN_impMOD
15817 call fooI(MOD(I1,I2))
15818 c FFEINTRIN_impNINT
15819 call fooI(NINT(R1))
15820 c FFEINTRIN_impSIGN
15821 call fooR(SIGN(R1,R2))
15822 c FFEINTRIN_impSIN
15823 call fooR(SIN(R1))
15824 c FFEINTRIN_impSINH
15825 call fooR(SINH(R1))
15826 c FFEINTRIN_impSQRT
15827 call fooR(SQRT(R1))
15828 c FFEINTRIN_impTAN
15829 call fooR(TAN(R1))
15830 c FFEINTRIN_impTANH
15831 call fooR(TANH(R1))
15832 c FFEINTRIN_imp_CMPLX_C
15833 call fooC(cmplx(C1,C2))
15834 c FFEINTRIN_imp_CMPLX_D
15835 call fooZ(cmplx(D1,D2))
15836 c FFEINTRIN_imp_CMPLX_I
15837 call fooC(cmplx(I1,I2))
15838 c FFEINTRIN_imp_CMPLX_R
15839 call fooC(cmplx(R1,R2))
15840 c FFEINTRIN_imp_DBLE_C
15841 call fooD(dble(C1))
15842 c FFEINTRIN_imp_DBLE_D
15843 call fooD(dble(D1))
15844 c FFEINTRIN_imp_DBLE_I
15845 call fooD(dble(I1))
15846 c FFEINTRIN_imp_DBLE_R
15847 call fooD(dble(R1))
15848 c FFEINTRIN_imp_INT_C
15849 call fooI(int(C1))
15850 c FFEINTRIN_imp_INT_D
15851 call fooI(int(D1))
15852 c FFEINTRIN_imp_INT_I
15853 call fooI(int(I1))
15854 c FFEINTRIN_imp_INT_R
15855 call fooI(int(R1))
15856 c FFEINTRIN_imp_REAL_C
15857 call fooR(real(C1))
15858 c FFEINTRIN_imp_REAL_D
15859 call fooR(real(D1))
15860 c FFEINTRIN_imp_REAL_I
15861 call fooR(real(I1))
15862 c FFEINTRIN_imp_REAL_R
15863 call fooR(real(R1))
15865 c FFEINTRIN_imp_INT_D:
15867 c FFEINTRIN_specIDINT
15868 call fooI(IDINT(D1))
15870 c FFEINTRIN_imp_INT_R:
15872 c FFEINTRIN_specIFIX
15873 call fooI(IFIX(R1))
15874 c FFEINTRIN_specINT
15875 call fooI(INT(R1))
15877 c FFEINTRIN_imp_REAL_D:
15879 c FFEINTRIN_specSNGL
15880 call fooR(SNGL(D1))
15882 c FFEINTRIN_imp_REAL_I:
15884 c FFEINTRIN_specFLOAT
15885 call fooR(FLOAT(I1))
15886 c FFEINTRIN_specREAL
15887 call fooR(REAL(I1))
15890 -------- (end input file to f2c)
15892 -------- (begin output from providing above input file as input to:
15893 -------- `f2c | gcc -E -C - | sed -e "s:/[*]*://:g" -e "s:[*]*[/]://:g" \
15894 -------- -e "s:^#.*$::g"')
15896 // -- translated by f2c (version 19950223).
15897 You must link the resulting object file with the libraries:
15898 -lf2c -lm (in that order)
15902 // f2c.h -- Standard Fortran to C header file //
15904 /// barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed."
15906 - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) //
15911 // F2C_INTEGER will normally be `int' but would be `long' on 16-bit systems //
15912 // we assume short, float are OK //
15913 typedef long int // long int // integer;
15914 typedef char *address;
15915 typedef short int shortint;
15916 typedef float real;
15917 typedef double doublereal;
15918 typedef struct { real r, i; } complex;
15919 typedef struct { doublereal r, i; } doublecomplex;
15920 typedef long int // long int // logical;
15921 typedef short int shortlogical;
15922 typedef char logical1;
15923 typedef char integer1;
15924 // typedef long long longint; // // system-dependent //
15929 // Extern is for use with -E //
15934 // I/O stuff //
15943 typedef long int // int or long int // flag;
15944 typedef long int // int or long int // ftnlen;
15945 typedef long int // int or long int // ftnint;
15948 //external read, write//
15949 typedef struct
15950 { flag cierr;
15951 ftnint ciunit;
15952 flag ciend;
15953 char *cifmt;
15954 ftnint cirec;
15955 } cilist;
15957 //internal read, write//
15958 typedef struct
15959 { flag icierr;
15960 char *iciunit;
15961 flag iciend;
15962 char *icifmt;
15963 ftnint icirlen;
15964 ftnint icirnum;
15965 } icilist;
15967 //open//
15968 typedef struct
15969 { flag oerr;
15970 ftnint ounit;
15971 char *ofnm;
15972 ftnlen ofnmlen;
15973 char *osta;
15974 char *oacc;
15975 char *ofm;
15976 ftnint orl;
15977 char *oblnk;
15978 } olist;
15980 //close//
15981 typedef struct
15982 { flag cerr;
15983 ftnint cunit;
15984 char *csta;
15985 } cllist;
15987 //rewind, backspace, endfile//
15988 typedef struct
15989 { flag aerr;
15990 ftnint aunit;
15991 } alist;
15993 // inquire //
15994 typedef struct
15995 { flag inerr;
15996 ftnint inunit;
15997 char *infile;
15998 ftnlen infilen;
15999 ftnint *inex; //parameters in standard's order//
16000 ftnint *inopen;
16001 ftnint *innum;
16002 ftnint *innamed;
16003 char *inname;
16004 ftnlen innamlen;
16005 char *inacc;
16006 ftnlen inacclen;
16007 char *inseq;
16008 ftnlen inseqlen;
16009 char *indir;
16010 ftnlen indirlen;
16011 char *infmt;
16012 ftnlen infmtlen;
16013 char *inform;
16014 ftnint informlen;
16015 char *inunf;
16016 ftnlen inunflen;
16017 ftnint *inrecl;
16018 ftnint *innrec;
16019 char *inblank;
16020 ftnlen inblanklen;
16021 } inlist;
16025 union Multitype { // for multiple entry points //
16026 integer1 g;
16027 shortint h;
16028 integer i;
16029 // longint j; //
16030 real r;
16031 doublereal d;
16032 complex c;
16033 doublecomplex z;
16036 typedef union Multitype Multitype;
16038 typedef long Long; // No longer used; formerly in Namelist //
16040 struct Vardesc { // for Namelist //
16041 char *name;
16042 char *addr;
16043 ftnlen *dims;
16044 int type;
16046 typedef struct Vardesc Vardesc;
16048 struct Namelist {
16049 char *name;
16050 Vardesc **vars;
16051 int nvars;
16053 typedef struct Namelist Namelist;
16062 // procedure parameter types for -A and -C++ //
16067 typedef int // Unknown procedure type // (*U_fp)();
16068 typedef shortint (*J_fp)();
16069 typedef integer (*I_fp)();
16070 typedef real (*R_fp)();
16071 typedef doublereal (*D_fp)(), (*E_fp)();
16072 typedef // Complex // void (*C_fp)();
16073 typedef // Double Complex // void (*Z_fp)();
16074 typedef logical (*L_fp)();
16075 typedef shortlogical (*K_fp)();
16076 typedef // Character // void (*H_fp)();
16077 typedef // Subroutine // int (*S_fp)();
16079 // E_fp is for real functions when -R is not specified //
16080 typedef void C_f; // complex function //
16081 typedef void H_f; // character function //
16082 typedef void Z_f; // double complex function //
16083 typedef doublereal E_f; // real function with -R not specified //
16085 // undef any lower-case symbols that your C compiler predefines, e.g.: //
16088 // (No such symbols should be defined in a strict ANSI C compiler.
16089 We can avoid trouble with f2c-translated code by using
16090 gcc -ansi.) //
16114 // Main program // MAIN__()
16116 // System generated locals //
16117 integer i__1;
16118 real r__1, r__2;
16119 doublereal d__1, d__2;
16120 complex q__1;
16121 doublecomplex z__1, z__2, z__3;
16122 logical L__1;
16123 char ch__1[1];
16125 // Builtin functions //
16126 void c_div();
16127 integer pow_ii();
16128 double pow_ri(), pow_di();
16129 void pow_ci();
16130 double pow_dd();
16131 void pow_zz();
16132 double acos(), r_imag(), r_int(), log(), r_lg10(), r_mod(), r_nint(),
16133 asin(), atan(), atan2(), c_abs();
16134 void c_cos(), c_exp(), c_log(), r_cnjg();
16135 double cos(), cosh();
16136 void c_sin(), c_sqrt();
16137 double d_dim(), exp(), r_dim(), d_int(), d_lg10(), d_mod(), d_nint(),
16138 d_sign(), sin(), sinh(), sqrt(), tan(), tanh();
16139 integer i_dim(), i_dnnt(), i_indx(), i_sign(), i_len();
16140 logical l_ge(), l_gt(), l_le(), l_lt();
16141 integer i_nint();
16142 double r_sign();
16144 // Local variables //
16145 extern // Subroutine // int fooa_(), fooc_(), food_(), fooi_(), foor_(),
16146 fool_(), fooz_(), getem_();
16147 static char a1[10], a2[10];
16148 static complex c1, c2;
16149 static doublereal d1, d2;
16150 static integer i1, i2;
16151 static real r1, r2;
16154 getem_(a1, a2, &c1, &c2, &i1, &i2, &r1, &r2, &d1, &d2, 10L, 10L);
16155 // / //
16156 i__1 = i1 / i2;
16157 fooi_(&i__1);
16158 r__1 = r1 / i1;
16159 foor_(&r__1);
16160 d__1 = d1 / i1;
16161 food_(&d__1);
16162 d__1 = (doublereal) i1;
16163 q__1.r = c1.r / d__1, q__1.i = c1.i / d__1;
16164 fooc_(&q__1);
16165 r__1 = r1 / r2;
16166 foor_(&r__1);
16167 d__1 = r1 / d1;
16168 food_(&d__1);
16169 d__1 = d1 / d2;
16170 food_(&d__1);
16171 d__1 = d1 / r1;
16172 food_(&d__1);
16173 c_div(&q__1, &c1, &c2);
16174 fooc_(&q__1);
16175 q__1.r = c1.r / r1, q__1.i = c1.i / r1;
16176 fooc_(&q__1);
16177 z__1.r = c1.r / d1, z__1.i = c1.i / d1;
16178 fooz_(&z__1);
16179 // ** //
16180 i__1 = pow_ii(&i1, &i2);
16181 fooi_(&i__1);
16182 r__1 = pow_ri(&r1, &i1);
16183 foor_(&r__1);
16184 d__1 = pow_di(&d1, &i1);
16185 food_(&d__1);
16186 pow_ci(&q__1, &c1, &i1);
16187 fooc_(&q__1);
16188 d__1 = (doublereal) r1;
16189 d__2 = (doublereal) r2;
16190 r__1 = pow_dd(&d__1, &d__2);
16191 foor_(&r__1);
16192 d__2 = (doublereal) r1;
16193 d__1 = pow_dd(&d__2, &d1);
16194 food_(&d__1);
16195 d__1 = pow_dd(&d1, &d2);
16196 food_(&d__1);
16197 d__2 = (doublereal) r1;
16198 d__1 = pow_dd(&d1, &d__2);
16199 food_(&d__1);
16200 z__2.r = c1.r, z__2.i = c1.i;
16201 z__3.r = c2.r, z__3.i = c2.i;
16202 pow_zz(&z__1, &z__2, &z__3);
16203 q__1.r = z__1.r, q__1.i = z__1.i;
16204 fooc_(&q__1);
16205 z__2.r = c1.r, z__2.i = c1.i;
16206 z__3.r = r1, z__3.i = 0.;
16207 pow_zz(&z__1, &z__2, &z__3);
16208 q__1.r = z__1.r, q__1.i = z__1.i;
16209 fooc_(&q__1);
16210 z__2.r = c1.r, z__2.i = c1.i;
16211 z__3.r = d1, z__3.i = 0.;
16212 pow_zz(&z__1, &z__2, &z__3);
16213 fooz_(&z__1);
16214 // FFEINTRIN_impABS //
16215 r__1 = (doublereal)(( r1 ) >= 0 ? ( r1 ) : -( r1 )) ;
16216 foor_(&r__1);
16217 // FFEINTRIN_impACOS //
16218 r__1 = acos(r1);
16219 foor_(&r__1);
16220 // FFEINTRIN_impAIMAG //
16221 r__1 = r_imag(&c1);
16222 foor_(&r__1);
16223 // FFEINTRIN_impAINT //
16224 r__1 = r_int(&r1);
16225 foor_(&r__1);
16226 // FFEINTRIN_impALOG //
16227 r__1 = log(r1);
16228 foor_(&r__1);
16229 // FFEINTRIN_impALOG10 //
16230 r__1 = r_lg10(&r1);
16231 foor_(&r__1);
16232 // FFEINTRIN_impAMAX0 //
16233 r__1 = (real) (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
16234 foor_(&r__1);
16235 // FFEINTRIN_impAMAX1 //
16236 r__1 = (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
16237 foor_(&r__1);
16238 // FFEINTRIN_impAMIN0 //
16239 r__1 = (real) (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
16240 foor_(&r__1);
16241 // FFEINTRIN_impAMIN1 //
16242 r__1 = (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
16243 foor_(&r__1);
16244 // FFEINTRIN_impAMOD //
16245 r__1 = r_mod(&r1, &r2);
16246 foor_(&r__1);
16247 // FFEINTRIN_impANINT //
16248 r__1 = r_nint(&r1);
16249 foor_(&r__1);
16250 // FFEINTRIN_impASIN //
16251 r__1 = asin(r1);
16252 foor_(&r__1);
16253 // FFEINTRIN_impATAN //
16254 r__1 = atan(r1);
16255 foor_(&r__1);
16256 // FFEINTRIN_impATAN2 //
16257 r__1 = atan2(r1, r2);
16258 foor_(&r__1);
16259 // FFEINTRIN_impCABS //
16260 r__1 = c_abs(&c1);
16261 foor_(&r__1);
16262 // FFEINTRIN_impCCOS //
16263 c_cos(&q__1, &c1);
16264 fooc_(&q__1);
16265 // FFEINTRIN_impCEXP //
16266 c_exp(&q__1, &c1);
16267 fooc_(&q__1);
16268 // FFEINTRIN_impCHAR //
16269 *(unsigned char *)&ch__1[0] = i1;
16270 fooa_(ch__1, 1L);
16271 // FFEINTRIN_impCLOG //
16272 c_log(&q__1, &c1);
16273 fooc_(&q__1);
16274 // FFEINTRIN_impCONJG //
16275 r_cnjg(&q__1, &c1);
16276 fooc_(&q__1);
16277 // FFEINTRIN_impCOS //
16278 r__1 = cos(r1);
16279 foor_(&r__1);
16280 // FFEINTRIN_impCOSH //
16281 r__1 = cosh(r1);
16282 foor_(&r__1);
16283 // FFEINTRIN_impCSIN //
16284 c_sin(&q__1, &c1);
16285 fooc_(&q__1);
16286 // FFEINTRIN_impCSQRT //
16287 c_sqrt(&q__1, &c1);
16288 fooc_(&q__1);
16289 // FFEINTRIN_impDABS //
16290 d__1 = (( d1 ) >= 0 ? ( d1 ) : -( d1 )) ;
16291 food_(&d__1);
16292 // FFEINTRIN_impDACOS //
16293 d__1 = acos(d1);
16294 food_(&d__1);
16295 // FFEINTRIN_impDASIN //
16296 d__1 = asin(d1);
16297 food_(&d__1);
16298 // FFEINTRIN_impDATAN //
16299 d__1 = atan(d1);
16300 food_(&d__1);
16301 // FFEINTRIN_impDATAN2 //
16302 d__1 = atan2(d1, d2);
16303 food_(&d__1);
16304 // FFEINTRIN_impDCOS //
16305 d__1 = cos(d1);
16306 food_(&d__1);
16307 // FFEINTRIN_impDCOSH //
16308 d__1 = cosh(d1);
16309 food_(&d__1);
16310 // FFEINTRIN_impDDIM //
16311 d__1 = d_dim(&d1, &d2);
16312 food_(&d__1);
16313 // FFEINTRIN_impDEXP //
16314 d__1 = exp(d1);
16315 food_(&d__1);
16316 // FFEINTRIN_impDIM //
16317 r__1 = r_dim(&r1, &r2);
16318 foor_(&r__1);
16319 // FFEINTRIN_impDINT //
16320 d__1 = d_int(&d1);
16321 food_(&d__1);
16322 // FFEINTRIN_impDLOG //
16323 d__1 = log(d1);
16324 food_(&d__1);
16325 // FFEINTRIN_impDLOG10 //
16326 d__1 = d_lg10(&d1);
16327 food_(&d__1);
16328 // FFEINTRIN_impDMAX1 //
16329 d__1 = (( d1 ) >= ( d2 ) ? ( d1 ) : ( d2 )) ;
16330 food_(&d__1);
16331 // FFEINTRIN_impDMIN1 //
16332 d__1 = (( d1 ) <= ( d2 ) ? ( d1 ) : ( d2 )) ;
16333 food_(&d__1);
16334 // FFEINTRIN_impDMOD //
16335 d__1 = d_mod(&d1, &d2);
16336 food_(&d__1);
16337 // FFEINTRIN_impDNINT //
16338 d__1 = d_nint(&d1);
16339 food_(&d__1);
16340 // FFEINTRIN_impDPROD //
16341 d__1 = (doublereal) r1 * r2;
16342 food_(&d__1);
16343 // FFEINTRIN_impDSIGN //
16344 d__1 = d_sign(&d1, &d2);
16345 food_(&d__1);
16346 // FFEINTRIN_impDSIN //
16347 d__1 = sin(d1);
16348 food_(&d__1);
16349 // FFEINTRIN_impDSINH //
16350 d__1 = sinh(d1);
16351 food_(&d__1);
16352 // FFEINTRIN_impDSQRT //
16353 d__1 = sqrt(d1);
16354 food_(&d__1);
16355 // FFEINTRIN_impDTAN //
16356 d__1 = tan(d1);
16357 food_(&d__1);
16358 // FFEINTRIN_impDTANH //
16359 d__1 = tanh(d1);
16360 food_(&d__1);
16361 // FFEINTRIN_impEXP //
16362 r__1 = exp(r1);
16363 foor_(&r__1);
16364 // FFEINTRIN_impIABS //
16365 i__1 = (( i1 ) >= 0 ? ( i1 ) : -( i1 )) ;
16366 fooi_(&i__1);
16367 // FFEINTRIN_impICHAR //
16368 i__1 = *(unsigned char *)a1;
16369 fooi_(&i__1);
16370 // FFEINTRIN_impIDIM //
16371 i__1 = i_dim(&i1, &i2);
16372 fooi_(&i__1);
16373 // FFEINTRIN_impIDNINT //
16374 i__1 = i_dnnt(&d1);
16375 fooi_(&i__1);
16376 // FFEINTRIN_impINDEX //
16377 i__1 = i_indx(a1, a2, 10L, 10L);
16378 fooi_(&i__1);
16379 // FFEINTRIN_impISIGN //
16380 i__1 = i_sign(&i1, &i2);
16381 fooi_(&i__1);
16382 // FFEINTRIN_impLEN //
16383 i__1 = i_len(a1, 10L);
16384 fooi_(&i__1);
16385 // FFEINTRIN_impLGE //
16386 L__1 = l_ge(a1, a2, 10L, 10L);
16387 fool_(&L__1);
16388 // FFEINTRIN_impLGT //
16389 L__1 = l_gt(a1, a2, 10L, 10L);
16390 fool_(&L__1);
16391 // FFEINTRIN_impLLE //
16392 L__1 = l_le(a1, a2, 10L, 10L);
16393 fool_(&L__1);
16394 // FFEINTRIN_impLLT //
16395 L__1 = l_lt(a1, a2, 10L, 10L);
16396 fool_(&L__1);
16397 // FFEINTRIN_impMAX0 //
16398 i__1 = (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
16399 fooi_(&i__1);
16400 // FFEINTRIN_impMAX1 //
16401 i__1 = (integer) (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
16402 fooi_(&i__1);
16403 // FFEINTRIN_impMIN0 //
16404 i__1 = (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
16405 fooi_(&i__1);
16406 // FFEINTRIN_impMIN1 //
16407 i__1 = (integer) (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
16408 fooi_(&i__1);
16409 // FFEINTRIN_impMOD //
16410 i__1 = i1 % i2;
16411 fooi_(&i__1);
16412 // FFEINTRIN_impNINT //
16413 i__1 = i_nint(&r1);
16414 fooi_(&i__1);
16415 // FFEINTRIN_impSIGN //
16416 r__1 = r_sign(&r1, &r2);
16417 foor_(&r__1);
16418 // FFEINTRIN_impSIN //
16419 r__1 = sin(r1);
16420 foor_(&r__1);
16421 // FFEINTRIN_impSINH //
16422 r__1 = sinh(r1);
16423 foor_(&r__1);
16424 // FFEINTRIN_impSQRT //
16425 r__1 = sqrt(r1);
16426 foor_(&r__1);
16427 // FFEINTRIN_impTAN //
16428 r__1 = tan(r1);
16429 foor_(&r__1);
16430 // FFEINTRIN_impTANH //
16431 r__1 = tanh(r1);
16432 foor_(&r__1);
16433 // FFEINTRIN_imp_CMPLX_C //
16434 r__1 = c1.r;
16435 r__2 = c2.r;
16436 q__1.r = r__1, q__1.i = r__2;
16437 fooc_(&q__1);
16438 // FFEINTRIN_imp_CMPLX_D //
16439 z__1.r = d1, z__1.i = d2;
16440 fooz_(&z__1);
16441 // FFEINTRIN_imp_CMPLX_I //
16442 r__1 = (real) i1;
16443 r__2 = (real) i2;
16444 q__1.r = r__1, q__1.i = r__2;
16445 fooc_(&q__1);
16446 // FFEINTRIN_imp_CMPLX_R //
16447 q__1.r = r1, q__1.i = r2;
16448 fooc_(&q__1);
16449 // FFEINTRIN_imp_DBLE_C //
16450 d__1 = (doublereal) c1.r;
16451 food_(&d__1);
16452 // FFEINTRIN_imp_DBLE_D //
16453 d__1 = d1;
16454 food_(&d__1);
16455 // FFEINTRIN_imp_DBLE_I //
16456 d__1 = (doublereal) i1;
16457 food_(&d__1);
16458 // FFEINTRIN_imp_DBLE_R //
16459 d__1 = (doublereal) r1;
16460 food_(&d__1);
16461 // FFEINTRIN_imp_INT_C //
16462 i__1 = (integer) c1.r;
16463 fooi_(&i__1);
16464 // FFEINTRIN_imp_INT_D //
16465 i__1 = (integer) d1;
16466 fooi_(&i__1);
16467 // FFEINTRIN_imp_INT_I //
16468 i__1 = i1;
16469 fooi_(&i__1);
16470 // FFEINTRIN_imp_INT_R //
16471 i__1 = (integer) r1;
16472 fooi_(&i__1);
16473 // FFEINTRIN_imp_REAL_C //
16474 r__1 = c1.r;
16475 foor_(&r__1);
16476 // FFEINTRIN_imp_REAL_D //
16477 r__1 = (real) d1;
16478 foor_(&r__1);
16479 // FFEINTRIN_imp_REAL_I //
16480 r__1 = (real) i1;
16481 foor_(&r__1);
16482 // FFEINTRIN_imp_REAL_R //
16483 r__1 = r1;
16484 foor_(&r__1);
16486 // FFEINTRIN_imp_INT_D: //
16488 // FFEINTRIN_specIDINT //
16489 i__1 = (integer) d1;
16490 fooi_(&i__1);
16492 // FFEINTRIN_imp_INT_R: //
16494 // FFEINTRIN_specIFIX //
16495 i__1 = (integer) r1;
16496 fooi_(&i__1);
16497 // FFEINTRIN_specINT //
16498 i__1 = (integer) r1;
16499 fooi_(&i__1);
16501 // FFEINTRIN_imp_REAL_D: //
16503 // FFEINTRIN_specSNGL //
16504 r__1 = (real) d1;
16505 foor_(&r__1);
16507 // FFEINTRIN_imp_REAL_I: //
16509 // FFEINTRIN_specFLOAT //
16510 r__1 = (real) i1;
16511 foor_(&r__1);
16512 // FFEINTRIN_specREAL //
16513 r__1 = (real) i1;
16514 foor_(&r__1);
16516 } // MAIN__ //
16518 -------- (end output file from f2c)
16522 #include "gt-f-com.h"
16523 #include "gtype-f.h"