Daily bump.
[official-gcc.git] / gcc / f / com.c
blobc100c2a12acc0e7af96fe067d4237842fd3dc02b
1 /* com.c -- Implementation File (module.c template V1.0)
2 Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
3 Free Software Foundation, Inc.
4 Contributed by James Craig Burley.
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 "rtl.h"
86 #include "toplev.h"
87 #include "tree.h"
88 #include "output.h" /* Must follow tree.h so TREE_CODE is defined! */
89 #include "convert.h"
90 #include "ggc.h"
91 #include "diagnostic.h"
92 #include "intl.h"
93 #include "langhooks.h"
94 #include "langhooks-def.h"
96 /* VMS-specific definitions */
97 #ifdef VMS
98 #include <descrip.h>
99 #define O_RDONLY 0 /* Open arg for Read/Only */
100 #define O_WRONLY 1 /* Open arg for Write/Only */
101 #define read(fd,buf,size) VMS_read (fd,buf,size)
102 #define write(fd,buf,size) VMS_write (fd,buf,size)
103 #define open(fname,mode,prot) VMS_open (fname,mode,prot)
104 #define fopen(fname,mode) VMS_fopen (fname,mode)
105 #define freopen(fname,mode,ofile) VMS_freopen (fname,mode,ofile)
106 #define strncat(dst,src,cnt) VMS_strncat (dst,src,cnt)
107 #define fstat(fd,stbuf) VMS_fstat (fd,stbuf)
108 static int VMS_fstat (), VMS_stat ();
109 static char * VMS_strncat ();
110 static int VMS_read ();
111 static int VMS_write ();
112 static int VMS_open ();
113 static FILE * VMS_fopen ();
114 static FILE * VMS_freopen ();
115 static void hack_vms_include_specification ();
116 typedef struct { unsigned :16, :16, :16; } vms_ino_t;
117 #define ino_t vms_ino_t
118 #define INCLUDE_LEN_FUDGE 10 /* leave room for VMS syntax conversion */
119 #endif /* VMS */
121 #define FFECOM_DETERMINE_TYPES 1 /* for com.h */
122 #include "com.h"
123 #include "bad.h"
124 #include "bld.h"
125 #include "equiv.h"
126 #include "expr.h"
127 #include "implic.h"
128 #include "info.h"
129 #include "malloc.h"
130 #include "src.h"
131 #include "st.h"
132 #include "storag.h"
133 #include "symbol.h"
134 #include "target.h"
135 #include "top.h"
136 #include "type.h"
138 /* Externals defined here. */
140 /* Stream for reading from the input file. */
141 FILE *finput;
143 /* These definitions parallel those in c-decl.c so that code from that
144 module can be used pretty much as is. Much of these defs aren't
145 otherwise used, i.e. by g77 code per se, except some of them are used
146 to build some of them that are. The ones that are global (i.e. not
147 "static") are those that ste.c and such might use (directly
148 or by using com macros that reference them in their definitions). */
150 tree string_type_node;
152 /* The rest of these are inventions for g77, though there might be
153 similar things in the C front end. As they are found, these
154 inventions should be renamed to be canonical. Note that only
155 the ones currently required to be global are so. */
157 static tree ffecom_tree_fun_type_void;
159 tree ffecom_integer_type_node; /* Abbrev for _tree_type[blah][blah]. */
160 tree ffecom_integer_zero_node; /* Like *_*_* with g77's integer type. */
161 tree ffecom_integer_one_node; /* " */
162 tree ffecom_tree_type[FFEINFO_basictype][FFEINFO_kindtype];
164 /* _fun_type things are the f2c-specific versions. For -fno-f2c,
165 just use build_function_type and build_pointer_type on the
166 appropriate _tree_type array element. */
168 static tree ffecom_tree_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
169 static tree ffecom_tree_ptr_to_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
170 static tree ffecom_tree_subr_type;
171 static tree ffecom_tree_ptr_to_subr_type;
172 static tree ffecom_tree_blockdata_type;
174 static tree ffecom_tree_xargc_;
176 ffecomSymbol ffecom_symbol_null_
179 NULL_TREE,
180 NULL_TREE,
181 NULL_TREE,
182 NULL_TREE,
183 false
185 ffeinfoKindtype ffecom_pointer_kind_ = FFEINFO_basictypeNONE;
186 ffeinfoKindtype ffecom_label_kind_ = FFEINFO_basictypeNONE;
188 int ffecom_f2c_typecode_[FFEINFO_basictype][FFEINFO_kindtype];
189 tree ffecom_f2c_integer_type_node;
190 tree ffecom_f2c_ptr_to_integer_type_node;
191 tree ffecom_f2c_address_type_node;
192 tree ffecom_f2c_real_type_node;
193 tree ffecom_f2c_ptr_to_real_type_node;
194 tree ffecom_f2c_doublereal_type_node;
195 tree ffecom_f2c_complex_type_node;
196 tree ffecom_f2c_doublecomplex_type_node;
197 tree ffecom_f2c_longint_type_node;
198 tree ffecom_f2c_logical_type_node;
199 tree ffecom_f2c_flag_type_node;
200 tree ffecom_f2c_ftnlen_type_node;
201 tree ffecom_f2c_ftnlen_zero_node;
202 tree ffecom_f2c_ftnlen_one_node;
203 tree ffecom_f2c_ftnlen_two_node;
204 tree ffecom_f2c_ptr_to_ftnlen_type_node;
205 tree ffecom_f2c_ftnint_type_node;
206 tree ffecom_f2c_ptr_to_ftnint_type_node;
208 /* Simple definitions and enumerations. */
210 #ifndef FFECOM_sizeMAXSTACKITEM
211 #define FFECOM_sizeMAXSTACKITEM 32*1024 /* Keep user-declared things
212 larger than this # bytes
213 off stack if possible. */
214 #endif
216 /* For systems that have large enough stacks, they should define
217 this to 0, and here, for ease of use later on, we just undefine
218 it if it is 0. */
220 #if FFECOM_sizeMAXSTACKITEM == 0
221 #undef FFECOM_sizeMAXSTACKITEM
222 #endif
224 typedef enum
226 FFECOM_rttypeVOID_,
227 FFECOM_rttypeVOIDSTAR_, /* C's `void *' type. */
228 FFECOM_rttypeFTNINT_, /* f2c's `ftnint' type. */
229 FFECOM_rttypeINTEGER_, /* f2c's `integer' type. */
230 FFECOM_rttypeLONGINT_, /* f2c's `longint' type. */
231 FFECOM_rttypeLOGICAL_, /* f2c's `logical' type. */
232 FFECOM_rttypeREAL_F2C_, /* f2c's `real' returned as `double'. */
233 FFECOM_rttypeREAL_GNU_, /* `real' returned as such. */
234 FFECOM_rttypeCOMPLEX_F2C_, /* f2c's `complex' returned via 1st arg. */
235 FFECOM_rttypeCOMPLEX_GNU_, /* f2c's `complex' returned directly. */
236 FFECOM_rttypeDOUBLE_, /* C's `double' type. */
237 FFECOM_rttypeDOUBLEREAL_, /* f2c's `doublereal' type. */
238 FFECOM_rttypeDBLCMPLX_F2C_, /* f2c's `doublecomplex' returned via 1st arg. */
239 FFECOM_rttypeDBLCMPLX_GNU_, /* f2c's `doublecomplex' returned directly. */
240 FFECOM_rttypeCHARACTER_, /* f2c `char *'/`ftnlen' pair. */
241 FFECOM_rttype_
242 } ffecomRttype_;
244 /* Internal typedefs. */
246 typedef struct _ffecom_concat_list_ ffecomConcatList_;
248 /* Private include files. */
251 /* Internal structure definitions. */
253 struct _ffecom_concat_list_
255 ffebld *exprs;
256 int count;
257 int max;
258 ffetargetCharacterSize minlen;
259 ffetargetCharacterSize maxlen;
262 /* Static functions (internal). */
264 static tree ffe_type_for_mode PARAMS ((enum machine_mode, int));
265 static tree ffe_type_for_size PARAMS ((unsigned int, int));
266 static tree ffe_unsigned_type PARAMS ((tree));
267 static tree ffe_signed_type PARAMS ((tree));
268 static tree ffe_signed_or_unsigned_type PARAMS ((int, tree));
269 static bool ffe_mark_addressable PARAMS ((tree));
270 static tree ffe_truthvalue_conversion PARAMS ((tree));
271 static void ffecom_init_decl_processing PARAMS ((void));
272 static tree ffecom_arglist_expr_ (const char *argstring, ffebld args);
273 static tree ffecom_widest_expr_type_ (ffebld list);
274 static bool ffecom_overlap_ (tree dest_decl, tree dest_offset,
275 tree dest_size, tree source_tree,
276 ffebld source, bool scalar_arg);
277 static bool ffecom_args_overlapping_ (tree dest_tree, ffebld dest,
278 tree args, tree callee_commons,
279 bool scalar_args);
280 static tree ffecom_build_f2c_string_ (int i, const char *s);
281 static tree ffecom_call_ (tree fn, ffeinfoKindtype kt,
282 bool is_f2c_complex, tree type,
283 tree args, tree dest_tree,
284 ffebld dest, bool *dest_used,
285 tree callee_commons, bool scalar_args, tree hook);
286 static tree ffecom_call_binop_ (tree fn, ffeinfoKindtype kt,
287 bool is_f2c_complex, tree type,
288 ffebld left, ffebld right,
289 tree dest_tree, ffebld dest,
290 bool *dest_used, tree callee_commons,
291 bool scalar_args, bool ref, tree hook);
292 static void ffecom_char_args_x_ (tree *xitem, tree *length,
293 ffebld expr, bool with_null);
294 static tree ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy);
295 static tree ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s);
296 static ffecomConcatList_
297 ffecom_concat_list_gather_ (ffecomConcatList_ catlist,
298 ffebld expr,
299 ffetargetCharacterSize max);
300 static void ffecom_concat_list_kill_ (ffecomConcatList_ catlist);
301 static ffecomConcatList_ ffecom_concat_list_new_ (ffebld expr,
302 ffetargetCharacterSize max);
303 static void ffecom_debug_kludge_ (tree aggr, const char *aggr_type,
304 ffesymbol member, tree member_type,
305 ffetargetOffset offset);
306 static void ffecom_do_entry_ (ffesymbol fn, int entrynum);
307 static tree ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
308 bool *dest_used, bool assignp, bool widenp);
309 static tree ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
310 ffebld dest, bool *dest_used);
311 static tree ffecom_expr_power_integer_ (ffebld expr);
312 static void ffecom_expr_transform_ (ffebld expr);
313 static void ffecom_f2c_make_type_ (tree *type, int tcode, const char *name);
314 static void ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
315 int code);
316 static ffeglobal ffecom_finish_global_ (ffeglobal global);
317 static ffesymbol ffecom_finish_symbol_transform_ (ffesymbol s);
318 static tree ffecom_get_appended_identifier_ (char us, const char *text);
319 static tree ffecom_get_external_identifier_ (ffesymbol s);
320 static tree ffecom_get_identifier_ (const char *text);
321 static tree ffecom_gen_sfuncdef_ (ffesymbol s,
322 ffeinfoBasictype bt,
323 ffeinfoKindtype kt);
324 static const char *ffecom_gfrt_args_ (ffecomGfrt ix);
325 static tree ffecom_gfrt_tree_ (ffecomGfrt ix);
326 static tree ffecom_init_zero_ (tree decl);
327 static tree ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
328 tree *maybe_tree);
329 static tree ffecom_intrinsic_len_ (ffebld expr);
330 static void ffecom_let_char_ (tree dest_tree,
331 tree dest_length,
332 ffetargetCharacterSize dest_size,
333 ffebld source);
334 static void ffecom_make_gfrt_ (ffecomGfrt ix);
335 static void ffecom_member_phase1_ (ffestorag mst, ffestorag st);
336 static void ffecom_member_phase2_ (ffestorag mst, ffestorag st);
337 static void ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size,
338 ffebld source);
339 static void ffecom_push_dummy_decls_ (ffebld dumlist,
340 bool stmtfunc);
341 static void ffecom_start_progunit_ (void);
342 static ffesymbol ffecom_sym_transform_ (ffesymbol s);
343 static ffesymbol ffecom_sym_transform_assign_ (ffesymbol s);
344 static void ffecom_transform_common_ (ffesymbol s);
345 static void ffecom_transform_equiv_ (ffestorag st);
346 static tree ffecom_transform_namelist_ (ffesymbol s);
347 static void ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
348 tree t);
349 static void ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
350 tree *size, tree tree);
351 static tree ffecom_tree_divide_ (tree tree_type, tree left, tree right,
352 tree dest_tree, ffebld dest,
353 bool *dest_used, tree hook);
354 static tree ffecom_type_localvar_ (ffesymbol s,
355 ffeinfoBasictype bt,
356 ffeinfoKindtype kt);
357 static tree ffecom_type_namelist_ (void);
358 static tree ffecom_type_vardesc_ (void);
359 static tree ffecom_vardesc_ (ffebld expr);
360 static tree ffecom_vardesc_array_ (ffesymbol s);
361 static tree ffecom_vardesc_dims_ (ffesymbol s);
362 static tree ffecom_convert_narrow_ (tree type, tree expr);
363 static tree ffecom_convert_widen_ (tree type, tree expr);
365 /* These are static functions that parallel those found in the C front
366 end and thus have the same names. */
368 static tree bison_rule_compstmt_ (void);
369 static void bison_rule_pushlevel_ (void);
370 static void delete_block (tree block);
371 static int duplicate_decls (tree newdecl, tree olddecl);
372 static void finish_decl (tree decl, tree init, bool is_top_level);
373 static void finish_function (int nested);
374 static const char *ffe_printable_name (tree decl, int v);
375 static void ffe_print_error_function (diagnostic_context *, const char *);
376 static tree lookup_name_current_level (tree name);
377 static struct binding_level *make_binding_level (void);
378 static void pop_f_function_context (void);
379 static void push_f_function_context (void);
380 static void push_parm_decl (tree parm);
381 static tree pushdecl_top_level (tree decl);
382 static int kept_level_p (void);
383 static tree storedecls (tree decls);
384 static void store_parm_decls (int is_main_program);
385 static tree start_decl (tree decl, bool is_top_level);
386 static void start_function (tree name, tree type, int nested, int public);
387 static void ffecom_file_ (const char *name);
388 static void ffecom_close_include_ (FILE *f);
389 static int ffecom_decode_include_option_ (char *spec);
390 static FILE *ffecom_open_include_ (char *name, ffewhereLine l,
391 ffewhereColumn c);
393 /* Static objects accessed by functions in this module. */
395 static ffesymbol ffecom_primary_entry_ = NULL;
396 static ffesymbol ffecom_nested_entry_ = NULL;
397 static ffeinfoKind ffecom_primary_entry_kind_;
398 static bool ffecom_primary_entry_is_proc_;
399 static tree ffecom_outer_function_decl_;
400 static tree ffecom_previous_function_decl_;
401 static tree ffecom_which_entrypoint_decl_;
402 static tree ffecom_float_zero_ = NULL_TREE;
403 static tree ffecom_float_half_ = NULL_TREE;
404 static tree ffecom_double_zero_ = NULL_TREE;
405 static tree ffecom_double_half_ = NULL_TREE;
406 static tree ffecom_func_result_;/* For functions. */
407 static tree ffecom_func_length_;/* For CHARACTER fns. */
408 static ffebld ffecom_list_blockdata_;
409 static ffebld ffecom_list_common_;
410 static ffebld ffecom_master_arglist_;
411 static ffeinfoBasictype ffecom_master_bt_;
412 static ffeinfoKindtype ffecom_master_kt_;
413 static ffetargetCharacterSize ffecom_master_size_;
414 static int ffecom_num_fns_ = 0;
415 static int ffecom_num_entrypoints_ = 0;
416 static bool ffecom_is_altreturning_ = FALSE;
417 static tree ffecom_multi_type_node_;
418 static tree ffecom_multi_retval_;
419 static tree
420 ffecom_multi_fields_[FFEINFO_basictype][FFEINFO_kindtype];
421 static bool ffecom_member_namelisted_; /* _member_phase1_ namelisted? */
422 static bool ffecom_doing_entry_ = FALSE;
423 static bool ffecom_transform_only_dummies_ = FALSE;
424 static int ffecom_typesize_pointer_;
425 static int ffecom_typesize_integer1_;
427 /* Holds pointer-to-function expressions. */
429 static tree ffecom_gfrt_[FFECOM_gfrt]
432 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) NULL_TREE,
433 #include "com-rt.def"
434 #undef DEFGFRT
437 /* Holds the external names of the functions. */
439 static const char *const ffecom_gfrt_name_[FFECOM_gfrt]
442 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) NAME,
443 #include "com-rt.def"
444 #undef DEFGFRT
447 /* Whether the function returns. */
449 static const bool ffecom_gfrt_volatile_[FFECOM_gfrt]
452 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) VOLATILE,
453 #include "com-rt.def"
454 #undef DEFGFRT
457 /* Whether the function returns type complex. */
459 static const bool ffecom_gfrt_complex_[FFECOM_gfrt]
462 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) COMPLEX,
463 #include "com-rt.def"
464 #undef DEFGFRT
467 /* Whether the function is const
468 (i.e., has no side effects and only depends on its arguments). */
470 static const bool ffecom_gfrt_const_[FFECOM_gfrt]
473 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) CONST,
474 #include "com-rt.def"
475 #undef DEFGFRT
478 /* Type code for the function return value. */
480 static const ffecomRttype_ ffecom_gfrt_type_[FFECOM_gfrt]
483 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) TYPE,
484 #include "com-rt.def"
485 #undef DEFGFRT
488 /* String of codes for the function's arguments. */
490 static const char *const ffecom_gfrt_argstring_[FFECOM_gfrt]
493 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) ARGS,
494 #include "com-rt.def"
495 #undef DEFGFRT
498 /* Internal macros. */
500 /* We let tm.h override the types used here, to handle trivial differences
501 such as the choice of unsigned int or long unsigned int for size_t.
502 When machines start needing nontrivial differences in the size type,
503 it would be best to do something here to figure out automatically
504 from other information what type to use. */
506 #ifndef SIZE_TYPE
507 #define SIZE_TYPE "long unsigned int"
508 #endif
510 #define ffecom_concat_list_count_(catlist) ((catlist).count)
511 #define ffecom_concat_list_expr_(catlist,i) ((catlist).exprs[(i)])
512 #define ffecom_concat_list_maxlen_(catlist) ((catlist).maxlen)
513 #define ffecom_concat_list_minlen_(catlist) ((catlist).minlen)
515 #define ffecom_char_args_(i,l,e) ffecom_char_args_x_((i),(l),(e),FALSE)
516 #define ffecom_char_args_with_null_(i,l,e) ffecom_char_args_x_((i),(l),(e),TRUE)
518 /* For each binding contour we allocate a binding_level structure
519 * which records the names defined in that contour.
520 * Contours include:
521 * 0) the global one
522 * 1) one for each function definition,
523 * where internal declarations of the parameters appear.
525 * The current meaning of a name can be found by searching the levels from
526 * the current one out to the global one.
529 /* Note that the information in the `names' component of the global contour
530 is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
532 struct binding_level
534 /* A chain of _DECL nodes for all variables, constants, functions,
535 and typedef types. These are in the reverse of the order supplied.
537 tree names;
539 /* For each level (except not the global one),
540 a chain of BLOCK nodes for all the levels
541 that were entered and exited one level down. */
542 tree blocks;
544 /* The BLOCK node for this level, if one has been preallocated.
545 If 0, the BLOCK is allocated (if needed) when the level is popped. */
546 tree this_block;
548 /* The binding level which this one is contained in (inherits from). */
549 struct binding_level *level_chain;
551 /* 0: no ffecom_prepare_* functions called at this level yet;
552 1: ffecom_prepare* functions called, except not ffecom_prepare_end;
553 2: ffecom_prepare_end called. */
554 int prep_state;
557 #define NULL_BINDING_LEVEL (struct binding_level *) NULL
559 /* The binding level currently in effect. */
561 static struct binding_level *current_binding_level;
563 /* A chain of binding_level structures awaiting reuse. */
565 static struct binding_level *free_binding_level;
567 /* The outermost binding level, for names of file scope.
568 This is created when the compiler is started and exists
569 through the entire run. */
571 static struct binding_level *global_binding_level;
573 /* Binding level structures are initialized by copying this one. */
575 static const struct binding_level clear_binding_level
577 {NULL, NULL, NULL, NULL_BINDING_LEVEL, 0};
579 /* Language-dependent contents of an identifier. */
581 struct lang_identifier
583 struct tree_identifier ignore;
584 tree global_value, local_value, label_value;
585 bool invented;
588 /* Macros for access to language-specific slots in an identifier. */
589 /* Each of these slots contains a DECL node or null. */
591 /* This represents the value which the identifier has in the
592 file-scope namespace. */
593 #define IDENTIFIER_GLOBAL_VALUE(NODE) \
594 (((struct lang_identifier *)(NODE))->global_value)
595 /* This represents the value which the identifier has in the current
596 scope. */
597 #define IDENTIFIER_LOCAL_VALUE(NODE) \
598 (((struct lang_identifier *)(NODE))->local_value)
599 /* This represents the value which the identifier has as a label in
600 the current label scope. */
601 #define IDENTIFIER_LABEL_VALUE(NODE) \
602 (((struct lang_identifier *)(NODE))->label_value)
603 /* This is nonzero if the identifier was "made up" by g77 code. */
604 #define IDENTIFIER_INVENTED(NODE) \
605 (((struct lang_identifier *)(NODE))->invented)
607 /* In identifiers, C uses the following fields in a special way:
608 TREE_PUBLIC to record that there was a previous local extern decl.
609 TREE_USED to record that such a decl was used.
610 TREE_ADDRESSABLE to record that the address of such a decl was used. */
612 /* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
613 that have names. Here so we can clear out their names' definitions
614 at the end of the function. */
616 static tree named_labels;
618 /* A list of LABEL_DECLs from outer contexts that are currently shadowed. */
620 static tree shadowed_labels;
622 /* Return the subscript expression, modified to do range-checking.
624 `array' is the array to be checked against.
625 `element' is the subscript expression to check.
626 `dim' is the dimension number (starting at 0).
627 `total_dims' is the total number of dimensions (0 for CHARACTER substring).
630 static tree
631 ffecom_subscript_check_ (tree array, tree element, int dim, int total_dims,
632 const char *array_name)
634 tree low = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
635 tree high = TYPE_MAX_VALUE (TYPE_DOMAIN (array));
636 tree cond;
637 tree die;
638 tree args;
640 if (element == error_mark_node)
641 return element;
643 if (TREE_TYPE (low) != TREE_TYPE (element))
645 if (TYPE_PRECISION (TREE_TYPE (low))
646 > TYPE_PRECISION (TREE_TYPE (element)))
647 element = convert (TREE_TYPE (low), element);
648 else
650 low = convert (TREE_TYPE (element), low);
651 if (high)
652 high = convert (TREE_TYPE (element), high);
656 element = ffecom_save_tree (element);
657 if (total_dims == 0)
659 /* Special handling for substring range checks. Fortran allows the
660 end subscript < begin subscript, which means that expressions like
661 string(1:0) are valid (and yield a null string). In view of this,
662 enforce two simpler conditions:
663 1) element<=high for end-substring;
664 2) element>=low for start-substring.
665 Run-time character movement will enforce remaining conditions.
667 More complicated checks would be better, but present structure only
668 provides one index element at a time, so it is not possible to
669 enforce a check of both i and j in string(i:j). If it were, the
670 complete set of rules would read,
671 if ( ((j<i) && ((low<=i<=high) || (low<=j<=high))) ||
672 ((low<=i<=high) && (low<=j<=high)) )
673 ok ;
674 else
675 range error ;
677 if (dim)
678 cond = ffecom_2 (LE_EXPR, integer_type_node, element, high);
679 else
680 cond = ffecom_2 (LE_EXPR, integer_type_node, low, element);
682 else
684 /* Array reference substring range checking. */
686 cond = ffecom_2 (LE_EXPR, integer_type_node,
687 low,
688 element);
689 if (high)
691 cond = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
692 cond,
693 ffecom_2 (LE_EXPR, integer_type_node,
694 element,
695 high));
700 int len;
701 char *proc;
702 char *var;
703 tree arg3;
704 tree arg2;
705 tree arg1;
706 tree arg4;
708 switch (total_dims)
710 case 0:
711 var = concat (array_name, "[", (dim ? "end" : "start"),
712 "-substring]", NULL);
713 len = strlen (var) + 1;
714 arg1 = build_string (len, var);
715 free (var);
716 break;
718 case 1:
719 len = strlen (array_name) + 1;
720 arg1 = build_string (len, array_name);
721 break;
723 default:
724 var = xmalloc (strlen (array_name) + 40);
725 sprintf (var, "%s[subscript-%d-of-%d]",
726 array_name,
727 dim + 1, total_dims);
728 len = strlen (var) + 1;
729 arg1 = build_string (len, var);
730 free (var);
731 break;
734 TREE_TYPE (arg1)
735 = build_type_variant (build_array_type (char_type_node,
736 build_range_type
737 (integer_type_node,
738 integer_one_node,
739 build_int_2 (len, 0))),
740 1, 0);
741 TREE_CONSTANT (arg1) = 1;
742 TREE_STATIC (arg1) = 1;
743 arg1 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg1)),
744 arg1);
746 /* s_rnge adds one to the element to print it, so bias against
747 that -- want to print a faithful *subscript* value. */
748 arg2 = convert (ffecom_f2c_ftnint_type_node,
749 ffecom_2 (MINUS_EXPR,
750 TREE_TYPE (element),
751 element,
752 convert (TREE_TYPE (element),
753 integer_one_node)));
755 proc = concat (input_filename, "/",
756 IDENTIFIER_POINTER (DECL_NAME (current_function_decl)),
757 NULL);
758 len = strlen (proc) + 1;
759 arg3 = build_string (len, proc);
761 free (proc);
763 TREE_TYPE (arg3)
764 = build_type_variant (build_array_type (char_type_node,
765 build_range_type
766 (integer_type_node,
767 integer_one_node,
768 build_int_2 (len, 0))),
769 1, 0);
770 TREE_CONSTANT (arg3) = 1;
771 TREE_STATIC (arg3) = 1;
772 arg3 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg3)),
773 arg3);
775 arg4 = convert (ffecom_f2c_ftnint_type_node,
776 build_int_2 (lineno, 0));
778 arg1 = build_tree_list (NULL_TREE, arg1);
779 arg2 = build_tree_list (NULL_TREE, arg2);
780 arg3 = build_tree_list (NULL_TREE, arg3);
781 arg4 = build_tree_list (NULL_TREE, arg4);
782 TREE_CHAIN (arg3) = arg4;
783 TREE_CHAIN (arg2) = arg3;
784 TREE_CHAIN (arg1) = arg2;
786 args = arg1;
788 die = ffecom_call_gfrt (FFECOM_gfrtRANGE,
789 args, NULL_TREE);
790 TREE_SIDE_EFFECTS (die) = 1;
792 element = ffecom_3 (COND_EXPR,
793 TREE_TYPE (element),
794 cond,
795 element,
796 die);
798 return element;
801 /* Return the computed element of an array reference.
803 `item' is NULL_TREE, or the transformed pointer to the array.
804 `expr' is the original opARRAYREF expression, which is transformed
805 if `item' is NULL_TREE.
806 `want_ptr' is non-zero if a pointer to the element, instead of
807 the element itself, is to be returned. */
809 static tree
810 ffecom_arrayref_ (tree item, ffebld expr, int want_ptr)
812 ffebld dims[FFECOM_dimensionsMAX];
813 int i;
814 int total_dims;
815 int flatten = ffe_is_flatten_arrays ();
816 int need_ptr;
817 tree array;
818 tree element;
819 tree tree_type;
820 tree tree_type_x;
821 const char *array_name;
822 ffetype type;
823 ffebld list;
825 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER)
826 array_name = ffesymbol_text (ffebld_symter (ffebld_left (expr)));
827 else
828 array_name = "[expr?]";
830 /* Build up ARRAY_REFs in reverse order (since we're column major
831 here in Fortran land). */
833 for (i = 0, list = ffebld_right (expr);
834 list != NULL;
835 ++i, list = ffebld_trail (list))
837 dims[i] = ffebld_head (list);
838 type = ffeinfo_type (ffebld_basictype (dims[i]),
839 ffebld_kindtype (dims[i]));
840 if (! flatten
841 && ffecom_typesize_pointer_ > ffecom_typesize_integer1_
842 && ffetype_size (type) > ffecom_typesize_integer1_)
843 /* E.g. ARRAY(INDEX), given INTEGER*8 INDEX, on a system with 64-bit
844 pointers and 32-bit integers. Do the full 64-bit pointer
845 arithmetic, for codes using arrays for nonstandard heap-like
846 work. */
847 flatten = 1;
850 total_dims = i;
852 need_ptr = want_ptr || flatten;
854 if (! item)
856 if (need_ptr)
857 item = ffecom_ptr_to_expr (ffebld_left (expr));
858 else
859 item = ffecom_expr (ffebld_left (expr));
861 if (item == error_mark_node)
862 return item;
864 if (ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereFLEETING
865 && ! ffe_mark_addressable (item))
866 return error_mark_node;
869 if (item == error_mark_node)
870 return item;
872 if (need_ptr)
874 tree min;
876 for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
877 i >= 0;
878 --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
880 min = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
881 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
882 if (flag_bounds_check)
883 element = ffecom_subscript_check_ (array, element, i, total_dims,
884 array_name);
885 if (element == error_mark_node)
886 return element;
888 /* Widen integral arithmetic as desired while preserving
889 signedness. */
890 tree_type = TREE_TYPE (element);
891 tree_type_x = tree_type;
892 if (tree_type
893 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
894 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
895 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
897 if (TREE_TYPE (min) != tree_type_x)
898 min = convert (tree_type_x, min);
899 if (TREE_TYPE (element) != tree_type_x)
900 element = convert (tree_type_x, element);
902 item = ffecom_2 (PLUS_EXPR,
903 build_pointer_type (TREE_TYPE (array)),
904 item,
905 size_binop (MULT_EXPR,
906 size_in_bytes (TREE_TYPE (array)),
907 convert (sizetype,
908 fold (build (MINUS_EXPR,
909 tree_type_x,
910 element, min)))));
912 if (! want_ptr)
914 item = ffecom_1 (INDIRECT_REF,
915 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
916 item);
919 else
921 for (--i;
922 i >= 0;
923 --i)
925 array = TYPE_MAIN_VARIANT (TREE_TYPE (item));
927 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
928 if (flag_bounds_check)
929 element = ffecom_subscript_check_ (array, element, i, total_dims,
930 array_name);
931 if (element == error_mark_node)
932 return element;
934 /* Widen integral arithmetic as desired while preserving
935 signedness. */
936 tree_type = TREE_TYPE (element);
937 tree_type_x = tree_type;
938 if (tree_type
939 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
940 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
941 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
943 element = convert (tree_type_x, element);
945 item = ffecom_2 (ARRAY_REF,
946 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
947 item,
948 element);
952 return item;
955 /* This is like gcc's stabilize_reference -- in fact, most of the code
956 comes from that -- but it handles the situation where the reference
957 is going to have its subparts picked at, and it shouldn't change
958 (or trigger extra invocations of functions in the subtrees) due to
959 this. save_expr is a bit overzealous, because we don't need the
960 entire thing calculated and saved like a temp. So, for DECLs, no
961 change is needed, because these are stable aggregates, and ARRAY_REF
962 and such might well be stable too, but for things like calculations,
963 we do need to calculate a snapshot of a value before picking at it. */
965 static tree
966 ffecom_stabilize_aggregate_ (tree ref)
968 tree result;
969 enum tree_code code = TREE_CODE (ref);
971 switch (code)
973 case VAR_DECL:
974 case PARM_DECL:
975 case RESULT_DECL:
976 /* No action is needed in this case. */
977 return ref;
979 case NOP_EXPR:
980 case CONVERT_EXPR:
981 case FLOAT_EXPR:
982 case FIX_TRUNC_EXPR:
983 case FIX_FLOOR_EXPR:
984 case FIX_ROUND_EXPR:
985 case FIX_CEIL_EXPR:
986 result = build_nt (code, stabilize_reference (TREE_OPERAND (ref, 0)));
987 break;
989 case INDIRECT_REF:
990 result = build_nt (INDIRECT_REF,
991 stabilize_reference_1 (TREE_OPERAND (ref, 0)));
992 break;
994 case COMPONENT_REF:
995 result = build_nt (COMPONENT_REF,
996 stabilize_reference (TREE_OPERAND (ref, 0)),
997 TREE_OPERAND (ref, 1));
998 break;
1000 case BIT_FIELD_REF:
1001 result = build_nt (BIT_FIELD_REF,
1002 stabilize_reference (TREE_OPERAND (ref, 0)),
1003 stabilize_reference_1 (TREE_OPERAND (ref, 1)),
1004 stabilize_reference_1 (TREE_OPERAND (ref, 2)));
1005 break;
1007 case ARRAY_REF:
1008 result = build_nt (ARRAY_REF,
1009 stabilize_reference (TREE_OPERAND (ref, 0)),
1010 stabilize_reference_1 (TREE_OPERAND (ref, 1)));
1011 break;
1013 case COMPOUND_EXPR:
1014 result = build_nt (COMPOUND_EXPR,
1015 stabilize_reference_1 (TREE_OPERAND (ref, 0)),
1016 stabilize_reference (TREE_OPERAND (ref, 1)));
1017 break;
1019 case RTL_EXPR:
1020 abort ();
1023 default:
1024 return save_expr (ref);
1026 case ERROR_MARK:
1027 return error_mark_node;
1030 TREE_TYPE (result) = TREE_TYPE (ref);
1031 TREE_READONLY (result) = TREE_READONLY (ref);
1032 TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (ref);
1033 TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (ref);
1035 return result;
1038 /* A rip-off of gcc's convert.c convert_to_complex function,
1039 reworked to handle complex implemented as C structures
1040 (RECORD_TYPE with two fields, real and imaginary `r' and `i'). */
1042 static tree
1043 ffecom_convert_to_complex_ (tree type, tree expr)
1045 register enum tree_code form = TREE_CODE (TREE_TYPE (expr));
1046 tree subtype;
1048 assert (TREE_CODE (type) == RECORD_TYPE);
1050 subtype = TREE_TYPE (TYPE_FIELDS (type));
1052 if (form == REAL_TYPE || form == INTEGER_TYPE || form == ENUMERAL_TYPE)
1054 expr = convert (subtype, expr);
1055 return ffecom_2 (COMPLEX_EXPR, type, expr,
1056 convert (subtype, integer_zero_node));
1059 if (form == RECORD_TYPE)
1061 tree elt_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr)));
1062 if (TYPE_MAIN_VARIANT (elt_type) == TYPE_MAIN_VARIANT (subtype))
1063 return expr;
1064 else
1066 expr = save_expr (expr);
1067 return ffecom_2 (COMPLEX_EXPR,
1068 type,
1069 convert (subtype,
1070 ffecom_1 (REALPART_EXPR,
1071 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1072 expr)),
1073 convert (subtype,
1074 ffecom_1 (IMAGPART_EXPR,
1075 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1076 expr)));
1080 if (form == POINTER_TYPE || form == REFERENCE_TYPE)
1081 error ("pointer value used where a complex was expected");
1082 else
1083 error ("aggregate value used where a complex was expected");
1085 return ffecom_2 (COMPLEX_EXPR, type,
1086 convert (subtype, integer_zero_node),
1087 convert (subtype, integer_zero_node));
1090 /* Like gcc's convert(), but crashes if widening might happen. */
1092 static tree
1093 ffecom_convert_narrow_ (type, expr)
1094 tree type, expr;
1096 register tree e = expr;
1097 register enum tree_code code = TREE_CODE (type);
1099 if (type == TREE_TYPE (e)
1100 || TREE_CODE (e) == ERROR_MARK)
1101 return e;
1102 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1103 return fold (build1 (NOP_EXPR, type, e));
1104 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1105 || code == ERROR_MARK)
1106 return error_mark_node;
1107 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1109 assert ("void value not ignored as it ought to be" == NULL);
1110 return error_mark_node;
1112 assert (code != VOID_TYPE);
1113 if ((code != RECORD_TYPE)
1114 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1115 assert ("converting COMPLEX to REAL" == NULL);
1116 assert (code != ENUMERAL_TYPE);
1117 if (code == INTEGER_TYPE)
1119 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1120 && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)))
1121 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1122 && (TYPE_PRECISION (type)
1123 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
1124 return fold (convert_to_integer (type, e));
1126 if (code == POINTER_TYPE)
1128 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1129 return fold (convert_to_pointer (type, e));
1131 if (code == REAL_TYPE)
1133 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1134 assert (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)));
1135 return fold (convert_to_real (type, e));
1137 if (code == COMPLEX_TYPE)
1139 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1140 assert (TYPE_PRECISION (TREE_TYPE (type)) <= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1141 return fold (convert_to_complex (type, e));
1143 if (code == RECORD_TYPE)
1145 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
1146 /* Check that at least the first field name agrees. */
1147 assert (DECL_NAME (TYPE_FIELDS (type))
1148 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
1149 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1150 <= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
1151 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1152 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1153 return e;
1154 return fold (ffecom_convert_to_complex_ (type, e));
1157 assert ("conversion to non-scalar type requested" == NULL);
1158 return error_mark_node;
1161 /* Like gcc's convert(), but crashes if narrowing might happen. */
1163 static tree
1164 ffecom_convert_widen_ (type, expr)
1165 tree type, expr;
1167 register tree e = expr;
1168 register enum tree_code code = TREE_CODE (type);
1170 if (type == TREE_TYPE (e)
1171 || TREE_CODE (e) == ERROR_MARK)
1172 return e;
1173 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1174 return fold (build1 (NOP_EXPR, type, e));
1175 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1176 || code == ERROR_MARK)
1177 return error_mark_node;
1178 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1180 assert ("void value not ignored as it ought to be" == NULL);
1181 return error_mark_node;
1183 assert (code != VOID_TYPE);
1184 if ((code != RECORD_TYPE)
1185 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1186 assert ("narrowing COMPLEX to REAL" == NULL);
1187 assert (code != ENUMERAL_TYPE);
1188 if (code == INTEGER_TYPE)
1190 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1191 && TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)))
1192 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1193 && (TYPE_PRECISION (type)
1194 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
1195 return fold (convert_to_integer (type, e));
1197 if (code == POINTER_TYPE)
1199 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1200 return fold (convert_to_pointer (type, e));
1202 if (code == REAL_TYPE)
1204 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1205 assert (TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)));
1206 return fold (convert_to_real (type, e));
1208 if (code == COMPLEX_TYPE)
1210 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1211 assert (TYPE_PRECISION (TREE_TYPE (type)) >= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1212 return fold (convert_to_complex (type, e));
1214 if (code == RECORD_TYPE)
1216 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
1217 /* Check that at least the first field name agrees. */
1218 assert (DECL_NAME (TYPE_FIELDS (type))
1219 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
1220 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1221 >= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
1222 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1223 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1224 return e;
1225 return fold (ffecom_convert_to_complex_ (type, e));
1228 assert ("conversion to non-scalar type requested" == NULL);
1229 return error_mark_node;
1232 /* Handles making a COMPLEX type, either the standard
1233 (but buggy?) gbe way, or the safer (but less elegant?)
1234 f2c way. */
1236 static tree
1237 ffecom_make_complex_type_ (tree subtype)
1239 tree type;
1240 tree realfield;
1241 tree imagfield;
1243 if (ffe_is_emulate_complex ())
1245 type = make_node (RECORD_TYPE);
1246 realfield = ffecom_decl_field (type, NULL_TREE, "r", subtype);
1247 imagfield = ffecom_decl_field (type, realfield, "i", subtype);
1248 TYPE_FIELDS (type) = realfield;
1249 layout_type (type);
1251 else
1253 type = make_node (COMPLEX_TYPE);
1254 TREE_TYPE (type) = subtype;
1255 layout_type (type);
1258 return type;
1261 /* Chooses either the gbe or the f2c way to build a
1262 complex constant. */
1264 static tree
1265 ffecom_build_complex_constant_ (tree type, tree realpart, tree imagpart)
1267 tree bothparts;
1269 if (ffe_is_emulate_complex ())
1271 bothparts = build_tree_list (TYPE_FIELDS (type), realpart);
1272 TREE_CHAIN (bothparts) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), imagpart);
1273 bothparts = build (CONSTRUCTOR, type, NULL_TREE, bothparts);
1275 else
1277 bothparts = build_complex (type, realpart, imagpart);
1280 return bothparts;
1283 static tree
1284 ffecom_arglist_expr_ (const char *c, ffebld expr)
1286 tree list;
1287 tree *plist = &list;
1288 tree trail = NULL_TREE; /* Append char length args here. */
1289 tree *ptrail = &trail;
1290 tree length;
1291 ffebld exprh;
1292 tree item;
1293 bool ptr = FALSE;
1294 tree wanted = NULL_TREE;
1295 static const char zed[] = "0";
1297 if (c == NULL)
1298 c = &zed[0];
1300 while (expr != NULL)
1302 if (*c != '\0')
1304 ptr = FALSE;
1305 if (*c == '&')
1307 ptr = TRUE;
1308 ++c;
1310 switch (*(c++))
1312 case '\0':
1313 ptr = TRUE;
1314 wanted = NULL_TREE;
1315 break;
1317 case 'a':
1318 assert (ptr);
1319 wanted = NULL_TREE;
1320 break;
1322 case 'c':
1323 wanted = ffecom_f2c_complex_type_node;
1324 break;
1326 case 'd':
1327 wanted = ffecom_f2c_doublereal_type_node;
1328 break;
1330 case 'e':
1331 wanted = ffecom_f2c_doublecomplex_type_node;
1332 break;
1334 case 'f':
1335 wanted = ffecom_f2c_real_type_node;
1336 break;
1338 case 'i':
1339 wanted = ffecom_f2c_integer_type_node;
1340 break;
1342 case 'j':
1343 wanted = ffecom_f2c_longint_type_node;
1344 break;
1346 default:
1347 assert ("bad argstring code" == NULL);
1348 wanted = NULL_TREE;
1349 break;
1353 exprh = ffebld_head (expr);
1354 if (exprh == NULL)
1355 wanted = NULL_TREE;
1357 if ((wanted == NULL_TREE)
1358 || (ptr
1359 && (TYPE_MODE
1360 (ffecom_tree_type[ffeinfo_basictype (ffebld_info (exprh))]
1361 [ffeinfo_kindtype (ffebld_info (exprh))])
1362 == TYPE_MODE (wanted))))
1363 *plist
1364 = build_tree_list (NULL_TREE,
1365 ffecom_arg_ptr_to_expr (exprh,
1366 &length));
1367 else
1369 item = ffecom_arg_expr (exprh, &length);
1370 item = ffecom_convert_widen_ (wanted, item);
1371 if (ptr)
1373 item = ffecom_1 (ADDR_EXPR,
1374 build_pointer_type (TREE_TYPE (item)),
1375 item);
1377 *plist
1378 = build_tree_list (NULL_TREE,
1379 item);
1382 plist = &TREE_CHAIN (*plist);
1383 expr = ffebld_trail (expr);
1384 if (length != NULL_TREE)
1386 *ptrail = build_tree_list (NULL_TREE, length);
1387 ptrail = &TREE_CHAIN (*ptrail);
1391 /* We've run out of args in the call; if the implementation expects
1392 more, supply null pointers for them, which the implementation can
1393 check to see if an arg was omitted. */
1395 while (*c != '\0' && *c != '0')
1397 if (*c == '&')
1398 ++c;
1399 else
1400 assert ("missing arg to run-time routine!" == NULL);
1402 switch (*(c++))
1404 case '\0':
1405 case 'a':
1406 case 'c':
1407 case 'd':
1408 case 'e':
1409 case 'f':
1410 case 'i':
1411 case 'j':
1412 break;
1414 default:
1415 assert ("bad arg string code" == NULL);
1416 break;
1418 *plist
1419 = build_tree_list (NULL_TREE,
1420 null_pointer_node);
1421 plist = &TREE_CHAIN (*plist);
1424 *plist = trail;
1426 return list;
1429 static tree
1430 ffecom_widest_expr_type_ (ffebld list)
1432 ffebld item;
1433 ffebld widest = NULL;
1434 ffetype type;
1435 ffetype widest_type = NULL;
1436 tree t;
1438 for (; list != NULL; list = ffebld_trail (list))
1440 item = ffebld_head (list);
1441 if (item == NULL)
1442 continue;
1443 if ((widest != NULL)
1444 && (ffeinfo_basictype (ffebld_info (item))
1445 != ffeinfo_basictype (ffebld_info (widest))))
1446 continue;
1447 type = ffeinfo_type (ffeinfo_basictype (ffebld_info (item)),
1448 ffeinfo_kindtype (ffebld_info (item)));
1449 if ((widest == FFEINFO_kindtypeNONE)
1450 || (ffetype_size (type)
1451 > ffetype_size (widest_type)))
1453 widest = item;
1454 widest_type = type;
1458 assert (widest != NULL);
1459 t = ffecom_tree_type[ffeinfo_basictype (ffebld_info (widest))]
1460 [ffeinfo_kindtype (ffebld_info (widest))];
1461 assert (t != NULL_TREE);
1462 return t;
1465 /* Check whether a partial overlap between two expressions is possible.
1467 Can *starting* to write a portion of expr1 change the value
1468 computed (perhaps already, *partially*) by expr2?
1470 Currently, this is a concern only for a COMPLEX expr1. But if it
1471 isn't in COMMON or local EQUIVALENCE, since we don't support
1472 aliasing of arguments, it isn't a concern. */
1474 static bool
1475 ffecom_possible_partial_overlap_ (ffebld expr1, ffebld expr2 ATTRIBUTE_UNUSED)
1477 ffesymbol sym;
1478 ffestorag st;
1480 switch (ffebld_op (expr1))
1482 case FFEBLD_opSYMTER:
1483 sym = ffebld_symter (expr1);
1484 break;
1486 case FFEBLD_opARRAYREF:
1487 if (ffebld_op (ffebld_left (expr1)) != FFEBLD_opSYMTER)
1488 return FALSE;
1489 sym = ffebld_symter (ffebld_left (expr1));
1490 break;
1492 default:
1493 return FALSE;
1496 if (ffesymbol_where (sym) != FFEINFO_whereCOMMON
1497 && (ffesymbol_where (sym) != FFEINFO_whereLOCAL
1498 || ! (st = ffesymbol_storage (sym))
1499 || ! ffestorag_parent (st)))
1500 return FALSE;
1502 /* It's in COMMON or local EQUIVALENCE. */
1504 return TRUE;
1507 /* Check whether dest and source might overlap. ffebld versions of these
1508 might or might not be passed, will be NULL if not.
1510 The test is really whether source_tree is modifiable and, if modified,
1511 might overlap destination such that the value(s) in the destination might
1512 change before it is finally modified. dest_* are the canonized
1513 destination itself. */
1515 static bool
1516 ffecom_overlap_ (tree dest_decl, tree dest_offset, tree dest_size,
1517 tree source_tree, ffebld source UNUSED,
1518 bool scalar_arg)
1520 tree source_decl;
1521 tree source_offset;
1522 tree source_size;
1523 tree t;
1525 if (source_tree == NULL_TREE)
1526 return FALSE;
1528 switch (TREE_CODE (source_tree))
1530 case ERROR_MARK:
1531 case IDENTIFIER_NODE:
1532 case INTEGER_CST:
1533 case REAL_CST:
1534 case COMPLEX_CST:
1535 case STRING_CST:
1536 case CONST_DECL:
1537 case VAR_DECL:
1538 case RESULT_DECL:
1539 case FIELD_DECL:
1540 case MINUS_EXPR:
1541 case MULT_EXPR:
1542 case TRUNC_DIV_EXPR:
1543 case CEIL_DIV_EXPR:
1544 case FLOOR_DIV_EXPR:
1545 case ROUND_DIV_EXPR:
1546 case TRUNC_MOD_EXPR:
1547 case CEIL_MOD_EXPR:
1548 case FLOOR_MOD_EXPR:
1549 case ROUND_MOD_EXPR:
1550 case RDIV_EXPR:
1551 case EXACT_DIV_EXPR:
1552 case FIX_TRUNC_EXPR:
1553 case FIX_CEIL_EXPR:
1554 case FIX_FLOOR_EXPR:
1555 case FIX_ROUND_EXPR:
1556 case FLOAT_EXPR:
1557 case NEGATE_EXPR:
1558 case MIN_EXPR:
1559 case MAX_EXPR:
1560 case ABS_EXPR:
1561 case FFS_EXPR:
1562 case LSHIFT_EXPR:
1563 case RSHIFT_EXPR:
1564 case LROTATE_EXPR:
1565 case RROTATE_EXPR:
1566 case BIT_IOR_EXPR:
1567 case BIT_XOR_EXPR:
1568 case BIT_AND_EXPR:
1569 case BIT_ANDTC_EXPR:
1570 case BIT_NOT_EXPR:
1571 case TRUTH_ANDIF_EXPR:
1572 case TRUTH_ORIF_EXPR:
1573 case TRUTH_AND_EXPR:
1574 case TRUTH_OR_EXPR:
1575 case TRUTH_XOR_EXPR:
1576 case TRUTH_NOT_EXPR:
1577 case LT_EXPR:
1578 case LE_EXPR:
1579 case GT_EXPR:
1580 case GE_EXPR:
1581 case EQ_EXPR:
1582 case NE_EXPR:
1583 case COMPLEX_EXPR:
1584 case CONJ_EXPR:
1585 case REALPART_EXPR:
1586 case IMAGPART_EXPR:
1587 case LABEL_EXPR:
1588 case COMPONENT_REF:
1589 return FALSE;
1591 case COMPOUND_EXPR:
1592 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1593 TREE_OPERAND (source_tree, 1), NULL,
1594 scalar_arg);
1596 case MODIFY_EXPR:
1597 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1598 TREE_OPERAND (source_tree, 0), NULL,
1599 scalar_arg);
1601 case CONVERT_EXPR:
1602 case NOP_EXPR:
1603 case NON_LVALUE_EXPR:
1604 case PLUS_EXPR:
1605 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1606 return TRUE;
1608 ffecom_tree_canonize_ptr_ (&source_decl, &source_offset,
1609 source_tree);
1610 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1611 break;
1613 case COND_EXPR:
1614 return
1615 ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1616 TREE_OPERAND (source_tree, 1), NULL,
1617 scalar_arg)
1618 || ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1619 TREE_OPERAND (source_tree, 2), NULL,
1620 scalar_arg);
1623 case ADDR_EXPR:
1624 ffecom_tree_canonize_ref_ (&source_decl, &source_offset,
1625 &source_size,
1626 TREE_OPERAND (source_tree, 0));
1627 break;
1629 case PARM_DECL:
1630 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1631 return TRUE;
1633 source_decl = source_tree;
1634 source_offset = bitsize_zero_node;
1635 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1636 break;
1638 case SAVE_EXPR:
1639 case REFERENCE_EXPR:
1640 case PREDECREMENT_EXPR:
1641 case PREINCREMENT_EXPR:
1642 case POSTDECREMENT_EXPR:
1643 case POSTINCREMENT_EXPR:
1644 case INDIRECT_REF:
1645 case ARRAY_REF:
1646 case CALL_EXPR:
1647 default:
1648 return TRUE;
1651 /* Come here when source_decl, source_offset, and source_size filled
1652 in appropriately. */
1654 if (source_decl == NULL_TREE)
1655 return FALSE; /* No decl involved, so no overlap. */
1657 if (source_decl != dest_decl)
1658 return FALSE; /* Different decl, no overlap. */
1660 if (TREE_CODE (dest_size) == ERROR_MARK)
1661 return TRUE; /* Assignment into entire assumed-size
1662 array? Shouldn't happen.... */
1664 t = ffecom_2 (LE_EXPR, integer_type_node,
1665 ffecom_2 (PLUS_EXPR, TREE_TYPE (dest_offset),
1666 dest_offset,
1667 convert (TREE_TYPE (dest_offset),
1668 dest_size)),
1669 convert (TREE_TYPE (dest_offset),
1670 source_offset));
1672 if (integer_onep (t))
1673 return FALSE; /* Destination precedes source. */
1675 if (!scalar_arg
1676 || (source_size == NULL_TREE)
1677 || (TREE_CODE (source_size) == ERROR_MARK)
1678 || integer_zerop (source_size))
1679 return TRUE; /* No way to tell if dest follows source. */
1681 t = ffecom_2 (LE_EXPR, integer_type_node,
1682 ffecom_2 (PLUS_EXPR, TREE_TYPE (source_offset),
1683 source_offset,
1684 convert (TREE_TYPE (source_offset),
1685 source_size)),
1686 convert (TREE_TYPE (source_offset),
1687 dest_offset));
1689 if (integer_onep (t))
1690 return FALSE; /* Destination follows source. */
1692 return TRUE; /* Destination and source overlap. */
1695 /* Check whether dest might overlap any of a list of arguments or is
1696 in a COMMON area the callee might know about (and thus modify). */
1698 static bool
1699 ffecom_args_overlapping_ (tree dest_tree, ffebld dest UNUSED,
1700 tree args, tree callee_commons,
1701 bool scalar_args)
1703 tree arg;
1704 tree dest_decl;
1705 tree dest_offset;
1706 tree dest_size;
1708 ffecom_tree_canonize_ref_ (&dest_decl, &dest_offset, &dest_size,
1709 dest_tree);
1711 if (dest_decl == NULL_TREE)
1712 return FALSE; /* Seems unlikely! */
1714 /* If the decl cannot be determined reliably, or if its in COMMON
1715 and the callee isn't known to not futz with COMMON via other
1716 means, overlap might happen. */
1718 if ((TREE_CODE (dest_decl) == ERROR_MARK)
1719 || ((callee_commons != NULL_TREE)
1720 && TREE_PUBLIC (dest_decl)))
1721 return TRUE;
1723 for (; args != NULL_TREE; args = TREE_CHAIN (args))
1725 if (((arg = TREE_VALUE (args)) != NULL_TREE)
1726 && ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1727 arg, NULL, scalar_args))
1728 return TRUE;
1731 return FALSE;
1734 /* Build a string for a variable name as used by NAMELIST. This means that
1735 if we're using the f2c library, we build an uppercase string, since
1736 f2c does this. */
1738 static tree
1739 ffecom_build_f2c_string_ (int i, const char *s)
1741 if (!ffe_is_f2c_library ())
1742 return build_string (i, s);
1745 char *tmp;
1746 const char *p;
1747 char *q;
1748 char space[34];
1749 tree t;
1751 if (((size_t) i) > ARRAY_SIZE (space))
1752 tmp = malloc_new_ks (malloc_pool_image (), "f2c_string", i);
1753 else
1754 tmp = &space[0];
1756 for (p = s, q = tmp; *p != '\0'; ++p, ++q)
1757 *q = TOUPPER (*p);
1758 *q = '\0';
1760 t = build_string (i, tmp);
1762 if (((size_t) i) > ARRAY_SIZE (space))
1763 malloc_kill_ks (malloc_pool_image (), tmp, i);
1765 return t;
1769 /* Returns CALL_EXPR or equivalent with given type (pass NULL_TREE for
1770 type to just get whatever the function returns), handling the
1771 f2c value-returning convention, if required, by prepending
1772 to the arglist a pointer to a temporary to receive the return value. */
1774 static tree
1775 ffecom_call_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1776 tree type, tree args, tree dest_tree,
1777 ffebld dest, bool *dest_used, tree callee_commons,
1778 bool scalar_args, tree hook)
1780 tree item;
1781 tree tempvar;
1783 if (dest_used != NULL)
1784 *dest_used = FALSE;
1786 if (is_f2c_complex)
1788 if ((dest_used == NULL)
1789 || (dest == NULL)
1790 || (ffeinfo_basictype (ffebld_info (dest))
1791 != FFEINFO_basictypeCOMPLEX)
1792 || (ffeinfo_kindtype (ffebld_info (dest)) != kt)
1793 || ((type != NULL_TREE) && (TREE_TYPE (dest_tree) != type))
1794 || ffecom_args_overlapping_ (dest_tree, dest, args,
1795 callee_commons,
1796 scalar_args))
1798 #ifdef HOHO
1799 tempvar = ffecom_make_tempvar (ffecom_tree_type
1800 [FFEINFO_basictypeCOMPLEX][kt],
1801 FFETARGET_charactersizeNONE,
1802 -1);
1803 #else
1804 tempvar = hook;
1805 assert (tempvar);
1806 #endif
1808 else
1810 *dest_used = TRUE;
1811 tempvar = dest_tree;
1812 type = NULL_TREE;
1815 item
1816 = build_tree_list (NULL_TREE,
1817 ffecom_1 (ADDR_EXPR,
1818 build_pointer_type (TREE_TYPE (tempvar)),
1819 tempvar));
1820 TREE_CHAIN (item) = args;
1822 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1823 item, NULL_TREE);
1825 if (tempvar != dest_tree)
1826 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item, tempvar);
1828 else
1829 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1830 args, NULL_TREE);
1832 if ((type != NULL_TREE) && (TREE_TYPE (item) != type))
1833 item = ffecom_convert_narrow_ (type, item);
1835 return item;
1838 /* Given two arguments, transform them and make a call to the given
1839 function via ffecom_call_. */
1841 static tree
1842 ffecom_call_binop_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1843 tree type, ffebld left, ffebld right,
1844 tree dest_tree, ffebld dest, bool *dest_used,
1845 tree callee_commons, bool scalar_args, bool ref, tree hook)
1847 tree left_tree;
1848 tree right_tree;
1849 tree left_length;
1850 tree right_length;
1852 if (ref)
1854 /* Pass arguments by reference. */
1855 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
1856 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
1858 else
1860 /* Pass arguments by value. */
1861 left_tree = ffecom_arg_expr (left, &left_length);
1862 right_tree = ffecom_arg_expr (right, &right_length);
1866 left_tree = build_tree_list (NULL_TREE, left_tree);
1867 right_tree = build_tree_list (NULL_TREE, right_tree);
1868 TREE_CHAIN (left_tree) = right_tree;
1870 if (left_length != NULL_TREE)
1872 left_length = build_tree_list (NULL_TREE, left_length);
1873 TREE_CHAIN (right_tree) = left_length;
1876 if (right_length != NULL_TREE)
1878 right_length = build_tree_list (NULL_TREE, right_length);
1879 if (left_length != NULL_TREE)
1880 TREE_CHAIN (left_length) = right_length;
1881 else
1882 TREE_CHAIN (right_tree) = right_length;
1885 return ffecom_call_ (fn, kt, is_f2c_complex, type, left_tree,
1886 dest_tree, dest, dest_used, callee_commons,
1887 scalar_args, hook);
1890 /* Return ptr/length args for char subexpression
1892 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
1893 subexpressions by constructing the appropriate trees for the ptr-to-
1894 character-text and length-of-character-text arguments in a calling
1895 sequence.
1897 Note that if with_null is TRUE, and the expression is an opCONTER,
1898 a null byte is appended to the string. */
1900 static void
1901 ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
1903 tree item;
1904 tree high;
1905 ffetargetCharacter1 val;
1906 ffetargetCharacterSize newlen;
1908 switch (ffebld_op (expr))
1910 case FFEBLD_opCONTER:
1911 val = ffebld_constant_character1 (ffebld_conter (expr));
1912 newlen = ffetarget_length_character1 (val);
1913 if (with_null)
1915 /* Begin FFETARGET-NULL-KLUDGE. */
1916 if (newlen != 0)
1917 ++newlen;
1919 *length = build_int_2 (newlen, 0);
1920 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
1921 high = build_int_2 (newlen, 0);
1922 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
1923 item = build_string (newlen,
1924 ffetarget_text_character1 (val));
1925 /* End FFETARGET-NULL-KLUDGE. */
1926 TREE_TYPE (item)
1927 = build_type_variant
1928 (build_array_type
1929 (char_type_node,
1930 build_range_type
1931 (ffecom_f2c_ftnlen_type_node,
1932 ffecom_f2c_ftnlen_one_node,
1933 high)),
1934 1, 0);
1935 TREE_CONSTANT (item) = 1;
1936 TREE_STATIC (item) = 1;
1937 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
1938 item);
1939 break;
1941 case FFEBLD_opSYMTER:
1943 ffesymbol s = ffebld_symter (expr);
1945 item = ffesymbol_hook (s).decl_tree;
1946 if (item == NULL_TREE)
1948 s = ffecom_sym_transform_ (s);
1949 item = ffesymbol_hook (s).decl_tree;
1951 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
1953 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
1954 *length = ffesymbol_hook (s).length_tree;
1955 else
1957 *length = build_int_2 (ffesymbol_size (s), 0);
1958 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
1961 else if (item == error_mark_node)
1962 *length = error_mark_node;
1963 else
1964 /* FFEINFO_kindFUNCTION. */
1965 *length = NULL_TREE;
1966 if (!ffesymbol_hook (s).addr
1967 && (item != error_mark_node))
1968 item = ffecom_1 (ADDR_EXPR,
1969 build_pointer_type (TREE_TYPE (item)),
1970 item);
1972 break;
1974 case FFEBLD_opARRAYREF:
1976 ffecom_char_args_ (&item, length, ffebld_left (expr));
1978 if (item == error_mark_node || *length == error_mark_node)
1980 item = *length = error_mark_node;
1981 break;
1984 item = ffecom_arrayref_ (item, expr, 1);
1986 break;
1988 case FFEBLD_opSUBSTR:
1990 ffebld start;
1991 ffebld end;
1992 ffebld thing = ffebld_right (expr);
1993 tree start_tree;
1994 tree end_tree;
1995 const char *char_name;
1996 ffebld left_symter;
1997 tree array;
1999 assert (ffebld_op (thing) == FFEBLD_opITEM);
2000 start = ffebld_head (thing);
2001 thing = ffebld_trail (thing);
2002 assert (ffebld_trail (thing) == NULL);
2003 end = ffebld_head (thing);
2005 /* Determine name for pretty-printing range-check errors. */
2006 for (left_symter = ffebld_left (expr);
2007 left_symter && ffebld_op (left_symter) == FFEBLD_opARRAYREF;
2008 left_symter = ffebld_left (left_symter))
2010 if (ffebld_op (left_symter) == FFEBLD_opSYMTER)
2011 char_name = ffesymbol_text (ffebld_symter (left_symter));
2012 else
2013 char_name = "[expr?]";
2015 ffecom_char_args_ (&item, length, ffebld_left (expr));
2017 if (item == error_mark_node || *length == error_mark_node)
2019 item = *length = error_mark_node;
2020 break;
2023 array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
2025 /* ~~~~Handle INTEGER*8 start/end, a la FFEBLD_opARRAYREF. */
2027 if (start == NULL)
2029 if (end == NULL)
2031 else
2033 end_tree = ffecom_expr (end);
2034 if (flag_bounds_check)
2035 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2036 char_name);
2037 end_tree = convert (ffecom_f2c_ftnlen_type_node,
2038 end_tree);
2040 if (end_tree == error_mark_node)
2042 item = *length = error_mark_node;
2043 break;
2046 *length = end_tree;
2049 else
2051 start_tree = ffecom_expr (start);
2052 if (flag_bounds_check)
2053 start_tree = ffecom_subscript_check_ (array, start_tree, 0, 0,
2054 char_name);
2055 start_tree = convert (ffecom_f2c_ftnlen_type_node,
2056 start_tree);
2058 if (start_tree == error_mark_node)
2060 item = *length = error_mark_node;
2061 break;
2064 start_tree = ffecom_save_tree (start_tree);
2066 item = ffecom_2 (PLUS_EXPR, TREE_TYPE (item),
2067 item,
2068 ffecom_2 (MINUS_EXPR,
2069 TREE_TYPE (start_tree),
2070 start_tree,
2071 ffecom_f2c_ftnlen_one_node));
2073 if (end == NULL)
2075 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2076 ffecom_f2c_ftnlen_one_node,
2077 ffecom_2 (MINUS_EXPR,
2078 ffecom_f2c_ftnlen_type_node,
2079 *length,
2080 start_tree));
2082 else
2084 end_tree = ffecom_expr (end);
2085 if (flag_bounds_check)
2086 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2087 char_name);
2088 end_tree = convert (ffecom_f2c_ftnlen_type_node,
2089 end_tree);
2091 if (end_tree == error_mark_node)
2093 item = *length = error_mark_node;
2094 break;
2097 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2098 ffecom_f2c_ftnlen_one_node,
2099 ffecom_2 (MINUS_EXPR,
2100 ffecom_f2c_ftnlen_type_node,
2101 end_tree, start_tree));
2105 break;
2107 case FFEBLD_opFUNCREF:
2109 ffesymbol s = ffebld_symter (ffebld_left (expr));
2110 tree tempvar;
2111 tree args;
2112 ffetargetCharacterSize size = ffeinfo_size (ffebld_info (expr));
2113 ffecomGfrt ix;
2115 if (size == FFETARGET_charactersizeNONE)
2116 /* ~~Kludge alert! This should someday be fixed. */
2117 size = 24;
2119 *length = build_int_2 (size, 0);
2120 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2122 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
2123 == FFEINFO_whereINTRINSIC)
2125 if (size == 1)
2127 /* Invocation of an intrinsic returning CHARACTER*1. */
2128 item = ffecom_expr_intrinsic_ (expr, NULL_TREE,
2129 NULL, NULL);
2130 break;
2132 ix = ffeintrin_gfrt_direct (ffebld_symter_implementation (ffebld_left (expr)));
2133 assert (ix != FFECOM_gfrt);
2134 item = ffecom_gfrt_tree_ (ix);
2136 else
2138 ix = FFECOM_gfrt;
2139 item = ffesymbol_hook (s).decl_tree;
2140 if (item == NULL_TREE)
2142 s = ffecom_sym_transform_ (s);
2143 item = ffesymbol_hook (s).decl_tree;
2145 if (item == error_mark_node)
2147 item = *length = error_mark_node;
2148 break;
2151 if (!ffesymbol_hook (s).addr)
2152 item = ffecom_1_fn (item);
2155 #ifdef HOHO
2156 tempvar = ffecom_push_tempvar (char_type_node, size, -1, TRUE);
2157 #else
2158 tempvar = ffebld_nonter_hook (expr);
2159 assert (tempvar);
2160 #endif
2161 tempvar = ffecom_1 (ADDR_EXPR,
2162 build_pointer_type (TREE_TYPE (tempvar)),
2163 tempvar);
2165 args = build_tree_list (NULL_TREE, tempvar);
2167 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT) /* Sfunc args by value. */
2168 TREE_CHAIN (args) = ffecom_list_expr (ffebld_right (expr));
2169 else
2171 TREE_CHAIN (args) = build_tree_list (NULL_TREE, *length);
2172 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
2174 TREE_CHAIN (TREE_CHAIN (args))
2175 = ffecom_arglist_expr_ (ffecom_gfrt_args_ (ix),
2176 ffebld_right (expr));
2178 else
2180 TREE_CHAIN (TREE_CHAIN (args))
2181 = ffecom_list_ptr_to_expr (ffebld_right (expr));
2185 item = ffecom_3s (CALL_EXPR,
2186 TREE_TYPE (TREE_TYPE (TREE_TYPE (item))),
2187 item, args, NULL_TREE);
2188 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item,
2189 tempvar);
2191 break;
2193 case FFEBLD_opCONVERT:
2195 ffecom_char_args_ (&item, length, ffebld_left (expr));
2197 if (item == error_mark_node || *length == error_mark_node)
2199 item = *length = error_mark_node;
2200 break;
2203 if ((ffebld_size_known (ffebld_left (expr))
2204 == FFETARGET_charactersizeNONE)
2205 || (ffebld_size_known (ffebld_left (expr)) < (ffebld_size (expr))))
2206 { /* Possible blank-padding needed, copy into
2207 temporary. */
2208 tree tempvar;
2209 tree args;
2210 tree newlen;
2212 #ifdef HOHO
2213 tempvar = ffecom_make_tempvar (char_type_node,
2214 ffebld_size (expr), -1);
2215 #else
2216 tempvar = ffebld_nonter_hook (expr);
2217 assert (tempvar);
2218 #endif
2219 tempvar = ffecom_1 (ADDR_EXPR,
2220 build_pointer_type (TREE_TYPE (tempvar)),
2221 tempvar);
2223 newlen = build_int_2 (ffebld_size (expr), 0);
2224 TREE_TYPE (newlen) = ffecom_f2c_ftnlen_type_node;
2226 args = build_tree_list (NULL_TREE, tempvar);
2227 TREE_CHAIN (args) = build_tree_list (NULL_TREE, item);
2228 TREE_CHAIN (TREE_CHAIN (args)) = build_tree_list (NULL_TREE, newlen);
2229 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (args)))
2230 = build_tree_list (NULL_TREE, *length);
2232 item = ffecom_call_gfrt (FFECOM_gfrtCOPY, args, NULL_TREE);
2233 TREE_SIDE_EFFECTS (item) = 1;
2234 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), fold (item),
2235 tempvar);
2236 *length = newlen;
2238 else
2239 { /* Just truncate the length. */
2240 *length = build_int_2 (ffebld_size (expr), 0);
2241 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2243 break;
2245 default:
2246 assert ("bad op for single char arg expr" == NULL);
2247 item = NULL_TREE;
2248 break;
2251 *xitem = item;
2254 /* Check the size of the type to be sure it doesn't overflow the
2255 "portable" capacities of the compiler back end. `dummy' types
2256 can generally overflow the normal sizes as long as the computations
2257 themselves don't overflow. A particular target of the back end
2258 must still enforce its size requirements, though, and the back
2259 end takes care of this in stor-layout.c. */
2261 static tree
2262 ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy)
2264 if (TREE_CODE (type) == ERROR_MARK)
2265 return type;
2267 if (TYPE_SIZE (type) == NULL_TREE)
2268 return type;
2270 if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
2271 return type;
2273 /* An array is too large if size is negative or the type_size overflows
2274 or its "upper half" is larger than 3 (which would make the signed
2275 byte size and offset computations overflow). */
2277 if ((tree_int_cst_sgn (TYPE_SIZE (type)) < 0)
2278 || (!dummy && (TREE_INT_CST_HIGH (TYPE_SIZE (type)) > 3
2279 || TREE_OVERFLOW (TYPE_SIZE (type)))))
2281 ffebad_start (FFEBAD_ARRAY_LARGE);
2282 ffebad_string (ffesymbol_text (s));
2283 ffebad_here (0, ffesymbol_where_line (s), ffesymbol_where_column (s));
2284 ffebad_finish ();
2286 return error_mark_node;
2289 return type;
2292 /* Builds a length argument (PARM_DECL). Also wraps type in an array type
2293 where the dimension info is (1:size) where <size> is ffesymbol_size(s) if
2294 known, length_arg if not known (FFETARGET_charactersizeNONE). */
2296 static tree
2297 ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s)
2299 ffetargetCharacterSize sz = ffesymbol_size (s);
2300 tree highval;
2301 tree tlen;
2302 tree type = *xtype;
2304 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
2305 tlen = NULL_TREE; /* A statement function, no length passed. */
2306 else
2308 if (ffesymbol_where (s) == FFEINFO_whereDUMMY)
2309 tlen = ffecom_get_invented_identifier ("__g77_length_%s",
2310 ffesymbol_text (s));
2311 else
2312 tlen = ffecom_get_invented_identifier ("__g77_%s", "length");
2313 tlen = build_decl (PARM_DECL, tlen, ffecom_f2c_ftnlen_type_node);
2314 DECL_ARTIFICIAL (tlen) = 1;
2317 if (sz == FFETARGET_charactersizeNONE)
2319 assert (tlen != NULL_TREE);
2320 highval = variable_size (tlen);
2322 else
2324 highval = build_int_2 (sz, 0);
2325 TREE_TYPE (highval) = ffecom_f2c_ftnlen_type_node;
2328 type = build_array_type (type,
2329 build_range_type (ffecom_f2c_ftnlen_type_node,
2330 ffecom_f2c_ftnlen_one_node,
2331 highval));
2333 *xtype = type;
2334 return tlen;
2337 /* ffecom_concat_list_gather_ -- Gather list of concatenated string exprs
2339 ffecomConcatList_ catlist;
2340 ffebld expr; // expr of CHARACTER basictype.
2341 ffetargetCharacterSize max; // max chars to gather or _...NONE if no max
2342 catlist = ffecom_concat_list_gather_(catlist,expr,max);
2344 Scans expr for character subexpressions, updates and returns catlist
2345 accordingly. */
2347 static ffecomConcatList_
2348 ffecom_concat_list_gather_ (ffecomConcatList_ catlist, ffebld expr,
2349 ffetargetCharacterSize max)
2351 ffetargetCharacterSize sz;
2353 recurse:
2355 if (expr == NULL)
2356 return catlist;
2358 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen >= max))
2359 return catlist; /* Don't append any more items. */
2361 switch (ffebld_op (expr))
2363 case FFEBLD_opCONTER:
2364 case FFEBLD_opSYMTER:
2365 case FFEBLD_opARRAYREF:
2366 case FFEBLD_opFUNCREF:
2367 case FFEBLD_opSUBSTR:
2368 case FFEBLD_opCONVERT: /* Callers should strip this off beforehand
2369 if they don't need to preserve it. */
2370 if (catlist.count == catlist.max)
2371 { /* Make a (larger) list. */
2372 ffebld *newx;
2373 int newmax;
2375 newmax = (catlist.max == 0) ? 8 : catlist.max * 2;
2376 newx = malloc_new_ks (malloc_pool_image (), "catlist",
2377 newmax * sizeof (newx[0]));
2378 if (catlist.max != 0)
2380 memcpy (newx, catlist.exprs, catlist.max * sizeof (newx[0]));
2381 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2382 catlist.max * sizeof (newx[0]));
2384 catlist.max = newmax;
2385 catlist.exprs = newx;
2387 if ((sz = ffebld_size_known (expr)) != FFETARGET_charactersizeNONE)
2388 catlist.minlen += sz;
2389 else
2390 ++catlist.minlen; /* Not true for F90; can be 0 length. */
2391 if ((sz = ffebld_size_max (expr)) == FFETARGET_charactersizeNONE)
2392 catlist.maxlen = sz;
2393 else
2394 catlist.maxlen += sz;
2395 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen > max))
2396 { /* This item overlaps (or is beyond) the end
2397 of the destination. */
2398 switch (ffebld_op (expr))
2400 case FFEBLD_opCONTER:
2401 case FFEBLD_opSYMTER:
2402 case FFEBLD_opARRAYREF:
2403 case FFEBLD_opFUNCREF:
2404 case FFEBLD_opSUBSTR:
2405 /* ~~Do useful truncations here. */
2406 break;
2408 default:
2409 assert ("op changed or inconsistent switches!" == NULL);
2410 break;
2413 catlist.exprs[catlist.count++] = expr;
2414 return catlist;
2416 case FFEBLD_opPAREN:
2417 expr = ffebld_left (expr);
2418 goto recurse; /* :::::::::::::::::::: */
2420 case FFEBLD_opCONCATENATE:
2421 catlist = ffecom_concat_list_gather_ (catlist, ffebld_left (expr), max);
2422 expr = ffebld_right (expr);
2423 goto recurse; /* :::::::::::::::::::: */
2425 #if 0 /* Breaks passing small actual arg to larger
2426 dummy arg of sfunc */
2427 case FFEBLD_opCONVERT:
2428 expr = ffebld_left (expr);
2430 ffetargetCharacterSize cmax;
2432 cmax = catlist.len + ffebld_size_known (expr);
2434 if ((max == FFETARGET_charactersizeNONE) || (max > cmax))
2435 max = cmax;
2437 goto recurse; /* :::::::::::::::::::: */
2438 #endif
2440 case FFEBLD_opANY:
2441 return catlist;
2443 default:
2444 assert ("bad op in _gather_" == NULL);
2445 return catlist;
2449 /* ffecom_concat_list_kill_ -- Kill list of concatenated string exprs
2451 ffecomConcatList_ catlist;
2452 ffecom_concat_list_kill_(catlist);
2454 Anything allocated within the list info is deallocated. */
2456 static void
2457 ffecom_concat_list_kill_ (ffecomConcatList_ catlist)
2459 if (catlist.max != 0)
2460 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2461 catlist.max * sizeof (catlist.exprs[0]));
2464 /* Make list of concatenated string exprs.
2466 Returns a flattened list of concatenated subexpressions given a
2467 tree of such expressions. */
2469 static ffecomConcatList_
2470 ffecom_concat_list_new_ (ffebld expr, ffetargetCharacterSize max)
2472 ffecomConcatList_ catlist;
2474 catlist.maxlen = catlist.minlen = catlist.max = catlist.count = 0;
2475 return ffecom_concat_list_gather_ (catlist, expr, max);
2478 /* Provide some kind of useful info on member of aggregate area,
2479 since current g77/gcc technology does not provide debug info
2480 on these members. */
2482 static void
2483 ffecom_debug_kludge_ (tree aggr, const char *aggr_type, ffesymbol member,
2484 tree member_type UNUSED, ffetargetOffset offset)
2486 tree value;
2487 tree decl;
2488 int len;
2489 char *buff;
2490 char space[120];
2491 #if 0
2492 tree type_id;
2494 for (type_id = member_type;
2495 TREE_CODE (type_id) != IDENTIFIER_NODE;
2498 switch (TREE_CODE (type_id))
2500 case INTEGER_TYPE:
2501 case REAL_TYPE:
2502 type_id = TYPE_NAME (type_id);
2503 break;
2505 case ARRAY_TYPE:
2506 case COMPLEX_TYPE:
2507 type_id = TREE_TYPE (type_id);
2508 break;
2510 default:
2511 assert ("no IDENTIFIER_NODE for type!" == NULL);
2512 type_id = error_mark_node;
2513 break;
2516 #endif
2518 if (ffecom_transform_only_dummies_
2519 || !ffe_is_debug_kludge ())
2520 return; /* Can't do this yet, maybe later. */
2522 len = 60
2523 + strlen (aggr_type)
2524 + IDENTIFIER_LENGTH (DECL_NAME (aggr));
2525 #if 0
2526 + IDENTIFIER_LENGTH (type_id);
2527 #endif
2529 if (((size_t) len) >= ARRAY_SIZE (space))
2530 buff = malloc_new_ks (malloc_pool_image (), "debug_kludge", len + 1);
2531 else
2532 buff = &space[0];
2534 sprintf (&buff[0], "At (%s) `%s' plus %ld bytes",
2535 aggr_type,
2536 IDENTIFIER_POINTER (DECL_NAME (aggr)),
2537 (long int) offset);
2539 value = build_string (len, buff);
2540 TREE_TYPE (value)
2541 = build_type_variant (build_array_type (char_type_node,
2542 build_range_type
2543 (integer_type_node,
2544 integer_one_node,
2545 build_int_2 (strlen (buff), 0))),
2546 1, 0);
2547 decl = build_decl (VAR_DECL,
2548 ffecom_get_identifier_ (ffesymbol_text (member)),
2549 TREE_TYPE (value));
2550 TREE_CONSTANT (decl) = 1;
2551 TREE_STATIC (decl) = 1;
2552 DECL_INITIAL (decl) = error_mark_node;
2553 DECL_IN_SYSTEM_HEADER (decl) = 1; /* Don't let -Wunused complain. */
2554 decl = start_decl (decl, FALSE);
2555 finish_decl (decl, value, FALSE);
2557 if (buff != &space[0])
2558 malloc_kill_ks (malloc_pool_image (), buff, len + 1);
2561 /* ffecom_do_entry_ -- Do compilation of a particular entrypoint
2563 ffesymbol fn; // the SUBROUTINE, FUNCTION, or ENTRY symbol itself
2564 int i; // entry# for this entrypoint (used by master fn)
2565 ffecom_do_entrypoint_(s,i);
2567 Makes a public entry point that calls our private master fn (already
2568 compiled). */
2570 static void
2571 ffecom_do_entry_ (ffesymbol fn, int entrynum)
2573 ffebld item;
2574 tree type; /* Type of function. */
2575 tree multi_retval; /* Var holding return value (union). */
2576 tree result; /* Var holding result. */
2577 ffeinfoBasictype bt;
2578 ffeinfoKindtype kt;
2579 ffeglobal g;
2580 ffeglobalType gt;
2581 bool charfunc; /* All entry points return same type
2582 CHARACTER. */
2583 bool cmplxfunc; /* Use f2c way of returning COMPLEX. */
2584 bool multi; /* Master fn has multiple return types. */
2585 bool altreturning = FALSE; /* This entry point has alternate returns. */
2586 int old_lineno = lineno;
2587 const char *old_input_filename = input_filename;
2589 input_filename = ffesymbol_where_filename (fn);
2590 lineno = ffesymbol_where_filelinenum (fn);
2592 ffecom_doing_entry_ = TRUE; /* Don't bother with array dimensions. */
2594 switch (ffecom_primary_entry_kind_)
2596 case FFEINFO_kindFUNCTION:
2598 /* Determine actual return type for function. */
2600 gt = FFEGLOBAL_typeFUNC;
2601 bt = ffesymbol_basictype (fn);
2602 kt = ffesymbol_kindtype (fn);
2603 if (bt == FFEINFO_basictypeNONE)
2605 ffeimplic_establish_symbol (fn);
2606 if (ffesymbol_funcresult (fn) != NULL)
2607 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
2608 bt = ffesymbol_basictype (fn);
2609 kt = ffesymbol_kindtype (fn);
2612 if (bt == FFEINFO_basictypeCHARACTER)
2613 charfunc = TRUE, cmplxfunc = FALSE;
2614 else if ((bt == FFEINFO_basictypeCOMPLEX)
2615 && ffesymbol_is_f2c (fn))
2616 charfunc = FALSE, cmplxfunc = TRUE;
2617 else
2618 charfunc = cmplxfunc = FALSE;
2620 if (charfunc)
2621 type = ffecom_tree_fun_type_void;
2622 else if (ffesymbol_is_f2c (fn))
2623 type = ffecom_tree_fun_type[bt][kt];
2624 else
2625 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
2627 if ((type == NULL_TREE)
2628 || (TREE_TYPE (type) == NULL_TREE))
2629 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
2631 multi = (ffecom_master_bt_ == FFEINFO_basictypeNONE);
2632 break;
2634 case FFEINFO_kindSUBROUTINE:
2635 gt = FFEGLOBAL_typeSUBR;
2636 bt = FFEINFO_basictypeNONE;
2637 kt = FFEINFO_kindtypeNONE;
2638 if (ffecom_is_altreturning_)
2639 { /* Am _I_ altreturning? */
2640 for (item = ffesymbol_dummyargs (fn);
2641 item != NULL;
2642 item = ffebld_trail (item))
2644 if (ffebld_op (ffebld_head (item)) == FFEBLD_opSTAR)
2646 altreturning = TRUE;
2647 break;
2650 if (altreturning)
2651 type = ffecom_tree_subr_type;
2652 else
2653 type = ffecom_tree_fun_type_void;
2655 else
2656 type = ffecom_tree_fun_type_void;
2657 charfunc = FALSE;
2658 cmplxfunc = FALSE;
2659 multi = FALSE;
2660 break;
2662 default:
2663 assert ("say what??" == NULL);
2664 /* Fall through. */
2665 case FFEINFO_kindANY:
2666 gt = FFEGLOBAL_typeANY;
2667 bt = FFEINFO_basictypeNONE;
2668 kt = FFEINFO_kindtypeNONE;
2669 type = error_mark_node;
2670 charfunc = FALSE;
2671 cmplxfunc = FALSE;
2672 multi = FALSE;
2673 break;
2676 /* build_decl uses the current lineno and input_filename to set the decl
2677 source info. So, I've putzed with ffestd and ffeste code to update that
2678 source info to point to the appropriate statement just before calling
2679 ffecom_do_entrypoint (which calls this fn). */
2681 start_function (ffecom_get_external_identifier_ (fn),
2682 type,
2683 0, /* nested/inline */
2684 1); /* TREE_PUBLIC */
2686 if (((g = ffesymbol_global (fn)) != NULL)
2687 && ((ffeglobal_type (g) == gt)
2688 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
2690 ffeglobal_set_hook (g, current_function_decl);
2693 /* Reset args in master arg list so they get retransitioned. */
2695 for (item = ffecom_master_arglist_;
2696 item != NULL;
2697 item = ffebld_trail (item))
2699 ffebld arg;
2700 ffesymbol s;
2702 arg = ffebld_head (item);
2703 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2704 continue; /* Alternate return or some such thing. */
2705 s = ffebld_symter (arg);
2706 ffesymbol_hook (s).decl_tree = NULL_TREE;
2707 ffesymbol_hook (s).length_tree = NULL_TREE;
2710 /* Build dummy arg list for this entry point. */
2712 if (charfunc || cmplxfunc)
2713 { /* Prepend arg for where result goes. */
2714 tree type;
2715 tree length;
2717 if (charfunc)
2718 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
2719 else
2720 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
2722 result = ffecom_get_invented_identifier ("__g77_%s", "result");
2724 /* Make length arg _and_ enhance type info for CHAR arg itself. */
2726 if (charfunc)
2727 length = ffecom_char_enhance_arg_ (&type, fn);
2728 else
2729 length = NULL_TREE; /* Not ref'd if !charfunc. */
2731 type = build_pointer_type (type);
2732 result = build_decl (PARM_DECL, result, type);
2734 push_parm_decl (result);
2735 ffecom_func_result_ = result;
2737 if (charfunc)
2739 push_parm_decl (length);
2740 ffecom_func_length_ = length;
2743 else
2744 result = DECL_RESULT (current_function_decl);
2746 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (fn), FALSE);
2748 store_parm_decls (0);
2750 ffecom_start_compstmt ();
2751 /* Disallow temp vars at this level. */
2752 current_binding_level->prep_state = 2;
2754 /* Make local var to hold return type for multi-type master fn. */
2756 if (multi)
2758 multi_retval = ffecom_get_invented_identifier ("__g77_%s",
2759 "multi_retval");
2760 multi_retval = build_decl (VAR_DECL, multi_retval,
2761 ffecom_multi_type_node_);
2762 multi_retval = start_decl (multi_retval, FALSE);
2763 finish_decl (multi_retval, NULL_TREE, FALSE);
2765 else
2766 multi_retval = NULL_TREE; /* Not actually ref'd if !multi. */
2768 /* Here we emit the actual code for the entry point. */
2771 ffebld list;
2772 ffebld arg;
2773 ffesymbol s;
2774 tree arglist = NULL_TREE;
2775 tree *plist = &arglist;
2776 tree prepend;
2777 tree call;
2778 tree actarg;
2779 tree master_fn;
2781 /* Prepare actual arg list based on master arg list. */
2783 for (list = ffecom_master_arglist_;
2784 list != NULL;
2785 list = ffebld_trail (list))
2787 arg = ffebld_head (list);
2788 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2789 continue;
2790 s = ffebld_symter (arg);
2791 if (ffesymbol_hook (s).decl_tree == NULL_TREE
2792 || ffesymbol_hook (s).decl_tree == error_mark_node)
2793 actarg = null_pointer_node; /* We don't have this arg. */
2794 else
2795 actarg = ffesymbol_hook (s).decl_tree;
2796 *plist = build_tree_list (NULL_TREE, actarg);
2797 plist = &TREE_CHAIN (*plist);
2800 /* This code appends the length arguments for character
2801 variables/arrays. */
2803 for (list = ffecom_master_arglist_;
2804 list != NULL;
2805 list = ffebld_trail (list))
2807 arg = ffebld_head (list);
2808 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2809 continue;
2810 s = ffebld_symter (arg);
2811 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
2812 continue; /* Only looking for CHARACTER arguments. */
2813 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
2814 continue; /* Only looking for variables and arrays. */
2815 if (ffesymbol_hook (s).length_tree == NULL_TREE
2816 || ffesymbol_hook (s).length_tree == error_mark_node)
2817 actarg = ffecom_f2c_ftnlen_zero_node; /* We don't have this arg. */
2818 else
2819 actarg = ffesymbol_hook (s).length_tree;
2820 *plist = build_tree_list (NULL_TREE, actarg);
2821 plist = &TREE_CHAIN (*plist);
2824 /* Prepend character-value return info to actual arg list. */
2826 if (charfunc)
2828 prepend = build_tree_list (NULL_TREE, ffecom_func_result_);
2829 TREE_CHAIN (prepend)
2830 = build_tree_list (NULL_TREE, ffecom_func_length_);
2831 TREE_CHAIN (TREE_CHAIN (prepend)) = arglist;
2832 arglist = prepend;
2835 /* Prepend multi-type return value to actual arg list. */
2837 if (multi)
2839 prepend
2840 = build_tree_list (NULL_TREE,
2841 ffecom_1 (ADDR_EXPR,
2842 build_pointer_type (TREE_TYPE (multi_retval)),
2843 multi_retval));
2844 TREE_CHAIN (prepend) = arglist;
2845 arglist = prepend;
2848 /* Prepend my entry-point number to the actual arg list. */
2850 prepend = build_tree_list (NULL_TREE, build_int_2 (entrynum, 0));
2851 TREE_CHAIN (prepend) = arglist;
2852 arglist = prepend;
2854 /* Build the call to the master function. */
2856 master_fn = ffecom_1_fn (ffecom_previous_function_decl_);
2857 call = ffecom_3s (CALL_EXPR,
2858 TREE_TYPE (TREE_TYPE (TREE_TYPE (master_fn))),
2859 master_fn, arglist, NULL_TREE);
2861 /* Decide whether the master function is a function or subroutine, and
2862 handle the return value for my entry point. */
2864 if (charfunc || ((ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
2865 && !altreturning))
2867 expand_expr_stmt (call);
2868 expand_null_return ();
2870 else if (multi && cmplxfunc)
2872 expand_expr_stmt (call);
2873 result
2874 = ffecom_1 (INDIRECT_REF,
2875 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
2876 result);
2877 result = ffecom_modify (NULL_TREE, result,
2878 ffecom_2 (COMPONENT_REF, TREE_TYPE (result),
2879 multi_retval,
2880 ffecom_multi_fields_[bt][kt]));
2881 expand_expr_stmt (result);
2882 expand_null_return ();
2884 else if (multi)
2886 expand_expr_stmt (call);
2887 result
2888 = ffecom_modify (NULL_TREE, result,
2889 convert (TREE_TYPE (result),
2890 ffecom_2 (COMPONENT_REF,
2891 ffecom_tree_type[bt][kt],
2892 multi_retval,
2893 ffecom_multi_fields_[bt][kt])));
2894 expand_return (result);
2896 else if (cmplxfunc)
2898 result
2899 = ffecom_1 (INDIRECT_REF,
2900 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
2901 result);
2902 result = ffecom_modify (NULL_TREE, result, call);
2903 expand_expr_stmt (result);
2904 expand_null_return ();
2906 else
2908 result = ffecom_modify (NULL_TREE,
2909 result,
2910 convert (TREE_TYPE (result),
2911 call));
2912 expand_return (result);
2916 ffecom_end_compstmt ();
2918 finish_function (0);
2920 lineno = old_lineno;
2921 input_filename = old_input_filename;
2923 ffecom_doing_entry_ = FALSE;
2926 /* Transform expr into gcc tree with possible destination
2928 Recursive descent on expr while making corresponding tree nodes and
2929 attaching type info and such. If destination supplied and compatible
2930 with temporary that would be made in certain cases, temporary isn't
2931 made, destination used instead, and dest_used flag set TRUE. */
2933 static tree
2934 ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
2935 bool *dest_used, bool assignp, bool widenp)
2937 tree item;
2938 tree list;
2939 tree args;
2940 ffeinfoBasictype bt;
2941 ffeinfoKindtype kt;
2942 tree t;
2943 tree dt; /* decl_tree for an ffesymbol. */
2944 tree tree_type, tree_type_x;
2945 tree left, right;
2946 ffesymbol s;
2947 enum tree_code code;
2949 assert (expr != NULL);
2951 if (dest_used != NULL)
2952 *dest_used = FALSE;
2954 bt = ffeinfo_basictype (ffebld_info (expr));
2955 kt = ffeinfo_kindtype (ffebld_info (expr));
2956 tree_type = ffecom_tree_type[bt][kt];
2958 /* Widen integral arithmetic as desired while preserving signedness. */
2959 tree_type_x = NULL_TREE;
2960 if (widenp && tree_type
2961 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
2962 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
2963 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
2965 switch (ffebld_op (expr))
2967 case FFEBLD_opACCTER:
2969 ffebitCount i;
2970 ffebit bits = ffebld_accter_bits (expr);
2971 ffetargetOffset source_offset = 0;
2972 ffetargetOffset dest_offset = ffebld_accter_pad (expr);
2973 tree purpose;
2975 assert (dest_offset == 0
2976 || (bt == FFEINFO_basictypeCHARACTER
2977 && kt == FFEINFO_kindtypeCHARACTER1));
2979 list = item = NULL;
2980 for (;;)
2982 ffebldConstantUnion cu;
2983 ffebitCount length;
2984 bool value;
2985 ffebldConstantArray ca = ffebld_accter (expr);
2987 ffebit_test (bits, source_offset, &value, &length);
2988 if (length == 0)
2989 break;
2991 if (value)
2993 for (i = 0; i < length; ++i)
2995 cu = ffebld_constantarray_get (ca, bt, kt,
2996 source_offset + i);
2998 t = ffecom_constantunion (&cu, bt, kt, tree_type);
3000 if (i == 0
3001 && dest_offset != 0)
3002 purpose = build_int_2 (dest_offset, 0);
3003 else
3004 purpose = NULL_TREE;
3006 if (list == NULL_TREE)
3007 list = item = build_tree_list (purpose, t);
3008 else
3010 TREE_CHAIN (item) = build_tree_list (purpose, t);
3011 item = TREE_CHAIN (item);
3015 source_offset += length;
3016 dest_offset += length;
3020 item = build_int_2 ((ffebld_accter_size (expr)
3021 + ffebld_accter_pad (expr)) - 1, 0);
3022 ffebit_kill (ffebld_accter_bits (expr));
3023 TREE_TYPE (item) = ffecom_integer_type_node;
3024 item
3025 = build_array_type
3026 (tree_type,
3027 build_range_type (ffecom_integer_type_node,
3028 ffecom_integer_zero_node,
3029 item));
3030 list = build (CONSTRUCTOR, item, NULL_TREE, list);
3031 TREE_CONSTANT (list) = 1;
3032 TREE_STATIC (list) = 1;
3033 return list;
3035 case FFEBLD_opARRTER:
3037 ffetargetOffset i;
3039 list = NULL_TREE;
3040 if (ffebld_arrter_pad (expr) == 0)
3041 item = NULL_TREE;
3042 else
3044 assert (bt == FFEINFO_basictypeCHARACTER
3045 && kt == FFEINFO_kindtypeCHARACTER1);
3047 /* Becomes PURPOSE first time through loop. */
3048 item = build_int_2 (ffebld_arrter_pad (expr), 0);
3051 for (i = 0; i < ffebld_arrter_size (expr); ++i)
3053 ffebldConstantUnion cu
3054 = ffebld_constantarray_get (ffebld_arrter (expr), bt, kt, i);
3056 t = ffecom_constantunion (&cu, bt, kt, tree_type);
3058 if (list == NULL_TREE)
3059 /* Assume item is PURPOSE first time through loop. */
3060 list = item = build_tree_list (item, t);
3061 else
3063 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
3064 item = TREE_CHAIN (item);
3069 item = build_int_2 ((ffebld_arrter_size (expr)
3070 + ffebld_arrter_pad (expr)) - 1, 0);
3071 TREE_TYPE (item) = ffecom_integer_type_node;
3072 item
3073 = build_array_type
3074 (tree_type,
3075 build_range_type (ffecom_integer_type_node,
3076 ffecom_integer_zero_node,
3077 item));
3078 list = build (CONSTRUCTOR, item, NULL_TREE, list);
3079 TREE_CONSTANT (list) = 1;
3080 TREE_STATIC (list) = 1;
3081 return list;
3083 case FFEBLD_opCONTER:
3084 assert (ffebld_conter_pad (expr) == 0);
3085 item
3086 = ffecom_constantunion (&ffebld_constant_union (ffebld_conter (expr)),
3087 bt, kt, tree_type);
3088 return item;
3090 case FFEBLD_opSYMTER:
3091 if ((ffebld_symter_generic (expr) != FFEINTRIN_genNONE)
3092 || (ffebld_symter_specific (expr) != FFEINTRIN_specNONE))
3093 return ffecom_ptr_to_expr (expr); /* Same as %REF(intrinsic). */
3094 s = ffebld_symter (expr);
3095 t = ffesymbol_hook (s).decl_tree;
3097 if (assignp)
3098 { /* ASSIGN'ed-label expr. */
3099 if (ffe_is_ugly_assign ())
3101 /* User explicitly wants ASSIGN'ed variables to be at the same
3102 memory address as the variables when used in non-ASSIGN
3103 contexts. That can make old, arcane, non-standard code
3104 work, but don't try to do it when a pointer wouldn't fit
3105 in the normal variable (take other approach, and warn,
3106 instead). */
3108 if (t == NULL_TREE)
3110 s = ffecom_sym_transform_ (s);
3111 t = ffesymbol_hook (s).decl_tree;
3112 assert (t != NULL_TREE);
3115 if (t == error_mark_node)
3116 return t;
3118 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (t)))
3119 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
3121 if (ffesymbol_hook (s).addr)
3122 t = ffecom_1 (INDIRECT_REF,
3123 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3124 return t;
3127 if (ffesymbol_hook (s).assign_tree == NULL_TREE)
3129 /* xgettext:no-c-format */
3130 ffebad_start_msg ("ASSIGN'ed label cannot fit into `%A' at %0 -- using wider sibling",
3131 FFEBAD_severityWARNING);
3132 ffebad_string (ffesymbol_text (s));
3133 ffebad_here (0, ffesymbol_where_line (s),
3134 ffesymbol_where_column (s));
3135 ffebad_finish ();
3139 /* Don't use the normal variable's tree for ASSIGN, though mark
3140 it as in the system header (housekeeping). Use an explicit,
3141 specially created sibling that is known to be wide enough
3142 to hold pointers to labels. */
3144 if (t != NULL_TREE
3145 && TREE_CODE (t) == VAR_DECL)
3146 DECL_IN_SYSTEM_HEADER (t) = 1; /* Don't let -Wunused complain. */
3148 t = ffesymbol_hook (s).assign_tree;
3149 if (t == NULL_TREE)
3151 s = ffecom_sym_transform_assign_ (s);
3152 t = ffesymbol_hook (s).assign_tree;
3153 assert (t != NULL_TREE);
3156 else
3158 if (t == NULL_TREE)
3160 s = ffecom_sym_transform_ (s);
3161 t = ffesymbol_hook (s).decl_tree;
3162 assert (t != NULL_TREE);
3164 if (ffesymbol_hook (s).addr)
3165 t = ffecom_1 (INDIRECT_REF,
3166 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3168 return t;
3170 case FFEBLD_opARRAYREF:
3171 return ffecom_arrayref_ (NULL_TREE, expr, 0);
3173 case FFEBLD_opUPLUS:
3174 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3175 return ffecom_1 (NOP_EXPR, tree_type, left);
3177 case FFEBLD_opPAREN:
3178 /* ~~~Make sure Fortran rules respected here */
3179 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3180 return ffecom_1 (NOP_EXPR, tree_type, left);
3182 case FFEBLD_opUMINUS:
3183 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3184 if (tree_type_x)
3186 tree_type = tree_type_x;
3187 left = convert (tree_type, left);
3189 return ffecom_1 (NEGATE_EXPR, tree_type, left);
3191 case FFEBLD_opADD:
3192 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3193 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3194 if (tree_type_x)
3196 tree_type = tree_type_x;
3197 left = convert (tree_type, left);
3198 right = convert (tree_type, right);
3200 return ffecom_2 (PLUS_EXPR, tree_type, left, right);
3202 case FFEBLD_opSUBTRACT:
3203 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3204 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3205 if (tree_type_x)
3207 tree_type = tree_type_x;
3208 left = convert (tree_type, left);
3209 right = convert (tree_type, right);
3211 return ffecom_2 (MINUS_EXPR, tree_type, left, right);
3213 case FFEBLD_opMULTIPLY:
3214 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3215 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3216 if (tree_type_x)
3218 tree_type = tree_type_x;
3219 left = convert (tree_type, left);
3220 right = convert (tree_type, right);
3222 return ffecom_2 (MULT_EXPR, tree_type, left, right);
3224 case FFEBLD_opDIVIDE:
3225 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3226 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3227 if (tree_type_x)
3229 tree_type = tree_type_x;
3230 left = convert (tree_type, left);
3231 right = convert (tree_type, right);
3233 return ffecom_tree_divide_ (tree_type, left, right,
3234 dest_tree, dest, dest_used,
3235 ffebld_nonter_hook (expr));
3237 case FFEBLD_opPOWER:
3239 ffebld left = ffebld_left (expr);
3240 ffebld right = ffebld_right (expr);
3241 ffecomGfrt code;
3242 ffeinfoKindtype rtkt;
3243 ffeinfoKindtype ltkt;
3244 bool ref = TRUE;
3246 switch (ffeinfo_basictype (ffebld_info (right)))
3249 case FFEINFO_basictypeINTEGER:
3250 if (1 || optimize)
3252 item = ffecom_expr_power_integer_ (expr);
3253 if (item != NULL_TREE)
3254 return item;
3257 rtkt = FFEINFO_kindtypeINTEGER1;
3258 switch (ffeinfo_basictype (ffebld_info (left)))
3260 case FFEINFO_basictypeINTEGER:
3261 if ((ffeinfo_kindtype (ffebld_info (left))
3262 == FFEINFO_kindtypeINTEGER4)
3263 || (ffeinfo_kindtype (ffebld_info (right))
3264 == FFEINFO_kindtypeINTEGER4))
3266 code = FFECOM_gfrtPOW_QQ;
3267 ltkt = FFEINFO_kindtypeINTEGER4;
3268 rtkt = FFEINFO_kindtypeINTEGER4;
3270 else
3272 code = FFECOM_gfrtPOW_II;
3273 ltkt = FFEINFO_kindtypeINTEGER1;
3275 break;
3277 case FFEINFO_basictypeREAL:
3278 if (ffeinfo_kindtype (ffebld_info (left))
3279 == FFEINFO_kindtypeREAL1)
3281 code = FFECOM_gfrtPOW_RI;
3282 ltkt = FFEINFO_kindtypeREAL1;
3284 else
3286 code = FFECOM_gfrtPOW_DI;
3287 ltkt = FFEINFO_kindtypeREAL2;
3289 break;
3291 case FFEINFO_basictypeCOMPLEX:
3292 if (ffeinfo_kindtype (ffebld_info (left))
3293 == FFEINFO_kindtypeREAL1)
3295 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
3296 ltkt = FFEINFO_kindtypeREAL1;
3298 else
3300 code = FFECOM_gfrtPOW_ZI; /* Overlapping result okay. */
3301 ltkt = FFEINFO_kindtypeREAL2;
3303 break;
3305 default:
3306 assert ("bad pow_*i" == NULL);
3307 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
3308 ltkt = FFEINFO_kindtypeREAL1;
3309 break;
3311 if (ffeinfo_kindtype (ffebld_info (left)) != ltkt)
3312 left = ffeexpr_convert (left, NULL, NULL,
3313 ffeinfo_basictype (ffebld_info (left)),
3314 ltkt, 0,
3315 FFETARGET_charactersizeNONE,
3316 FFEEXPR_contextLET);
3317 if (ffeinfo_kindtype (ffebld_info (right)) != rtkt)
3318 right = ffeexpr_convert (right, NULL, NULL,
3319 FFEINFO_basictypeINTEGER,
3320 rtkt, 0,
3321 FFETARGET_charactersizeNONE,
3322 FFEEXPR_contextLET);
3323 break;
3325 case FFEINFO_basictypeREAL:
3326 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3327 left = ffeexpr_convert (left, NULL, NULL, FFEINFO_basictypeREAL,
3328 FFEINFO_kindtypeREALDOUBLE, 0,
3329 FFETARGET_charactersizeNONE,
3330 FFEEXPR_contextLET);
3331 if (ffeinfo_kindtype (ffebld_info (right))
3332 == FFEINFO_kindtypeREAL1)
3333 right = ffeexpr_convert (right, NULL, NULL,
3334 FFEINFO_basictypeREAL,
3335 FFEINFO_kindtypeREALDOUBLE, 0,
3336 FFETARGET_charactersizeNONE,
3337 FFEEXPR_contextLET);
3338 /* We used to call FFECOM_gfrtPOW_DD here,
3339 which passes arguments by reference. */
3340 code = FFECOM_gfrtL_POW;
3341 /* Pass arguments by value. */
3342 ref = FALSE;
3343 break;
3345 case FFEINFO_basictypeCOMPLEX:
3346 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3347 left = ffeexpr_convert (left, NULL, NULL,
3348 FFEINFO_basictypeCOMPLEX,
3349 FFEINFO_kindtypeREALDOUBLE, 0,
3350 FFETARGET_charactersizeNONE,
3351 FFEEXPR_contextLET);
3352 if (ffeinfo_kindtype (ffebld_info (right))
3353 == FFEINFO_kindtypeREAL1)
3354 right = ffeexpr_convert (right, NULL, NULL,
3355 FFEINFO_basictypeCOMPLEX,
3356 FFEINFO_kindtypeREALDOUBLE, 0,
3357 FFETARGET_charactersizeNONE,
3358 FFEEXPR_contextLET);
3359 code = FFECOM_gfrtPOW_ZZ; /* Overlapping result okay. */
3360 ref = TRUE; /* Pass arguments by reference. */
3361 break;
3363 default:
3364 assert ("bad pow_x*" == NULL);
3365 code = FFECOM_gfrtPOW_II;
3366 break;
3368 return ffecom_call_binop_ (ffecom_gfrt_tree_ (code),
3369 ffecom_gfrt_kindtype (code),
3370 (ffe_is_f2c_library ()
3371 && ffecom_gfrt_complex_[code]),
3372 tree_type, left, right,
3373 dest_tree, dest, dest_used,
3374 NULL_TREE, FALSE, ref,
3375 ffebld_nonter_hook (expr));
3378 case FFEBLD_opNOT:
3379 switch (bt)
3381 case FFEINFO_basictypeLOGICAL:
3382 item = ffecom_truth_value_invert (ffecom_expr (ffebld_left (expr)));
3383 return convert (tree_type, item);
3385 case FFEINFO_basictypeINTEGER:
3386 return ffecom_1 (BIT_NOT_EXPR, tree_type,
3387 ffecom_expr (ffebld_left (expr)));
3389 default:
3390 assert ("NOT bad basictype" == NULL);
3391 /* Fall through. */
3392 case FFEINFO_basictypeANY:
3393 return error_mark_node;
3395 break;
3397 case FFEBLD_opFUNCREF:
3398 assert (ffeinfo_basictype (ffebld_info (expr))
3399 != FFEINFO_basictypeCHARACTER);
3400 /* Fall through. */
3401 case FFEBLD_opSUBRREF:
3402 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
3403 == FFEINFO_whereINTRINSIC)
3404 { /* Invocation of an intrinsic. */
3405 item = ffecom_expr_intrinsic_ (expr, dest_tree, dest,
3406 dest_used);
3407 return item;
3409 s = ffebld_symter (ffebld_left (expr));
3410 dt = ffesymbol_hook (s).decl_tree;
3411 if (dt == NULL_TREE)
3413 s = ffecom_sym_transform_ (s);
3414 dt = ffesymbol_hook (s).decl_tree;
3416 if (dt == error_mark_node)
3417 return dt;
3419 if (ffesymbol_hook (s).addr)
3420 item = dt;
3421 else
3422 item = ffecom_1_fn (dt);
3424 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
3425 args = ffecom_list_expr (ffebld_right (expr));
3426 else
3427 args = ffecom_list_ptr_to_expr (ffebld_right (expr));
3429 if (args == error_mark_node)
3430 return error_mark_node;
3432 item = ffecom_call_ (item, kt,
3433 ffesymbol_is_f2c (s)
3434 && (bt == FFEINFO_basictypeCOMPLEX)
3435 && (ffesymbol_where (s)
3436 != FFEINFO_whereCONSTANT),
3437 tree_type,
3438 args,
3439 dest_tree, dest, dest_used,
3440 error_mark_node, FALSE,
3441 ffebld_nonter_hook (expr));
3442 TREE_SIDE_EFFECTS (item) = 1;
3443 return item;
3445 case FFEBLD_opAND:
3446 switch (bt)
3448 case FFEINFO_basictypeLOGICAL:
3449 item
3450 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3451 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3452 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3453 return convert (tree_type, item);
3455 case FFEINFO_basictypeINTEGER:
3456 return ffecom_2 (BIT_AND_EXPR, tree_type,
3457 ffecom_expr (ffebld_left (expr)),
3458 ffecom_expr (ffebld_right (expr)));
3460 default:
3461 assert ("AND bad basictype" == NULL);
3462 /* Fall through. */
3463 case FFEINFO_basictypeANY:
3464 return error_mark_node;
3466 break;
3468 case FFEBLD_opOR:
3469 switch (bt)
3471 case FFEINFO_basictypeLOGICAL:
3472 item
3473 = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
3474 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3475 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3476 return convert (tree_type, item);
3478 case FFEINFO_basictypeINTEGER:
3479 return ffecom_2 (BIT_IOR_EXPR, tree_type,
3480 ffecom_expr (ffebld_left (expr)),
3481 ffecom_expr (ffebld_right (expr)));
3483 default:
3484 assert ("OR bad basictype" == NULL);
3485 /* Fall through. */
3486 case FFEINFO_basictypeANY:
3487 return error_mark_node;
3489 break;
3491 case FFEBLD_opXOR:
3492 case FFEBLD_opNEQV:
3493 switch (bt)
3495 case FFEINFO_basictypeLOGICAL:
3496 item
3497 = ffecom_2 (NE_EXPR, integer_type_node,
3498 ffecom_expr (ffebld_left (expr)),
3499 ffecom_expr (ffebld_right (expr)));
3500 return convert (tree_type, ffecom_truth_value (item));
3502 case FFEINFO_basictypeINTEGER:
3503 return ffecom_2 (BIT_XOR_EXPR, tree_type,
3504 ffecom_expr (ffebld_left (expr)),
3505 ffecom_expr (ffebld_right (expr)));
3507 default:
3508 assert ("XOR/NEQV bad basictype" == NULL);
3509 /* Fall through. */
3510 case FFEINFO_basictypeANY:
3511 return error_mark_node;
3513 break;
3515 case FFEBLD_opEQV:
3516 switch (bt)
3518 case FFEINFO_basictypeLOGICAL:
3519 item
3520 = ffecom_2 (EQ_EXPR, integer_type_node,
3521 ffecom_expr (ffebld_left (expr)),
3522 ffecom_expr (ffebld_right (expr)));
3523 return convert (tree_type, ffecom_truth_value (item));
3525 case FFEINFO_basictypeINTEGER:
3526 return
3527 ffecom_1 (BIT_NOT_EXPR, tree_type,
3528 ffecom_2 (BIT_XOR_EXPR, tree_type,
3529 ffecom_expr (ffebld_left (expr)),
3530 ffecom_expr (ffebld_right (expr))));
3532 default:
3533 assert ("EQV bad basictype" == NULL);
3534 /* Fall through. */
3535 case FFEINFO_basictypeANY:
3536 return error_mark_node;
3538 break;
3540 case FFEBLD_opCONVERT:
3541 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opANY)
3542 return error_mark_node;
3544 switch (bt)
3546 case FFEINFO_basictypeLOGICAL:
3547 case FFEINFO_basictypeINTEGER:
3548 case FFEINFO_basictypeREAL:
3549 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3551 case FFEINFO_basictypeCOMPLEX:
3552 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3554 case FFEINFO_basictypeINTEGER:
3555 case FFEINFO_basictypeLOGICAL:
3556 case FFEINFO_basictypeREAL:
3557 item = ffecom_expr (ffebld_left (expr));
3558 if (item == error_mark_node)
3559 return error_mark_node;
3560 /* convert() takes care of converting to the subtype first,
3561 at least in gcc-2.7.2. */
3562 item = convert (tree_type, item);
3563 return item;
3565 case FFEINFO_basictypeCOMPLEX:
3566 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3568 default:
3569 assert ("CONVERT COMPLEX bad basictype" == NULL);
3570 /* Fall through. */
3571 case FFEINFO_basictypeANY:
3572 return error_mark_node;
3574 break;
3576 default:
3577 assert ("CONVERT bad basictype" == NULL);
3578 /* Fall through. */
3579 case FFEINFO_basictypeANY:
3580 return error_mark_node;
3582 break;
3584 case FFEBLD_opLT:
3585 code = LT_EXPR;
3586 goto relational; /* :::::::::::::::::::: */
3588 case FFEBLD_opLE:
3589 code = LE_EXPR;
3590 goto relational; /* :::::::::::::::::::: */
3592 case FFEBLD_opEQ:
3593 code = EQ_EXPR;
3594 goto relational; /* :::::::::::::::::::: */
3596 case FFEBLD_opNE:
3597 code = NE_EXPR;
3598 goto relational; /* :::::::::::::::::::: */
3600 case FFEBLD_opGT:
3601 code = GT_EXPR;
3602 goto relational; /* :::::::::::::::::::: */
3604 case FFEBLD_opGE:
3605 code = GE_EXPR;
3607 relational: /* :::::::::::::::::::: */
3608 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3610 case FFEINFO_basictypeLOGICAL:
3611 case FFEINFO_basictypeINTEGER:
3612 case FFEINFO_basictypeREAL:
3613 item = ffecom_2 (code, integer_type_node,
3614 ffecom_expr (ffebld_left (expr)),
3615 ffecom_expr (ffebld_right (expr)));
3616 return convert (tree_type, item);
3618 case FFEINFO_basictypeCOMPLEX:
3619 assert (code == EQ_EXPR || code == NE_EXPR);
3621 tree real_type;
3622 tree arg1 = ffecom_expr (ffebld_left (expr));
3623 tree arg2 = ffecom_expr (ffebld_right (expr));
3625 if (arg1 == error_mark_node || arg2 == error_mark_node)
3626 return error_mark_node;
3628 arg1 = ffecom_save_tree (arg1);
3629 arg2 = ffecom_save_tree (arg2);
3631 if (TREE_CODE (TREE_TYPE (arg1)) == COMPLEX_TYPE)
3633 real_type = TREE_TYPE (TREE_TYPE (arg1));
3634 assert (real_type == TREE_TYPE (TREE_TYPE (arg2)));
3636 else
3638 real_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg1)));
3639 assert (real_type == TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg2))));
3642 item
3643 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3644 ffecom_2 (EQ_EXPR, integer_type_node,
3645 ffecom_1 (REALPART_EXPR, real_type, arg1),
3646 ffecom_1 (REALPART_EXPR, real_type, arg2)),
3647 ffecom_2 (EQ_EXPR, integer_type_node,
3648 ffecom_1 (IMAGPART_EXPR, real_type, arg1),
3649 ffecom_1 (IMAGPART_EXPR, real_type,
3650 arg2)));
3651 if (code == EQ_EXPR)
3652 item = ffecom_truth_value (item);
3653 else
3654 item = ffecom_truth_value_invert (item);
3655 return convert (tree_type, item);
3658 case FFEINFO_basictypeCHARACTER:
3660 ffebld left = ffebld_left (expr);
3661 ffebld right = ffebld_right (expr);
3662 tree left_tree;
3663 tree right_tree;
3664 tree left_length;
3665 tree right_length;
3667 /* f2c run-time functions do the implicit blank-padding for us,
3668 so we don't usually have to implement blank-padding ourselves.
3669 (The exception is when we pass an argument to a separately
3670 compiled statement function -- if we know the arg is not the
3671 same length as the dummy, we must truncate or extend it. If
3672 we "inline" statement functions, that necessity goes away as
3673 well.)
3675 Strip off the CONVERT operators that blank-pad. (Truncation by
3676 CONVERT shouldn't happen here, but it can happen in
3677 assignments.) */
3679 while (ffebld_op (left) == FFEBLD_opCONVERT)
3680 left = ffebld_left (left);
3681 while (ffebld_op (right) == FFEBLD_opCONVERT)
3682 right = ffebld_left (right);
3684 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
3685 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
3687 if (left_tree == error_mark_node || left_length == error_mark_node
3688 || right_tree == error_mark_node
3689 || right_length == error_mark_node)
3690 return error_mark_node;
3692 if ((ffebld_size_known (left) == 1)
3693 && (ffebld_size_known (right) == 1))
3695 left_tree
3696 = ffecom_1 (INDIRECT_REF,
3697 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3698 left_tree);
3699 right_tree
3700 = ffecom_1 (INDIRECT_REF,
3701 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3702 right_tree);
3704 item
3705 = ffecom_2 (code, integer_type_node,
3706 ffecom_2 (ARRAY_REF,
3707 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3708 left_tree,
3709 integer_one_node),
3710 ffecom_2 (ARRAY_REF,
3711 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3712 right_tree,
3713 integer_one_node));
3715 else
3717 item = build_tree_list (NULL_TREE, left_tree);
3718 TREE_CHAIN (item) = build_tree_list (NULL_TREE, right_tree);
3719 TREE_CHAIN (TREE_CHAIN (item)) = build_tree_list (NULL_TREE,
3720 left_length);
3721 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
3722 = build_tree_list (NULL_TREE, right_length);
3723 item = ffecom_call_gfrt (FFECOM_gfrtCMP, item, NULL_TREE);
3724 item = ffecom_2 (code, integer_type_node,
3725 item,
3726 convert (TREE_TYPE (item),
3727 integer_zero_node));
3729 item = convert (tree_type, item);
3732 return item;
3734 default:
3735 assert ("relational bad basictype" == NULL);
3736 /* Fall through. */
3737 case FFEINFO_basictypeANY:
3738 return error_mark_node;
3740 break;
3742 case FFEBLD_opPERCENT_LOC:
3743 item = ffecom_arg_ptr_to_expr (ffebld_left (expr), &list);
3744 return convert (tree_type, item);
3746 case FFEBLD_opPERCENT_VAL:
3747 item = ffecom_arg_expr (ffebld_left (expr), &list);
3748 return convert (tree_type, item);
3750 case FFEBLD_opITEM:
3751 case FFEBLD_opSTAR:
3752 case FFEBLD_opBOUNDS:
3753 case FFEBLD_opREPEAT:
3754 case FFEBLD_opLABTER:
3755 case FFEBLD_opLABTOK:
3756 case FFEBLD_opIMPDO:
3757 case FFEBLD_opCONCATENATE:
3758 case FFEBLD_opSUBSTR:
3759 default:
3760 assert ("bad op" == NULL);
3761 /* Fall through. */
3762 case FFEBLD_opANY:
3763 return error_mark_node;
3766 #if 1
3767 assert ("didn't think anything got here anymore!!" == NULL);
3768 #else
3769 switch (ffebld_arity (expr))
3771 case 2:
3772 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3773 TREE_OPERAND (item, 1) = ffecom_expr (ffebld_right (expr));
3774 if (TREE_OPERAND (item, 0) == error_mark_node
3775 || TREE_OPERAND (item, 1) == error_mark_node)
3776 return error_mark_node;
3777 break;
3779 case 1:
3780 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3781 if (TREE_OPERAND (item, 0) == error_mark_node)
3782 return error_mark_node;
3783 break;
3785 default:
3786 break;
3789 return fold (item);
3790 #endif
3793 /* Returns the tree that does the intrinsic invocation.
3795 Note: this function applies only to intrinsics returning
3796 CHARACTER*1 or non-CHARACTER results, and to intrinsic
3797 subroutines. */
3799 static tree
3800 ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
3801 ffebld dest, bool *dest_used)
3803 tree expr_tree;
3804 tree saved_expr1; /* For those who need it. */
3805 tree saved_expr2; /* For those who need it. */
3806 ffeinfoBasictype bt;
3807 ffeinfoKindtype kt;
3808 tree tree_type;
3809 tree arg1_type;
3810 tree real_type; /* REAL type corresponding to COMPLEX. */
3811 tree tempvar;
3812 ffebld list = ffebld_right (expr); /* List of (some) args. */
3813 ffebld arg1; /* For handy reference. */
3814 ffebld arg2;
3815 ffebld arg3;
3816 ffeintrinImp codegen_imp;
3817 ffecomGfrt gfrt;
3819 assert (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER);
3821 if (dest_used != NULL)
3822 *dest_used = FALSE;
3824 bt = ffeinfo_basictype (ffebld_info (expr));
3825 kt = ffeinfo_kindtype (ffebld_info (expr));
3826 tree_type = ffecom_tree_type[bt][kt];
3828 if (list != NULL)
3830 arg1 = ffebld_head (list);
3831 if (arg1 != NULL && ffebld_op (arg1) == FFEBLD_opANY)
3832 return error_mark_node;
3833 if ((list = ffebld_trail (list)) != NULL)
3835 arg2 = ffebld_head (list);
3836 if (arg2 != NULL && ffebld_op (arg2) == FFEBLD_opANY)
3837 return error_mark_node;
3838 if ((list = ffebld_trail (list)) != NULL)
3840 arg3 = ffebld_head (list);
3841 if (arg3 != NULL && ffebld_op (arg3) == FFEBLD_opANY)
3842 return error_mark_node;
3844 else
3845 arg3 = NULL;
3847 else
3848 arg2 = arg3 = NULL;
3850 else
3851 arg1 = arg2 = arg3 = NULL;
3853 /* <list> ends up at the opITEM of the 3rd arg, or NULL if there are < 3
3854 args. This is used by the MAX/MIN expansions. */
3856 if (arg1 != NULL)
3857 arg1_type = ffecom_tree_type
3858 [ffeinfo_basictype (ffebld_info (arg1))]
3859 [ffeinfo_kindtype (ffebld_info (arg1))];
3860 else
3861 arg1_type = NULL_TREE; /* Really not needed, but might catch bugs
3862 here. */
3864 /* There are several ways for each of the cases in the following switch
3865 statements to exit (from simplest to use to most complicated):
3867 break; (when expr_tree == NULL)
3869 A standard call is made to the specific intrinsic just as if it had been
3870 passed in as a dummy procedure and called as any old procedure. This
3871 method can produce slower code but in some cases it's the easiest way for
3872 now. However, if a (presumably faster) direct call is available,
3873 that is used, so this is the easiest way in many more cases now.
3875 gfrt = FFECOM_gfrtWHATEVER;
3876 break;
3878 gfrt contains the gfrt index of a library function to call, passing the
3879 argument(s) by value rather than by reference. Used when a more
3880 careful choice of library function is needed than that provided
3881 by the vanilla `break;'.
3883 return expr_tree;
3885 The expr_tree has been completely set up and is ready to be returned
3886 as is. No further actions are taken. Use this when the tree is not
3887 in the simple form for one of the arity_n labels. */
3889 /* For info on how the switch statement cases were written, see the files
3890 enclosed in comments below the switch statement. */
3892 codegen_imp = ffebld_symter_implementation (ffebld_left (expr));
3893 gfrt = ffeintrin_gfrt_direct (codegen_imp);
3894 if (gfrt == FFECOM_gfrt)
3895 gfrt = ffeintrin_gfrt_indirect (codegen_imp);
3897 switch (codegen_imp)
3899 case FFEINTRIN_impABS:
3900 case FFEINTRIN_impCABS:
3901 case FFEINTRIN_impCDABS:
3902 case FFEINTRIN_impDABS:
3903 case FFEINTRIN_impIABS:
3904 if (ffeinfo_basictype (ffebld_info (arg1))
3905 == FFEINFO_basictypeCOMPLEX)
3907 if (kt == FFEINFO_kindtypeREAL1)
3908 gfrt = FFECOM_gfrtCABS;
3909 else if (kt == FFEINFO_kindtypeREAL2)
3910 gfrt = FFECOM_gfrtCDABS;
3911 break;
3913 return ffecom_1 (ABS_EXPR, tree_type,
3914 convert (tree_type, ffecom_expr (arg1)));
3916 case FFEINTRIN_impACOS:
3917 case FFEINTRIN_impDACOS:
3918 break;
3920 case FFEINTRIN_impAIMAG:
3921 case FFEINTRIN_impDIMAG:
3922 case FFEINTRIN_impIMAGPART:
3923 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
3924 arg1_type = TREE_TYPE (arg1_type);
3925 else
3926 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
3928 return
3929 convert (tree_type,
3930 ffecom_1 (IMAGPART_EXPR, arg1_type,
3931 ffecom_expr (arg1)));
3933 case FFEINTRIN_impAINT:
3934 case FFEINTRIN_impDINT:
3935 #if 0
3936 /* ~~Someday implement FIX_TRUNC_EXPR yielding same type as arg. */
3937 return ffecom_1 (FIX_TRUNC_EXPR, tree_type, ffecom_expr (arg1));
3938 #else /* in the meantime, must use floor to avoid range problems with ints */
3939 /* r__1 = r1 >= 0 ? floor(r1) : -floor(-r1); */
3940 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
3941 return
3942 convert (tree_type,
3943 ffecom_3 (COND_EXPR, double_type_node,
3944 ffecom_truth_value
3945 (ffecom_2 (GE_EXPR, integer_type_node,
3946 saved_expr1,
3947 convert (arg1_type,
3948 ffecom_float_zero_))),
3949 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
3950 build_tree_list (NULL_TREE,
3951 convert (double_type_node,
3952 saved_expr1)),
3953 NULL_TREE),
3954 ffecom_1 (NEGATE_EXPR, double_type_node,
3955 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
3956 build_tree_list (NULL_TREE,
3957 convert (double_type_node,
3958 ffecom_1 (NEGATE_EXPR,
3959 arg1_type,
3960 saved_expr1))),
3961 NULL_TREE)
3964 #endif
3966 case FFEINTRIN_impANINT:
3967 case FFEINTRIN_impDNINT:
3968 #if 0 /* This way of doing it won't handle real
3969 numbers of large magnitudes. */
3970 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
3971 expr_tree = convert (tree_type,
3972 convert (integer_type_node,
3973 ffecom_3 (COND_EXPR, tree_type,
3974 ffecom_truth_value
3975 (ffecom_2 (GE_EXPR,
3976 integer_type_node,
3977 saved_expr1,
3978 ffecom_float_zero_)),
3979 ffecom_2 (PLUS_EXPR,
3980 tree_type,
3981 saved_expr1,
3982 ffecom_float_half_),
3983 ffecom_2 (MINUS_EXPR,
3984 tree_type,
3985 saved_expr1,
3986 ffecom_float_half_))));
3987 return expr_tree;
3988 #else /* So we instead call floor. */
3989 /* r__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1) */
3990 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
3991 return
3992 convert (tree_type,
3993 ffecom_3 (COND_EXPR, double_type_node,
3994 ffecom_truth_value
3995 (ffecom_2 (GE_EXPR, integer_type_node,
3996 saved_expr1,
3997 convert (arg1_type,
3998 ffecom_float_zero_))),
3999 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4000 build_tree_list (NULL_TREE,
4001 convert (double_type_node,
4002 ffecom_2 (PLUS_EXPR,
4003 arg1_type,
4004 saved_expr1,
4005 convert (arg1_type,
4006 ffecom_float_half_)))),
4007 NULL_TREE),
4008 ffecom_1 (NEGATE_EXPR, double_type_node,
4009 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4010 build_tree_list (NULL_TREE,
4011 convert (double_type_node,
4012 ffecom_2 (MINUS_EXPR,
4013 arg1_type,
4014 convert (arg1_type,
4015 ffecom_float_half_),
4016 saved_expr1))),
4017 NULL_TREE))
4020 #endif
4022 case FFEINTRIN_impASIN:
4023 case FFEINTRIN_impDASIN:
4024 case FFEINTRIN_impATAN:
4025 case FFEINTRIN_impDATAN:
4026 case FFEINTRIN_impATAN2:
4027 case FFEINTRIN_impDATAN2:
4028 break;
4030 case FFEINTRIN_impCHAR:
4031 case FFEINTRIN_impACHAR:
4032 #ifdef HOHO
4033 tempvar = ffecom_make_tempvar (char_type_node, 1, -1);
4034 #else
4035 tempvar = ffebld_nonter_hook (expr);
4036 assert (tempvar);
4037 #endif
4039 tree tmv = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (tempvar)));
4041 expr_tree = ffecom_modify (tmv,
4042 ffecom_2 (ARRAY_REF, tmv, tempvar,
4043 integer_one_node),
4044 convert (tmv, ffecom_expr (arg1)));
4046 expr_tree = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar),
4047 expr_tree,
4048 tempvar);
4049 expr_tree = ffecom_1 (ADDR_EXPR,
4050 build_pointer_type (TREE_TYPE (expr_tree)),
4051 expr_tree);
4052 return expr_tree;
4054 case FFEINTRIN_impCMPLX:
4055 case FFEINTRIN_impDCMPLX:
4056 if (arg2 == NULL)
4057 return
4058 convert (tree_type, ffecom_expr (arg1));
4060 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4061 return
4062 ffecom_2 (COMPLEX_EXPR, tree_type,
4063 convert (real_type, ffecom_expr (arg1)),
4064 convert (real_type,
4065 ffecom_expr (arg2)));
4067 case FFEINTRIN_impCOMPLEX:
4068 return
4069 ffecom_2 (COMPLEX_EXPR, tree_type,
4070 ffecom_expr (arg1),
4071 ffecom_expr (arg2));
4073 case FFEINTRIN_impCONJG:
4074 case FFEINTRIN_impDCONJG:
4076 tree arg1_tree;
4078 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4079 arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4080 return
4081 ffecom_2 (COMPLEX_EXPR, tree_type,
4082 ffecom_1 (REALPART_EXPR, real_type, arg1_tree),
4083 ffecom_1 (NEGATE_EXPR, real_type,
4084 ffecom_1 (IMAGPART_EXPR, real_type, arg1_tree)));
4087 case FFEINTRIN_impCOS:
4088 case FFEINTRIN_impCCOS:
4089 case FFEINTRIN_impCDCOS:
4090 case FFEINTRIN_impDCOS:
4091 if (bt == FFEINFO_basictypeCOMPLEX)
4093 if (kt == FFEINFO_kindtypeREAL1)
4094 gfrt = FFECOM_gfrtCCOS; /* Overlapping result okay. */
4095 else if (kt == FFEINFO_kindtypeREAL2)
4096 gfrt = FFECOM_gfrtCDCOS; /* Overlapping result okay. */
4098 break;
4100 case FFEINTRIN_impCOSH:
4101 case FFEINTRIN_impDCOSH:
4102 break;
4104 case FFEINTRIN_impDBLE:
4105 case FFEINTRIN_impDFLOAT:
4106 case FFEINTRIN_impDREAL:
4107 case FFEINTRIN_impFLOAT:
4108 case FFEINTRIN_impIDINT:
4109 case FFEINTRIN_impIFIX:
4110 case FFEINTRIN_impINT2:
4111 case FFEINTRIN_impINT8:
4112 case FFEINTRIN_impINT:
4113 case FFEINTRIN_impLONG:
4114 case FFEINTRIN_impREAL:
4115 case FFEINTRIN_impSHORT:
4116 case FFEINTRIN_impSNGL:
4117 return convert (tree_type, ffecom_expr (arg1));
4119 case FFEINTRIN_impDIM:
4120 case FFEINTRIN_impDDIM:
4121 case FFEINTRIN_impIDIM:
4122 saved_expr1 = ffecom_save_tree (convert (tree_type,
4123 ffecom_expr (arg1)));
4124 saved_expr2 = ffecom_save_tree (convert (tree_type,
4125 ffecom_expr (arg2)));
4126 return
4127 ffecom_3 (COND_EXPR, tree_type,
4128 ffecom_truth_value
4129 (ffecom_2 (GT_EXPR, integer_type_node,
4130 saved_expr1,
4131 saved_expr2)),
4132 ffecom_2 (MINUS_EXPR, tree_type,
4133 saved_expr1,
4134 saved_expr2),
4135 convert (tree_type, ffecom_float_zero_));
4137 case FFEINTRIN_impDPROD:
4138 return
4139 ffecom_2 (MULT_EXPR, tree_type,
4140 convert (tree_type, ffecom_expr (arg1)),
4141 convert (tree_type, ffecom_expr (arg2)));
4143 case FFEINTRIN_impEXP:
4144 case FFEINTRIN_impCDEXP:
4145 case FFEINTRIN_impCEXP:
4146 case FFEINTRIN_impDEXP:
4147 if (bt == FFEINFO_basictypeCOMPLEX)
4149 if (kt == FFEINFO_kindtypeREAL1)
4150 gfrt = FFECOM_gfrtCEXP; /* Overlapping result okay. */
4151 else if (kt == FFEINFO_kindtypeREAL2)
4152 gfrt = FFECOM_gfrtCDEXP; /* Overlapping result okay. */
4154 break;
4156 case FFEINTRIN_impICHAR:
4157 case FFEINTRIN_impIACHAR:
4158 #if 0 /* The simple approach. */
4159 ffecom_char_args_ (&expr_tree, &saved_expr1 /* Ignored */ , arg1);
4160 expr_tree
4161 = ffecom_1 (INDIRECT_REF,
4162 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4163 expr_tree);
4164 expr_tree
4165 = ffecom_2 (ARRAY_REF,
4166 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4167 expr_tree,
4168 integer_one_node);
4169 return convert (tree_type, expr_tree);
4170 #else /* The more interesting (and more optimal) approach. */
4171 expr_tree = ffecom_intrinsic_ichar_ (tree_type, arg1, &saved_expr1);
4172 expr_tree = ffecom_3 (COND_EXPR, tree_type,
4173 saved_expr1,
4174 expr_tree,
4175 convert (tree_type, integer_zero_node));
4176 return expr_tree;
4177 #endif
4179 case FFEINTRIN_impINDEX:
4180 break;
4182 case FFEINTRIN_impLEN:
4183 #if 0
4184 break; /* The simple approach. */
4185 #else
4186 return ffecom_intrinsic_len_ (arg1); /* The more optimal approach. */
4187 #endif
4189 case FFEINTRIN_impLGE:
4190 case FFEINTRIN_impLGT:
4191 case FFEINTRIN_impLLE:
4192 case FFEINTRIN_impLLT:
4193 break;
4195 case FFEINTRIN_impLOG:
4196 case FFEINTRIN_impALOG:
4197 case FFEINTRIN_impCDLOG:
4198 case FFEINTRIN_impCLOG:
4199 case FFEINTRIN_impDLOG:
4200 if (bt == FFEINFO_basictypeCOMPLEX)
4202 if (kt == FFEINFO_kindtypeREAL1)
4203 gfrt = FFECOM_gfrtCLOG; /* Overlapping result okay. */
4204 else if (kt == FFEINFO_kindtypeREAL2)
4205 gfrt = FFECOM_gfrtCDLOG; /* Overlapping result okay. */
4207 break;
4209 case FFEINTRIN_impLOG10:
4210 case FFEINTRIN_impALOG10:
4211 case FFEINTRIN_impDLOG10:
4212 if (gfrt != FFECOM_gfrt)
4213 break; /* Already picked one, stick with it. */
4215 if (kt == FFEINFO_kindtypeREAL1)
4216 /* We used to call FFECOM_gfrtALOG10 here. */
4217 gfrt = FFECOM_gfrtL_LOG10;
4218 else if (kt == FFEINFO_kindtypeREAL2)
4219 /* We used to call FFECOM_gfrtDLOG10 here. */
4220 gfrt = FFECOM_gfrtL_LOG10;
4221 break;
4223 case FFEINTRIN_impMAX:
4224 case FFEINTRIN_impAMAX0:
4225 case FFEINTRIN_impAMAX1:
4226 case FFEINTRIN_impDMAX1:
4227 case FFEINTRIN_impMAX0:
4228 case FFEINTRIN_impMAX1:
4229 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4230 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4231 else
4232 arg1_type = tree_type;
4233 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4234 convert (arg1_type, ffecom_expr (arg1)),
4235 convert (arg1_type, ffecom_expr (arg2)));
4236 for (; list != NULL; list = ffebld_trail (list))
4238 if ((ffebld_head (list) == NULL)
4239 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4240 continue;
4241 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4242 expr_tree,
4243 convert (arg1_type,
4244 ffecom_expr (ffebld_head (list))));
4246 return convert (tree_type, expr_tree);
4248 case FFEINTRIN_impMIN:
4249 case FFEINTRIN_impAMIN0:
4250 case FFEINTRIN_impAMIN1:
4251 case FFEINTRIN_impDMIN1:
4252 case FFEINTRIN_impMIN0:
4253 case FFEINTRIN_impMIN1:
4254 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4255 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4256 else
4257 arg1_type = tree_type;
4258 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4259 convert (arg1_type, ffecom_expr (arg1)),
4260 convert (arg1_type, ffecom_expr (arg2)));
4261 for (; list != NULL; list = ffebld_trail (list))
4263 if ((ffebld_head (list) == NULL)
4264 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4265 continue;
4266 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4267 expr_tree,
4268 convert (arg1_type,
4269 ffecom_expr (ffebld_head (list))));
4271 return convert (tree_type, expr_tree);
4273 case FFEINTRIN_impMOD:
4274 case FFEINTRIN_impAMOD:
4275 case FFEINTRIN_impDMOD:
4276 if (bt != FFEINFO_basictypeREAL)
4277 return ffecom_2 (TRUNC_MOD_EXPR, tree_type,
4278 convert (tree_type, ffecom_expr (arg1)),
4279 convert (tree_type, ffecom_expr (arg2)));
4281 if (kt == FFEINFO_kindtypeREAL1)
4282 /* We used to call FFECOM_gfrtAMOD here. */
4283 gfrt = FFECOM_gfrtL_FMOD;
4284 else if (kt == FFEINFO_kindtypeREAL2)
4285 /* We used to call FFECOM_gfrtDMOD here. */
4286 gfrt = FFECOM_gfrtL_FMOD;
4287 break;
4289 case FFEINTRIN_impNINT:
4290 case FFEINTRIN_impIDNINT:
4291 #if 0
4292 /* ~~Ideally FIX_ROUND_EXPR would be implemented, but it ain't yet. */
4293 return ffecom_1 (FIX_ROUND_EXPR, tree_type, ffecom_expr (arg1));
4294 #else
4295 /* i__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1); */
4296 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4297 return
4298 convert (ffecom_integer_type_node,
4299 ffecom_3 (COND_EXPR, arg1_type,
4300 ffecom_truth_value
4301 (ffecom_2 (GE_EXPR, integer_type_node,
4302 saved_expr1,
4303 convert (arg1_type,
4304 ffecom_float_zero_))),
4305 ffecom_2 (PLUS_EXPR, arg1_type,
4306 saved_expr1,
4307 convert (arg1_type,
4308 ffecom_float_half_)),
4309 ffecom_2 (MINUS_EXPR, arg1_type,
4310 saved_expr1,
4311 convert (arg1_type,
4312 ffecom_float_half_))));
4313 #endif
4315 case FFEINTRIN_impSIGN:
4316 case FFEINTRIN_impDSIGN:
4317 case FFEINTRIN_impISIGN:
4319 tree arg2_tree = ffecom_expr (arg2);
4321 saved_expr1
4322 = ffecom_save_tree
4323 (ffecom_1 (ABS_EXPR, tree_type,
4324 convert (tree_type,
4325 ffecom_expr (arg1))));
4326 expr_tree
4327 = ffecom_3 (COND_EXPR, tree_type,
4328 ffecom_truth_value
4329 (ffecom_2 (GE_EXPR, integer_type_node,
4330 arg2_tree,
4331 convert (TREE_TYPE (arg2_tree),
4332 integer_zero_node))),
4333 saved_expr1,
4334 ffecom_1 (NEGATE_EXPR, tree_type, saved_expr1));
4335 /* Make sure SAVE_EXPRs get referenced early enough. */
4336 expr_tree
4337 = ffecom_2 (COMPOUND_EXPR, tree_type,
4338 convert (void_type_node, saved_expr1),
4339 expr_tree);
4341 return expr_tree;
4343 case FFEINTRIN_impSIN:
4344 case FFEINTRIN_impCDSIN:
4345 case FFEINTRIN_impCSIN:
4346 case FFEINTRIN_impDSIN:
4347 if (bt == FFEINFO_basictypeCOMPLEX)
4349 if (kt == FFEINFO_kindtypeREAL1)
4350 gfrt = FFECOM_gfrtCSIN; /* Overlapping result okay. */
4351 else if (kt == FFEINFO_kindtypeREAL2)
4352 gfrt = FFECOM_gfrtCDSIN; /* Overlapping result okay. */
4354 break;
4356 case FFEINTRIN_impSINH:
4357 case FFEINTRIN_impDSINH:
4358 break;
4360 case FFEINTRIN_impSQRT:
4361 case FFEINTRIN_impCDSQRT:
4362 case FFEINTRIN_impCSQRT:
4363 case FFEINTRIN_impDSQRT:
4364 if (bt == FFEINFO_basictypeCOMPLEX)
4366 if (kt == FFEINFO_kindtypeREAL1)
4367 gfrt = FFECOM_gfrtCSQRT; /* Overlapping result okay. */
4368 else if (kt == FFEINFO_kindtypeREAL2)
4369 gfrt = FFECOM_gfrtCDSQRT; /* Overlapping result okay. */
4371 break;
4373 case FFEINTRIN_impTAN:
4374 case FFEINTRIN_impDTAN:
4375 case FFEINTRIN_impTANH:
4376 case FFEINTRIN_impDTANH:
4377 break;
4379 case FFEINTRIN_impREALPART:
4380 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4381 arg1_type = TREE_TYPE (arg1_type);
4382 else
4383 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4385 return
4386 convert (tree_type,
4387 ffecom_1 (REALPART_EXPR, arg1_type,
4388 ffecom_expr (arg1)));
4390 case FFEINTRIN_impIAND:
4391 case FFEINTRIN_impAND:
4392 return ffecom_2 (BIT_AND_EXPR, tree_type,
4393 convert (tree_type,
4394 ffecom_expr (arg1)),
4395 convert (tree_type,
4396 ffecom_expr (arg2)));
4398 case FFEINTRIN_impIOR:
4399 case FFEINTRIN_impOR:
4400 return ffecom_2 (BIT_IOR_EXPR, tree_type,
4401 convert (tree_type,
4402 ffecom_expr (arg1)),
4403 convert (tree_type,
4404 ffecom_expr (arg2)));
4406 case FFEINTRIN_impIEOR:
4407 case FFEINTRIN_impXOR:
4408 return ffecom_2 (BIT_XOR_EXPR, tree_type,
4409 convert (tree_type,
4410 ffecom_expr (arg1)),
4411 convert (tree_type,
4412 ffecom_expr (arg2)));
4414 case FFEINTRIN_impLSHIFT:
4415 return ffecom_2 (LSHIFT_EXPR, tree_type,
4416 ffecom_expr (arg1),
4417 convert (integer_type_node,
4418 ffecom_expr (arg2)));
4420 case FFEINTRIN_impRSHIFT:
4421 return ffecom_2 (RSHIFT_EXPR, tree_type,
4422 ffecom_expr (arg1),
4423 convert (integer_type_node,
4424 ffecom_expr (arg2)));
4426 case FFEINTRIN_impNOT:
4427 return ffecom_1 (BIT_NOT_EXPR, tree_type, ffecom_expr (arg1));
4429 case FFEINTRIN_impBIT_SIZE:
4430 return convert (tree_type, TYPE_SIZE (arg1_type));
4432 case FFEINTRIN_impBTEST:
4434 ffetargetLogical1 target_true;
4435 ffetargetLogical1 target_false;
4436 tree true_tree;
4437 tree false_tree;
4439 ffetarget_logical1 (&target_true, TRUE);
4440 ffetarget_logical1 (&target_false, FALSE);
4441 if (target_true == 1)
4442 true_tree = convert (tree_type, integer_one_node);
4443 else
4444 true_tree = convert (tree_type, build_int_2 (target_true, 0));
4445 if (target_false == 0)
4446 false_tree = convert (tree_type, integer_zero_node);
4447 else
4448 false_tree = convert (tree_type, build_int_2 (target_false, 0));
4450 return
4451 ffecom_3 (COND_EXPR, tree_type,
4452 ffecom_truth_value
4453 (ffecom_2 (EQ_EXPR, integer_type_node,
4454 ffecom_2 (BIT_AND_EXPR, arg1_type,
4455 ffecom_expr (arg1),
4456 ffecom_2 (LSHIFT_EXPR, arg1_type,
4457 convert (arg1_type,
4458 integer_one_node),
4459 convert (integer_type_node,
4460 ffecom_expr (arg2)))),
4461 convert (arg1_type,
4462 integer_zero_node))),
4463 false_tree,
4464 true_tree);
4467 case FFEINTRIN_impIBCLR:
4468 return
4469 ffecom_2 (BIT_AND_EXPR, tree_type,
4470 ffecom_expr (arg1),
4471 ffecom_1 (BIT_NOT_EXPR, tree_type,
4472 ffecom_2 (LSHIFT_EXPR, tree_type,
4473 convert (tree_type,
4474 integer_one_node),
4475 convert (integer_type_node,
4476 ffecom_expr (arg2)))));
4478 case FFEINTRIN_impIBITS:
4480 tree arg3_tree = ffecom_save_tree (convert (integer_type_node,
4481 ffecom_expr (arg3)));
4482 tree uns_type
4483 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4485 expr_tree
4486 = ffecom_2 (BIT_AND_EXPR, tree_type,
4487 ffecom_2 (RSHIFT_EXPR, tree_type,
4488 ffecom_expr (arg1),
4489 convert (integer_type_node,
4490 ffecom_expr (arg2))),
4491 convert (tree_type,
4492 ffecom_2 (RSHIFT_EXPR, uns_type,
4493 ffecom_1 (BIT_NOT_EXPR,
4494 uns_type,
4495 convert (uns_type,
4496 integer_zero_node)),
4497 ffecom_2 (MINUS_EXPR,
4498 integer_type_node,
4499 TYPE_SIZE (uns_type),
4500 arg3_tree))));
4501 /* Fix up, because the RSHIFT_EXPR above can't shift over TYPE_SIZE. */
4502 expr_tree
4503 = ffecom_3 (COND_EXPR, tree_type,
4504 ffecom_truth_value
4505 (ffecom_2 (NE_EXPR, integer_type_node,
4506 arg3_tree,
4507 integer_zero_node)),
4508 expr_tree,
4509 convert (tree_type, integer_zero_node));
4511 return expr_tree;
4513 case FFEINTRIN_impIBSET:
4514 return
4515 ffecom_2 (BIT_IOR_EXPR, tree_type,
4516 ffecom_expr (arg1),
4517 ffecom_2 (LSHIFT_EXPR, tree_type,
4518 convert (tree_type, integer_one_node),
4519 convert (integer_type_node,
4520 ffecom_expr (arg2))));
4522 case FFEINTRIN_impISHFT:
4524 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4525 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4526 ffecom_expr (arg2)));
4527 tree uns_type
4528 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4530 expr_tree
4531 = ffecom_3 (COND_EXPR, tree_type,
4532 ffecom_truth_value
4533 (ffecom_2 (GE_EXPR, integer_type_node,
4534 arg2_tree,
4535 integer_zero_node)),
4536 ffecom_2 (LSHIFT_EXPR, tree_type,
4537 arg1_tree,
4538 arg2_tree),
4539 convert (tree_type,
4540 ffecom_2 (RSHIFT_EXPR, uns_type,
4541 convert (uns_type, arg1_tree),
4542 ffecom_1 (NEGATE_EXPR,
4543 integer_type_node,
4544 arg2_tree))));
4545 /* Fix up, because {L|R}SHIFT_EXPR don't go over TYPE_SIZE bounds. */
4546 expr_tree
4547 = ffecom_3 (COND_EXPR, tree_type,
4548 ffecom_truth_value
4549 (ffecom_2 (NE_EXPR, integer_type_node,
4550 ffecom_1 (ABS_EXPR,
4551 integer_type_node,
4552 arg2_tree),
4553 TYPE_SIZE (uns_type))),
4554 expr_tree,
4555 convert (tree_type, integer_zero_node));
4556 /* Make sure SAVE_EXPRs get referenced early enough. */
4557 expr_tree
4558 = ffecom_2 (COMPOUND_EXPR, tree_type,
4559 convert (void_type_node, arg1_tree),
4560 ffecom_2 (COMPOUND_EXPR, tree_type,
4561 convert (void_type_node, arg2_tree),
4562 expr_tree));
4564 return expr_tree;
4566 case FFEINTRIN_impISHFTC:
4568 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4569 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4570 ffecom_expr (arg2)));
4571 tree arg3_tree = (arg3 == NULL) ? TYPE_SIZE (tree_type)
4572 : ffecom_save_tree (convert (integer_type_node, ffecom_expr (arg3)));
4573 tree shift_neg;
4574 tree shift_pos;
4575 tree mask_arg1;
4576 tree masked_arg1;
4577 tree uns_type
4578 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4580 mask_arg1
4581 = ffecom_2 (LSHIFT_EXPR, tree_type,
4582 ffecom_1 (BIT_NOT_EXPR, tree_type,
4583 convert (tree_type, integer_zero_node)),
4584 arg3_tree);
4585 /* Fix up, because LSHIFT_EXPR above can't shift over TYPE_SIZE. */
4586 mask_arg1
4587 = ffecom_3 (COND_EXPR, tree_type,
4588 ffecom_truth_value
4589 (ffecom_2 (NE_EXPR, integer_type_node,
4590 arg3_tree,
4591 TYPE_SIZE (uns_type))),
4592 mask_arg1,
4593 convert (tree_type, integer_zero_node));
4594 mask_arg1 = ffecom_save_tree (mask_arg1);
4595 masked_arg1
4596 = ffecom_2 (BIT_AND_EXPR, tree_type,
4597 arg1_tree,
4598 ffecom_1 (BIT_NOT_EXPR, tree_type,
4599 mask_arg1));
4600 masked_arg1 = ffecom_save_tree (masked_arg1);
4601 shift_neg
4602 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4603 convert (tree_type,
4604 ffecom_2 (RSHIFT_EXPR, uns_type,
4605 convert (uns_type, masked_arg1),
4606 ffecom_1 (NEGATE_EXPR,
4607 integer_type_node,
4608 arg2_tree))),
4609 ffecom_2 (LSHIFT_EXPR, tree_type,
4610 arg1_tree,
4611 ffecom_2 (PLUS_EXPR, integer_type_node,
4612 arg2_tree,
4613 arg3_tree)));
4614 shift_pos
4615 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4616 ffecom_2 (LSHIFT_EXPR, tree_type,
4617 arg1_tree,
4618 arg2_tree),
4619 convert (tree_type,
4620 ffecom_2 (RSHIFT_EXPR, uns_type,
4621 convert (uns_type, masked_arg1),
4622 ffecom_2 (MINUS_EXPR,
4623 integer_type_node,
4624 arg3_tree,
4625 arg2_tree))));
4626 expr_tree
4627 = ffecom_3 (COND_EXPR, tree_type,
4628 ffecom_truth_value
4629 (ffecom_2 (LT_EXPR, integer_type_node,
4630 arg2_tree,
4631 integer_zero_node)),
4632 shift_neg,
4633 shift_pos);
4634 expr_tree
4635 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4636 ffecom_2 (BIT_AND_EXPR, tree_type,
4637 mask_arg1,
4638 arg1_tree),
4639 ffecom_2 (BIT_AND_EXPR, tree_type,
4640 ffecom_1 (BIT_NOT_EXPR, tree_type,
4641 mask_arg1),
4642 expr_tree));
4643 expr_tree
4644 = ffecom_3 (COND_EXPR, tree_type,
4645 ffecom_truth_value
4646 (ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
4647 ffecom_2 (EQ_EXPR, integer_type_node,
4648 ffecom_1 (ABS_EXPR,
4649 integer_type_node,
4650 arg2_tree),
4651 arg3_tree),
4652 ffecom_2 (EQ_EXPR, integer_type_node,
4653 arg2_tree,
4654 integer_zero_node))),
4655 arg1_tree,
4656 expr_tree);
4657 /* Make sure SAVE_EXPRs get referenced early enough. */
4658 expr_tree
4659 = ffecom_2 (COMPOUND_EXPR, tree_type,
4660 convert (void_type_node, arg1_tree),
4661 ffecom_2 (COMPOUND_EXPR, tree_type,
4662 convert (void_type_node, arg2_tree),
4663 ffecom_2 (COMPOUND_EXPR, tree_type,
4664 convert (void_type_node,
4665 mask_arg1),
4666 ffecom_2 (COMPOUND_EXPR, tree_type,
4667 convert (void_type_node,
4668 masked_arg1),
4669 expr_tree))));
4670 expr_tree
4671 = ffecom_2 (COMPOUND_EXPR, tree_type,
4672 convert (void_type_node,
4673 arg3_tree),
4674 expr_tree);
4676 return expr_tree;
4678 case FFEINTRIN_impLOC:
4680 tree arg1_tree = ffecom_expr (arg1);
4682 expr_tree
4683 = convert (tree_type,
4684 ffecom_1 (ADDR_EXPR,
4685 build_pointer_type (TREE_TYPE (arg1_tree)),
4686 arg1_tree));
4688 return expr_tree;
4690 case FFEINTRIN_impMVBITS:
4692 tree arg1_tree;
4693 tree arg2_tree;
4694 tree arg3_tree;
4695 ffebld arg4 = ffebld_head (ffebld_trail (list));
4696 tree arg4_tree;
4697 tree arg4_type;
4698 ffebld arg5 = ffebld_head (ffebld_trail (ffebld_trail (list)));
4699 tree arg5_tree;
4700 tree prep_arg1;
4701 tree prep_arg4;
4702 tree arg5_plus_arg3;
4704 arg2_tree = convert (integer_type_node,
4705 ffecom_expr (arg2));
4706 arg3_tree = ffecom_save_tree (convert (integer_type_node,
4707 ffecom_expr (arg3)));
4708 arg4_tree = ffecom_expr_rw (NULL_TREE, arg4);
4709 arg4_type = TREE_TYPE (arg4_tree);
4711 arg1_tree = ffecom_save_tree (convert (arg4_type,
4712 ffecom_expr (arg1)));
4714 arg5_tree = ffecom_save_tree (convert (integer_type_node,
4715 ffecom_expr (arg5)));
4717 prep_arg1
4718 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4719 ffecom_2 (BIT_AND_EXPR, arg4_type,
4720 ffecom_2 (RSHIFT_EXPR, arg4_type,
4721 arg1_tree,
4722 arg2_tree),
4723 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4724 ffecom_2 (LSHIFT_EXPR, arg4_type,
4725 ffecom_1 (BIT_NOT_EXPR,
4726 arg4_type,
4727 convert
4728 (arg4_type,
4729 integer_zero_node)),
4730 arg3_tree))),
4731 arg5_tree);
4732 arg5_plus_arg3
4733 = ffecom_save_tree (ffecom_2 (PLUS_EXPR, arg4_type,
4734 arg5_tree,
4735 arg3_tree));
4736 prep_arg4
4737 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4738 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4739 convert (arg4_type,
4740 integer_zero_node)),
4741 arg5_plus_arg3);
4742 /* Fix up, because LSHIFT_EXPR above can't shift over TYPE_SIZE. */
4743 prep_arg4
4744 = ffecom_3 (COND_EXPR, arg4_type,
4745 ffecom_truth_value
4746 (ffecom_2 (NE_EXPR, integer_type_node,
4747 arg5_plus_arg3,
4748 convert (TREE_TYPE (arg5_plus_arg3),
4749 TYPE_SIZE (arg4_type)))),
4750 prep_arg4,
4751 convert (arg4_type, integer_zero_node));
4752 prep_arg4
4753 = ffecom_2 (BIT_AND_EXPR, arg4_type,
4754 arg4_tree,
4755 ffecom_2 (BIT_IOR_EXPR, arg4_type,
4756 prep_arg4,
4757 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4758 ffecom_2 (LSHIFT_EXPR, arg4_type,
4759 ffecom_1 (BIT_NOT_EXPR,
4760 arg4_type,
4761 convert
4762 (arg4_type,
4763 integer_zero_node)),
4764 arg5_tree))));
4765 prep_arg1
4766 = ffecom_2 (BIT_IOR_EXPR, arg4_type,
4767 prep_arg1,
4768 prep_arg4);
4769 /* Fix up (twice), because LSHIFT_EXPR above
4770 can't shift over TYPE_SIZE. */
4771 prep_arg1
4772 = ffecom_3 (COND_EXPR, arg4_type,
4773 ffecom_truth_value
4774 (ffecom_2 (NE_EXPR, integer_type_node,
4775 arg3_tree,
4776 convert (TREE_TYPE (arg3_tree),
4777 integer_zero_node))),
4778 prep_arg1,
4779 arg4_tree);
4780 prep_arg1
4781 = ffecom_3 (COND_EXPR, arg4_type,
4782 ffecom_truth_value
4783 (ffecom_2 (NE_EXPR, integer_type_node,
4784 arg3_tree,
4785 convert (TREE_TYPE (arg3_tree),
4786 TYPE_SIZE (arg4_type)))),
4787 prep_arg1,
4788 arg1_tree);
4789 expr_tree
4790 = ffecom_2s (MODIFY_EXPR, void_type_node,
4791 arg4_tree,
4792 prep_arg1);
4793 /* Make sure SAVE_EXPRs get referenced early enough. */
4794 expr_tree
4795 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4796 arg1_tree,
4797 ffecom_2 (COMPOUND_EXPR, void_type_node,
4798 arg3_tree,
4799 ffecom_2 (COMPOUND_EXPR, void_type_node,
4800 arg5_tree,
4801 ffecom_2 (COMPOUND_EXPR, void_type_node,
4802 arg5_plus_arg3,
4803 expr_tree))));
4804 expr_tree
4805 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4806 arg4_tree,
4807 expr_tree);
4810 return expr_tree;
4812 case FFEINTRIN_impDERF:
4813 case FFEINTRIN_impERF:
4814 case FFEINTRIN_impDERFC:
4815 case FFEINTRIN_impERFC:
4816 break;
4818 case FFEINTRIN_impIARGC:
4819 /* extern int xargc; i__1 = xargc - 1; */
4820 expr_tree = ffecom_2 (MINUS_EXPR, TREE_TYPE (ffecom_tree_xargc_),
4821 ffecom_tree_xargc_,
4822 convert (TREE_TYPE (ffecom_tree_xargc_),
4823 integer_one_node));
4824 return expr_tree;
4826 case FFEINTRIN_impSIGNAL_func:
4827 case FFEINTRIN_impSIGNAL_subr:
4829 tree arg1_tree;
4830 tree arg2_tree;
4831 tree arg3_tree;
4833 arg1_tree = convert (ffecom_f2c_integer_type_node,
4834 ffecom_expr (arg1));
4835 arg1_tree = ffecom_1 (ADDR_EXPR,
4836 build_pointer_type (TREE_TYPE (arg1_tree)),
4837 arg1_tree);
4839 /* Pass procedure as a pointer to it, anything else by value. */
4840 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4841 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4842 else
4843 arg2_tree = ffecom_ptr_to_expr (arg2);
4844 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4845 arg2_tree);
4847 if (arg3 != NULL)
4848 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
4849 else
4850 arg3_tree = NULL_TREE;
4852 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4853 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4854 TREE_CHAIN (arg1_tree) = arg2_tree;
4856 expr_tree
4857 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4858 ffecom_gfrt_kindtype (gfrt),
4859 FALSE,
4860 ((codegen_imp == FFEINTRIN_impSIGNAL_subr) ?
4861 NULL_TREE :
4862 tree_type),
4863 arg1_tree,
4864 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4865 ffebld_nonter_hook (expr));
4867 if (arg3_tree != NULL_TREE)
4868 expr_tree
4869 = ffecom_modify (NULL_TREE, arg3_tree,
4870 convert (TREE_TYPE (arg3_tree),
4871 expr_tree));
4873 return expr_tree;
4875 case FFEINTRIN_impALARM:
4877 tree arg1_tree;
4878 tree arg2_tree;
4879 tree arg3_tree;
4881 arg1_tree = convert (ffecom_f2c_integer_type_node,
4882 ffecom_expr (arg1));
4883 arg1_tree = ffecom_1 (ADDR_EXPR,
4884 build_pointer_type (TREE_TYPE (arg1_tree)),
4885 arg1_tree);
4887 /* Pass procedure as a pointer to it, anything else by value. */
4888 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4889 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4890 else
4891 arg2_tree = ffecom_ptr_to_expr (arg2);
4892 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4893 arg2_tree);
4895 if (arg3 != NULL)
4896 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
4897 else
4898 arg3_tree = NULL_TREE;
4900 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4901 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4902 TREE_CHAIN (arg1_tree) = arg2_tree;
4904 expr_tree
4905 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4906 ffecom_gfrt_kindtype (gfrt),
4907 FALSE,
4908 NULL_TREE,
4909 arg1_tree,
4910 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4911 ffebld_nonter_hook (expr));
4913 if (arg3_tree != NULL_TREE)
4914 expr_tree
4915 = ffecom_modify (NULL_TREE, arg3_tree,
4916 convert (TREE_TYPE (arg3_tree),
4917 expr_tree));
4919 return expr_tree;
4921 case FFEINTRIN_impCHDIR_subr:
4922 case FFEINTRIN_impFDATE_subr:
4923 case FFEINTRIN_impFGET_subr:
4924 case FFEINTRIN_impFPUT_subr:
4925 case FFEINTRIN_impGETCWD_subr:
4926 case FFEINTRIN_impHOSTNM_subr:
4927 case FFEINTRIN_impSYSTEM_subr:
4928 case FFEINTRIN_impUNLINK_subr:
4930 tree arg1_len = integer_zero_node;
4931 tree arg1_tree;
4932 tree arg2_tree;
4934 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
4936 if (arg2 != NULL)
4937 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
4938 else
4939 arg2_tree = NULL_TREE;
4941 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4942 arg1_len = build_tree_list (NULL_TREE, arg1_len);
4943 TREE_CHAIN (arg1_tree) = arg1_len;
4945 expr_tree
4946 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4947 ffecom_gfrt_kindtype (gfrt),
4948 FALSE,
4949 NULL_TREE,
4950 arg1_tree,
4951 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4952 ffebld_nonter_hook (expr));
4954 if (arg2_tree != NULL_TREE)
4955 expr_tree
4956 = ffecom_modify (NULL_TREE, arg2_tree,
4957 convert (TREE_TYPE (arg2_tree),
4958 expr_tree));
4960 return expr_tree;
4962 case FFEINTRIN_impEXIT:
4963 if (arg1 != NULL)
4964 break;
4966 expr_tree = build_tree_list (NULL_TREE,
4967 ffecom_1 (ADDR_EXPR,
4968 build_pointer_type
4969 (ffecom_integer_type_node),
4970 integer_zero_node));
4972 return
4973 ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4974 ffecom_gfrt_kindtype (gfrt),
4975 FALSE,
4976 void_type_node,
4977 expr_tree,
4978 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4979 ffebld_nonter_hook (expr));
4981 case FFEINTRIN_impFLUSH:
4982 if (arg1 == NULL)
4983 gfrt = FFECOM_gfrtFLUSH;
4984 else
4985 gfrt = FFECOM_gfrtFLUSH1;
4986 break;
4988 case FFEINTRIN_impCHMOD_subr:
4989 case FFEINTRIN_impLINK_subr:
4990 case FFEINTRIN_impRENAME_subr:
4991 case FFEINTRIN_impSYMLNK_subr:
4993 tree arg1_len = integer_zero_node;
4994 tree arg1_tree;
4995 tree arg2_len = integer_zero_node;
4996 tree arg2_tree;
4997 tree arg3_tree;
4999 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5000 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
5001 if (arg3 != NULL)
5002 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5003 else
5004 arg3_tree = NULL_TREE;
5006 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5007 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5008 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5009 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5010 TREE_CHAIN (arg1_tree) = arg2_tree;
5011 TREE_CHAIN (arg2_tree) = arg1_len;
5012 TREE_CHAIN (arg1_len) = arg2_len;
5013 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5014 ffecom_gfrt_kindtype (gfrt),
5015 FALSE,
5016 NULL_TREE,
5017 arg1_tree,
5018 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5019 ffebld_nonter_hook (expr));
5020 if (arg3_tree != NULL_TREE)
5021 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5022 convert (TREE_TYPE (arg3_tree),
5023 expr_tree));
5025 return expr_tree;
5027 case FFEINTRIN_impLSTAT_subr:
5028 case FFEINTRIN_impSTAT_subr:
5030 tree arg1_len = integer_zero_node;
5031 tree arg1_tree;
5032 tree arg2_tree;
5033 tree arg3_tree;
5035 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5037 arg2_tree = ffecom_ptr_to_expr (arg2);
5039 if (arg3 != NULL)
5040 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5041 else
5042 arg3_tree = NULL_TREE;
5044 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5045 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5046 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5047 TREE_CHAIN (arg1_tree) = arg2_tree;
5048 TREE_CHAIN (arg2_tree) = arg1_len;
5049 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5050 ffecom_gfrt_kindtype (gfrt),
5051 FALSE,
5052 NULL_TREE,
5053 arg1_tree,
5054 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5055 ffebld_nonter_hook (expr));
5056 if (arg3_tree != NULL_TREE)
5057 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5058 convert (TREE_TYPE (arg3_tree),
5059 expr_tree));
5061 return expr_tree;
5063 case FFEINTRIN_impFGETC_subr:
5064 case FFEINTRIN_impFPUTC_subr:
5066 tree arg1_tree;
5067 tree arg2_tree;
5068 tree arg2_len = integer_zero_node;
5069 tree arg3_tree;
5071 arg1_tree = convert (ffecom_f2c_integer_type_node,
5072 ffecom_expr (arg1));
5073 arg1_tree = ffecom_1 (ADDR_EXPR,
5074 build_pointer_type (TREE_TYPE (arg1_tree)),
5075 arg1_tree);
5077 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
5078 if (arg3 != NULL)
5079 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5080 else
5081 arg3_tree = NULL_TREE;
5083 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5084 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5085 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5086 TREE_CHAIN (arg1_tree) = arg2_tree;
5087 TREE_CHAIN (arg2_tree) = arg2_len;
5089 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5090 ffecom_gfrt_kindtype (gfrt),
5091 FALSE,
5092 NULL_TREE,
5093 arg1_tree,
5094 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5095 ffebld_nonter_hook (expr));
5096 if (arg3_tree != NULL_TREE)
5097 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5098 convert (TREE_TYPE (arg3_tree),
5099 expr_tree));
5101 return expr_tree;
5103 case FFEINTRIN_impFSTAT_subr:
5105 tree arg1_tree;
5106 tree arg2_tree;
5107 tree arg3_tree;
5109 arg1_tree = convert (ffecom_f2c_integer_type_node,
5110 ffecom_expr (arg1));
5111 arg1_tree = ffecom_1 (ADDR_EXPR,
5112 build_pointer_type (TREE_TYPE (arg1_tree)),
5113 arg1_tree);
5115 arg2_tree = convert (ffecom_f2c_ptr_to_integer_type_node,
5116 ffecom_ptr_to_expr (arg2));
5118 if (arg3 == NULL)
5119 arg3_tree = NULL_TREE;
5120 else
5121 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5123 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5124 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5125 TREE_CHAIN (arg1_tree) = arg2_tree;
5126 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5127 ffecom_gfrt_kindtype (gfrt),
5128 FALSE,
5129 NULL_TREE,
5130 arg1_tree,
5131 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5132 ffebld_nonter_hook (expr));
5133 if (arg3_tree != NULL_TREE) {
5134 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5135 convert (TREE_TYPE (arg3_tree),
5136 expr_tree));
5139 return expr_tree;
5141 case FFEINTRIN_impKILL_subr:
5143 tree arg1_tree;
5144 tree arg2_tree;
5145 tree arg3_tree;
5147 arg1_tree = convert (ffecom_f2c_integer_type_node,
5148 ffecom_expr (arg1));
5149 arg1_tree = ffecom_1 (ADDR_EXPR,
5150 build_pointer_type (TREE_TYPE (arg1_tree)),
5151 arg1_tree);
5153 arg2_tree = convert (ffecom_f2c_integer_type_node,
5154 ffecom_expr (arg2));
5155 arg2_tree = ffecom_1 (ADDR_EXPR,
5156 build_pointer_type (TREE_TYPE (arg2_tree)),
5157 arg2_tree);
5159 if (arg3 == NULL)
5160 arg3_tree = NULL_TREE;
5161 else
5162 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5164 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5165 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5166 TREE_CHAIN (arg1_tree) = arg2_tree;
5167 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5168 ffecom_gfrt_kindtype (gfrt),
5169 FALSE,
5170 NULL_TREE,
5171 arg1_tree,
5172 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5173 ffebld_nonter_hook (expr));
5174 if (arg3_tree != NULL_TREE) {
5175 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5176 convert (TREE_TYPE (arg3_tree),
5177 expr_tree));
5180 return expr_tree;
5182 case FFEINTRIN_impCTIME_subr:
5183 case FFEINTRIN_impTTYNAM_subr:
5185 tree arg1_len = integer_zero_node;
5186 tree arg1_tree;
5187 tree arg2_tree;
5189 arg1_tree = ffecom_arg_ptr_to_expr (arg2, &arg1_len);
5191 arg2_tree = convert (((codegen_imp == FFEINTRIN_impCTIME_subr) ?
5192 ffecom_f2c_longint_type_node :
5193 ffecom_f2c_integer_type_node),
5194 ffecom_expr (arg1));
5195 arg2_tree = ffecom_1 (ADDR_EXPR,
5196 build_pointer_type (TREE_TYPE (arg2_tree)),
5197 arg2_tree);
5199 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5200 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5201 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5202 TREE_CHAIN (arg1_len) = arg2_tree;
5203 TREE_CHAIN (arg1_tree) = arg1_len;
5205 expr_tree
5206 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5207 ffecom_gfrt_kindtype (gfrt),
5208 FALSE,
5209 NULL_TREE,
5210 arg1_tree,
5211 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5212 ffebld_nonter_hook (expr));
5213 TREE_SIDE_EFFECTS (expr_tree) = 1;
5215 return expr_tree;
5217 case FFEINTRIN_impIRAND:
5218 case FFEINTRIN_impRAND:
5219 /* Arg defaults to 0 (normal random case) */
5221 tree arg1_tree;
5223 if (arg1 == NULL)
5224 arg1_tree = ffecom_integer_zero_node;
5225 else
5226 arg1_tree = ffecom_expr (arg1);
5227 arg1_tree = convert (ffecom_f2c_integer_type_node,
5228 arg1_tree);
5229 arg1_tree = ffecom_1 (ADDR_EXPR,
5230 build_pointer_type (TREE_TYPE (arg1_tree)),
5231 arg1_tree);
5232 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5234 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5235 ffecom_gfrt_kindtype (gfrt),
5236 FALSE,
5237 ((codegen_imp == FFEINTRIN_impIRAND) ?
5238 ffecom_f2c_integer_type_node :
5239 ffecom_f2c_real_type_node),
5240 arg1_tree,
5241 dest_tree, dest, dest_used,
5242 NULL_TREE, TRUE,
5243 ffebld_nonter_hook (expr));
5245 return expr_tree;
5247 case FFEINTRIN_impFTELL_subr:
5248 case FFEINTRIN_impUMASK_subr:
5250 tree arg1_tree;
5251 tree arg2_tree;
5253 arg1_tree = convert (ffecom_f2c_integer_type_node,
5254 ffecom_expr (arg1));
5255 arg1_tree = ffecom_1 (ADDR_EXPR,
5256 build_pointer_type (TREE_TYPE (arg1_tree)),
5257 arg1_tree);
5259 if (arg2 == NULL)
5260 arg2_tree = NULL_TREE;
5261 else
5262 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
5264 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5265 ffecom_gfrt_kindtype (gfrt),
5266 FALSE,
5267 NULL_TREE,
5268 build_tree_list (NULL_TREE, arg1_tree),
5269 NULL_TREE, NULL, NULL, NULL_TREE,
5270 TRUE,
5271 ffebld_nonter_hook (expr));
5272 if (arg2_tree != NULL_TREE) {
5273 expr_tree = ffecom_modify (NULL_TREE, arg2_tree,
5274 convert (TREE_TYPE (arg2_tree),
5275 expr_tree));
5278 return expr_tree;
5280 case FFEINTRIN_impCPU_TIME:
5281 case FFEINTRIN_impSECOND_subr:
5283 tree arg1_tree;
5285 arg1_tree = ffecom_expr_w (NULL_TREE, arg1);
5287 expr_tree
5288 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5289 ffecom_gfrt_kindtype (gfrt),
5290 FALSE,
5291 NULL_TREE,
5292 NULL_TREE,
5293 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5294 ffebld_nonter_hook (expr));
5296 expr_tree
5297 = ffecom_modify (NULL_TREE, arg1_tree,
5298 convert (TREE_TYPE (arg1_tree),
5299 expr_tree));
5301 return expr_tree;
5303 case FFEINTRIN_impDTIME_subr:
5304 case FFEINTRIN_impETIME_subr:
5306 tree arg1_tree;
5307 tree result_tree;
5309 result_tree = ffecom_expr_w (NULL_TREE, arg2);
5311 arg1_tree = ffecom_ptr_to_expr (arg1);
5313 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5314 ffecom_gfrt_kindtype (gfrt),
5315 FALSE,
5316 NULL_TREE,
5317 build_tree_list (NULL_TREE, arg1_tree),
5318 NULL_TREE, NULL, NULL, NULL_TREE,
5319 TRUE,
5320 ffebld_nonter_hook (expr));
5321 expr_tree = ffecom_modify (NULL_TREE, result_tree,
5322 convert (TREE_TYPE (result_tree),
5323 expr_tree));
5325 return expr_tree;
5327 /* Straightforward calls of libf2c routines: */
5328 case FFEINTRIN_impABORT:
5329 case FFEINTRIN_impACCESS:
5330 case FFEINTRIN_impBESJ0:
5331 case FFEINTRIN_impBESJ1:
5332 case FFEINTRIN_impBESJN:
5333 case FFEINTRIN_impBESY0:
5334 case FFEINTRIN_impBESY1:
5335 case FFEINTRIN_impBESYN:
5336 case FFEINTRIN_impCHDIR_func:
5337 case FFEINTRIN_impCHMOD_func:
5338 case FFEINTRIN_impDATE:
5339 case FFEINTRIN_impDATE_AND_TIME:
5340 case FFEINTRIN_impDBESJ0:
5341 case FFEINTRIN_impDBESJ1:
5342 case FFEINTRIN_impDBESJN:
5343 case FFEINTRIN_impDBESY0:
5344 case FFEINTRIN_impDBESY1:
5345 case FFEINTRIN_impDBESYN:
5346 case FFEINTRIN_impDTIME_func:
5347 case FFEINTRIN_impETIME_func:
5348 case FFEINTRIN_impFGETC_func:
5349 case FFEINTRIN_impFGET_func:
5350 case FFEINTRIN_impFNUM:
5351 case FFEINTRIN_impFPUTC_func:
5352 case FFEINTRIN_impFPUT_func:
5353 case FFEINTRIN_impFSEEK:
5354 case FFEINTRIN_impFSTAT_func:
5355 case FFEINTRIN_impFTELL_func:
5356 case FFEINTRIN_impGERROR:
5357 case FFEINTRIN_impGETARG:
5358 case FFEINTRIN_impGETCWD_func:
5359 case FFEINTRIN_impGETENV:
5360 case FFEINTRIN_impGETGID:
5361 case FFEINTRIN_impGETLOG:
5362 case FFEINTRIN_impGETPID:
5363 case FFEINTRIN_impGETUID:
5364 case FFEINTRIN_impGMTIME:
5365 case FFEINTRIN_impHOSTNM_func:
5366 case FFEINTRIN_impIDATE_unix:
5367 case FFEINTRIN_impIDATE_vxt:
5368 case FFEINTRIN_impIERRNO:
5369 case FFEINTRIN_impISATTY:
5370 case FFEINTRIN_impITIME:
5371 case FFEINTRIN_impKILL_func:
5372 case FFEINTRIN_impLINK_func:
5373 case FFEINTRIN_impLNBLNK:
5374 case FFEINTRIN_impLSTAT_func:
5375 case FFEINTRIN_impLTIME:
5376 case FFEINTRIN_impMCLOCK8:
5377 case FFEINTRIN_impMCLOCK:
5378 case FFEINTRIN_impPERROR:
5379 case FFEINTRIN_impRENAME_func:
5380 case FFEINTRIN_impSECNDS:
5381 case FFEINTRIN_impSECOND_func:
5382 case FFEINTRIN_impSLEEP:
5383 case FFEINTRIN_impSRAND:
5384 case FFEINTRIN_impSTAT_func:
5385 case FFEINTRIN_impSYMLNK_func:
5386 case FFEINTRIN_impSYSTEM_CLOCK:
5387 case FFEINTRIN_impSYSTEM_func:
5388 case FFEINTRIN_impTIME8:
5389 case FFEINTRIN_impTIME_unix:
5390 case FFEINTRIN_impTIME_vxt:
5391 case FFEINTRIN_impUMASK_func:
5392 case FFEINTRIN_impUNLINK_func:
5393 break;
5395 case FFEINTRIN_impCTIME_func: /* CHARACTER functions not handled here. */
5396 case FFEINTRIN_impFDATE_func: /* CHARACTER functions not handled here. */
5397 case FFEINTRIN_impTTYNAM_func: /* CHARACTER functions not handled here. */
5398 case FFEINTRIN_impNONE:
5399 case FFEINTRIN_imp: /* Hush up gcc warning. */
5400 fprintf (stderr, "No %s implementation.\n",
5401 ffeintrin_name_implementation (ffebld_symter_implementation (ffebld_left (expr))));
5402 assert ("unimplemented intrinsic" == NULL);
5403 return error_mark_node;
5406 assert (gfrt != FFECOM_gfrt); /* Must have an implementation! */
5408 expr_tree = ffecom_arglist_expr_ (ffecom_gfrt_args_ (gfrt),
5409 ffebld_right (expr));
5411 return ffecom_call_ (ffecom_gfrt_tree_ (gfrt), ffecom_gfrt_kindtype (gfrt),
5412 (ffe_is_f2c_library () && ffecom_gfrt_complex_[gfrt]),
5413 tree_type,
5414 expr_tree, dest_tree, dest, dest_used,
5415 NULL_TREE, TRUE,
5416 ffebld_nonter_hook (expr));
5418 /* See bottom of this file for f2c transforms used to determine
5419 many of the above implementations. The info seems to confuse
5420 Emacs's C mode indentation, which is why it's been moved to
5421 the bottom of this source file. */
5424 /* For power (exponentiation) where right-hand operand is type INTEGER,
5425 generate in-line code to do it the fast way (which, if the operand
5426 is a constant, might just mean a series of multiplies). */
5428 static tree
5429 ffecom_expr_power_integer_ (ffebld expr)
5431 tree l = ffecom_expr (ffebld_left (expr));
5432 tree r = ffecom_expr (ffebld_right (expr));
5433 tree ltype = TREE_TYPE (l);
5434 tree rtype = TREE_TYPE (r);
5435 tree result = NULL_TREE;
5437 if (l == error_mark_node
5438 || r == error_mark_node)
5439 return error_mark_node;
5441 if (TREE_CODE (r) == INTEGER_CST)
5443 int sgn = tree_int_cst_sgn (r);
5445 if (sgn == 0)
5446 return convert (ltype, integer_one_node);
5448 if ((TREE_CODE (ltype) == INTEGER_TYPE)
5449 && (sgn < 0))
5451 /* Reciprocal of integer is either 0, -1, or 1, so after
5452 calculating that (which we leave to the back end to do
5453 or not do optimally), don't bother with any multiplying. */
5455 result = ffecom_tree_divide_ (ltype,
5456 convert (ltype, integer_one_node),
5458 NULL_TREE, NULL, NULL, NULL_TREE);
5459 r = ffecom_1 (NEGATE_EXPR,
5460 rtype,
5462 if ((TREE_INT_CST_LOW (r) & 1) == 0)
5463 result = ffecom_1 (ABS_EXPR, rtype,
5464 result);
5467 /* Generate appropriate series of multiplies, preceded
5468 by divide if the exponent is negative. */
5470 l = save_expr (l);
5472 if (sgn < 0)
5474 l = ffecom_tree_divide_ (ltype,
5475 convert (ltype, integer_one_node),
5477 NULL_TREE, NULL, NULL,
5478 ffebld_nonter_hook (expr));
5479 r = ffecom_1 (NEGATE_EXPR, rtype, r);
5480 assert (TREE_CODE (r) == INTEGER_CST);
5482 if (tree_int_cst_sgn (r) < 0)
5483 { /* The "most negative" number. */
5484 r = ffecom_1 (NEGATE_EXPR, rtype,
5485 ffecom_2 (RSHIFT_EXPR, rtype,
5487 integer_one_node));
5488 l = save_expr (l);
5489 l = ffecom_2 (MULT_EXPR, ltype,
5495 for (;;)
5497 if (TREE_INT_CST_LOW (r) & 1)
5499 if (result == NULL_TREE)
5500 result = l;
5501 else
5502 result = ffecom_2 (MULT_EXPR, ltype,
5503 result,
5507 r = ffecom_2 (RSHIFT_EXPR, rtype,
5509 integer_one_node);
5510 if (integer_zerop (r))
5511 break;
5512 assert (TREE_CODE (r) == INTEGER_CST);
5514 l = save_expr (l);
5515 l = ffecom_2 (MULT_EXPR, ltype,
5519 return result;
5522 /* Though rhs isn't a constant, in-line code cannot be expanded
5523 while transforming dummies
5524 because the back end cannot be easily convinced to generate
5525 stores (MODIFY_EXPR), handle temporaries, and so on before
5526 all the appropriate rtx's have been generated for things like
5527 dummy args referenced in rhs -- which doesn't happen until
5528 store_parm_decls() is called (expand_function_start, I believe,
5529 does the actual rtx-stuffing of PARM_DECLs).
5531 So, in this case, let the caller generate the call to the
5532 run-time-library function to evaluate the power for us. */
5534 if (ffecom_transform_only_dummies_)
5535 return NULL_TREE;
5537 /* Right-hand operand not a constant, expand in-line code to figure
5538 out how to do the multiplies, &c.
5540 The returned expression is expressed this way in GNU C, where l and
5541 r are the "inputs":
5543 ({ typeof (r) rtmp = r;
5544 typeof (l) ltmp = l;
5545 typeof (l) result;
5547 if (rtmp == 0)
5548 result = 1;
5549 else
5551 if ((basetypeof (l) == basetypeof (int))
5552 && (rtmp < 0))
5554 result = ((typeof (l)) 1) / ltmp;
5555 if ((ltmp < 0) && (((-rtmp) & 1) == 0))
5556 result = -result;
5558 else
5560 result = 1;
5561 if ((basetypeof (l) != basetypeof (int))
5562 && (rtmp < 0))
5564 ltmp = ((typeof (l)) 1) / ltmp;
5565 rtmp = -rtmp;
5566 if (rtmp < 0)
5568 rtmp = -(rtmp >> 1);
5569 ltmp *= ltmp;
5572 for (;;)
5574 if (rtmp & 1)
5575 result *= ltmp;
5576 if ((rtmp >>= 1) == 0)
5577 break;
5578 ltmp *= ltmp;
5582 result;
5585 Note that some of the above is compile-time collapsable, such as
5586 the first part of the if statements that checks the base type of
5587 l against int. The if statements are phrased that way to suggest
5588 an easy way to generate the if/else constructs here, knowing that
5589 the back end should (and probably does) eliminate the resulting
5590 dead code (either the int case or the non-int case), something
5591 it couldn't do without the redundant phrasing, requiring explicit
5592 dead-code elimination here, which would be kind of difficult to
5593 read. */
5596 tree rtmp;
5597 tree ltmp;
5598 tree divide;
5599 tree basetypeof_l_is_int;
5600 tree se;
5601 tree t;
5603 basetypeof_l_is_int
5604 = build_int_2 ((TREE_CODE (ltype) == INTEGER_TYPE), 0);
5606 se = expand_start_stmt_expr (/*has_scope=*/1);
5608 ffecom_start_compstmt ();
5610 #ifndef HAHA
5611 rtmp = ffecom_make_tempvar ("power_r", rtype,
5612 FFETARGET_charactersizeNONE, -1);
5613 ltmp = ffecom_make_tempvar ("power_l", ltype,
5614 FFETARGET_charactersizeNONE, -1);
5615 result = ffecom_make_tempvar ("power_res", ltype,
5616 FFETARGET_charactersizeNONE, -1);
5617 if (TREE_CODE (ltype) == COMPLEX_TYPE
5618 || TREE_CODE (ltype) == RECORD_TYPE)
5619 divide = ffecom_make_tempvar ("power_div", ltype,
5620 FFETARGET_charactersizeNONE, -1);
5621 else
5622 divide = NULL_TREE;
5623 #else /* HAHA */
5625 tree hook;
5627 hook = ffebld_nonter_hook (expr);
5628 assert (hook);
5629 assert (TREE_CODE (hook) == TREE_VEC);
5630 assert (TREE_VEC_LENGTH (hook) == 4);
5631 rtmp = TREE_VEC_ELT (hook, 0);
5632 ltmp = TREE_VEC_ELT (hook, 1);
5633 result = TREE_VEC_ELT (hook, 2);
5634 divide = TREE_VEC_ELT (hook, 3);
5635 if (TREE_CODE (ltype) == COMPLEX_TYPE
5636 || TREE_CODE (ltype) == RECORD_TYPE)
5637 assert (divide);
5638 else
5639 assert (! divide);
5641 #endif /* HAHA */
5643 expand_expr_stmt (ffecom_modify (void_type_node,
5644 rtmp,
5645 r));
5646 expand_expr_stmt (ffecom_modify (void_type_node,
5647 ltmp,
5648 l));
5649 expand_start_cond (ffecom_truth_value
5650 (ffecom_2 (EQ_EXPR, integer_type_node,
5651 rtmp,
5652 convert (rtype, integer_zero_node))),
5654 expand_expr_stmt (ffecom_modify (void_type_node,
5655 result,
5656 convert (ltype, integer_one_node)));
5657 expand_start_else ();
5658 if (! integer_zerop (basetypeof_l_is_int))
5660 expand_start_cond (ffecom_2 (LT_EXPR, integer_type_node,
5661 rtmp,
5662 convert (rtype,
5663 integer_zero_node)),
5665 expand_expr_stmt (ffecom_modify (void_type_node,
5666 result,
5667 ffecom_tree_divide_
5668 (ltype,
5669 convert (ltype, integer_one_node),
5670 ltmp,
5671 NULL_TREE, NULL, NULL,
5672 divide)));
5673 expand_start_cond (ffecom_truth_value
5674 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5675 ffecom_2 (LT_EXPR, integer_type_node,
5676 ltmp,
5677 convert (ltype,
5678 integer_zero_node)),
5679 ffecom_2 (EQ_EXPR, integer_type_node,
5680 ffecom_2 (BIT_AND_EXPR,
5681 rtype,
5682 ffecom_1 (NEGATE_EXPR,
5683 rtype,
5684 rtmp),
5685 convert (rtype,
5686 integer_one_node)),
5687 convert (rtype,
5688 integer_zero_node)))),
5690 expand_expr_stmt (ffecom_modify (void_type_node,
5691 result,
5692 ffecom_1 (NEGATE_EXPR,
5693 ltype,
5694 result)));
5695 expand_end_cond ();
5696 expand_start_else ();
5698 expand_expr_stmt (ffecom_modify (void_type_node,
5699 result,
5700 convert (ltype, integer_one_node)));
5701 expand_start_cond (ffecom_truth_value
5702 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5703 ffecom_truth_value_invert
5704 (basetypeof_l_is_int),
5705 ffecom_2 (LT_EXPR, integer_type_node,
5706 rtmp,
5707 convert (rtype,
5708 integer_zero_node)))),
5710 expand_expr_stmt (ffecom_modify (void_type_node,
5711 ltmp,
5712 ffecom_tree_divide_
5713 (ltype,
5714 convert (ltype, integer_one_node),
5715 ltmp,
5716 NULL_TREE, NULL, NULL,
5717 divide)));
5718 expand_expr_stmt (ffecom_modify (void_type_node,
5719 rtmp,
5720 ffecom_1 (NEGATE_EXPR, rtype,
5721 rtmp)));
5722 expand_start_cond (ffecom_truth_value
5723 (ffecom_2 (LT_EXPR, integer_type_node,
5724 rtmp,
5725 convert (rtype, integer_zero_node))),
5727 expand_expr_stmt (ffecom_modify (void_type_node,
5728 rtmp,
5729 ffecom_1 (NEGATE_EXPR, rtype,
5730 ffecom_2 (RSHIFT_EXPR,
5731 rtype,
5732 rtmp,
5733 integer_one_node))));
5734 expand_expr_stmt (ffecom_modify (void_type_node,
5735 ltmp,
5736 ffecom_2 (MULT_EXPR, ltype,
5737 ltmp,
5738 ltmp)));
5739 expand_end_cond ();
5740 expand_end_cond ();
5741 expand_start_loop (1);
5742 expand_start_cond (ffecom_truth_value
5743 (ffecom_2 (BIT_AND_EXPR, rtype,
5744 rtmp,
5745 convert (rtype, integer_one_node))),
5747 expand_expr_stmt (ffecom_modify (void_type_node,
5748 result,
5749 ffecom_2 (MULT_EXPR, ltype,
5750 result,
5751 ltmp)));
5752 expand_end_cond ();
5753 expand_exit_loop_if_false (NULL,
5754 ffecom_truth_value
5755 (ffecom_modify (rtype,
5756 rtmp,
5757 ffecom_2 (RSHIFT_EXPR,
5758 rtype,
5759 rtmp,
5760 integer_one_node))));
5761 expand_expr_stmt (ffecom_modify (void_type_node,
5762 ltmp,
5763 ffecom_2 (MULT_EXPR, ltype,
5764 ltmp,
5765 ltmp)));
5766 expand_end_loop ();
5767 expand_end_cond ();
5768 if (!integer_zerop (basetypeof_l_is_int))
5769 expand_end_cond ();
5770 expand_expr_stmt (result);
5772 t = ffecom_end_compstmt ();
5774 result = expand_end_stmt_expr (se);
5776 /* This code comes from c-parse.in, after its expand_end_stmt_expr. */
5778 if (TREE_CODE (t) == BLOCK)
5780 /* Make a BIND_EXPR for the BLOCK already made. */
5781 result = build (BIND_EXPR, TREE_TYPE (result),
5782 NULL_TREE, result, t);
5783 /* Remove the block from the tree at this point.
5784 It gets put back at the proper place
5785 when the BIND_EXPR is expanded. */
5786 delete_block (t);
5788 else
5789 result = t;
5792 return result;
5795 /* ffecom_expr_transform_ -- Transform symbols in expr
5797 ffebld expr; // FFE expression.
5798 ffecom_expr_transform_ (expr);
5800 Recursive descent on expr while transforming any untransformed SYMTERs. */
5802 static void
5803 ffecom_expr_transform_ (ffebld expr)
5805 tree t;
5806 ffesymbol s;
5808 tail_recurse:
5810 if (expr == NULL)
5811 return;
5813 switch (ffebld_op (expr))
5815 case FFEBLD_opSYMTER:
5816 s = ffebld_symter (expr);
5817 t = ffesymbol_hook (s).decl_tree;
5818 if ((t == NULL_TREE)
5819 && ((ffesymbol_kind (s) != FFEINFO_kindNONE)
5820 || ((ffesymbol_where (s) != FFEINFO_whereNONE)
5821 && (ffesymbol_where (s) != FFEINFO_whereINTRINSIC))))
5823 s = ffecom_sym_transform_ (s);
5824 t = ffesymbol_hook (s).decl_tree; /* Sfunc expr non-dummy,
5825 DIMENSION expr? */
5827 break; /* Ok if (t == NULL) here. */
5829 case FFEBLD_opITEM:
5830 ffecom_expr_transform_ (ffebld_head (expr));
5831 expr = ffebld_trail (expr);
5832 goto tail_recurse; /* :::::::::::::::::::: */
5834 default:
5835 break;
5838 switch (ffebld_arity (expr))
5840 case 2:
5841 ffecom_expr_transform_ (ffebld_left (expr));
5842 expr = ffebld_right (expr);
5843 goto tail_recurse; /* :::::::::::::::::::: */
5845 case 1:
5846 expr = ffebld_left (expr);
5847 goto tail_recurse; /* :::::::::::::::::::: */
5849 default:
5850 break;
5853 return;
5856 /* Make a type based on info in live f2c.h file. */
5858 static void
5859 ffecom_f2c_make_type_ (tree *type, int tcode, const char *name)
5861 switch (tcode)
5863 case FFECOM_f2ccodeCHAR:
5864 *type = make_signed_type (CHAR_TYPE_SIZE);
5865 break;
5867 case FFECOM_f2ccodeSHORT:
5868 *type = make_signed_type (SHORT_TYPE_SIZE);
5869 break;
5871 case FFECOM_f2ccodeINT:
5872 *type = make_signed_type (INT_TYPE_SIZE);
5873 break;
5875 case FFECOM_f2ccodeLONG:
5876 *type = make_signed_type (LONG_TYPE_SIZE);
5877 break;
5879 case FFECOM_f2ccodeLONGLONG:
5880 *type = make_signed_type (LONG_LONG_TYPE_SIZE);
5881 break;
5883 case FFECOM_f2ccodeCHARPTR:
5884 *type = build_pointer_type (DEFAULT_SIGNED_CHAR
5885 ? signed_char_type_node
5886 : unsigned_char_type_node);
5887 break;
5889 case FFECOM_f2ccodeFLOAT:
5890 *type = make_node (REAL_TYPE);
5891 TYPE_PRECISION (*type) = FLOAT_TYPE_SIZE;
5892 layout_type (*type);
5893 break;
5895 case FFECOM_f2ccodeDOUBLE:
5896 *type = make_node (REAL_TYPE);
5897 TYPE_PRECISION (*type) = DOUBLE_TYPE_SIZE;
5898 layout_type (*type);
5899 break;
5901 case FFECOM_f2ccodeLONGDOUBLE:
5902 *type = make_node (REAL_TYPE);
5903 TYPE_PRECISION (*type) = LONG_DOUBLE_TYPE_SIZE;
5904 layout_type (*type);
5905 break;
5907 case FFECOM_f2ccodeTWOREALS:
5908 *type = ffecom_make_complex_type_ (ffecom_f2c_real_type_node);
5909 break;
5911 case FFECOM_f2ccodeTWODOUBLEREALS:
5912 *type = ffecom_make_complex_type_ (ffecom_f2c_doublereal_type_node);
5913 break;
5915 default:
5916 assert ("unexpected FFECOM_f2ccodeXYZZY!" == NULL);
5917 *type = error_mark_node;
5918 return;
5921 pushdecl (build_decl (TYPE_DECL,
5922 ffecom_get_invented_identifier ("__g77_f2c_%s", name),
5923 *type));
5926 /* Set the f2c list-directed-I/O code for whatever (integral) type has the
5927 given size. */
5929 static void
5930 ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
5931 int code)
5933 int j;
5934 tree t;
5936 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
5937 if ((t = ffecom_tree_type[bt][j]) != NULL_TREE
5938 && compare_tree_int (TYPE_SIZE (t), size) == 0)
5940 assert (code != -1);
5941 ffecom_f2c_typecode_[bt][j] = code;
5942 code = -1;
5946 /* Finish up globals after doing all program units in file
5948 Need to handle only uninitialized COMMON areas. */
5950 static ffeglobal
5951 ffecom_finish_global_ (ffeglobal global)
5953 tree cbtype;
5954 tree cbt;
5955 tree size;
5957 if (ffeglobal_type (global) != FFEGLOBAL_typeCOMMON)
5958 return global;
5960 if (ffeglobal_common_init (global))
5961 return global;
5963 cbt = ffeglobal_hook (global);
5964 if ((cbt == NULL_TREE)
5965 || !ffeglobal_common_have_size (global))
5966 return global; /* No need to make common, never ref'd. */
5968 DECL_EXTERNAL (cbt) = 0;
5970 /* Give the array a size now. */
5972 size = build_int_2 ((ffeglobal_common_size (global)
5973 + ffeglobal_common_pad (global)) - 1,
5976 cbtype = TREE_TYPE (cbt);
5977 TYPE_DOMAIN (cbtype) = build_range_type (integer_type_node,
5978 integer_zero_node,
5979 size);
5980 if (!TREE_TYPE (size))
5981 TREE_TYPE (size) = TYPE_DOMAIN (cbtype);
5982 layout_type (cbtype);
5984 cbt = start_decl (cbt, FALSE);
5985 assert (cbt == ffeglobal_hook (global));
5987 finish_decl (cbt, NULL_TREE, FALSE);
5989 return global;
5992 /* Finish up any untransformed symbols. */
5994 static ffesymbol
5995 ffecom_finish_symbol_transform_ (ffesymbol s)
5997 if ((s == NULL) || (TREE_CODE (current_function_decl) == ERROR_MARK))
5998 return s;
6000 /* It's easy to know to transform an untransformed symbol, to make sure
6001 we put out debugging info for it. But COMMON variables, unlike
6002 EQUIVALENCE ones, aren't given declarations in addition to the
6003 tree expressions that specify offsets, because COMMON variables
6004 can be referenced in the outer scope where only dummy arguments
6005 (PARM_DECLs) should really be seen. To be safe, just don't do any
6006 VAR_DECLs for COMMON variables when we transform them for real
6007 use, and therefore we do all the VAR_DECL creating here. */
6009 if (ffesymbol_hook (s).decl_tree == NULL_TREE)
6011 if (ffesymbol_kind (s) != FFEINFO_kindNONE
6012 || (ffesymbol_where (s) != FFEINFO_whereNONE
6013 && ffesymbol_where (s) != FFEINFO_whereINTRINSIC
6014 && ffesymbol_where (s) != FFEINFO_whereDUMMY))
6015 /* Not transformed, and not CHARACTER*(*), and not a dummy
6016 argument, which can happen only if the entry point names
6017 it "rides in on" are all invalidated for other reasons. */
6018 s = ffecom_sym_transform_ (s);
6021 if ((ffesymbol_where (s) == FFEINFO_whereCOMMON)
6022 && (ffesymbol_hook (s).decl_tree != error_mark_node))
6024 /* This isn't working, at least for dbxout. The .s file looks
6025 okay to me (burley), but in gdb 4.9 at least, the variables
6026 appear to reside somewhere outside of the common area, so
6027 it doesn't make sense to mislead anyone by generating the info
6028 on those variables until this is fixed. NOTE: Same problem
6029 with EQUIVALENCE, sadly...see similar #if later. */
6030 ffecom_member_phase2_ (ffesymbol_storage (ffesymbol_common (s)),
6031 ffesymbol_storage (s));
6034 return s;
6037 /* Append underscore(s) to name before calling get_identifier. "us"
6038 is nonzero if the name already contains an underscore and thus
6039 needs two underscores appended. */
6041 static tree
6042 ffecom_get_appended_identifier_ (char us, const char *name)
6044 int i;
6045 char *newname;
6046 tree id;
6048 newname = xmalloc ((i = strlen (name)) + 1
6049 + ffe_is_underscoring ()
6050 + us);
6051 memcpy (newname, name, i);
6052 newname[i] = '_';
6053 newname[i + us] = '_';
6054 newname[i + 1 + us] = '\0';
6055 id = get_identifier (newname);
6057 free (newname);
6059 return id;
6062 /* Decide whether to append underscore to name before calling
6063 get_identifier. */
6065 static tree
6066 ffecom_get_external_identifier_ (ffesymbol s)
6068 char us;
6069 const char *name = ffesymbol_text (s);
6071 /* If name is a built-in name, just return it as is. */
6073 if (!ffe_is_underscoring ()
6074 || (strcmp (name, FFETARGET_nameBLANK_COMMON) == 0)
6075 #if FFETARGET_isENFORCED_MAIN_NAME
6076 || (strcmp (name, FFETARGET_nameENFORCED_NAME) == 0)
6077 #else
6078 || (strcmp (name, FFETARGET_nameUNNAMED_MAIN) == 0)
6079 #endif
6080 || (strcmp (name, FFETARGET_nameUNNAMED_BLOCK_DATA) == 0))
6081 return get_identifier (name);
6083 us = ffe_is_second_underscore ()
6084 ? (strchr (name, '_') != NULL)
6085 : 0;
6087 return ffecom_get_appended_identifier_ (us, name);
6090 /* Decide whether to append underscore to internal name before calling
6091 get_identifier.
6093 This is for non-external, top-function-context names only. Transform
6094 identifier so it doesn't conflict with the transformed result
6095 of using a _different_ external name. E.g. if "CALL FOO" is
6096 transformed into "FOO_();", then the variable in "FOO_ = 3"
6097 must be transformed into something that does not conflict, since
6098 these two things should be independent.
6100 The transformation is as follows. If the name does not contain
6101 an underscore, there is no possible conflict, so just return.
6102 If the name does contain an underscore, then transform it just
6103 like we transform an external identifier. */
6105 static tree
6106 ffecom_get_identifier_ (const char *name)
6108 /* If name does not contain an underscore, just return it as is. */
6110 if (!ffe_is_underscoring ()
6111 || (strchr (name, '_') == NULL))
6112 return get_identifier (name);
6114 return ffecom_get_appended_identifier_ (ffe_is_second_underscore (),
6115 name);
6118 /* ffecom_gen_sfuncdef_ -- Generate definition of statement function
6120 tree t;
6121 ffesymbol s; // kindFUNCTION, whereIMMEDIATE.
6122 t = ffecom_gen_sfuncdef_(s,ffesymbol_basictype(s),
6123 ffesymbol_kindtype(s));
6125 Call after setting up containing function and getting trees for all
6126 other symbols. */
6128 static tree
6129 ffecom_gen_sfuncdef_ (ffesymbol s, ffeinfoBasictype bt, ffeinfoKindtype kt)
6131 ffebld expr = ffesymbol_sfexpr (s);
6132 tree type;
6133 tree func;
6134 tree result;
6135 bool charfunc = (bt == FFEINFO_basictypeCHARACTER);
6136 static bool recurse = FALSE;
6137 int old_lineno = lineno;
6138 const char *old_input_filename = input_filename;
6140 ffecom_nested_entry_ = s;
6142 /* For now, we don't have a handy pointer to where the sfunc is actually
6143 defined, though that should be easy to add to an ffesymbol. (The
6144 token/where info available might well point to the place where the type
6145 of the sfunc is declared, especially if that precedes the place where
6146 the sfunc itself is defined, which is typically the case.) We should
6147 put out a null pointer rather than point somewhere wrong, but I want to
6148 see how it works at this point. */
6150 input_filename = ffesymbol_where_filename (s);
6151 lineno = ffesymbol_where_filelinenum (s);
6153 /* Pretransform the expression so any newly discovered things belong to the
6154 outer program unit, not to the statement function. */
6156 ffecom_expr_transform_ (expr);
6158 /* Make sure no recursive invocation of this fn (a specific case of failing
6159 to pretransform an sfunc's expression, i.e. where its expression
6160 references another untransformed sfunc) happens. */
6162 assert (!recurse);
6163 recurse = TRUE;
6165 push_f_function_context ();
6167 if (charfunc)
6168 type = void_type_node;
6169 else
6171 type = ffecom_tree_type[bt][kt];
6172 if (type == NULL_TREE)
6173 type = integer_type_node; /* _sym_exec_transition reports
6174 error. */
6177 start_function (ffecom_get_identifier_ (ffesymbol_text (s)),
6178 build_function_type (type, NULL_TREE),
6179 1, /* nested/inline */
6180 0); /* TREE_PUBLIC */
6182 /* We don't worry about COMPLEX return values here, because this is
6183 entirely internal to our code, and gcc has the ability to return COMPLEX
6184 directly as a value. */
6186 if (charfunc)
6187 { /* Prepend arg for where result goes. */
6188 tree type;
6190 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
6192 result = ffecom_get_invented_identifier ("__g77_%s", "result");
6194 ffecom_char_enhance_arg_ (&type, s); /* Ignore returned length. */
6196 type = build_pointer_type (type);
6197 result = build_decl (PARM_DECL, result, type);
6199 push_parm_decl (result);
6201 else
6202 result = NULL_TREE; /* Not ref'd if !charfunc. */
6204 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (s), TRUE);
6206 store_parm_decls (0);
6208 ffecom_start_compstmt ();
6210 if (expr != NULL)
6212 if (charfunc)
6214 ffetargetCharacterSize sz = ffesymbol_size (s);
6215 tree result_length;
6217 result_length = build_int_2 (sz, 0);
6218 TREE_TYPE (result_length) = ffecom_f2c_ftnlen_type_node;
6220 ffecom_prepare_let_char_ (sz, expr);
6222 ffecom_prepare_end ();
6224 ffecom_let_char_ (result, result_length, sz, expr);
6225 expand_null_return ();
6227 else
6229 ffecom_prepare_expr (expr);
6231 ffecom_prepare_end ();
6233 expand_return (ffecom_modify (NULL_TREE,
6234 DECL_RESULT (current_function_decl),
6235 ffecom_expr (expr)));
6239 ffecom_end_compstmt ();
6241 func = current_function_decl;
6242 finish_function (1);
6244 pop_f_function_context ();
6246 recurse = FALSE;
6248 lineno = old_lineno;
6249 input_filename = old_input_filename;
6251 ffecom_nested_entry_ = NULL;
6253 return func;
6256 static const char *
6257 ffecom_gfrt_args_ (ffecomGfrt ix)
6259 return ffecom_gfrt_argstring_[ix];
6262 static tree
6263 ffecom_gfrt_tree_ (ffecomGfrt ix)
6265 if (ffecom_gfrt_[ix] == NULL_TREE)
6266 ffecom_make_gfrt_ (ix);
6268 return ffecom_1 (ADDR_EXPR,
6269 build_pointer_type (TREE_TYPE (ffecom_gfrt_[ix])),
6270 ffecom_gfrt_[ix]);
6273 /* Return initialize-to-zero expression for this VAR_DECL. */
6275 /* A somewhat evil way to prevent the garbage collector
6276 from collecting 'tree' structures. */
6277 #define NUM_TRACKED_CHUNK 63
6278 static struct tree_ggc_tracker
6280 struct tree_ggc_tracker *next;
6281 tree trees[NUM_TRACKED_CHUNK];
6282 } *tracker_head = NULL;
6284 static void
6285 mark_tracker_head (void *arg)
6287 struct tree_ggc_tracker *head;
6288 int i;
6290 for (head = * (struct tree_ggc_tracker **) arg;
6291 head != NULL;
6292 head = head->next)
6294 ggc_mark (head);
6295 for (i = 0; i < NUM_TRACKED_CHUNK; i++)
6296 ggc_mark_tree (head->trees[i]);
6300 void
6301 ffecom_save_tree_forever (tree t)
6303 int i;
6304 if (tracker_head != NULL)
6305 for (i = 0; i < NUM_TRACKED_CHUNK; i++)
6306 if (tracker_head->trees[i] == NULL)
6308 tracker_head->trees[i] = t;
6309 return;
6313 /* Need to allocate a new block. */
6314 struct tree_ggc_tracker *old_head = tracker_head;
6316 tracker_head = ggc_alloc (sizeof (*tracker_head));
6317 tracker_head->next = old_head;
6318 tracker_head->trees[0] = t;
6319 for (i = 1; i < NUM_TRACKED_CHUNK; i++)
6320 tracker_head->trees[i] = NULL;
6324 static tree
6325 ffecom_init_zero_ (tree decl)
6327 tree init;
6328 int incremental = TREE_STATIC (decl);
6329 tree type = TREE_TYPE (decl);
6331 if (incremental)
6333 make_decl_rtl (decl, NULL);
6334 assemble_variable (decl, TREE_PUBLIC (decl) ? 1 : 0, 0, 1);
6337 if ((TREE_CODE (type) != ARRAY_TYPE)
6338 && (TREE_CODE (type) != RECORD_TYPE)
6339 && (TREE_CODE (type) != UNION_TYPE)
6340 && !incremental)
6341 init = convert (type, integer_zero_node);
6342 else if (!incremental)
6344 init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
6345 TREE_CONSTANT (init) = 1;
6346 TREE_STATIC (init) = 1;
6348 else
6350 assemble_zeros (int_size_in_bytes (type));
6351 init = error_mark_node;
6354 return init;
6357 static tree
6358 ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
6359 tree *maybe_tree)
6361 tree expr_tree;
6362 tree length_tree;
6364 switch (ffebld_op (arg))
6366 case FFEBLD_opCONTER: /* For F90, check 0-length. */
6367 if (ffetarget_length_character1
6368 (ffebld_constant_character1
6369 (ffebld_conter (arg))) == 0)
6371 *maybe_tree = integer_zero_node;
6372 return convert (tree_type, integer_zero_node);
6375 *maybe_tree = integer_one_node;
6376 expr_tree = build_int_2 (*ffetarget_text_character1
6377 (ffebld_constant_character1
6378 (ffebld_conter (arg))),
6380 TREE_TYPE (expr_tree) = tree_type;
6381 return expr_tree;
6383 case FFEBLD_opSYMTER:
6384 case FFEBLD_opARRAYREF:
6385 case FFEBLD_opFUNCREF:
6386 case FFEBLD_opSUBSTR:
6387 ffecom_char_args_ (&expr_tree, &length_tree, arg);
6389 if ((expr_tree == error_mark_node)
6390 || (length_tree == error_mark_node))
6392 *maybe_tree = error_mark_node;
6393 return error_mark_node;
6396 if (integer_zerop (length_tree))
6398 *maybe_tree = integer_zero_node;
6399 return convert (tree_type, integer_zero_node);
6402 expr_tree
6403 = ffecom_1 (INDIRECT_REF,
6404 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6405 expr_tree);
6406 expr_tree
6407 = ffecom_2 (ARRAY_REF,
6408 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6409 expr_tree,
6410 integer_one_node);
6411 expr_tree = convert (tree_type, expr_tree);
6413 if (TREE_CODE (length_tree) == INTEGER_CST)
6414 *maybe_tree = integer_one_node;
6415 else /* Must check length at run time. */
6416 *maybe_tree
6417 = ffecom_truth_value
6418 (ffecom_2 (GT_EXPR, integer_type_node,
6419 length_tree,
6420 ffecom_f2c_ftnlen_zero_node));
6421 return expr_tree;
6423 case FFEBLD_opPAREN:
6424 case FFEBLD_opCONVERT:
6425 if (ffeinfo_size (ffebld_info (arg)) == 0)
6427 *maybe_tree = integer_zero_node;
6428 return convert (tree_type, integer_zero_node);
6430 return ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6431 maybe_tree);
6433 case FFEBLD_opCONCATENATE:
6435 tree maybe_left;
6436 tree maybe_right;
6437 tree expr_left;
6438 tree expr_right;
6440 expr_left = ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6441 &maybe_left);
6442 expr_right = ffecom_intrinsic_ichar_ (tree_type, ffebld_right (arg),
6443 &maybe_right);
6444 *maybe_tree = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
6445 maybe_left,
6446 maybe_right);
6447 expr_tree = ffecom_3 (COND_EXPR, tree_type,
6448 maybe_left,
6449 expr_left,
6450 expr_right);
6451 return expr_tree;
6454 default:
6455 assert ("bad op in ICHAR" == NULL);
6456 return error_mark_node;
6460 /* ffecom_intrinsic_len_ -- Return length info for char arg (LEN())
6462 tree length_arg;
6463 ffebld expr;
6464 length_arg = ffecom_intrinsic_len_ (expr);
6466 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
6467 subexpressions by constructing the appropriate tree for the
6468 length-of-character-text argument in a calling sequence. */
6470 static tree
6471 ffecom_intrinsic_len_ (ffebld expr)
6473 ffetargetCharacter1 val;
6474 tree length;
6476 switch (ffebld_op (expr))
6478 case FFEBLD_opCONTER:
6479 val = ffebld_constant_character1 (ffebld_conter (expr));
6480 length = build_int_2 (ffetarget_length_character1 (val), 0);
6481 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6482 break;
6484 case FFEBLD_opSYMTER:
6486 ffesymbol s = ffebld_symter (expr);
6487 tree item;
6489 item = ffesymbol_hook (s).decl_tree;
6490 if (item == NULL_TREE)
6492 s = ffecom_sym_transform_ (s);
6493 item = ffesymbol_hook (s).decl_tree;
6495 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
6497 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
6498 length = ffesymbol_hook (s).length_tree;
6499 else
6501 length = build_int_2 (ffesymbol_size (s), 0);
6502 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6505 else if (item == error_mark_node)
6506 length = error_mark_node;
6507 else /* FFEINFO_kindFUNCTION: */
6508 length = NULL_TREE;
6510 break;
6512 case FFEBLD_opARRAYREF:
6513 length = ffecom_intrinsic_len_ (ffebld_left (expr));
6514 break;
6516 case FFEBLD_opSUBSTR:
6518 ffebld start;
6519 ffebld end;
6520 ffebld thing = ffebld_right (expr);
6521 tree start_tree;
6522 tree end_tree;
6524 assert (ffebld_op (thing) == FFEBLD_opITEM);
6525 start = ffebld_head (thing);
6526 thing = ffebld_trail (thing);
6527 assert (ffebld_trail (thing) == NULL);
6528 end = ffebld_head (thing);
6530 length = ffecom_intrinsic_len_ (ffebld_left (expr));
6532 if (length == error_mark_node)
6533 break;
6535 if (start == NULL)
6537 if (end == NULL)
6539 else
6541 length = convert (ffecom_f2c_ftnlen_type_node,
6542 ffecom_expr (end));
6545 else
6547 start_tree = convert (ffecom_f2c_ftnlen_type_node,
6548 ffecom_expr (start));
6550 if (start_tree == error_mark_node)
6552 length = error_mark_node;
6553 break;
6556 if (end == NULL)
6558 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6559 ffecom_f2c_ftnlen_one_node,
6560 ffecom_2 (MINUS_EXPR,
6561 ffecom_f2c_ftnlen_type_node,
6562 length,
6563 start_tree));
6565 else
6567 end_tree = convert (ffecom_f2c_ftnlen_type_node,
6568 ffecom_expr (end));
6570 if (end_tree == error_mark_node)
6572 length = error_mark_node;
6573 break;
6576 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6577 ffecom_f2c_ftnlen_one_node,
6578 ffecom_2 (MINUS_EXPR,
6579 ffecom_f2c_ftnlen_type_node,
6580 end_tree, start_tree));
6584 break;
6586 case FFEBLD_opCONCATENATE:
6587 length
6588 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6589 ffecom_intrinsic_len_ (ffebld_left (expr)),
6590 ffecom_intrinsic_len_ (ffebld_right (expr)));
6591 break;
6593 case FFEBLD_opFUNCREF:
6594 case FFEBLD_opCONVERT:
6595 length = build_int_2 (ffebld_size (expr), 0);
6596 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6597 break;
6599 default:
6600 assert ("bad op for single char arg expr" == NULL);
6601 length = ffecom_f2c_ftnlen_zero_node;
6602 break;
6605 assert (length != NULL_TREE);
6607 return length;
6610 /* Handle CHARACTER assignments.
6612 Generates code to do the assignment. Used by ordinary assignment
6613 statement handler ffecom_let_stmt and by statement-function
6614 handler to generate code for a statement function. */
6616 static void
6617 ffecom_let_char_ (tree dest_tree, tree dest_length,
6618 ffetargetCharacterSize dest_size, ffebld source)
6620 ffecomConcatList_ catlist;
6621 tree source_length;
6622 tree source_tree;
6623 tree expr_tree;
6625 if ((dest_tree == error_mark_node)
6626 || (dest_length == error_mark_node))
6627 return;
6629 assert (dest_tree != NULL_TREE);
6630 assert (dest_length != NULL_TREE);
6632 /* Source might be an opCONVERT, which just means it is a different size
6633 than the destination. Since the underlying implementation here handles
6634 that (directly or via the s_copy or s_cat run-time-library functions),
6635 we don't need the "convenience" of an opCONVERT that tells us to
6636 truncate or blank-pad, particularly since the resulting implementation
6637 would probably be slower than otherwise. */
6639 while (ffebld_op (source) == FFEBLD_opCONVERT)
6640 source = ffebld_left (source);
6642 catlist = ffecom_concat_list_new_ (source, dest_size);
6643 switch (ffecom_concat_list_count_ (catlist))
6645 case 0: /* Shouldn't happen, but in case it does... */
6646 ffecom_concat_list_kill_ (catlist);
6647 source_tree = null_pointer_node;
6648 source_length = ffecom_f2c_ftnlen_zero_node;
6649 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6650 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6651 TREE_CHAIN (TREE_CHAIN (expr_tree))
6652 = build_tree_list (NULL_TREE, dest_length);
6653 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6654 = build_tree_list (NULL_TREE, source_length);
6656 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6657 TREE_SIDE_EFFECTS (expr_tree) = 1;
6659 expand_expr_stmt (expr_tree);
6661 return;
6663 case 1: /* The (fairly) easy case. */
6664 ffecom_char_args_ (&source_tree, &source_length,
6665 ffecom_concat_list_expr_ (catlist, 0));
6666 ffecom_concat_list_kill_ (catlist);
6667 assert (source_tree != NULL_TREE);
6668 assert (source_length != NULL_TREE);
6670 if ((source_tree == error_mark_node)
6671 || (source_length == error_mark_node))
6672 return;
6674 if (dest_size == 1)
6676 dest_tree
6677 = ffecom_1 (INDIRECT_REF,
6678 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6679 (dest_tree))),
6680 dest_tree);
6681 dest_tree
6682 = ffecom_2 (ARRAY_REF,
6683 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6684 (dest_tree))),
6685 dest_tree,
6686 integer_one_node);
6687 source_tree
6688 = ffecom_1 (INDIRECT_REF,
6689 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6690 (source_tree))),
6691 source_tree);
6692 source_tree
6693 = ffecom_2 (ARRAY_REF,
6694 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6695 (source_tree))),
6696 source_tree,
6697 integer_one_node);
6699 expr_tree = ffecom_modify (void_type_node, dest_tree, source_tree);
6701 expand_expr_stmt (expr_tree);
6703 return;
6706 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6707 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6708 TREE_CHAIN (TREE_CHAIN (expr_tree))
6709 = build_tree_list (NULL_TREE, dest_length);
6710 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6711 = build_tree_list (NULL_TREE, source_length);
6713 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6714 TREE_SIDE_EFFECTS (expr_tree) = 1;
6716 expand_expr_stmt (expr_tree);
6718 return;
6720 default: /* Must actually concatenate things. */
6721 break;
6724 /* Heavy-duty concatenation. */
6727 int count = ffecom_concat_list_count_ (catlist);
6728 int i;
6729 tree lengths;
6730 tree items;
6731 tree length_array;
6732 tree item_array;
6733 tree citem;
6734 tree clength;
6736 #ifdef HOHO
6737 length_array
6738 = lengths
6739 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
6740 FFETARGET_charactersizeNONE, count, TRUE);
6741 item_array = items = ffecom_push_tempvar (ffecom_f2c_address_type_node,
6742 FFETARGET_charactersizeNONE,
6743 count, TRUE);
6744 #else
6746 tree hook;
6748 hook = ffebld_nonter_hook (source);
6749 assert (hook);
6750 assert (TREE_CODE (hook) == TREE_VEC);
6751 assert (TREE_VEC_LENGTH (hook) == 2);
6752 length_array = lengths = TREE_VEC_ELT (hook, 0);
6753 item_array = items = TREE_VEC_ELT (hook, 1);
6755 #endif
6757 for (i = 0; i < count; ++i)
6759 ffecom_char_args_ (&citem, &clength,
6760 ffecom_concat_list_expr_ (catlist, i));
6761 if ((citem == error_mark_node)
6762 || (clength == error_mark_node))
6764 ffecom_concat_list_kill_ (catlist);
6765 return;
6768 items
6769 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
6770 ffecom_modify (void_type_node,
6771 ffecom_2 (ARRAY_REF,
6772 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
6773 item_array,
6774 build_int_2 (i, 0)),
6775 citem),
6776 items);
6777 lengths
6778 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
6779 ffecom_modify (void_type_node,
6780 ffecom_2 (ARRAY_REF,
6781 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
6782 length_array,
6783 build_int_2 (i, 0)),
6784 clength),
6785 lengths);
6788 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6789 TREE_CHAIN (expr_tree)
6790 = build_tree_list (NULL_TREE,
6791 ffecom_1 (ADDR_EXPR,
6792 build_pointer_type (TREE_TYPE (items)),
6793 items));
6794 TREE_CHAIN (TREE_CHAIN (expr_tree))
6795 = build_tree_list (NULL_TREE,
6796 ffecom_1 (ADDR_EXPR,
6797 build_pointer_type (TREE_TYPE (lengths)),
6798 lengths));
6799 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6800 = build_tree_list
6801 (NULL_TREE,
6802 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
6803 convert (ffecom_f2c_ftnlen_type_node,
6804 build_int_2 (count, 0))));
6805 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree))))
6806 = build_tree_list (NULL_TREE, dest_length);
6808 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCAT, expr_tree, NULL_TREE);
6809 TREE_SIDE_EFFECTS (expr_tree) = 1;
6811 expand_expr_stmt (expr_tree);
6814 ffecom_concat_list_kill_ (catlist);
6817 /* ffecom_make_gfrt_ -- Make initial info for run-time routine
6819 ffecomGfrt ix;
6820 ffecom_make_gfrt_(ix);
6822 Assumes gfrt_[ix] is NULL_TREE, and replaces it with the FUNCTION_DECL
6823 for the indicated run-time routine (ix). */
6825 static void
6826 ffecom_make_gfrt_ (ffecomGfrt ix)
6828 tree t;
6829 tree ttype;
6831 switch (ffecom_gfrt_type_[ix])
6833 case FFECOM_rttypeVOID_:
6834 ttype = void_type_node;
6835 break;
6837 case FFECOM_rttypeVOIDSTAR_:
6838 ttype = TREE_TYPE (null_pointer_node); /* `void *'. */
6839 break;
6841 case FFECOM_rttypeFTNINT_:
6842 ttype = ffecom_f2c_ftnint_type_node;
6843 break;
6845 case FFECOM_rttypeINTEGER_:
6846 ttype = ffecom_f2c_integer_type_node;
6847 break;
6849 case FFECOM_rttypeLONGINT_:
6850 ttype = ffecom_f2c_longint_type_node;
6851 break;
6853 case FFECOM_rttypeLOGICAL_:
6854 ttype = ffecom_f2c_logical_type_node;
6855 break;
6857 case FFECOM_rttypeREAL_F2C_:
6858 ttype = double_type_node;
6859 break;
6861 case FFECOM_rttypeREAL_GNU_:
6862 ttype = float_type_node;
6863 break;
6865 case FFECOM_rttypeCOMPLEX_F2C_:
6866 ttype = void_type_node;
6867 break;
6869 case FFECOM_rttypeCOMPLEX_GNU_:
6870 ttype = ffecom_f2c_complex_type_node;
6871 break;
6873 case FFECOM_rttypeDOUBLE_:
6874 ttype = double_type_node;
6875 break;
6877 case FFECOM_rttypeDOUBLEREAL_:
6878 ttype = ffecom_f2c_doublereal_type_node;
6879 break;
6881 case FFECOM_rttypeDBLCMPLX_F2C_:
6882 ttype = void_type_node;
6883 break;
6885 case FFECOM_rttypeDBLCMPLX_GNU_:
6886 ttype = ffecom_f2c_doublecomplex_type_node;
6887 break;
6889 case FFECOM_rttypeCHARACTER_:
6890 ttype = void_type_node;
6891 break;
6893 default:
6894 ttype = NULL;
6895 assert ("bad rttype" == NULL);
6896 break;
6899 ttype = build_function_type (ttype, NULL_TREE);
6900 t = build_decl (FUNCTION_DECL,
6901 get_identifier (ffecom_gfrt_name_[ix]),
6902 ttype);
6903 DECL_EXTERNAL (t) = 1;
6904 TREE_READONLY (t) = ffecom_gfrt_const_[ix] ? 1 : 0;
6905 TREE_PUBLIC (t) = 1;
6906 TREE_THIS_VOLATILE (t) = ffecom_gfrt_volatile_[ix] ? 1 : 0;
6908 /* Sanity check: A function that's const cannot be volatile. */
6910 assert (ffecom_gfrt_const_[ix] ? !ffecom_gfrt_volatile_[ix] : 1);
6912 /* Sanity check: A function that's const cannot return complex. */
6914 assert (ffecom_gfrt_const_[ix] ? !ffecom_gfrt_complex_[ix] : 1);
6916 t = start_decl (t, TRUE);
6918 finish_decl (t, NULL_TREE, TRUE);
6920 ffecom_gfrt_[ix] = t;
6923 /* Phase 1 pass over each member of a COMMON/EQUIVALENCE group. */
6925 static void
6926 ffecom_member_phase1_ (ffestorag mst UNUSED, ffestorag st)
6928 ffesymbol s = ffestorag_symbol (st);
6930 if (ffesymbol_namelisted (s))
6931 ffecom_member_namelisted_ = TRUE;
6934 /* Phase 2 pass over each member of a COMMON/EQUIVALENCE group. Declare
6935 the member so debugger will see it. Otherwise nobody should be
6936 referencing the member. */
6938 static void
6939 ffecom_member_phase2_ (ffestorag mst, ffestorag st)
6941 ffesymbol s;
6942 tree t;
6943 tree mt;
6944 tree type;
6946 if ((mst == NULL)
6947 || ((mt = ffestorag_hook (mst)) == NULL)
6948 || (mt == error_mark_node))
6949 return;
6951 if ((st == NULL)
6952 || ((s = ffestorag_symbol (st)) == NULL))
6953 return;
6955 type = ffecom_type_localvar_ (s,
6956 ffesymbol_basictype (s),
6957 ffesymbol_kindtype (s));
6958 if (type == error_mark_node)
6959 return;
6961 t = build_decl (VAR_DECL,
6962 ffecom_get_identifier_ (ffesymbol_text (s)),
6963 type);
6965 TREE_STATIC (t) = TREE_STATIC (mt);
6966 DECL_INITIAL (t) = NULL_TREE;
6967 TREE_ASM_WRITTEN (t) = 1;
6968 TREE_USED (t) = 1;
6970 SET_DECL_RTL (t,
6971 gen_rtx (MEM, TYPE_MODE (type),
6972 plus_constant (XEXP (DECL_RTL (mt), 0),
6973 ffestorag_modulo (mst)
6974 + ffestorag_offset (st)
6975 - ffestorag_offset (mst))));
6977 t = start_decl (t, FALSE);
6979 finish_decl (t, NULL_TREE, FALSE);
6982 /* Prepare source expression for assignment into a destination perhaps known
6983 to be of a specific size. */
6985 static void
6986 ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size, ffebld source)
6988 ffecomConcatList_ catlist;
6989 int count;
6990 int i;
6991 tree ltmp;
6992 tree itmp;
6993 tree tempvar = NULL_TREE;
6995 while (ffebld_op (source) == FFEBLD_opCONVERT)
6996 source = ffebld_left (source);
6998 catlist = ffecom_concat_list_new_ (source, dest_size);
6999 count = ffecom_concat_list_count_ (catlist);
7001 if (count >= 2)
7003 ltmp
7004 = ffecom_make_tempvar ("let_char_len", ffecom_f2c_ftnlen_type_node,
7005 FFETARGET_charactersizeNONE, count);
7006 itmp
7007 = ffecom_make_tempvar ("let_char_item", ffecom_f2c_address_type_node,
7008 FFETARGET_charactersizeNONE, count);
7010 tempvar = make_tree_vec (2);
7011 TREE_VEC_ELT (tempvar, 0) = ltmp;
7012 TREE_VEC_ELT (tempvar, 1) = itmp;
7015 for (i = 0; i < count; ++i)
7016 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist, i));
7018 ffecom_concat_list_kill_ (catlist);
7020 if (tempvar)
7022 ffebld_nonter_set_hook (source, tempvar);
7023 current_binding_level->prep_state = 1;
7027 /* ffecom_push_dummy_decls_ -- Transform dummy args, push parm decls in order
7029 Ignores STAR (alternate-return) dummies. All other get exec-transitioned
7030 (which generates their trees) and then their trees get push_parm_decl'd.
7032 The second arg is TRUE if the dummies are for a statement function, in
7033 which case lengths are not pushed for character arguments (since they are
7034 always known by both the caller and the callee, though the code allows
7035 for someday permitting CHAR*(*) stmtfunc dummies). */
7037 static void
7038 ffecom_push_dummy_decls_ (ffebld dummy_list, bool stmtfunc)
7040 ffebld dummy;
7041 ffebld dumlist;
7042 ffesymbol s;
7043 tree parm;
7045 ffecom_transform_only_dummies_ = TRUE;
7047 /* First push the parms corresponding to actual dummy "contents". */
7049 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7051 dummy = ffebld_head (dumlist);
7052 switch (ffebld_op (dummy))
7054 case FFEBLD_opSTAR:
7055 case FFEBLD_opANY:
7056 continue; /* Forget alternate returns. */
7058 default:
7059 break;
7061 assert (ffebld_op (dummy) == FFEBLD_opSYMTER);
7062 s = ffebld_symter (dummy);
7063 parm = ffesymbol_hook (s).decl_tree;
7064 if (parm == NULL_TREE)
7066 s = ffecom_sym_transform_ (s);
7067 parm = ffesymbol_hook (s).decl_tree;
7068 assert (parm != NULL_TREE);
7070 if (parm != error_mark_node)
7071 push_parm_decl (parm);
7074 /* Then, for CHARACTER dummies, push the parms giving their lengths. */
7076 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7078 dummy = ffebld_head (dumlist);
7079 switch (ffebld_op (dummy))
7081 case FFEBLD_opSTAR:
7082 case FFEBLD_opANY:
7083 continue; /* Forget alternate returns, they mean
7084 NOTHING! */
7086 default:
7087 break;
7089 s = ffebld_symter (dummy);
7090 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
7091 continue; /* Only looking for CHARACTER arguments. */
7092 if (stmtfunc && (ffesymbol_size (s) != FFETARGET_charactersizeNONE))
7093 continue; /* Stmtfunc arg with known size needs no
7094 length param. */
7095 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
7096 continue; /* Only looking for variables and arrays. */
7097 parm = ffesymbol_hook (s).length_tree;
7098 assert (parm != NULL_TREE);
7099 if (parm != error_mark_node)
7100 push_parm_decl (parm);
7103 ffecom_transform_only_dummies_ = FALSE;
7106 /* ffecom_start_progunit_ -- Beginning of program unit
7108 Does GNU back end stuff necessary to teach it about the start of its
7109 equivalent of a Fortran program unit. */
7111 static void
7112 ffecom_start_progunit_ ()
7114 ffesymbol fn = ffecom_primary_entry_;
7115 ffebld arglist;
7116 tree id; /* Identifier (name) of function. */
7117 tree type; /* Type of function. */
7118 tree result; /* Result of function. */
7119 ffeinfoBasictype bt;
7120 ffeinfoKindtype kt;
7121 ffeglobal g;
7122 ffeglobalType gt;
7123 ffeglobalType egt = FFEGLOBAL_type;
7124 bool charfunc;
7125 bool cmplxfunc;
7126 bool altentries = (ffecom_num_entrypoints_ != 0);
7127 bool multi
7128 = altentries
7129 && (ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
7130 && (ffecom_master_bt_ == FFEINFO_basictypeNONE);
7131 bool main_program = FALSE;
7132 int old_lineno = lineno;
7133 const char *old_input_filename = input_filename;
7135 assert (fn != NULL);
7136 assert (ffesymbol_hook (fn).decl_tree == NULL_TREE);
7138 input_filename = ffesymbol_where_filename (fn);
7139 lineno = ffesymbol_where_filelinenum (fn);
7141 switch (ffecom_primary_entry_kind_)
7143 case FFEINFO_kindPROGRAM:
7144 main_program = TRUE;
7145 gt = FFEGLOBAL_typeMAIN;
7146 bt = FFEINFO_basictypeNONE;
7147 kt = FFEINFO_kindtypeNONE;
7148 type = ffecom_tree_fun_type_void;
7149 charfunc = FALSE;
7150 cmplxfunc = FALSE;
7151 break;
7153 case FFEINFO_kindBLOCKDATA:
7154 gt = FFEGLOBAL_typeBDATA;
7155 bt = FFEINFO_basictypeNONE;
7156 kt = FFEINFO_kindtypeNONE;
7157 type = ffecom_tree_fun_type_void;
7158 charfunc = FALSE;
7159 cmplxfunc = FALSE;
7160 break;
7162 case FFEINFO_kindFUNCTION:
7163 gt = FFEGLOBAL_typeFUNC;
7164 egt = FFEGLOBAL_typeEXT;
7165 bt = ffesymbol_basictype (fn);
7166 kt = ffesymbol_kindtype (fn);
7167 if (bt == FFEINFO_basictypeNONE)
7169 ffeimplic_establish_symbol (fn);
7170 if (ffesymbol_funcresult (fn) != NULL)
7171 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
7172 bt = ffesymbol_basictype (fn);
7173 kt = ffesymbol_kindtype (fn);
7176 if (multi)
7177 charfunc = cmplxfunc = FALSE;
7178 else if (bt == FFEINFO_basictypeCHARACTER)
7179 charfunc = TRUE, cmplxfunc = FALSE;
7180 else if ((bt == FFEINFO_basictypeCOMPLEX)
7181 && ffesymbol_is_f2c (fn)
7182 && !altentries)
7183 charfunc = FALSE, cmplxfunc = TRUE;
7184 else
7185 charfunc = cmplxfunc = FALSE;
7187 if (multi || charfunc)
7188 type = ffecom_tree_fun_type_void;
7189 else if (ffesymbol_is_f2c (fn) && !altentries)
7190 type = ffecom_tree_fun_type[bt][kt];
7191 else
7192 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
7194 if ((type == NULL_TREE)
7195 || (TREE_TYPE (type) == NULL_TREE))
7196 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
7197 break;
7199 case FFEINFO_kindSUBROUTINE:
7200 gt = FFEGLOBAL_typeSUBR;
7201 egt = FFEGLOBAL_typeEXT;
7202 bt = FFEINFO_basictypeNONE;
7203 kt = FFEINFO_kindtypeNONE;
7204 if (ffecom_is_altreturning_)
7205 type = ffecom_tree_subr_type;
7206 else
7207 type = ffecom_tree_fun_type_void;
7208 charfunc = FALSE;
7209 cmplxfunc = FALSE;
7210 break;
7212 default:
7213 assert ("say what??" == NULL);
7214 /* Fall through. */
7215 case FFEINFO_kindANY:
7216 gt = FFEGLOBAL_typeANY;
7217 bt = FFEINFO_basictypeNONE;
7218 kt = FFEINFO_kindtypeNONE;
7219 type = error_mark_node;
7220 charfunc = FALSE;
7221 cmplxfunc = FALSE;
7222 break;
7225 if (altentries)
7227 id = ffecom_get_invented_identifier ("__g77_masterfun_%s",
7228 ffesymbol_text (fn));
7230 #if FFETARGET_isENFORCED_MAIN
7231 else if (main_program)
7232 id = get_identifier (FFETARGET_nameENFORCED_MAIN_NAME);
7233 #endif
7234 else
7235 id = ffecom_get_external_identifier_ (fn);
7237 start_function (id,
7238 type,
7239 0, /* nested/inline */
7240 !altentries); /* TREE_PUBLIC */
7242 TREE_USED (current_function_decl) = 1; /* Avoid spurious warning if altentries. */
7244 if (!altentries
7245 && ((g = ffesymbol_global (fn)) != NULL)
7246 && ((ffeglobal_type (g) == gt)
7247 || (ffeglobal_type (g) == egt)))
7249 ffeglobal_set_hook (g, current_function_decl);
7252 /* Arg handling needs exec-transitioned ffesymbols to work with. But
7253 exec-transitioning needs current_function_decl to be filled in. So we
7254 do these things in two phases. */
7256 if (altentries)
7257 { /* 1st arg identifies which entrypoint. */
7258 ffecom_which_entrypoint_decl_
7259 = build_decl (PARM_DECL,
7260 ffecom_get_invented_identifier ("__g77_%s",
7261 "which_entrypoint"),
7262 integer_type_node);
7263 push_parm_decl (ffecom_which_entrypoint_decl_);
7266 if (charfunc
7267 || cmplxfunc
7268 || multi)
7269 { /* Arg for result (return value). */
7270 tree type;
7271 tree length;
7273 if (charfunc)
7274 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
7275 else if (cmplxfunc)
7276 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
7277 else
7278 type = ffecom_multi_type_node_;
7280 result = ffecom_get_invented_identifier ("__g77_%s", "result");
7282 /* Make length arg _and_ enhance type info for CHAR arg itself. */
7284 if (charfunc)
7285 length = ffecom_char_enhance_arg_ (&type, fn);
7286 else
7287 length = NULL_TREE; /* Not ref'd if !charfunc. */
7289 type = build_pointer_type (type);
7290 result = build_decl (PARM_DECL, result, type);
7292 push_parm_decl (result);
7293 if (multi)
7294 ffecom_multi_retval_ = result;
7295 else
7296 ffecom_func_result_ = result;
7298 if (charfunc)
7300 push_parm_decl (length);
7301 ffecom_func_length_ = length;
7305 if (ffecom_primary_entry_is_proc_)
7307 if (altentries)
7308 arglist = ffecom_master_arglist_;
7309 else
7310 arglist = ffesymbol_dummyargs (fn);
7311 ffecom_push_dummy_decls_ (arglist, FALSE);
7314 if (TREE_CODE (current_function_decl) != ERROR_MARK)
7315 store_parm_decls (main_program ? 1 : 0);
7317 ffecom_start_compstmt ();
7318 /* Disallow temp vars at this level. */
7319 current_binding_level->prep_state = 2;
7321 lineno = old_lineno;
7322 input_filename = old_input_filename;
7324 /* This handles any symbols still untransformed, in case -g specified.
7325 This used to be done in ffecom_finish_progunit, but it turns out to
7326 be necessary to do it here so that statement functions are
7327 expanded before code. But don't bother for BLOCK DATA. */
7329 if (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
7330 ffesymbol_drive (ffecom_finish_symbol_transform_);
7333 /* ffecom_sym_transform_ -- Transform FFE sym into backend sym
7335 ffesymbol s;
7336 ffecom_sym_transform_(s);
7338 The ffesymbol_hook info for s is updated with appropriate backend info
7339 on the symbol. */
7341 static ffesymbol
7342 ffecom_sym_transform_ (ffesymbol s)
7344 tree t; /* Transformed thingy. */
7345 tree tlen; /* Length if CHAR*(*). */
7346 bool addr; /* Is t the address of the thingy? */
7347 ffeinfoBasictype bt;
7348 ffeinfoKindtype kt;
7349 ffeglobal g;
7350 int old_lineno = lineno;
7351 const char *old_input_filename = input_filename;
7353 /* Must ensure special ASSIGN variables are declared at top of outermost
7354 block, else they'll end up in the innermost block when their first
7355 ASSIGN is seen, which leaves them out of scope when they're the
7356 subject of a GOTO or I/O statement.
7358 We make this variable even if -fugly-assign. Just let it go unused,
7359 in case it turns out there are cases where we really want to use this
7360 variable anyway (e.g. ASSIGN to INTEGER*2 variable). */
7362 if (! ffecom_transform_only_dummies_
7363 && ffesymbol_assigned (s)
7364 && ! ffesymbol_hook (s).assign_tree)
7365 s = ffecom_sym_transform_assign_ (s);
7367 if (ffesymbol_sfdummyparent (s) == NULL)
7369 input_filename = ffesymbol_where_filename (s);
7370 lineno = ffesymbol_where_filelinenum (s);
7372 else
7374 ffesymbol sf = ffesymbol_sfdummyparent (s);
7376 input_filename = ffesymbol_where_filename (sf);
7377 lineno = ffesymbol_where_filelinenum (sf);
7380 bt = ffeinfo_basictype (ffebld_info (s));
7381 kt = ffeinfo_kindtype (ffebld_info (s));
7383 t = NULL_TREE;
7384 tlen = NULL_TREE;
7385 addr = FALSE;
7387 switch (ffesymbol_kind (s))
7389 case FFEINFO_kindNONE:
7390 switch (ffesymbol_where (s))
7392 case FFEINFO_whereDUMMY: /* Subroutine or function. */
7393 assert (ffecom_transform_only_dummies_);
7395 /* Before 0.4, this could be ENTITY/DUMMY, but see
7396 ffestu_sym_end_transition -- no longer true (in particular, if
7397 it could be an ENTITY, it _will_ be made one, so that
7398 possibility won't come through here). So we never make length
7399 arg for CHARACTER type. */
7401 t = build_decl (PARM_DECL,
7402 ffecom_get_identifier_ (ffesymbol_text (s)),
7403 ffecom_tree_ptr_to_subr_type);
7404 DECL_ARTIFICIAL (t) = 1;
7405 addr = TRUE;
7406 break;
7408 case FFEINFO_whereGLOBAL: /* Subroutine or function. */
7409 assert (!ffecom_transform_only_dummies_);
7411 if (((g = ffesymbol_global (s)) != NULL)
7412 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7413 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7414 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
7415 && (ffeglobal_hook (g) != NULL_TREE)
7416 && ffe_is_globals ())
7418 t = ffeglobal_hook (g);
7419 break;
7422 t = build_decl (FUNCTION_DECL,
7423 ffecom_get_external_identifier_ (s),
7424 ffecom_tree_subr_type); /* Assume subr. */
7425 DECL_EXTERNAL (t) = 1;
7426 TREE_PUBLIC (t) = 1;
7428 t = start_decl (t, FALSE);
7429 finish_decl (t, NULL_TREE, FALSE);
7431 if ((g != NULL)
7432 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7433 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7434 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
7435 ffeglobal_set_hook (g, t);
7437 ffecom_save_tree_forever (t);
7439 break;
7441 default:
7442 assert ("NONE where unexpected" == NULL);
7443 /* Fall through. */
7444 case FFEINFO_whereANY:
7445 break;
7447 break;
7449 case FFEINFO_kindENTITY:
7450 switch (ffeinfo_where (ffesymbol_info (s)))
7453 case FFEINFO_whereCONSTANT:
7454 /* ~~Debugging info needed? */
7455 assert (!ffecom_transform_only_dummies_);
7456 t = error_mark_node; /* Shouldn't ever see this in expr. */
7457 break;
7459 case FFEINFO_whereLOCAL:
7460 assert (!ffecom_transform_only_dummies_);
7463 ffestorag st = ffesymbol_storage (s);
7464 tree type;
7466 if ((st != NULL)
7467 && (ffestorag_size (st) == 0))
7469 t = error_mark_node;
7470 break;
7473 type = ffecom_type_localvar_ (s, bt, kt);
7475 if (type == error_mark_node)
7477 t = error_mark_node;
7478 break;
7481 if ((st != NULL)
7482 && (ffestorag_parent (st) != NULL))
7483 { /* Child of EQUIVALENCE parent. */
7484 ffestorag est;
7485 tree et;
7486 ffetargetOffset offset;
7488 est = ffestorag_parent (st);
7489 ffecom_transform_equiv_ (est);
7491 et = ffestorag_hook (est);
7492 assert (et != NULL_TREE);
7494 if (! TREE_STATIC (et))
7495 put_var_into_stack (et);
7497 offset = ffestorag_modulo (est)
7498 + ffestorag_offset (ffesymbol_storage (s))
7499 - ffestorag_offset (est);
7501 ffecom_debug_kludge_ (et, "EQUIVALENCE", s, type, offset);
7503 /* (t_type *) (((char *) &et) + offset) */
7505 t = convert (string_type_node, /* (char *) */
7506 ffecom_1 (ADDR_EXPR,
7507 build_pointer_type (TREE_TYPE (et)),
7508 et));
7509 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
7511 build_int_2 (offset, 0));
7512 t = convert (build_pointer_type (type),
7514 TREE_CONSTANT (t) = staticp (et);
7516 addr = TRUE;
7518 else
7520 tree initexpr;
7521 bool init = ffesymbol_is_init (s);
7523 t = build_decl (VAR_DECL,
7524 ffecom_get_identifier_ (ffesymbol_text (s)),
7525 type);
7527 if (init
7528 || ffesymbol_namelisted (s)
7529 #ifdef FFECOM_sizeMAXSTACKITEM
7530 || ((st != NULL)
7531 && (ffestorag_size (st) > FFECOM_sizeMAXSTACKITEM))
7532 #endif
7533 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
7534 && (ffecom_primary_entry_kind_
7535 != FFEINFO_kindBLOCKDATA)
7536 && (ffesymbol_is_save (s) || ffe_is_saveall ())))
7537 TREE_STATIC (t) = !ffesymbol_attr (s, FFESYMBOL_attrADJUSTABLE);
7538 else
7539 TREE_STATIC (t) = 0; /* No need to make static. */
7541 if (init || ffe_is_init_local_zero ())
7542 DECL_INITIAL (t) = error_mark_node;
7544 /* Keep -Wunused from complaining about var if it
7545 is used as sfunc arg or DATA implied-DO. */
7546 if (ffesymbol_attrs (s) & FFESYMBOL_attrsSFARG)
7547 DECL_IN_SYSTEM_HEADER (t) = 1;
7549 t = start_decl (t, FALSE);
7551 if (init)
7553 if (ffesymbol_init (s) != NULL)
7554 initexpr = ffecom_expr (ffesymbol_init (s));
7555 else
7556 initexpr = ffecom_init_zero_ (t);
7558 else if (ffe_is_init_local_zero ())
7559 initexpr = ffecom_init_zero_ (t);
7560 else
7561 initexpr = NULL_TREE; /* Not ref'd if !init. */
7563 finish_decl (t, initexpr, FALSE);
7565 if (st != NULL && DECL_SIZE (t) != error_mark_node)
7567 assert (TREE_CODE (DECL_SIZE_UNIT (t)) == INTEGER_CST);
7568 assert (0 == compare_tree_int (DECL_SIZE_UNIT (t),
7569 ffestorag_size (st)));
7573 break;
7575 case FFEINFO_whereRESULT:
7576 assert (!ffecom_transform_only_dummies_);
7578 if (bt == FFEINFO_basictypeCHARACTER)
7579 { /* Result is already in list of dummies, use
7580 it (& length). */
7581 t = ffecom_func_result_;
7582 tlen = ffecom_func_length_;
7583 addr = TRUE;
7584 break;
7586 if ((ffecom_num_entrypoints_ == 0)
7587 && (bt == FFEINFO_basictypeCOMPLEX)
7588 && (ffesymbol_is_f2c (ffecom_primary_entry_)))
7589 { /* Result is already in list of dummies, use
7590 it. */
7591 t = ffecom_func_result_;
7592 addr = TRUE;
7593 break;
7595 if (ffecom_func_result_ != NULL_TREE)
7597 t = ffecom_func_result_;
7598 break;
7600 if ((ffecom_num_entrypoints_ != 0)
7601 && (ffecom_master_bt_ == FFEINFO_basictypeNONE))
7603 assert (ffecom_multi_retval_ != NULL_TREE);
7604 t = ffecom_1 (INDIRECT_REF, ffecom_multi_type_node_,
7605 ffecom_multi_retval_);
7606 t = ffecom_2 (COMPONENT_REF, ffecom_tree_type[bt][kt],
7607 t, ffecom_multi_fields_[bt][kt]);
7609 break;
7612 t = build_decl (VAR_DECL,
7613 ffecom_get_identifier_ (ffesymbol_text (s)),
7614 ffecom_tree_type[bt][kt]);
7615 TREE_STATIC (t) = 0; /* Put result on stack. */
7616 t = start_decl (t, FALSE);
7617 finish_decl (t, NULL_TREE, FALSE);
7619 ffecom_func_result_ = t;
7621 break;
7623 case FFEINFO_whereDUMMY:
7625 tree type;
7626 ffebld dl;
7627 ffebld dim;
7628 tree low;
7629 tree high;
7630 tree old_sizes;
7631 bool adjustable = FALSE; /* Conditionally adjustable? */
7633 type = ffecom_tree_type[bt][kt];
7634 if (ffesymbol_sfdummyparent (s) != NULL)
7636 if (current_function_decl == ffecom_outer_function_decl_)
7637 { /* Exec transition before sfunc
7638 context; get it later. */
7639 break;
7641 t = ffecom_get_identifier_ (ffesymbol_text
7642 (ffesymbol_sfdummyparent (s)));
7644 else
7645 t = ffecom_get_identifier_ (ffesymbol_text (s));
7647 assert (ffecom_transform_only_dummies_);
7649 old_sizes = get_pending_sizes ();
7650 put_pending_sizes (old_sizes);
7652 if (bt == FFEINFO_basictypeCHARACTER)
7653 tlen = ffecom_char_enhance_arg_ (&type, s);
7654 type = ffecom_check_size_overflow_ (s, type, TRUE);
7656 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
7658 if (type == error_mark_node)
7659 break;
7661 dim = ffebld_head (dl);
7662 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
7663 if ((ffebld_left (dim) == NULL) || ffecom_doing_entry_)
7664 low = ffecom_integer_one_node;
7665 else
7666 low = ffecom_expr (ffebld_left (dim));
7667 assert (ffebld_right (dim) != NULL);
7668 if ((ffebld_op (ffebld_right (dim)) == FFEBLD_opSTAR)
7669 || ffecom_doing_entry_)
7671 /* Used to just do high=low. But for ffecom_tree_
7672 canonize_ref_, it probably is important to correctly
7673 assess the size. E.g. given COMPLEX C(*),CFUNC and
7674 C(2)=CFUNC(C), overlap can happen, while it can't
7675 for, say, C(1)=CFUNC(C(2)). */
7676 /* Even more recently used to set to INT_MAX, but that
7677 broke when some overflow checking went into the back
7678 end. Now we just leave the upper bound unspecified. */
7679 high = NULL;
7681 else
7682 high = ffecom_expr (ffebld_right (dim));
7684 /* Determine whether array is conditionally adjustable,
7685 to decide whether back-end magic is needed.
7687 Normally the front end uses the back-end function
7688 variable_size to wrap SAVE_EXPR's around expressions
7689 affecting the size/shape of an array so that the
7690 size/shape info doesn't change during execution
7691 of the compiled code even though variables and
7692 functions referenced in those expressions might.
7694 variable_size also makes sure those saved expressions
7695 get evaluated immediately upon entry to the
7696 compiled procedure -- the front end normally doesn't
7697 have to worry about that.
7699 However, there is a problem with this that affects
7700 g77's implementation of entry points, and that is
7701 that it is _not_ true that each invocation of the
7702 compiled procedure is permitted to evaluate
7703 array size/shape info -- because it is possible
7704 that, for some invocations, that info is invalid (in
7705 which case it is "promised" -- i.e. a violation of
7706 the Fortran standard -- that the compiled code
7707 won't reference the array or its size/shape
7708 during that particular invocation).
7710 To phrase this in C terms, consider this gcc function:
7712 void foo (int *n, float (*a)[*n])
7714 // a is "pointer to array ...", fyi.
7717 Suppose that, for some invocations, it is permitted
7718 for a caller of foo to do this:
7720 foo (NULL, NULL);
7722 Now the _written_ code for foo can take such a call
7723 into account by either testing explicitly for whether
7724 (a == NULL) || (n == NULL) -- presumably it is
7725 not permitted to reference *a in various fashions
7726 if (n == NULL) I suppose -- or it can avoid it by
7727 looking at other info (other arguments, static/global
7728 data, etc.).
7730 However, this won't work in gcc 2.5.8 because it'll
7731 automatically emit the code to save the "*n"
7732 expression, which'll yield a NULL dereference for
7733 the "foo (NULL, NULL)" call, something the code
7734 for foo cannot prevent.
7736 g77 definitely needs to avoid executing such
7737 code anytime the pointer to the adjustable array
7738 is NULL, because even if its bounds expressions
7739 don't have any references to possible "absent"
7740 variables like "*n" -- say all variable references
7741 are to COMMON variables, i.e. global (though in C,
7742 local static could actually make sense) -- the
7743 expressions could yield other run-time problems
7744 for allowably "dead" values in those variables.
7746 For example, let's consider a more complicated
7747 version of foo:
7749 extern int i;
7750 extern int j;
7752 void foo (float (*a)[i/j])
7757 The above is (essentially) quite valid for Fortran
7758 but, again, for a call like "foo (NULL);", it is
7759 permitted for i and j to be undefined when the
7760 call is made. If j happened to be zero, for
7761 example, emitting the code to evaluate "i/j"
7762 could result in a run-time error.
7764 Offhand, though I don't have my F77 or F90
7765 standards handy, it might even be valid for a
7766 bounds expression to contain a function reference,
7767 in which case I doubt it is permitted for an
7768 implementation to invoke that function in the
7769 Fortran case involved here (invocation of an
7770 alternate ENTRY point that doesn't have the adjustable
7771 array as one of its arguments).
7773 So, the code that the compiler would normally emit
7774 to preevaluate the size/shape info for an
7775 adjustable array _must not_ be executed at run time
7776 in certain cases. Specifically, for Fortran,
7777 the case is when the pointer to the adjustable
7778 array == NULL. (For gnu-ish C, it might be nice
7779 for the source code itself to specify an expression
7780 that, if TRUE, inhibits execution of the code. Or
7781 reverse the sense for elegance.)
7783 (Note that g77 could use a different test than NULL,
7784 actually, since it happens to always pass an
7785 integer to the called function that specifies which
7786 entry point is being invoked. Hmm, this might
7787 solve the next problem.)
7789 One way a user could, I suppose, write "foo" so
7790 it works is to insert COND_EXPR's for the
7791 size/shape info so the dangerous stuff isn't
7792 actually done, as in:
7794 void foo (int *n, float (*a)[(a == NULL) ? 0 : *n])
7799 The next problem is that the front end needs to
7800 be able to tell the back end about the array's
7801 decl _before_ it tells it about the conditional
7802 expression to inhibit evaluation of size/shape info,
7803 as shown above.
7805 To solve this, the front end needs to be able
7806 to give the back end the expression to inhibit
7807 generation of the preevaluation code _after_
7808 it makes the decl for the adjustable array.
7810 Until then, the above example using the COND_EXPR
7811 doesn't pass muster with gcc because the "(a == NULL)"
7812 part has a reference to "a", which is still
7813 undefined at that point.
7815 g77 will therefore use a different mechanism in the
7816 meantime. */
7818 if (!adjustable
7819 && ((TREE_CODE (low) != INTEGER_CST)
7820 || (high && TREE_CODE (high) != INTEGER_CST)))
7821 adjustable = TRUE;
7823 #if 0 /* Old approach -- see below. */
7824 if (TREE_CODE (low) != INTEGER_CST)
7825 low = ffecom_3 (COND_EXPR, integer_type_node,
7826 ffecom_adjarray_passed_ (s),
7827 low,
7828 ffecom_integer_zero_node);
7830 if (high && TREE_CODE (high) != INTEGER_CST)
7831 high = ffecom_3 (COND_EXPR, integer_type_node,
7832 ffecom_adjarray_passed_ (s),
7833 high,
7834 ffecom_integer_zero_node);
7835 #endif
7837 /* ~~~gcc/stor-layout.c (layout_type) should do this,
7838 probably. Fixes 950302-1.f. */
7840 if (TREE_CODE (low) != INTEGER_CST)
7841 low = variable_size (low);
7843 /* ~~~Similarly, this fixes dumb0.f. The C front end
7844 does this, which is why dumb0.c would work. */
7846 if (high && TREE_CODE (high) != INTEGER_CST)
7847 high = variable_size (high);
7849 type
7850 = build_array_type
7851 (type,
7852 build_range_type (ffecom_integer_type_node,
7853 low, high));
7854 type = ffecom_check_size_overflow_ (s, type, TRUE);
7857 if (type == error_mark_node)
7859 t = error_mark_node;
7860 break;
7863 if ((ffesymbol_sfdummyparent (s) == NULL)
7864 || (ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER))
7866 type = build_pointer_type (type);
7867 addr = TRUE;
7870 t = build_decl (PARM_DECL, t, type);
7871 DECL_ARTIFICIAL (t) = 1;
7873 /* If this arg is present in every entry point's list of
7874 dummy args, then we're done. */
7876 if (ffesymbol_numentries (s)
7877 == (ffecom_num_entrypoints_ + 1))
7878 break;
7880 #if 1
7882 /* If variable_size in stor-layout has been called during
7883 the above, then get_pending_sizes should have the
7884 yet-to-be-evaluated saved expressions pending.
7885 Make the whole lot of them get emitted, conditionally
7886 on whether the array decl ("t" above) is not NULL. */
7889 tree sizes = get_pending_sizes ();
7890 tree tem;
7892 for (tem = sizes;
7893 tem != old_sizes;
7894 tem = TREE_CHAIN (tem))
7896 tree temv = TREE_VALUE (tem);
7898 if (sizes == tem)
7899 sizes = temv;
7900 else
7901 sizes
7902 = ffecom_2 (COMPOUND_EXPR,
7903 TREE_TYPE (sizes),
7904 temv,
7905 sizes);
7908 if (sizes != tem)
7910 sizes
7911 = ffecom_3 (COND_EXPR,
7912 TREE_TYPE (sizes),
7913 ffecom_2 (NE_EXPR,
7914 integer_type_node,
7916 null_pointer_node),
7917 sizes,
7918 convert (TREE_TYPE (sizes),
7919 integer_zero_node));
7920 sizes = ffecom_save_tree (sizes);
7922 sizes
7923 = tree_cons (NULL_TREE, sizes, tem);
7926 if (sizes)
7927 put_pending_sizes (sizes);
7930 #else
7931 #if 0
7932 if (adjustable
7933 && (ffesymbol_numentries (s)
7934 != ffecom_num_entrypoints_ + 1))
7935 DECL_SOMETHING (t)
7936 = ffecom_2 (NE_EXPR, integer_type_node,
7938 null_pointer_node);
7939 #else
7940 #if 0
7941 if (adjustable
7942 && (ffesymbol_numentries (s)
7943 != ffecom_num_entrypoints_ + 1))
7945 ffebad_start (FFEBAD_MISSING_ADJARRAY_UNSUPPORTED);
7946 ffebad_here (0, ffesymbol_where_line (s),
7947 ffesymbol_where_column (s));
7948 ffebad_string (ffesymbol_text (s));
7949 ffebad_finish ();
7951 #endif
7952 #endif
7953 #endif
7955 break;
7957 case FFEINFO_whereCOMMON:
7959 ffesymbol cs;
7960 ffeglobal cg;
7961 tree ct;
7962 ffestorag st = ffesymbol_storage (s);
7963 tree type;
7965 cs = ffesymbol_common (s); /* The COMMON area itself. */
7966 if (st != NULL) /* Else not laid out. */
7968 ffecom_transform_common_ (cs);
7969 st = ffesymbol_storage (s);
7972 type = ffecom_type_localvar_ (s, bt, kt);
7974 cg = ffesymbol_global (cs); /* The global COMMON info. */
7975 if ((cg == NULL)
7976 || (ffeglobal_type (cg) != FFEGLOBAL_typeCOMMON))
7977 ct = NULL_TREE;
7978 else
7979 ct = ffeglobal_hook (cg); /* The common area's tree. */
7981 if ((ct == NULL_TREE)
7982 || (st == NULL)
7983 || (type == error_mark_node))
7984 t = error_mark_node;
7985 else
7987 ffetargetOffset offset;
7988 ffestorag cst;
7990 cst = ffestorag_parent (st);
7991 assert (cst == ffesymbol_storage (cs));
7993 offset = ffestorag_modulo (cst)
7994 + ffestorag_offset (st)
7995 - ffestorag_offset (cst);
7997 ffecom_debug_kludge_ (ct, "COMMON", s, type, offset);
7999 /* (t_type *) (((char *) &ct) + offset) */
8001 t = convert (string_type_node, /* (char *) */
8002 ffecom_1 (ADDR_EXPR,
8003 build_pointer_type (TREE_TYPE (ct)),
8004 ct));
8005 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
8007 build_int_2 (offset, 0));
8008 t = convert (build_pointer_type (type),
8010 TREE_CONSTANT (t) = 1;
8012 addr = TRUE;
8015 break;
8017 case FFEINFO_whereIMMEDIATE:
8018 case FFEINFO_whereGLOBAL:
8019 case FFEINFO_whereFLEETING:
8020 case FFEINFO_whereFLEETING_CADDR:
8021 case FFEINFO_whereFLEETING_IADDR:
8022 case FFEINFO_whereINTRINSIC:
8023 case FFEINFO_whereCONSTANT_SUBOBJECT:
8024 default:
8025 assert ("ENTITY where unheard of" == NULL);
8026 /* Fall through. */
8027 case FFEINFO_whereANY:
8028 t = error_mark_node;
8029 break;
8031 break;
8033 case FFEINFO_kindFUNCTION:
8034 switch (ffeinfo_where (ffesymbol_info (s)))
8036 case FFEINFO_whereLOCAL: /* Me. */
8037 assert (!ffecom_transform_only_dummies_);
8038 t = current_function_decl;
8039 break;
8041 case FFEINFO_whereGLOBAL:
8042 assert (!ffecom_transform_only_dummies_);
8044 if (((g = ffesymbol_global (s)) != NULL)
8045 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8046 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8047 && (ffeglobal_hook (g) != NULL_TREE)
8048 && ffe_is_globals ())
8050 t = ffeglobal_hook (g);
8051 break;
8054 if (ffesymbol_is_f2c (s)
8055 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8056 t = ffecom_tree_fun_type[bt][kt];
8057 else
8058 t = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
8060 t = build_decl (FUNCTION_DECL,
8061 ffecom_get_external_identifier_ (s),
8063 DECL_EXTERNAL (t) = 1;
8064 TREE_PUBLIC (t) = 1;
8066 t = start_decl (t, FALSE);
8067 finish_decl (t, NULL_TREE, FALSE);
8069 if ((g != NULL)
8070 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8071 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8072 ffeglobal_set_hook (g, t);
8074 ffecom_save_tree_forever (t);
8076 break;
8078 case FFEINFO_whereDUMMY:
8079 assert (ffecom_transform_only_dummies_);
8081 if (ffesymbol_is_f2c (s)
8082 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8083 t = ffecom_tree_ptr_to_fun_type[bt][kt];
8084 else
8085 t = build_pointer_type
8086 (build_function_type (ffecom_tree_type[bt][kt], NULL_TREE));
8088 t = build_decl (PARM_DECL,
8089 ffecom_get_identifier_ (ffesymbol_text (s)),
8091 DECL_ARTIFICIAL (t) = 1;
8092 addr = TRUE;
8093 break;
8095 case FFEINFO_whereCONSTANT: /* Statement function. */
8096 assert (!ffecom_transform_only_dummies_);
8097 t = ffecom_gen_sfuncdef_ (s, bt, kt);
8098 break;
8100 case FFEINFO_whereINTRINSIC:
8101 assert (!ffecom_transform_only_dummies_);
8102 break; /* Let actual references generate their
8103 decls. */
8105 default:
8106 assert ("FUNCTION where unheard of" == NULL);
8107 /* Fall through. */
8108 case FFEINFO_whereANY:
8109 t = error_mark_node;
8110 break;
8112 break;
8114 case FFEINFO_kindSUBROUTINE:
8115 switch (ffeinfo_where (ffesymbol_info (s)))
8117 case FFEINFO_whereLOCAL: /* Me. */
8118 assert (!ffecom_transform_only_dummies_);
8119 t = current_function_decl;
8120 break;
8122 case FFEINFO_whereGLOBAL:
8123 assert (!ffecom_transform_only_dummies_);
8125 if (((g = ffesymbol_global (s)) != NULL)
8126 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8127 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8128 && (ffeglobal_hook (g) != NULL_TREE)
8129 && ffe_is_globals ())
8131 t = ffeglobal_hook (g);
8132 break;
8135 t = build_decl (FUNCTION_DECL,
8136 ffecom_get_external_identifier_ (s),
8137 ffecom_tree_subr_type);
8138 DECL_EXTERNAL (t) = 1;
8139 TREE_PUBLIC (t) = 1;
8141 t = start_decl (t, FALSE);
8142 finish_decl (t, NULL_TREE, FALSE);
8144 if ((g != NULL)
8145 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8146 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8147 ffeglobal_set_hook (g, t);
8149 ffecom_save_tree_forever (t);
8151 break;
8153 case FFEINFO_whereDUMMY:
8154 assert (ffecom_transform_only_dummies_);
8156 t = build_decl (PARM_DECL,
8157 ffecom_get_identifier_ (ffesymbol_text (s)),
8158 ffecom_tree_ptr_to_subr_type);
8159 DECL_ARTIFICIAL (t) = 1;
8160 addr = TRUE;
8161 break;
8163 case FFEINFO_whereINTRINSIC:
8164 assert (!ffecom_transform_only_dummies_);
8165 break; /* Let actual references generate their
8166 decls. */
8168 default:
8169 assert ("SUBROUTINE where unheard of" == NULL);
8170 /* Fall through. */
8171 case FFEINFO_whereANY:
8172 t = error_mark_node;
8173 break;
8175 break;
8177 case FFEINFO_kindPROGRAM:
8178 switch (ffeinfo_where (ffesymbol_info (s)))
8180 case FFEINFO_whereLOCAL: /* Me. */
8181 assert (!ffecom_transform_only_dummies_);
8182 t = current_function_decl;
8183 break;
8185 case FFEINFO_whereCOMMON:
8186 case FFEINFO_whereDUMMY:
8187 case FFEINFO_whereGLOBAL:
8188 case FFEINFO_whereRESULT:
8189 case FFEINFO_whereFLEETING:
8190 case FFEINFO_whereFLEETING_CADDR:
8191 case FFEINFO_whereFLEETING_IADDR:
8192 case FFEINFO_whereIMMEDIATE:
8193 case FFEINFO_whereINTRINSIC:
8194 case FFEINFO_whereCONSTANT:
8195 case FFEINFO_whereCONSTANT_SUBOBJECT:
8196 default:
8197 assert ("PROGRAM where unheard of" == NULL);
8198 /* Fall through. */
8199 case FFEINFO_whereANY:
8200 t = error_mark_node;
8201 break;
8203 break;
8205 case FFEINFO_kindBLOCKDATA:
8206 switch (ffeinfo_where (ffesymbol_info (s)))
8208 case FFEINFO_whereLOCAL: /* Me. */
8209 assert (!ffecom_transform_only_dummies_);
8210 t = current_function_decl;
8211 break;
8213 case FFEINFO_whereGLOBAL:
8214 assert (!ffecom_transform_only_dummies_);
8216 t = build_decl (FUNCTION_DECL,
8217 ffecom_get_external_identifier_ (s),
8218 ffecom_tree_blockdata_type);
8219 DECL_EXTERNAL (t) = 1;
8220 TREE_PUBLIC (t) = 1;
8222 t = start_decl (t, FALSE);
8223 finish_decl (t, NULL_TREE, FALSE);
8225 ffecom_save_tree_forever (t);
8227 break;
8229 case FFEINFO_whereCOMMON:
8230 case FFEINFO_whereDUMMY:
8231 case FFEINFO_whereRESULT:
8232 case FFEINFO_whereFLEETING:
8233 case FFEINFO_whereFLEETING_CADDR:
8234 case FFEINFO_whereFLEETING_IADDR:
8235 case FFEINFO_whereIMMEDIATE:
8236 case FFEINFO_whereINTRINSIC:
8237 case FFEINFO_whereCONSTANT:
8238 case FFEINFO_whereCONSTANT_SUBOBJECT:
8239 default:
8240 assert ("BLOCKDATA where unheard of" == NULL);
8241 /* Fall through. */
8242 case FFEINFO_whereANY:
8243 t = error_mark_node;
8244 break;
8246 break;
8248 case FFEINFO_kindCOMMON:
8249 switch (ffeinfo_where (ffesymbol_info (s)))
8251 case FFEINFO_whereLOCAL:
8252 assert (!ffecom_transform_only_dummies_);
8253 ffecom_transform_common_ (s);
8254 break;
8256 case FFEINFO_whereNONE:
8257 case FFEINFO_whereCOMMON:
8258 case FFEINFO_whereDUMMY:
8259 case FFEINFO_whereGLOBAL:
8260 case FFEINFO_whereRESULT:
8261 case FFEINFO_whereFLEETING:
8262 case FFEINFO_whereFLEETING_CADDR:
8263 case FFEINFO_whereFLEETING_IADDR:
8264 case FFEINFO_whereIMMEDIATE:
8265 case FFEINFO_whereINTRINSIC:
8266 case FFEINFO_whereCONSTANT:
8267 case FFEINFO_whereCONSTANT_SUBOBJECT:
8268 default:
8269 assert ("COMMON where unheard of" == NULL);
8270 /* Fall through. */
8271 case FFEINFO_whereANY:
8272 t = error_mark_node;
8273 break;
8275 break;
8277 case FFEINFO_kindCONSTRUCT:
8278 switch (ffeinfo_where (ffesymbol_info (s)))
8280 case FFEINFO_whereLOCAL:
8281 assert (!ffecom_transform_only_dummies_);
8282 break;
8284 case FFEINFO_whereNONE:
8285 case FFEINFO_whereCOMMON:
8286 case FFEINFO_whereDUMMY:
8287 case FFEINFO_whereGLOBAL:
8288 case FFEINFO_whereRESULT:
8289 case FFEINFO_whereFLEETING:
8290 case FFEINFO_whereFLEETING_CADDR:
8291 case FFEINFO_whereFLEETING_IADDR:
8292 case FFEINFO_whereIMMEDIATE:
8293 case FFEINFO_whereINTRINSIC:
8294 case FFEINFO_whereCONSTANT:
8295 case FFEINFO_whereCONSTANT_SUBOBJECT:
8296 default:
8297 assert ("CONSTRUCT where unheard of" == NULL);
8298 /* Fall through. */
8299 case FFEINFO_whereANY:
8300 t = error_mark_node;
8301 break;
8303 break;
8305 case FFEINFO_kindNAMELIST:
8306 switch (ffeinfo_where (ffesymbol_info (s)))
8308 case FFEINFO_whereLOCAL:
8309 assert (!ffecom_transform_only_dummies_);
8310 t = ffecom_transform_namelist_ (s);
8311 break;
8313 case FFEINFO_whereNONE:
8314 case FFEINFO_whereCOMMON:
8315 case FFEINFO_whereDUMMY:
8316 case FFEINFO_whereGLOBAL:
8317 case FFEINFO_whereRESULT:
8318 case FFEINFO_whereFLEETING:
8319 case FFEINFO_whereFLEETING_CADDR:
8320 case FFEINFO_whereFLEETING_IADDR:
8321 case FFEINFO_whereIMMEDIATE:
8322 case FFEINFO_whereINTRINSIC:
8323 case FFEINFO_whereCONSTANT:
8324 case FFEINFO_whereCONSTANT_SUBOBJECT:
8325 default:
8326 assert ("NAMELIST where unheard of" == NULL);
8327 /* Fall through. */
8328 case FFEINFO_whereANY:
8329 t = error_mark_node;
8330 break;
8332 break;
8334 default:
8335 assert ("kind unheard of" == NULL);
8336 /* Fall through. */
8337 case FFEINFO_kindANY:
8338 t = error_mark_node;
8339 break;
8342 ffesymbol_hook (s).decl_tree = t;
8343 ffesymbol_hook (s).length_tree = tlen;
8344 ffesymbol_hook (s).addr = addr;
8346 lineno = old_lineno;
8347 input_filename = old_input_filename;
8349 return s;
8352 /* Transform into ASSIGNable symbol.
8354 Symbol has already been transformed, but for whatever reason, the
8355 resulting decl_tree has been deemed not usable for an ASSIGN target.
8356 (E.g. it isn't wide enough to hold a pointer.) So, here we invent
8357 another local symbol of type void * and stuff that in the assign_tree
8358 argument. The F77/F90 standards allow this implementation. */
8360 static ffesymbol
8361 ffecom_sym_transform_assign_ (ffesymbol s)
8363 tree t; /* Transformed thingy. */
8364 int old_lineno = lineno;
8365 const char *old_input_filename = input_filename;
8367 if (ffesymbol_sfdummyparent (s) == NULL)
8369 input_filename = ffesymbol_where_filename (s);
8370 lineno = ffesymbol_where_filelinenum (s);
8372 else
8374 ffesymbol sf = ffesymbol_sfdummyparent (s);
8376 input_filename = ffesymbol_where_filename (sf);
8377 lineno = ffesymbol_where_filelinenum (sf);
8380 assert (!ffecom_transform_only_dummies_);
8382 t = build_decl (VAR_DECL,
8383 ffecom_get_invented_identifier ("__g77_ASSIGN_%s",
8384 ffesymbol_text (s)),
8385 TREE_TYPE (null_pointer_node));
8387 switch (ffesymbol_where (s))
8389 case FFEINFO_whereLOCAL:
8390 /* Unlike for regular vars, SAVE status is easy to determine for
8391 ASSIGNed vars, since there's no initialization, there's no
8392 effective storage association (so "SAVE J" does not apply to
8393 K even given "EQUIVALENCE (J,K)"), there's no size issue
8394 to worry about, etc. */
8395 if ((ffesymbol_is_save (s) || ffe_is_saveall ())
8396 && (ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8397 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA))
8398 TREE_STATIC (t) = 1; /* SAVEd in proc, make static. */
8399 else
8400 TREE_STATIC (t) = 0; /* No need to make static. */
8401 break;
8403 case FFEINFO_whereCOMMON:
8404 TREE_STATIC (t) = 1; /* Assume COMMONs always SAVEd. */
8405 break;
8407 case FFEINFO_whereDUMMY:
8408 /* Note that twinning a DUMMY means the caller won't see
8409 the ASSIGNed value. But both F77 and F90 allow implementations
8410 to do this, i.e. disallow Fortran code that would try and
8411 take advantage of actually putting a label into a variable
8412 via a dummy argument (or any other storage association, for
8413 that matter). */
8414 TREE_STATIC (t) = 0;
8415 break;
8417 default:
8418 TREE_STATIC (t) = 0;
8419 break;
8422 t = start_decl (t, FALSE);
8423 finish_decl (t, NULL_TREE, FALSE);
8425 ffesymbol_hook (s).assign_tree = t;
8427 lineno = old_lineno;
8428 input_filename = old_input_filename;
8430 return s;
8433 /* Implement COMMON area in back end.
8435 Because COMMON-based variables can be referenced in the dimension
8436 expressions of dummy (adjustable) arrays, and because dummies
8437 (in the gcc back end) need to be put in the outer binding level
8438 of a function (which has two binding levels, the outer holding
8439 the dummies and the inner holding the other vars), special care
8440 must be taken to handle COMMON areas.
8442 The current strategy is basically to always tell the back end about
8443 the COMMON area as a top-level external reference to just a block
8444 of storage of the master type of that area (e.g. integer, real,
8445 character, whatever -- not a structure). As a distinct action,
8446 if initial values are provided, tell the back end about the area
8447 as a top-level non-external (initialized) area and remember not to
8448 allow further initialization or expansion of the area. Meanwhile,
8449 if no initialization happens at all, tell the back end about
8450 the largest size we've seen declared so the space does get reserved.
8451 (This function doesn't handle all that stuff, but it does some
8452 of the important things.)
8454 Meanwhile, for COMMON variables themselves, just keep creating
8455 references like *((float *) (&common_area + offset)) each time
8456 we reference the variable. In other words, don't make a VAR_DECL
8457 or any kind of component reference (like we used to do before 0.4),
8458 though we might do that as well just for debugging purposes (and
8459 stuff the rtl with the appropriate offset expression). */
8461 static void
8462 ffecom_transform_common_ (ffesymbol s)
8464 ffestorag st = ffesymbol_storage (s);
8465 ffeglobal g = ffesymbol_global (s);
8466 tree cbt;
8467 tree cbtype;
8468 tree init;
8469 tree high;
8470 bool is_init = ffestorag_is_init (st);
8472 assert (st != NULL);
8474 if ((g == NULL)
8475 || (ffeglobal_type (g) != FFEGLOBAL_typeCOMMON))
8476 return;
8478 /* First update the size of the area in global terms. */
8480 ffeglobal_size_common (s, ffestorag_size (st));
8482 if (!ffeglobal_common_init (g))
8483 is_init = FALSE; /* No explicit init, don't let erroneous joins init. */
8485 cbt = ffeglobal_hook (g);
8487 /* If we already have declared this common block for a previous program
8488 unit, and either we already initialized it or we don't have new
8489 initialization for it, just return what we have without changing it. */
8491 if ((cbt != NULL_TREE)
8492 && (!is_init
8493 || !DECL_EXTERNAL (cbt)))
8495 if (st->hook == NULL) ffestorag_set_hook (st, cbt);
8496 return;
8499 /* Process inits. */
8501 if (is_init)
8503 if (ffestorag_init (st) != NULL)
8505 ffebld sexp;
8507 /* Set the padding for the expression, so ffecom_expr
8508 knows to insert that many zeros. */
8509 switch (ffebld_op (sexp = ffestorag_init (st)))
8511 case FFEBLD_opCONTER:
8512 ffebld_conter_set_pad (sexp, ffestorag_modulo (st));
8513 break;
8515 case FFEBLD_opARRTER:
8516 ffebld_arrter_set_pad (sexp, ffestorag_modulo (st));
8517 break;
8519 case FFEBLD_opACCTER:
8520 ffebld_accter_set_pad (sexp, ffestorag_modulo (st));
8521 break;
8523 default:
8524 assert ("bad op for cmn init (pad)" == NULL);
8525 break;
8528 init = ffecom_expr (sexp);
8529 if (init == error_mark_node)
8530 { /* Hopefully the back end complained! */
8531 init = NULL_TREE;
8532 if (cbt != NULL_TREE)
8533 return;
8536 else
8537 init = error_mark_node;
8539 else
8540 init = NULL_TREE;
8542 /* cbtype must be permanently allocated! */
8544 /* Allocate the MAX of the areas so far, seen filewide. */
8545 high = build_int_2 ((ffeglobal_common_size (g)
8546 + ffeglobal_common_pad (g)) - 1, 0);
8547 TREE_TYPE (high) = ffecom_integer_type_node;
8549 if (init)
8550 cbtype = build_array_type (char_type_node,
8551 build_range_type (integer_type_node,
8552 integer_zero_node,
8553 high));
8554 else
8555 cbtype = build_array_type (char_type_node, NULL_TREE);
8557 if (cbt == NULL_TREE)
8560 = build_decl (VAR_DECL,
8561 ffecom_get_external_identifier_ (s),
8562 cbtype);
8563 TREE_STATIC (cbt) = 1;
8564 TREE_PUBLIC (cbt) = 1;
8566 else
8568 assert (is_init);
8569 TREE_TYPE (cbt) = cbtype;
8571 DECL_EXTERNAL (cbt) = init ? 0 : 1;
8572 DECL_INITIAL (cbt) = init ? error_mark_node : NULL_TREE;
8574 cbt = start_decl (cbt, TRUE);
8575 if (ffeglobal_hook (g) != NULL)
8576 assert (cbt == ffeglobal_hook (g));
8578 assert (!init || !DECL_EXTERNAL (cbt));
8580 /* Make sure that any type can live in COMMON and be referenced
8581 without getting a bus error. We could pick the most restrictive
8582 alignment of all entities actually placed in the COMMON, but
8583 this seems easy enough. */
8585 DECL_ALIGN (cbt) = BIGGEST_ALIGNMENT;
8586 DECL_USER_ALIGN (cbt) = 0;
8588 if (is_init && (ffestorag_init (st) == NULL))
8589 init = ffecom_init_zero_ (cbt);
8591 finish_decl (cbt, init, TRUE);
8593 if (is_init)
8594 ffestorag_set_init (st, ffebld_new_any ());
8596 if (init)
8598 assert (DECL_SIZE_UNIT (cbt) != NULL_TREE);
8599 assert (TREE_CODE (DECL_SIZE_UNIT (cbt)) == INTEGER_CST);
8600 assert (0 == compare_tree_int (DECL_SIZE_UNIT (cbt),
8601 (ffeglobal_common_size (g)
8602 + ffeglobal_common_pad (g))));
8605 ffeglobal_set_hook (g, cbt);
8607 ffestorag_set_hook (st, cbt);
8609 ffecom_save_tree_forever (cbt);
8612 /* Make master area for local EQUIVALENCE. */
8614 static void
8615 ffecom_transform_equiv_ (ffestorag eqst)
8617 tree eqt;
8618 tree eqtype;
8619 tree init;
8620 tree high;
8621 bool is_init = ffestorag_is_init (eqst);
8623 assert (eqst != NULL);
8625 eqt = ffestorag_hook (eqst);
8627 if (eqt != NULL_TREE)
8628 return;
8630 /* Process inits. */
8632 if (is_init)
8634 if (ffestorag_init (eqst) != NULL)
8636 ffebld sexp;
8638 /* Set the padding for the expression, so ffecom_expr
8639 knows to insert that many zeros. */
8640 switch (ffebld_op (sexp = ffestorag_init (eqst)))
8642 case FFEBLD_opCONTER:
8643 ffebld_conter_set_pad (sexp, ffestorag_modulo (eqst));
8644 break;
8646 case FFEBLD_opARRTER:
8647 ffebld_arrter_set_pad (sexp, ffestorag_modulo (eqst));
8648 break;
8650 case FFEBLD_opACCTER:
8651 ffebld_accter_set_pad (sexp, ffestorag_modulo (eqst));
8652 break;
8654 default:
8655 assert ("bad op for eqv init (pad)" == NULL);
8656 break;
8659 init = ffecom_expr (sexp);
8660 if (init == error_mark_node)
8661 init = NULL_TREE; /* Hopefully the back end complained! */
8663 else
8664 init = error_mark_node;
8666 else if (ffe_is_init_local_zero ())
8667 init = error_mark_node;
8668 else
8669 init = NULL_TREE;
8671 ffecom_member_namelisted_ = FALSE;
8672 ffestorag_drive (ffestorag_list_equivs (eqst),
8673 &ffecom_member_phase1_,
8674 eqst);
8676 high = build_int_2 ((ffestorag_size (eqst)
8677 + ffestorag_modulo (eqst)) - 1, 0);
8678 TREE_TYPE (high) = ffecom_integer_type_node;
8680 eqtype = build_array_type (char_type_node,
8681 build_range_type (ffecom_integer_type_node,
8682 ffecom_integer_zero_node,
8683 high));
8685 eqt = build_decl (VAR_DECL,
8686 ffecom_get_invented_identifier ("__g77_equiv_%s",
8687 ffesymbol_text
8688 (ffestorag_symbol (eqst))),
8689 eqtype);
8690 DECL_EXTERNAL (eqt) = 0;
8691 if (is_init
8692 || ffecom_member_namelisted_
8693 #ifdef FFECOM_sizeMAXSTACKITEM
8694 || (ffestorag_size (eqst) > FFECOM_sizeMAXSTACKITEM)
8695 #endif
8696 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8697 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
8698 && (ffestorag_is_save (eqst) || ffe_is_saveall ())))
8699 TREE_STATIC (eqt) = 1;
8700 else
8701 TREE_STATIC (eqt) = 0;
8702 TREE_PUBLIC (eqt) = 0;
8703 TREE_ADDRESSABLE (eqt) = 1; /* Ensure non-register allocation */
8704 DECL_CONTEXT (eqt) = current_function_decl;
8705 if (init)
8706 DECL_INITIAL (eqt) = error_mark_node;
8707 else
8708 DECL_INITIAL (eqt) = NULL_TREE;
8710 eqt = start_decl (eqt, FALSE);
8712 /* Make sure that any type can live in EQUIVALENCE and be referenced
8713 without getting a bus error. We could pick the most restrictive
8714 alignment of all entities actually placed in the EQUIVALENCE, but
8715 this seems easy enough. */
8717 DECL_ALIGN (eqt) = BIGGEST_ALIGNMENT;
8718 DECL_USER_ALIGN (eqt) = 0;
8720 if ((!is_init && ffe_is_init_local_zero ())
8721 || (is_init && (ffestorag_init (eqst) == NULL)))
8722 init = ffecom_init_zero_ (eqt);
8724 finish_decl (eqt, init, FALSE);
8726 if (is_init)
8727 ffestorag_set_init (eqst, ffebld_new_any ());
8730 assert (TREE_CODE (DECL_SIZE_UNIT (eqt)) == INTEGER_CST);
8731 assert (0 == compare_tree_int (DECL_SIZE_UNIT (eqt),
8732 (ffestorag_size (eqst)
8733 + ffestorag_modulo (eqst))));
8736 ffestorag_set_hook (eqst, eqt);
8738 ffestorag_drive (ffestorag_list_equivs (eqst),
8739 &ffecom_member_phase2_,
8740 eqst);
8743 /* Implement NAMELIST in back end. See f2c/format.c for more info. */
8745 static tree
8746 ffecom_transform_namelist_ (ffesymbol s)
8748 tree nmlt;
8749 tree nmltype = ffecom_type_namelist_ ();
8750 tree nmlinits;
8751 tree nameinit;
8752 tree varsinit;
8753 tree nvarsinit;
8754 tree field;
8755 tree high;
8756 int i;
8757 static int mynumber = 0;
8759 nmlt = build_decl (VAR_DECL,
8760 ffecom_get_invented_identifier ("__g77_namelist_%d",
8761 mynumber++),
8762 nmltype);
8763 TREE_STATIC (nmlt) = 1;
8764 DECL_INITIAL (nmlt) = error_mark_node;
8766 nmlt = start_decl (nmlt, FALSE);
8768 /* Process inits. */
8770 i = strlen (ffesymbol_text (s));
8772 high = build_int_2 (i, 0);
8773 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
8775 nameinit = ffecom_build_f2c_string_ (i + 1,
8776 ffesymbol_text (s));
8777 TREE_TYPE (nameinit)
8778 = build_type_variant
8779 (build_array_type
8780 (char_type_node,
8781 build_range_type (ffecom_f2c_ftnlen_type_node,
8782 ffecom_f2c_ftnlen_one_node,
8783 high)),
8784 1, 0);
8785 TREE_CONSTANT (nameinit) = 1;
8786 TREE_STATIC (nameinit) = 1;
8787 nameinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (nameinit)),
8788 nameinit);
8790 varsinit = ffecom_vardesc_array_ (s);
8791 varsinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (varsinit)),
8792 varsinit);
8793 TREE_CONSTANT (varsinit) = 1;
8794 TREE_STATIC (varsinit) = 1;
8797 ffebld b;
8799 for (i = 0, b = ffesymbol_namelist (s); b != NULL; b = ffebld_trail (b))
8800 ++i;
8802 nvarsinit = build_int_2 (i, 0);
8803 TREE_TYPE (nvarsinit) = integer_type_node;
8804 TREE_CONSTANT (nvarsinit) = 1;
8805 TREE_STATIC (nvarsinit) = 1;
8807 nmlinits = build_tree_list ((field = TYPE_FIELDS (nmltype)), nameinit);
8808 TREE_CHAIN (nmlinits) = build_tree_list ((field = TREE_CHAIN (field)),
8809 varsinit);
8810 TREE_CHAIN (TREE_CHAIN (nmlinits))
8811 = build_tree_list ((field = TREE_CHAIN (field)), nvarsinit);
8813 nmlinits = build (CONSTRUCTOR, nmltype, NULL_TREE, nmlinits);
8814 TREE_CONSTANT (nmlinits) = 1;
8815 TREE_STATIC (nmlinits) = 1;
8817 finish_decl (nmlt, nmlinits, FALSE);
8819 nmlt = ffecom_1 (ADDR_EXPR, build_pointer_type (nmltype), nmlt);
8821 return nmlt;
8824 /* A subroutine of ffecom_tree_canonize_ref_. The incoming tree is
8825 analyzed on the assumption it is calculating a pointer to be
8826 indirected through. It must return the proper decl and offset,
8827 taking into account different units of measurements for offsets. */
8829 static void
8830 ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
8831 tree t)
8833 switch (TREE_CODE (t))
8835 case NOP_EXPR:
8836 case CONVERT_EXPR:
8837 case NON_LVALUE_EXPR:
8838 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
8839 break;
8841 case PLUS_EXPR:
8842 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
8843 if ((*decl == NULL_TREE)
8844 || (*decl == error_mark_node))
8845 break;
8847 if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST)
8849 /* An offset into COMMON. */
8850 *offset = fold (build (PLUS_EXPR, TREE_TYPE (*offset),
8851 *offset, TREE_OPERAND (t, 1)));
8852 /* Convert offset (presumably in bytes) into canonical units
8853 (presumably bits). */
8854 *offset = size_binop (MULT_EXPR,
8855 convert (bitsizetype, *offset),
8856 TYPE_SIZE (TREE_TYPE (TREE_TYPE (t))));
8857 break;
8859 /* Not a COMMON reference, so an unrecognized pattern. */
8860 *decl = error_mark_node;
8861 break;
8863 case PARM_DECL:
8864 *decl = t;
8865 *offset = bitsize_zero_node;
8866 break;
8868 case ADDR_EXPR:
8869 if (TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL)
8871 /* A reference to COMMON. */
8872 *decl = TREE_OPERAND (t, 0);
8873 *offset = bitsize_zero_node;
8874 break;
8876 /* Fall through. */
8877 default:
8878 /* Not a COMMON reference, so an unrecognized pattern. */
8879 *decl = error_mark_node;
8880 break;
8884 /* Given a tree that is possibly intended for use as an lvalue, return
8885 information representing a canonical view of that tree as a decl, an
8886 offset into that decl, and a size for the lvalue.
8888 If there's no applicable decl, NULL_TREE is returned for the decl,
8889 and the other fields are left undefined.
8891 If the tree doesn't fit the recognizable forms, an ERROR_MARK node
8892 is returned for the decl, and the other fields are left undefined.
8894 Otherwise, the decl returned currently is either a VAR_DECL or a
8895 PARM_DECL.
8897 The offset returned is always valid, but of course not necessarily
8898 a constant, and not necessarily converted into the appropriate
8899 type, leaving that up to the caller (so as to avoid that overhead
8900 if the decls being looked at are different anyway).
8902 If the size cannot be determined (e.g. an adjustable array),
8903 an ERROR_MARK node is returned for the size. Otherwise, the
8904 size returned is valid, not necessarily a constant, and not
8905 necessarily converted into the appropriate type as with the
8906 offset.
8908 Note that the offset and size expressions are expressed in the
8909 base storage units (usually bits) rather than in the units of
8910 the type of the decl, because two decls with different types
8911 might overlap but with apparently non-overlapping array offsets,
8912 whereas converting the array offsets to consistant offsets will
8913 reveal the overlap. */
8915 static void
8916 ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
8917 tree *size, tree t)
8919 /* The default path is to report a nonexistant decl. */
8920 *decl = NULL_TREE;
8922 if (t == NULL_TREE)
8923 return;
8925 switch (TREE_CODE (t))
8927 case ERROR_MARK:
8928 case IDENTIFIER_NODE:
8929 case INTEGER_CST:
8930 case REAL_CST:
8931 case COMPLEX_CST:
8932 case STRING_CST:
8933 case CONST_DECL:
8934 case PLUS_EXPR:
8935 case MINUS_EXPR:
8936 case MULT_EXPR:
8937 case TRUNC_DIV_EXPR:
8938 case CEIL_DIV_EXPR:
8939 case FLOOR_DIV_EXPR:
8940 case ROUND_DIV_EXPR:
8941 case TRUNC_MOD_EXPR:
8942 case CEIL_MOD_EXPR:
8943 case FLOOR_MOD_EXPR:
8944 case ROUND_MOD_EXPR:
8945 case RDIV_EXPR:
8946 case EXACT_DIV_EXPR:
8947 case FIX_TRUNC_EXPR:
8948 case FIX_CEIL_EXPR:
8949 case FIX_FLOOR_EXPR:
8950 case FIX_ROUND_EXPR:
8951 case FLOAT_EXPR:
8952 case NEGATE_EXPR:
8953 case MIN_EXPR:
8954 case MAX_EXPR:
8955 case ABS_EXPR:
8956 case FFS_EXPR:
8957 case LSHIFT_EXPR:
8958 case RSHIFT_EXPR:
8959 case LROTATE_EXPR:
8960 case RROTATE_EXPR:
8961 case BIT_IOR_EXPR:
8962 case BIT_XOR_EXPR:
8963 case BIT_AND_EXPR:
8964 case BIT_ANDTC_EXPR:
8965 case BIT_NOT_EXPR:
8966 case TRUTH_ANDIF_EXPR:
8967 case TRUTH_ORIF_EXPR:
8968 case TRUTH_AND_EXPR:
8969 case TRUTH_OR_EXPR:
8970 case TRUTH_XOR_EXPR:
8971 case TRUTH_NOT_EXPR:
8972 case LT_EXPR:
8973 case LE_EXPR:
8974 case GT_EXPR:
8975 case GE_EXPR:
8976 case EQ_EXPR:
8977 case NE_EXPR:
8978 case COMPLEX_EXPR:
8979 case CONJ_EXPR:
8980 case REALPART_EXPR:
8981 case IMAGPART_EXPR:
8982 case LABEL_EXPR:
8983 case COMPONENT_REF:
8984 case COMPOUND_EXPR:
8985 case ADDR_EXPR:
8986 return;
8988 case VAR_DECL:
8989 case PARM_DECL:
8990 *decl = t;
8991 *offset = bitsize_zero_node;
8992 *size = TYPE_SIZE (TREE_TYPE (t));
8993 return;
8995 case ARRAY_REF:
8997 tree array = TREE_OPERAND (t, 0);
8998 tree element = TREE_OPERAND (t, 1);
8999 tree init_offset;
9001 if ((array == NULL_TREE)
9002 || (element == NULL_TREE))
9004 *decl = error_mark_node;
9005 return;
9008 ffecom_tree_canonize_ref_ (decl, &init_offset, size,
9009 array);
9010 if ((*decl == NULL_TREE)
9011 || (*decl == error_mark_node))
9012 return;
9014 /* Calculate ((element - base) * NBBY) + init_offset. */
9015 *offset = fold (build (MINUS_EXPR, TREE_TYPE (element),
9016 element,
9017 TYPE_MIN_VALUE (TYPE_DOMAIN
9018 (TREE_TYPE (array)))));
9020 *offset = size_binop (MULT_EXPR,
9021 convert (bitsizetype, *offset),
9022 TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))));
9024 *offset = size_binop (PLUS_EXPR, init_offset, *offset);
9026 *size = TYPE_SIZE (TREE_TYPE (t));
9027 return;
9030 case INDIRECT_REF:
9032 /* Most of this code is to handle references to COMMON. And so
9033 far that is useful only for calling library functions, since
9034 external (user) functions might reference common areas. But
9035 even calling an external function, it's worthwhile to decode
9036 COMMON references because if not storing into COMMON, we don't
9037 want COMMON-based arguments to gratuitously force use of a
9038 temporary. */
9040 *size = TYPE_SIZE (TREE_TYPE (t));
9042 ffecom_tree_canonize_ptr_ (decl, offset,
9043 TREE_OPERAND (t, 0));
9045 return;
9047 case CONVERT_EXPR:
9048 case NOP_EXPR:
9049 case MODIFY_EXPR:
9050 case NON_LVALUE_EXPR:
9051 case RESULT_DECL:
9052 case FIELD_DECL:
9053 case COND_EXPR: /* More cases than we can handle. */
9054 case SAVE_EXPR:
9055 case REFERENCE_EXPR:
9056 case PREDECREMENT_EXPR:
9057 case PREINCREMENT_EXPR:
9058 case POSTDECREMENT_EXPR:
9059 case POSTINCREMENT_EXPR:
9060 case CALL_EXPR:
9061 default:
9062 *decl = error_mark_node;
9063 return;
9067 /* Do divide operation appropriate to type of operands. */
9069 static tree
9070 ffecom_tree_divide_ (tree tree_type, tree left, tree right,
9071 tree dest_tree, ffebld dest, bool *dest_used,
9072 tree hook)
9074 if ((left == error_mark_node)
9075 || (right == error_mark_node))
9076 return error_mark_node;
9078 switch (TREE_CODE (tree_type))
9080 case INTEGER_TYPE:
9081 return ffecom_2 (TRUNC_DIV_EXPR, tree_type,
9082 left,
9083 right);
9085 case COMPLEX_TYPE:
9086 if (! optimize_size)
9087 return ffecom_2 (RDIV_EXPR, tree_type,
9088 left,
9089 right);
9091 ffecomGfrt ix;
9093 if (TREE_TYPE (tree_type)
9094 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9095 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9096 else
9097 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
9099 left = ffecom_1 (ADDR_EXPR,
9100 build_pointer_type (TREE_TYPE (left)),
9101 left);
9102 left = build_tree_list (NULL_TREE, left);
9103 right = ffecom_1 (ADDR_EXPR,
9104 build_pointer_type (TREE_TYPE (right)),
9105 right);
9106 right = build_tree_list (NULL_TREE, right);
9107 TREE_CHAIN (left) = right;
9109 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9110 ffecom_gfrt_kindtype (ix),
9111 ffe_is_f2c_library (),
9112 tree_type,
9113 left,
9114 dest_tree, dest, dest_used,
9115 NULL_TREE, TRUE, hook);
9117 break;
9119 case RECORD_TYPE:
9121 ffecomGfrt ix;
9123 if (TREE_TYPE (TYPE_FIELDS (tree_type))
9124 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9125 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9126 else
9127 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
9129 left = ffecom_1 (ADDR_EXPR,
9130 build_pointer_type (TREE_TYPE (left)),
9131 left);
9132 left = build_tree_list (NULL_TREE, left);
9133 right = ffecom_1 (ADDR_EXPR,
9134 build_pointer_type (TREE_TYPE (right)),
9135 right);
9136 right = build_tree_list (NULL_TREE, right);
9137 TREE_CHAIN (left) = right;
9139 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9140 ffecom_gfrt_kindtype (ix),
9141 ffe_is_f2c_library (),
9142 tree_type,
9143 left,
9144 dest_tree, dest, dest_used,
9145 NULL_TREE, TRUE, hook);
9147 break;
9149 default:
9150 return ffecom_2 (RDIV_EXPR, tree_type,
9151 left,
9152 right);
9156 /* Build type info for non-dummy variable. */
9158 static tree
9159 ffecom_type_localvar_ (ffesymbol s, ffeinfoBasictype bt,
9160 ffeinfoKindtype kt)
9162 tree type;
9163 ffebld dl;
9164 ffebld dim;
9165 tree lowt;
9166 tree hight;
9168 type = ffecom_tree_type[bt][kt];
9169 if (bt == FFEINFO_basictypeCHARACTER)
9171 hight = build_int_2 (ffesymbol_size (s), 0);
9172 TREE_TYPE (hight) = ffecom_f2c_ftnlen_type_node;
9174 type
9175 = build_array_type
9176 (type,
9177 build_range_type (ffecom_f2c_ftnlen_type_node,
9178 ffecom_f2c_ftnlen_one_node,
9179 hight));
9180 type = ffecom_check_size_overflow_ (s, type, FALSE);
9183 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
9185 if (type == error_mark_node)
9186 break;
9188 dim = ffebld_head (dl);
9189 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
9191 if (ffebld_left (dim) == NULL)
9192 lowt = integer_one_node;
9193 else
9194 lowt = ffecom_expr (ffebld_left (dim));
9196 if (TREE_CODE (lowt) != INTEGER_CST)
9197 lowt = variable_size (lowt);
9199 assert (ffebld_right (dim) != NULL);
9200 hight = ffecom_expr (ffebld_right (dim));
9202 if (TREE_CODE (hight) != INTEGER_CST)
9203 hight = variable_size (hight);
9205 type = build_array_type (type,
9206 build_range_type (ffecom_integer_type_node,
9207 lowt, hight));
9208 type = ffecom_check_size_overflow_ (s, type, FALSE);
9211 return type;
9214 /* Build Namelist type. */
9216 static tree
9217 ffecom_type_namelist_ ()
9219 static tree type = NULL_TREE;
9221 if (type == NULL_TREE)
9223 static tree namefield, varsfield, nvarsfield;
9224 tree vardesctype;
9226 vardesctype = ffecom_type_vardesc_ ();
9228 type = make_node (RECORD_TYPE);
9230 vardesctype = build_pointer_type (build_pointer_type (vardesctype));
9232 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9233 string_type_node);
9234 varsfield = ffecom_decl_field (type, namefield, "vars", vardesctype);
9235 nvarsfield = ffecom_decl_field (type, varsfield, "nvars",
9236 integer_type_node);
9238 TYPE_FIELDS (type) = namefield;
9239 layout_type (type);
9241 ggc_add_tree_root (&type, 1);
9244 return type;
9247 /* Build Vardesc type. */
9249 static tree
9250 ffecom_type_vardesc_ ()
9252 static tree type = NULL_TREE;
9253 static tree namefield, addrfield, dimsfield, typefield;
9255 if (type == NULL_TREE)
9257 type = make_node (RECORD_TYPE);
9259 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9260 string_type_node);
9261 addrfield = ffecom_decl_field (type, namefield, "addr",
9262 string_type_node);
9263 dimsfield = ffecom_decl_field (type, addrfield, "dims",
9264 ffecom_f2c_ptr_to_ftnlen_type_node);
9265 typefield = ffecom_decl_field (type, dimsfield, "type",
9266 integer_type_node);
9268 TYPE_FIELDS (type) = namefield;
9269 layout_type (type);
9271 ggc_add_tree_root (&type, 1);
9274 return type;
9277 static tree
9278 ffecom_vardesc_ (ffebld expr)
9280 ffesymbol s;
9282 assert (ffebld_op (expr) == FFEBLD_opSYMTER);
9283 s = ffebld_symter (expr);
9285 if (ffesymbol_hook (s).vardesc_tree == NULL_TREE)
9287 int i;
9288 tree vardesctype = ffecom_type_vardesc_ ();
9289 tree var;
9290 tree nameinit;
9291 tree dimsinit;
9292 tree addrinit;
9293 tree typeinit;
9294 tree field;
9295 tree varinits;
9296 static int mynumber = 0;
9298 var = build_decl (VAR_DECL,
9299 ffecom_get_invented_identifier ("__g77_vardesc_%d",
9300 mynumber++),
9301 vardesctype);
9302 TREE_STATIC (var) = 1;
9303 DECL_INITIAL (var) = error_mark_node;
9305 var = start_decl (var, FALSE);
9307 /* Process inits. */
9309 nameinit = ffecom_build_f2c_string_ ((i = strlen (ffesymbol_text (s)))
9310 + 1,
9311 ffesymbol_text (s));
9312 TREE_TYPE (nameinit)
9313 = build_type_variant
9314 (build_array_type
9315 (char_type_node,
9316 build_range_type (integer_type_node,
9317 integer_one_node,
9318 build_int_2 (i, 0))),
9319 1, 0);
9320 TREE_CONSTANT (nameinit) = 1;
9321 TREE_STATIC (nameinit) = 1;
9322 nameinit = ffecom_1 (ADDR_EXPR,
9323 build_pointer_type (TREE_TYPE (nameinit)),
9324 nameinit);
9326 addrinit = ffecom_arg_ptr_to_expr (expr, &typeinit);
9328 dimsinit = ffecom_vardesc_dims_ (s);
9330 if (typeinit == NULL_TREE)
9332 ffeinfoBasictype bt = ffesymbol_basictype (s);
9333 ffeinfoKindtype kt = ffesymbol_kindtype (s);
9334 int tc = ffecom_f2c_typecode (bt, kt);
9336 assert (tc != -1);
9337 typeinit = build_int_2 (tc, (tc < 0) ? -1 : 0);
9339 else
9340 typeinit = ffecom_1 (NEGATE_EXPR, TREE_TYPE (typeinit), typeinit);
9342 varinits = build_tree_list ((field = TYPE_FIELDS (vardesctype)),
9343 nameinit);
9344 TREE_CHAIN (varinits) = build_tree_list ((field = TREE_CHAIN (field)),
9345 addrinit);
9346 TREE_CHAIN (TREE_CHAIN (varinits))
9347 = build_tree_list ((field = TREE_CHAIN (field)), dimsinit);
9348 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (varinits)))
9349 = build_tree_list ((field = TREE_CHAIN (field)), typeinit);
9351 varinits = build (CONSTRUCTOR, vardesctype, NULL_TREE, varinits);
9352 TREE_CONSTANT (varinits) = 1;
9353 TREE_STATIC (varinits) = 1;
9355 finish_decl (var, varinits, FALSE);
9357 var = ffecom_1 (ADDR_EXPR, build_pointer_type (vardesctype), var);
9359 ffesymbol_hook (s).vardesc_tree = var;
9362 return ffesymbol_hook (s).vardesc_tree;
9365 static tree
9366 ffecom_vardesc_array_ (ffesymbol s)
9368 ffebld b;
9369 tree list;
9370 tree item = NULL_TREE;
9371 tree var;
9372 int i;
9373 static int mynumber = 0;
9375 for (i = 0, list = NULL_TREE, b = ffesymbol_namelist (s);
9376 b != NULL;
9377 b = ffebld_trail (b), ++i)
9379 tree t;
9381 t = ffecom_vardesc_ (ffebld_head (b));
9383 if (list == NULL_TREE)
9384 list = item = build_tree_list (NULL_TREE, t);
9385 else
9387 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9388 item = TREE_CHAIN (item);
9392 item = build_array_type (build_pointer_type (ffecom_type_vardesc_ ()),
9393 build_range_type (integer_type_node,
9394 integer_one_node,
9395 build_int_2 (i, 0)));
9396 list = build (CONSTRUCTOR, item, NULL_TREE, list);
9397 TREE_CONSTANT (list) = 1;
9398 TREE_STATIC (list) = 1;
9400 var = ffecom_get_invented_identifier ("__g77_vardesc_array_%d", mynumber++);
9401 var = build_decl (VAR_DECL, var, item);
9402 TREE_STATIC (var) = 1;
9403 DECL_INITIAL (var) = error_mark_node;
9404 var = start_decl (var, FALSE);
9405 finish_decl (var, list, FALSE);
9407 return var;
9410 static tree
9411 ffecom_vardesc_dims_ (ffesymbol s)
9413 if (ffesymbol_dims (s) == NULL)
9414 return convert (ffecom_f2c_ptr_to_ftnlen_type_node,
9415 integer_zero_node);
9418 ffebld b;
9419 ffebld e;
9420 tree list;
9421 tree backlist;
9422 tree item = NULL_TREE;
9423 tree var;
9424 tree numdim;
9425 tree numelem;
9426 tree baseoff = NULL_TREE;
9427 static int mynumber = 0;
9429 numdim = build_int_2 ((int) ffesymbol_rank (s), 0);
9430 TREE_TYPE (numdim) = ffecom_f2c_ftnlen_type_node;
9432 numelem = ffecom_expr (ffesymbol_arraysize (s));
9433 TREE_TYPE (numelem) = ffecom_f2c_ftnlen_type_node;
9435 list = NULL_TREE;
9436 backlist = NULL_TREE;
9437 for (b = ffesymbol_dims (s), e = ffesymbol_extents (s);
9438 b != NULL;
9439 b = ffebld_trail (b), e = ffebld_trail (e))
9441 tree t;
9442 tree low;
9443 tree back;
9445 if (ffebld_trail (b) == NULL)
9446 t = NULL_TREE;
9447 else
9449 t = convert (ffecom_f2c_ftnlen_type_node,
9450 ffecom_expr (ffebld_head (e)));
9452 if (list == NULL_TREE)
9453 list = item = build_tree_list (NULL_TREE, t);
9454 else
9456 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9457 item = TREE_CHAIN (item);
9461 if (ffebld_left (ffebld_head (b)) == NULL)
9462 low = ffecom_integer_one_node;
9463 else
9464 low = ffecom_expr (ffebld_left (ffebld_head (b)));
9465 low = convert (ffecom_f2c_ftnlen_type_node, low);
9467 back = build_tree_list (low, t);
9468 TREE_CHAIN (back) = backlist;
9469 backlist = back;
9472 for (item = backlist; item != NULL_TREE; item = TREE_CHAIN (item))
9474 if (TREE_VALUE (item) == NULL_TREE)
9475 baseoff = TREE_PURPOSE (item);
9476 else
9477 baseoff = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
9478 TREE_PURPOSE (item),
9479 ffecom_2 (MULT_EXPR,
9480 ffecom_f2c_ftnlen_type_node,
9481 TREE_VALUE (item),
9482 baseoff));
9485 /* backlist now dead, along with all TREE_PURPOSEs on it. */
9487 baseoff = build_tree_list (NULL_TREE, baseoff);
9488 TREE_CHAIN (baseoff) = list;
9490 numelem = build_tree_list (NULL_TREE, numelem);
9491 TREE_CHAIN (numelem) = baseoff;
9493 numdim = build_tree_list (NULL_TREE, numdim);
9494 TREE_CHAIN (numdim) = numelem;
9496 item = build_array_type (ffecom_f2c_ftnlen_type_node,
9497 build_range_type (integer_type_node,
9498 integer_zero_node,
9499 build_int_2
9500 ((int) ffesymbol_rank (s)
9501 + 2, 0)));
9502 list = build (CONSTRUCTOR, item, NULL_TREE, numdim);
9503 TREE_CONSTANT (list) = 1;
9504 TREE_STATIC (list) = 1;
9506 var = ffecom_get_invented_identifier ("__g77_dims_%d", mynumber++);
9507 var = build_decl (VAR_DECL, var, item);
9508 TREE_STATIC (var) = 1;
9509 DECL_INITIAL (var) = error_mark_node;
9510 var = start_decl (var, FALSE);
9511 finish_decl (var, list, FALSE);
9513 var = ffecom_1 (ADDR_EXPR, build_pointer_type (item), var);
9515 return var;
9519 /* Essentially does a "fold (build1 (code, type, node))" while checking
9520 for certain housekeeping things.
9522 NOTE: for building an ADDR_EXPR around a FUNCTION_DECL, use
9523 ffecom_1_fn instead. */
9525 tree
9526 ffecom_1 (enum tree_code code, tree type, tree node)
9528 tree item;
9530 if ((node == error_mark_node)
9531 || (type == error_mark_node))
9532 return error_mark_node;
9534 if (code == ADDR_EXPR)
9536 if (!ffe_mark_addressable (node))
9537 assert ("can't mark_addressable this node!" == NULL);
9540 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
9542 tree realtype;
9544 case REALPART_EXPR:
9545 item = build (COMPONENT_REF, type, node, TYPE_FIELDS (TREE_TYPE (node)));
9546 break;
9548 case IMAGPART_EXPR:
9549 item = build (COMPONENT_REF, type, node, TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (node))));
9550 break;
9553 case NEGATE_EXPR:
9554 if (TREE_CODE (type) != RECORD_TYPE)
9556 item = build1 (code, type, node);
9557 break;
9559 node = ffecom_stabilize_aggregate_ (node);
9560 realtype = TREE_TYPE (TYPE_FIELDS (type));
9561 item =
9562 ffecom_2 (COMPLEX_EXPR, type,
9563 ffecom_1 (NEGATE_EXPR, realtype,
9564 ffecom_1 (REALPART_EXPR, realtype,
9565 node)),
9566 ffecom_1 (NEGATE_EXPR, realtype,
9567 ffecom_1 (IMAGPART_EXPR, realtype,
9568 node)));
9569 break;
9571 default:
9572 item = build1 (code, type, node);
9573 break;
9576 if (TREE_SIDE_EFFECTS (node))
9577 TREE_SIDE_EFFECTS (item) = 1;
9578 if (code == ADDR_EXPR && staticp (node))
9579 TREE_CONSTANT (item) = 1;
9580 else if (code == INDIRECT_REF)
9581 TREE_READONLY (item) = TYPE_READONLY (type);
9582 return fold (item);
9585 /* Like ffecom_1 (ADDR_EXPR, TREE_TYPE (node), node), except
9586 handles TREE_CODE (node) == FUNCTION_DECL. In particular,
9587 does not set TREE_ADDRESSABLE (because calling an inline
9588 function does not mean the function needs to be separately
9589 compiled). */
9591 tree
9592 ffecom_1_fn (tree node)
9594 tree item;
9595 tree type;
9597 if (node == error_mark_node)
9598 return error_mark_node;
9600 type = build_type_variant (TREE_TYPE (node),
9601 TREE_READONLY (node),
9602 TREE_THIS_VOLATILE (node));
9603 item = build1 (ADDR_EXPR,
9604 build_pointer_type (type), node);
9605 if (TREE_SIDE_EFFECTS (node))
9606 TREE_SIDE_EFFECTS (item) = 1;
9607 if (staticp (node))
9608 TREE_CONSTANT (item) = 1;
9609 return fold (item);
9612 /* Essentially does a "fold (build (code, type, node1, node2))" while
9613 checking for certain housekeeping things. */
9615 tree
9616 ffecom_2 (enum tree_code code, tree type, tree node1,
9617 tree node2)
9619 tree item;
9621 if ((node1 == error_mark_node)
9622 || (node2 == error_mark_node)
9623 || (type == error_mark_node))
9624 return error_mark_node;
9626 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
9628 tree a, b, c, d, realtype;
9630 case CONJ_EXPR:
9631 assert ("no CONJ_EXPR support yet" == NULL);
9632 return error_mark_node;
9634 case COMPLEX_EXPR:
9635 item = build_tree_list (TYPE_FIELDS (type), node1);
9636 TREE_CHAIN (item) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), node2);
9637 item = build (CONSTRUCTOR, type, NULL_TREE, item);
9638 break;
9640 case PLUS_EXPR:
9641 if (TREE_CODE (type) != RECORD_TYPE)
9643 item = build (code, type, node1, node2);
9644 break;
9646 node1 = ffecom_stabilize_aggregate_ (node1);
9647 node2 = ffecom_stabilize_aggregate_ (node2);
9648 realtype = TREE_TYPE (TYPE_FIELDS (type));
9649 item =
9650 ffecom_2 (COMPLEX_EXPR, type,
9651 ffecom_2 (PLUS_EXPR, realtype,
9652 ffecom_1 (REALPART_EXPR, realtype,
9653 node1),
9654 ffecom_1 (REALPART_EXPR, realtype,
9655 node2)),
9656 ffecom_2 (PLUS_EXPR, realtype,
9657 ffecom_1 (IMAGPART_EXPR, realtype,
9658 node1),
9659 ffecom_1 (IMAGPART_EXPR, realtype,
9660 node2)));
9661 break;
9663 case MINUS_EXPR:
9664 if (TREE_CODE (type) != RECORD_TYPE)
9666 item = build (code, type, node1, node2);
9667 break;
9669 node1 = ffecom_stabilize_aggregate_ (node1);
9670 node2 = ffecom_stabilize_aggregate_ (node2);
9671 realtype = TREE_TYPE (TYPE_FIELDS (type));
9672 item =
9673 ffecom_2 (COMPLEX_EXPR, type,
9674 ffecom_2 (MINUS_EXPR, realtype,
9675 ffecom_1 (REALPART_EXPR, realtype,
9676 node1),
9677 ffecom_1 (REALPART_EXPR, realtype,
9678 node2)),
9679 ffecom_2 (MINUS_EXPR, realtype,
9680 ffecom_1 (IMAGPART_EXPR, realtype,
9681 node1),
9682 ffecom_1 (IMAGPART_EXPR, realtype,
9683 node2)));
9684 break;
9686 case MULT_EXPR:
9687 if (TREE_CODE (type) != RECORD_TYPE)
9689 item = build (code, type, node1, node2);
9690 break;
9692 node1 = ffecom_stabilize_aggregate_ (node1);
9693 node2 = ffecom_stabilize_aggregate_ (node2);
9694 realtype = TREE_TYPE (TYPE_FIELDS (type));
9695 a = save_expr (ffecom_1 (REALPART_EXPR, realtype,
9696 node1));
9697 b = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
9698 node1));
9699 c = save_expr (ffecom_1 (REALPART_EXPR, realtype,
9700 node2));
9701 d = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
9702 node2));
9703 item =
9704 ffecom_2 (COMPLEX_EXPR, type,
9705 ffecom_2 (MINUS_EXPR, realtype,
9706 ffecom_2 (MULT_EXPR, realtype,
9709 ffecom_2 (MULT_EXPR, realtype,
9711 d)),
9712 ffecom_2 (PLUS_EXPR, realtype,
9713 ffecom_2 (MULT_EXPR, realtype,
9716 ffecom_2 (MULT_EXPR, realtype,
9718 b)));
9719 break;
9721 case EQ_EXPR:
9722 if ((TREE_CODE (node1) != RECORD_TYPE)
9723 && (TREE_CODE (node2) != RECORD_TYPE))
9725 item = build (code, type, node1, node2);
9726 break;
9728 assert (TREE_CODE (node1) == RECORD_TYPE);
9729 assert (TREE_CODE (node2) == RECORD_TYPE);
9730 node1 = ffecom_stabilize_aggregate_ (node1);
9731 node2 = ffecom_stabilize_aggregate_ (node2);
9732 realtype = TREE_TYPE (TYPE_FIELDS (type));
9733 item =
9734 ffecom_2 (TRUTH_ANDIF_EXPR, type,
9735 ffecom_2 (code, type,
9736 ffecom_1 (REALPART_EXPR, realtype,
9737 node1),
9738 ffecom_1 (REALPART_EXPR, realtype,
9739 node2)),
9740 ffecom_2 (code, type,
9741 ffecom_1 (IMAGPART_EXPR, realtype,
9742 node1),
9743 ffecom_1 (IMAGPART_EXPR, realtype,
9744 node2)));
9745 break;
9747 case NE_EXPR:
9748 if ((TREE_CODE (node1) != RECORD_TYPE)
9749 && (TREE_CODE (node2) != RECORD_TYPE))
9751 item = build (code, type, node1, node2);
9752 break;
9754 assert (TREE_CODE (node1) == RECORD_TYPE);
9755 assert (TREE_CODE (node2) == RECORD_TYPE);
9756 node1 = ffecom_stabilize_aggregate_ (node1);
9757 node2 = ffecom_stabilize_aggregate_ (node2);
9758 realtype = TREE_TYPE (TYPE_FIELDS (type));
9759 item =
9760 ffecom_2 (TRUTH_ORIF_EXPR, type,
9761 ffecom_2 (code, type,
9762 ffecom_1 (REALPART_EXPR, realtype,
9763 node1),
9764 ffecom_1 (REALPART_EXPR, realtype,
9765 node2)),
9766 ffecom_2 (code, type,
9767 ffecom_1 (IMAGPART_EXPR, realtype,
9768 node1),
9769 ffecom_1 (IMAGPART_EXPR, realtype,
9770 node2)));
9771 break;
9773 default:
9774 item = build (code, type, node1, node2);
9775 break;
9778 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2))
9779 TREE_SIDE_EFFECTS (item) = 1;
9780 return fold (item);
9783 /* ffecom_2pass_advise_entrypoint -- Advise that there's this entrypoint
9785 ffesymbol s; // the ENTRY point itself
9786 if (ffecom_2pass_advise_entrypoint(s))
9787 // the ENTRY point has been accepted
9789 Does whatever compiler needs to do when it learns about the entrypoint,
9790 like determine the return type of the master function, count the
9791 number of entrypoints, etc. Returns FALSE if the return type is
9792 not compatible with the return type(s) of other entrypoint(s).
9794 NOTE: for every call to this fn that returns TRUE, _do_entrypoint must
9795 later (after _finish_progunit) be called with the same entrypoint(s)
9796 as passed to this fn for which TRUE was returned.
9798 03-Jan-92 JCB 2.0
9799 Return FALSE if the return type conflicts with previous entrypoints. */
9801 bool
9802 ffecom_2pass_advise_entrypoint (ffesymbol entry)
9804 ffebld list; /* opITEM. */
9805 ffebld mlist; /* opITEM. */
9806 ffebld plist; /* opITEM. */
9807 ffebld arg; /* ffebld_head(opITEM). */
9808 ffebld item; /* opITEM. */
9809 ffesymbol s; /* ffebld_symter(arg). */
9810 ffeinfoBasictype bt = ffesymbol_basictype (entry);
9811 ffeinfoKindtype kt = ffesymbol_kindtype (entry);
9812 ffetargetCharacterSize size = ffesymbol_size (entry);
9813 bool ok;
9815 if (ffecom_num_entrypoints_ == 0)
9816 { /* First entrypoint, make list of main
9817 arglist's dummies. */
9818 assert (ffecom_primary_entry_ != NULL);
9820 ffecom_master_bt_ = ffesymbol_basictype (ffecom_primary_entry_);
9821 ffecom_master_kt_ = ffesymbol_kindtype (ffecom_primary_entry_);
9822 ffecom_master_size_ = ffesymbol_size (ffecom_primary_entry_);
9824 for (plist = NULL, list = ffesymbol_dummyargs (ffecom_primary_entry_);
9825 list != NULL;
9826 list = ffebld_trail (list))
9828 arg = ffebld_head (list);
9829 if (ffebld_op (arg) != FFEBLD_opSYMTER)
9830 continue; /* Alternate return or some such thing. */
9831 item = ffebld_new_item (arg, NULL);
9832 if (plist == NULL)
9833 ffecom_master_arglist_ = item;
9834 else
9835 ffebld_set_trail (plist, item);
9836 plist = item;
9840 /* If necessary, scan entry arglist for alternate returns. Do this scan
9841 apparently redundantly (it's done below to UNIONize the arglists) so
9842 that we don't complain about RETURN 1 if an offending ENTRY is the only
9843 one with an alternate return. */
9845 if (!ffecom_is_altreturning_)
9847 for (list = ffesymbol_dummyargs (entry);
9848 list != NULL;
9849 list = ffebld_trail (list))
9851 arg = ffebld_head (list);
9852 if (ffebld_op (arg) == FFEBLD_opSTAR)
9854 ffecom_is_altreturning_ = TRUE;
9855 break;
9860 /* Now check type compatibility. */
9862 switch (ffecom_master_bt_)
9864 case FFEINFO_basictypeNONE:
9865 ok = (bt != FFEINFO_basictypeCHARACTER);
9866 break;
9868 case FFEINFO_basictypeCHARACTER:
9870 = (bt == FFEINFO_basictypeCHARACTER)
9871 && (kt == ffecom_master_kt_)
9872 && (size == ffecom_master_size_);
9873 break;
9875 case FFEINFO_basictypeANY:
9876 return FALSE; /* Just don't bother. */
9878 default:
9879 if (bt == FFEINFO_basictypeCHARACTER)
9881 ok = FALSE;
9882 break;
9884 ok = TRUE;
9885 if ((bt != ffecom_master_bt_) || (kt != ffecom_master_kt_))
9887 ffecom_master_bt_ = FFEINFO_basictypeNONE;
9888 ffecom_master_kt_ = FFEINFO_kindtypeNONE;
9890 break;
9893 if (!ok)
9895 ffebad_start (FFEBAD_ENTRY_CONFLICTS);
9896 ffest_ffebad_here_current_stmt (0);
9897 ffebad_finish ();
9898 return FALSE; /* Can't handle entrypoint. */
9901 /* Entrypoint type compatible with previous types. */
9903 ++ffecom_num_entrypoints_;
9905 /* Master-arg-list = UNION(Master-arg-list,entry-arg-list). */
9907 for (list = ffesymbol_dummyargs (entry);
9908 list != NULL;
9909 list = ffebld_trail (list))
9911 arg = ffebld_head (list);
9912 if (ffebld_op (arg) != FFEBLD_opSYMTER)
9913 continue; /* Alternate return or some such thing. */
9914 s = ffebld_symter (arg);
9915 for (plist = NULL, mlist = ffecom_master_arglist_;
9916 mlist != NULL;
9917 plist = mlist, mlist = ffebld_trail (mlist))
9918 { /* plist points to previous item for easy
9919 appending of arg. */
9920 if (ffebld_symter (ffebld_head (mlist)) == s)
9921 break; /* Already have this arg in the master list. */
9923 if (mlist != NULL)
9924 continue; /* Already have this arg in the master list. */
9926 /* Append this arg to the master list. */
9928 item = ffebld_new_item (arg, NULL);
9929 if (plist == NULL)
9930 ffecom_master_arglist_ = item;
9931 else
9932 ffebld_set_trail (plist, item);
9935 return TRUE;
9938 /* ffecom_2pass_do_entrypoint -- Do compilation of entrypoint
9940 ffesymbol s; // the ENTRY point itself
9941 ffecom_2pass_do_entrypoint(s);
9943 Does whatever compiler needs to do to make the entrypoint actually
9944 happen. Must be called for each entrypoint after
9945 ffecom_finish_progunit is called. */
9947 void
9948 ffecom_2pass_do_entrypoint (ffesymbol entry)
9950 static int mfn_num = 0;
9951 static int ent_num;
9953 if (mfn_num != ffecom_num_fns_)
9954 { /* First entrypoint for this program unit. */
9955 ent_num = 1;
9956 mfn_num = ffecom_num_fns_;
9957 ffecom_do_entry_ (ffecom_primary_entry_, 0);
9959 else
9960 ++ent_num;
9962 --ffecom_num_entrypoints_;
9964 ffecom_do_entry_ (entry, ent_num);
9967 /* Essentially does a "fold (build (code, type, node1, node2))" while
9968 checking for certain housekeeping things. Always sets
9969 TREE_SIDE_EFFECTS. */
9971 tree
9972 ffecom_2s (enum tree_code code, tree type, tree node1,
9973 tree node2)
9975 tree item;
9977 if ((node1 == error_mark_node)
9978 || (node2 == error_mark_node)
9979 || (type == error_mark_node))
9980 return error_mark_node;
9982 item = build (code, type, node1, node2);
9983 TREE_SIDE_EFFECTS (item) = 1;
9984 return fold (item);
9987 /* Essentially does a "fold (build (code, type, node1, node2, node3))" while
9988 checking for certain housekeeping things. */
9990 tree
9991 ffecom_3 (enum tree_code code, tree type, tree node1,
9992 tree node2, tree node3)
9994 tree item;
9996 if ((node1 == error_mark_node)
9997 || (node2 == error_mark_node)
9998 || (node3 == error_mark_node)
9999 || (type == error_mark_node))
10000 return error_mark_node;
10002 item = build (code, type, node1, node2, node3);
10003 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2)
10004 || (node3 != NULL_TREE && TREE_SIDE_EFFECTS (node3)))
10005 TREE_SIDE_EFFECTS (item) = 1;
10006 return fold (item);
10009 /* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10010 checking for certain housekeeping things. Always sets
10011 TREE_SIDE_EFFECTS. */
10013 tree
10014 ffecom_3s (enum tree_code code, tree type, tree node1,
10015 tree node2, tree node3)
10017 tree item;
10019 if ((node1 == error_mark_node)
10020 || (node2 == error_mark_node)
10021 || (node3 == error_mark_node)
10022 || (type == error_mark_node))
10023 return error_mark_node;
10025 item = build (code, type, node1, node2, node3);
10026 TREE_SIDE_EFFECTS (item) = 1;
10027 return fold (item);
10030 /* ffecom_arg_expr -- Transform argument expr into gcc tree
10032 See use by ffecom_list_expr.
10034 If expression is NULL, returns an integer zero tree. If it is not
10035 a CHARACTER expression, returns whatever ffecom_expr
10036 returns and sets the length return value to NULL_TREE. Otherwise
10037 generates code to evaluate the character expression, returns the proper
10038 pointer to the result, but does NOT set the length return value to a tree
10039 that specifies the length of the result. (In other words, the length
10040 variable is always set to NULL_TREE, because a length is never passed.)
10042 21-Dec-91 JCB 1.1
10043 Don't set returned length, since nobody needs it (yet; someday if
10044 we allow CHARACTER*(*) dummies to statement functions, we'll need
10045 it). */
10047 tree
10048 ffecom_arg_expr (ffebld expr, tree *length)
10050 tree ign;
10052 *length = NULL_TREE;
10054 if (expr == NULL)
10055 return integer_zero_node;
10057 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10058 return ffecom_expr (expr);
10060 return ffecom_arg_ptr_to_expr (expr, &ign);
10063 /* Transform expression into constant argument-pointer-to-expression tree.
10065 If the expression can be transformed into a argument-pointer-to-expression
10066 tree that is constant, that is done, and the tree returned. Else
10067 NULL_TREE is returned.
10069 That way, a caller can attempt to provide compile-time initialization
10070 of a variable and, if that fails, *then* choose to start a new block
10071 and resort to using temporaries, as appropriate. */
10073 tree
10074 ffecom_arg_ptr_to_const_expr (ffebld expr, tree *length)
10076 if (! expr)
10077 return integer_zero_node;
10079 if (ffebld_op (expr) == FFEBLD_opANY)
10081 if (length)
10082 *length = error_mark_node;
10083 return error_mark_node;
10086 if (ffebld_arity (expr) == 0
10087 && (ffebld_op (expr) != FFEBLD_opSYMTER
10088 || ffebld_where (expr) == FFEINFO_whereCOMMON
10089 || ffebld_where (expr) == FFEINFO_whereGLOBAL
10090 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
10092 tree t;
10094 t = ffecom_arg_ptr_to_expr (expr, length);
10095 assert (TREE_CONSTANT (t));
10096 assert (! length || TREE_CONSTANT (*length));
10097 return t;
10100 if (length
10101 && ffebld_size (expr) != FFETARGET_charactersizeNONE)
10102 *length = build_int_2 (ffebld_size (expr), 0);
10103 else if (length)
10104 *length = NULL_TREE;
10105 return NULL_TREE;
10108 /* ffecom_arg_ptr_to_expr -- Transform argument expr into gcc tree
10110 See use by ffecom_list_ptr_to_expr.
10112 If expression is NULL, returns an integer zero tree. If it is not
10113 a CHARACTER expression, returns whatever ffecom_ptr_to_expr
10114 returns and sets the length return value to NULL_TREE. Otherwise
10115 generates code to evaluate the character expression, returns the proper
10116 pointer to the result, AND sets the length return value to a tree that
10117 specifies the length of the result.
10119 If the length argument is NULL, this is a slightly special
10120 case of building a FORMAT expression, that is, an expression that
10121 will be used at run time without regard to length. For the current
10122 implementation, which uses the libf2c library, this means it is nice
10123 to append a null byte to the end of the expression, where feasible,
10124 to make sure any diagnostic about the FORMAT string terminates at
10125 some useful point.
10127 For now, treat %REF(char-expr) as the same as char-expr with a NULL
10128 length argument. This might even be seen as a feature, if a null
10129 byte can always be appended. */
10131 tree
10132 ffecom_arg_ptr_to_expr (ffebld expr, tree *length)
10134 tree item;
10135 tree ign_length;
10136 ffecomConcatList_ catlist;
10138 if (length != NULL)
10139 *length = NULL_TREE;
10141 if (expr == NULL)
10142 return integer_zero_node;
10144 switch (ffebld_op (expr))
10146 case FFEBLD_opPERCENT_VAL:
10147 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10148 return ffecom_expr (ffebld_left (expr));
10150 tree temp_exp;
10151 tree temp_length;
10153 temp_exp = ffecom_arg_ptr_to_expr (ffebld_left (expr), &temp_length);
10154 if (temp_exp == error_mark_node)
10155 return error_mark_node;
10157 return ffecom_1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (temp_exp)),
10158 temp_exp);
10161 case FFEBLD_opPERCENT_REF:
10162 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10163 return ffecom_ptr_to_expr (ffebld_left (expr));
10164 if (length != NULL)
10166 ign_length = NULL_TREE;
10167 length = &ign_length;
10169 expr = ffebld_left (expr);
10170 break;
10172 case FFEBLD_opPERCENT_DESCR:
10173 switch (ffeinfo_basictype (ffebld_info (expr)))
10175 #ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10176 case FFEINFO_basictypeHOLLERITH:
10177 #endif
10178 case FFEINFO_basictypeCHARACTER:
10179 break; /* Passed by descriptor anyway. */
10181 default:
10182 item = ffecom_ptr_to_expr (expr);
10183 if (item != error_mark_node)
10184 *length = TYPE_SIZE (TREE_TYPE (TREE_TYPE (item)));
10185 break;
10187 break;
10189 default:
10190 break;
10193 #ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10194 if ((ffeinfo_basictype (ffebld_info (expr)) == FFEINFO_basictypeHOLLERITH)
10195 && (length != NULL))
10196 { /* Pass Hollerith by descriptor. */
10197 ffetargetHollerith h;
10199 assert (ffebld_op (expr) == FFEBLD_opCONTER);
10200 h = ffebld_cu_val_hollerith (ffebld_constant_union
10201 (ffebld_conter (expr)));
10202 *length
10203 = build_int_2 (h.length, 0);
10204 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10206 #endif
10208 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10209 return ffecom_ptr_to_expr (expr);
10211 assert (ffeinfo_kindtype (ffebld_info (expr))
10212 == FFEINFO_kindtypeCHARACTER1);
10214 while (ffebld_op (expr) == FFEBLD_opPAREN)
10215 expr = ffebld_left (expr);
10217 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
10218 switch (ffecom_concat_list_count_ (catlist))
10220 case 0: /* Shouldn't happen, but in case it does... */
10221 if (length != NULL)
10223 *length = ffecom_f2c_ftnlen_zero_node;
10224 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10226 ffecom_concat_list_kill_ (catlist);
10227 return null_pointer_node;
10229 case 1: /* The (fairly) easy case. */
10230 if (length == NULL)
10231 ffecom_char_args_with_null_ (&item, &ign_length,
10232 ffecom_concat_list_expr_ (catlist, 0));
10233 else
10234 ffecom_char_args_ (&item, length,
10235 ffecom_concat_list_expr_ (catlist, 0));
10236 ffecom_concat_list_kill_ (catlist);
10237 assert (item != NULL_TREE);
10238 return item;
10240 default: /* Must actually concatenate things. */
10241 break;
10245 int count = ffecom_concat_list_count_ (catlist);
10246 int i;
10247 tree lengths;
10248 tree items;
10249 tree length_array;
10250 tree item_array;
10251 tree citem;
10252 tree clength;
10253 tree temporary;
10254 tree num;
10255 tree known_length;
10256 ffetargetCharacterSize sz;
10258 sz = ffecom_concat_list_maxlen_ (catlist);
10259 /* ~~Kludge! */
10260 assert (sz != FFETARGET_charactersizeNONE);
10262 #ifdef HOHO
10263 length_array
10264 = lengths
10265 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
10266 FFETARGET_charactersizeNONE, count, TRUE);
10267 item_array
10268 = items
10269 = ffecom_push_tempvar (ffecom_f2c_address_type_node,
10270 FFETARGET_charactersizeNONE, count, TRUE);
10271 temporary = ffecom_push_tempvar (char_type_node,
10272 sz, -1, TRUE);
10273 #else
10275 tree hook;
10277 hook = ffebld_nonter_hook (expr);
10278 assert (hook);
10279 assert (TREE_CODE (hook) == TREE_VEC);
10280 assert (TREE_VEC_LENGTH (hook) == 3);
10281 length_array = lengths = TREE_VEC_ELT (hook, 0);
10282 item_array = items = TREE_VEC_ELT (hook, 1);
10283 temporary = TREE_VEC_ELT (hook, 2);
10285 #endif
10287 known_length = ffecom_f2c_ftnlen_zero_node;
10289 for (i = 0; i < count; ++i)
10291 if ((i == count)
10292 && (length == NULL))
10293 ffecom_char_args_with_null_ (&citem, &clength,
10294 ffecom_concat_list_expr_ (catlist, i));
10295 else
10296 ffecom_char_args_ (&citem, &clength,
10297 ffecom_concat_list_expr_ (catlist, i));
10298 if ((citem == error_mark_node)
10299 || (clength == error_mark_node))
10301 ffecom_concat_list_kill_ (catlist);
10302 *length = error_mark_node;
10303 return error_mark_node;
10306 items
10307 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
10308 ffecom_modify (void_type_node,
10309 ffecom_2 (ARRAY_REF,
10310 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
10311 item_array,
10312 build_int_2 (i, 0)),
10313 citem),
10314 items);
10315 clength = ffecom_save_tree (clength);
10316 if (length != NULL)
10317 known_length
10318 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
10319 known_length,
10320 clength);
10321 lengths
10322 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
10323 ffecom_modify (void_type_node,
10324 ffecom_2 (ARRAY_REF,
10325 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
10326 length_array,
10327 build_int_2 (i, 0)),
10328 clength),
10329 lengths);
10332 temporary = ffecom_1 (ADDR_EXPR,
10333 build_pointer_type (TREE_TYPE (temporary)),
10334 temporary);
10336 item = build_tree_list (NULL_TREE, temporary);
10337 TREE_CHAIN (item)
10338 = build_tree_list (NULL_TREE,
10339 ffecom_1 (ADDR_EXPR,
10340 build_pointer_type (TREE_TYPE (items)),
10341 items));
10342 TREE_CHAIN (TREE_CHAIN (item))
10343 = build_tree_list (NULL_TREE,
10344 ffecom_1 (ADDR_EXPR,
10345 build_pointer_type (TREE_TYPE (lengths)),
10346 lengths));
10347 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
10348 = build_tree_list
10349 (NULL_TREE,
10350 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
10351 convert (ffecom_f2c_ftnlen_type_node,
10352 build_int_2 (count, 0))));
10353 num = build_int_2 (sz, 0);
10354 TREE_TYPE (num) = ffecom_f2c_ftnlen_type_node;
10355 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item))))
10356 = build_tree_list (NULL_TREE, num);
10358 item = ffecom_call_gfrt (FFECOM_gfrtCAT, item, NULL_TREE);
10359 TREE_SIDE_EFFECTS (item) = 1;
10360 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (temporary),
10361 item,
10362 temporary);
10364 if (length != NULL)
10365 *length = known_length;
10368 ffecom_concat_list_kill_ (catlist);
10369 assert (item != NULL_TREE);
10370 return item;
10373 /* Generate call to run-time function.
10375 The first arg is the GNU Fortran Run-Time function index, the second
10376 arg is the list of arguments to pass to it. Returned is the expression
10377 (WITHOUT TREE_SIDE_EFFECTS set!) that makes the call and returns the
10378 result (which may be void). */
10380 tree
10381 ffecom_call_gfrt (ffecomGfrt ix, tree args, tree hook)
10383 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
10384 ffecom_gfrt_kindtype (ix),
10385 ffe_is_f2c_library () && ffecom_gfrt_complex_[ix],
10386 NULL_TREE, args, NULL_TREE, NULL,
10387 NULL, NULL_TREE, TRUE, hook);
10390 /* Transform constant-union to tree. */
10392 tree
10393 ffecom_constantunion (ffebldConstantUnion *cu, ffeinfoBasictype bt,
10394 ffeinfoKindtype kt, tree tree_type)
10396 tree item;
10398 switch (bt)
10400 case FFEINFO_basictypeINTEGER:
10402 int val;
10404 switch (kt)
10406 #if FFETARGET_okINTEGER1
10407 case FFEINFO_kindtypeINTEGER1:
10408 val = ffebld_cu_val_integer1 (*cu);
10409 break;
10410 #endif
10412 #if FFETARGET_okINTEGER2
10413 case FFEINFO_kindtypeINTEGER2:
10414 val = ffebld_cu_val_integer2 (*cu);
10415 break;
10416 #endif
10418 #if FFETARGET_okINTEGER3
10419 case FFEINFO_kindtypeINTEGER3:
10420 val = ffebld_cu_val_integer3 (*cu);
10421 break;
10422 #endif
10424 #if FFETARGET_okINTEGER4
10425 case FFEINFO_kindtypeINTEGER4:
10426 val = ffebld_cu_val_integer4 (*cu);
10427 break;
10428 #endif
10430 default:
10431 assert ("bad INTEGER constant kind type" == NULL);
10432 /* Fall through. */
10433 case FFEINFO_kindtypeANY:
10434 return error_mark_node;
10436 item = build_int_2 (val, (val < 0) ? -1 : 0);
10437 TREE_TYPE (item) = tree_type;
10439 break;
10441 case FFEINFO_basictypeLOGICAL:
10443 int val;
10445 switch (kt)
10447 #if FFETARGET_okLOGICAL1
10448 case FFEINFO_kindtypeLOGICAL1:
10449 val = ffebld_cu_val_logical1 (*cu);
10450 break;
10451 #endif
10453 #if FFETARGET_okLOGICAL2
10454 case FFEINFO_kindtypeLOGICAL2:
10455 val = ffebld_cu_val_logical2 (*cu);
10456 break;
10457 #endif
10459 #if FFETARGET_okLOGICAL3
10460 case FFEINFO_kindtypeLOGICAL3:
10461 val = ffebld_cu_val_logical3 (*cu);
10462 break;
10463 #endif
10465 #if FFETARGET_okLOGICAL4
10466 case FFEINFO_kindtypeLOGICAL4:
10467 val = ffebld_cu_val_logical4 (*cu);
10468 break;
10469 #endif
10471 default:
10472 assert ("bad LOGICAL constant kind type" == NULL);
10473 /* Fall through. */
10474 case FFEINFO_kindtypeANY:
10475 return error_mark_node;
10477 item = build_int_2 (val, (val < 0) ? -1 : 0);
10478 TREE_TYPE (item) = tree_type;
10480 break;
10482 case FFEINFO_basictypeREAL:
10484 REAL_VALUE_TYPE val;
10486 switch (kt)
10488 #if FFETARGET_okREAL1
10489 case FFEINFO_kindtypeREAL1:
10490 val = ffetarget_value_real1 (ffebld_cu_val_real1 (*cu));
10491 break;
10492 #endif
10494 #if FFETARGET_okREAL2
10495 case FFEINFO_kindtypeREAL2:
10496 val = ffetarget_value_real2 (ffebld_cu_val_real2 (*cu));
10497 break;
10498 #endif
10500 #if FFETARGET_okREAL3
10501 case FFEINFO_kindtypeREAL3:
10502 val = ffetarget_value_real3 (ffebld_cu_val_real3 (*cu));
10503 break;
10504 #endif
10506 #if FFETARGET_okREAL4
10507 case FFEINFO_kindtypeREAL4:
10508 val = ffetarget_value_real4 (ffebld_cu_val_real4 (*cu));
10509 break;
10510 #endif
10512 default:
10513 assert ("bad REAL constant kind type" == NULL);
10514 /* Fall through. */
10515 case FFEINFO_kindtypeANY:
10516 return error_mark_node;
10518 item = build_real (tree_type, val);
10520 break;
10522 case FFEINFO_basictypeCOMPLEX:
10524 REAL_VALUE_TYPE real;
10525 REAL_VALUE_TYPE imag;
10526 tree el_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
10528 switch (kt)
10530 #if FFETARGET_okCOMPLEX1
10531 case FFEINFO_kindtypeREAL1:
10532 real = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).real);
10533 imag = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).imaginary);
10534 break;
10535 #endif
10537 #if FFETARGET_okCOMPLEX2
10538 case FFEINFO_kindtypeREAL2:
10539 real = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).real);
10540 imag = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).imaginary);
10541 break;
10542 #endif
10544 #if FFETARGET_okCOMPLEX3
10545 case FFEINFO_kindtypeREAL3:
10546 real = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).real);
10547 imag = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).imaginary);
10548 break;
10549 #endif
10551 #if FFETARGET_okCOMPLEX4
10552 case FFEINFO_kindtypeREAL4:
10553 real = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).real);
10554 imag = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).imaginary);
10555 break;
10556 #endif
10558 default:
10559 assert ("bad REAL constant kind type" == NULL);
10560 /* Fall through. */
10561 case FFEINFO_kindtypeANY:
10562 return error_mark_node;
10564 item = ffecom_build_complex_constant_ (tree_type,
10565 build_real (el_type, real),
10566 build_real (el_type, imag));
10568 break;
10570 case FFEINFO_basictypeCHARACTER:
10571 { /* Happens only in DATA and similar contexts. */
10572 ffetargetCharacter1 val;
10574 switch (kt)
10576 #if FFETARGET_okCHARACTER1
10577 case FFEINFO_kindtypeLOGICAL1:
10578 val = ffebld_cu_val_character1 (*cu);
10579 break;
10580 #endif
10582 default:
10583 assert ("bad CHARACTER constant kind type" == NULL);
10584 /* Fall through. */
10585 case FFEINFO_kindtypeANY:
10586 return error_mark_node;
10588 item = build_string (ffetarget_length_character1 (val),
10589 ffetarget_text_character1 (val));
10590 TREE_TYPE (item)
10591 = build_type_variant (build_array_type (char_type_node,
10592 build_range_type
10593 (integer_type_node,
10594 integer_one_node,
10595 build_int_2
10596 (ffetarget_length_character1
10597 (val), 0))),
10598 1, 0);
10600 break;
10602 case FFEINFO_basictypeHOLLERITH:
10604 ffetargetHollerith h;
10606 h = ffebld_cu_val_hollerith (*cu);
10608 /* If not at least as wide as default INTEGER, widen it. */
10609 if (h.length >= FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE)
10610 item = build_string (h.length, h.text);
10611 else
10613 char str[FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE];
10615 memcpy (str, h.text, h.length);
10616 memset (&str[h.length], ' ',
10617 FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE
10618 - h.length);
10619 item = build_string (FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE,
10620 str);
10622 TREE_TYPE (item)
10623 = build_type_variant (build_array_type (char_type_node,
10624 build_range_type
10625 (integer_type_node,
10626 integer_one_node,
10627 build_int_2
10628 (h.length, 0))),
10629 1, 0);
10631 break;
10633 case FFEINFO_basictypeTYPELESS:
10635 ffetargetInteger1 ival;
10636 ffetargetTypeless tless;
10637 ffebad error;
10639 tless = ffebld_cu_val_typeless (*cu);
10640 error = ffetarget_convert_integer1_typeless (&ival, tless);
10641 assert (error == FFEBAD);
10643 item = build_int_2 ((int) ival, 0);
10645 break;
10647 default:
10648 assert ("not yet on constant type" == NULL);
10649 /* Fall through. */
10650 case FFEINFO_basictypeANY:
10651 return error_mark_node;
10654 TREE_CONSTANT (item) = 1;
10656 return item;
10659 /* Transform expression into constant tree.
10661 If the expression can be transformed into a tree that is constant,
10662 that is done, and the tree returned. Else NULL_TREE is returned.
10664 That way, a caller can attempt to provide compile-time initialization
10665 of a variable and, if that fails, *then* choose to start a new block
10666 and resort to using temporaries, as appropriate. */
10668 tree
10669 ffecom_const_expr (ffebld expr)
10671 if (! expr)
10672 return integer_zero_node;
10674 if (ffebld_op (expr) == FFEBLD_opANY)
10675 return error_mark_node;
10677 if (ffebld_arity (expr) == 0
10678 && (ffebld_op (expr) != FFEBLD_opSYMTER
10679 #if NEWCOMMON
10680 /* ~~Enable once common/equivalence is handled properly? */
10681 || ffebld_where (expr) == FFEINFO_whereCOMMON
10682 #endif
10683 || ffebld_where (expr) == FFEINFO_whereGLOBAL
10684 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
10686 tree t;
10688 t = ffecom_expr (expr);
10689 assert (TREE_CONSTANT (t));
10690 return t;
10693 return NULL_TREE;
10696 /* Handy way to make a field in a struct/union. */
10698 tree
10699 ffecom_decl_field (tree context, tree prevfield,
10700 const char *name, tree type)
10702 tree field;
10704 field = build_decl (FIELD_DECL, get_identifier (name), type);
10705 DECL_CONTEXT (field) = context;
10706 DECL_ALIGN (field) = 0;
10707 DECL_USER_ALIGN (field) = 0;
10708 if (prevfield != NULL_TREE)
10709 TREE_CHAIN (prevfield) = field;
10711 return field;
10714 void
10715 ffecom_close_include (FILE *f)
10717 ffecom_close_include_ (f);
10721 ffecom_decode_include_option (char *spec)
10723 return ffecom_decode_include_option_ (spec);
10726 /* End a compound statement (block). */
10728 tree
10729 ffecom_end_compstmt (void)
10731 return bison_rule_compstmt_ ();
10734 /* ffecom_end_transition -- Perform end transition on all symbols
10736 ffecom_end_transition();
10738 Calls ffecom_sym_end_transition for each global and local symbol. */
10740 void
10741 ffecom_end_transition ()
10743 ffebld item;
10745 if (ffe_is_ffedebug ())
10746 fprintf (dmpout, "; end_stmt_transition\n");
10748 ffecom_list_blockdata_ = NULL;
10749 ffecom_list_common_ = NULL;
10751 ffesymbol_drive (ffecom_sym_end_transition);
10752 if (ffe_is_ffedebug ())
10754 ffestorag_report ();
10757 ffecom_start_progunit_ ();
10759 for (item = ffecom_list_blockdata_;
10760 item != NULL;
10761 item = ffebld_trail (item))
10763 ffebld callee;
10764 ffesymbol s;
10765 tree dt;
10766 tree t;
10767 tree var;
10768 static int number = 0;
10770 callee = ffebld_head (item);
10771 s = ffebld_symter (callee);
10772 t = ffesymbol_hook (s).decl_tree;
10773 if (t == NULL_TREE)
10775 s = ffecom_sym_transform_ (s);
10776 t = ffesymbol_hook (s).decl_tree;
10779 dt = build_pointer_type (TREE_TYPE (t));
10781 var = build_decl (VAR_DECL,
10782 ffecom_get_invented_identifier ("__g77_forceload_%d",
10783 number++),
10784 dt);
10785 DECL_EXTERNAL (var) = 0;
10786 TREE_STATIC (var) = 1;
10787 TREE_PUBLIC (var) = 0;
10788 DECL_INITIAL (var) = error_mark_node;
10789 TREE_USED (var) = 1;
10791 var = start_decl (var, FALSE);
10793 t = ffecom_1 (ADDR_EXPR, dt, t);
10795 finish_decl (var, t, FALSE);
10798 /* This handles any COMMON areas that weren't referenced but have, for
10799 example, important initial data. */
10801 for (item = ffecom_list_common_;
10802 item != NULL;
10803 item = ffebld_trail (item))
10804 ffecom_transform_common_ (ffebld_symter (ffebld_head (item)));
10806 ffecom_list_common_ = NULL;
10809 /* ffecom_exec_transition -- Perform exec transition on all symbols
10811 ffecom_exec_transition();
10813 Calls ffecom_sym_exec_transition for each global and local symbol.
10814 Make sure error updating not inhibited. */
10816 void
10817 ffecom_exec_transition ()
10819 bool inhibited;
10821 if (ffe_is_ffedebug ())
10822 fprintf (dmpout, "; exec_stmt_transition\n");
10824 inhibited = ffebad_inhibit ();
10825 ffebad_set_inhibit (FALSE);
10827 ffesymbol_drive (ffecom_sym_exec_transition); /* Don't retract! */
10828 ffeequiv_exec_transition (); /* Handle all pending EQUIVALENCEs. */
10829 if (ffe_is_ffedebug ())
10831 ffestorag_report ();
10834 if (inhibited)
10835 ffebad_set_inhibit (TRUE);
10838 /* Handle assignment statement.
10840 Convert dest and source using ffecom_expr, then join them
10841 with an ASSIGN op and pass the whole thing to expand_expr_stmt. */
10843 void
10844 ffecom_expand_let_stmt (ffebld dest, ffebld source)
10846 tree dest_tree;
10847 tree dest_length;
10848 tree source_tree;
10849 tree expr_tree;
10851 if (ffeinfo_basictype (ffebld_info (dest)) != FFEINFO_basictypeCHARACTER)
10853 bool dest_used;
10854 tree assign_temp;
10856 /* This attempts to replicate the test below, but must not be
10857 true when the test below is false. (Always err on the side
10858 of creating unused temporaries, to avoid ICEs.) */
10859 if (ffebld_op (dest) != FFEBLD_opSYMTER
10860 || ((dest_tree = ffesymbol_hook (ffebld_symter (dest)).decl_tree)
10861 && (TREE_CODE (dest_tree) != VAR_DECL
10862 || TREE_ADDRESSABLE (dest_tree))))
10864 ffecom_prepare_expr_ (source, dest);
10865 dest_used = TRUE;
10867 else
10869 ffecom_prepare_expr_ (source, NULL);
10870 dest_used = FALSE;
10873 ffecom_prepare_expr_w (NULL_TREE, dest);
10875 /* For COMPLEX assignment like C1=C2, if partial overlap is possible,
10876 create a temporary through which the assignment is to take place,
10877 since MODIFY_EXPR doesn't handle partial overlap properly. */
10878 if (ffebld_basictype (dest) == FFEINFO_basictypeCOMPLEX
10879 && ffecom_possible_partial_overlap_ (dest, source))
10881 assign_temp = ffecom_make_tempvar ("complex_let",
10882 ffecom_tree_type
10883 [ffebld_basictype (dest)]
10884 [ffebld_kindtype (dest)],
10885 FFETARGET_charactersizeNONE,
10886 -1);
10888 else
10889 assign_temp = NULL_TREE;
10891 ffecom_prepare_end ();
10893 dest_tree = ffecom_expr_w (NULL_TREE, dest);
10894 if (dest_tree == error_mark_node)
10895 return;
10897 if ((TREE_CODE (dest_tree) != VAR_DECL)
10898 || TREE_ADDRESSABLE (dest_tree))
10899 source_tree = ffecom_expr_ (source, dest_tree, dest, &dest_used,
10900 FALSE, FALSE);
10901 else
10903 assert (! dest_used);
10904 dest_used = FALSE;
10905 source_tree = ffecom_expr (source);
10907 if (source_tree == error_mark_node)
10908 return;
10910 if (dest_used)
10911 expr_tree = source_tree;
10912 else if (assign_temp)
10914 #ifdef MOVE_EXPR
10915 /* The back end understands a conceptual move (evaluate source;
10916 store into dest), so use that, in case it can determine
10917 that it is going to use, say, two registers as temporaries
10918 anyway. So don't use the temp (and someday avoid generating
10919 it, once this code starts triggering regularly). */
10920 expr_tree = ffecom_2s (MOVE_EXPR, void_type_node,
10921 dest_tree,
10922 source_tree);
10923 #else
10924 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
10925 assign_temp,
10926 source_tree);
10927 expand_expr_stmt (expr_tree);
10928 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
10929 dest_tree,
10930 assign_temp);
10931 #endif
10933 else
10934 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
10935 dest_tree,
10936 source_tree);
10938 expand_expr_stmt (expr_tree);
10939 return;
10942 ffecom_prepare_let_char_ (ffebld_size_known (dest), source);
10943 ffecom_prepare_expr_w (NULL_TREE, dest);
10945 ffecom_prepare_end ();
10947 ffecom_char_args_ (&dest_tree, &dest_length, dest);
10948 ffecom_let_char_ (dest_tree, dest_length, ffebld_size_known (dest),
10949 source);
10952 /* ffecom_expr -- Transform expr into gcc tree
10954 tree t;
10955 ffebld expr; // FFE expression.
10956 tree = ffecom_expr(expr);
10958 Recursive descent on expr while making corresponding tree nodes and
10959 attaching type info and such. */
10961 tree
10962 ffecom_expr (ffebld expr)
10964 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, FALSE, FALSE);
10967 /* Like ffecom_expr, but return tree usable for assigned GOTO or FORMAT. */
10969 tree
10970 ffecom_expr_assign (ffebld expr)
10972 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
10975 /* Like ffecom_expr_rw, but return tree usable for ASSIGN. */
10977 tree
10978 ffecom_expr_assign_w (ffebld expr)
10980 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
10983 /* Transform expr for use as into read/write tree and stabilize the
10984 reference. Not for use on CHARACTER expressions.
10986 Recursive descent on expr while making corresponding tree nodes and
10987 attaching type info and such. */
10989 tree
10990 ffecom_expr_rw (tree type, ffebld expr)
10992 assert (expr != NULL);
10993 /* Different target types not yet supported. */
10994 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
10996 return stabilize_reference (ffecom_expr (expr));
10999 /* Transform expr for use as into write tree and stabilize the
11000 reference. Not for use on CHARACTER expressions.
11002 Recursive descent on expr while making corresponding tree nodes and
11003 attaching type info and such. */
11005 tree
11006 ffecom_expr_w (tree type, ffebld expr)
11008 assert (expr != NULL);
11009 /* Different target types not yet supported. */
11010 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
11012 return stabilize_reference (ffecom_expr (expr));
11015 /* Do global stuff. */
11017 void
11018 ffecom_finish_compile ()
11020 assert (ffecom_outer_function_decl_ == NULL_TREE);
11021 assert (current_function_decl == NULL_TREE);
11023 ffeglobal_drive (ffecom_finish_global_);
11026 /* Public entry point for front end to access finish_decl. */
11028 void
11029 ffecom_finish_decl (tree decl, tree init, bool is_top_level)
11031 assert (!is_top_level);
11032 finish_decl (decl, init, FALSE);
11035 /* Finish a program unit. */
11037 void
11038 ffecom_finish_progunit ()
11040 ffecom_end_compstmt ();
11042 ffecom_previous_function_decl_ = current_function_decl;
11043 ffecom_which_entrypoint_decl_ = NULL_TREE;
11045 finish_function (0);
11048 /* Wrapper for get_identifier. pattern is sprintf-like. */
11050 tree
11051 ffecom_get_invented_identifier (const char *pattern, ...)
11053 tree decl;
11054 char *nam;
11055 va_list ap;
11057 va_start (ap, pattern);
11058 if (vasprintf (&nam, pattern, ap) == 0)
11059 abort ();
11060 va_end (ap);
11061 decl = get_identifier (nam);
11062 free (nam);
11063 IDENTIFIER_INVENTED (decl) = 1;
11064 return decl;
11067 ffeinfoBasictype
11068 ffecom_gfrt_basictype (ffecomGfrt gfrt)
11070 assert (gfrt < FFECOM_gfrt);
11072 switch (ffecom_gfrt_type_[gfrt])
11074 case FFECOM_rttypeVOID_:
11075 case FFECOM_rttypeVOIDSTAR_:
11076 return FFEINFO_basictypeNONE;
11078 case FFECOM_rttypeFTNINT_:
11079 return FFEINFO_basictypeINTEGER;
11081 case FFECOM_rttypeINTEGER_:
11082 return FFEINFO_basictypeINTEGER;
11084 case FFECOM_rttypeLONGINT_:
11085 return FFEINFO_basictypeINTEGER;
11087 case FFECOM_rttypeLOGICAL_:
11088 return FFEINFO_basictypeLOGICAL;
11090 case FFECOM_rttypeREAL_F2C_:
11091 case FFECOM_rttypeREAL_GNU_:
11092 return FFEINFO_basictypeREAL;
11094 case FFECOM_rttypeCOMPLEX_F2C_:
11095 case FFECOM_rttypeCOMPLEX_GNU_:
11096 return FFEINFO_basictypeCOMPLEX;
11098 case FFECOM_rttypeDOUBLE_:
11099 case FFECOM_rttypeDOUBLEREAL_:
11100 return FFEINFO_basictypeREAL;
11102 case FFECOM_rttypeDBLCMPLX_F2C_:
11103 case FFECOM_rttypeDBLCMPLX_GNU_:
11104 return FFEINFO_basictypeCOMPLEX;
11106 case FFECOM_rttypeCHARACTER_:
11107 return FFEINFO_basictypeCHARACTER;
11109 default:
11110 return FFEINFO_basictypeANY;
11114 ffeinfoKindtype
11115 ffecom_gfrt_kindtype (ffecomGfrt gfrt)
11117 assert (gfrt < FFECOM_gfrt);
11119 switch (ffecom_gfrt_type_[gfrt])
11121 case FFECOM_rttypeVOID_:
11122 case FFECOM_rttypeVOIDSTAR_:
11123 return FFEINFO_kindtypeNONE;
11125 case FFECOM_rttypeFTNINT_:
11126 return FFEINFO_kindtypeINTEGER1;
11128 case FFECOM_rttypeINTEGER_:
11129 return FFEINFO_kindtypeINTEGER1;
11131 case FFECOM_rttypeLONGINT_:
11132 return FFEINFO_kindtypeINTEGER4;
11134 case FFECOM_rttypeLOGICAL_:
11135 return FFEINFO_kindtypeLOGICAL1;
11137 case FFECOM_rttypeREAL_F2C_:
11138 case FFECOM_rttypeREAL_GNU_:
11139 return FFEINFO_kindtypeREAL1;
11141 case FFECOM_rttypeCOMPLEX_F2C_:
11142 case FFECOM_rttypeCOMPLEX_GNU_:
11143 return FFEINFO_kindtypeREAL1;
11145 case FFECOM_rttypeDOUBLE_:
11146 case FFECOM_rttypeDOUBLEREAL_:
11147 return FFEINFO_kindtypeREAL2;
11149 case FFECOM_rttypeDBLCMPLX_F2C_:
11150 case FFECOM_rttypeDBLCMPLX_GNU_:
11151 return FFEINFO_kindtypeREAL2;
11153 case FFECOM_rttypeCHARACTER_:
11154 return FFEINFO_kindtypeCHARACTER1;
11156 default:
11157 return FFEINFO_kindtypeANY;
11161 void
11162 ffecom_init_0 ()
11164 tree endlink;
11165 int i;
11166 int j;
11167 tree t;
11168 tree field;
11169 ffetype type;
11170 ffetype base_type;
11171 tree double_ftype_double;
11172 tree float_ftype_float;
11173 tree ldouble_ftype_ldouble;
11174 tree ffecom_tree_ptr_to_fun_type_void;
11176 /* This block of code comes from the now-obsolete cktyps.c. It checks
11177 whether the compiler environment is buggy in known ways, some of which
11178 would, if not explicitly checked here, result in subtle bugs in g77. */
11180 if (ffe_is_do_internal_checks ())
11182 static const char names[][12]
11184 {"bar", "bletch", "foo", "foobar"};
11185 const char *name;
11186 unsigned long ul;
11187 double fl;
11189 name = bsearch ("foo", &names[0], ARRAY_SIZE (names), sizeof (names[0]),
11190 (int (*)(const void *, const void *)) strcmp);
11191 if (name != &names[0][2])
11193 assert ("bsearch doesn't work, #define FFEPROJ_BSEARCH 0 in proj.h"
11194 == NULL);
11195 abort ();
11198 ul = strtoul ("123456789", NULL, 10);
11199 if (ul != 123456789L)
11201 assert ("strtoul doesn't have enough range, #define FFEPROJ_STRTOUL 0\
11202 in proj.h" == NULL);
11203 abort ();
11206 fl = atof ("56.789");
11207 if ((fl < 56.788) || (fl > 56.79))
11209 assert ("atof not type double, fix your #include <stdio.h>"
11210 == NULL);
11211 abort ();
11215 ffecom_outer_function_decl_ = NULL_TREE;
11216 current_function_decl = NULL_TREE;
11217 named_labels = NULL_TREE;
11218 current_binding_level = NULL_BINDING_LEVEL;
11219 free_binding_level = NULL_BINDING_LEVEL;
11220 /* Make the binding_level structure for global names. */
11221 pushlevel (0);
11222 global_binding_level = current_binding_level;
11223 current_binding_level->prep_state = 2;
11225 build_common_tree_nodes (1);
11227 /* Define `int' and `char' first so that dbx will output them first. */
11228 pushdecl (build_decl (TYPE_DECL, get_identifier ("int"),
11229 integer_type_node));
11230 /* CHARACTER*1 is unsigned in ICHAR contexts. */
11231 char_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
11232 pushdecl (build_decl (TYPE_DECL, get_identifier ("char"),
11233 char_type_node));
11234 pushdecl (build_decl (TYPE_DECL, get_identifier ("long int"),
11235 long_integer_type_node));
11236 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned int"),
11237 unsigned_type_node));
11238 pushdecl (build_decl (TYPE_DECL, get_identifier ("long unsigned int"),
11239 long_unsigned_type_node));
11240 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long int"),
11241 long_long_integer_type_node));
11242 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"),
11243 long_long_unsigned_type_node));
11244 pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"),
11245 short_integer_type_node));
11246 pushdecl (build_decl (TYPE_DECL, get_identifier ("short unsigned int"),
11247 short_unsigned_type_node));
11249 /* Set the sizetype before we make other types. This *should* be the
11250 first type we create. */
11252 set_sizetype
11253 (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))));
11254 ffecom_typesize_pointer_
11255 = TREE_INT_CST_LOW (TYPE_SIZE (sizetype)) / BITS_PER_UNIT;
11257 build_common_tree_nodes_2 (0);
11259 /* Define both `signed char' and `unsigned char'. */
11260 pushdecl (build_decl (TYPE_DECL, get_identifier ("signed char"),
11261 signed_char_type_node));
11263 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned char"),
11264 unsigned_char_type_node));
11266 pushdecl (build_decl (TYPE_DECL, get_identifier ("float"),
11267 float_type_node));
11268 pushdecl (build_decl (TYPE_DECL, get_identifier ("double"),
11269 double_type_node));
11270 pushdecl (build_decl (TYPE_DECL, get_identifier ("long double"),
11271 long_double_type_node));
11273 /* For now, override what build_common_tree_nodes has done. */
11274 complex_integer_type_node = ffecom_make_complex_type_ (integer_type_node);
11275 complex_float_type_node = ffecom_make_complex_type_ (float_type_node);
11276 complex_double_type_node = ffecom_make_complex_type_ (double_type_node);
11277 complex_long_double_type_node
11278 = ffecom_make_complex_type_ (long_double_type_node);
11280 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"),
11281 complex_integer_type_node));
11282 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"),
11283 complex_float_type_node));
11284 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"),
11285 complex_double_type_node));
11286 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"),
11287 complex_long_double_type_node));
11289 pushdecl (build_decl (TYPE_DECL, get_identifier ("void"),
11290 void_type_node));
11291 /* We are not going to have real types in C with less than byte alignment,
11292 so we might as well not have any types that claim to have it. */
11293 TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
11294 TYPE_USER_ALIGN (void_type_node) = 0;
11296 string_type_node = build_pointer_type (char_type_node);
11298 ffecom_tree_fun_type_void
11299 = build_function_type (void_type_node, NULL_TREE);
11301 ffecom_tree_ptr_to_fun_type_void
11302 = build_pointer_type (ffecom_tree_fun_type_void);
11304 endlink = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
11306 float_ftype_float
11307 = build_function_type (float_type_node,
11308 tree_cons (NULL_TREE, float_type_node, endlink));
11310 double_ftype_double
11311 = build_function_type (double_type_node,
11312 tree_cons (NULL_TREE, double_type_node, endlink));
11314 ldouble_ftype_ldouble
11315 = build_function_type (long_double_type_node,
11316 tree_cons (NULL_TREE, long_double_type_node,
11317 endlink));
11319 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11320 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11322 ffecom_tree_type[i][j] = NULL_TREE;
11323 ffecom_tree_fun_type[i][j] = NULL_TREE;
11324 ffecom_tree_ptr_to_fun_type[i][j] = NULL_TREE;
11325 ffecom_f2c_typecode_[i][j] = -1;
11328 /* Set up standard g77 types. Note that INTEGER and LOGICAL are set
11329 to size FLOAT_TYPE_SIZE because they have to be the same size as
11330 REAL, which also is FLOAT_TYPE_SIZE, according to the standard.
11331 Compiler options and other such stuff that change the ways these
11332 types are set should not affect this particular setup. */
11334 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1]
11335 = t = make_signed_type (FLOAT_TYPE_SIZE);
11336 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer"),
11337 t));
11338 type = ffetype_new ();
11339 base_type = type;
11340 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER1,
11341 type);
11342 ffetype_set_ams (type,
11343 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11344 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11345 ffetype_set_star (base_type,
11346 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11347 type);
11348 ffetype_set_kind (base_type, 1, type);
11349 ffecom_typesize_integer1_ = ffetype_size (type);
11350 assert (ffetype_size (type) == sizeof (ffetargetInteger1));
11352 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER1]
11353 = t = make_unsigned_type (FLOAT_TYPE_SIZE); /* HOLLERITH means unsigned. */
11354 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned"),
11355 t));
11357 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER2]
11358 = t = make_signed_type (CHAR_TYPE_SIZE);
11359 pushdecl (build_decl (TYPE_DECL, get_identifier ("byte"),
11360 t));
11361 type = ffetype_new ();
11362 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER2,
11363 type);
11364 ffetype_set_ams (type,
11365 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11366 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11367 ffetype_set_star (base_type,
11368 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11369 type);
11370 ffetype_set_kind (base_type, 3, type);
11371 assert (ffetype_size (type) == sizeof (ffetargetInteger2));
11373 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER2]
11374 = t = make_unsigned_type (CHAR_TYPE_SIZE);
11375 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned byte"),
11376 t));
11378 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER3]
11379 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11380 pushdecl (build_decl (TYPE_DECL, get_identifier ("word"),
11381 t));
11382 type = ffetype_new ();
11383 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER3,
11384 type);
11385 ffetype_set_ams (type,
11386 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11387 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11388 ffetype_set_star (base_type,
11389 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11390 type);
11391 ffetype_set_kind (base_type, 6, type);
11392 assert (ffetype_size (type) == sizeof (ffetargetInteger3));
11394 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER3]
11395 = t = make_unsigned_type (CHAR_TYPE_SIZE * 2);
11396 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned word"),
11397 t));
11399 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER4]
11400 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11401 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer4"),
11402 t));
11403 type = ffetype_new ();
11404 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER4,
11405 type);
11406 ffetype_set_ams (type,
11407 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11408 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11409 ffetype_set_star (base_type,
11410 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11411 type);
11412 ffetype_set_kind (base_type, 2, type);
11413 assert (ffetype_size (type) == sizeof (ffetargetInteger4));
11415 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER4]
11416 = t = make_unsigned_type (FLOAT_TYPE_SIZE * 2);
11417 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned4"),
11418 t));
11420 #if 0
11421 if (ffe_is_do_internal_checks ()
11422 && LONG_TYPE_SIZE != FLOAT_TYPE_SIZE
11423 && LONG_TYPE_SIZE != CHAR_TYPE_SIZE
11424 && LONG_TYPE_SIZE != SHORT_TYPE_SIZE
11425 && LONG_TYPE_SIZE != LONG_LONG_TYPE_SIZE)
11427 fprintf (stderr, "Sorry, no g77 support for LONG_TYPE_SIZE (%d bits) yet.\n",
11428 LONG_TYPE_SIZE);
11430 #endif
11432 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL1]
11433 = t = make_signed_type (FLOAT_TYPE_SIZE);
11434 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical"),
11435 t));
11436 type = ffetype_new ();
11437 base_type = type;
11438 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL1,
11439 type);
11440 ffetype_set_ams (type,
11441 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11442 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11443 ffetype_set_star (base_type,
11444 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11445 type);
11446 ffetype_set_kind (base_type, 1, type);
11447 assert (ffetype_size (type) == sizeof (ffetargetLogical1));
11449 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL2]
11450 = t = make_signed_type (CHAR_TYPE_SIZE);
11451 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical2"),
11452 t));
11453 type = ffetype_new ();
11454 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL2,
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, 3, type);
11463 assert (ffetype_size (type) == sizeof (ffetargetLogical2));
11465 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL3]
11466 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11467 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical3"),
11468 t));
11469 type = ffetype_new ();
11470 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL3,
11471 type);
11472 ffetype_set_ams (type,
11473 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11474 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11475 ffetype_set_star (base_type,
11476 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11477 type);
11478 ffetype_set_kind (base_type, 6, type);
11479 assert (ffetype_size (type) == sizeof (ffetargetLogical3));
11481 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL4]
11482 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11483 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical4"),
11484 t));
11485 type = ffetype_new ();
11486 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL4,
11487 type);
11488 ffetype_set_ams (type,
11489 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11490 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11491 ffetype_set_star (base_type,
11492 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11493 type);
11494 ffetype_set_kind (base_type, 2, type);
11495 assert (ffetype_size (type) == sizeof (ffetargetLogical4));
11497 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
11498 = t = make_node (REAL_TYPE);
11499 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE;
11500 pushdecl (build_decl (TYPE_DECL, get_identifier ("real"),
11501 t));
11502 layout_type (t);
11503 type = ffetype_new ();
11504 base_type = type;
11505 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREAL1,
11506 type);
11507 ffetype_set_ams (type,
11508 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11509 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11510 ffetype_set_star (base_type,
11511 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11512 type);
11513 ffetype_set_kind (base_type, 1, type);
11514 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
11515 = FFETARGET_f2cTYREAL;
11516 assert (ffetype_size (type) == sizeof (ffetargetReal1));
11518 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREALDOUBLE]
11519 = t = make_node (REAL_TYPE);
11520 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE * 2; /* Always twice REAL. */
11521 pushdecl (build_decl (TYPE_DECL, get_identifier ("double precision"),
11522 t));
11523 layout_type (t);
11524 type = ffetype_new ();
11525 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREALDOUBLE,
11526 type);
11527 ffetype_set_ams (type,
11528 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11529 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11530 ffetype_set_star (base_type,
11531 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11532 type);
11533 ffetype_set_kind (base_type, 2, type);
11534 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]
11535 = FFETARGET_f2cTYDREAL;
11536 assert (ffetype_size (type) == sizeof (ffetargetReal2));
11538 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
11539 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]);
11540 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex"),
11541 t));
11542 type = ffetype_new ();
11543 base_type = type;
11544 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREAL1,
11545 type);
11546 ffetype_set_ams (type,
11547 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11548 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11549 ffetype_set_star (base_type,
11550 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11551 type);
11552 ffetype_set_kind (base_type, 1, type);
11553 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
11554 = FFETARGET_f2cTYCOMPLEX;
11555 assert (ffetype_size (type) == sizeof (ffetargetComplex1));
11557 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREALDOUBLE]
11558 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]);
11559 pushdecl (build_decl (TYPE_DECL, get_identifier ("double complex"),
11560 t));
11561 type = ffetype_new ();
11562 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREALDOUBLE,
11563 type);
11564 ffetype_set_ams (type,
11565 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11566 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11567 ffetype_set_star (base_type,
11568 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11569 type);
11570 ffetype_set_kind (base_type, 2,
11571 type);
11572 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL2]
11573 = FFETARGET_f2cTYDCOMPLEX;
11574 assert (ffetype_size (type) == sizeof (ffetargetComplex2));
11576 /* Make function and ptr-to-function types for non-CHARACTER types. */
11578 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11579 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11581 if ((t = ffecom_tree_type[i][j]) != NULL_TREE)
11583 if (i == FFEINFO_basictypeINTEGER)
11585 /* Figure out the smallest INTEGER type that can hold
11586 a pointer on this machine. */
11587 if (GET_MODE_SIZE (TYPE_MODE (t))
11588 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
11590 if ((ffecom_pointer_kind_ == FFEINFO_kindtypeNONE)
11591 || (GET_MODE_SIZE (TYPE_MODE (ffecom_tree_type[i][ffecom_pointer_kind_]))
11592 > GET_MODE_SIZE (TYPE_MODE (t))))
11593 ffecom_pointer_kind_ = j;
11596 else if (i == FFEINFO_basictypeCOMPLEX)
11597 t = void_type_node;
11598 /* For f2c compatibility, REAL functions are really
11599 implemented as DOUBLE PRECISION. */
11600 else if ((i == FFEINFO_basictypeREAL)
11601 && (j == FFEINFO_kindtypeREAL1))
11602 t = ffecom_tree_type
11603 [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2];
11605 t = ffecom_tree_fun_type[i][j] = build_function_type (t,
11606 NULL_TREE);
11607 ffecom_tree_ptr_to_fun_type[i][j] = build_pointer_type (t);
11611 /* Set up pointer types. */
11613 if (ffecom_pointer_kind_ == FFEINFO_basictypeNONE)
11614 fatal_error ("no INTEGER type can hold a pointer on this configuration");
11615 else if (0 && ffe_is_do_internal_checks ())
11616 fprintf (stderr, "Pointer type kt=%d\n", ffecom_pointer_kind_);
11617 ffetype_set_kind (ffeinfo_type (FFEINFO_basictypeINTEGER,
11618 FFEINFO_kindtypeINTEGERDEFAULT),
11620 ffeinfo_type (FFEINFO_basictypeINTEGER,
11621 ffecom_pointer_kind_));
11623 if (ffe_is_ugly_assign ())
11624 ffecom_label_kind_ = ffecom_pointer_kind_; /* Require ASSIGN etc to this. */
11625 else
11626 ffecom_label_kind_ = FFEINFO_kindtypeINTEGERDEFAULT;
11627 if (0 && ffe_is_do_internal_checks ())
11628 fprintf (stderr, "Label type kt=%d\n", ffecom_label_kind_);
11630 ffecom_integer_type_node
11631 = ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1];
11632 ffecom_integer_zero_node = convert (ffecom_integer_type_node,
11633 integer_zero_node);
11634 ffecom_integer_one_node = convert (ffecom_integer_type_node,
11635 integer_one_node);
11637 /* Yes, the "FLOAT_TYPE_SIZE" references below are intentional.
11638 Turns out that by TYLONG, runtime/libI77/lio.h really means
11639 "whatever size an ftnint is". For consistency and sanity,
11640 com.h and runtime/f2c.h.in agree that flag, ftnint, and ftlen
11641 all are INTEGER, which we also make out of whatever back-end
11642 integer type is FLOAT_TYPE_SIZE bits wide. This change, from
11643 LONG_TYPE_SIZE, for TYLONG and TYLOGICAL, was necessary to
11644 accommodate machines like the Alpha. Note that this suggests
11645 f2c and libf2c are missing a distinction perhaps needed on
11646 some machines between "int" and "long int". -- burley 0.5.5 950215 */
11648 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, FLOAT_TYPE_SIZE,
11649 FFETARGET_f2cTYLONG);
11650 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, SHORT_TYPE_SIZE,
11651 FFETARGET_f2cTYSHORT);
11652 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, CHAR_TYPE_SIZE,
11653 FFETARGET_f2cTYINT1);
11654 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, LONG_LONG_TYPE_SIZE,
11655 FFETARGET_f2cTYQUAD);
11656 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, FLOAT_TYPE_SIZE,
11657 FFETARGET_f2cTYLOGICAL);
11658 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, SHORT_TYPE_SIZE,
11659 FFETARGET_f2cTYLOGICAL2);
11660 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, CHAR_TYPE_SIZE,
11661 FFETARGET_f2cTYLOGICAL1);
11662 /* ~~~Not really such a type in libf2c, e.g. I/O support? */
11663 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, LONG_LONG_TYPE_SIZE,
11664 FFETARGET_f2cTYQUAD);
11666 /* CHARACTER stuff is all special-cased, so it is not handled in the above
11667 loop. CHARACTER items are built as arrays of unsigned char. */
11669 ffecom_tree_type[FFEINFO_basictypeCHARACTER]
11670 [FFEINFO_kindtypeCHARACTER1] = t = char_type_node;
11671 type = ffetype_new ();
11672 base_type = type;
11673 ffeinfo_set_type (FFEINFO_basictypeCHARACTER,
11674 FFEINFO_kindtypeCHARACTER1,
11675 type);
11676 ffetype_set_ams (type,
11677 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11678 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11679 ffetype_set_kind (base_type, 1, type);
11680 assert (ffetype_size (type)
11681 == sizeof (((ffetargetCharacter1) { 0, NULL }).text[0]));
11683 ffecom_tree_fun_type[FFEINFO_basictypeCHARACTER]
11684 [FFEINFO_kindtypeCHARACTER1] = ffecom_tree_fun_type_void;
11685 ffecom_tree_ptr_to_fun_type[FFEINFO_basictypeCHARACTER]
11686 [FFEINFO_kindtypeCHARACTER1]
11687 = ffecom_tree_ptr_to_fun_type_void;
11688 ffecom_f2c_typecode_[FFEINFO_basictypeCHARACTER][FFEINFO_kindtypeCHARACTER1]
11689 = FFETARGET_f2cTYCHAR;
11691 ffecom_f2c_typecode_[FFEINFO_basictypeANY][FFEINFO_kindtypeANY]
11692 = 0;
11694 /* Make multi-return-value type and fields. */
11696 ffecom_multi_type_node_ = make_node (UNION_TYPE);
11698 field = NULL_TREE;
11700 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11701 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11703 char name[30];
11705 if (ffecom_tree_type[i][j] == NULL_TREE)
11706 continue; /* Not supported. */
11707 sprintf (&name[0], "bt_%s_kt_%s",
11708 ffeinfo_basictype_string ((ffeinfoBasictype) i),
11709 ffeinfo_kindtype_string ((ffeinfoKindtype) j));
11710 ffecom_multi_fields_[i][j] = build_decl (FIELD_DECL,
11711 get_identifier (name),
11712 ffecom_tree_type[i][j]);
11713 DECL_CONTEXT (ffecom_multi_fields_[i][j])
11714 = ffecom_multi_type_node_;
11715 DECL_ALIGN (ffecom_multi_fields_[i][j]) = 0;
11716 DECL_USER_ALIGN (ffecom_multi_fields_[i][j]) = 0;
11717 TREE_CHAIN (ffecom_multi_fields_[i][j]) = field;
11718 field = ffecom_multi_fields_[i][j];
11721 TYPE_FIELDS (ffecom_multi_type_node_) = field;
11722 layout_type (ffecom_multi_type_node_);
11724 /* Subroutines usually return integer because they might have alternate
11725 returns. */
11727 ffecom_tree_subr_type
11728 = build_function_type (integer_type_node, NULL_TREE);
11729 ffecom_tree_ptr_to_subr_type
11730 = build_pointer_type (ffecom_tree_subr_type);
11731 ffecom_tree_blockdata_type
11732 = build_function_type (void_type_node, NULL_TREE);
11734 builtin_function ("__builtin_sqrtf", float_ftype_float,
11735 BUILT_IN_SQRTF, BUILT_IN_NORMAL, "sqrtf");
11736 builtin_function ("__builtin_sqrt", double_ftype_double,
11737 BUILT_IN_SQRT, BUILT_IN_NORMAL, "sqrt");
11738 builtin_function ("__builtin_sqrtl", ldouble_ftype_ldouble,
11739 BUILT_IN_SQRTL, BUILT_IN_NORMAL, "sqrtl");
11740 builtin_function ("__builtin_sinf", float_ftype_float,
11741 BUILT_IN_SINF, BUILT_IN_NORMAL, "sinf");
11742 builtin_function ("__builtin_sin", double_ftype_double,
11743 BUILT_IN_SIN, BUILT_IN_NORMAL, "sin");
11744 builtin_function ("__builtin_sinl", ldouble_ftype_ldouble,
11745 BUILT_IN_SINL, BUILT_IN_NORMAL, "sinl");
11746 builtin_function ("__builtin_cosf", float_ftype_float,
11747 BUILT_IN_COSF, BUILT_IN_NORMAL, "cosf");
11748 builtin_function ("__builtin_cos", double_ftype_double,
11749 BUILT_IN_COS, BUILT_IN_NORMAL, "cos");
11750 builtin_function ("__builtin_cosl", ldouble_ftype_ldouble,
11751 BUILT_IN_COSL, BUILT_IN_NORMAL, "cosl");
11753 pedantic_lvalues = FALSE;
11755 ffecom_f2c_make_type_ (&ffecom_f2c_integer_type_node,
11756 FFECOM_f2cINTEGER,
11757 "integer");
11758 ffecom_f2c_make_type_ (&ffecom_f2c_address_type_node,
11759 FFECOM_f2cADDRESS,
11760 "address");
11761 ffecom_f2c_make_type_ (&ffecom_f2c_real_type_node,
11762 FFECOM_f2cREAL,
11763 "real");
11764 ffecom_f2c_make_type_ (&ffecom_f2c_doublereal_type_node,
11765 FFECOM_f2cDOUBLEREAL,
11766 "doublereal");
11767 ffecom_f2c_make_type_ (&ffecom_f2c_complex_type_node,
11768 FFECOM_f2cCOMPLEX,
11769 "complex");
11770 ffecom_f2c_make_type_ (&ffecom_f2c_doublecomplex_type_node,
11771 FFECOM_f2cDOUBLECOMPLEX,
11772 "doublecomplex");
11773 ffecom_f2c_make_type_ (&ffecom_f2c_longint_type_node,
11774 FFECOM_f2cLONGINT,
11775 "longint");
11776 ffecom_f2c_make_type_ (&ffecom_f2c_logical_type_node,
11777 FFECOM_f2cLOGICAL,
11778 "logical");
11779 ffecom_f2c_make_type_ (&ffecom_f2c_flag_type_node,
11780 FFECOM_f2cFLAG,
11781 "flag");
11782 ffecom_f2c_make_type_ (&ffecom_f2c_ftnlen_type_node,
11783 FFECOM_f2cFTNLEN,
11784 "ftnlen");
11785 ffecom_f2c_make_type_ (&ffecom_f2c_ftnint_type_node,
11786 FFECOM_f2cFTNINT,
11787 "ftnint");
11789 ffecom_f2c_ftnlen_zero_node
11790 = convert (ffecom_f2c_ftnlen_type_node, integer_zero_node);
11792 ffecom_f2c_ftnlen_one_node
11793 = convert (ffecom_f2c_ftnlen_type_node, integer_one_node);
11795 ffecom_f2c_ftnlen_two_node = build_int_2 (2, 0);
11796 TREE_TYPE (ffecom_f2c_ftnlen_two_node) = ffecom_integer_type_node;
11798 ffecom_f2c_ptr_to_ftnlen_type_node
11799 = build_pointer_type (ffecom_f2c_ftnlen_type_node);
11801 ffecom_f2c_ptr_to_ftnint_type_node
11802 = build_pointer_type (ffecom_f2c_ftnint_type_node);
11804 ffecom_f2c_ptr_to_integer_type_node
11805 = build_pointer_type (ffecom_f2c_integer_type_node);
11807 ffecom_f2c_ptr_to_real_type_node
11808 = build_pointer_type (ffecom_f2c_real_type_node);
11810 ffecom_float_zero_ = build_real (float_type_node, dconst0);
11811 ffecom_double_zero_ = build_real (double_type_node, dconst0);
11813 REAL_VALUE_TYPE point_5;
11815 REAL_ARITHMETIC (point_5, RDIV_EXPR, dconst1, dconst2);
11816 ffecom_float_half_ = build_real (float_type_node, point_5);
11817 ffecom_double_half_ = build_real (double_type_node, point_5);
11820 /* Do "extern int xargc;". */
11822 ffecom_tree_xargc_ = build_decl (VAR_DECL,
11823 get_identifier ("f__xargc"),
11824 integer_type_node);
11825 DECL_EXTERNAL (ffecom_tree_xargc_) = 1;
11826 TREE_STATIC (ffecom_tree_xargc_) = 1;
11827 TREE_PUBLIC (ffecom_tree_xargc_) = 1;
11828 ffecom_tree_xargc_ = start_decl (ffecom_tree_xargc_, FALSE);
11829 finish_decl (ffecom_tree_xargc_, NULL_TREE, FALSE);
11831 #if 0 /* This is being fixed, and seems to be working now. */
11832 if ((FLOAT_TYPE_SIZE != 32)
11833 || (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))) != 32))
11835 warning ("configuration: REAL, INTEGER, and LOGICAL are %d bits wide,",
11836 (int) FLOAT_TYPE_SIZE);
11837 warning ("and pointers are %d bits wide, but g77 doesn't yet work",
11838 (int) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))));
11839 warning ("properly unless they all are 32 bits wide");
11840 warning ("Please keep this in mind before you report bugs.");
11842 #endif
11844 #if 0 /* Code in ste.c that would crash has been commented out. */
11845 if (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
11846 < TYPE_PRECISION (string_type_node))
11847 /* I/O will probably crash. */
11848 warning ("configuration: char * holds %d bits, but ftnlen only %d",
11849 TYPE_PRECISION (string_type_node),
11850 TYPE_PRECISION (ffecom_f2c_ftnlen_type_node));
11851 #endif
11853 #if 0 /* ASSIGN-related stuff has been changed to accommodate this. */
11854 if (TYPE_PRECISION (ffecom_integer_type_node)
11855 < TYPE_PRECISION (string_type_node))
11856 /* ASSIGN 10 TO I will crash. */
11857 warning ("configuration: char * holds %d bits, but INTEGER only %d --\n\
11858 ASSIGN statement might fail",
11859 TYPE_PRECISION (string_type_node),
11860 TYPE_PRECISION (ffecom_integer_type_node));
11861 #endif
11864 /* ffecom_init_2 -- Initialize
11866 ffecom_init_2(); */
11868 void
11869 ffecom_init_2 ()
11871 assert (ffecom_outer_function_decl_ == NULL_TREE);
11872 assert (current_function_decl == NULL_TREE);
11873 assert (ffecom_which_entrypoint_decl_ == NULL_TREE);
11875 ffecom_master_arglist_ = NULL;
11876 ++ffecom_num_fns_;
11877 ffecom_primary_entry_ = NULL;
11878 ffecom_is_altreturning_ = FALSE;
11879 ffecom_func_result_ = NULL_TREE;
11880 ffecom_multi_retval_ = NULL_TREE;
11883 /* ffecom_list_expr -- Transform list of exprs into gcc tree
11885 tree t;
11886 ffebld expr; // FFE opITEM list.
11887 tree = ffecom_list_expr(expr);
11889 List of actual args is transformed into corresponding gcc backend list. */
11891 tree
11892 ffecom_list_expr (ffebld expr)
11894 tree list;
11895 tree *plist = &list;
11896 tree trail = NULL_TREE; /* Append char length args here. */
11897 tree *ptrail = &trail;
11898 tree length;
11900 while (expr != NULL)
11902 tree texpr = ffecom_arg_expr (ffebld_head (expr), &length);
11904 if (texpr == error_mark_node)
11905 return error_mark_node;
11907 *plist = build_tree_list (NULL_TREE, texpr);
11908 plist = &TREE_CHAIN (*plist);
11909 expr = ffebld_trail (expr);
11910 if (length != NULL_TREE)
11912 *ptrail = build_tree_list (NULL_TREE, length);
11913 ptrail = &TREE_CHAIN (*ptrail);
11917 *plist = trail;
11919 return list;
11922 /* ffecom_list_ptr_to_expr -- Transform list of exprs into gcc tree
11924 tree t;
11925 ffebld expr; // FFE opITEM list.
11926 tree = ffecom_list_ptr_to_expr(expr);
11928 List of actual args is transformed into corresponding gcc backend list for
11929 use in calling an external procedure (vs. a statement function). */
11931 tree
11932 ffecom_list_ptr_to_expr (ffebld expr)
11934 tree list;
11935 tree *plist = &list;
11936 tree trail = NULL_TREE; /* Append char length args here. */
11937 tree *ptrail = &trail;
11938 tree length;
11940 while (expr != NULL)
11942 tree texpr = ffecom_arg_ptr_to_expr (ffebld_head (expr), &length);
11944 if (texpr == error_mark_node)
11945 return error_mark_node;
11947 *plist = build_tree_list (NULL_TREE, texpr);
11948 plist = &TREE_CHAIN (*plist);
11949 expr = ffebld_trail (expr);
11950 if (length != NULL_TREE)
11952 *ptrail = build_tree_list (NULL_TREE, length);
11953 ptrail = &TREE_CHAIN (*ptrail);
11957 *plist = trail;
11959 return list;
11962 /* Obtain gcc's LABEL_DECL tree for label. */
11964 tree
11965 ffecom_lookup_label (ffelab label)
11967 tree glabel;
11969 if (ffelab_hook (label) == NULL_TREE)
11971 char labelname[16];
11973 switch (ffelab_type (label))
11975 case FFELAB_typeLOOPEND:
11976 case FFELAB_typeNOTLOOP:
11977 case FFELAB_typeENDIF:
11978 sprintf (labelname, "%" ffelabValue_f "u", ffelab_value (label));
11979 glabel = build_decl (LABEL_DECL, get_identifier (labelname),
11980 void_type_node);
11981 DECL_CONTEXT (glabel) = current_function_decl;
11982 DECL_MODE (glabel) = VOIDmode;
11983 break;
11985 case FFELAB_typeFORMAT:
11986 glabel = build_decl (VAR_DECL,
11987 ffecom_get_invented_identifier
11988 ("__g77_format_%d", (int) ffelab_value (label)),
11989 build_type_variant (build_array_type
11990 (char_type_node,
11991 NULL_TREE),
11992 1, 0));
11993 TREE_CONSTANT (glabel) = 1;
11994 TREE_STATIC (glabel) = 1;
11995 DECL_CONTEXT (glabel) = current_function_decl;
11996 DECL_INITIAL (glabel) = NULL;
11997 make_decl_rtl (glabel, NULL);
11998 expand_decl (glabel);
12000 ffecom_save_tree_forever (glabel);
12002 break;
12004 case FFELAB_typeANY:
12005 glabel = error_mark_node;
12006 break;
12008 default:
12009 assert ("bad label type" == NULL);
12010 glabel = NULL;
12011 break;
12013 ffelab_set_hook (label, glabel);
12015 else
12017 glabel = ffelab_hook (label);
12020 return glabel;
12023 /* Stabilizes the arguments. Don't use this if the lhs and rhs come from
12024 a single source specification (as in the fourth argument of MVBITS).
12025 If the type is NULL_TREE, the type of lhs is used to make the type of
12026 the MODIFY_EXPR. */
12028 tree
12029 ffecom_modify (tree newtype, tree lhs,
12030 tree rhs)
12032 if (lhs == error_mark_node || rhs == error_mark_node)
12033 return error_mark_node;
12035 if (newtype == NULL_TREE)
12036 newtype = TREE_TYPE (lhs);
12038 if (TREE_SIDE_EFFECTS (lhs))
12039 lhs = stabilize_reference (lhs);
12041 return ffecom_2s (MODIFY_EXPR, newtype, lhs, rhs);
12044 /* Register source file name. */
12046 void
12047 ffecom_file (const char *name)
12049 ffecom_file_ (name);
12052 /* ffecom_notify_init_storage -- An aggregate storage is now fully init'ed
12054 ffestorag st;
12055 ffecom_notify_init_storage(st);
12057 Gets called when all possible units in an aggregate storage area (a LOCAL
12058 with equivalences or a COMMON) have been initialized. The initialization
12059 info either is in ffestorag_init or, if that is NULL,
12060 ffestorag_accretion:
12062 ffestorag_init may contain an opCONTER or opARRTER. opCONTER may occur
12063 even for an array if the array is one element in length!
12065 ffestorag_accretion will contain an opACCTER. It is much like an
12066 opARRTER except it has an ffebit object in it instead of just a size.
12067 The back end can use the info in the ffebit object, if it wants, to
12068 reduce the amount of actual initialization, but in any case it should
12069 kill the ffebit object when done. Also, set accretion to NULL but
12070 init to a non-NULL value.
12072 After performing initialization, DO NOT set init to NULL, because that'll
12073 tell the front end it is ok for more initialization to happen. Instead,
12074 set init to an opANY expression or some such thing that you can use to
12075 tell that you've already initialized the object.
12077 27-Oct-91 JCB 1.1
12078 Support two-pass FFE. */
12080 void
12081 ffecom_notify_init_storage (ffestorag st)
12083 ffebld init; /* The initialization expression. */
12085 if (ffestorag_init (st) == NULL)
12087 init = ffestorag_accretion (st);
12088 assert (init != NULL);
12089 ffestorag_set_accretion (st, NULL);
12090 ffestorag_set_accretes (st, 0);
12091 ffestorag_set_init (st, init);
12095 /* ffecom_notify_init_symbol -- A symbol is now fully init'ed
12097 ffesymbol s;
12098 ffecom_notify_init_symbol(s);
12100 Gets called when all possible units in a symbol (not placed in COMMON
12101 or involved in EQUIVALENCE, unless it as yet has no ffestorag object)
12102 have been initialized. The initialization info either is in
12103 ffesymbol_init or, if that is NULL, ffesymbol_accretion:
12105 ffesymbol_init may contain an opCONTER or opARRTER. opCONTER may occur
12106 even for an array if the array is one element in length!
12108 ffesymbol_accretion will contain an opACCTER. It is much like an
12109 opARRTER except it has an ffebit object in it instead of just a size.
12110 The back end can use the info in the ffebit object, if it wants, to
12111 reduce the amount of actual initialization, but in any case it should
12112 kill the ffebit object when done. Also, set accretion to NULL but
12113 init to a non-NULL value.
12115 After performing initialization, DO NOT set init to NULL, because that'll
12116 tell the front end it is ok for more initialization to happen. Instead,
12117 set init to an opANY expression or some such thing that you can use to
12118 tell that you've already initialized the object.
12120 27-Oct-91 JCB 1.1
12121 Support two-pass FFE. */
12123 void
12124 ffecom_notify_init_symbol (ffesymbol s)
12126 ffebld init; /* The initialization expression. */
12128 if (ffesymbol_storage (s) == NULL)
12129 return; /* Do nothing until COMMON/EQUIVALENCE
12130 possibilities checked. */
12132 if ((ffesymbol_init (s) == NULL)
12133 && ((init = ffesymbol_accretion (s)) != NULL))
12135 ffesymbol_set_accretion (s, NULL);
12136 ffesymbol_set_accretes (s, 0);
12137 ffesymbol_set_init (s, init);
12141 /* ffecom_notify_primary_entry -- Learn which is the primary entry point
12143 ffesymbol s;
12144 ffecom_notify_primary_entry(s);
12146 Gets called when implicit or explicit PROGRAM statement seen or when
12147 FUNCTION, SUBROUTINE, or BLOCK DATA statement seen, with the primary
12148 global symbol that serves as the entry point. */
12150 void
12151 ffecom_notify_primary_entry (ffesymbol s)
12153 ffecom_primary_entry_ = s;
12154 ffecom_primary_entry_kind_ = ffesymbol_kind (s);
12156 if ((ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
12157 || (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE))
12158 ffecom_primary_entry_is_proc_ = TRUE;
12159 else
12160 ffecom_primary_entry_is_proc_ = FALSE;
12162 if (!ffe_is_silent ())
12164 if (ffecom_primary_entry_kind_ == FFEINFO_kindPROGRAM)
12165 fprintf (stderr, "%s:\n", ffesymbol_text (s));
12166 else
12167 fprintf (stderr, " %s:\n", ffesymbol_text (s));
12170 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
12172 ffebld list;
12173 ffebld arg;
12175 for (list = ffesymbol_dummyargs (s);
12176 list != NULL;
12177 list = ffebld_trail (list))
12179 arg = ffebld_head (list);
12180 if (ffebld_op (arg) == FFEBLD_opSTAR)
12182 ffecom_is_altreturning_ = TRUE;
12183 break;
12189 FILE *
12190 ffecom_open_include (char *name, ffewhereLine l, ffewhereColumn c)
12192 return ffecom_open_include_ (name, l, c);
12195 /* ffecom_ptr_to_expr -- Transform expr into gcc tree with & in front
12197 tree t;
12198 ffebld expr; // FFE expression.
12199 tree = ffecom_ptr_to_expr(expr);
12201 Like ffecom_expr, but sticks address-of in front of most things. */
12203 tree
12204 ffecom_ptr_to_expr (ffebld expr)
12206 tree item;
12207 ffeinfoBasictype bt;
12208 ffeinfoKindtype kt;
12209 ffesymbol s;
12211 assert (expr != NULL);
12213 switch (ffebld_op (expr))
12215 case FFEBLD_opSYMTER:
12216 s = ffebld_symter (expr);
12217 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
12219 ffecomGfrt ix;
12221 ix = ffeintrin_gfrt_indirect (ffebld_symter_implementation (expr));
12222 assert (ix != FFECOM_gfrt);
12223 if ((item = ffecom_gfrt_[ix]) == NULL_TREE)
12225 ffecom_make_gfrt_ (ix);
12226 item = ffecom_gfrt_[ix];
12229 else
12231 item = ffesymbol_hook (s).decl_tree;
12232 if (item == NULL_TREE)
12234 s = ffecom_sym_transform_ (s);
12235 item = ffesymbol_hook (s).decl_tree;
12238 assert (item != NULL);
12239 if (item == error_mark_node)
12240 return item;
12241 if (!ffesymbol_hook (s).addr)
12242 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12243 item);
12244 return item;
12246 case FFEBLD_opARRAYREF:
12247 return ffecom_arrayref_ (NULL_TREE, expr, 1);
12249 case FFEBLD_opCONTER:
12251 bt = ffeinfo_basictype (ffebld_info (expr));
12252 kt = ffeinfo_kindtype (ffebld_info (expr));
12254 item = ffecom_constantunion (&ffebld_constant_union
12255 (ffebld_conter (expr)), bt, kt,
12256 ffecom_tree_type[bt][kt]);
12257 if (item == error_mark_node)
12258 return error_mark_node;
12259 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12260 item);
12261 return item;
12263 case FFEBLD_opANY:
12264 return error_mark_node;
12266 default:
12267 bt = ffeinfo_basictype (ffebld_info (expr));
12268 kt = ffeinfo_kindtype (ffebld_info (expr));
12270 item = ffecom_expr (expr);
12271 if (item == error_mark_node)
12272 return error_mark_node;
12274 /* The back end currently optimizes a bit too zealously for us, in that
12275 we fail JCB001 if the following block of code is omitted. It checks
12276 to see if the transformed expression is a symbol or array reference,
12277 and encloses it in a SAVE_EXPR if that is the case. */
12279 STRIP_NOPS (item);
12280 if ((TREE_CODE (item) == VAR_DECL)
12281 || (TREE_CODE (item) == PARM_DECL)
12282 || (TREE_CODE (item) == RESULT_DECL)
12283 || (TREE_CODE (item) == INDIRECT_REF)
12284 || (TREE_CODE (item) == ARRAY_REF)
12285 || (TREE_CODE (item) == COMPONENT_REF)
12286 #ifdef OFFSET_REF
12287 || (TREE_CODE (item) == OFFSET_REF)
12288 #endif
12289 || (TREE_CODE (item) == BUFFER_REF)
12290 || (TREE_CODE (item) == REALPART_EXPR)
12291 || (TREE_CODE (item) == IMAGPART_EXPR))
12293 item = ffecom_save_tree (item);
12296 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12297 item);
12298 return item;
12301 assert ("fall-through error" == NULL);
12302 return error_mark_node;
12305 /* Obtain a temp var with given data type.
12307 size is FFETARGET_charactersizeNONE for a non-CHARACTER type
12308 or >= 0 for a CHARACTER type.
12310 elements is -1 for a scalar or > 0 for an array of type. */
12312 tree
12313 ffecom_make_tempvar (const char *commentary, tree type,
12314 ffetargetCharacterSize size, int elements)
12316 tree t;
12317 static int mynumber;
12319 assert (current_binding_level->prep_state < 2);
12321 if (type == error_mark_node)
12322 return error_mark_node;
12324 if (size != FFETARGET_charactersizeNONE)
12325 type = build_array_type (type,
12326 build_range_type (ffecom_f2c_ftnlen_type_node,
12327 ffecom_f2c_ftnlen_one_node,
12328 build_int_2 (size, 0)));
12329 if (elements != -1)
12330 type = build_array_type (type,
12331 build_range_type (integer_type_node,
12332 integer_zero_node,
12333 build_int_2 (elements - 1,
12334 0)));
12335 t = build_decl (VAR_DECL,
12336 ffecom_get_invented_identifier ("__g77_%s_%d",
12337 commentary,
12338 mynumber++),
12339 type);
12341 t = start_decl (t, FALSE);
12342 finish_decl (t, NULL_TREE, FALSE);
12344 return t;
12347 /* Prepare argument pointer to expression.
12349 Like ffecom_prepare_expr, except for expressions to be evaluated
12350 via ffecom_arg_ptr_to_expr. */
12352 void
12353 ffecom_prepare_arg_ptr_to_expr (ffebld expr)
12355 /* ~~For now, it seems to be the same thing. */
12356 ffecom_prepare_expr (expr);
12357 return;
12360 /* End of preparations. */
12362 bool
12363 ffecom_prepare_end (void)
12365 int prep_state = current_binding_level->prep_state;
12367 assert (prep_state < 2);
12368 current_binding_level->prep_state = 2;
12370 return (prep_state == 1) ? TRUE : FALSE;
12373 /* Prepare expression.
12375 This is called before any code is generated for the current block.
12376 It scans the expression, declares any temporaries that might be needed
12377 during evaluation of the expression, and stores those temporaries in
12378 the appropriate "hook" fields of the expression. `dest', if not NULL,
12379 specifies the destination that ffecom_expr_ will see, in case that
12380 helps avoid generating unused temporaries.
12382 ~~Improve to avoid allocating unused temporaries by taking `dest'
12383 into account vis-a-vis aliasing requirements of complex/character
12384 functions. */
12386 void
12387 ffecom_prepare_expr_ (ffebld expr, ffebld dest UNUSED)
12389 ffeinfoBasictype bt;
12390 ffeinfoKindtype kt;
12391 ffetargetCharacterSize sz;
12392 tree tempvar = NULL_TREE;
12394 assert (current_binding_level->prep_state < 2);
12396 if (! expr)
12397 return;
12399 bt = ffeinfo_basictype (ffebld_info (expr));
12400 kt = ffeinfo_kindtype (ffebld_info (expr));
12401 sz = ffeinfo_size (ffebld_info (expr));
12403 /* Generate whatever temporaries are needed to represent the result
12404 of the expression. */
12406 if (bt == FFEINFO_basictypeCHARACTER)
12408 while (ffebld_op (expr) == FFEBLD_opPAREN)
12409 expr = ffebld_left (expr);
12412 switch (ffebld_op (expr))
12414 default:
12415 /* Don't make temps for SYMTER, CONTER, etc. */
12416 if (ffebld_arity (expr) == 0)
12417 break;
12419 switch (bt)
12421 case FFEINFO_basictypeCOMPLEX:
12422 if (ffebld_op (expr) == FFEBLD_opFUNCREF)
12424 ffesymbol s;
12426 if (ffebld_op (ffebld_left (expr)) != FFEBLD_opSYMTER)
12427 break;
12429 s = ffebld_symter (ffebld_left (expr));
12430 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT
12431 || (ffesymbol_where (s) != FFEINFO_whereINTRINSIC
12432 && ! ffesymbol_is_f2c (s))
12433 || (ffesymbol_where (s) == FFEINFO_whereINTRINSIC
12434 && ! ffe_is_f2c_library ()))
12435 break;
12437 else if (ffebld_op (expr) == FFEBLD_opPOWER)
12439 /* Requires special treatment. There's no POW_CC function
12440 in libg2c, so POW_ZZ is used, which means we always
12441 need a double-complex temp, not a single-complex. */
12442 kt = FFEINFO_kindtypeREAL2;
12444 else if (ffebld_op (expr) != FFEBLD_opDIVIDE)
12445 /* The other ops don't need temps for complex operands. */
12446 break;
12448 /* ~~~Avoid making temps for some intrinsics, such as AIMAG(C),
12449 REAL(C). See 19990325-0.f, routine `check', for cases. */
12450 tempvar = ffecom_make_tempvar ("complex",
12451 ffecom_tree_type
12452 [FFEINFO_basictypeCOMPLEX][kt],
12453 FFETARGET_charactersizeNONE,
12454 -1);
12455 break;
12457 case FFEINFO_basictypeCHARACTER:
12458 if (ffebld_op (expr) != FFEBLD_opFUNCREF)
12459 break;
12461 if (sz == FFETARGET_charactersizeNONE)
12462 /* ~~Kludge alert! This should someday be fixed. */
12463 sz = 24;
12465 tempvar = ffecom_make_tempvar ("char", char_type_node, sz, -1);
12466 break;
12468 default:
12469 break;
12471 break;
12473 #ifdef HAHA
12474 case FFEBLD_opPOWER:
12476 tree rtype, ltype;
12477 tree rtmp, ltmp, result;
12479 ltype = ffecom_type_expr (ffebld_left (expr));
12480 rtype = ffecom_type_expr (ffebld_right (expr));
12482 rtmp = ffecom_make_tempvar (rtype, FFETARGET_charactersizeNONE, -1);
12483 ltmp = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
12484 result = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
12486 tempvar = make_tree_vec (3);
12487 TREE_VEC_ELT (tempvar, 0) = rtmp;
12488 TREE_VEC_ELT (tempvar, 1) = ltmp;
12489 TREE_VEC_ELT (tempvar, 2) = result;
12491 break;
12492 #endif /* HAHA */
12494 case FFEBLD_opCONCATENATE:
12496 /* This gets special handling, because only one set of temps
12497 is needed for a tree of these -- the tree is treated as
12498 a flattened list of concatenations when generating code. */
12500 ffecomConcatList_ catlist;
12501 tree ltmp, itmp, result;
12502 int count;
12503 int i;
12505 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
12506 count = ffecom_concat_list_count_ (catlist);
12508 if (count >= 2)
12510 ltmp
12511 = ffecom_make_tempvar ("concat_len",
12512 ffecom_f2c_ftnlen_type_node,
12513 FFETARGET_charactersizeNONE, count);
12514 itmp
12515 = ffecom_make_tempvar ("concat_item",
12516 ffecom_f2c_address_type_node,
12517 FFETARGET_charactersizeNONE, count);
12518 result
12519 = ffecom_make_tempvar ("concat_res",
12520 char_type_node,
12521 ffecom_concat_list_maxlen_ (catlist),
12522 -1);
12524 tempvar = make_tree_vec (3);
12525 TREE_VEC_ELT (tempvar, 0) = ltmp;
12526 TREE_VEC_ELT (tempvar, 1) = itmp;
12527 TREE_VEC_ELT (tempvar, 2) = result;
12530 for (i = 0; i < count; ++i)
12531 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist,
12532 i));
12534 ffecom_concat_list_kill_ (catlist);
12536 if (tempvar)
12538 ffebld_nonter_set_hook (expr, tempvar);
12539 current_binding_level->prep_state = 1;
12542 return;
12544 case FFEBLD_opCONVERT:
12545 if (bt == FFEINFO_basictypeCHARACTER
12546 && ((ffebld_size_known (ffebld_left (expr))
12547 == FFETARGET_charactersizeNONE)
12548 || (ffebld_size_known (ffebld_left (expr)) >= sz)))
12549 tempvar = ffecom_make_tempvar ("convert", char_type_node, sz, -1);
12550 break;
12553 if (tempvar)
12555 ffebld_nonter_set_hook (expr, tempvar);
12556 current_binding_level->prep_state = 1;
12559 /* Prepare subexpressions for this expr. */
12561 switch (ffebld_op (expr))
12563 case FFEBLD_opPERCENT_LOC:
12564 ffecom_prepare_ptr_to_expr (ffebld_left (expr));
12565 break;
12567 case FFEBLD_opPERCENT_VAL:
12568 case FFEBLD_opPERCENT_REF:
12569 ffecom_prepare_expr (ffebld_left (expr));
12570 break;
12572 case FFEBLD_opPERCENT_DESCR:
12573 ffecom_prepare_arg_ptr_to_expr (ffebld_left (expr));
12574 break;
12576 case FFEBLD_opITEM:
12578 ffebld item;
12580 for (item = expr;
12581 item != NULL;
12582 item = ffebld_trail (item))
12583 if (ffebld_head (item) != NULL)
12584 ffecom_prepare_expr (ffebld_head (item));
12586 break;
12588 default:
12589 /* Need to handle character conversion specially. */
12590 switch (ffebld_arity (expr))
12592 case 2:
12593 ffecom_prepare_expr (ffebld_left (expr));
12594 ffecom_prepare_expr (ffebld_right (expr));
12595 break;
12597 case 1:
12598 ffecom_prepare_expr (ffebld_left (expr));
12599 break;
12601 default:
12602 break;
12606 return;
12609 /* Prepare expression for reading and writing.
12611 Like ffecom_prepare_expr, except for expressions to be evaluated
12612 via ffecom_expr_rw. */
12614 void
12615 ffecom_prepare_expr_rw (tree type, ffebld expr)
12617 /* This is all we support for now. */
12618 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
12620 /* ~~For now, it seems to be the same thing. */
12621 ffecom_prepare_expr (expr);
12622 return;
12625 /* Prepare expression for writing.
12627 Like ffecom_prepare_expr, except for expressions to be evaluated
12628 via ffecom_expr_w. */
12630 void
12631 ffecom_prepare_expr_w (tree type, ffebld expr)
12633 /* This is all we support for now. */
12634 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
12636 /* ~~For now, it seems to be the same thing. */
12637 ffecom_prepare_expr (expr);
12638 return;
12641 /* Prepare expression for returning.
12643 Like ffecom_prepare_expr, except for expressions to be evaluated
12644 via ffecom_return_expr. */
12646 void
12647 ffecom_prepare_return_expr (ffebld expr)
12649 assert (current_binding_level->prep_state < 2);
12651 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE
12652 && ffecom_is_altreturning_
12653 && expr != NULL)
12654 ffecom_prepare_expr (expr);
12657 /* Prepare pointer to expression.
12659 Like ffecom_prepare_expr, except for expressions to be evaluated
12660 via ffecom_ptr_to_expr. */
12662 void
12663 ffecom_prepare_ptr_to_expr (ffebld expr)
12665 /* ~~For now, it seems to be the same thing. */
12666 ffecom_prepare_expr (expr);
12667 return;
12670 /* Transform expression into constant pointer-to-expression tree.
12672 If the expression can be transformed into a pointer-to-expression tree
12673 that is constant, that is done, and the tree returned. Else NULL_TREE
12674 is returned.
12676 That way, a caller can attempt to provide compile-time initialization
12677 of a variable and, if that fails, *then* choose to start a new block
12678 and resort to using temporaries, as appropriate. */
12680 tree
12681 ffecom_ptr_to_const_expr (ffebld expr)
12683 if (! expr)
12684 return integer_zero_node;
12686 if (ffebld_op (expr) == FFEBLD_opANY)
12687 return error_mark_node;
12689 if (ffebld_arity (expr) == 0
12690 && (ffebld_op (expr) != FFEBLD_opSYMTER
12691 || ffebld_where (expr) == FFEINFO_whereCOMMON
12692 || ffebld_where (expr) == FFEINFO_whereGLOBAL
12693 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
12695 tree t;
12697 t = ffecom_ptr_to_expr (expr);
12698 assert (TREE_CONSTANT (t));
12699 return t;
12702 return NULL_TREE;
12705 /* ffecom_return_expr -- Returns return-value expr given alt return expr
12707 tree rtn; // NULL_TREE means use expand_null_return()
12708 ffebld expr; // NULL if no alt return expr to RETURN stmt
12709 rtn = ffecom_return_expr(expr);
12711 Based on the program unit type and other info (like return function
12712 type, return master function type when alternate ENTRY points,
12713 whether subroutine has any alternate RETURN points, etc), returns the
12714 appropriate expression to be returned to the caller, or NULL_TREE
12715 meaning no return value or the caller expects it to be returned somewhere
12716 else (which is handled by other parts of this module). */
12718 tree
12719 ffecom_return_expr (ffebld expr)
12721 tree rtn;
12723 switch (ffecom_primary_entry_kind_)
12725 case FFEINFO_kindPROGRAM:
12726 case FFEINFO_kindBLOCKDATA:
12727 rtn = NULL_TREE;
12728 break;
12730 case FFEINFO_kindSUBROUTINE:
12731 if (!ffecom_is_altreturning_)
12732 rtn = NULL_TREE; /* No alt returns, never an expr. */
12733 else if (expr == NULL)
12734 rtn = integer_zero_node;
12735 else
12736 rtn = ffecom_expr (expr);
12737 break;
12739 case FFEINFO_kindFUNCTION:
12740 if ((ffecom_multi_retval_ != NULL_TREE)
12741 || (ffesymbol_basictype (ffecom_primary_entry_)
12742 == FFEINFO_basictypeCHARACTER)
12743 || ((ffesymbol_basictype (ffecom_primary_entry_)
12744 == FFEINFO_basictypeCOMPLEX)
12745 && (ffecom_num_entrypoints_ == 0)
12746 && ffesymbol_is_f2c (ffecom_primary_entry_)))
12747 { /* Value is returned by direct assignment
12748 into (implicit) dummy. */
12749 rtn = NULL_TREE;
12750 break;
12752 rtn = ffecom_func_result_;
12753 #if 0
12754 /* Spurious error if RETURN happens before first reference! So elide
12755 this code. In particular, for debugging registry, rtn should always
12756 be non-null after all, but TREE_USED won't be set until we encounter
12757 a reference in the code. Perfectly okay (but weird) code that,
12758 e.g., has "GOTO 20;10 RETURN;20 RTN=0;GOTO 10", would result in
12759 this diagnostic for no reason. Have people use -O -Wuninitialized
12760 and leave it to the back end to find obviously weird cases. */
12762 /* Used to "assert(rtn != NULL_TREE);" here, but it's kind of a valid
12763 situation; if the return value has never been referenced, it won't
12764 have a tree under 2pass mode. */
12765 if ((rtn == NULL_TREE)
12766 || !TREE_USED (rtn))
12768 ffebad_start (FFEBAD_RETURN_VALUE_UNSET);
12769 ffebad_here (0, ffesymbol_where_line (ffecom_primary_entry_),
12770 ffesymbol_where_column (ffecom_primary_entry_));
12771 ffebad_string (ffesymbol_text (ffesymbol_funcresult
12772 (ffecom_primary_entry_)));
12773 ffebad_finish ();
12775 #endif
12776 break;
12778 default:
12779 assert ("bad unit kind" == NULL);
12780 case FFEINFO_kindANY:
12781 rtn = error_mark_node;
12782 break;
12785 return rtn;
12788 /* Do save_expr only if tree is not error_mark_node. */
12790 tree
12791 ffecom_save_tree (tree t)
12793 return save_expr (t);
12796 /* Start a compound statement (block). */
12798 void
12799 ffecom_start_compstmt (void)
12801 bison_rule_pushlevel_ ();
12804 /* Public entry point for front end to access start_decl. */
12806 tree
12807 ffecom_start_decl (tree decl, bool is_initialized)
12809 DECL_INITIAL (decl) = is_initialized ? error_mark_node : NULL_TREE;
12810 return start_decl (decl, FALSE);
12813 /* ffecom_sym_commit -- Symbol's state being committed to reality
12815 ffesymbol s;
12816 ffecom_sym_commit(s);
12818 Does whatever the backend needs when a symbol is committed after having
12819 been backtrackable for a period of time. */
12821 void
12822 ffecom_sym_commit (ffesymbol s UNUSED)
12824 assert (!ffesymbol_retractable ());
12827 /* ffecom_sym_end_transition -- Perform end transition on all symbols
12829 ffecom_sym_end_transition();
12831 Does backend-specific stuff and also calls ffest_sym_end_transition
12832 to do the necessary FFE stuff.
12834 Backtracking is never enabled when this fn is called, so don't worry
12835 about it. */
12837 ffesymbol
12838 ffecom_sym_end_transition (ffesymbol s)
12840 ffestorag st;
12842 assert (!ffesymbol_retractable ());
12844 s = ffest_sym_end_transition (s);
12846 if ((ffesymbol_kind (s) == FFEINFO_kindBLOCKDATA)
12847 && (ffesymbol_where (s) == FFEINFO_whereGLOBAL))
12849 ffecom_list_blockdata_
12850 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
12851 FFEINTRIN_specNONE,
12852 FFEINTRIN_impNONE),
12853 ffecom_list_blockdata_);
12856 /* This is where we finally notice that a symbol has partial initialization
12857 and finalize it. */
12859 if (ffesymbol_accretion (s) != NULL)
12861 assert (ffesymbol_init (s) == NULL);
12862 ffecom_notify_init_symbol (s);
12864 else if (((st = ffesymbol_storage (s)) != NULL)
12865 && ((st = ffestorag_parent (st)) != NULL)
12866 && (ffestorag_accretion (st) != NULL))
12868 assert (ffestorag_init (st) == NULL);
12869 ffecom_notify_init_storage (st);
12872 if ((ffesymbol_kind (s) == FFEINFO_kindCOMMON)
12873 && (ffesymbol_where (s) == FFEINFO_whereLOCAL)
12874 && (ffesymbol_storage (s) != NULL))
12876 ffecom_list_common_
12877 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
12878 FFEINTRIN_specNONE,
12879 FFEINTRIN_impNONE),
12880 ffecom_list_common_);
12883 return s;
12886 /* ffecom_sym_exec_transition -- Perform exec transition on all symbols
12888 ffecom_sym_exec_transition();
12890 Does backend-specific stuff and also calls ffest_sym_exec_transition
12891 to do the necessary FFE stuff.
12893 See the long-winded description in ffecom_sym_learned for info
12894 on handling the situation where backtracking is inhibited. */
12896 ffesymbol
12897 ffecom_sym_exec_transition (ffesymbol s)
12899 s = ffest_sym_exec_transition (s);
12901 return s;
12904 /* ffecom_sym_learned -- Initial or more info gained on symbol after exec
12906 ffesymbol s;
12907 s = ffecom_sym_learned(s);
12909 Called when a new symbol is seen after the exec transition or when more
12910 info (perhaps) is gained for an UNCERTAIN symbol. The symbol state when
12911 it arrives here is that all its latest info is updated already, so its
12912 state may be UNCERTAIN or UNDERSTOOD, it might already have the hook
12913 field filled in if its gone through here or exec_transition first, and
12914 so on.
12916 The backend probably wants to check ffesymbol_retractable() to see if
12917 backtracking is in effect. If so, the FFE's changes to the symbol may
12918 be retracted (undone) or committed (ratified), at which time the
12919 appropriate ffecom_sym_retract or _commit function will be called
12920 for that function.
12922 If the backend has its own backtracking mechanism, great, use it so that
12923 committal is a simple operation. Though it doesn't make much difference,
12924 I suppose: the reason for tentative symbol evolution in the FFE is to
12925 enable error detection in weird incorrect statements early and to disable
12926 incorrect error detection on a correct statement. The backend is not
12927 likely to introduce any information that'll get involved in these
12928 considerations, so it is probably just fine that the implementation
12929 model for this fn and for _exec_transition is to not do anything
12930 (besides the required FFE stuff) if ffesymbol_retractable() returns TRUE
12931 and instead wait until ffecom_sym_commit is called (which it never
12932 will be as long as we're using ambiguity-detecting statement analysis in
12933 the FFE, which we are initially to shake out the code, but don't depend
12934 on this), otherwise go ahead and do whatever is needed.
12936 In essence, then, when this fn and _exec_transition get called while
12937 backtracking is enabled, a general mechanism would be to flag which (or
12938 both) of these were called (and in what order? neat question as to what
12939 might happen that I'm too lame to think through right now) and then when
12940 _commit is called reproduce the original calling sequence, if any, for
12941 the two fns (at which point backtracking will, of course, be disabled). */
12943 ffesymbol
12944 ffecom_sym_learned (ffesymbol s)
12946 ffestorag_exec_layout (s);
12948 return s;
12951 /* ffecom_sym_retract -- Symbol's state being retracted from reality
12953 ffesymbol s;
12954 ffecom_sym_retract(s);
12956 Does whatever the backend needs when a symbol is retracted after having
12957 been backtrackable for a period of time. */
12959 void
12960 ffecom_sym_retract (ffesymbol s UNUSED)
12962 assert (!ffesymbol_retractable ());
12964 #if 0 /* GCC doesn't commit any backtrackable sins,
12965 so nothing needed here. */
12966 switch (ffesymbol_hook (s).state)
12968 case 0: /* nothing happened yet. */
12969 break;
12971 case 1: /* exec transition happened. */
12972 break;
12974 case 2: /* learned happened. */
12975 break;
12977 case 3: /* learned then exec. */
12978 break;
12980 case 4: /* exec then learned. */
12981 break;
12983 default:
12984 assert ("bad hook state" == NULL);
12985 break;
12987 #endif
12990 /* Create temporary gcc label. */
12992 tree
12993 ffecom_temp_label ()
12995 tree glabel;
12996 static int mynumber = 0;
12998 glabel = build_decl (LABEL_DECL,
12999 ffecom_get_invented_identifier ("__g77_label_%d",
13000 mynumber++),
13001 void_type_node);
13002 DECL_CONTEXT (glabel) = current_function_decl;
13003 DECL_MODE (glabel) = VOIDmode;
13005 return glabel;
13008 /* Return an expression that is usable as an arg in a conditional context
13009 (IF, DO WHILE, .NOT., and so on).
13011 Use the one provided for the back end as of >2.6.0. */
13013 tree
13014 ffecom_truth_value (tree expr)
13016 return ffe_truthvalue_conversion (expr);
13019 /* Return the inversion of a truth value (the inversion of what
13020 ffecom_truth_value builds).
13022 Apparently invert_truthvalue, which is properly in the back end, is
13023 enough for now, so just use it. */
13025 tree
13026 ffecom_truth_value_invert (tree expr)
13028 return invert_truthvalue (ffecom_truth_value (expr));
13031 /* Return the tree that is the type of the expression, as would be
13032 returned in TREE_TYPE(ffecom_expr(expr)), without otherwise
13033 transforming the expression, generating temporaries, etc. */
13035 tree
13036 ffecom_type_expr (ffebld expr)
13038 ffeinfoBasictype bt;
13039 ffeinfoKindtype kt;
13040 tree tree_type;
13042 assert (expr != NULL);
13044 bt = ffeinfo_basictype (ffebld_info (expr));
13045 kt = ffeinfo_kindtype (ffebld_info (expr));
13046 tree_type = ffecom_tree_type[bt][kt];
13048 switch (ffebld_op (expr))
13050 case FFEBLD_opCONTER:
13051 case FFEBLD_opSYMTER:
13052 case FFEBLD_opARRAYREF:
13053 case FFEBLD_opUPLUS:
13054 case FFEBLD_opPAREN:
13055 case FFEBLD_opUMINUS:
13056 case FFEBLD_opADD:
13057 case FFEBLD_opSUBTRACT:
13058 case FFEBLD_opMULTIPLY:
13059 case FFEBLD_opDIVIDE:
13060 case FFEBLD_opPOWER:
13061 case FFEBLD_opNOT:
13062 case FFEBLD_opFUNCREF:
13063 case FFEBLD_opSUBRREF:
13064 case FFEBLD_opAND:
13065 case FFEBLD_opOR:
13066 case FFEBLD_opXOR:
13067 case FFEBLD_opNEQV:
13068 case FFEBLD_opEQV:
13069 case FFEBLD_opCONVERT:
13070 case FFEBLD_opLT:
13071 case FFEBLD_opLE:
13072 case FFEBLD_opEQ:
13073 case FFEBLD_opNE:
13074 case FFEBLD_opGT:
13075 case FFEBLD_opGE:
13076 case FFEBLD_opPERCENT_LOC:
13077 return tree_type;
13079 case FFEBLD_opACCTER:
13080 case FFEBLD_opARRTER:
13081 case FFEBLD_opITEM:
13082 case FFEBLD_opSTAR:
13083 case FFEBLD_opBOUNDS:
13084 case FFEBLD_opREPEAT:
13085 case FFEBLD_opLABTER:
13086 case FFEBLD_opLABTOK:
13087 case FFEBLD_opIMPDO:
13088 case FFEBLD_opCONCATENATE:
13089 case FFEBLD_opSUBSTR:
13090 default:
13091 assert ("bad op for ffecom_type_expr" == NULL);
13092 /* Fall through. */
13093 case FFEBLD_opANY:
13094 return error_mark_node;
13098 /* Return PARM_DECL for arg#1 of master fn containing alternate ENTRY points
13100 If the PARM_DECL already exists, return it, else create it. It's an
13101 integer_type_node argument for the master function that implements a
13102 subroutine or function with more than one entrypoint and is bound at
13103 run time with the entrypoint number (0 for SUBROUTINE/FUNCTION, 1 for
13104 first ENTRY statement, and so on). */
13106 tree
13107 ffecom_which_entrypoint_decl ()
13109 assert (ffecom_which_entrypoint_decl_ != NULL_TREE);
13111 return ffecom_which_entrypoint_decl_;
13114 /* The following sections consists of private and public functions
13115 that have the same names and perform roughly the same functions
13116 as counterparts in the C front end. Changes in the C front end
13117 might affect how things should be done here. Only functions
13118 needed by the back end should be public here; the rest should
13119 be private (static in the C sense). Functions needed by other
13120 g77 front-end modules should be accessed by them via public
13121 ffecom_* names, which should themselves call private versions
13122 in this section so the private versions are easy to recognize
13123 when upgrading to a new gcc and finding interesting changes
13124 in the front end.
13126 Functions named after rule "foo:" in c-parse.y are named
13127 "bison_rule_foo_" so they are easy to find. */
13129 static void
13130 bison_rule_pushlevel_ ()
13132 emit_line_note (input_filename, lineno);
13133 pushlevel (0);
13134 clear_last_expr ();
13135 expand_start_bindings (0);
13138 static tree
13139 bison_rule_compstmt_ ()
13141 tree t;
13142 int keep = kept_level_p ();
13144 /* Make the temps go away. */
13145 if (! keep)
13146 current_binding_level->names = NULL_TREE;
13148 emit_line_note (input_filename, lineno);
13149 expand_end_bindings (getdecls (), keep, 0);
13150 t = poplevel (keep, 1, 0);
13152 return t;
13155 /* Return a definition for a builtin function named NAME and whose data type
13156 is TYPE. TYPE should be a function type with argument types.
13157 FUNCTION_CODE tells later passes how to compile calls to this function.
13158 See tree.h for its possible values.
13160 If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
13161 the name to be called if we can't opencode the function. */
13163 tree
13164 builtin_function (const char *name, tree type, int function_code,
13165 enum built_in_class class,
13166 const char *library_name)
13168 tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
13169 DECL_EXTERNAL (decl) = 1;
13170 TREE_PUBLIC (decl) = 1;
13171 if (library_name)
13172 SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
13173 make_decl_rtl (decl, NULL);
13174 pushdecl (decl);
13175 DECL_BUILT_IN_CLASS (decl) = class;
13176 DECL_FUNCTION_CODE (decl) = function_code;
13178 return decl;
13181 /* Handle when a new declaration NEWDECL
13182 has the same name as an old one OLDDECL
13183 in the same binding contour.
13184 Prints an error message if appropriate.
13186 If safely possible, alter OLDDECL to look like NEWDECL, and return 1.
13187 Otherwise, return 0. */
13189 static int
13190 duplicate_decls (tree newdecl, tree olddecl)
13192 int types_match = 1;
13193 int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
13194 && DECL_INITIAL (newdecl) != 0);
13195 tree oldtype = TREE_TYPE (olddecl);
13196 tree newtype = TREE_TYPE (newdecl);
13198 if (olddecl == newdecl)
13199 return 1;
13201 if (TREE_CODE (newtype) == ERROR_MARK
13202 || TREE_CODE (oldtype) == ERROR_MARK)
13203 types_match = 0;
13205 /* New decl is completely inconsistent with the old one =>
13206 tell caller to replace the old one.
13207 This is always an error except in the case of shadowing a builtin. */
13208 if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
13209 return 0;
13211 /* For real parm decl following a forward decl,
13212 return 1 so old decl will be reused. */
13213 if (types_match && TREE_CODE (newdecl) == PARM_DECL
13214 && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
13215 return 1;
13217 /* The new declaration is the same kind of object as the old one.
13218 The declarations may partially match. Print warnings if they don't
13219 match enough. Ultimately, copy most of the information from the new
13220 decl to the old one, and keep using the old one. */
13222 if (TREE_CODE (olddecl) == FUNCTION_DECL
13223 && DECL_BUILT_IN (olddecl))
13225 /* A function declaration for a built-in function. */
13226 if (!TREE_PUBLIC (newdecl))
13227 return 0;
13228 else if (!types_match)
13230 /* Accept the return type of the new declaration if same modes. */
13231 tree oldreturntype = TREE_TYPE (TREE_TYPE (olddecl));
13232 tree newreturntype = TREE_TYPE (TREE_TYPE (newdecl));
13234 if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
13236 /* Function types may be shared, so we can't just modify
13237 the return type of olddecl's function type. */
13238 tree newtype
13239 = build_function_type (newreturntype,
13240 TYPE_ARG_TYPES (TREE_TYPE (olddecl)));
13242 types_match = 1;
13243 if (types_match)
13244 TREE_TYPE (olddecl) = newtype;
13247 if (!types_match)
13248 return 0;
13250 else if (TREE_CODE (olddecl) == FUNCTION_DECL
13251 && DECL_SOURCE_LINE (olddecl) == 0)
13253 /* A function declaration for a predeclared function
13254 that isn't actually built in. */
13255 if (!TREE_PUBLIC (newdecl))
13256 return 0;
13257 else if (!types_match)
13259 /* If the types don't match, preserve volatility indication.
13260 Later on, we will discard everything else about the
13261 default declaration. */
13262 TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
13266 /* Copy all the DECL_... slots specified in the new decl
13267 except for any that we copy here from the old type.
13269 Past this point, we don't change OLDTYPE and NEWTYPE
13270 even if we change the types of NEWDECL and OLDDECL. */
13272 if (types_match)
13274 /* Merge the data types specified in the two decls. */
13275 if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
13276 TREE_TYPE (newdecl)
13277 = TREE_TYPE (olddecl)
13278 = TREE_TYPE (newdecl);
13280 /* Lay the type out, unless already done. */
13281 if (oldtype != TREE_TYPE (newdecl))
13283 if (TREE_TYPE (newdecl) != error_mark_node)
13284 layout_type (TREE_TYPE (newdecl));
13285 if (TREE_CODE (newdecl) != FUNCTION_DECL
13286 && TREE_CODE (newdecl) != TYPE_DECL
13287 && TREE_CODE (newdecl) != CONST_DECL)
13288 layout_decl (newdecl, 0);
13290 else
13292 /* Since the type is OLDDECL's, make OLDDECL's size go with. */
13293 DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
13294 DECL_SIZE_UNIT (newdecl) = DECL_SIZE_UNIT (olddecl);
13295 if (TREE_CODE (olddecl) != FUNCTION_DECL)
13296 if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
13298 DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
13299 DECL_USER_ALIGN (newdecl) |= DECL_USER_ALIGN (olddecl);
13303 /* Keep the old rtl since we can safely use it. */
13304 COPY_DECL_RTL (olddecl, newdecl);
13306 /* Merge the type qualifiers. */
13307 if (DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl)
13308 && !TREE_THIS_VOLATILE (newdecl))
13309 TREE_THIS_VOLATILE (olddecl) = 0;
13310 if (TREE_READONLY (newdecl))
13311 TREE_READONLY (olddecl) = 1;
13312 if (TREE_THIS_VOLATILE (newdecl))
13314 TREE_THIS_VOLATILE (olddecl) = 1;
13315 if (TREE_CODE (newdecl) == VAR_DECL)
13316 make_var_volatile (newdecl);
13319 /* Keep source location of definition rather than declaration.
13320 Likewise, keep decl at outer scope. */
13321 if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
13322 || (DECL_CONTEXT (newdecl) != 0 && DECL_CONTEXT (olddecl) == 0))
13324 DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
13325 DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl);
13327 if (DECL_CONTEXT (olddecl) == 0
13328 && TREE_CODE (newdecl) != FUNCTION_DECL)
13329 DECL_CONTEXT (newdecl) = 0;
13332 /* Merge the unused-warning information. */
13333 if (DECL_IN_SYSTEM_HEADER (olddecl))
13334 DECL_IN_SYSTEM_HEADER (newdecl) = 1;
13335 else if (DECL_IN_SYSTEM_HEADER (newdecl))
13336 DECL_IN_SYSTEM_HEADER (olddecl) = 1;
13338 /* Merge the initialization information. */
13339 if (DECL_INITIAL (newdecl) == 0)
13340 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
13342 /* Merge the section attribute.
13343 We want to issue an error if the sections conflict but that must be
13344 done later in decl_attributes since we are called before attributes
13345 are assigned. */
13346 if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
13347 DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
13349 if (TREE_CODE (newdecl) == FUNCTION_DECL)
13351 DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
13352 DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
13355 /* If cannot merge, then use the new type and qualifiers,
13356 and don't preserve the old rtl. */
13357 else
13359 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
13360 TREE_READONLY (olddecl) = TREE_READONLY (newdecl);
13361 TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl);
13362 TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl);
13365 /* Merge the storage class information. */
13366 /* For functions, static overrides non-static. */
13367 if (TREE_CODE (newdecl) == FUNCTION_DECL)
13369 TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
13370 /* This is since we don't automatically
13371 copy the attributes of NEWDECL into OLDDECL. */
13372 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
13373 /* If this clears `static', clear it in the identifier too. */
13374 if (! TREE_PUBLIC (olddecl))
13375 TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
13377 if (DECL_EXTERNAL (newdecl))
13379 TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
13380 DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
13381 /* An extern decl does not override previous storage class. */
13382 TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
13384 else
13386 TREE_STATIC (olddecl) = TREE_STATIC (newdecl);
13387 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
13390 /* If either decl says `inline', this fn is inline,
13391 unless its definition was passed already. */
13392 if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
13393 DECL_INLINE (olddecl) = 1;
13394 DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
13396 /* Get rid of any built-in function if new arg types don't match it
13397 or if we have a function definition. */
13398 if (TREE_CODE (newdecl) == FUNCTION_DECL
13399 && DECL_BUILT_IN (olddecl)
13400 && (!types_match || new_is_definition))
13402 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
13403 DECL_BUILT_IN_CLASS (olddecl) = NOT_BUILT_IN;
13406 /* If redeclaring a builtin function, and not a definition,
13407 it stays built in.
13408 Also preserve various other info from the definition. */
13409 if (TREE_CODE (newdecl) == FUNCTION_DECL && !new_is_definition)
13411 if (DECL_BUILT_IN (olddecl))
13413 DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
13414 DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
13417 DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
13418 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
13419 DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
13420 DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
13423 /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
13424 But preserve olddecl's DECL_UID. */
13426 register unsigned olddecl_uid = DECL_UID (olddecl);
13428 memcpy ((char *) olddecl + sizeof (struct tree_common),
13429 (char *) newdecl + sizeof (struct tree_common),
13430 sizeof (struct tree_decl) - sizeof (struct tree_common));
13431 DECL_UID (olddecl) = olddecl_uid;
13434 return 1;
13437 /* Finish processing of a declaration;
13438 install its initial value.
13439 If the length of an array type is not known before,
13440 it must be determined now, from the initial value, or it is an error. */
13442 static void
13443 finish_decl (tree decl, tree init, bool is_top_level)
13445 register tree type = TREE_TYPE (decl);
13446 int was_incomplete = (DECL_SIZE (decl) == 0);
13447 bool at_top_level = (current_binding_level == global_binding_level);
13448 bool top_level = is_top_level || at_top_level;
13450 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
13451 level anyway. */
13452 assert (!is_top_level || !at_top_level);
13454 if (TREE_CODE (decl) == PARM_DECL)
13455 assert (init == NULL_TREE);
13456 /* Remember that PARM_DECL doesn't have a DECL_INITIAL field per se -- it
13457 overlaps DECL_ARG_TYPE. */
13458 else if (init == NULL_TREE)
13459 assert (DECL_INITIAL (decl) == NULL_TREE);
13460 else
13461 assert (DECL_INITIAL (decl) == error_mark_node);
13463 if (init != NULL_TREE)
13465 if (TREE_CODE (decl) != TYPE_DECL)
13466 DECL_INITIAL (decl) = init;
13467 else
13469 /* typedef foo = bar; store the type of bar as the type of foo. */
13470 TREE_TYPE (decl) = TREE_TYPE (init);
13471 DECL_INITIAL (decl) = init = 0;
13475 /* Deduce size of array from initialization, if not already known */
13477 if (TREE_CODE (type) == ARRAY_TYPE
13478 && TYPE_DOMAIN (type) == 0
13479 && TREE_CODE (decl) != TYPE_DECL)
13481 assert (top_level);
13482 assert (was_incomplete);
13484 layout_decl (decl, 0);
13487 if (TREE_CODE (decl) == VAR_DECL)
13489 if (DECL_SIZE (decl) == NULL_TREE
13490 && TYPE_SIZE (TREE_TYPE (decl)) != NULL_TREE)
13491 layout_decl (decl, 0);
13493 if (DECL_SIZE (decl) == NULL_TREE
13494 && (TREE_STATIC (decl)
13496 /* A static variable with an incomplete type is an error if it is
13497 initialized. Also if it is not file scope. Otherwise, let it
13498 through, but if it is not `extern' then it may cause an error
13499 message later. */
13500 (DECL_INITIAL (decl) != 0 || DECL_CONTEXT (decl) != 0)
13502 /* An automatic variable with an incomplete type is an error. */
13503 !DECL_EXTERNAL (decl)))
13505 assert ("storage size not known" == NULL);
13506 abort ();
13509 if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
13510 && (DECL_SIZE (decl) != 0)
13511 && (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST))
13513 assert ("storage size not constant" == NULL);
13514 abort ();
13518 /* Output the assembler code and/or RTL code for variables and functions,
13519 unless the type is an undefined structure or union. If not, it will get
13520 done when the type is completed. */
13522 if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
13524 rest_of_decl_compilation (decl, NULL,
13525 DECL_CONTEXT (decl) == 0,
13528 if (DECL_CONTEXT (decl) != 0)
13530 /* Recompute the RTL of a local array now if it used to be an
13531 incomplete type. */
13532 if (was_incomplete
13533 && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
13535 /* If we used it already as memory, it must stay in memory. */
13536 TREE_ADDRESSABLE (decl) = TREE_USED (decl);
13537 /* If it's still incomplete now, no init will save it. */
13538 if (DECL_SIZE (decl) == 0)
13539 DECL_INITIAL (decl) = 0;
13540 expand_decl (decl);
13542 /* Compute and store the initial value. */
13543 if (TREE_CODE (decl) != FUNCTION_DECL)
13544 expand_decl_init (decl);
13547 else if (TREE_CODE (decl) == TYPE_DECL)
13549 rest_of_decl_compilation (decl, NULL,
13550 DECL_CONTEXT (decl) == 0,
13554 /* At the end of a declaration, throw away any variable type sizes of types
13555 defined inside that declaration. There is no use computing them in the
13556 following function definition. */
13557 if (current_binding_level == global_binding_level)
13558 get_pending_sizes ();
13561 /* Finish up a function declaration and compile that function
13562 all the way to assembler language output. The free the storage
13563 for the function definition.
13565 This is called after parsing the body of the function definition.
13567 NESTED is nonzero if the function being finished is nested in another. */
13569 static void
13570 finish_function (int nested)
13572 register tree fndecl = current_function_decl;
13574 assert (fndecl != NULL_TREE);
13575 if (TREE_CODE (fndecl) != ERROR_MARK)
13577 if (nested)
13578 assert (DECL_CONTEXT (fndecl) != NULL_TREE);
13579 else
13580 assert (DECL_CONTEXT (fndecl) == NULL_TREE);
13583 /* TREE_READONLY (fndecl) = 1;
13584 This caused &foo to be of type ptr-to-const-function
13585 which then got a warning when stored in a ptr-to-function variable. */
13587 poplevel (1, 0, 1);
13589 if (TREE_CODE (fndecl) != ERROR_MARK)
13591 BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
13593 /* Must mark the RESULT_DECL as being in this function. */
13595 DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
13597 /* Obey `register' declarations if `setjmp' is called in this fn. */
13598 /* Generate rtl for function exit. */
13599 expand_function_end (input_filename, lineno, 0);
13601 /* If this is a nested function, protect the local variables in the stack
13602 above us from being collected while we're compiling this function. */
13603 if (nested)
13604 ggc_push_context ();
13606 /* Run the optimizers and output the assembler code for this function. */
13607 rest_of_compilation (fndecl);
13609 /* Undo the GC context switch. */
13610 if (nested)
13611 ggc_pop_context ();
13614 if (TREE_CODE (fndecl) != ERROR_MARK
13615 && !nested
13616 && DECL_SAVED_INSNS (fndecl) == 0)
13618 /* Stop pointing to the local nodes about to be freed. */
13619 /* But DECL_INITIAL must remain nonzero so we know this was an actual
13620 function definition. */
13621 /* For a nested function, this is done in pop_f_function_context. */
13622 /* If rest_of_compilation set this to 0, leave it 0. */
13623 if (DECL_INITIAL (fndecl) != 0)
13624 DECL_INITIAL (fndecl) = error_mark_node;
13625 DECL_ARGUMENTS (fndecl) = 0;
13628 if (!nested)
13630 /* Let the error reporting routines know that we're outside a function.
13631 For a nested function, this value is used in pop_c_function_context
13632 and then reset via pop_function_context. */
13633 ffecom_outer_function_decl_ = current_function_decl = NULL;
13637 /* Plug-in replacement for identifying the name of a decl and, for a
13638 function, what we call it in diagnostics. For now, "program unit"
13639 should suffice, since it's a bit of a hassle to figure out which
13640 of several kinds of things it is. Note that it could conceivably
13641 be a statement function, which probably isn't really a program unit
13642 per se, but if that comes up, it should be easy to check (being a
13643 nested function and all). */
13645 static const char *
13646 ffe_printable_name (tree decl, int v)
13648 /* Just to keep GCC quiet about the unused variable.
13649 In theory, differing values of V should produce different
13650 output. */
13651 switch (v)
13653 default:
13654 if (TREE_CODE (decl) == ERROR_MARK)
13655 return "erroneous code";
13656 return IDENTIFIER_POINTER (DECL_NAME (decl));
13660 /* g77's function to print out name of current function that caused
13661 an error. */
13663 static void
13664 ffe_print_error_function (diagnostic_context *context __attribute__((unused)),
13665 const char *file)
13667 static ffeglobal last_g = NULL;
13668 static ffesymbol last_s = NULL;
13669 ffeglobal g;
13670 ffesymbol s;
13671 const char *kind;
13673 if ((ffecom_primary_entry_ == NULL)
13674 || (ffesymbol_global (ffecom_primary_entry_) == NULL))
13676 g = NULL;
13677 s = NULL;
13678 kind = NULL;
13680 else
13682 g = ffesymbol_global (ffecom_primary_entry_);
13683 if (ffecom_nested_entry_ == NULL)
13685 s = ffecom_primary_entry_;
13686 kind = _(ffeinfo_kind_message (ffesymbol_kind (s)));
13688 else
13690 s = ffecom_nested_entry_;
13691 kind = _("In statement function");
13695 if ((last_g != g) || (last_s != s))
13697 if (file)
13698 fprintf (stderr, "%s: ", file);
13700 if (s == NULL)
13701 fprintf (stderr, _("Outside of any program unit:\n"));
13702 else
13704 const char *name = ffesymbol_text (s);
13706 fprintf (stderr, "%s `%s':\n", kind, name);
13709 last_g = g;
13710 last_s = s;
13714 /* Similar to `lookup_name' but look only at current binding level. */
13716 static tree
13717 lookup_name_current_level (tree name)
13719 register tree t;
13721 if (current_binding_level == global_binding_level)
13722 return IDENTIFIER_GLOBAL_VALUE (name);
13724 if (IDENTIFIER_LOCAL_VALUE (name) == 0)
13725 return 0;
13727 for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
13728 if (DECL_NAME (t) == name)
13729 break;
13731 return t;
13734 /* Create a new `struct binding_level'. */
13736 static struct binding_level *
13737 make_binding_level ()
13739 /* NOSTRICT */
13740 return (struct binding_level *) xmalloc (sizeof (struct binding_level));
13743 /* Save and restore the variables in this file and elsewhere
13744 that keep track of the progress of compilation of the current function.
13745 Used for nested functions. */
13747 struct f_function
13749 struct f_function *next;
13750 tree named_labels;
13751 tree shadowed_labels;
13752 struct binding_level *binding_level;
13755 struct f_function *f_function_chain;
13757 /* Restore the variables used during compilation of a C function. */
13759 static void
13760 pop_f_function_context ()
13762 struct f_function *p = f_function_chain;
13763 tree link;
13765 /* Bring back all the labels that were shadowed. */
13766 for (link = shadowed_labels; link; link = TREE_CHAIN (link))
13767 if (DECL_NAME (TREE_VALUE (link)) != 0)
13768 IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)))
13769 = TREE_VALUE (link);
13771 if (current_function_decl != error_mark_node
13772 && DECL_SAVED_INSNS (current_function_decl) == 0)
13774 /* Stop pointing to the local nodes about to be freed. */
13775 /* But DECL_INITIAL must remain nonzero so we know this was an actual
13776 function definition. */
13777 DECL_INITIAL (current_function_decl) = error_mark_node;
13778 DECL_ARGUMENTS (current_function_decl) = 0;
13781 pop_function_context ();
13783 f_function_chain = p->next;
13785 named_labels = p->named_labels;
13786 shadowed_labels = p->shadowed_labels;
13787 current_binding_level = p->binding_level;
13789 free (p);
13792 /* Save and reinitialize the variables
13793 used during compilation of a C function. */
13795 static void
13796 push_f_function_context ()
13798 struct f_function *p
13799 = (struct f_function *) xmalloc (sizeof (struct f_function));
13801 push_function_context ();
13803 p->next = f_function_chain;
13804 f_function_chain = p;
13806 p->named_labels = named_labels;
13807 p->shadowed_labels = shadowed_labels;
13808 p->binding_level = current_binding_level;
13811 static void
13812 push_parm_decl (tree parm)
13814 int old_immediate_size_expand = immediate_size_expand;
13816 /* Don't try computing parm sizes now -- wait till fn is called. */
13818 immediate_size_expand = 0;
13820 /* Fill in arg stuff. */
13822 DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
13823 DECL_ARG_TYPE_AS_WRITTEN (parm) = TREE_TYPE (parm);
13824 TREE_READONLY (parm) = 1; /* All implementation args are read-only. */
13826 parm = pushdecl (parm);
13828 immediate_size_expand = old_immediate_size_expand;
13830 finish_decl (parm, NULL_TREE, FALSE);
13833 /* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, if appropriate. */
13835 static tree
13836 pushdecl_top_level (x)
13837 tree x;
13839 register tree t;
13840 register struct binding_level *b = current_binding_level;
13841 register tree f = current_function_decl;
13843 current_binding_level = global_binding_level;
13844 current_function_decl = NULL_TREE;
13845 t = pushdecl (x);
13846 current_binding_level = b;
13847 current_function_decl = f;
13848 return t;
13851 /* Store the list of declarations of the current level.
13852 This is done for the parameter declarations of a function being defined,
13853 after they are modified in the light of any missing parameters. */
13855 static tree
13856 storedecls (decls)
13857 tree decls;
13859 return current_binding_level->names = decls;
13862 /* Store the parameter declarations into the current function declaration.
13863 This is called after parsing the parameter declarations, before
13864 digesting the body of the function.
13866 For an old-style definition, modify the function's type
13867 to specify at least the number of arguments. */
13869 static void
13870 store_parm_decls (int is_main_program UNUSED)
13872 register tree fndecl = current_function_decl;
13874 if (fndecl == error_mark_node)
13875 return;
13877 /* This is a chain of PARM_DECLs from old-style parm declarations. */
13878 DECL_ARGUMENTS (fndecl) = storedecls (nreverse (getdecls ()));
13880 /* Initialize the RTL code for the function. */
13882 init_function_start (fndecl, input_filename, lineno);
13884 /* Set up parameters and prepare for return, for the function. */
13886 expand_function_start (fndecl, 0);
13889 static tree
13890 start_decl (tree decl, bool is_top_level)
13892 register tree tem;
13893 bool at_top_level = (current_binding_level == global_binding_level);
13894 bool top_level = is_top_level || at_top_level;
13896 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
13897 level anyway. */
13898 assert (!is_top_level || !at_top_level);
13900 if (DECL_INITIAL (decl) != NULL_TREE)
13902 assert (DECL_INITIAL (decl) == error_mark_node);
13903 assert (!DECL_EXTERNAL (decl));
13905 else if (top_level)
13906 assert ((TREE_STATIC (decl) == 1) || DECL_EXTERNAL (decl) == 1);
13908 /* For Fortran, we by default put things in .common when possible. */
13909 DECL_COMMON (decl) = 1;
13911 /* Add this decl to the current binding level. TEM may equal DECL or it may
13912 be a previous decl of the same name. */
13913 if (is_top_level)
13914 tem = pushdecl_top_level (decl);
13915 else
13916 tem = pushdecl (decl);
13918 /* For a local variable, define the RTL now. */
13919 if (!top_level
13920 /* But not if this is a duplicate decl and we preserved the rtl from the
13921 previous one (which may or may not happen). */
13922 && !DECL_RTL_SET_P (tem))
13924 if (TYPE_SIZE (TREE_TYPE (tem)) != 0)
13925 expand_decl (tem);
13926 else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
13927 && DECL_INITIAL (tem) != 0)
13928 expand_decl (tem);
13931 return tem;
13934 /* Create the FUNCTION_DECL for a function definition.
13935 DECLSPECS and DECLARATOR are the parts of the declaration;
13936 they describe the function's name and the type it returns,
13937 but twisted together in a fashion that parallels the syntax of C.
13939 This function creates a binding context for the function body
13940 as well as setting up the FUNCTION_DECL in current_function_decl.
13942 Returns 1 on success. If the DECLARATOR is not suitable for a function
13943 (it defines a datum instead), we return 0, which tells
13944 ffe_parse_file to report a parse error.
13946 NESTED is nonzero for a function nested within another function. */
13948 static void
13949 start_function (tree name, tree type, int nested, int public)
13951 tree decl1;
13952 tree restype;
13953 int old_immediate_size_expand = immediate_size_expand;
13955 named_labels = 0;
13956 shadowed_labels = 0;
13958 /* Don't expand any sizes in the return type of the function. */
13959 immediate_size_expand = 0;
13961 if (nested)
13963 assert (!public);
13964 assert (current_function_decl != NULL_TREE);
13965 assert (DECL_CONTEXT (current_function_decl) == NULL_TREE);
13967 else
13969 assert (current_function_decl == NULL_TREE);
13972 if (TREE_CODE (type) == ERROR_MARK)
13973 decl1 = current_function_decl = error_mark_node;
13974 else
13976 decl1 = build_decl (FUNCTION_DECL,
13977 name,
13978 type);
13979 TREE_PUBLIC (decl1) = public ? 1 : 0;
13980 if (nested)
13981 DECL_INLINE (decl1) = 1;
13982 TREE_STATIC (decl1) = 1;
13983 DECL_EXTERNAL (decl1) = 0;
13985 announce_function (decl1);
13987 /* Make the init_value nonzero so pushdecl knows this is not tentative.
13988 error_mark_node is replaced below (in poplevel) with the BLOCK. */
13989 DECL_INITIAL (decl1) = error_mark_node;
13991 /* Record the decl so that the function name is defined. If we already have
13992 a decl for this name, and it is a FUNCTION_DECL, use the old decl. */
13994 current_function_decl = pushdecl (decl1);
13997 if (!nested)
13998 ffecom_outer_function_decl_ = current_function_decl;
14000 pushlevel (0);
14001 current_binding_level->prep_state = 2;
14003 if (TREE_CODE (current_function_decl) != ERROR_MARK)
14005 make_decl_rtl (current_function_decl, NULL);
14007 restype = TREE_TYPE (TREE_TYPE (current_function_decl));
14008 DECL_RESULT (current_function_decl)
14009 = build_decl (RESULT_DECL, NULL_TREE, restype);
14012 if (!nested && (TREE_CODE (current_function_decl) != ERROR_MARK))
14013 TREE_ADDRESSABLE (current_function_decl) = 1;
14015 immediate_size_expand = old_immediate_size_expand;
14018 /* Here are the public functions the GNU back end needs. */
14020 tree
14021 convert (type, expr)
14022 tree type, expr;
14024 register tree e = expr;
14025 register enum tree_code code = TREE_CODE (type);
14027 if (type == TREE_TYPE (e)
14028 || TREE_CODE (e) == ERROR_MARK)
14029 return e;
14030 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
14031 return fold (build1 (NOP_EXPR, type, e));
14032 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
14033 || code == ERROR_MARK)
14034 return error_mark_node;
14035 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
14037 assert ("void value not ignored as it ought to be" == NULL);
14038 return error_mark_node;
14040 if (code == VOID_TYPE)
14041 return build1 (CONVERT_EXPR, type, e);
14042 if ((code != RECORD_TYPE)
14043 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
14044 e = ffecom_1 (REALPART_EXPR, TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e))),
14046 if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
14047 return fold (convert_to_integer (type, e));
14048 if (code == POINTER_TYPE)
14049 return fold (convert_to_pointer (type, e));
14050 if (code == REAL_TYPE)
14051 return fold (convert_to_real (type, e));
14052 if (code == COMPLEX_TYPE)
14053 return fold (convert_to_complex (type, e));
14054 if (code == RECORD_TYPE)
14055 return fold (ffecom_convert_to_complex_ (type, e));
14057 assert ("conversion to non-scalar type requested" == NULL);
14058 return error_mark_node;
14061 /* Return the list of declarations of the current level.
14062 Note that this list is in reverse order unless/until
14063 you nreverse it; and when you do nreverse it, you must
14064 store the result back using `storedecls' or you will lose. */
14066 tree
14067 getdecls ()
14069 return current_binding_level->names;
14072 /* Nonzero if we are currently in the global binding level. */
14075 global_bindings_p ()
14077 return current_binding_level == global_binding_level;
14080 /* Mark ARG for GC. */
14081 static void
14082 mark_binding_level (void *arg)
14084 struct binding_level *level = *(struct binding_level **) arg;
14086 while (level)
14088 ggc_mark_tree (level->names);
14089 ggc_mark_tree (level->blocks);
14090 ggc_mark_tree (level->this_block);
14091 level = level->level_chain;
14095 static void
14096 ffecom_init_decl_processing ()
14098 static tree *const tree_roots[] = {
14099 &current_function_decl,
14100 &string_type_node,
14101 &ffecom_tree_fun_type_void,
14102 &ffecom_integer_zero_node,
14103 &ffecom_integer_one_node,
14104 &ffecom_tree_subr_type,
14105 &ffecom_tree_ptr_to_subr_type,
14106 &ffecom_tree_blockdata_type,
14107 &ffecom_tree_xargc_,
14108 &ffecom_f2c_integer_type_node,
14109 &ffecom_f2c_ptr_to_integer_type_node,
14110 &ffecom_f2c_address_type_node,
14111 &ffecom_f2c_real_type_node,
14112 &ffecom_f2c_ptr_to_real_type_node,
14113 &ffecom_f2c_doublereal_type_node,
14114 &ffecom_f2c_complex_type_node,
14115 &ffecom_f2c_doublecomplex_type_node,
14116 &ffecom_f2c_longint_type_node,
14117 &ffecom_f2c_logical_type_node,
14118 &ffecom_f2c_flag_type_node,
14119 &ffecom_f2c_ftnlen_type_node,
14120 &ffecom_f2c_ftnlen_zero_node,
14121 &ffecom_f2c_ftnlen_one_node,
14122 &ffecom_f2c_ftnlen_two_node,
14123 &ffecom_f2c_ptr_to_ftnlen_type_node,
14124 &ffecom_f2c_ftnint_type_node,
14125 &ffecom_f2c_ptr_to_ftnint_type_node,
14126 &ffecom_outer_function_decl_,
14127 &ffecom_previous_function_decl_,
14128 &ffecom_which_entrypoint_decl_,
14129 &ffecom_float_zero_,
14130 &ffecom_float_half_,
14131 &ffecom_double_zero_,
14132 &ffecom_double_half_,
14133 &ffecom_func_result_,
14134 &ffecom_func_length_,
14135 &ffecom_multi_type_node_,
14136 &ffecom_multi_retval_,
14137 &named_labels,
14138 &shadowed_labels
14140 size_t i;
14142 malloc_init ();
14144 /* Record our roots. */
14145 for (i = 0; i < ARRAY_SIZE (tree_roots); i++)
14146 ggc_add_tree_root (tree_roots[i], 1);
14147 ggc_add_tree_root (&ffecom_tree_type[0][0],
14148 FFEINFO_basictype*FFEINFO_kindtype);
14149 ggc_add_tree_root (&ffecom_tree_fun_type[0][0],
14150 FFEINFO_basictype*FFEINFO_kindtype);
14151 ggc_add_tree_root (&ffecom_tree_ptr_to_fun_type[0][0],
14152 FFEINFO_basictype*FFEINFO_kindtype);
14153 ggc_add_tree_root (ffecom_gfrt_, FFECOM_gfrt);
14154 ggc_add_root (&current_binding_level, 1, sizeof current_binding_level,
14155 mark_binding_level);
14156 ggc_add_root (&free_binding_level, 1, sizeof current_binding_level,
14157 mark_binding_level);
14158 ggc_add_root (&tracker_head, 1, sizeof tracker_head, mark_tracker_head);
14160 ffe_init_0 ();
14163 /* Delete the node BLOCK from the current binding level.
14164 This is used for the block inside a stmt expr ({...})
14165 so that the block can be reinserted where appropriate. */
14167 static void
14168 delete_block (block)
14169 tree block;
14171 tree t;
14172 if (current_binding_level->blocks == block)
14173 current_binding_level->blocks = TREE_CHAIN (block);
14174 for (t = current_binding_level->blocks; t;)
14176 if (TREE_CHAIN (t) == block)
14177 TREE_CHAIN (t) = TREE_CHAIN (block);
14178 else
14179 t = TREE_CHAIN (t);
14181 TREE_CHAIN (block) = NULL;
14182 /* Clear TREE_USED which is always set by poplevel.
14183 The flag is set again if insert_block is called. */
14184 TREE_USED (block) = 0;
14187 void
14188 insert_block (block)
14189 tree block;
14191 TREE_USED (block) = 1;
14192 current_binding_level->blocks
14193 = chainon (current_binding_level->blocks, block);
14196 /* Each front end provides its own. */
14197 static const char *ffe_init PARAMS ((const char *));
14198 static void ffe_finish PARAMS ((void));
14199 static void ffe_init_options PARAMS ((void));
14200 static void ffe_print_identifier PARAMS ((FILE *, tree, int));
14201 static void ffe_mark_tree (tree);
14203 #undef LANG_HOOKS_NAME
14204 #define LANG_HOOKS_NAME "GNU F77"
14205 #undef LANG_HOOKS_INIT
14206 #define LANG_HOOKS_INIT ffe_init
14207 #undef LANG_HOOKS_FINISH
14208 #define LANG_HOOKS_FINISH ffe_finish
14209 #undef LANG_HOOKS_INIT_OPTIONS
14210 #define LANG_HOOKS_INIT_OPTIONS ffe_init_options
14211 #undef LANG_HOOKS_DECODE_OPTION
14212 #define LANG_HOOKS_DECODE_OPTION ffe_decode_option
14213 #undef LANG_HOOKS_PARSE_FILE
14214 #define LANG_HOOKS_PARSE_FILE ffe_parse_file
14215 #undef LANG_HOOKS_MARK_TREE
14216 #define LANG_HOOKS_MARK_TREE ffe_mark_tree
14217 #undef LANG_HOOKS_MARK_ADDRESSABLE
14218 #define LANG_HOOKS_MARK_ADDRESSABLE ffe_mark_addressable
14219 #undef LANG_HOOKS_PRINT_IDENTIFIER
14220 #define LANG_HOOKS_PRINT_IDENTIFIER ffe_print_identifier
14221 #undef LANG_HOOKS_DECL_PRINTABLE_NAME
14222 #define LANG_HOOKS_DECL_PRINTABLE_NAME ffe_printable_name
14223 #undef LANG_HOOKS_PRINT_ERROR_FUNCTION
14224 #define LANG_HOOKS_PRINT_ERROR_FUNCTION ffe_print_error_function
14225 #undef LANG_HOOKS_TRUTHVALUE_CONVERSION
14226 #define LANG_HOOKS_TRUTHVALUE_CONVERSION ffe_truthvalue_conversion
14228 #undef LANG_HOOKS_TYPE_FOR_MODE
14229 #define LANG_HOOKS_TYPE_FOR_MODE ffe_type_for_mode
14230 #undef LANG_HOOKS_TYPE_FOR_SIZE
14231 #define LANG_HOOKS_TYPE_FOR_SIZE ffe_type_for_size
14232 #undef LANG_HOOKS_SIGNED_TYPE
14233 #define LANG_HOOKS_SIGNED_TYPE ffe_signed_type
14234 #undef LANG_HOOKS_UNSIGNED_TYPE
14235 #define LANG_HOOKS_UNSIGNED_TYPE ffe_unsigned_type
14236 #undef LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE
14237 #define LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE ffe_signed_or_unsigned_type
14239 /* We do not wish to use alias-set based aliasing at all. Used in the
14240 extreme (every object with its own set, with equivalences recorded) it
14241 might be helpful, but there are problems when it comes to inlining. We
14242 get on ok with flag_argument_noalias, and alias-set aliasing does
14243 currently limit how stack slots can be reused, which is a lose. */
14244 #undef LANG_HOOKS_GET_ALIAS_SET
14245 #define LANG_HOOKS_GET_ALIAS_SET hook_get_alias_set_0
14247 const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
14249 /* Table indexed by tree code giving a string containing a character
14250 classifying the tree code. Possibilities are
14251 t, d, s, c, r, <, 1, 2 and e. See tree.def for details. */
14253 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
14255 const char tree_code_type[] = {
14256 #include "tree.def"
14258 #undef DEFTREECODE
14260 /* Table indexed by tree code giving number of expression
14261 operands beyond the fixed part of the node structure.
14262 Not used for types or decls. */
14264 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
14266 const unsigned char tree_code_length[] = {
14267 #include "tree.def"
14269 #undef DEFTREECODE
14271 /* Names of tree components.
14272 Used for printing out the tree and error messages. */
14273 #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
14275 const char *const tree_code_name[] = {
14276 #include "tree.def"
14278 #undef DEFTREECODE
14280 static const char *
14281 ffe_init (filename)
14282 const char *filename;
14284 /* Open input file. */
14285 if (filename == 0 || !strcmp (filename, "-"))
14287 finput = stdin;
14288 filename = "stdin";
14290 else
14291 finput = fopen (filename, "r");
14292 if (finput == 0)
14293 fatal_io_error ("can't open %s", filename);
14295 #ifdef IO_BUFFER_SIZE
14296 setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);
14297 #endif
14299 ffecom_init_decl_processing ();
14301 /* If the file is output from cpp, it should contain a first line
14302 `# 1 "real-filename"', and the current design of gcc (toplev.c
14303 in particular and the way it sets up information relied on by
14304 INCLUDE) requires that we read this now, and store the
14305 "real-filename" info in master_input_filename. Ask the lexer
14306 to try doing this. */
14307 ffelex_hash_kludge (finput);
14309 /* FIXME: The ffelex_hash_kludge code needs to be cleaned up to
14310 return the new file name. */
14311 if (main_input_filename)
14312 filename = main_input_filename;
14314 return filename;
14317 static void
14318 ffe_finish ()
14320 ffe_terminate_0 ();
14322 if (ffe_is_ffedebug ())
14323 malloc_pool_display (malloc_pool_image ());
14325 fclose (finput);
14328 static void
14329 ffe_init_options ()
14331 /* Set default options for Fortran. */
14332 flag_move_all_movables = 1;
14333 flag_reduce_all_givs = 1;
14334 flag_argument_noalias = 2;
14335 flag_merge_constants = 2;
14336 flag_errno_math = 0;
14337 flag_complex_divide_method = 1;
14340 static bool
14341 ffe_mark_addressable (exp)
14342 tree exp;
14344 register tree x = exp;
14345 while (1)
14346 switch (TREE_CODE (x))
14348 case ADDR_EXPR:
14349 case COMPONENT_REF:
14350 case ARRAY_REF:
14351 x = TREE_OPERAND (x, 0);
14352 break;
14354 case CONSTRUCTOR:
14355 TREE_ADDRESSABLE (x) = 1;
14356 return true;
14358 case VAR_DECL:
14359 case CONST_DECL:
14360 case PARM_DECL:
14361 case RESULT_DECL:
14362 if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)
14363 && DECL_NONLOCAL (x))
14365 if (TREE_PUBLIC (x))
14367 assert ("address of global register var requested" == NULL);
14368 return false;
14370 assert ("address of register variable requested" == NULL);
14372 else if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x))
14374 if (TREE_PUBLIC (x))
14376 assert ("address of global register var requested" == NULL);
14377 return false;
14379 assert ("address of register var requested" == NULL);
14381 put_var_into_stack (x);
14383 /* drops in */
14384 case FUNCTION_DECL:
14385 TREE_ADDRESSABLE (x) = 1;
14386 #if 0 /* poplevel deals with this now. */
14387 if (DECL_CONTEXT (x) == 0)
14388 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
14389 #endif
14391 default:
14392 return true;
14396 /* Exit a binding level.
14397 Pop the level off, and restore the state of the identifier-decl mappings
14398 that were in effect when this level was entered.
14400 If KEEP is nonzero, this level had explicit declarations, so
14401 and create a "block" (a BLOCK node) for the level
14402 to record its declarations and subblocks for symbol table output.
14404 If FUNCTIONBODY is nonzero, this level is the body of a function,
14405 so create a block as if KEEP were set and also clear out all
14406 label names.
14408 If REVERSE is nonzero, reverse the order of decls before putting
14409 them into the BLOCK. */
14411 tree
14412 poplevel (keep, reverse, functionbody)
14413 int keep;
14414 int reverse;
14415 int functionbody;
14417 register tree link;
14418 /* The chain of decls was accumulated in reverse order.
14419 Put it into forward order, just for cleanliness. */
14420 tree decls;
14421 tree subblocks = current_binding_level->blocks;
14422 tree block = 0;
14423 tree decl;
14424 int block_previously_created;
14426 /* Get the decls in the order they were written.
14427 Usually current_binding_level->names is in reverse order.
14428 But parameter decls were previously put in forward order. */
14430 if (reverse)
14431 current_binding_level->names
14432 = decls = nreverse (current_binding_level->names);
14433 else
14434 decls = current_binding_level->names;
14436 /* Output any nested inline functions within this block
14437 if they weren't already output. */
14439 for (decl = decls; decl; decl = TREE_CHAIN (decl))
14440 if (TREE_CODE (decl) == FUNCTION_DECL
14441 && ! TREE_ASM_WRITTEN (decl)
14442 && DECL_INITIAL (decl) != 0
14443 && TREE_ADDRESSABLE (decl))
14445 /* If this decl was copied from a file-scope decl
14446 on account of a block-scope extern decl,
14447 propagate TREE_ADDRESSABLE to the file-scope decl.
14449 DECL_ABSTRACT_ORIGIN can be set to itself if warn_return_type is
14450 true, since then the decl goes through save_for_inline_copying. */
14451 if (DECL_ABSTRACT_ORIGIN (decl) != 0
14452 && DECL_ABSTRACT_ORIGIN (decl) != decl)
14453 TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
14454 else if (DECL_SAVED_INSNS (decl) != 0)
14456 push_function_context ();
14457 output_inline_function (decl);
14458 pop_function_context ();
14462 /* If there were any declarations or structure tags in that level,
14463 or if this level is a function body,
14464 create a BLOCK to record them for the life of this function. */
14466 block = 0;
14467 block_previously_created = (current_binding_level->this_block != 0);
14468 if (block_previously_created)
14469 block = current_binding_level->this_block;
14470 else if (keep || functionbody)
14471 block = make_node (BLOCK);
14472 if (block != 0)
14474 BLOCK_VARS (block) = decls;
14475 BLOCK_SUBBLOCKS (block) = subblocks;
14478 /* In each subblock, record that this is its superior. */
14480 for (link = subblocks; link; link = TREE_CHAIN (link))
14481 BLOCK_SUPERCONTEXT (link) = block;
14483 /* Clear out the meanings of the local variables of this level. */
14485 for (link = decls; link; link = TREE_CHAIN (link))
14487 if (DECL_NAME (link) != 0)
14489 /* If the ident. was used or addressed via a local extern decl,
14490 don't forget that fact. */
14491 if (DECL_EXTERNAL (link))
14493 if (TREE_USED (link))
14494 TREE_USED (DECL_NAME (link)) = 1;
14495 if (TREE_ADDRESSABLE (link))
14496 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
14498 IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0;
14502 /* If the level being exited is the top level of a function,
14503 check over all the labels, and clear out the current
14504 (function local) meanings of their names. */
14506 if (functionbody)
14508 /* If this is the top level block of a function,
14509 the vars are the function's parameters.
14510 Don't leave them in the BLOCK because they are
14511 found in the FUNCTION_DECL instead. */
14513 BLOCK_VARS (block) = 0;
14516 /* Pop the current level, and free the structure for reuse. */
14519 register struct binding_level *level = current_binding_level;
14520 current_binding_level = current_binding_level->level_chain;
14522 level->level_chain = free_binding_level;
14523 free_binding_level = level;
14526 /* Dispose of the block that we just made inside some higher level. */
14527 if (functionbody
14528 && current_function_decl != error_mark_node)
14529 DECL_INITIAL (current_function_decl) = block;
14530 else if (block)
14532 if (!block_previously_created)
14533 current_binding_level->blocks
14534 = chainon (current_binding_level->blocks, block);
14536 /* If we did not make a block for the level just exited,
14537 any blocks made for inner levels
14538 (since they cannot be recorded as subblocks in that level)
14539 must be carried forward so they will later become subblocks
14540 of something else. */
14541 else if (subblocks)
14542 current_binding_level->blocks
14543 = chainon (current_binding_level->blocks, subblocks);
14545 if (block)
14546 TREE_USED (block) = 1;
14547 return block;
14550 static void
14551 ffe_print_identifier (file, node, indent)
14552 FILE *file;
14553 tree node;
14554 int indent;
14556 print_node (file, "global", IDENTIFIER_GLOBAL_VALUE (node), indent + 4);
14557 print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4);
14560 /* Record a decl-node X as belonging to the current lexical scope.
14561 Check for errors (such as an incompatible declaration for the same
14562 name already seen in the same scope).
14564 Returns either X or an old decl for the same name.
14565 If an old decl is returned, it may have been smashed
14566 to agree with what X says. */
14568 tree
14569 pushdecl (x)
14570 tree x;
14572 register tree t;
14573 register tree name = DECL_NAME (x);
14574 register struct binding_level *b = current_binding_level;
14576 if ((TREE_CODE (x) == FUNCTION_DECL)
14577 && (DECL_INITIAL (x) == 0)
14578 && DECL_EXTERNAL (x))
14579 DECL_CONTEXT (x) = NULL_TREE;
14580 else
14581 DECL_CONTEXT (x) = current_function_decl;
14583 if (name)
14585 if (IDENTIFIER_INVENTED (name))
14587 DECL_ARTIFICIAL (x) = 1;
14588 DECL_IN_SYSTEM_HEADER (x) = 1;
14591 t = lookup_name_current_level (name);
14593 assert ((t == NULL_TREE) || (DECL_CONTEXT (x) == NULL_TREE));
14595 /* Don't push non-parms onto list for parms until we understand
14596 why we're doing this and whether it works. */
14598 assert ((b == global_binding_level)
14599 || !ffecom_transform_only_dummies_
14600 || TREE_CODE (x) == PARM_DECL);
14602 if ((t != NULL_TREE) && duplicate_decls (x, t))
14603 return t;
14605 /* If we are processing a typedef statement, generate a whole new
14606 ..._TYPE node (which will be just an variant of the existing
14607 ..._TYPE node with identical properties) and then install the
14608 TYPE_DECL node generated to represent the typedef name as the
14609 TYPE_NAME of this brand new (duplicate) ..._TYPE node.
14611 The whole point here is to end up with a situation where each and every
14612 ..._TYPE node the compiler creates will be uniquely associated with
14613 AT MOST one node representing a typedef name. This way, even though
14614 the compiler substitutes corresponding ..._TYPE nodes for TYPE_DECL
14615 (i.e. "typedef name") nodes very early on, later parts of the
14616 compiler can always do the reverse translation and get back the
14617 corresponding typedef name. For example, given:
14619 typedef struct S MY_TYPE; MY_TYPE object;
14621 Later parts of the compiler might only know that `object' was of type
14622 `struct S' if it were not for code just below. With this code
14623 however, later parts of the compiler see something like:
14625 struct S' == struct S typedef struct S' MY_TYPE; struct S' object;
14627 And they can then deduce (from the node for type struct S') that the
14628 original object declaration was:
14630 MY_TYPE object;
14632 Being able to do this is important for proper support of protoize, and
14633 also for generating precise symbolic debugging information which
14634 takes full account of the programmer's (typedef) vocabulary.
14636 Obviously, we don't want to generate a duplicate ..._TYPE node if the
14637 TYPE_DECL node that we are now processing really represents a
14638 standard built-in type.
14640 Since all standard types are effectively declared at line zero in the
14641 source file, we can easily check to see if we are working on a
14642 standard type by checking the current value of lineno. */
14644 if (TREE_CODE (x) == TYPE_DECL)
14646 if (DECL_SOURCE_LINE (x) == 0)
14648 if (TYPE_NAME (TREE_TYPE (x)) == 0)
14649 TYPE_NAME (TREE_TYPE (x)) = x;
14651 else if (TREE_TYPE (x) != error_mark_node)
14653 tree tt = TREE_TYPE (x);
14655 tt = build_type_copy (tt);
14656 TYPE_NAME (tt) = x;
14657 TREE_TYPE (x) = tt;
14661 /* This name is new in its binding level. Install the new declaration
14662 and return it. */
14663 if (b == global_binding_level)
14664 IDENTIFIER_GLOBAL_VALUE (name) = x;
14665 else
14666 IDENTIFIER_LOCAL_VALUE (name) = x;
14669 /* Put decls on list in reverse order. We will reverse them later if
14670 necessary. */
14671 TREE_CHAIN (x) = b->names;
14672 b->names = x;
14674 return x;
14677 /* Nonzero if the current level needs to have a BLOCK made. */
14679 static int
14680 kept_level_p ()
14682 tree decl;
14684 for (decl = current_binding_level->names;
14685 decl;
14686 decl = TREE_CHAIN (decl))
14688 if (TREE_USED (decl) || TREE_CODE (decl) != VAR_DECL
14689 || (DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl)))
14690 /* Currently, there aren't supposed to be non-artificial names
14691 at other than the top block for a function -- they're
14692 believed to always be temps. But it's wise to check anyway. */
14693 return 1;
14695 return 0;
14698 /* Enter a new binding level.
14699 If TAG_TRANSPARENT is nonzero, do so only for the name space of variables,
14700 not for that of tags. */
14702 void
14703 pushlevel (tag_transparent)
14704 int tag_transparent;
14706 register struct binding_level *newlevel = NULL_BINDING_LEVEL;
14708 assert (! tag_transparent);
14710 if (current_binding_level == global_binding_level)
14712 named_labels = 0;
14715 /* Reuse or create a struct for this binding level. */
14717 if (free_binding_level)
14719 newlevel = free_binding_level;
14720 free_binding_level = free_binding_level->level_chain;
14722 else
14724 newlevel = make_binding_level ();
14727 /* Add this level to the front of the chain (stack) of levels that
14728 are active. */
14730 *newlevel = clear_binding_level;
14731 newlevel->level_chain = current_binding_level;
14732 current_binding_level = newlevel;
14735 /* Set the BLOCK node for the innermost scope
14736 (the one we are currently in). */
14738 void
14739 set_block (block)
14740 register tree block;
14742 current_binding_level->this_block = block;
14743 current_binding_level->names = chainon (current_binding_level->names,
14744 BLOCK_VARS (block));
14745 current_binding_level->blocks = chainon (current_binding_level->blocks,
14746 BLOCK_SUBBLOCKS (block));
14749 static tree
14750 ffe_signed_or_unsigned_type (unsignedp, type)
14751 int unsignedp;
14752 tree type;
14754 tree type2;
14756 if (! INTEGRAL_TYPE_P (type))
14757 return type;
14758 if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
14759 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
14760 if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
14761 return unsignedp ? unsigned_type_node : integer_type_node;
14762 if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node))
14763 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
14764 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node))
14765 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
14766 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node))
14767 return (unsignedp ? long_long_unsigned_type_node
14768 : long_long_integer_type_node);
14770 type2 = ffe_type_for_size (TYPE_PRECISION (type), unsignedp);
14771 if (type2 == NULL_TREE)
14772 return type;
14774 return type2;
14777 static tree
14778 ffe_signed_type (type)
14779 tree type;
14781 tree type1 = TYPE_MAIN_VARIANT (type);
14782 ffeinfoKindtype kt;
14783 tree type2;
14785 if (type1 == unsigned_char_type_node || type1 == char_type_node)
14786 return signed_char_type_node;
14787 if (type1 == unsigned_type_node)
14788 return integer_type_node;
14789 if (type1 == short_unsigned_type_node)
14790 return short_integer_type_node;
14791 if (type1 == long_unsigned_type_node)
14792 return long_integer_type_node;
14793 if (type1 == long_long_unsigned_type_node)
14794 return long_long_integer_type_node;
14795 #if 0 /* gcc/c-* files only */
14796 if (type1 == unsigned_intDI_type_node)
14797 return intDI_type_node;
14798 if (type1 == unsigned_intSI_type_node)
14799 return intSI_type_node;
14800 if (type1 == unsigned_intHI_type_node)
14801 return intHI_type_node;
14802 if (type1 == unsigned_intQI_type_node)
14803 return intQI_type_node;
14804 #endif
14806 type2 = ffe_type_for_size (TYPE_PRECISION (type1), 0);
14807 if (type2 != NULL_TREE)
14808 return type2;
14810 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
14812 type2 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
14814 if (type1 == type2)
14815 return ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
14818 return type;
14821 /* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
14822 or validate its data type for an `if' or `while' statement or ?..: exp.
14824 This preparation consists of taking the ordinary
14825 representation of an expression expr and producing a valid tree
14826 boolean expression describing whether expr is nonzero. We could
14827 simply always do build_binary_op (NE_EXPR, expr, integer_zero_node, 1),
14828 but we optimize comparisons, &&, ||, and !.
14830 The resulting type should always be `integer_type_node'. */
14832 static tree
14833 ffe_truthvalue_conversion (expr)
14834 tree expr;
14836 if (TREE_CODE (expr) == ERROR_MARK)
14837 return expr;
14839 #if 0 /* This appears to be wrong for C++. */
14840 /* These really should return error_mark_node after 2.4 is stable.
14841 But not all callers handle ERROR_MARK properly. */
14842 switch (TREE_CODE (TREE_TYPE (expr)))
14844 case RECORD_TYPE:
14845 error ("struct type value used where scalar is required");
14846 return integer_zero_node;
14848 case UNION_TYPE:
14849 error ("union type value used where scalar is required");
14850 return integer_zero_node;
14852 case ARRAY_TYPE:
14853 error ("array type value used where scalar is required");
14854 return integer_zero_node;
14856 default:
14857 break;
14859 #endif /* 0 */
14861 switch (TREE_CODE (expr))
14863 /* It is simpler and generates better code to have only TRUTH_*_EXPR
14864 or comparison expressions as truth values at this level. */
14865 #if 0
14866 case COMPONENT_REF:
14867 /* A one-bit unsigned bit-field is already acceptable. */
14868 if (1 == TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (expr, 1)))
14869 && TREE_UNSIGNED (TREE_OPERAND (expr, 1)))
14870 return expr;
14871 break;
14872 #endif
14874 case EQ_EXPR:
14875 /* It is simpler and generates better code to have only TRUTH_*_EXPR
14876 or comparison expressions as truth values at this level. */
14877 #if 0
14878 if (integer_zerop (TREE_OPERAND (expr, 1)))
14879 return build_unary_op (TRUTH_NOT_EXPR, TREE_OPERAND (expr, 0), 0);
14880 #endif
14881 case NE_EXPR: case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
14882 case TRUTH_ANDIF_EXPR:
14883 case TRUTH_ORIF_EXPR:
14884 case TRUTH_AND_EXPR:
14885 case TRUTH_OR_EXPR:
14886 case TRUTH_XOR_EXPR:
14887 TREE_TYPE (expr) = integer_type_node;
14888 return expr;
14890 case ERROR_MARK:
14891 return expr;
14893 case INTEGER_CST:
14894 return integer_zerop (expr) ? integer_zero_node : integer_one_node;
14896 case REAL_CST:
14897 return real_zerop (expr) ? integer_zero_node : integer_one_node;
14899 case ADDR_EXPR:
14900 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0)))
14901 return build (COMPOUND_EXPR, integer_type_node,
14902 TREE_OPERAND (expr, 0), integer_one_node);
14903 else
14904 return integer_one_node;
14906 case COMPLEX_EXPR:
14907 return ffecom_2 ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
14908 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
14909 integer_type_node,
14910 ffe_truthvalue_conversion (TREE_OPERAND (expr, 0)),
14911 ffe_truthvalue_conversion (TREE_OPERAND (expr, 1)));
14913 case NEGATE_EXPR:
14914 case ABS_EXPR:
14915 case FLOAT_EXPR:
14916 case FFS_EXPR:
14917 /* These don't change whether an object is non-zero or zero. */
14918 return ffe_truthvalue_conversion (TREE_OPERAND (expr, 0));
14920 case LROTATE_EXPR:
14921 case RROTATE_EXPR:
14922 /* These don't change whether an object is zero or non-zero, but
14923 we can't ignore them if their second arg has side-effects. */
14924 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
14925 return build (COMPOUND_EXPR, integer_type_node, TREE_OPERAND (expr, 1),
14926 ffe_truthvalue_conversion (TREE_OPERAND (expr, 0)));
14927 else
14928 return ffe_truthvalue_conversion (TREE_OPERAND (expr, 0));
14930 case COND_EXPR:
14931 /* Distribute the conversion into the arms of a COND_EXPR. */
14932 return fold (build (COND_EXPR, integer_type_node, TREE_OPERAND (expr, 0),
14933 ffe_truthvalue_conversion (TREE_OPERAND (expr, 1)),
14934 ffe_truthvalue_conversion (TREE_OPERAND (expr, 2))));
14936 case CONVERT_EXPR:
14937 /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
14938 since that affects how `default_conversion' will behave. */
14939 if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE
14940 || TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
14941 break;
14942 /* fall through... */
14943 case NOP_EXPR:
14944 /* If this is widening the argument, we can ignore it. */
14945 if (TYPE_PRECISION (TREE_TYPE (expr))
14946 >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
14947 return ffe_truthvalue_conversion (TREE_OPERAND (expr, 0));
14948 break;
14950 case MINUS_EXPR:
14951 /* With IEEE arithmetic, x - x may not equal 0, so we can't optimize
14952 this case. */
14953 if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
14954 && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE)
14955 break;
14956 /* fall through... */
14957 case BIT_XOR_EXPR:
14958 /* This and MINUS_EXPR can be changed into a comparison of the
14959 two objects. */
14960 if (TREE_TYPE (TREE_OPERAND (expr, 0))
14961 == TREE_TYPE (TREE_OPERAND (expr, 1)))
14962 return ffecom_2 (NE_EXPR, integer_type_node,
14963 TREE_OPERAND (expr, 0),
14964 TREE_OPERAND (expr, 1));
14965 return ffecom_2 (NE_EXPR, integer_type_node,
14966 TREE_OPERAND (expr, 0),
14967 fold (build1 (NOP_EXPR,
14968 TREE_TYPE (TREE_OPERAND (expr, 0)),
14969 TREE_OPERAND (expr, 1))));
14971 case BIT_AND_EXPR:
14972 if (integer_onep (TREE_OPERAND (expr, 1)))
14973 return expr;
14974 break;
14976 case MODIFY_EXPR:
14977 #if 0 /* No such thing in Fortran. */
14978 if (warn_parentheses && C_EXP_ORIGINAL_CODE (expr) == MODIFY_EXPR)
14979 warning ("suggest parentheses around assignment used as truth value");
14980 #endif
14981 break;
14983 default:
14984 break;
14987 if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
14988 return (ffecom_2
14989 ((TREE_SIDE_EFFECTS (expr)
14990 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
14991 integer_type_node,
14992 ffe_truthvalue_conversion (ffecom_1 (REALPART_EXPR,
14993 TREE_TYPE (TREE_TYPE (expr)),
14994 expr)),
14995 ffe_truthvalue_conversion (ffecom_1 (IMAGPART_EXPR,
14996 TREE_TYPE (TREE_TYPE (expr)),
14997 expr))));
14999 return ffecom_2 (NE_EXPR, integer_type_node,
15000 expr,
15001 convert (TREE_TYPE (expr), integer_zero_node));
15004 static tree
15005 ffe_type_for_mode (mode, unsignedp)
15006 enum machine_mode mode;
15007 int unsignedp;
15009 int i;
15010 int j;
15011 tree t;
15013 if (mode == TYPE_MODE (integer_type_node))
15014 return unsignedp ? unsigned_type_node : integer_type_node;
15016 if (mode == TYPE_MODE (signed_char_type_node))
15017 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15019 if (mode == TYPE_MODE (short_integer_type_node))
15020 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15022 if (mode == TYPE_MODE (long_integer_type_node))
15023 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15025 if (mode == TYPE_MODE (long_long_integer_type_node))
15026 return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
15028 #if HOST_BITS_PER_WIDE_INT >= 64
15029 if (mode == TYPE_MODE (intTI_type_node))
15030 return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
15031 #endif
15033 if (mode == TYPE_MODE (float_type_node))
15034 return float_type_node;
15036 if (mode == TYPE_MODE (double_type_node))
15037 return double_type_node;
15039 if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
15040 return build_pointer_type (char_type_node);
15042 if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
15043 return build_pointer_type (integer_type_node);
15045 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
15046 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
15048 if (((t = ffecom_tree_type[i][j]) != NULL_TREE)
15049 && (mode == TYPE_MODE (t)))
15051 if ((i == FFEINFO_basictypeINTEGER) && unsignedp)
15052 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][j];
15053 else
15054 return t;
15058 return 0;
15061 static tree
15062 ffe_type_for_size (bits, unsignedp)
15063 unsigned bits;
15064 int unsignedp;
15066 ffeinfoKindtype kt;
15067 tree type_node;
15069 if (bits == TYPE_PRECISION (integer_type_node))
15070 return unsignedp ? unsigned_type_node : integer_type_node;
15072 if (bits == TYPE_PRECISION (signed_char_type_node))
15073 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15075 if (bits == TYPE_PRECISION (short_integer_type_node))
15076 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15078 if (bits == TYPE_PRECISION (long_integer_type_node))
15079 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15081 if (bits == TYPE_PRECISION (long_long_integer_type_node))
15082 return (unsignedp ? long_long_unsigned_type_node
15083 : long_long_integer_type_node);
15085 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15087 type_node = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15089 if ((type_node != NULL_TREE) && (bits == TYPE_PRECISION (type_node)))
15090 return unsignedp ? ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt]
15091 : type_node;
15094 return 0;
15097 static tree
15098 ffe_unsigned_type (type)
15099 tree type;
15101 tree type1 = TYPE_MAIN_VARIANT (type);
15102 ffeinfoKindtype kt;
15103 tree type2;
15105 if (type1 == signed_char_type_node || type1 == char_type_node)
15106 return unsigned_char_type_node;
15107 if (type1 == integer_type_node)
15108 return unsigned_type_node;
15109 if (type1 == short_integer_type_node)
15110 return short_unsigned_type_node;
15111 if (type1 == long_integer_type_node)
15112 return long_unsigned_type_node;
15113 if (type1 == long_long_integer_type_node)
15114 return long_long_unsigned_type_node;
15115 #if 0 /* gcc/c-* files only */
15116 if (type1 == intDI_type_node)
15117 return unsigned_intDI_type_node;
15118 if (type1 == intSI_type_node)
15119 return unsigned_intSI_type_node;
15120 if (type1 == intHI_type_node)
15121 return unsigned_intHI_type_node;
15122 if (type1 == intQI_type_node)
15123 return unsigned_intQI_type_node;
15124 #endif
15126 type2 = ffe_type_for_size (TYPE_PRECISION (type1), 1);
15127 if (type2 != NULL_TREE)
15128 return type2;
15130 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15132 type2 = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15134 if (type1 == type2)
15135 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
15138 return type;
15141 static void
15142 ffe_mark_tree (t)
15143 tree t;
15145 if (TREE_CODE (t) == IDENTIFIER_NODE)
15147 struct lang_identifier *i = (struct lang_identifier *) t;
15148 ggc_mark_tree (IDENTIFIER_GLOBAL_VALUE (i));
15149 ggc_mark_tree (IDENTIFIER_LOCAL_VALUE (i));
15150 ggc_mark_tree (IDENTIFIER_LABEL_VALUE (i));
15152 else if (TYPE_P (t) && TYPE_LANG_SPECIFIC (t))
15153 ggc_mark (TYPE_LANG_SPECIFIC (t));
15156 /* From gcc/cccp.c, the code to handle -I. */
15158 /* Skip leading "./" from a directory name.
15159 This may yield the empty string, which represents the current directory. */
15161 static const char *
15162 skip_redundant_dir_prefix (const char *dir)
15164 while (dir[0] == '.' && dir[1] == '/')
15165 for (dir += 2; *dir == '/'; dir++)
15166 continue;
15167 if (dir[0] == '.' && !dir[1])
15168 dir++;
15169 return dir;
15172 /* The file_name_map structure holds a mapping of file names for a
15173 particular directory. This mapping is read from the file named
15174 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
15175 map filenames on a file system with severe filename restrictions,
15176 such as DOS. The format of the file name map file is just a series
15177 of lines with two tokens on each line. The first token is the name
15178 to map, and the second token is the actual name to use. */
15180 struct file_name_map
15182 struct file_name_map *map_next;
15183 char *map_from;
15184 char *map_to;
15187 #define FILE_NAME_MAP_FILE "header.gcc"
15189 /* Current maximum length of directory names in the search path
15190 for include files. (Altered as we get more of them.) */
15192 static int max_include_len = 0;
15194 struct file_name_list
15196 struct file_name_list *next;
15197 char *fname;
15198 /* Mapping of file names for this directory. */
15199 struct file_name_map *name_map;
15200 /* Non-zero if name_map is valid. */
15201 int got_name_map;
15204 static struct file_name_list *include = NULL; /* First dir to search */
15205 static struct file_name_list *last_include = NULL; /* Last in chain */
15207 /* I/O buffer structure.
15208 The `fname' field is nonzero for source files and #include files
15209 and for the dummy text used for -D and -U.
15210 It is zero for rescanning results of macro expansion
15211 and for expanding macro arguments. */
15212 #define INPUT_STACK_MAX 400
15213 static struct file_buf {
15214 const char *fname;
15215 /* Filename specified with #line command. */
15216 const char *nominal_fname;
15217 /* Record where in the search path this file was found.
15218 For #include_next. */
15219 struct file_name_list *dir;
15220 ffewhereLine line;
15221 ffewhereColumn column;
15222 } instack[INPUT_STACK_MAX];
15224 static int last_error_tick = 0; /* Incremented each time we print it. */
15225 static int input_file_stack_tick = 0; /* Incremented when status changes. */
15227 /* Current nesting level of input sources.
15228 `instack[indepth]' is the level currently being read. */
15229 static int indepth = -1;
15231 typedef struct file_buf FILE_BUF;
15233 /* Nonzero means -I- has been seen,
15234 so don't look for #include "foo" the source-file directory. */
15235 static int ignore_srcdir;
15237 #ifndef INCLUDE_LEN_FUDGE
15238 #define INCLUDE_LEN_FUDGE 0
15239 #endif
15241 static void append_include_chain (struct file_name_list *first,
15242 struct file_name_list *last);
15243 static FILE *open_include_file (char *filename,
15244 struct file_name_list *searchptr);
15245 static void print_containing_files (ffebadSeverity sev);
15246 static char *read_filename_string (int ch, FILE *f);
15247 static struct file_name_map *read_name_map (const char *dirname);
15249 /* Append a chain of `struct file_name_list's
15250 to the end of the main include chain.
15251 FIRST is the beginning of the chain to append, and LAST is the end. */
15253 static void
15254 append_include_chain (first, last)
15255 struct file_name_list *first, *last;
15257 struct file_name_list *dir;
15259 if (!first || !last)
15260 return;
15262 if (include == 0)
15263 include = first;
15264 else
15265 last_include->next = first;
15267 for (dir = first; ; dir = dir->next) {
15268 int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE;
15269 if (len > max_include_len)
15270 max_include_len = len;
15271 if (dir == last)
15272 break;
15275 last->next = NULL;
15276 last_include = last;
15279 /* Try to open include file FILENAME. SEARCHPTR is the directory
15280 being tried from the include file search path. This function maps
15281 filenames on file systems based on information read by
15282 read_name_map. */
15284 static FILE *
15285 open_include_file (filename, searchptr)
15286 char *filename;
15287 struct file_name_list *searchptr;
15289 register struct file_name_map *map;
15290 register char *from;
15291 char *p, *dir;
15293 if (searchptr && ! searchptr->got_name_map)
15295 searchptr->name_map = read_name_map (searchptr->fname
15296 ? searchptr->fname : ".");
15297 searchptr->got_name_map = 1;
15300 /* First check the mapping for the directory we are using. */
15301 if (searchptr && searchptr->name_map)
15303 from = filename;
15304 if (searchptr->fname)
15305 from += strlen (searchptr->fname) + 1;
15306 for (map = searchptr->name_map; map; map = map->map_next)
15308 if (! strcmp (map->map_from, from))
15310 /* Found a match. */
15311 return fopen (map->map_to, "r");
15316 /* Try to find a mapping file for the particular directory we are
15317 looking in. Thus #include <sys/types.h> will look up sys/types.h
15318 in /usr/include/header.gcc and look up types.h in
15319 /usr/include/sys/header.gcc. */
15320 p = strrchr (filename, '/');
15321 #ifdef DIR_SEPARATOR
15322 if (! p) p = strrchr (filename, DIR_SEPARATOR);
15323 else {
15324 char *tmp = strrchr (filename, DIR_SEPARATOR);
15325 if (tmp != NULL && tmp > p) p = tmp;
15327 #endif
15328 if (! p)
15329 p = filename;
15330 if (searchptr
15331 && searchptr->fname
15332 && strlen (searchptr->fname) == (size_t) (p - filename)
15333 && ! strncmp (searchptr->fname, filename, (int) (p - filename)))
15335 /* FILENAME is in SEARCHPTR, which we've already checked. */
15336 return fopen (filename, "r");
15339 if (p == filename)
15341 from = filename;
15342 map = read_name_map (".");
15344 else
15346 dir = (char *) xmalloc (p - filename + 1);
15347 memcpy (dir, filename, p - filename);
15348 dir[p - filename] = '\0';
15349 from = p + 1;
15350 map = read_name_map (dir);
15351 free (dir);
15353 for (; map; map = map->map_next)
15354 if (! strcmp (map->map_from, from))
15355 return fopen (map->map_to, "r");
15357 return fopen (filename, "r");
15360 /* Print the file names and line numbers of the #include
15361 commands which led to the current file. */
15363 static void
15364 print_containing_files (ffebadSeverity sev)
15366 FILE_BUF *ip = NULL;
15367 int i;
15368 int first = 1;
15369 const char *str1;
15370 const char *str2;
15372 /* If stack of files hasn't changed since we last printed
15373 this info, don't repeat it. */
15374 if (last_error_tick == input_file_stack_tick)
15375 return;
15377 for (i = indepth; i >= 0; i--)
15378 if (instack[i].fname != NULL) {
15379 ip = &instack[i];
15380 break;
15383 /* Give up if we don't find a source file. */
15384 if (ip == NULL)
15385 return;
15387 /* Find the other, outer source files. */
15388 for (i--; i >= 0; i--)
15389 if (instack[i].fname != NULL)
15391 ip = &instack[i];
15392 if (first)
15394 first = 0;
15395 str1 = "In file included";
15397 else
15399 str1 = "... ...";
15402 if (i == 1)
15403 str2 = ":";
15404 else
15405 str2 = "";
15407 /* xgettext:no-c-format */
15408 ffebad_start_msg ("%A from %B at %0%C", sev);
15409 ffebad_here (0, ip->line, ip->column);
15410 ffebad_string (str1);
15411 ffebad_string (ip->nominal_fname);
15412 ffebad_string (str2);
15413 ffebad_finish ();
15416 /* Record we have printed the status as of this time. */
15417 last_error_tick = input_file_stack_tick;
15420 /* Read a space delimited string of unlimited length from a stdio
15421 file. */
15423 static char *
15424 read_filename_string (ch, f)
15425 int ch;
15426 FILE *f;
15428 char *alloc, *set;
15429 int len;
15431 len = 20;
15432 set = alloc = xmalloc (len + 1);
15433 if (! ISSPACE (ch))
15435 *set++ = ch;
15436 while ((ch = getc (f)) != EOF && ! ISSPACE (ch))
15438 if (set - alloc == len)
15440 len *= 2;
15441 alloc = xrealloc (alloc, len + 1);
15442 set = alloc + len / 2;
15444 *set++ = ch;
15447 *set = '\0';
15448 ungetc (ch, f);
15449 return alloc;
15452 /* Read the file name map file for DIRNAME. */
15454 static struct file_name_map *
15455 read_name_map (dirname)
15456 const char *dirname;
15458 /* This structure holds a linked list of file name maps, one per
15459 directory. */
15460 struct file_name_map_list
15462 struct file_name_map_list *map_list_next;
15463 char *map_list_name;
15464 struct file_name_map *map_list_map;
15466 static struct file_name_map_list *map_list;
15467 register struct file_name_map_list *map_list_ptr;
15468 char *name;
15469 FILE *f;
15470 size_t dirlen;
15471 int separator_needed;
15473 dirname = skip_redundant_dir_prefix (dirname);
15475 for (map_list_ptr = map_list; map_list_ptr;
15476 map_list_ptr = map_list_ptr->map_list_next)
15477 if (! strcmp (map_list_ptr->map_list_name, dirname))
15478 return map_list_ptr->map_list_map;
15480 map_list_ptr = ((struct file_name_map_list *)
15481 xmalloc (sizeof (struct file_name_map_list)));
15482 map_list_ptr->map_list_name = xstrdup (dirname);
15483 map_list_ptr->map_list_map = NULL;
15485 dirlen = strlen (dirname);
15486 separator_needed = dirlen != 0 && dirname[dirlen - 1] != '/';
15487 name = (char *) xmalloc (dirlen + strlen (FILE_NAME_MAP_FILE) + 2);
15488 strcpy (name, dirname);
15489 name[dirlen] = '/';
15490 strcpy (name + dirlen + separator_needed, FILE_NAME_MAP_FILE);
15491 f = fopen (name, "r");
15492 free (name);
15493 if (!f)
15494 map_list_ptr->map_list_map = NULL;
15495 else
15497 int ch;
15499 while ((ch = getc (f)) != EOF)
15501 char *from, *to;
15502 struct file_name_map *ptr;
15504 if (ISSPACE (ch))
15505 continue;
15506 from = read_filename_string (ch, f);
15507 while ((ch = getc (f)) != EOF && ISSPACE (ch) && ch != '\n')
15509 to = read_filename_string (ch, f);
15511 ptr = ((struct file_name_map *)
15512 xmalloc (sizeof (struct file_name_map)));
15513 ptr->map_from = from;
15515 /* Make the real filename absolute. */
15516 if (*to == '/')
15517 ptr->map_to = to;
15518 else
15520 ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
15521 strcpy (ptr->map_to, dirname);
15522 ptr->map_to[dirlen] = '/';
15523 strcpy (ptr->map_to + dirlen + separator_needed, to);
15524 free (to);
15527 ptr->map_next = map_list_ptr->map_list_map;
15528 map_list_ptr->map_list_map = ptr;
15530 while ((ch = getc (f)) != '\n')
15531 if (ch == EOF)
15532 break;
15534 fclose (f);
15537 map_list_ptr->map_list_next = map_list;
15538 map_list = map_list_ptr;
15540 return map_list_ptr->map_list_map;
15543 static void
15544 ffecom_file_ (const char *name)
15546 FILE_BUF *fp;
15548 /* Do partial setup of input buffer for the sake of generating
15549 early #line directives (when -g is in effect). */
15551 fp = &instack[++indepth];
15552 memset ((char *) fp, 0, sizeof (FILE_BUF));
15553 if (name == NULL)
15554 name = "";
15555 fp->nominal_fname = fp->fname = name;
15558 static void
15559 ffecom_close_include_ (FILE *f)
15561 fclose (f);
15563 indepth--;
15564 input_file_stack_tick++;
15566 ffewhere_line_kill (instack[indepth].line);
15567 ffewhere_column_kill (instack[indepth].column);
15570 static int
15571 ffecom_decode_include_option_ (char *spec)
15573 struct file_name_list *dirtmp;
15575 if (! ignore_srcdir && !strcmp (spec, "-"))
15576 ignore_srcdir = 1;
15577 else
15579 dirtmp = (struct file_name_list *)
15580 xmalloc (sizeof (struct file_name_list));
15581 dirtmp->next = 0; /* New one goes on the end */
15582 dirtmp->fname = spec;
15583 dirtmp->got_name_map = 0;
15584 if (spec[0] == 0)
15585 error ("directory name must immediately follow -I");
15586 else
15587 append_include_chain (dirtmp, dirtmp);
15589 return 1;
15592 /* Open INCLUDEd file. */
15594 static FILE *
15595 ffecom_open_include_ (char *name, ffewhereLine l, ffewhereColumn c)
15597 char *fbeg = name;
15598 size_t flen = strlen (fbeg);
15599 struct file_name_list *search_start = include; /* Chain of dirs to search */
15600 struct file_name_list dsp[1]; /* First in chain, if #include "..." */
15601 struct file_name_list *searchptr = 0;
15602 char *fname; /* Dynamically allocated fname buffer */
15603 FILE *f;
15604 FILE_BUF *fp;
15606 if (flen == 0)
15607 return NULL;
15609 dsp[0].fname = NULL;
15611 /* If -I- was specified, don't search current dir, only spec'd ones. */
15612 if (!ignore_srcdir)
15614 for (fp = &instack[indepth]; fp >= instack; fp--)
15616 int n;
15617 char *ep;
15618 const char *nam;
15620 if ((nam = fp->nominal_fname) != NULL)
15622 /* Found a named file. Figure out dir of the file,
15623 and put it in front of the search list. */
15624 dsp[0].next = search_start;
15625 search_start = dsp;
15626 #ifndef VMS
15627 ep = strrchr (nam, '/');
15628 #ifdef DIR_SEPARATOR
15629 if (ep == NULL) ep = strrchr (nam, DIR_SEPARATOR);
15630 else {
15631 char *tmp = strrchr (nam, DIR_SEPARATOR);
15632 if (tmp != NULL && tmp > ep) ep = tmp;
15634 #endif
15635 #else /* VMS */
15636 ep = strrchr (nam, ']');
15637 if (ep == NULL) ep = strrchr (nam, '>');
15638 if (ep == NULL) ep = strrchr (nam, ':');
15639 if (ep != NULL) ep++;
15640 #endif /* VMS */
15641 if (ep != NULL)
15643 n = ep - nam;
15644 dsp[0].fname = (char *) xmalloc (n + 1);
15645 strncpy (dsp[0].fname, nam, n);
15646 dsp[0].fname[n] = '\0';
15647 if (n + INCLUDE_LEN_FUDGE > max_include_len)
15648 max_include_len = n + INCLUDE_LEN_FUDGE;
15650 else
15651 dsp[0].fname = NULL; /* Current directory */
15652 dsp[0].got_name_map = 0;
15653 break;
15658 /* Allocate this permanently, because it gets stored in the definitions
15659 of macros. */
15660 fname = xmalloc (max_include_len + flen + 4);
15661 /* + 2 above for slash and terminating null. */
15662 /* + 2 added for '.h' on VMS (to support '#include filename') (NOT USED
15663 for g77 yet). */
15665 /* If specified file name is absolute, just open it. */
15667 if (*fbeg == '/'
15668 #ifdef DIR_SEPARATOR
15669 || *fbeg == DIR_SEPARATOR
15670 #endif
15673 strncpy (fname, (char *) fbeg, flen);
15674 fname[flen] = 0;
15675 f = open_include_file (fname, NULL);
15677 else
15679 f = NULL;
15681 /* Search directory path, trying to open the file.
15682 Copy each filename tried into FNAME. */
15684 for (searchptr = search_start; searchptr; searchptr = searchptr->next)
15686 if (searchptr->fname)
15688 /* The empty string in a search path is ignored.
15689 This makes it possible to turn off entirely
15690 a standard piece of the list. */
15691 if (searchptr->fname[0] == 0)
15692 continue;
15693 strcpy (fname, skip_redundant_dir_prefix (searchptr->fname));
15694 if (fname[0] && fname[strlen (fname) - 1] != '/')
15695 strcat (fname, "/");
15696 fname[strlen (fname) + flen] = 0;
15698 else
15699 fname[0] = 0;
15701 strncat (fname, fbeg, flen);
15702 #ifdef VMS
15703 /* Change this 1/2 Unix 1/2 VMS file specification into a
15704 full VMS file specification */
15705 if (searchptr->fname && (searchptr->fname[0] != 0))
15707 /* Fix up the filename */
15708 hack_vms_include_specification (fname);
15710 else
15712 /* This is a normal VMS filespec, so use it unchanged. */
15713 strncpy (fname, (char *) fbeg, flen);
15714 fname[flen] = 0;
15715 #if 0 /* Not for g77. */
15716 /* if it's '#include filename', add the missing .h */
15717 if (strchr (fname, '.') == NULL)
15718 strcat (fname, ".h");
15719 #endif
15721 #endif /* VMS */
15722 f = open_include_file (fname, searchptr);
15723 #ifdef EACCES
15724 if (f == NULL && errno == EACCES)
15726 print_containing_files (FFEBAD_severityWARNING);
15727 /* xgettext:no-c-format */
15728 ffebad_start_msg ("At %0, INCLUDE file %A exists, but is not readable",
15729 FFEBAD_severityWARNING);
15730 ffebad_string (fname);
15731 ffebad_here (0, l, c);
15732 ffebad_finish ();
15734 #endif
15735 if (f != NULL)
15736 break;
15740 if (f == NULL)
15742 /* A file that was not found. */
15744 strncpy (fname, (char *) fbeg, flen);
15745 fname[flen] = 0;
15746 print_containing_files (ffebad_severity (FFEBAD_OPEN_INCLUDE));
15747 ffebad_start (FFEBAD_OPEN_INCLUDE);
15748 ffebad_here (0, l, c);
15749 ffebad_string (fname);
15750 ffebad_finish ();
15753 if (dsp[0].fname != NULL)
15754 free (dsp[0].fname);
15756 if (f == NULL)
15757 return NULL;
15759 if (indepth >= (INPUT_STACK_MAX - 1))
15761 print_containing_files (FFEBAD_severityFATAL);
15762 /* xgettext:no-c-format */
15763 ffebad_start_msg ("At %0, INCLUDE nesting too deep",
15764 FFEBAD_severityFATAL);
15765 ffebad_string (fname);
15766 ffebad_here (0, l, c);
15767 ffebad_finish ();
15768 return NULL;
15771 instack[indepth].line = ffewhere_line_use (l);
15772 instack[indepth].column = ffewhere_column_use (c);
15774 fp = &instack[indepth + 1];
15775 memset ((char *) fp, 0, sizeof (FILE_BUF));
15776 fp->nominal_fname = fp->fname = fname;
15777 fp->dir = searchptr;
15779 indepth++;
15780 input_file_stack_tick++;
15782 return f;
15785 /**INDENT* (Do not reformat this comment even with -fca option.)
15786 Data-gathering files: Given the source file listed below, compiled with
15787 f2c I obtained the output file listed after that, and from the output
15788 file I derived the above code.
15790 -------- (begin input file to f2c)
15791 implicit none
15792 character*10 A1,A2
15793 complex C1,C2
15794 integer I1,I2
15795 real R1,R2
15796 double precision D1,D2
15798 call getem(A1,A2,C1,C2,I1,I2,R1,R2,D1,D2)
15800 call fooI(I1/I2)
15801 call fooR(R1/I1)
15802 call fooD(D1/I1)
15803 call fooC(C1/I1)
15804 call fooR(R1/R2)
15805 call fooD(R1/D1)
15806 call fooD(D1/D2)
15807 call fooD(D1/R1)
15808 call fooC(C1/C2)
15809 call fooC(C1/R1)
15810 call fooZ(C1/D1)
15811 c **
15812 call fooI(I1**I2)
15813 call fooR(R1**I1)
15814 call fooD(D1**I1)
15815 call fooC(C1**I1)
15816 call fooR(R1**R2)
15817 call fooD(R1**D1)
15818 call fooD(D1**D2)
15819 call fooD(D1**R1)
15820 call fooC(C1**C2)
15821 call fooC(C1**R1)
15822 call fooZ(C1**D1)
15823 c FFEINTRIN_impABS
15824 call fooR(ABS(R1))
15825 c FFEINTRIN_impACOS
15826 call fooR(ACOS(R1))
15827 c FFEINTRIN_impAIMAG
15828 call fooR(AIMAG(C1))
15829 c FFEINTRIN_impAINT
15830 call fooR(AINT(R1))
15831 c FFEINTRIN_impALOG
15832 call fooR(ALOG(R1))
15833 c FFEINTRIN_impALOG10
15834 call fooR(ALOG10(R1))
15835 c FFEINTRIN_impAMAX0
15836 call fooR(AMAX0(I1,I2))
15837 c FFEINTRIN_impAMAX1
15838 call fooR(AMAX1(R1,R2))
15839 c FFEINTRIN_impAMIN0
15840 call fooR(AMIN0(I1,I2))
15841 c FFEINTRIN_impAMIN1
15842 call fooR(AMIN1(R1,R2))
15843 c FFEINTRIN_impAMOD
15844 call fooR(AMOD(R1,R2))
15845 c FFEINTRIN_impANINT
15846 call fooR(ANINT(R1))
15847 c FFEINTRIN_impASIN
15848 call fooR(ASIN(R1))
15849 c FFEINTRIN_impATAN
15850 call fooR(ATAN(R1))
15851 c FFEINTRIN_impATAN2
15852 call fooR(ATAN2(R1,R2))
15853 c FFEINTRIN_impCABS
15854 call fooR(CABS(C1))
15855 c FFEINTRIN_impCCOS
15856 call fooC(CCOS(C1))
15857 c FFEINTRIN_impCEXP
15858 call fooC(CEXP(C1))
15859 c FFEINTRIN_impCHAR
15860 call fooA(CHAR(I1))
15861 c FFEINTRIN_impCLOG
15862 call fooC(CLOG(C1))
15863 c FFEINTRIN_impCONJG
15864 call fooC(CONJG(C1))
15865 c FFEINTRIN_impCOS
15866 call fooR(COS(R1))
15867 c FFEINTRIN_impCOSH
15868 call fooR(COSH(R1))
15869 c FFEINTRIN_impCSIN
15870 call fooC(CSIN(C1))
15871 c FFEINTRIN_impCSQRT
15872 call fooC(CSQRT(C1))
15873 c FFEINTRIN_impDABS
15874 call fooD(DABS(D1))
15875 c FFEINTRIN_impDACOS
15876 call fooD(DACOS(D1))
15877 c FFEINTRIN_impDASIN
15878 call fooD(DASIN(D1))
15879 c FFEINTRIN_impDATAN
15880 call fooD(DATAN(D1))
15881 c FFEINTRIN_impDATAN2
15882 call fooD(DATAN2(D1,D2))
15883 c FFEINTRIN_impDCOS
15884 call fooD(DCOS(D1))
15885 c FFEINTRIN_impDCOSH
15886 call fooD(DCOSH(D1))
15887 c FFEINTRIN_impDDIM
15888 call fooD(DDIM(D1,D2))
15889 c FFEINTRIN_impDEXP
15890 call fooD(DEXP(D1))
15891 c FFEINTRIN_impDIM
15892 call fooR(DIM(R1,R2))
15893 c FFEINTRIN_impDINT
15894 call fooD(DINT(D1))
15895 c FFEINTRIN_impDLOG
15896 call fooD(DLOG(D1))
15897 c FFEINTRIN_impDLOG10
15898 call fooD(DLOG10(D1))
15899 c FFEINTRIN_impDMAX1
15900 call fooD(DMAX1(D1,D2))
15901 c FFEINTRIN_impDMIN1
15902 call fooD(DMIN1(D1,D2))
15903 c FFEINTRIN_impDMOD
15904 call fooD(DMOD(D1,D2))
15905 c FFEINTRIN_impDNINT
15906 call fooD(DNINT(D1))
15907 c FFEINTRIN_impDPROD
15908 call fooD(DPROD(R1,R2))
15909 c FFEINTRIN_impDSIGN
15910 call fooD(DSIGN(D1,D2))
15911 c FFEINTRIN_impDSIN
15912 call fooD(DSIN(D1))
15913 c FFEINTRIN_impDSINH
15914 call fooD(DSINH(D1))
15915 c FFEINTRIN_impDSQRT
15916 call fooD(DSQRT(D1))
15917 c FFEINTRIN_impDTAN
15918 call fooD(DTAN(D1))
15919 c FFEINTRIN_impDTANH
15920 call fooD(DTANH(D1))
15921 c FFEINTRIN_impEXP
15922 call fooR(EXP(R1))
15923 c FFEINTRIN_impIABS
15924 call fooI(IABS(I1))
15925 c FFEINTRIN_impICHAR
15926 call fooI(ICHAR(A1))
15927 c FFEINTRIN_impIDIM
15928 call fooI(IDIM(I1,I2))
15929 c FFEINTRIN_impIDNINT
15930 call fooI(IDNINT(D1))
15931 c FFEINTRIN_impINDEX
15932 call fooI(INDEX(A1,A2))
15933 c FFEINTRIN_impISIGN
15934 call fooI(ISIGN(I1,I2))
15935 c FFEINTRIN_impLEN
15936 call fooI(LEN(A1))
15937 c FFEINTRIN_impLGE
15938 call fooL(LGE(A1,A2))
15939 c FFEINTRIN_impLGT
15940 call fooL(LGT(A1,A2))
15941 c FFEINTRIN_impLLE
15942 call fooL(LLE(A1,A2))
15943 c FFEINTRIN_impLLT
15944 call fooL(LLT(A1,A2))
15945 c FFEINTRIN_impMAX0
15946 call fooI(MAX0(I1,I2))
15947 c FFEINTRIN_impMAX1
15948 call fooI(MAX1(R1,R2))
15949 c FFEINTRIN_impMIN0
15950 call fooI(MIN0(I1,I2))
15951 c FFEINTRIN_impMIN1
15952 call fooI(MIN1(R1,R2))
15953 c FFEINTRIN_impMOD
15954 call fooI(MOD(I1,I2))
15955 c FFEINTRIN_impNINT
15956 call fooI(NINT(R1))
15957 c FFEINTRIN_impSIGN
15958 call fooR(SIGN(R1,R2))
15959 c FFEINTRIN_impSIN
15960 call fooR(SIN(R1))
15961 c FFEINTRIN_impSINH
15962 call fooR(SINH(R1))
15963 c FFEINTRIN_impSQRT
15964 call fooR(SQRT(R1))
15965 c FFEINTRIN_impTAN
15966 call fooR(TAN(R1))
15967 c FFEINTRIN_impTANH
15968 call fooR(TANH(R1))
15969 c FFEINTRIN_imp_CMPLX_C
15970 call fooC(cmplx(C1,C2))
15971 c FFEINTRIN_imp_CMPLX_D
15972 call fooZ(cmplx(D1,D2))
15973 c FFEINTRIN_imp_CMPLX_I
15974 call fooC(cmplx(I1,I2))
15975 c FFEINTRIN_imp_CMPLX_R
15976 call fooC(cmplx(R1,R2))
15977 c FFEINTRIN_imp_DBLE_C
15978 call fooD(dble(C1))
15979 c FFEINTRIN_imp_DBLE_D
15980 call fooD(dble(D1))
15981 c FFEINTRIN_imp_DBLE_I
15982 call fooD(dble(I1))
15983 c FFEINTRIN_imp_DBLE_R
15984 call fooD(dble(R1))
15985 c FFEINTRIN_imp_INT_C
15986 call fooI(int(C1))
15987 c FFEINTRIN_imp_INT_D
15988 call fooI(int(D1))
15989 c FFEINTRIN_imp_INT_I
15990 call fooI(int(I1))
15991 c FFEINTRIN_imp_INT_R
15992 call fooI(int(R1))
15993 c FFEINTRIN_imp_REAL_C
15994 call fooR(real(C1))
15995 c FFEINTRIN_imp_REAL_D
15996 call fooR(real(D1))
15997 c FFEINTRIN_imp_REAL_I
15998 call fooR(real(I1))
15999 c FFEINTRIN_imp_REAL_R
16000 call fooR(real(R1))
16002 c FFEINTRIN_imp_INT_D:
16004 c FFEINTRIN_specIDINT
16005 call fooI(IDINT(D1))
16007 c FFEINTRIN_imp_INT_R:
16009 c FFEINTRIN_specIFIX
16010 call fooI(IFIX(R1))
16011 c FFEINTRIN_specINT
16012 call fooI(INT(R1))
16014 c FFEINTRIN_imp_REAL_D:
16016 c FFEINTRIN_specSNGL
16017 call fooR(SNGL(D1))
16019 c FFEINTRIN_imp_REAL_I:
16021 c FFEINTRIN_specFLOAT
16022 call fooR(FLOAT(I1))
16023 c FFEINTRIN_specREAL
16024 call fooR(REAL(I1))
16027 -------- (end input file to f2c)
16029 -------- (begin output from providing above input file as input to:
16030 -------- `f2c | gcc -E -C - | sed -e "s:/[*]*://:g" -e "s:[*]*[/]://:g" \
16031 -------- -e "s:^#.*$::g"')
16033 // -- translated by f2c (version 19950223).
16034 You must link the resulting object file with the libraries:
16035 -lf2c -lm (in that order)
16039 // f2c.h -- Standard Fortran to C header file //
16041 /// barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed."
16043 - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) //
16048 // F2C_INTEGER will normally be `int' but would be `long' on 16-bit systems //
16049 // we assume short, float are OK //
16050 typedef long int // long int // integer;
16051 typedef char *address;
16052 typedef short int shortint;
16053 typedef float real;
16054 typedef double doublereal;
16055 typedef struct { real r, i; } complex;
16056 typedef struct { doublereal r, i; } doublecomplex;
16057 typedef long int // long int // logical;
16058 typedef short int shortlogical;
16059 typedef char logical1;
16060 typedef char integer1;
16061 // typedef long long longint; // // system-dependent //
16066 // Extern is for use with -E //
16071 // I/O stuff //
16080 typedef long int // int or long int // flag;
16081 typedef long int // int or long int // ftnlen;
16082 typedef long int // int or long int // ftnint;
16085 //external read, write//
16086 typedef struct
16087 { flag cierr;
16088 ftnint ciunit;
16089 flag ciend;
16090 char *cifmt;
16091 ftnint cirec;
16092 } cilist;
16094 //internal read, write//
16095 typedef struct
16096 { flag icierr;
16097 char *iciunit;
16098 flag iciend;
16099 char *icifmt;
16100 ftnint icirlen;
16101 ftnint icirnum;
16102 } icilist;
16104 //open//
16105 typedef struct
16106 { flag oerr;
16107 ftnint ounit;
16108 char *ofnm;
16109 ftnlen ofnmlen;
16110 char *osta;
16111 char *oacc;
16112 char *ofm;
16113 ftnint orl;
16114 char *oblnk;
16115 } olist;
16117 //close//
16118 typedef struct
16119 { flag cerr;
16120 ftnint cunit;
16121 char *csta;
16122 } cllist;
16124 //rewind, backspace, endfile//
16125 typedef struct
16126 { flag aerr;
16127 ftnint aunit;
16128 } alist;
16130 // inquire //
16131 typedef struct
16132 { flag inerr;
16133 ftnint inunit;
16134 char *infile;
16135 ftnlen infilen;
16136 ftnint *inex; //parameters in standard's order//
16137 ftnint *inopen;
16138 ftnint *innum;
16139 ftnint *innamed;
16140 char *inname;
16141 ftnlen innamlen;
16142 char *inacc;
16143 ftnlen inacclen;
16144 char *inseq;
16145 ftnlen inseqlen;
16146 char *indir;
16147 ftnlen indirlen;
16148 char *infmt;
16149 ftnlen infmtlen;
16150 char *inform;
16151 ftnint informlen;
16152 char *inunf;
16153 ftnlen inunflen;
16154 ftnint *inrecl;
16155 ftnint *innrec;
16156 char *inblank;
16157 ftnlen inblanklen;
16158 } inlist;
16162 union Multitype { // for multiple entry points //
16163 integer1 g;
16164 shortint h;
16165 integer i;
16166 // longint j; //
16167 real r;
16168 doublereal d;
16169 complex c;
16170 doublecomplex z;
16173 typedef union Multitype Multitype;
16175 typedef long Long; // No longer used; formerly in Namelist //
16177 struct Vardesc { // for Namelist //
16178 char *name;
16179 char *addr;
16180 ftnlen *dims;
16181 int type;
16183 typedef struct Vardesc Vardesc;
16185 struct Namelist {
16186 char *name;
16187 Vardesc **vars;
16188 int nvars;
16190 typedef struct Namelist Namelist;
16199 // procedure parameter types for -A and -C++ //
16204 typedef int // Unknown procedure type // (*U_fp)();
16205 typedef shortint (*J_fp)();
16206 typedef integer (*I_fp)();
16207 typedef real (*R_fp)();
16208 typedef doublereal (*D_fp)(), (*E_fp)();
16209 typedef // Complex // void (*C_fp)();
16210 typedef // Double Complex // void (*Z_fp)();
16211 typedef logical (*L_fp)();
16212 typedef shortlogical (*K_fp)();
16213 typedef // Character // void (*H_fp)();
16214 typedef // Subroutine // int (*S_fp)();
16216 // E_fp is for real functions when -R is not specified //
16217 typedef void C_f; // complex function //
16218 typedef void H_f; // character function //
16219 typedef void Z_f; // double complex function //
16220 typedef doublereal E_f; // real function with -R not specified //
16222 // undef any lower-case symbols that your C compiler predefines, e.g.: //
16225 // (No such symbols should be defined in a strict ANSI C compiler.
16226 We can avoid trouble with f2c-translated code by using
16227 gcc -ansi.) //
16251 // Main program // MAIN__()
16253 // System generated locals //
16254 integer i__1;
16255 real r__1, r__2;
16256 doublereal d__1, d__2;
16257 complex q__1;
16258 doublecomplex z__1, z__2, z__3;
16259 logical L__1;
16260 char ch__1[1];
16262 // Builtin functions //
16263 void c_div();
16264 integer pow_ii();
16265 double pow_ri(), pow_di();
16266 void pow_ci();
16267 double pow_dd();
16268 void pow_zz();
16269 double acos(), r_imag(), r_int(), log(), r_lg10(), r_mod(), r_nint(),
16270 asin(), atan(), atan2(), c_abs();
16271 void c_cos(), c_exp(), c_log(), r_cnjg();
16272 double cos(), cosh();
16273 void c_sin(), c_sqrt();
16274 double d_dim(), exp(), r_dim(), d_int(), d_lg10(), d_mod(), d_nint(),
16275 d_sign(), sin(), sinh(), sqrt(), tan(), tanh();
16276 integer i_dim(), i_dnnt(), i_indx(), i_sign(), i_len();
16277 logical l_ge(), l_gt(), l_le(), l_lt();
16278 integer i_nint();
16279 double r_sign();
16281 // Local variables //
16282 extern // Subroutine // int fooa_(), fooc_(), food_(), fooi_(), foor_(),
16283 fool_(), fooz_(), getem_();
16284 static char a1[10], a2[10];
16285 static complex c1, c2;
16286 static doublereal d1, d2;
16287 static integer i1, i2;
16288 static real r1, r2;
16291 getem_(a1, a2, &c1, &c2, &i1, &i2, &r1, &r2, &d1, &d2, 10L, 10L);
16292 // / //
16293 i__1 = i1 / i2;
16294 fooi_(&i__1);
16295 r__1 = r1 / i1;
16296 foor_(&r__1);
16297 d__1 = d1 / i1;
16298 food_(&d__1);
16299 d__1 = (doublereal) i1;
16300 q__1.r = c1.r / d__1, q__1.i = c1.i / d__1;
16301 fooc_(&q__1);
16302 r__1 = r1 / r2;
16303 foor_(&r__1);
16304 d__1 = r1 / d1;
16305 food_(&d__1);
16306 d__1 = d1 / d2;
16307 food_(&d__1);
16308 d__1 = d1 / r1;
16309 food_(&d__1);
16310 c_div(&q__1, &c1, &c2);
16311 fooc_(&q__1);
16312 q__1.r = c1.r / r1, q__1.i = c1.i / r1;
16313 fooc_(&q__1);
16314 z__1.r = c1.r / d1, z__1.i = c1.i / d1;
16315 fooz_(&z__1);
16316 // ** //
16317 i__1 = pow_ii(&i1, &i2);
16318 fooi_(&i__1);
16319 r__1 = pow_ri(&r1, &i1);
16320 foor_(&r__1);
16321 d__1 = pow_di(&d1, &i1);
16322 food_(&d__1);
16323 pow_ci(&q__1, &c1, &i1);
16324 fooc_(&q__1);
16325 d__1 = (doublereal) r1;
16326 d__2 = (doublereal) r2;
16327 r__1 = pow_dd(&d__1, &d__2);
16328 foor_(&r__1);
16329 d__2 = (doublereal) r1;
16330 d__1 = pow_dd(&d__2, &d1);
16331 food_(&d__1);
16332 d__1 = pow_dd(&d1, &d2);
16333 food_(&d__1);
16334 d__2 = (doublereal) r1;
16335 d__1 = pow_dd(&d1, &d__2);
16336 food_(&d__1);
16337 z__2.r = c1.r, z__2.i = c1.i;
16338 z__3.r = c2.r, z__3.i = c2.i;
16339 pow_zz(&z__1, &z__2, &z__3);
16340 q__1.r = z__1.r, q__1.i = z__1.i;
16341 fooc_(&q__1);
16342 z__2.r = c1.r, z__2.i = c1.i;
16343 z__3.r = r1, z__3.i = 0.;
16344 pow_zz(&z__1, &z__2, &z__3);
16345 q__1.r = z__1.r, q__1.i = z__1.i;
16346 fooc_(&q__1);
16347 z__2.r = c1.r, z__2.i = c1.i;
16348 z__3.r = d1, z__3.i = 0.;
16349 pow_zz(&z__1, &z__2, &z__3);
16350 fooz_(&z__1);
16351 // FFEINTRIN_impABS //
16352 r__1 = (doublereal)(( r1 ) >= 0 ? ( r1 ) : -( r1 )) ;
16353 foor_(&r__1);
16354 // FFEINTRIN_impACOS //
16355 r__1 = acos(r1);
16356 foor_(&r__1);
16357 // FFEINTRIN_impAIMAG //
16358 r__1 = r_imag(&c1);
16359 foor_(&r__1);
16360 // FFEINTRIN_impAINT //
16361 r__1 = r_int(&r1);
16362 foor_(&r__1);
16363 // FFEINTRIN_impALOG //
16364 r__1 = log(r1);
16365 foor_(&r__1);
16366 // FFEINTRIN_impALOG10 //
16367 r__1 = r_lg10(&r1);
16368 foor_(&r__1);
16369 // FFEINTRIN_impAMAX0 //
16370 r__1 = (real) (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
16371 foor_(&r__1);
16372 // FFEINTRIN_impAMAX1 //
16373 r__1 = (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
16374 foor_(&r__1);
16375 // FFEINTRIN_impAMIN0 //
16376 r__1 = (real) (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
16377 foor_(&r__1);
16378 // FFEINTRIN_impAMIN1 //
16379 r__1 = (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
16380 foor_(&r__1);
16381 // FFEINTRIN_impAMOD //
16382 r__1 = r_mod(&r1, &r2);
16383 foor_(&r__1);
16384 // FFEINTRIN_impANINT //
16385 r__1 = r_nint(&r1);
16386 foor_(&r__1);
16387 // FFEINTRIN_impASIN //
16388 r__1 = asin(r1);
16389 foor_(&r__1);
16390 // FFEINTRIN_impATAN //
16391 r__1 = atan(r1);
16392 foor_(&r__1);
16393 // FFEINTRIN_impATAN2 //
16394 r__1 = atan2(r1, r2);
16395 foor_(&r__1);
16396 // FFEINTRIN_impCABS //
16397 r__1 = c_abs(&c1);
16398 foor_(&r__1);
16399 // FFEINTRIN_impCCOS //
16400 c_cos(&q__1, &c1);
16401 fooc_(&q__1);
16402 // FFEINTRIN_impCEXP //
16403 c_exp(&q__1, &c1);
16404 fooc_(&q__1);
16405 // FFEINTRIN_impCHAR //
16406 *(unsigned char *)&ch__1[0] = i1;
16407 fooa_(ch__1, 1L);
16408 // FFEINTRIN_impCLOG //
16409 c_log(&q__1, &c1);
16410 fooc_(&q__1);
16411 // FFEINTRIN_impCONJG //
16412 r_cnjg(&q__1, &c1);
16413 fooc_(&q__1);
16414 // FFEINTRIN_impCOS //
16415 r__1 = cos(r1);
16416 foor_(&r__1);
16417 // FFEINTRIN_impCOSH //
16418 r__1 = cosh(r1);
16419 foor_(&r__1);
16420 // FFEINTRIN_impCSIN //
16421 c_sin(&q__1, &c1);
16422 fooc_(&q__1);
16423 // FFEINTRIN_impCSQRT //
16424 c_sqrt(&q__1, &c1);
16425 fooc_(&q__1);
16426 // FFEINTRIN_impDABS //
16427 d__1 = (( d1 ) >= 0 ? ( d1 ) : -( d1 )) ;
16428 food_(&d__1);
16429 // FFEINTRIN_impDACOS //
16430 d__1 = acos(d1);
16431 food_(&d__1);
16432 // FFEINTRIN_impDASIN //
16433 d__1 = asin(d1);
16434 food_(&d__1);
16435 // FFEINTRIN_impDATAN //
16436 d__1 = atan(d1);
16437 food_(&d__1);
16438 // FFEINTRIN_impDATAN2 //
16439 d__1 = atan2(d1, d2);
16440 food_(&d__1);
16441 // FFEINTRIN_impDCOS //
16442 d__1 = cos(d1);
16443 food_(&d__1);
16444 // FFEINTRIN_impDCOSH //
16445 d__1 = cosh(d1);
16446 food_(&d__1);
16447 // FFEINTRIN_impDDIM //
16448 d__1 = d_dim(&d1, &d2);
16449 food_(&d__1);
16450 // FFEINTRIN_impDEXP //
16451 d__1 = exp(d1);
16452 food_(&d__1);
16453 // FFEINTRIN_impDIM //
16454 r__1 = r_dim(&r1, &r2);
16455 foor_(&r__1);
16456 // FFEINTRIN_impDINT //
16457 d__1 = d_int(&d1);
16458 food_(&d__1);
16459 // FFEINTRIN_impDLOG //
16460 d__1 = log(d1);
16461 food_(&d__1);
16462 // FFEINTRIN_impDLOG10 //
16463 d__1 = d_lg10(&d1);
16464 food_(&d__1);
16465 // FFEINTRIN_impDMAX1 //
16466 d__1 = (( d1 ) >= ( d2 ) ? ( d1 ) : ( d2 )) ;
16467 food_(&d__1);
16468 // FFEINTRIN_impDMIN1 //
16469 d__1 = (( d1 ) <= ( d2 ) ? ( d1 ) : ( d2 )) ;
16470 food_(&d__1);
16471 // FFEINTRIN_impDMOD //
16472 d__1 = d_mod(&d1, &d2);
16473 food_(&d__1);
16474 // FFEINTRIN_impDNINT //
16475 d__1 = d_nint(&d1);
16476 food_(&d__1);
16477 // FFEINTRIN_impDPROD //
16478 d__1 = (doublereal) r1 * r2;
16479 food_(&d__1);
16480 // FFEINTRIN_impDSIGN //
16481 d__1 = d_sign(&d1, &d2);
16482 food_(&d__1);
16483 // FFEINTRIN_impDSIN //
16484 d__1 = sin(d1);
16485 food_(&d__1);
16486 // FFEINTRIN_impDSINH //
16487 d__1 = sinh(d1);
16488 food_(&d__1);
16489 // FFEINTRIN_impDSQRT //
16490 d__1 = sqrt(d1);
16491 food_(&d__1);
16492 // FFEINTRIN_impDTAN //
16493 d__1 = tan(d1);
16494 food_(&d__1);
16495 // FFEINTRIN_impDTANH //
16496 d__1 = tanh(d1);
16497 food_(&d__1);
16498 // FFEINTRIN_impEXP //
16499 r__1 = exp(r1);
16500 foor_(&r__1);
16501 // FFEINTRIN_impIABS //
16502 i__1 = (( i1 ) >= 0 ? ( i1 ) : -( i1 )) ;
16503 fooi_(&i__1);
16504 // FFEINTRIN_impICHAR //
16505 i__1 = *(unsigned char *)a1;
16506 fooi_(&i__1);
16507 // FFEINTRIN_impIDIM //
16508 i__1 = i_dim(&i1, &i2);
16509 fooi_(&i__1);
16510 // FFEINTRIN_impIDNINT //
16511 i__1 = i_dnnt(&d1);
16512 fooi_(&i__1);
16513 // FFEINTRIN_impINDEX //
16514 i__1 = i_indx(a1, a2, 10L, 10L);
16515 fooi_(&i__1);
16516 // FFEINTRIN_impISIGN //
16517 i__1 = i_sign(&i1, &i2);
16518 fooi_(&i__1);
16519 // FFEINTRIN_impLEN //
16520 i__1 = i_len(a1, 10L);
16521 fooi_(&i__1);
16522 // FFEINTRIN_impLGE //
16523 L__1 = l_ge(a1, a2, 10L, 10L);
16524 fool_(&L__1);
16525 // FFEINTRIN_impLGT //
16526 L__1 = l_gt(a1, a2, 10L, 10L);
16527 fool_(&L__1);
16528 // FFEINTRIN_impLLE //
16529 L__1 = l_le(a1, a2, 10L, 10L);
16530 fool_(&L__1);
16531 // FFEINTRIN_impLLT //
16532 L__1 = l_lt(a1, a2, 10L, 10L);
16533 fool_(&L__1);
16534 // FFEINTRIN_impMAX0 //
16535 i__1 = (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
16536 fooi_(&i__1);
16537 // FFEINTRIN_impMAX1 //
16538 i__1 = (integer) (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
16539 fooi_(&i__1);
16540 // FFEINTRIN_impMIN0 //
16541 i__1 = (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
16542 fooi_(&i__1);
16543 // FFEINTRIN_impMIN1 //
16544 i__1 = (integer) (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
16545 fooi_(&i__1);
16546 // FFEINTRIN_impMOD //
16547 i__1 = i1 % i2;
16548 fooi_(&i__1);
16549 // FFEINTRIN_impNINT //
16550 i__1 = i_nint(&r1);
16551 fooi_(&i__1);
16552 // FFEINTRIN_impSIGN //
16553 r__1 = r_sign(&r1, &r2);
16554 foor_(&r__1);
16555 // FFEINTRIN_impSIN //
16556 r__1 = sin(r1);
16557 foor_(&r__1);
16558 // FFEINTRIN_impSINH //
16559 r__1 = sinh(r1);
16560 foor_(&r__1);
16561 // FFEINTRIN_impSQRT //
16562 r__1 = sqrt(r1);
16563 foor_(&r__1);
16564 // FFEINTRIN_impTAN //
16565 r__1 = tan(r1);
16566 foor_(&r__1);
16567 // FFEINTRIN_impTANH //
16568 r__1 = tanh(r1);
16569 foor_(&r__1);
16570 // FFEINTRIN_imp_CMPLX_C //
16571 r__1 = c1.r;
16572 r__2 = c2.r;
16573 q__1.r = r__1, q__1.i = r__2;
16574 fooc_(&q__1);
16575 // FFEINTRIN_imp_CMPLX_D //
16576 z__1.r = d1, z__1.i = d2;
16577 fooz_(&z__1);
16578 // FFEINTRIN_imp_CMPLX_I //
16579 r__1 = (real) i1;
16580 r__2 = (real) i2;
16581 q__1.r = r__1, q__1.i = r__2;
16582 fooc_(&q__1);
16583 // FFEINTRIN_imp_CMPLX_R //
16584 q__1.r = r1, q__1.i = r2;
16585 fooc_(&q__1);
16586 // FFEINTRIN_imp_DBLE_C //
16587 d__1 = (doublereal) c1.r;
16588 food_(&d__1);
16589 // FFEINTRIN_imp_DBLE_D //
16590 d__1 = d1;
16591 food_(&d__1);
16592 // FFEINTRIN_imp_DBLE_I //
16593 d__1 = (doublereal) i1;
16594 food_(&d__1);
16595 // FFEINTRIN_imp_DBLE_R //
16596 d__1 = (doublereal) r1;
16597 food_(&d__1);
16598 // FFEINTRIN_imp_INT_C //
16599 i__1 = (integer) c1.r;
16600 fooi_(&i__1);
16601 // FFEINTRIN_imp_INT_D //
16602 i__1 = (integer) d1;
16603 fooi_(&i__1);
16604 // FFEINTRIN_imp_INT_I //
16605 i__1 = i1;
16606 fooi_(&i__1);
16607 // FFEINTRIN_imp_INT_R //
16608 i__1 = (integer) r1;
16609 fooi_(&i__1);
16610 // FFEINTRIN_imp_REAL_C //
16611 r__1 = c1.r;
16612 foor_(&r__1);
16613 // FFEINTRIN_imp_REAL_D //
16614 r__1 = (real) d1;
16615 foor_(&r__1);
16616 // FFEINTRIN_imp_REAL_I //
16617 r__1 = (real) i1;
16618 foor_(&r__1);
16619 // FFEINTRIN_imp_REAL_R //
16620 r__1 = r1;
16621 foor_(&r__1);
16623 // FFEINTRIN_imp_INT_D: //
16625 // FFEINTRIN_specIDINT //
16626 i__1 = (integer) d1;
16627 fooi_(&i__1);
16629 // FFEINTRIN_imp_INT_R: //
16631 // FFEINTRIN_specIFIX //
16632 i__1 = (integer) r1;
16633 fooi_(&i__1);
16634 // FFEINTRIN_specINT //
16635 i__1 = (integer) r1;
16636 fooi_(&i__1);
16638 // FFEINTRIN_imp_REAL_D: //
16640 // FFEINTRIN_specSNGL //
16641 r__1 = (real) d1;
16642 foor_(&r__1);
16644 // FFEINTRIN_imp_REAL_I: //
16646 // FFEINTRIN_specFLOAT //
16647 r__1 = (real) i1;
16648 foor_(&r__1);
16649 // FFEINTRIN_specREAL //
16650 r__1 = (real) i1;
16651 foor_(&r__1);
16653 } // MAIN__ //
16655 -------- (end output file from f2c)