1 /* com.c -- Implementation File (module.c template V1.0)
2 Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001
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)
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
27 Contains compiler-specific functions.
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
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 ();
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);
84 #if FFECOM_targetCURRENT == FFECOM_targetGCC
89 #include "output.h" /* Must follow tree.h so TREE_CODE is defined! */
92 #include "diagnostic.h"
93 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
95 #define FFECOM_GCC_INCLUDE 1 /* Enable -I. */
97 /* VMS-specific definitions */
100 #define O_RDONLY 0 /* Open arg for Read/Only */
101 #define O_WRONLY 1 /* Open arg for Write/Only */
102 #define read(fd,buf,size) VMS_read (fd,buf,size)
103 #define write(fd,buf,size) VMS_write (fd,buf,size)
104 #define open(fname,mode,prot) VMS_open (fname,mode,prot)
105 #define fopen(fname,mode) VMS_fopen (fname,mode)
106 #define freopen(fname,mode,ofile) VMS_freopen (fname,mode,ofile)
107 #define strncat(dst,src,cnt) VMS_strncat (dst,src,cnt)
108 #define fstat(fd,stbuf) VMS_fstat (fd,stbuf)
109 static int VMS_fstat (), VMS_stat ();
110 static char * VMS_strncat ();
111 static int VMS_read ();
112 static int VMS_write ();
113 static int VMS_open ();
114 static FILE * VMS_fopen ();
115 static FILE * VMS_freopen ();
116 static void hack_vms_include_specification ();
117 typedef struct { unsigned :16, :16, :16; } vms_ino_t;
118 #define ino_t vms_ino_t
119 #define INCLUDE_LEN_FUDGE 10 /* leave room for VMS syntax conversion */
122 #define FFECOM_DETERMINE_TYPES 1 /* for com.h */
139 /* Externals defined here. */
141 #if FFECOM_targetCURRENT == FFECOM_targetGCC
143 /* ~~gcc/tree.h *should* declare this, because toplev.c and dwarfout.c
146 const char * const language_string = "GNU F77";
148 /* Stream for reading from the input file. */
151 /* These definitions parallel those in c-decl.c so that code from that
152 module can be used pretty much as is. Much of these defs aren't
153 otherwise used, i.e. by g77 code per se, except some of them are used
154 to build some of them that are. The ones that are global (i.e. not
155 "static") are those that ste.c and such might use (directly
156 or by using com macros that reference them in their definitions). */
158 tree string_type_node;
160 /* The rest of these are inventions for g77, though there might be
161 similar things in the C front end. As they are found, these
162 inventions should be renamed to be canonical. Note that only
163 the ones currently required to be global are so. */
165 static tree ffecom_tree_fun_type_void;
167 tree ffecom_integer_type_node; /* Abbrev for _tree_type[blah][blah]. */
168 tree ffecom_integer_zero_node; /* Like *_*_* with g77's integer type. */
169 tree ffecom_integer_one_node; /* " */
170 tree ffecom_tree_type[FFEINFO_basictype][FFEINFO_kindtype];
172 /* _fun_type things are the f2c-specific versions. For -fno-f2c,
173 just use build_function_type and build_pointer_type on the
174 appropriate _tree_type array element. */
176 static tree ffecom_tree_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
177 static tree ffecom_tree_ptr_to_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
178 static tree ffecom_tree_subr_type;
179 static tree ffecom_tree_ptr_to_subr_type;
180 static tree ffecom_tree_blockdata_type;
182 static tree ffecom_tree_xargc_;
184 ffecomSymbol ffecom_symbol_null_
193 ffeinfoKindtype ffecom_pointer_kind_ = FFEINFO_basictypeNONE;
194 ffeinfoKindtype ffecom_label_kind_ = FFEINFO_basictypeNONE;
196 int ffecom_f2c_typecode_[FFEINFO_basictype][FFEINFO_kindtype];
197 tree ffecom_f2c_integer_type_node;
198 tree ffecom_f2c_ptr_to_integer_type_node;
199 tree ffecom_f2c_address_type_node;
200 tree ffecom_f2c_real_type_node;
201 tree ffecom_f2c_ptr_to_real_type_node;
202 tree ffecom_f2c_doublereal_type_node;
203 tree ffecom_f2c_complex_type_node;
204 tree ffecom_f2c_doublecomplex_type_node;
205 tree ffecom_f2c_longint_type_node;
206 tree ffecom_f2c_logical_type_node;
207 tree ffecom_f2c_flag_type_node;
208 tree ffecom_f2c_ftnlen_type_node;
209 tree ffecom_f2c_ftnlen_zero_node;
210 tree ffecom_f2c_ftnlen_one_node;
211 tree ffecom_f2c_ftnlen_two_node;
212 tree ffecom_f2c_ptr_to_ftnlen_type_node;
213 tree ffecom_f2c_ftnint_type_node;
214 tree ffecom_f2c_ptr_to_ftnint_type_node;
215 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
217 /* Simple definitions and enumerations. */
219 #ifndef FFECOM_sizeMAXSTACKITEM
220 #define FFECOM_sizeMAXSTACKITEM 32*1024 /* Keep user-declared things
221 larger than this # bytes
222 off stack if possible. */
225 /* For systems that have large enough stacks, they should define
226 this to 0, and here, for ease of use later on, we just undefine
229 #if FFECOM_sizeMAXSTACKITEM == 0
230 #undef FFECOM_sizeMAXSTACKITEM
236 FFECOM_rttypeVOIDSTAR_, /* C's `void *' type. */
237 FFECOM_rttypeFTNINT_, /* f2c's `ftnint' type. */
238 FFECOM_rttypeINTEGER_, /* f2c's `integer' type. */
239 FFECOM_rttypeLONGINT_, /* f2c's `longint' type. */
240 FFECOM_rttypeLOGICAL_, /* f2c's `logical' type. */
241 FFECOM_rttypeREAL_F2C_, /* f2c's `real' returned as `double'. */
242 FFECOM_rttypeREAL_GNU_, /* `real' returned as such. */
243 FFECOM_rttypeCOMPLEX_F2C_, /* f2c's `complex' returned via 1st arg. */
244 FFECOM_rttypeCOMPLEX_GNU_, /* f2c's `complex' returned directly. */
245 FFECOM_rttypeDOUBLE_, /* C's `double' type. */
246 FFECOM_rttypeDOUBLEREAL_, /* f2c's `doublereal' type. */
247 FFECOM_rttypeDBLCMPLX_F2C_, /* f2c's `doublecomplex' returned via 1st arg. */
248 FFECOM_rttypeDBLCMPLX_GNU_, /* f2c's `doublecomplex' returned directly. */
249 FFECOM_rttypeCHARACTER_, /* f2c `char *'/`ftnlen' pair. */
253 /* Internal typedefs. */
255 #if FFECOM_targetCURRENT == FFECOM_targetGCC
256 typedef struct _ffecom_concat_list_ ffecomConcatList_;
257 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
259 /* Private include files. */
262 /* Internal structure definitions. */
264 #if FFECOM_targetCURRENT == FFECOM_targetGCC
265 struct _ffecom_concat_list_
270 ffetargetCharacterSize minlen;
271 ffetargetCharacterSize maxlen;
273 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
275 /* Static functions (internal). */
277 #if FFECOM_targetCURRENT == FFECOM_targetGCC
278 static tree ffecom_arglist_expr_ (const char *argstring, ffebld args);
279 static tree ffecom_widest_expr_type_ (ffebld list);
280 static bool ffecom_overlap_ (tree dest_decl, tree dest_offset,
281 tree dest_size, tree source_tree,
282 ffebld source, bool scalar_arg);
283 static bool ffecom_args_overlapping_ (tree dest_tree, ffebld dest,
284 tree args, tree callee_commons,
286 static tree ffecom_build_f2c_string_ (int i, const char *s);
287 static tree ffecom_call_ (tree fn, ffeinfoKindtype kt,
288 bool is_f2c_complex, tree type,
289 tree args, tree dest_tree,
290 ffebld dest, bool *dest_used,
291 tree callee_commons, bool scalar_args, tree hook);
292 static tree ffecom_call_binop_ (tree fn, ffeinfoKindtype kt,
293 bool is_f2c_complex, tree type,
294 ffebld left, ffebld right,
295 tree dest_tree, ffebld dest,
296 bool *dest_used, tree callee_commons,
297 bool scalar_args, bool ref, tree hook);
298 static void ffecom_char_args_x_ (tree *xitem, tree *length,
299 ffebld expr, bool with_null);
300 static tree ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy);
301 static tree ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s);
302 static ffecomConcatList_
303 ffecom_concat_list_gather_ (ffecomConcatList_ catlist,
305 ffetargetCharacterSize max);
306 static void ffecom_concat_list_kill_ (ffecomConcatList_ catlist);
307 static ffecomConcatList_ ffecom_concat_list_new_ (ffebld expr,
308 ffetargetCharacterSize max);
309 static void ffecom_debug_kludge_ (tree aggr, const char *aggr_type,
310 ffesymbol member, tree member_type,
311 ffetargetOffset offset);
312 static void ffecom_do_entry_ (ffesymbol fn, int entrynum);
313 static tree ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
314 bool *dest_used, bool assignp, bool widenp);
315 static tree ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
316 ffebld dest, bool *dest_used);
317 static tree ffecom_expr_power_integer_ (ffebld expr);
318 static void ffecom_expr_transform_ (ffebld expr);
319 static void ffecom_f2c_make_type_ (tree *type, int tcode, const char *name);
320 static void ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
322 static ffeglobal ffecom_finish_global_ (ffeglobal global);
323 static ffesymbol ffecom_finish_symbol_transform_ (ffesymbol s);
324 static tree ffecom_get_appended_identifier_ (char us, const char *text);
325 static tree ffecom_get_external_identifier_ (ffesymbol s);
326 static tree ffecom_get_identifier_ (const char *text);
327 static tree ffecom_gen_sfuncdef_ (ffesymbol s,
330 static const char *ffecom_gfrt_args_ (ffecomGfrt ix);
331 static tree ffecom_gfrt_tree_ (ffecomGfrt ix);
332 static tree ffecom_init_zero_ (tree decl);
333 static tree ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
335 static tree ffecom_intrinsic_len_ (ffebld expr);
336 static void ffecom_let_char_ (tree dest_tree,
338 ffetargetCharacterSize dest_size,
340 static void ffecom_make_gfrt_ (ffecomGfrt ix);
341 static void ffecom_member_phase1_ (ffestorag mst, ffestorag st);
342 static void ffecom_member_phase2_ (ffestorag mst, ffestorag st);
343 static void ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size,
345 static void ffecom_push_dummy_decls_ (ffebld dumlist,
347 static void ffecom_start_progunit_ (void);
348 static ffesymbol ffecom_sym_transform_ (ffesymbol s);
349 static ffesymbol ffecom_sym_transform_assign_ (ffesymbol s);
350 static void ffecom_transform_common_ (ffesymbol s);
351 static void ffecom_transform_equiv_ (ffestorag st);
352 static tree ffecom_transform_namelist_ (ffesymbol s);
353 static void ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
355 static void ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
356 tree *size, tree tree);
357 static tree ffecom_tree_divide_ (tree tree_type, tree left, tree right,
358 tree dest_tree, ffebld dest,
359 bool *dest_used, tree hook);
360 static tree ffecom_type_localvar_ (ffesymbol s,
363 static tree ffecom_type_namelist_ (void);
364 static tree ffecom_type_vardesc_ (void);
365 static tree ffecom_vardesc_ (ffebld expr);
366 static tree ffecom_vardesc_array_ (ffesymbol s);
367 static tree ffecom_vardesc_dims_ (ffesymbol s);
368 static tree ffecom_convert_narrow_ (tree type, tree expr);
369 static tree ffecom_convert_widen_ (tree type, tree expr);
370 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
372 /* These are static functions that parallel those found in the C front
373 end and thus have the same names. */
375 #if FFECOM_targetCURRENT == FFECOM_targetGCC
376 static tree bison_rule_compstmt_ (void);
377 static void bison_rule_pushlevel_ (void);
378 static void delete_block (tree block);
379 static int duplicate_decls (tree newdecl, tree olddecl);
380 static void finish_decl (tree decl, tree init, bool is_top_level);
381 static void finish_function (int nested);
382 static const char *lang_printable_name (tree decl, int v);
383 static tree lookup_name_current_level (tree name);
384 static struct binding_level *make_binding_level (void);
385 static void pop_f_function_context (void);
386 static void push_f_function_context (void);
387 static void push_parm_decl (tree parm);
388 static tree pushdecl_top_level (tree decl);
389 static int kept_level_p (void);
390 static tree storedecls (tree decls);
391 static void store_parm_decls (int is_main_program);
392 static tree start_decl (tree decl, bool is_top_level);
393 static void start_function (tree name, tree type, int nested, int public);
394 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
395 #if FFECOM_GCC_INCLUDE
396 static void ffecom_file_ (const char *name);
397 static void ffecom_initialize_char_syntax_ (void);
398 static void ffecom_close_include_ (FILE *f);
399 static int ffecom_decode_include_option_ (char *spec);
400 static FILE *ffecom_open_include_ (char *name, ffewhereLine l,
402 #endif /* FFECOM_GCC_INCLUDE */
404 /* Static objects accessed by functions in this module. */
406 static ffesymbol ffecom_primary_entry_ = NULL;
407 static ffesymbol ffecom_nested_entry_ = NULL;
408 static ffeinfoKind ffecom_primary_entry_kind_;
409 static bool ffecom_primary_entry_is_proc_;
410 #if FFECOM_targetCURRENT == FFECOM_targetGCC
411 static tree ffecom_outer_function_decl_;
412 static tree ffecom_previous_function_decl_;
413 static tree ffecom_which_entrypoint_decl_;
414 static tree ffecom_float_zero_ = NULL_TREE;
415 static tree ffecom_float_half_ = NULL_TREE;
416 static tree ffecom_double_zero_ = NULL_TREE;
417 static tree ffecom_double_half_ = NULL_TREE;
418 static tree ffecom_func_result_;/* For functions. */
419 static tree ffecom_func_length_;/* For CHARACTER fns. */
420 static ffebld ffecom_list_blockdata_;
421 static ffebld ffecom_list_common_;
422 static ffebld ffecom_master_arglist_;
423 static ffeinfoBasictype ffecom_master_bt_;
424 static ffeinfoKindtype ffecom_master_kt_;
425 static ffetargetCharacterSize ffecom_master_size_;
426 static int ffecom_num_fns_ = 0;
427 static int ffecom_num_entrypoints_ = 0;
428 static bool ffecom_is_altreturning_ = FALSE;
429 static tree ffecom_multi_type_node_;
430 static tree ffecom_multi_retval_;
432 ffecom_multi_fields_[FFEINFO_basictype][FFEINFO_kindtype];
433 static bool ffecom_member_namelisted_; /* _member_phase1_ namelisted? */
434 static bool ffecom_doing_entry_ = FALSE;
435 static bool ffecom_transform_only_dummies_ = FALSE;
436 static int ffecom_typesize_pointer_;
437 static int ffecom_typesize_integer1_;
439 /* Holds pointer-to-function expressions. */
441 static tree ffecom_gfrt_[FFECOM_gfrt]
444 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) NULL_TREE,
445 #include "com-rt.def"
449 /* Holds the external names of the functions. */
451 static const char *ffecom_gfrt_name_[FFECOM_gfrt]
454 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) NAME,
455 #include "com-rt.def"
459 /* Whether the function returns. */
461 static bool ffecom_gfrt_volatile_[FFECOM_gfrt]
464 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) VOLATILE,
465 #include "com-rt.def"
469 /* Whether the function returns type complex. */
471 static bool ffecom_gfrt_complex_[FFECOM_gfrt]
474 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) COMPLEX,
475 #include "com-rt.def"
479 /* Whether the function is const
480 (i.e., has no side effects and only depends on its arguments). */
482 static bool ffecom_gfrt_const_[FFECOM_gfrt]
485 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) CONST,
486 #include "com-rt.def"
490 /* Type code for the function return value. */
492 static ffecomRttype_ ffecom_gfrt_type_[FFECOM_gfrt]
495 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) TYPE,
496 #include "com-rt.def"
500 /* String of codes for the function's arguments. */
502 static const char *ffecom_gfrt_argstring_[FFECOM_gfrt]
505 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) ARGS,
506 #include "com-rt.def"
509 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
511 /* Internal macros. */
513 #if FFECOM_targetCURRENT == FFECOM_targetGCC
515 /* We let tm.h override the types used here, to handle trivial differences
516 such as the choice of unsigned int or long unsigned int for size_t.
517 When machines start needing nontrivial differences in the size type,
518 it would be best to do something here to figure out automatically
519 from other information what type to use. */
522 #define SIZE_TYPE "long unsigned int"
525 #define ffecom_concat_list_count_(catlist) ((catlist).count)
526 #define ffecom_concat_list_expr_(catlist,i) ((catlist).exprs[(i)])
527 #define ffecom_concat_list_maxlen_(catlist) ((catlist).maxlen)
528 #define ffecom_concat_list_minlen_(catlist) ((catlist).minlen)
530 #define ffecom_char_args_(i,l,e) ffecom_char_args_x_((i),(l),(e),FALSE)
531 #define ffecom_char_args_with_null_(i,l,e) ffecom_char_args_x_((i),(l),(e),TRUE)
533 /* For each binding contour we allocate a binding_level structure
534 * which records the names defined in that contour.
537 * 1) one for each function definition,
538 * where internal declarations of the parameters appear.
540 * The current meaning of a name can be found by searching the levels from
541 * the current one out to the global one.
544 /* Note that the information in the `names' component of the global contour
545 is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */
549 /* A chain of _DECL nodes for all variables, constants, functions,
550 and typedef types. These are in the reverse of the order supplied.
554 /* For each level (except not the global one),
555 a chain of BLOCK nodes for all the levels
556 that were entered and exited one level down. */
559 /* The BLOCK node for this level, if one has been preallocated.
560 If 0, the BLOCK is allocated (if needed) when the level is popped. */
563 /* The binding level which this one is contained in (inherits from). */
564 struct binding_level *level_chain;
566 /* 0: no ffecom_prepare_* functions called at this level yet;
567 1: ffecom_prepare* functions called, except not ffecom_prepare_end;
568 2: ffecom_prepare_end called. */
572 #define NULL_BINDING_LEVEL (struct binding_level *) NULL
574 /* The binding level currently in effect. */
576 static struct binding_level *current_binding_level;
578 /* A chain of binding_level structures awaiting reuse. */
580 static struct binding_level *free_binding_level;
582 /* The outermost binding level, for names of file scope.
583 This is created when the compiler is started and exists
584 through the entire run. */
586 static struct binding_level *global_binding_level;
588 /* Binding level structures are initialized by copying this one. */
590 static struct binding_level clear_binding_level
592 {NULL, NULL, NULL, NULL_BINDING_LEVEL, 0};
594 /* Language-dependent contents of an identifier. */
596 struct lang_identifier
598 struct tree_identifier ignore;
599 tree global_value, local_value, label_value;
603 /* Macros for access to language-specific slots in an identifier. */
604 /* Each of these slots contains a DECL node or null. */
606 /* This represents the value which the identifier has in the
607 file-scope namespace. */
608 #define IDENTIFIER_GLOBAL_VALUE(NODE) \
609 (((struct lang_identifier *)(NODE))->global_value)
610 /* This represents the value which the identifier has in the current
612 #define IDENTIFIER_LOCAL_VALUE(NODE) \
613 (((struct lang_identifier *)(NODE))->local_value)
614 /* This represents the value which the identifier has as a label in
615 the current label scope. */
616 #define IDENTIFIER_LABEL_VALUE(NODE) \
617 (((struct lang_identifier *)(NODE))->label_value)
618 /* This is nonzero if the identifier was "made up" by g77 code. */
619 #define IDENTIFIER_INVENTED(NODE) \
620 (((struct lang_identifier *)(NODE))->invented)
622 /* In identifiers, C uses the following fields in a special way:
623 TREE_PUBLIC to record that there was a previous local extern decl.
624 TREE_USED to record that such a decl was used.
625 TREE_ADDRESSABLE to record that the address of such a decl was used. */
627 /* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
628 that have names. Here so we can clear out their names' definitions
629 at the end of the function. */
631 static tree named_labels;
633 /* A list of LABEL_DECLs from outer contexts that are currently shadowed. */
635 static tree shadowed_labels;
637 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
639 /* Return the subscript expression, modified to do range-checking.
641 `array' is the array to be checked against.
642 `element' is the subscript expression to check.
643 `dim' is the dimension number (starting at 0).
644 `total_dims' is the total number of dimensions (0 for CHARACTER substring).
648 ffecom_subscript_check_ (tree array, tree element, int dim, int total_dims,
649 const char *array_name)
651 tree low = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
652 tree high = TYPE_MAX_VALUE (TYPE_DOMAIN (array));
657 if (element == error_mark_node)
660 if (TREE_TYPE (low) != TREE_TYPE (element))
662 if (TYPE_PRECISION (TREE_TYPE (low))
663 > TYPE_PRECISION (TREE_TYPE (element)))
664 element = convert (TREE_TYPE (low), element);
667 low = convert (TREE_TYPE (element), low);
669 high = convert (TREE_TYPE (element), high);
673 element = ffecom_save_tree (element);
674 cond = ffecom_2 (LE_EXPR, integer_type_node,
679 cond = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
681 ffecom_2 (LE_EXPR, integer_type_node,
698 var = concat (array_name, "[", (dim ? "end" : "start"),
699 "-substring]", NULL);
700 len = strlen (var) + 1;
701 arg1 = build_string (len, var);
706 len = strlen (array_name) + 1;
707 arg1 = build_string (len, array_name);
711 var = xmalloc (strlen (array_name) + 40);
712 sprintf (var, "%s[subscript-%d-of-%d]",
714 dim + 1, total_dims);
715 len = strlen (var) + 1;
716 arg1 = build_string (len, var);
722 = build_type_variant (build_array_type (char_type_node,
726 build_int_2 (len, 0))),
728 TREE_CONSTANT (arg1) = 1;
729 TREE_STATIC (arg1) = 1;
730 arg1 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg1)),
733 /* s_rnge adds one to the element to print it, so bias against
734 that -- want to print a faithful *subscript* value. */
735 arg2 = convert (ffecom_f2c_ftnint_type_node,
736 ffecom_2 (MINUS_EXPR,
739 convert (TREE_TYPE (element),
742 proc = concat (input_filename, "/",
743 IDENTIFIER_POINTER (DECL_NAME (current_function_decl)),
745 len = strlen (proc) + 1;
746 arg3 = build_string (len, proc);
751 = build_type_variant (build_array_type (char_type_node,
755 build_int_2 (len, 0))),
757 TREE_CONSTANT (arg3) = 1;
758 TREE_STATIC (arg3) = 1;
759 arg3 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg3)),
762 arg4 = convert (ffecom_f2c_ftnint_type_node,
763 build_int_2 (lineno, 0));
765 arg1 = build_tree_list (NULL_TREE, arg1);
766 arg2 = build_tree_list (NULL_TREE, arg2);
767 arg3 = build_tree_list (NULL_TREE, arg3);
768 arg4 = build_tree_list (NULL_TREE, arg4);
769 TREE_CHAIN (arg3) = arg4;
770 TREE_CHAIN (arg2) = arg3;
771 TREE_CHAIN (arg1) = arg2;
775 die = ffecom_call_gfrt (FFECOM_gfrtRANGE,
777 TREE_SIDE_EFFECTS (die) = 1;
779 element = ffecom_3 (COND_EXPR,
788 /* Return the computed element of an array reference.
790 `item' is NULL_TREE, or the transformed pointer to the array.
791 `expr' is the original opARRAYREF expression, which is transformed
792 if `item' is NULL_TREE.
793 `want_ptr' is non-zero if a pointer to the element, instead of
794 the element itself, is to be returned. */
797 ffecom_arrayref_ (tree item, ffebld expr, int want_ptr)
799 ffebld dims[FFECOM_dimensionsMAX];
802 int flatten = ffe_is_flatten_arrays ();
808 const char *array_name;
812 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER)
813 array_name = ffesymbol_text (ffebld_symter (ffebld_left (expr)));
815 array_name = "[expr?]";
817 /* Build up ARRAY_REFs in reverse order (since we're column major
818 here in Fortran land). */
820 for (i = 0, list = ffebld_right (expr);
822 ++i, list = ffebld_trail (list))
824 dims[i] = ffebld_head (list);
825 type = ffeinfo_type (ffebld_basictype (dims[i]),
826 ffebld_kindtype (dims[i]));
828 && ffecom_typesize_pointer_ > ffecom_typesize_integer1_
829 && ffetype_size (type) > ffecom_typesize_integer1_)
830 /* E.g. ARRAY(INDEX), given INTEGER*8 INDEX, on a system with 64-bit
831 pointers and 32-bit integers. Do the full 64-bit pointer
832 arithmetic, for codes using arrays for nonstandard heap-like
839 need_ptr = want_ptr || flatten;
844 item = ffecom_ptr_to_expr (ffebld_left (expr));
846 item = ffecom_expr (ffebld_left (expr));
848 if (item == error_mark_node)
851 if (ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereFLEETING
852 && ! mark_addressable (item))
853 return error_mark_node;
856 if (item == error_mark_node)
863 for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
865 --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
867 min = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
868 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
869 if (flag_bounds_check)
870 element = ffecom_subscript_check_ (array, element, i, total_dims,
872 if (element == error_mark_node)
875 /* Widen integral arithmetic as desired while preserving
877 tree_type = TREE_TYPE (element);
878 tree_type_x = tree_type;
880 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
881 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
882 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
884 if (TREE_TYPE (min) != tree_type_x)
885 min = convert (tree_type_x, min);
886 if (TREE_TYPE (element) != tree_type_x)
887 element = convert (tree_type_x, element);
889 item = ffecom_2 (PLUS_EXPR,
890 build_pointer_type (TREE_TYPE (array)),
892 size_binop (MULT_EXPR,
893 size_in_bytes (TREE_TYPE (array)),
895 fold (build (MINUS_EXPR,
901 item = ffecom_1 (INDIRECT_REF,
902 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
912 array = TYPE_MAIN_VARIANT (TREE_TYPE (item));
914 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
915 if (flag_bounds_check)
916 element = ffecom_subscript_check_ (array, element, i, total_dims,
918 if (element == error_mark_node)
921 /* Widen integral arithmetic as desired while preserving
923 tree_type = TREE_TYPE (element);
924 tree_type_x = tree_type;
926 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
927 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
928 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
930 element = convert (tree_type_x, element);
932 item = ffecom_2 (ARRAY_REF,
933 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
942 /* This is like gcc's stabilize_reference -- in fact, most of the code
943 comes from that -- but it handles the situation where the reference
944 is going to have its subparts picked at, and it shouldn't change
945 (or trigger extra invocations of functions in the subtrees) due to
946 this. save_expr is a bit overzealous, because we don't need the
947 entire thing calculated and saved like a temp. So, for DECLs, no
948 change is needed, because these are stable aggregates, and ARRAY_REF
949 and such might well be stable too, but for things like calculations,
950 we do need to calculate a snapshot of a value before picking at it. */
952 #if FFECOM_targetCURRENT == FFECOM_targetGCC
954 ffecom_stabilize_aggregate_ (tree ref)
957 enum tree_code code = TREE_CODE (ref);
964 /* No action is needed in this case. */
974 result = build_nt (code, stabilize_reference (TREE_OPERAND (ref, 0)));
978 result = build_nt (INDIRECT_REF,
979 stabilize_reference_1 (TREE_OPERAND (ref, 0)));
983 result = build_nt (COMPONENT_REF,
984 stabilize_reference (TREE_OPERAND (ref, 0)),
985 TREE_OPERAND (ref, 1));
989 result = build_nt (BIT_FIELD_REF,
990 stabilize_reference (TREE_OPERAND (ref, 0)),
991 stabilize_reference_1 (TREE_OPERAND (ref, 1)),
992 stabilize_reference_1 (TREE_OPERAND (ref, 2)));
996 result = build_nt (ARRAY_REF,
997 stabilize_reference (TREE_OPERAND (ref, 0)),
998 stabilize_reference_1 (TREE_OPERAND (ref, 1)));
1002 result = build_nt (COMPOUND_EXPR,
1003 stabilize_reference_1 (TREE_OPERAND (ref, 0)),
1004 stabilize_reference (TREE_OPERAND (ref, 1)));
1012 return save_expr (ref);
1015 return error_mark_node;
1018 TREE_TYPE (result) = TREE_TYPE (ref);
1019 TREE_READONLY (result) = TREE_READONLY (ref);
1020 TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (ref);
1021 TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (ref);
1027 /* A rip-off of gcc's convert.c convert_to_complex function,
1028 reworked to handle complex implemented as C structures
1029 (RECORD_TYPE with two fields, real and imaginary `r' and `i'). */
1031 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1033 ffecom_convert_to_complex_ (tree type, tree expr)
1035 register enum tree_code form = TREE_CODE (TREE_TYPE (expr));
1038 assert (TREE_CODE (type) == RECORD_TYPE);
1040 subtype = TREE_TYPE (TYPE_FIELDS (type));
1042 if (form == REAL_TYPE || form == INTEGER_TYPE || form == ENUMERAL_TYPE)
1044 expr = convert (subtype, expr);
1045 return ffecom_2 (COMPLEX_EXPR, type, expr,
1046 convert (subtype, integer_zero_node));
1049 if (form == RECORD_TYPE)
1051 tree elt_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr)));
1052 if (TYPE_MAIN_VARIANT (elt_type) == TYPE_MAIN_VARIANT (subtype))
1056 expr = save_expr (expr);
1057 return ffecom_2 (COMPLEX_EXPR,
1060 ffecom_1 (REALPART_EXPR,
1061 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1064 ffecom_1 (IMAGPART_EXPR,
1065 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1070 if (form == POINTER_TYPE || form == REFERENCE_TYPE)
1071 error ("pointer value used where a complex was expected");
1073 error ("aggregate value used where a complex was expected");
1075 return ffecom_2 (COMPLEX_EXPR, type,
1076 convert (subtype, integer_zero_node),
1077 convert (subtype, integer_zero_node));
1081 /* Like gcc's convert(), but crashes if widening might happen. */
1083 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1085 ffecom_convert_narrow_ (type, expr)
1088 register tree e = expr;
1089 register enum tree_code code = TREE_CODE (type);
1091 if (type == TREE_TYPE (e)
1092 || TREE_CODE (e) == ERROR_MARK)
1094 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1095 return fold (build1 (NOP_EXPR, type, e));
1096 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1097 || code == ERROR_MARK)
1098 return error_mark_node;
1099 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1101 assert ("void value not ignored as it ought to be" == NULL);
1102 return error_mark_node;
1104 assert (code != VOID_TYPE);
1105 if ((code != RECORD_TYPE)
1106 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1107 assert ("converting COMPLEX to REAL" == NULL);
1108 assert (code != ENUMERAL_TYPE);
1109 if (code == INTEGER_TYPE)
1111 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1112 && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)))
1113 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1114 && (TYPE_PRECISION (type)
1115 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
1116 return fold (convert_to_integer (type, e));
1118 if (code == POINTER_TYPE)
1120 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1121 return fold (convert_to_pointer (type, e));
1123 if (code == REAL_TYPE)
1125 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1126 assert (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)));
1127 return fold (convert_to_real (type, e));
1129 if (code == COMPLEX_TYPE)
1131 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1132 assert (TYPE_PRECISION (TREE_TYPE (type)) <= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1133 return fold (convert_to_complex (type, e));
1135 if (code == RECORD_TYPE)
1137 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
1138 /* Check that at least the first field name agrees. */
1139 assert (DECL_NAME (TYPE_FIELDS (type))
1140 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
1141 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1142 <= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
1143 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1144 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1146 return fold (ffecom_convert_to_complex_ (type, e));
1149 assert ("conversion to non-scalar type requested" == NULL);
1150 return error_mark_node;
1154 /* Like gcc's convert(), but crashes if narrowing might happen. */
1156 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1158 ffecom_convert_widen_ (type, expr)
1161 register tree e = expr;
1162 register enum tree_code code = TREE_CODE (type);
1164 if (type == TREE_TYPE (e)
1165 || TREE_CODE (e) == ERROR_MARK)
1167 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1168 return fold (build1 (NOP_EXPR, type, e));
1169 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1170 || code == ERROR_MARK)
1171 return error_mark_node;
1172 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1174 assert ("void value not ignored as it ought to be" == NULL);
1175 return error_mark_node;
1177 assert (code != VOID_TYPE);
1178 if ((code != RECORD_TYPE)
1179 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1180 assert ("narrowing COMPLEX to REAL" == NULL);
1181 assert (code != ENUMERAL_TYPE);
1182 if (code == INTEGER_TYPE)
1184 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1185 && TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)))
1186 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1187 && (TYPE_PRECISION (type)
1188 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
1189 return fold (convert_to_integer (type, e));
1191 if (code == POINTER_TYPE)
1193 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1194 return fold (convert_to_pointer (type, e));
1196 if (code == REAL_TYPE)
1198 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1199 assert (TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)));
1200 return fold (convert_to_real (type, e));
1202 if (code == COMPLEX_TYPE)
1204 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1205 assert (TYPE_PRECISION (TREE_TYPE (type)) >= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1206 return fold (convert_to_complex (type, e));
1208 if (code == RECORD_TYPE)
1210 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
1211 /* Check that at least the first field name agrees. */
1212 assert (DECL_NAME (TYPE_FIELDS (type))
1213 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
1214 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1215 >= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
1216 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1217 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1219 return fold (ffecom_convert_to_complex_ (type, e));
1222 assert ("conversion to non-scalar type requested" == NULL);
1223 return error_mark_node;
1227 /* Handles making a COMPLEX type, either the standard
1228 (but buggy?) gbe way, or the safer (but less elegant?)
1231 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1233 ffecom_make_complex_type_ (tree subtype)
1239 if (ffe_is_emulate_complex ())
1241 type = make_node (RECORD_TYPE);
1242 realfield = ffecom_decl_field (type, NULL_TREE, "r", subtype);
1243 imagfield = ffecom_decl_field (type, realfield, "i", subtype);
1244 TYPE_FIELDS (type) = realfield;
1249 type = make_node (COMPLEX_TYPE);
1250 TREE_TYPE (type) = subtype;
1258 /* Chooses either the gbe or the f2c way to build a
1259 complex constant. */
1261 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1263 ffecom_build_complex_constant_ (tree type, tree realpart, tree imagpart)
1267 if (ffe_is_emulate_complex ())
1269 bothparts = build_tree_list (TYPE_FIELDS (type), realpart);
1270 TREE_CHAIN (bothparts) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), imagpart);
1271 bothparts = build (CONSTRUCTOR, type, NULL_TREE, bothparts);
1275 bothparts = build_complex (type, realpart, imagpart);
1282 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1284 ffecom_arglist_expr_ (const char *c, ffebld expr)
1287 tree *plist = &list;
1288 tree trail = NULL_TREE; /* Append char length args here. */
1289 tree *ptrail = &trail;
1294 tree wanted = NULL_TREE;
1295 static char zed[] = "0";
1300 while (expr != NULL)
1323 wanted = ffecom_f2c_complex_type_node;
1327 wanted = ffecom_f2c_doublereal_type_node;
1331 wanted = ffecom_f2c_doublecomplex_type_node;
1335 wanted = ffecom_f2c_real_type_node;
1339 wanted = ffecom_f2c_integer_type_node;
1343 wanted = ffecom_f2c_longint_type_node;
1347 assert ("bad argstring code" == NULL);
1353 exprh = ffebld_head (expr);
1357 if ((wanted == NULL_TREE)
1360 (ffecom_tree_type[ffeinfo_basictype (ffebld_info (exprh))]
1361 [ffeinfo_kindtype (ffebld_info (exprh))])
1362 == TYPE_MODE (wanted))))
1364 = build_tree_list (NULL_TREE,
1365 ffecom_arg_ptr_to_expr (exprh,
1369 item = ffecom_arg_expr (exprh, &length);
1370 item = ffecom_convert_widen_ (wanted, item);
1373 item = ffecom_1 (ADDR_EXPR,
1374 build_pointer_type (TREE_TYPE (item)),
1378 = build_tree_list (NULL_TREE,
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')
1400 assert ("missing arg to run-time routine!" == NULL);
1415 assert ("bad arg string code" == NULL);
1419 = build_tree_list (NULL_TREE,
1421 plist = &TREE_CHAIN (*plist);
1430 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1432 ffecom_widest_expr_type_ (ffebld list)
1435 ffebld widest = NULL;
1437 ffetype widest_type = NULL;
1440 for (; list != NULL; list = ffebld_trail (list))
1442 item = ffebld_head (list);
1445 if ((widest != NULL)
1446 && (ffeinfo_basictype (ffebld_info (item))
1447 != ffeinfo_basictype (ffebld_info (widest))))
1449 type = ffeinfo_type (ffeinfo_basictype (ffebld_info (item)),
1450 ffeinfo_kindtype (ffebld_info (item)));
1451 if ((widest == FFEINFO_kindtypeNONE)
1452 || (ffetype_size (type)
1453 > ffetype_size (widest_type)))
1460 assert (widest != NULL);
1461 t = ffecom_tree_type[ffeinfo_basictype (ffebld_info (widest))]
1462 [ffeinfo_kindtype (ffebld_info (widest))];
1463 assert (t != NULL_TREE);
1468 /* Check whether a partial overlap between two expressions is possible.
1470 Can *starting* to write a portion of expr1 change the value
1471 computed (perhaps already, *partially*) by expr2?
1473 Currently, this is a concern only for a COMPLEX expr1. But if it
1474 isn't in COMMON or local EQUIVALENCE, since we don't support
1475 aliasing of arguments, it isn't a concern. */
1478 ffecom_possible_partial_overlap_ (ffebld expr1, ffebld expr2 ATTRIBUTE_UNUSED)
1483 switch (ffebld_op (expr1))
1485 case FFEBLD_opSYMTER:
1486 sym = ffebld_symter (expr1);
1489 case FFEBLD_opARRAYREF:
1490 if (ffebld_op (ffebld_left (expr1)) != FFEBLD_opSYMTER)
1492 sym = ffebld_symter (ffebld_left (expr1));
1499 if (ffesymbol_where (sym) != FFEINFO_whereCOMMON
1500 && (ffesymbol_where (sym) != FFEINFO_whereLOCAL
1501 || ! (st = ffesymbol_storage (sym))
1502 || ! ffestorag_parent (st)))
1505 /* It's in COMMON or local EQUIVALENCE. */
1510 /* Check whether dest and source might overlap. ffebld versions of these
1511 might or might not be passed, will be NULL if not.
1513 The test is really whether source_tree is modifiable and, if modified,
1514 might overlap destination such that the value(s) in the destination might
1515 change before it is finally modified. dest_* are the canonized
1516 destination itself. */
1518 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1520 ffecom_overlap_ (tree dest_decl, tree dest_offset, tree dest_size,
1521 tree source_tree, ffebld source UNUSED,
1529 if (source_tree == NULL_TREE)
1532 switch (TREE_CODE (source_tree))
1535 case IDENTIFIER_NODE:
1546 case TRUNC_DIV_EXPR:
1548 case FLOOR_DIV_EXPR:
1549 case ROUND_DIV_EXPR:
1550 case TRUNC_MOD_EXPR:
1552 case FLOOR_MOD_EXPR:
1553 case ROUND_MOD_EXPR:
1555 case EXACT_DIV_EXPR:
1556 case FIX_TRUNC_EXPR:
1558 case FIX_FLOOR_EXPR:
1559 case FIX_ROUND_EXPR:
1573 case BIT_ANDTC_EXPR:
1575 case TRUTH_ANDIF_EXPR:
1576 case TRUTH_ORIF_EXPR:
1577 case TRUTH_AND_EXPR:
1579 case TRUTH_XOR_EXPR:
1580 case TRUTH_NOT_EXPR:
1596 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1597 TREE_OPERAND (source_tree, 1), NULL,
1601 return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1602 TREE_OPERAND (source_tree, 0), NULL,
1607 case NON_LVALUE_EXPR:
1609 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1612 ffecom_tree_canonize_ptr_ (&source_decl, &source_offset,
1614 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1619 ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1620 TREE_OPERAND (source_tree, 1), NULL,
1622 || ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1623 TREE_OPERAND (source_tree, 2), NULL,
1628 ffecom_tree_canonize_ref_ (&source_decl, &source_offset,
1630 TREE_OPERAND (source_tree, 0));
1634 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1637 source_decl = source_tree;
1638 source_offset = bitsize_zero_node;
1639 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1643 case REFERENCE_EXPR:
1644 case PREDECREMENT_EXPR:
1645 case PREINCREMENT_EXPR:
1646 case POSTDECREMENT_EXPR:
1647 case POSTINCREMENT_EXPR:
1655 /* Come here when source_decl, source_offset, and source_size filled
1656 in appropriately. */
1658 if (source_decl == NULL_TREE)
1659 return FALSE; /* No decl involved, so no overlap. */
1661 if (source_decl != dest_decl)
1662 return FALSE; /* Different decl, no overlap. */
1664 if (TREE_CODE (dest_size) == ERROR_MARK)
1665 return TRUE; /* Assignment into entire assumed-size
1666 array? Shouldn't happen.... */
1668 t = ffecom_2 (LE_EXPR, integer_type_node,
1669 ffecom_2 (PLUS_EXPR, TREE_TYPE (dest_offset),
1671 convert (TREE_TYPE (dest_offset),
1673 convert (TREE_TYPE (dest_offset),
1676 if (integer_onep (t))
1677 return FALSE; /* Destination precedes source. */
1680 || (source_size == NULL_TREE)
1681 || (TREE_CODE (source_size) == ERROR_MARK)
1682 || integer_zerop (source_size))
1683 return TRUE; /* No way to tell if dest follows source. */
1685 t = ffecom_2 (LE_EXPR, integer_type_node,
1686 ffecom_2 (PLUS_EXPR, TREE_TYPE (source_offset),
1688 convert (TREE_TYPE (source_offset),
1690 convert (TREE_TYPE (source_offset),
1693 if (integer_onep (t))
1694 return FALSE; /* Destination follows source. */
1696 return TRUE; /* Destination and source overlap. */
1700 /* Check whether dest might overlap any of a list of arguments or is
1701 in a COMMON area the callee might know about (and thus modify). */
1703 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1705 ffecom_args_overlapping_ (tree dest_tree, ffebld dest UNUSED,
1706 tree args, tree callee_commons,
1714 ffecom_tree_canonize_ref_ (&dest_decl, &dest_offset, &dest_size,
1717 if (dest_decl == NULL_TREE)
1718 return FALSE; /* Seems unlikely! */
1720 /* If the decl cannot be determined reliably, or if its in COMMON
1721 and the callee isn't known to not futz with COMMON via other
1722 means, overlap might happen. */
1724 if ((TREE_CODE (dest_decl) == ERROR_MARK)
1725 || ((callee_commons != NULL_TREE)
1726 && TREE_PUBLIC (dest_decl)))
1729 for (; args != NULL_TREE; args = TREE_CHAIN (args))
1731 if (((arg = TREE_VALUE (args)) != NULL_TREE)
1732 && ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1733 arg, NULL, scalar_args))
1741 /* Build a string for a variable name as used by NAMELIST. This means that
1742 if we're using the f2c library, we build an uppercase string, since
1745 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1747 ffecom_build_f2c_string_ (int i, const char *s)
1749 if (!ffe_is_f2c_library ())
1750 return build_string (i, s);
1759 if (((size_t) i) > ARRAY_SIZE (space))
1760 tmp = malloc_new_ks (malloc_pool_image (), "f2c_string", i);
1764 for (p = s, q = tmp; *p != '\0'; ++p, ++q)
1768 t = build_string (i, tmp);
1770 if (((size_t) i) > ARRAY_SIZE (space))
1771 malloc_kill_ks (malloc_pool_image (), tmp, i);
1778 /* Returns CALL_EXPR or equivalent with given type (pass NULL_TREE for
1779 type to just get whatever the function returns), handling the
1780 f2c value-returning convention, if required, by prepending
1781 to the arglist a pointer to a temporary to receive the return value. */
1783 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1785 ffecom_call_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1786 tree type, tree args, tree dest_tree,
1787 ffebld dest, bool *dest_used, tree callee_commons,
1788 bool scalar_args, tree hook)
1793 if (dest_used != NULL)
1798 if ((dest_used == NULL)
1800 || (ffeinfo_basictype (ffebld_info (dest))
1801 != FFEINFO_basictypeCOMPLEX)
1802 || (ffeinfo_kindtype (ffebld_info (dest)) != kt)
1803 || ((type != NULL_TREE) && (TREE_TYPE (dest_tree) != type))
1804 || ffecom_args_overlapping_ (dest_tree, dest, args,
1809 tempvar = ffecom_make_tempvar (ffecom_tree_type
1810 [FFEINFO_basictypeCOMPLEX][kt],
1811 FFETARGET_charactersizeNONE,
1821 tempvar = dest_tree;
1826 = build_tree_list (NULL_TREE,
1827 ffecom_1 (ADDR_EXPR,
1828 build_pointer_type (TREE_TYPE (tempvar)),
1830 TREE_CHAIN (item) = args;
1832 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1835 if (tempvar != dest_tree)
1836 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item, tempvar);
1839 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1842 if ((type != NULL_TREE) && (TREE_TYPE (item) != type))
1843 item = ffecom_convert_narrow_ (type, item);
1849 /* Given two arguments, transform them and make a call to the given
1850 function via ffecom_call_. */
1852 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1854 ffecom_call_binop_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1855 tree type, ffebld left, ffebld right,
1856 tree dest_tree, ffebld dest, bool *dest_used,
1857 tree callee_commons, bool scalar_args, bool ref, tree hook)
1866 /* Pass arguments by reference. */
1867 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
1868 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
1872 /* Pass arguments by value. */
1873 left_tree = ffecom_arg_expr (left, &left_length);
1874 right_tree = ffecom_arg_expr (right, &right_length);
1878 left_tree = build_tree_list (NULL_TREE, left_tree);
1879 right_tree = build_tree_list (NULL_TREE, right_tree);
1880 TREE_CHAIN (left_tree) = right_tree;
1882 if (left_length != NULL_TREE)
1884 left_length = build_tree_list (NULL_TREE, left_length);
1885 TREE_CHAIN (right_tree) = left_length;
1888 if (right_length != NULL_TREE)
1890 right_length = build_tree_list (NULL_TREE, right_length);
1891 if (left_length != NULL_TREE)
1892 TREE_CHAIN (left_length) = right_length;
1894 TREE_CHAIN (right_tree) = right_length;
1897 return ffecom_call_ (fn, kt, is_f2c_complex, type, left_tree,
1898 dest_tree, dest, dest_used, callee_commons,
1903 /* Return ptr/length args for char subexpression
1905 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
1906 subexpressions by constructing the appropriate trees for the ptr-to-
1907 character-text and length-of-character-text arguments in a calling
1910 Note that if with_null is TRUE, and the expression is an opCONTER,
1911 a null byte is appended to the string. */
1913 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1915 ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
1919 ffetargetCharacter1 val;
1920 ffetargetCharacterSize newlen;
1922 switch (ffebld_op (expr))
1924 case FFEBLD_opCONTER:
1925 val = ffebld_constant_character1 (ffebld_conter (expr));
1926 newlen = ffetarget_length_character1 (val);
1929 /* Begin FFETARGET-NULL-KLUDGE. */
1933 *length = build_int_2 (newlen, 0);
1934 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
1935 high = build_int_2 (newlen, 0);
1936 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
1937 item = build_string (newlen,
1938 ffetarget_text_character1 (val));
1939 /* End FFETARGET-NULL-KLUDGE. */
1941 = build_type_variant
1945 (ffecom_f2c_ftnlen_type_node,
1946 ffecom_f2c_ftnlen_one_node,
1949 TREE_CONSTANT (item) = 1;
1950 TREE_STATIC (item) = 1;
1951 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
1955 case FFEBLD_opSYMTER:
1957 ffesymbol s = ffebld_symter (expr);
1959 item = ffesymbol_hook (s).decl_tree;
1960 if (item == NULL_TREE)
1962 s = ffecom_sym_transform_ (s);
1963 item = ffesymbol_hook (s).decl_tree;
1965 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
1967 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
1968 *length = ffesymbol_hook (s).length_tree;
1971 *length = build_int_2 (ffesymbol_size (s), 0);
1972 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
1975 else if (item == error_mark_node)
1976 *length = error_mark_node;
1978 /* FFEINFO_kindFUNCTION. */
1979 *length = NULL_TREE;
1980 if (!ffesymbol_hook (s).addr
1981 && (item != error_mark_node))
1982 item = ffecom_1 (ADDR_EXPR,
1983 build_pointer_type (TREE_TYPE (item)),
1988 case FFEBLD_opARRAYREF:
1990 ffecom_char_args_ (&item, length, ffebld_left (expr));
1992 if (item == error_mark_node || *length == error_mark_node)
1994 item = *length = error_mark_node;
1998 item = ffecom_arrayref_ (item, expr, 1);
2002 case FFEBLD_opSUBSTR:
2006 ffebld thing = ffebld_right (expr);
2009 const char *char_name;
2013 assert (ffebld_op (thing) == FFEBLD_opITEM);
2014 start = ffebld_head (thing);
2015 thing = ffebld_trail (thing);
2016 assert (ffebld_trail (thing) == NULL);
2017 end = ffebld_head (thing);
2019 /* Determine name for pretty-printing range-check errors. */
2020 for (left_symter = ffebld_left (expr);
2021 left_symter && ffebld_op (left_symter) == FFEBLD_opARRAYREF;
2022 left_symter = ffebld_left (left_symter))
2024 if (ffebld_op (left_symter) == FFEBLD_opSYMTER)
2025 char_name = ffesymbol_text (ffebld_symter (left_symter));
2027 char_name = "[expr?]";
2029 ffecom_char_args_ (&item, length, ffebld_left (expr));
2031 if (item == error_mark_node || *length == error_mark_node)
2033 item = *length = error_mark_node;
2037 array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
2039 /* ~~~~Handle INTEGER*8 start/end, a la FFEBLD_opARRAYREF. */
2047 end_tree = ffecom_expr (end);
2048 if (flag_bounds_check)
2049 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2051 end_tree = convert (ffecom_f2c_ftnlen_type_node,
2054 if (end_tree == error_mark_node)
2056 item = *length = error_mark_node;
2065 start_tree = ffecom_expr (start);
2066 if (flag_bounds_check)
2067 start_tree = ffecom_subscript_check_ (array, start_tree, 0, 0,
2069 start_tree = convert (ffecom_f2c_ftnlen_type_node,
2072 if (start_tree == error_mark_node)
2074 item = *length = error_mark_node;
2078 start_tree = ffecom_save_tree (start_tree);
2080 item = ffecom_2 (PLUS_EXPR, TREE_TYPE (item),
2082 ffecom_2 (MINUS_EXPR,
2083 TREE_TYPE (start_tree),
2085 ffecom_f2c_ftnlen_one_node));
2089 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2090 ffecom_f2c_ftnlen_one_node,
2091 ffecom_2 (MINUS_EXPR,
2092 ffecom_f2c_ftnlen_type_node,
2098 end_tree = ffecom_expr (end);
2099 if (flag_bounds_check)
2100 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2102 end_tree = convert (ffecom_f2c_ftnlen_type_node,
2105 if (end_tree == error_mark_node)
2107 item = *length = error_mark_node;
2111 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2112 ffecom_f2c_ftnlen_one_node,
2113 ffecom_2 (MINUS_EXPR,
2114 ffecom_f2c_ftnlen_type_node,
2115 end_tree, start_tree));
2121 case FFEBLD_opFUNCREF:
2123 ffesymbol s = ffebld_symter (ffebld_left (expr));
2126 ffetargetCharacterSize size = ffeinfo_size (ffebld_info (expr));
2129 if (size == FFETARGET_charactersizeNONE)
2130 /* ~~Kludge alert! This should someday be fixed. */
2133 *length = build_int_2 (size, 0);
2134 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2136 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
2137 == FFEINFO_whereINTRINSIC)
2141 /* Invocation of an intrinsic returning CHARACTER*1. */
2142 item = ffecom_expr_intrinsic_ (expr, NULL_TREE,
2146 ix = ffeintrin_gfrt_direct (ffebld_symter_implementation (ffebld_left (expr)));
2147 assert (ix != FFECOM_gfrt);
2148 item = ffecom_gfrt_tree_ (ix);
2153 item = ffesymbol_hook (s).decl_tree;
2154 if (item == NULL_TREE)
2156 s = ffecom_sym_transform_ (s);
2157 item = ffesymbol_hook (s).decl_tree;
2159 if (item == error_mark_node)
2161 item = *length = error_mark_node;
2165 if (!ffesymbol_hook (s).addr)
2166 item = ffecom_1_fn (item);
2170 tempvar = ffecom_push_tempvar (char_type_node, size, -1, TRUE);
2172 tempvar = ffebld_nonter_hook (expr);
2175 tempvar = ffecom_1 (ADDR_EXPR,
2176 build_pointer_type (TREE_TYPE (tempvar)),
2179 args = build_tree_list (NULL_TREE, tempvar);
2181 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT) /* Sfunc args by value. */
2182 TREE_CHAIN (args) = ffecom_list_expr (ffebld_right (expr));
2185 TREE_CHAIN (args) = build_tree_list (NULL_TREE, *length);
2186 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
2188 TREE_CHAIN (TREE_CHAIN (args))
2189 = ffecom_arglist_expr_ (ffecom_gfrt_args_ (ix),
2190 ffebld_right (expr));
2194 TREE_CHAIN (TREE_CHAIN (args))
2195 = ffecom_list_ptr_to_expr (ffebld_right (expr));
2199 item = ffecom_3s (CALL_EXPR,
2200 TREE_TYPE (TREE_TYPE (TREE_TYPE (item))),
2201 item, args, NULL_TREE);
2202 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item,
2207 case FFEBLD_opCONVERT:
2209 ffecom_char_args_ (&item, length, ffebld_left (expr));
2211 if (item == error_mark_node || *length == error_mark_node)
2213 item = *length = error_mark_node;
2217 if ((ffebld_size_known (ffebld_left (expr))
2218 == FFETARGET_charactersizeNONE)
2219 || (ffebld_size_known (ffebld_left (expr)) < (ffebld_size (expr))))
2220 { /* Possible blank-padding needed, copy into
2227 tempvar = ffecom_make_tempvar (char_type_node,
2228 ffebld_size (expr), -1);
2230 tempvar = ffebld_nonter_hook (expr);
2233 tempvar = ffecom_1 (ADDR_EXPR,
2234 build_pointer_type (TREE_TYPE (tempvar)),
2237 newlen = build_int_2 (ffebld_size (expr), 0);
2238 TREE_TYPE (newlen) = ffecom_f2c_ftnlen_type_node;
2240 args = build_tree_list (NULL_TREE, tempvar);
2241 TREE_CHAIN (args) = build_tree_list (NULL_TREE, item);
2242 TREE_CHAIN (TREE_CHAIN (args)) = build_tree_list (NULL_TREE, newlen);
2243 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (args)))
2244 = build_tree_list (NULL_TREE, *length);
2246 item = ffecom_call_gfrt (FFECOM_gfrtCOPY, args, NULL_TREE);
2247 TREE_SIDE_EFFECTS (item) = 1;
2248 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), fold (item),
2253 { /* Just truncate the length. */
2254 *length = build_int_2 (ffebld_size (expr), 0);
2255 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2260 assert ("bad op for single char arg expr" == NULL);
2269 /* Check the size of the type to be sure it doesn't overflow the
2270 "portable" capacities of the compiler back end. `dummy' types
2271 can generally overflow the normal sizes as long as the computations
2272 themselves don't overflow. A particular target of the back end
2273 must still enforce its size requirements, though, and the back
2274 end takes care of this in stor-layout.c. */
2276 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2278 ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy)
2280 if (TREE_CODE (type) == ERROR_MARK)
2283 if (TYPE_SIZE (type) == NULL_TREE)
2286 if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
2289 if ((tree_int_cst_sgn (TYPE_SIZE (type)) < 0)
2290 || (!dummy && (((TREE_INT_CST_HIGH (TYPE_SIZE (type)) != 0))
2291 || TREE_OVERFLOW (TYPE_SIZE (type)))))
2293 ffebad_start (FFEBAD_ARRAY_LARGE);
2294 ffebad_string (ffesymbol_text (s));
2295 ffebad_here (0, ffesymbol_where_line (s), ffesymbol_where_column (s));
2298 return error_mark_node;
2305 /* Builds a length argument (PARM_DECL). Also wraps type in an array type
2306 where the dimension info is (1:size) where <size> is ffesymbol_size(s) if
2307 known, length_arg if not known (FFETARGET_charactersizeNONE). */
2309 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2311 ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s)
2313 ffetargetCharacterSize sz = ffesymbol_size (s);
2318 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
2319 tlen = NULL_TREE; /* A statement function, no length passed. */
2322 if (ffesymbol_where (s) == FFEINFO_whereDUMMY)
2323 tlen = ffecom_get_invented_identifier ("__g77_length_%s",
2324 ffesymbol_text (s));
2326 tlen = ffecom_get_invented_identifier ("__g77_%s", "length");
2327 tlen = build_decl (PARM_DECL, tlen, ffecom_f2c_ftnlen_type_node);
2329 DECL_ARTIFICIAL (tlen) = 1;
2333 if (sz == FFETARGET_charactersizeNONE)
2335 assert (tlen != NULL_TREE);
2336 highval = variable_size (tlen);
2340 highval = build_int_2 (sz, 0);
2341 TREE_TYPE (highval) = ffecom_f2c_ftnlen_type_node;
2344 type = build_array_type (type,
2345 build_range_type (ffecom_f2c_ftnlen_type_node,
2346 ffecom_f2c_ftnlen_one_node,
2354 /* ffecom_concat_list_gather_ -- Gather list of concatenated string exprs
2356 ffecomConcatList_ catlist;
2357 ffebld expr; // expr of CHARACTER basictype.
2358 ffetargetCharacterSize max; // max chars to gather or _...NONE if no max
2359 catlist = ffecom_concat_list_gather_(catlist,expr,max);
2361 Scans expr for character subexpressions, updates and returns catlist
2364 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2365 static ffecomConcatList_
2366 ffecom_concat_list_gather_ (ffecomConcatList_ catlist, ffebld expr,
2367 ffetargetCharacterSize max)
2369 ffetargetCharacterSize sz;
2371 recurse: /* :::::::::::::::::::: */
2376 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen >= max))
2377 return catlist; /* Don't append any more items. */
2379 switch (ffebld_op (expr))
2381 case FFEBLD_opCONTER:
2382 case FFEBLD_opSYMTER:
2383 case FFEBLD_opARRAYREF:
2384 case FFEBLD_opFUNCREF:
2385 case FFEBLD_opSUBSTR:
2386 case FFEBLD_opCONVERT: /* Callers should strip this off beforehand
2387 if they don't need to preserve it. */
2388 if (catlist.count == catlist.max)
2389 { /* Make a (larger) list. */
2393 newmax = (catlist.max == 0) ? 8 : catlist.max * 2;
2394 newx = malloc_new_ks (malloc_pool_image (), "catlist",
2395 newmax * sizeof (newx[0]));
2396 if (catlist.max != 0)
2398 memcpy (newx, catlist.exprs, catlist.max * sizeof (newx[0]));
2399 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2400 catlist.max * sizeof (newx[0]));
2402 catlist.max = newmax;
2403 catlist.exprs = newx;
2405 if ((sz = ffebld_size_known (expr)) != FFETARGET_charactersizeNONE)
2406 catlist.minlen += sz;
2408 ++catlist.minlen; /* Not true for F90; can be 0 length. */
2409 if ((sz = ffebld_size_max (expr)) == FFETARGET_charactersizeNONE)
2410 catlist.maxlen = sz;
2412 catlist.maxlen += sz;
2413 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen > max))
2414 { /* This item overlaps (or is beyond) the end
2415 of the destination. */
2416 switch (ffebld_op (expr))
2418 case FFEBLD_opCONTER:
2419 case FFEBLD_opSYMTER:
2420 case FFEBLD_opARRAYREF:
2421 case FFEBLD_opFUNCREF:
2422 case FFEBLD_opSUBSTR:
2423 /* ~~Do useful truncations here. */
2427 assert ("op changed or inconsistent switches!" == NULL);
2431 catlist.exprs[catlist.count++] = expr;
2434 case FFEBLD_opPAREN:
2435 expr = ffebld_left (expr);
2436 goto recurse; /* :::::::::::::::::::: */
2438 case FFEBLD_opCONCATENATE:
2439 catlist = ffecom_concat_list_gather_ (catlist, ffebld_left (expr), max);
2440 expr = ffebld_right (expr);
2441 goto recurse; /* :::::::::::::::::::: */
2443 #if 0 /* Breaks passing small actual arg to larger
2444 dummy arg of sfunc */
2445 case FFEBLD_opCONVERT:
2446 expr = ffebld_left (expr);
2448 ffetargetCharacterSize cmax;
2450 cmax = catlist.len + ffebld_size_known (expr);
2452 if ((max == FFETARGET_charactersizeNONE) || (max > cmax))
2455 goto recurse; /* :::::::::::::::::::: */
2462 assert ("bad op in _gather_" == NULL);
2468 /* ffecom_concat_list_kill_ -- Kill list of concatenated string exprs
2470 ffecomConcatList_ catlist;
2471 ffecom_concat_list_kill_(catlist);
2473 Anything allocated within the list info is deallocated. */
2475 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2477 ffecom_concat_list_kill_ (ffecomConcatList_ catlist)
2479 if (catlist.max != 0)
2480 malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2481 catlist.max * sizeof (catlist.exprs[0]));
2485 /* Make list of concatenated string exprs.
2487 Returns a flattened list of concatenated subexpressions given a
2488 tree of such expressions. */
2490 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2491 static ffecomConcatList_
2492 ffecom_concat_list_new_ (ffebld expr, ffetargetCharacterSize max)
2494 ffecomConcatList_ catlist;
2496 catlist.maxlen = catlist.minlen = catlist.max = catlist.count = 0;
2497 return ffecom_concat_list_gather_ (catlist, expr, max);
2502 /* Provide some kind of useful info on member of aggregate area,
2503 since current g77/gcc technology does not provide debug info
2504 on these members. */
2506 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2508 ffecom_debug_kludge_ (tree aggr, const char *aggr_type, ffesymbol member,
2509 tree member_type UNUSED, ffetargetOffset offset)
2519 for (type_id = member_type;
2520 TREE_CODE (type_id) != IDENTIFIER_NODE;
2523 switch (TREE_CODE (type_id))
2527 type_id = TYPE_NAME (type_id);
2532 type_id = TREE_TYPE (type_id);
2536 assert ("no IDENTIFIER_NODE for type!" == NULL);
2537 type_id = error_mark_node;
2543 if (ffecom_transform_only_dummies_
2544 || !ffe_is_debug_kludge ())
2545 return; /* Can't do this yet, maybe later. */
2548 + strlen (aggr_type)
2549 + IDENTIFIER_LENGTH (DECL_NAME (aggr));
2551 + IDENTIFIER_LENGTH (type_id);
2554 if (((size_t) len) >= ARRAY_SIZE (space))
2555 buff = malloc_new_ks (malloc_pool_image (), "debug_kludge", len + 1);
2559 sprintf (&buff[0], "At (%s) `%s' plus %ld bytes",
2561 IDENTIFIER_POINTER (DECL_NAME (aggr)),
2564 value = build_string (len, buff);
2566 = build_type_variant (build_array_type (char_type_node,
2570 build_int_2 (strlen (buff), 0))),
2572 decl = build_decl (VAR_DECL,
2573 ffecom_get_identifier_ (ffesymbol_text (member)),
2575 TREE_CONSTANT (decl) = 1;
2576 TREE_STATIC (decl) = 1;
2577 DECL_INITIAL (decl) = error_mark_node;
2578 DECL_IN_SYSTEM_HEADER (decl) = 1; /* Don't let -Wunused complain. */
2579 decl = start_decl (decl, FALSE);
2580 finish_decl (decl, value, FALSE);
2582 if (buff != &space[0])
2583 malloc_kill_ks (malloc_pool_image (), buff, len + 1);
2587 /* ffecom_do_entry_ -- Do compilation of a particular entrypoint
2589 ffesymbol fn; // the SUBROUTINE, FUNCTION, or ENTRY symbol itself
2590 int i; // entry# for this entrypoint (used by master fn)
2591 ffecom_do_entrypoint_(s,i);
2593 Makes a public entry point that calls our private master fn (already
2596 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2598 ffecom_do_entry_ (ffesymbol fn, int entrynum)
2601 tree type; /* Type of function. */
2602 tree multi_retval; /* Var holding return value (union). */
2603 tree result; /* Var holding result. */
2604 ffeinfoBasictype bt;
2608 bool charfunc; /* All entry points return same type
2610 bool cmplxfunc; /* Use f2c way of returning COMPLEX. */
2611 bool multi; /* Master fn has multiple return types. */
2612 bool altreturning = FALSE; /* This entry point has alternate returns. */
2613 int old_lineno = lineno;
2614 const char *old_input_filename = input_filename;
2616 input_filename = ffesymbol_where_filename (fn);
2617 lineno = ffesymbol_where_filelinenum (fn);
2619 ffecom_doing_entry_ = TRUE; /* Don't bother with array dimensions. */
2621 switch (ffecom_primary_entry_kind_)
2623 case FFEINFO_kindFUNCTION:
2625 /* Determine actual return type for function. */
2627 gt = FFEGLOBAL_typeFUNC;
2628 bt = ffesymbol_basictype (fn);
2629 kt = ffesymbol_kindtype (fn);
2630 if (bt == FFEINFO_basictypeNONE)
2632 ffeimplic_establish_symbol (fn);
2633 if (ffesymbol_funcresult (fn) != NULL)
2634 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
2635 bt = ffesymbol_basictype (fn);
2636 kt = ffesymbol_kindtype (fn);
2639 if (bt == FFEINFO_basictypeCHARACTER)
2640 charfunc = TRUE, cmplxfunc = FALSE;
2641 else if ((bt == FFEINFO_basictypeCOMPLEX)
2642 && ffesymbol_is_f2c (fn))
2643 charfunc = FALSE, cmplxfunc = TRUE;
2645 charfunc = cmplxfunc = FALSE;
2648 type = ffecom_tree_fun_type_void;
2649 else if (ffesymbol_is_f2c (fn))
2650 type = ffecom_tree_fun_type[bt][kt];
2652 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
2654 if ((type == NULL_TREE)
2655 || (TREE_TYPE (type) == NULL_TREE))
2656 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
2658 multi = (ffecom_master_bt_ == FFEINFO_basictypeNONE);
2661 case FFEINFO_kindSUBROUTINE:
2662 gt = FFEGLOBAL_typeSUBR;
2663 bt = FFEINFO_basictypeNONE;
2664 kt = FFEINFO_kindtypeNONE;
2665 if (ffecom_is_altreturning_)
2666 { /* Am _I_ altreturning? */
2667 for (item = ffesymbol_dummyargs (fn);
2669 item = ffebld_trail (item))
2671 if (ffebld_op (ffebld_head (item)) == FFEBLD_opSTAR)
2673 altreturning = TRUE;
2678 type = ffecom_tree_subr_type;
2680 type = ffecom_tree_fun_type_void;
2683 type = ffecom_tree_fun_type_void;
2690 assert ("say what??" == NULL);
2692 case FFEINFO_kindANY:
2693 gt = FFEGLOBAL_typeANY;
2694 bt = FFEINFO_basictypeNONE;
2695 kt = FFEINFO_kindtypeNONE;
2696 type = error_mark_node;
2703 /* build_decl uses the current lineno and input_filename to set the decl
2704 source info. So, I've putzed with ffestd and ffeste code to update that
2705 source info to point to the appropriate statement just before calling
2706 ffecom_do_entrypoint (which calls this fn). */
2708 start_function (ffecom_get_external_identifier_ (fn),
2710 0, /* nested/inline */
2711 1); /* TREE_PUBLIC */
2713 if (((g = ffesymbol_global (fn)) != NULL)
2714 && ((ffeglobal_type (g) == gt)
2715 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
2717 ffeglobal_set_hook (g, current_function_decl);
2720 /* Reset args in master arg list so they get retransitioned. */
2722 for (item = ffecom_master_arglist_;
2724 item = ffebld_trail (item))
2729 arg = ffebld_head (item);
2730 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2731 continue; /* Alternate return or some such thing. */
2732 s = ffebld_symter (arg);
2733 ffesymbol_hook (s).decl_tree = NULL_TREE;
2734 ffesymbol_hook (s).length_tree = NULL_TREE;
2737 /* Build dummy arg list for this entry point. */
2739 if (charfunc || cmplxfunc)
2740 { /* Prepend arg for where result goes. */
2745 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
2747 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
2749 result = ffecom_get_invented_identifier ("__g77_%s", "result");
2751 /* Make length arg _and_ enhance type info for CHAR arg itself. */
2754 length = ffecom_char_enhance_arg_ (&type, fn);
2756 length = NULL_TREE; /* Not ref'd if !charfunc. */
2758 type = build_pointer_type (type);
2759 result = build_decl (PARM_DECL, result, type);
2761 push_parm_decl (result);
2762 ffecom_func_result_ = result;
2766 push_parm_decl (length);
2767 ffecom_func_length_ = length;
2771 result = DECL_RESULT (current_function_decl);
2773 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (fn), FALSE);
2775 store_parm_decls (0);
2777 ffecom_start_compstmt ();
2778 /* Disallow temp vars at this level. */
2779 current_binding_level->prep_state = 2;
2781 /* Make local var to hold return type for multi-type master fn. */
2785 multi_retval = ffecom_get_invented_identifier ("__g77_%s",
2787 multi_retval = build_decl (VAR_DECL, multi_retval,
2788 ffecom_multi_type_node_);
2789 multi_retval = start_decl (multi_retval, FALSE);
2790 finish_decl (multi_retval, NULL_TREE, FALSE);
2793 multi_retval = NULL_TREE; /* Not actually ref'd if !multi. */
2795 /* Here we emit the actual code for the entry point. */
2801 tree arglist = NULL_TREE;
2802 tree *plist = &arglist;
2808 /* Prepare actual arg list based on master arg list. */
2810 for (list = ffecom_master_arglist_;
2812 list = ffebld_trail (list))
2814 arg = ffebld_head (list);
2815 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2817 s = ffebld_symter (arg);
2818 if (ffesymbol_hook (s).decl_tree == NULL_TREE
2819 || ffesymbol_hook (s).decl_tree == error_mark_node)
2820 actarg = null_pointer_node; /* We don't have this arg. */
2822 actarg = ffesymbol_hook (s).decl_tree;
2823 *plist = build_tree_list (NULL_TREE, actarg);
2824 plist = &TREE_CHAIN (*plist);
2827 /* This code appends the length arguments for character
2828 variables/arrays. */
2830 for (list = ffecom_master_arglist_;
2832 list = ffebld_trail (list))
2834 arg = ffebld_head (list);
2835 if (ffebld_op (arg) != FFEBLD_opSYMTER)
2837 s = ffebld_symter (arg);
2838 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
2839 continue; /* Only looking for CHARACTER arguments. */
2840 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
2841 continue; /* Only looking for variables and arrays. */
2842 if (ffesymbol_hook (s).length_tree == NULL_TREE
2843 || ffesymbol_hook (s).length_tree == error_mark_node)
2844 actarg = ffecom_f2c_ftnlen_zero_node; /* We don't have this arg. */
2846 actarg = ffesymbol_hook (s).length_tree;
2847 *plist = build_tree_list (NULL_TREE, actarg);
2848 plist = &TREE_CHAIN (*plist);
2851 /* Prepend character-value return info to actual arg list. */
2855 prepend = build_tree_list (NULL_TREE, ffecom_func_result_);
2856 TREE_CHAIN (prepend)
2857 = build_tree_list (NULL_TREE, ffecom_func_length_);
2858 TREE_CHAIN (TREE_CHAIN (prepend)) = arglist;
2862 /* Prepend multi-type return value to actual arg list. */
2867 = build_tree_list (NULL_TREE,
2868 ffecom_1 (ADDR_EXPR,
2869 build_pointer_type (TREE_TYPE (multi_retval)),
2871 TREE_CHAIN (prepend) = arglist;
2875 /* Prepend my entry-point number to the actual arg list. */
2877 prepend = build_tree_list (NULL_TREE, build_int_2 (entrynum, 0));
2878 TREE_CHAIN (prepend) = arglist;
2881 /* Build the call to the master function. */
2883 master_fn = ffecom_1_fn (ffecom_previous_function_decl_);
2884 call = ffecom_3s (CALL_EXPR,
2885 TREE_TYPE (TREE_TYPE (TREE_TYPE (master_fn))),
2886 master_fn, arglist, NULL_TREE);
2888 /* Decide whether the master function is a function or subroutine, and
2889 handle the return value for my entry point. */
2891 if (charfunc || ((ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
2894 expand_expr_stmt (call);
2895 expand_null_return ();
2897 else if (multi && cmplxfunc)
2899 expand_expr_stmt (call);
2901 = ffecom_1 (INDIRECT_REF,
2902 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
2904 result = ffecom_modify (NULL_TREE, result,
2905 ffecom_2 (COMPONENT_REF, TREE_TYPE (result),
2907 ffecom_multi_fields_[bt][kt]));
2908 expand_expr_stmt (result);
2909 expand_null_return ();
2913 expand_expr_stmt (call);
2915 = ffecom_modify (NULL_TREE, result,
2916 convert (TREE_TYPE (result),
2917 ffecom_2 (COMPONENT_REF,
2918 ffecom_tree_type[bt][kt],
2920 ffecom_multi_fields_[bt][kt])));
2921 expand_return (result);
2926 = ffecom_1 (INDIRECT_REF,
2927 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
2929 result = ffecom_modify (NULL_TREE, result, call);
2930 expand_expr_stmt (result);
2931 expand_null_return ();
2935 result = ffecom_modify (NULL_TREE,
2937 convert (TREE_TYPE (result),
2939 expand_return (result);
2943 ffecom_end_compstmt ();
2945 finish_function (0);
2947 lineno = old_lineno;
2948 input_filename = old_input_filename;
2950 ffecom_doing_entry_ = FALSE;
2954 /* Transform expr into gcc tree with possible destination
2956 Recursive descent on expr while making corresponding tree nodes and
2957 attaching type info and such. If destination supplied and compatible
2958 with temporary that would be made in certain cases, temporary isn't
2959 made, destination used instead, and dest_used flag set TRUE. */
2961 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2963 ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
2964 bool *dest_used, bool assignp, bool widenp)
2969 ffeinfoBasictype bt;
2972 tree dt; /* decl_tree for an ffesymbol. */
2973 tree tree_type, tree_type_x;
2976 enum tree_code code;
2978 assert (expr != NULL);
2980 if (dest_used != NULL)
2983 bt = ffeinfo_basictype (ffebld_info (expr));
2984 kt = ffeinfo_kindtype (ffebld_info (expr));
2985 tree_type = ffecom_tree_type[bt][kt];
2987 /* Widen integral arithmetic as desired while preserving signedness. */
2988 tree_type_x = NULL_TREE;
2989 if (widenp && tree_type
2990 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
2991 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
2992 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
2994 switch (ffebld_op (expr))
2996 case FFEBLD_opACCTER:
2999 ffebit bits = ffebld_accter_bits (expr);
3000 ffetargetOffset source_offset = 0;
3001 ffetargetOffset dest_offset = ffebld_accter_pad (expr);
3004 assert (dest_offset == 0
3005 || (bt == FFEINFO_basictypeCHARACTER
3006 && kt == FFEINFO_kindtypeCHARACTER1));
3011 ffebldConstantUnion cu;
3014 ffebldConstantArray ca = ffebld_accter (expr);
3016 ffebit_test (bits, source_offset, &value, &length);
3022 for (i = 0; i < length; ++i)
3024 cu = ffebld_constantarray_get (ca, bt, kt,
3027 t = ffecom_constantunion (&cu, bt, kt, tree_type);
3030 && dest_offset != 0)
3031 purpose = build_int_2 (dest_offset, 0);
3033 purpose = NULL_TREE;
3035 if (list == NULL_TREE)
3036 list = item = build_tree_list (purpose, t);
3039 TREE_CHAIN (item) = build_tree_list (purpose, t);
3040 item = TREE_CHAIN (item);
3044 source_offset += length;
3045 dest_offset += length;
3049 item = build_int_2 ((ffebld_accter_size (expr)
3050 + ffebld_accter_pad (expr)) - 1, 0);
3051 ffebit_kill (ffebld_accter_bits (expr));
3052 TREE_TYPE (item) = ffecom_integer_type_node;
3056 build_range_type (ffecom_integer_type_node,
3057 ffecom_integer_zero_node,
3059 list = build (CONSTRUCTOR, item, NULL_TREE, list);
3060 TREE_CONSTANT (list) = 1;
3061 TREE_STATIC (list) = 1;
3064 case FFEBLD_opARRTER:
3069 if (ffebld_arrter_pad (expr) == 0)
3073 assert (bt == FFEINFO_basictypeCHARACTER
3074 && kt == FFEINFO_kindtypeCHARACTER1);
3076 /* Becomes PURPOSE first time through loop. */
3077 item = build_int_2 (ffebld_arrter_pad (expr), 0);
3080 for (i = 0; i < ffebld_arrter_size (expr); ++i)
3082 ffebldConstantUnion cu
3083 = ffebld_constantarray_get (ffebld_arrter (expr), bt, kt, i);
3085 t = ffecom_constantunion (&cu, bt, kt, tree_type);
3087 if (list == NULL_TREE)
3088 /* Assume item is PURPOSE first time through loop. */
3089 list = item = build_tree_list (item, t);
3092 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
3093 item = TREE_CHAIN (item);
3098 item = build_int_2 ((ffebld_arrter_size (expr)
3099 + ffebld_arrter_pad (expr)) - 1, 0);
3100 TREE_TYPE (item) = ffecom_integer_type_node;
3104 build_range_type (ffecom_integer_type_node,
3105 ffecom_integer_zero_node,
3107 list = build (CONSTRUCTOR, item, NULL_TREE, list);
3108 TREE_CONSTANT (list) = 1;
3109 TREE_STATIC (list) = 1;
3112 case FFEBLD_opCONTER:
3113 assert (ffebld_conter_pad (expr) == 0);
3115 = ffecom_constantunion (&ffebld_constant_union (ffebld_conter (expr)),
3119 case FFEBLD_opSYMTER:
3120 if ((ffebld_symter_generic (expr) != FFEINTRIN_genNONE)
3121 || (ffebld_symter_specific (expr) != FFEINTRIN_specNONE))
3122 return ffecom_ptr_to_expr (expr); /* Same as %REF(intrinsic). */
3123 s = ffebld_symter (expr);
3124 t = ffesymbol_hook (s).decl_tree;
3127 { /* ASSIGN'ed-label expr. */
3128 if (ffe_is_ugly_assign ())
3130 /* User explicitly wants ASSIGN'ed variables to be at the same
3131 memory address as the variables when used in non-ASSIGN
3132 contexts. That can make old, arcane, non-standard code
3133 work, but don't try to do it when a pointer wouldn't fit
3134 in the normal variable (take other approach, and warn,
3139 s = ffecom_sym_transform_ (s);
3140 t = ffesymbol_hook (s).decl_tree;
3141 assert (t != NULL_TREE);
3144 if (t == error_mark_node)
3147 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (t)))
3148 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
3150 if (ffesymbol_hook (s).addr)
3151 t = ffecom_1 (INDIRECT_REF,
3152 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3156 if (ffesymbol_hook (s).assign_tree == NULL_TREE)
3158 ffebad_start_msg ("ASSIGN'ed label cannot fit into `%A' at %0 -- using wider sibling",
3159 FFEBAD_severityWARNING);
3160 ffebad_string (ffesymbol_text (s));
3161 ffebad_here (0, ffesymbol_where_line (s),
3162 ffesymbol_where_column (s));
3167 /* Don't use the normal variable's tree for ASSIGN, though mark
3168 it as in the system header (housekeeping). Use an explicit,
3169 specially created sibling that is known to be wide enough
3170 to hold pointers to labels. */
3173 && TREE_CODE (t) == VAR_DECL)
3174 DECL_IN_SYSTEM_HEADER (t) = 1; /* Don't let -Wunused complain. */
3176 t = ffesymbol_hook (s).assign_tree;
3179 s = ffecom_sym_transform_assign_ (s);
3180 t = ffesymbol_hook (s).assign_tree;
3181 assert (t != NULL_TREE);
3188 s = ffecom_sym_transform_ (s);
3189 t = ffesymbol_hook (s).decl_tree;
3190 assert (t != NULL_TREE);
3192 if (ffesymbol_hook (s).addr)
3193 t = ffecom_1 (INDIRECT_REF,
3194 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3198 case FFEBLD_opARRAYREF:
3199 return ffecom_arrayref_ (NULL_TREE, expr, 0);
3201 case FFEBLD_opUPLUS:
3202 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3203 return ffecom_1 (NOP_EXPR, tree_type, left);
3205 case FFEBLD_opPAREN:
3206 /* ~~~Make sure Fortran rules respected here */
3207 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3208 return ffecom_1 (NOP_EXPR, tree_type, left);
3210 case FFEBLD_opUMINUS:
3211 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3214 tree_type = tree_type_x;
3215 left = convert (tree_type, left);
3217 return ffecom_1 (NEGATE_EXPR, tree_type, left);
3220 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3221 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3224 tree_type = tree_type_x;
3225 left = convert (tree_type, left);
3226 right = convert (tree_type, right);
3228 return ffecom_2 (PLUS_EXPR, tree_type, left, right);
3230 case FFEBLD_opSUBTRACT:
3231 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3232 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3235 tree_type = tree_type_x;
3236 left = convert (tree_type, left);
3237 right = convert (tree_type, right);
3239 return ffecom_2 (MINUS_EXPR, tree_type, left, right);
3241 case FFEBLD_opMULTIPLY:
3242 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3243 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3246 tree_type = tree_type_x;
3247 left = convert (tree_type, left);
3248 right = convert (tree_type, right);
3250 return ffecom_2 (MULT_EXPR, tree_type, left, right);
3252 case FFEBLD_opDIVIDE:
3253 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3254 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3257 tree_type = tree_type_x;
3258 left = convert (tree_type, left);
3259 right = convert (tree_type, right);
3261 return ffecom_tree_divide_ (tree_type, left, right,
3262 dest_tree, dest, dest_used,
3263 ffebld_nonter_hook (expr));
3265 case FFEBLD_opPOWER:
3267 ffebld left = ffebld_left (expr);
3268 ffebld right = ffebld_right (expr);
3270 ffeinfoKindtype rtkt;
3271 ffeinfoKindtype ltkt;
3274 switch (ffeinfo_basictype (ffebld_info (right)))
3277 case FFEINFO_basictypeINTEGER:
3280 item = ffecom_expr_power_integer_ (expr);
3281 if (item != NULL_TREE)
3285 rtkt = FFEINFO_kindtypeINTEGER1;
3286 switch (ffeinfo_basictype (ffebld_info (left)))
3288 case FFEINFO_basictypeINTEGER:
3289 if ((ffeinfo_kindtype (ffebld_info (left))
3290 == FFEINFO_kindtypeINTEGER4)
3291 || (ffeinfo_kindtype (ffebld_info (right))
3292 == FFEINFO_kindtypeINTEGER4))
3294 code = FFECOM_gfrtPOW_QQ;
3295 ltkt = FFEINFO_kindtypeINTEGER4;
3296 rtkt = FFEINFO_kindtypeINTEGER4;
3300 code = FFECOM_gfrtPOW_II;
3301 ltkt = FFEINFO_kindtypeINTEGER1;
3305 case FFEINFO_basictypeREAL:
3306 if (ffeinfo_kindtype (ffebld_info (left))
3307 == FFEINFO_kindtypeREAL1)
3309 code = FFECOM_gfrtPOW_RI;
3310 ltkt = FFEINFO_kindtypeREAL1;
3314 code = FFECOM_gfrtPOW_DI;
3315 ltkt = FFEINFO_kindtypeREAL2;
3319 case FFEINFO_basictypeCOMPLEX:
3320 if (ffeinfo_kindtype (ffebld_info (left))
3321 == FFEINFO_kindtypeREAL1)
3323 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
3324 ltkt = FFEINFO_kindtypeREAL1;
3328 code = FFECOM_gfrtPOW_ZI; /* Overlapping result okay. */
3329 ltkt = FFEINFO_kindtypeREAL2;
3334 assert ("bad pow_*i" == NULL);
3335 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */
3336 ltkt = FFEINFO_kindtypeREAL1;
3339 if (ffeinfo_kindtype (ffebld_info (left)) != ltkt)
3340 left = ffeexpr_convert (left, NULL, NULL,
3341 ffeinfo_basictype (ffebld_info (left)),
3343 FFETARGET_charactersizeNONE,
3344 FFEEXPR_contextLET);
3345 if (ffeinfo_kindtype (ffebld_info (right)) != rtkt)
3346 right = ffeexpr_convert (right, NULL, NULL,
3347 FFEINFO_basictypeINTEGER,
3349 FFETARGET_charactersizeNONE,
3350 FFEEXPR_contextLET);
3353 case FFEINFO_basictypeREAL:
3354 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3355 left = ffeexpr_convert (left, NULL, NULL, FFEINFO_basictypeREAL,
3356 FFEINFO_kindtypeREALDOUBLE, 0,
3357 FFETARGET_charactersizeNONE,
3358 FFEEXPR_contextLET);
3359 if (ffeinfo_kindtype (ffebld_info (right))
3360 == FFEINFO_kindtypeREAL1)
3361 right = ffeexpr_convert (right, NULL, NULL,
3362 FFEINFO_basictypeREAL,
3363 FFEINFO_kindtypeREALDOUBLE, 0,
3364 FFETARGET_charactersizeNONE,
3365 FFEEXPR_contextLET);
3366 /* We used to call FFECOM_gfrtPOW_DD here,
3367 which passes arguments by reference. */
3368 code = FFECOM_gfrtL_POW;
3369 /* Pass arguments by value. */
3373 case FFEINFO_basictypeCOMPLEX:
3374 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3375 left = ffeexpr_convert (left, NULL, NULL,
3376 FFEINFO_basictypeCOMPLEX,
3377 FFEINFO_kindtypeREALDOUBLE, 0,
3378 FFETARGET_charactersizeNONE,
3379 FFEEXPR_contextLET);
3380 if (ffeinfo_kindtype (ffebld_info (right))
3381 == FFEINFO_kindtypeREAL1)
3382 right = ffeexpr_convert (right, NULL, NULL,
3383 FFEINFO_basictypeCOMPLEX,
3384 FFEINFO_kindtypeREALDOUBLE, 0,
3385 FFETARGET_charactersizeNONE,
3386 FFEEXPR_contextLET);
3387 code = FFECOM_gfrtPOW_ZZ; /* Overlapping result okay. */
3388 ref = TRUE; /* Pass arguments by reference. */
3392 assert ("bad pow_x*" == NULL);
3393 code = FFECOM_gfrtPOW_II;
3396 return ffecom_call_binop_ (ffecom_gfrt_tree_ (code),
3397 ffecom_gfrt_kindtype (code),
3398 (ffe_is_f2c_library ()
3399 && ffecom_gfrt_complex_[code]),
3400 tree_type, left, right,
3401 dest_tree, dest, dest_used,
3402 NULL_TREE, FALSE, ref,
3403 ffebld_nonter_hook (expr));
3409 case FFEINFO_basictypeLOGICAL:
3410 item = ffecom_truth_value_invert (ffecom_expr (ffebld_left (expr)));
3411 return convert (tree_type, item);
3413 case FFEINFO_basictypeINTEGER:
3414 return ffecom_1 (BIT_NOT_EXPR, tree_type,
3415 ffecom_expr (ffebld_left (expr)));
3418 assert ("NOT bad basictype" == NULL);
3420 case FFEINFO_basictypeANY:
3421 return error_mark_node;
3425 case FFEBLD_opFUNCREF:
3426 assert (ffeinfo_basictype (ffebld_info (expr))
3427 != FFEINFO_basictypeCHARACTER);
3429 case FFEBLD_opSUBRREF:
3430 if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
3431 == FFEINFO_whereINTRINSIC)
3432 { /* Invocation of an intrinsic. */
3433 item = ffecom_expr_intrinsic_ (expr, dest_tree, dest,
3437 s = ffebld_symter (ffebld_left (expr));
3438 dt = ffesymbol_hook (s).decl_tree;
3439 if (dt == NULL_TREE)
3441 s = ffecom_sym_transform_ (s);
3442 dt = ffesymbol_hook (s).decl_tree;
3444 if (dt == error_mark_node)
3447 if (ffesymbol_hook (s).addr)
3450 item = ffecom_1_fn (dt);
3452 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
3453 args = ffecom_list_expr (ffebld_right (expr));
3455 args = ffecom_list_ptr_to_expr (ffebld_right (expr));
3457 if (args == error_mark_node)
3458 return error_mark_node;
3460 item = ffecom_call_ (item, kt,
3461 ffesymbol_is_f2c (s)
3462 && (bt == FFEINFO_basictypeCOMPLEX)
3463 && (ffesymbol_where (s)
3464 != FFEINFO_whereCONSTANT),
3467 dest_tree, dest, dest_used,
3468 error_mark_node, FALSE,
3469 ffebld_nonter_hook (expr));
3470 TREE_SIDE_EFFECTS (item) = 1;
3476 case FFEINFO_basictypeLOGICAL:
3478 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3479 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3480 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3481 return convert (tree_type, item);
3483 case FFEINFO_basictypeINTEGER:
3484 return ffecom_2 (BIT_AND_EXPR, tree_type,
3485 ffecom_expr (ffebld_left (expr)),
3486 ffecom_expr (ffebld_right (expr)));
3489 assert ("AND bad basictype" == NULL);
3491 case FFEINFO_basictypeANY:
3492 return error_mark_node;
3499 case FFEINFO_basictypeLOGICAL:
3501 = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
3502 ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3503 ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3504 return convert (tree_type, item);
3506 case FFEINFO_basictypeINTEGER:
3507 return ffecom_2 (BIT_IOR_EXPR, tree_type,
3508 ffecom_expr (ffebld_left (expr)),
3509 ffecom_expr (ffebld_right (expr)));
3512 assert ("OR bad basictype" == NULL);
3514 case FFEINFO_basictypeANY:
3515 return error_mark_node;
3523 case FFEINFO_basictypeLOGICAL:
3525 = ffecom_2 (NE_EXPR, integer_type_node,
3526 ffecom_expr (ffebld_left (expr)),
3527 ffecom_expr (ffebld_right (expr)));
3528 return convert (tree_type, ffecom_truth_value (item));
3530 case FFEINFO_basictypeINTEGER:
3531 return ffecom_2 (BIT_XOR_EXPR, tree_type,
3532 ffecom_expr (ffebld_left (expr)),
3533 ffecom_expr (ffebld_right (expr)));
3536 assert ("XOR/NEQV bad basictype" == NULL);
3538 case FFEINFO_basictypeANY:
3539 return error_mark_node;
3546 case FFEINFO_basictypeLOGICAL:
3548 = ffecom_2 (EQ_EXPR, integer_type_node,
3549 ffecom_expr (ffebld_left (expr)),
3550 ffecom_expr (ffebld_right (expr)));
3551 return convert (tree_type, ffecom_truth_value (item));
3553 case FFEINFO_basictypeINTEGER:
3555 ffecom_1 (BIT_NOT_EXPR, tree_type,
3556 ffecom_2 (BIT_XOR_EXPR, tree_type,
3557 ffecom_expr (ffebld_left (expr)),
3558 ffecom_expr (ffebld_right (expr))));
3561 assert ("EQV bad basictype" == NULL);
3563 case FFEINFO_basictypeANY:
3564 return error_mark_node;
3568 case FFEBLD_opCONVERT:
3569 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opANY)
3570 return error_mark_node;
3574 case FFEINFO_basictypeLOGICAL:
3575 case FFEINFO_basictypeINTEGER:
3576 case FFEINFO_basictypeREAL:
3577 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3579 case FFEINFO_basictypeCOMPLEX:
3580 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3582 case FFEINFO_basictypeINTEGER:
3583 case FFEINFO_basictypeLOGICAL:
3584 case FFEINFO_basictypeREAL:
3585 item = ffecom_expr (ffebld_left (expr));
3586 if (item == error_mark_node)
3587 return error_mark_node;
3588 /* convert() takes care of converting to the subtype first,
3589 at least in gcc-2.7.2. */
3590 item = convert (tree_type, item);
3593 case FFEINFO_basictypeCOMPLEX:
3594 return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3597 assert ("CONVERT COMPLEX bad basictype" == NULL);
3599 case FFEINFO_basictypeANY:
3600 return error_mark_node;
3605 assert ("CONVERT bad basictype" == NULL);
3607 case FFEINFO_basictypeANY:
3608 return error_mark_node;
3614 goto relational; /* :::::::::::::::::::: */
3618 goto relational; /* :::::::::::::::::::: */
3622 goto relational; /* :::::::::::::::::::: */
3626 goto relational; /* :::::::::::::::::::: */
3630 goto relational; /* :::::::::::::::::::: */
3635 relational: /* :::::::::::::::::::: */
3636 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3638 case FFEINFO_basictypeLOGICAL:
3639 case FFEINFO_basictypeINTEGER:
3640 case FFEINFO_basictypeREAL:
3641 item = ffecom_2 (code, integer_type_node,
3642 ffecom_expr (ffebld_left (expr)),
3643 ffecom_expr (ffebld_right (expr)));
3644 return convert (tree_type, item);
3646 case FFEINFO_basictypeCOMPLEX:
3647 assert (code == EQ_EXPR || code == NE_EXPR);
3650 tree arg1 = ffecom_expr (ffebld_left (expr));
3651 tree arg2 = ffecom_expr (ffebld_right (expr));
3653 if (arg1 == error_mark_node || arg2 == error_mark_node)
3654 return error_mark_node;
3656 arg1 = ffecom_save_tree (arg1);
3657 arg2 = ffecom_save_tree (arg2);
3659 if (TREE_CODE (TREE_TYPE (arg1)) == COMPLEX_TYPE)
3661 real_type = TREE_TYPE (TREE_TYPE (arg1));
3662 assert (real_type == TREE_TYPE (TREE_TYPE (arg2)));
3666 real_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg1)));
3667 assert (real_type == TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg2))));
3671 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3672 ffecom_2 (EQ_EXPR, integer_type_node,
3673 ffecom_1 (REALPART_EXPR, real_type, arg1),
3674 ffecom_1 (REALPART_EXPR, real_type, arg2)),
3675 ffecom_2 (EQ_EXPR, integer_type_node,
3676 ffecom_1 (IMAGPART_EXPR, real_type, arg1),
3677 ffecom_1 (IMAGPART_EXPR, real_type,
3679 if (code == EQ_EXPR)
3680 item = ffecom_truth_value (item);
3682 item = ffecom_truth_value_invert (item);
3683 return convert (tree_type, item);
3686 case FFEINFO_basictypeCHARACTER:
3688 ffebld left = ffebld_left (expr);
3689 ffebld right = ffebld_right (expr);
3695 /* f2c run-time functions do the implicit blank-padding for us,
3696 so we don't usually have to implement blank-padding ourselves.
3697 (The exception is when we pass an argument to a separately
3698 compiled statement function -- if we know the arg is not the
3699 same length as the dummy, we must truncate or extend it. If
3700 we "inline" statement functions, that necessity goes away as
3703 Strip off the CONVERT operators that blank-pad. (Truncation by
3704 CONVERT shouldn't happen here, but it can happen in
3707 while (ffebld_op (left) == FFEBLD_opCONVERT)
3708 left = ffebld_left (left);
3709 while (ffebld_op (right) == FFEBLD_opCONVERT)
3710 right = ffebld_left (right);
3712 left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
3713 right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
3715 if (left_tree == error_mark_node || left_length == error_mark_node
3716 || right_tree == error_mark_node
3717 || right_length == error_mark_node)
3718 return error_mark_node;
3720 if ((ffebld_size_known (left) == 1)
3721 && (ffebld_size_known (right) == 1))
3724 = ffecom_1 (INDIRECT_REF,
3725 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3728 = ffecom_1 (INDIRECT_REF,
3729 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3733 = ffecom_2 (code, integer_type_node,
3734 ffecom_2 (ARRAY_REF,
3735 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3738 ffecom_2 (ARRAY_REF,
3739 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3745 item = build_tree_list (NULL_TREE, left_tree);
3746 TREE_CHAIN (item) = build_tree_list (NULL_TREE, right_tree);
3747 TREE_CHAIN (TREE_CHAIN (item)) = build_tree_list (NULL_TREE,
3749 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
3750 = build_tree_list (NULL_TREE, right_length);
3751 item = ffecom_call_gfrt (FFECOM_gfrtCMP, item, NULL_TREE);
3752 item = ffecom_2 (code, integer_type_node,
3754 convert (TREE_TYPE (item),
3755 integer_zero_node));
3757 item = convert (tree_type, item);
3763 assert ("relational bad basictype" == NULL);
3765 case FFEINFO_basictypeANY:
3766 return error_mark_node;
3770 case FFEBLD_opPERCENT_LOC:
3771 item = ffecom_arg_ptr_to_expr (ffebld_left (expr), &list);
3772 return convert (tree_type, item);
3776 case FFEBLD_opBOUNDS:
3777 case FFEBLD_opREPEAT:
3778 case FFEBLD_opLABTER:
3779 case FFEBLD_opLABTOK:
3780 case FFEBLD_opIMPDO:
3781 case FFEBLD_opCONCATENATE:
3782 case FFEBLD_opSUBSTR:
3784 assert ("bad op" == NULL);
3787 return error_mark_node;
3791 assert ("didn't think anything got here anymore!!" == NULL);
3793 switch (ffebld_arity (expr))
3796 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3797 TREE_OPERAND (item, 1) = ffecom_expr (ffebld_right (expr));
3798 if (TREE_OPERAND (item, 0) == error_mark_node
3799 || TREE_OPERAND (item, 1) == error_mark_node)
3800 return error_mark_node;
3804 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3805 if (TREE_OPERAND (item, 0) == error_mark_node)
3806 return error_mark_node;
3818 /* Returns the tree that does the intrinsic invocation.
3820 Note: this function applies only to intrinsics returning
3821 CHARACTER*1 or non-CHARACTER results, and to intrinsic
3824 #if FFECOM_targetCURRENT == FFECOM_targetGCC
3826 ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
3827 ffebld dest, bool *dest_used)
3830 tree saved_expr1; /* For those who need it. */
3831 tree saved_expr2; /* For those who need it. */
3832 ffeinfoBasictype bt;
3836 tree real_type; /* REAL type corresponding to COMPLEX. */
3838 ffebld list = ffebld_right (expr); /* List of (some) args. */
3839 ffebld arg1; /* For handy reference. */
3842 ffeintrinImp codegen_imp;
3845 assert (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER);
3847 if (dest_used != NULL)
3850 bt = ffeinfo_basictype (ffebld_info (expr));
3851 kt = ffeinfo_kindtype (ffebld_info (expr));
3852 tree_type = ffecom_tree_type[bt][kt];
3856 arg1 = ffebld_head (list);
3857 if (arg1 != NULL && ffebld_op (arg1) == FFEBLD_opANY)
3858 return error_mark_node;
3859 if ((list = ffebld_trail (list)) != NULL)
3861 arg2 = ffebld_head (list);
3862 if (arg2 != NULL && ffebld_op (arg2) == FFEBLD_opANY)
3863 return error_mark_node;
3864 if ((list = ffebld_trail (list)) != NULL)
3866 arg3 = ffebld_head (list);
3867 if (arg3 != NULL && ffebld_op (arg3) == FFEBLD_opANY)
3868 return error_mark_node;
3877 arg1 = arg2 = arg3 = NULL;
3879 /* <list> ends up at the opITEM of the 3rd arg, or NULL if there are < 3
3880 args. This is used by the MAX/MIN expansions. */
3883 arg1_type = ffecom_tree_type
3884 [ffeinfo_basictype (ffebld_info (arg1))]
3885 [ffeinfo_kindtype (ffebld_info (arg1))];
3887 arg1_type = NULL_TREE; /* Really not needed, but might catch bugs
3890 /* There are several ways for each of the cases in the following switch
3891 statements to exit (from simplest to use to most complicated):
3893 break; (when expr_tree == NULL)
3895 A standard call is made to the specific intrinsic just as if it had been
3896 passed in as a dummy procedure and called as any old procedure. This
3897 method can produce slower code but in some cases it's the easiest way for
3898 now. However, if a (presumably faster) direct call is available,
3899 that is used, so this is the easiest way in many more cases now.
3901 gfrt = FFECOM_gfrtWHATEVER;
3904 gfrt contains the gfrt index of a library function to call, passing the
3905 argument(s) by value rather than by reference. Used when a more
3906 careful choice of library function is needed than that provided
3907 by the vanilla `break;'.
3911 The expr_tree has been completely set up and is ready to be returned
3912 as is. No further actions are taken. Use this when the tree is not
3913 in the simple form for one of the arity_n labels. */
3915 /* For info on how the switch statement cases were written, see the files
3916 enclosed in comments below the switch statement. */
3918 codegen_imp = ffebld_symter_implementation (ffebld_left (expr));
3919 gfrt = ffeintrin_gfrt_direct (codegen_imp);
3920 if (gfrt == FFECOM_gfrt)
3921 gfrt = ffeintrin_gfrt_indirect (codegen_imp);
3923 switch (codegen_imp)
3925 case FFEINTRIN_impABS:
3926 case FFEINTRIN_impCABS:
3927 case FFEINTRIN_impCDABS:
3928 case FFEINTRIN_impDABS:
3929 case FFEINTRIN_impIABS:
3930 if (ffeinfo_basictype (ffebld_info (arg1))
3931 == FFEINFO_basictypeCOMPLEX)
3933 if (kt == FFEINFO_kindtypeREAL1)
3934 gfrt = FFECOM_gfrtCABS;
3935 else if (kt == FFEINFO_kindtypeREAL2)
3936 gfrt = FFECOM_gfrtCDABS;
3939 return ffecom_1 (ABS_EXPR, tree_type,
3940 convert (tree_type, ffecom_expr (arg1)));
3942 case FFEINTRIN_impACOS:
3943 case FFEINTRIN_impDACOS:
3946 case FFEINTRIN_impAIMAG:
3947 case FFEINTRIN_impDIMAG:
3948 case FFEINTRIN_impIMAGPART:
3949 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
3950 arg1_type = TREE_TYPE (arg1_type);
3952 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
3956 ffecom_1 (IMAGPART_EXPR, arg1_type,
3957 ffecom_expr (arg1)));
3959 case FFEINTRIN_impAINT:
3960 case FFEINTRIN_impDINT:
3962 /* ~~Someday implement FIX_TRUNC_EXPR yielding same type as arg. */
3963 return ffecom_1 (FIX_TRUNC_EXPR, tree_type, ffecom_expr (arg1));
3964 #else /* in the meantime, must use floor to avoid range problems with ints */
3965 /* r__1 = r1 >= 0 ? floor(r1) : -floor(-r1); */
3966 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
3969 ffecom_3 (COND_EXPR, double_type_node,
3971 (ffecom_2 (GE_EXPR, integer_type_node,
3974 ffecom_float_zero_))),
3975 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
3976 build_tree_list (NULL_TREE,
3977 convert (double_type_node,
3980 ffecom_1 (NEGATE_EXPR, double_type_node,
3981 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
3982 build_tree_list (NULL_TREE,
3983 convert (double_type_node,
3984 ffecom_1 (NEGATE_EXPR,
3992 case FFEINTRIN_impANINT:
3993 case FFEINTRIN_impDNINT:
3994 #if 0 /* This way of doing it won't handle real
3995 numbers of large magnitudes. */
3996 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
3997 expr_tree = convert (tree_type,
3998 convert (integer_type_node,
3999 ffecom_3 (COND_EXPR, tree_type,
4004 ffecom_float_zero_)),
4005 ffecom_2 (PLUS_EXPR,
4008 ffecom_float_half_),
4009 ffecom_2 (MINUS_EXPR,
4012 ffecom_float_half_))));
4014 #else /* So we instead call floor. */
4015 /* r__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1) */
4016 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4019 ffecom_3 (COND_EXPR, double_type_node,
4021 (ffecom_2 (GE_EXPR, integer_type_node,
4024 ffecom_float_zero_))),
4025 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4026 build_tree_list (NULL_TREE,
4027 convert (double_type_node,
4028 ffecom_2 (PLUS_EXPR,
4032 ffecom_float_half_)))),
4034 ffecom_1 (NEGATE_EXPR, double_type_node,
4035 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4036 build_tree_list (NULL_TREE,
4037 convert (double_type_node,
4038 ffecom_2 (MINUS_EXPR,
4041 ffecom_float_half_),
4048 case FFEINTRIN_impASIN:
4049 case FFEINTRIN_impDASIN:
4050 case FFEINTRIN_impATAN:
4051 case FFEINTRIN_impDATAN:
4052 case FFEINTRIN_impATAN2:
4053 case FFEINTRIN_impDATAN2:
4056 case FFEINTRIN_impCHAR:
4057 case FFEINTRIN_impACHAR:
4059 tempvar = ffecom_make_tempvar (char_type_node, 1, -1);
4061 tempvar = ffebld_nonter_hook (expr);
4065 tree tmv = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (tempvar)));
4067 expr_tree = ffecom_modify (tmv,
4068 ffecom_2 (ARRAY_REF, tmv, tempvar,
4070 convert (tmv, ffecom_expr (arg1)));
4072 expr_tree = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar),
4075 expr_tree = ffecom_1 (ADDR_EXPR,
4076 build_pointer_type (TREE_TYPE (expr_tree)),
4080 case FFEINTRIN_impCMPLX:
4081 case FFEINTRIN_impDCMPLX:
4084 convert (tree_type, ffecom_expr (arg1));
4086 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4088 ffecom_2 (COMPLEX_EXPR, tree_type,
4089 convert (real_type, ffecom_expr (arg1)),
4091 ffecom_expr (arg2)));
4093 case FFEINTRIN_impCOMPLEX:
4095 ffecom_2 (COMPLEX_EXPR, tree_type,
4097 ffecom_expr (arg2));
4099 case FFEINTRIN_impCONJG:
4100 case FFEINTRIN_impDCONJG:
4104 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4105 arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4107 ffecom_2 (COMPLEX_EXPR, tree_type,
4108 ffecom_1 (REALPART_EXPR, real_type, arg1_tree),
4109 ffecom_1 (NEGATE_EXPR, real_type,
4110 ffecom_1 (IMAGPART_EXPR, real_type, arg1_tree)));
4113 case FFEINTRIN_impCOS:
4114 case FFEINTRIN_impCCOS:
4115 case FFEINTRIN_impCDCOS:
4116 case FFEINTRIN_impDCOS:
4117 if (bt == FFEINFO_basictypeCOMPLEX)
4119 if (kt == FFEINFO_kindtypeREAL1)
4120 gfrt = FFECOM_gfrtCCOS; /* Overlapping result okay. */
4121 else if (kt == FFEINFO_kindtypeREAL2)
4122 gfrt = FFECOM_gfrtCDCOS; /* Overlapping result okay. */
4126 case FFEINTRIN_impCOSH:
4127 case FFEINTRIN_impDCOSH:
4130 case FFEINTRIN_impDBLE:
4131 case FFEINTRIN_impDFLOAT:
4132 case FFEINTRIN_impDREAL:
4133 case FFEINTRIN_impFLOAT:
4134 case FFEINTRIN_impIDINT:
4135 case FFEINTRIN_impIFIX:
4136 case FFEINTRIN_impINT2:
4137 case FFEINTRIN_impINT8:
4138 case FFEINTRIN_impINT:
4139 case FFEINTRIN_impLONG:
4140 case FFEINTRIN_impREAL:
4141 case FFEINTRIN_impSHORT:
4142 case FFEINTRIN_impSNGL:
4143 return convert (tree_type, ffecom_expr (arg1));
4145 case FFEINTRIN_impDIM:
4146 case FFEINTRIN_impDDIM:
4147 case FFEINTRIN_impIDIM:
4148 saved_expr1 = ffecom_save_tree (convert (tree_type,
4149 ffecom_expr (arg1)));
4150 saved_expr2 = ffecom_save_tree (convert (tree_type,
4151 ffecom_expr (arg2)));
4153 ffecom_3 (COND_EXPR, tree_type,
4155 (ffecom_2 (GT_EXPR, integer_type_node,
4158 ffecom_2 (MINUS_EXPR, tree_type,
4161 convert (tree_type, ffecom_float_zero_));
4163 case FFEINTRIN_impDPROD:
4165 ffecom_2 (MULT_EXPR, tree_type,
4166 convert (tree_type, ffecom_expr (arg1)),
4167 convert (tree_type, ffecom_expr (arg2)));
4169 case FFEINTRIN_impEXP:
4170 case FFEINTRIN_impCDEXP:
4171 case FFEINTRIN_impCEXP:
4172 case FFEINTRIN_impDEXP:
4173 if (bt == FFEINFO_basictypeCOMPLEX)
4175 if (kt == FFEINFO_kindtypeREAL1)
4176 gfrt = FFECOM_gfrtCEXP; /* Overlapping result okay. */
4177 else if (kt == FFEINFO_kindtypeREAL2)
4178 gfrt = FFECOM_gfrtCDEXP; /* Overlapping result okay. */
4182 case FFEINTRIN_impICHAR:
4183 case FFEINTRIN_impIACHAR:
4184 #if 0 /* The simple approach. */
4185 ffecom_char_args_ (&expr_tree, &saved_expr1 /* Ignored */ , arg1);
4187 = ffecom_1 (INDIRECT_REF,
4188 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4191 = ffecom_2 (ARRAY_REF,
4192 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4195 return convert (tree_type, expr_tree);
4196 #else /* The more interesting (and more optimal) approach. */
4197 expr_tree = ffecom_intrinsic_ichar_ (tree_type, arg1, &saved_expr1);
4198 expr_tree = ffecom_3 (COND_EXPR, tree_type,
4201 convert (tree_type, integer_zero_node));
4205 case FFEINTRIN_impINDEX:
4208 case FFEINTRIN_impLEN:
4210 break; /* The simple approach. */
4212 return ffecom_intrinsic_len_ (arg1); /* The more optimal approach. */
4215 case FFEINTRIN_impLGE:
4216 case FFEINTRIN_impLGT:
4217 case FFEINTRIN_impLLE:
4218 case FFEINTRIN_impLLT:
4221 case FFEINTRIN_impLOG:
4222 case FFEINTRIN_impALOG:
4223 case FFEINTRIN_impCDLOG:
4224 case FFEINTRIN_impCLOG:
4225 case FFEINTRIN_impDLOG:
4226 if (bt == FFEINFO_basictypeCOMPLEX)
4228 if (kt == FFEINFO_kindtypeREAL1)
4229 gfrt = FFECOM_gfrtCLOG; /* Overlapping result okay. */
4230 else if (kt == FFEINFO_kindtypeREAL2)
4231 gfrt = FFECOM_gfrtCDLOG; /* Overlapping result okay. */
4235 case FFEINTRIN_impLOG10:
4236 case FFEINTRIN_impALOG10:
4237 case FFEINTRIN_impDLOG10:
4238 if (gfrt != FFECOM_gfrt)
4239 break; /* Already picked one, stick with it. */
4241 if (kt == FFEINFO_kindtypeREAL1)
4242 /* We used to call FFECOM_gfrtALOG10 here. */
4243 gfrt = FFECOM_gfrtL_LOG10;
4244 else if (kt == FFEINFO_kindtypeREAL2)
4245 /* We used to call FFECOM_gfrtDLOG10 here. */
4246 gfrt = FFECOM_gfrtL_LOG10;
4249 case FFEINTRIN_impMAX:
4250 case FFEINTRIN_impAMAX0:
4251 case FFEINTRIN_impAMAX1:
4252 case FFEINTRIN_impDMAX1:
4253 case FFEINTRIN_impMAX0:
4254 case FFEINTRIN_impMAX1:
4255 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4256 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4258 arg1_type = tree_type;
4259 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4260 convert (arg1_type, ffecom_expr (arg1)),
4261 convert (arg1_type, ffecom_expr (arg2)));
4262 for (; list != NULL; list = ffebld_trail (list))
4264 if ((ffebld_head (list) == NULL)
4265 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4267 expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4270 ffecom_expr (ffebld_head (list))));
4272 return convert (tree_type, expr_tree);
4274 case FFEINTRIN_impMIN:
4275 case FFEINTRIN_impAMIN0:
4276 case FFEINTRIN_impAMIN1:
4277 case FFEINTRIN_impDMIN1:
4278 case FFEINTRIN_impMIN0:
4279 case FFEINTRIN_impMIN1:
4280 if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4281 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4283 arg1_type = tree_type;
4284 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4285 convert (arg1_type, ffecom_expr (arg1)),
4286 convert (arg1_type, ffecom_expr (arg2)));
4287 for (; list != NULL; list = ffebld_trail (list))
4289 if ((ffebld_head (list) == NULL)
4290 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4292 expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4295 ffecom_expr (ffebld_head (list))));
4297 return convert (tree_type, expr_tree);
4299 case FFEINTRIN_impMOD:
4300 case FFEINTRIN_impAMOD:
4301 case FFEINTRIN_impDMOD:
4302 if (bt != FFEINFO_basictypeREAL)
4303 return ffecom_2 (TRUNC_MOD_EXPR, tree_type,
4304 convert (tree_type, ffecom_expr (arg1)),
4305 convert (tree_type, ffecom_expr (arg2)));
4307 if (kt == FFEINFO_kindtypeREAL1)
4308 /* We used to call FFECOM_gfrtAMOD here. */
4309 gfrt = FFECOM_gfrtL_FMOD;
4310 else if (kt == FFEINFO_kindtypeREAL2)
4311 /* We used to call FFECOM_gfrtDMOD here. */
4312 gfrt = FFECOM_gfrtL_FMOD;
4315 case FFEINTRIN_impNINT:
4316 case FFEINTRIN_impIDNINT:
4318 /* ~~Ideally FIX_ROUND_EXPR would be implemented, but it ain't yet. */
4319 return ffecom_1 (FIX_ROUND_EXPR, tree_type, ffecom_expr (arg1));
4321 /* i__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1); */
4322 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4324 convert (ffecom_integer_type_node,
4325 ffecom_3 (COND_EXPR, arg1_type,
4327 (ffecom_2 (GE_EXPR, integer_type_node,
4330 ffecom_float_zero_))),
4331 ffecom_2 (PLUS_EXPR, arg1_type,
4334 ffecom_float_half_)),
4335 ffecom_2 (MINUS_EXPR, arg1_type,
4338 ffecom_float_half_))));
4341 case FFEINTRIN_impSIGN:
4342 case FFEINTRIN_impDSIGN:
4343 case FFEINTRIN_impISIGN:
4345 tree arg2_tree = ffecom_expr (arg2);
4349 (ffecom_1 (ABS_EXPR, tree_type,
4351 ffecom_expr (arg1))));
4353 = ffecom_3 (COND_EXPR, tree_type,
4355 (ffecom_2 (GE_EXPR, integer_type_node,
4357 convert (TREE_TYPE (arg2_tree),
4358 integer_zero_node))),
4360 ffecom_1 (NEGATE_EXPR, tree_type, saved_expr1));
4361 /* Make sure SAVE_EXPRs get referenced early enough. */
4363 = ffecom_2 (COMPOUND_EXPR, tree_type,
4364 convert (void_type_node, saved_expr1),
4369 case FFEINTRIN_impSIN:
4370 case FFEINTRIN_impCDSIN:
4371 case FFEINTRIN_impCSIN:
4372 case FFEINTRIN_impDSIN:
4373 if (bt == FFEINFO_basictypeCOMPLEX)
4375 if (kt == FFEINFO_kindtypeREAL1)
4376 gfrt = FFECOM_gfrtCSIN; /* Overlapping result okay. */
4377 else if (kt == FFEINFO_kindtypeREAL2)
4378 gfrt = FFECOM_gfrtCDSIN; /* Overlapping result okay. */
4382 case FFEINTRIN_impSINH:
4383 case FFEINTRIN_impDSINH:
4386 case FFEINTRIN_impSQRT:
4387 case FFEINTRIN_impCDSQRT:
4388 case FFEINTRIN_impCSQRT:
4389 case FFEINTRIN_impDSQRT:
4390 if (bt == FFEINFO_basictypeCOMPLEX)
4392 if (kt == FFEINFO_kindtypeREAL1)
4393 gfrt = FFECOM_gfrtCSQRT; /* Overlapping result okay. */
4394 else if (kt == FFEINFO_kindtypeREAL2)
4395 gfrt = FFECOM_gfrtCDSQRT; /* Overlapping result okay. */
4399 case FFEINTRIN_impTAN:
4400 case FFEINTRIN_impDTAN:
4401 case FFEINTRIN_impTANH:
4402 case FFEINTRIN_impDTANH:
4405 case FFEINTRIN_impREALPART:
4406 if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4407 arg1_type = TREE_TYPE (arg1_type);
4409 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4413 ffecom_1 (REALPART_EXPR, arg1_type,
4414 ffecom_expr (arg1)));
4416 case FFEINTRIN_impIAND:
4417 case FFEINTRIN_impAND:
4418 return ffecom_2 (BIT_AND_EXPR, tree_type,
4420 ffecom_expr (arg1)),
4422 ffecom_expr (arg2)));
4424 case FFEINTRIN_impIOR:
4425 case FFEINTRIN_impOR:
4426 return ffecom_2 (BIT_IOR_EXPR, tree_type,
4428 ffecom_expr (arg1)),
4430 ffecom_expr (arg2)));
4432 case FFEINTRIN_impIEOR:
4433 case FFEINTRIN_impXOR:
4434 return ffecom_2 (BIT_XOR_EXPR, tree_type,
4436 ffecom_expr (arg1)),
4438 ffecom_expr (arg2)));
4440 case FFEINTRIN_impLSHIFT:
4441 return ffecom_2 (LSHIFT_EXPR, tree_type,
4443 convert (integer_type_node,
4444 ffecom_expr (arg2)));
4446 case FFEINTRIN_impRSHIFT:
4447 return ffecom_2 (RSHIFT_EXPR, tree_type,
4449 convert (integer_type_node,
4450 ffecom_expr (arg2)));
4452 case FFEINTRIN_impNOT:
4453 return ffecom_1 (BIT_NOT_EXPR, tree_type, ffecom_expr (arg1));
4455 case FFEINTRIN_impBIT_SIZE:
4456 return convert (tree_type, TYPE_SIZE (arg1_type));
4458 case FFEINTRIN_impBTEST:
4460 ffetargetLogical1 target_true;
4461 ffetargetLogical1 target_false;
4465 ffetarget_logical1 (&target_true, TRUE);
4466 ffetarget_logical1 (&target_false, FALSE);
4467 if (target_true == 1)
4468 true_tree = convert (tree_type, integer_one_node);
4470 true_tree = convert (tree_type, build_int_2 (target_true, 0));
4471 if (target_false == 0)
4472 false_tree = convert (tree_type, integer_zero_node);
4474 false_tree = convert (tree_type, build_int_2 (target_false, 0));
4477 ffecom_3 (COND_EXPR, tree_type,
4479 (ffecom_2 (EQ_EXPR, integer_type_node,
4480 ffecom_2 (BIT_AND_EXPR, arg1_type,
4482 ffecom_2 (LSHIFT_EXPR, arg1_type,
4485 convert (integer_type_node,
4486 ffecom_expr (arg2)))),
4488 integer_zero_node))),
4493 case FFEINTRIN_impIBCLR:
4495 ffecom_2 (BIT_AND_EXPR, tree_type,
4497 ffecom_1 (BIT_NOT_EXPR, tree_type,
4498 ffecom_2 (LSHIFT_EXPR, tree_type,
4501 convert (integer_type_node,
4502 ffecom_expr (arg2)))));
4504 case FFEINTRIN_impIBITS:
4506 tree arg3_tree = ffecom_save_tree (convert (integer_type_node,
4507 ffecom_expr (arg3)));
4509 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4512 = ffecom_2 (BIT_AND_EXPR, tree_type,
4513 ffecom_2 (RSHIFT_EXPR, tree_type,
4515 convert (integer_type_node,
4516 ffecom_expr (arg2))),
4518 ffecom_2 (RSHIFT_EXPR, uns_type,
4519 ffecom_1 (BIT_NOT_EXPR,
4522 integer_zero_node)),
4523 ffecom_2 (MINUS_EXPR,
4525 TYPE_SIZE (uns_type),
4527 /* Fix up, because the RSHIFT_EXPR above can't shift over TYPE_SIZE. */
4529 = ffecom_3 (COND_EXPR, tree_type,
4531 (ffecom_2 (NE_EXPR, integer_type_node,
4533 integer_zero_node)),
4535 convert (tree_type, integer_zero_node));
4539 case FFEINTRIN_impIBSET:
4541 ffecom_2 (BIT_IOR_EXPR, tree_type,
4543 ffecom_2 (LSHIFT_EXPR, tree_type,
4544 convert (tree_type, integer_one_node),
4545 convert (integer_type_node,
4546 ffecom_expr (arg2))));
4548 case FFEINTRIN_impISHFT:
4550 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4551 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4552 ffecom_expr (arg2)));
4554 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4557 = ffecom_3 (COND_EXPR, tree_type,
4559 (ffecom_2 (GE_EXPR, integer_type_node,
4561 integer_zero_node)),
4562 ffecom_2 (LSHIFT_EXPR, tree_type,
4566 ffecom_2 (RSHIFT_EXPR, uns_type,
4567 convert (uns_type, arg1_tree),
4568 ffecom_1 (NEGATE_EXPR,
4571 /* Fix up, because {L|R}SHIFT_EXPR don't go over TYPE_SIZE bounds. */
4573 = ffecom_3 (COND_EXPR, tree_type,
4575 (ffecom_2 (NE_EXPR, integer_type_node,
4579 TYPE_SIZE (uns_type))),
4581 convert (tree_type, integer_zero_node));
4582 /* Make sure SAVE_EXPRs get referenced early enough. */
4584 = ffecom_2 (COMPOUND_EXPR, tree_type,
4585 convert (void_type_node, arg1_tree),
4586 ffecom_2 (COMPOUND_EXPR, tree_type,
4587 convert (void_type_node, arg2_tree),
4592 case FFEINTRIN_impISHFTC:
4594 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4595 tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4596 ffecom_expr (arg2)));
4597 tree arg3_tree = (arg3 == NULL) ? TYPE_SIZE (tree_type)
4598 : ffecom_save_tree (convert (integer_type_node, ffecom_expr (arg3)));
4604 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4607 = ffecom_2 (LSHIFT_EXPR, tree_type,
4608 ffecom_1 (BIT_NOT_EXPR, tree_type,
4609 convert (tree_type, integer_zero_node)),
4611 /* Fix up, because LSHIFT_EXPR above can't shift over TYPE_SIZE. */
4613 = ffecom_3 (COND_EXPR, tree_type,
4615 (ffecom_2 (NE_EXPR, integer_type_node,
4617 TYPE_SIZE (uns_type))),
4619 convert (tree_type, integer_zero_node));
4620 mask_arg1 = ffecom_save_tree (mask_arg1);
4622 = ffecom_2 (BIT_AND_EXPR, tree_type,
4624 ffecom_1 (BIT_NOT_EXPR, tree_type,
4626 masked_arg1 = ffecom_save_tree (masked_arg1);
4628 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4630 ffecom_2 (RSHIFT_EXPR, uns_type,
4631 convert (uns_type, masked_arg1),
4632 ffecom_1 (NEGATE_EXPR,
4635 ffecom_2 (LSHIFT_EXPR, tree_type,
4637 ffecom_2 (PLUS_EXPR, integer_type_node,
4641 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4642 ffecom_2 (LSHIFT_EXPR, tree_type,
4646 ffecom_2 (RSHIFT_EXPR, uns_type,
4647 convert (uns_type, masked_arg1),
4648 ffecom_2 (MINUS_EXPR,
4653 = ffecom_3 (COND_EXPR, tree_type,
4655 (ffecom_2 (LT_EXPR, integer_type_node,
4657 integer_zero_node)),
4661 = ffecom_2 (BIT_IOR_EXPR, tree_type,
4662 ffecom_2 (BIT_AND_EXPR, tree_type,
4665 ffecom_2 (BIT_AND_EXPR, tree_type,
4666 ffecom_1 (BIT_NOT_EXPR, tree_type,
4670 = ffecom_3 (COND_EXPR, tree_type,
4672 (ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
4673 ffecom_2 (EQ_EXPR, integer_type_node,
4678 ffecom_2 (EQ_EXPR, integer_type_node,
4680 integer_zero_node))),
4683 /* Make sure SAVE_EXPRs get referenced early enough. */
4685 = ffecom_2 (COMPOUND_EXPR, tree_type,
4686 convert (void_type_node, arg1_tree),
4687 ffecom_2 (COMPOUND_EXPR, tree_type,
4688 convert (void_type_node, arg2_tree),
4689 ffecom_2 (COMPOUND_EXPR, tree_type,
4690 convert (void_type_node,
4692 ffecom_2 (COMPOUND_EXPR, tree_type,
4693 convert (void_type_node,
4697 = ffecom_2 (COMPOUND_EXPR, tree_type,
4698 convert (void_type_node,
4704 case FFEINTRIN_impLOC:
4706 tree arg1_tree = ffecom_expr (arg1);
4709 = convert (tree_type,
4710 ffecom_1 (ADDR_EXPR,
4711 build_pointer_type (TREE_TYPE (arg1_tree)),
4716 case FFEINTRIN_impMVBITS:
4721 ffebld arg4 = ffebld_head (ffebld_trail (list));
4724 ffebld arg5 = ffebld_head (ffebld_trail (ffebld_trail (list)));
4728 tree arg5_plus_arg3;
4730 arg2_tree = convert (integer_type_node,
4731 ffecom_expr (arg2));
4732 arg3_tree = ffecom_save_tree (convert (integer_type_node,
4733 ffecom_expr (arg3)));
4734 arg4_tree = ffecom_expr_rw (NULL_TREE, arg4);
4735 arg4_type = TREE_TYPE (arg4_tree);
4737 arg1_tree = ffecom_save_tree (convert (arg4_type,
4738 ffecom_expr (arg1)));
4740 arg5_tree = ffecom_save_tree (convert (integer_type_node,
4741 ffecom_expr (arg5)));
4744 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4745 ffecom_2 (BIT_AND_EXPR, arg4_type,
4746 ffecom_2 (RSHIFT_EXPR, arg4_type,
4749 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4750 ffecom_2 (LSHIFT_EXPR, arg4_type,
4751 ffecom_1 (BIT_NOT_EXPR,
4755 integer_zero_node)),
4759 = ffecom_save_tree (ffecom_2 (PLUS_EXPR, arg4_type,
4763 = ffecom_2 (LSHIFT_EXPR, arg4_type,
4764 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4766 integer_zero_node)),
4768 /* Fix up, because LSHIFT_EXPR above can't shift over TYPE_SIZE. */
4770 = ffecom_3 (COND_EXPR, arg4_type,
4772 (ffecom_2 (NE_EXPR, integer_type_node,
4774 convert (TREE_TYPE (arg5_plus_arg3),
4775 TYPE_SIZE (arg4_type)))),
4777 convert (arg4_type, integer_zero_node));
4779 = ffecom_2 (BIT_AND_EXPR, arg4_type,
4781 ffecom_2 (BIT_IOR_EXPR, arg4_type,
4783 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4784 ffecom_2 (LSHIFT_EXPR, arg4_type,
4785 ffecom_1 (BIT_NOT_EXPR,
4789 integer_zero_node)),
4792 = ffecom_2 (BIT_IOR_EXPR, arg4_type,
4795 /* Fix up (twice), because LSHIFT_EXPR above
4796 can't shift over TYPE_SIZE. */
4798 = ffecom_3 (COND_EXPR, arg4_type,
4800 (ffecom_2 (NE_EXPR, integer_type_node,
4802 convert (TREE_TYPE (arg3_tree),
4803 integer_zero_node))),
4807 = ffecom_3 (COND_EXPR, arg4_type,
4809 (ffecom_2 (NE_EXPR, integer_type_node,
4811 convert (TREE_TYPE (arg3_tree),
4812 TYPE_SIZE (arg4_type)))),
4816 = ffecom_2s (MODIFY_EXPR, void_type_node,
4819 /* Make sure SAVE_EXPRs get referenced early enough. */
4821 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4823 ffecom_2 (COMPOUND_EXPR, void_type_node,
4825 ffecom_2 (COMPOUND_EXPR, void_type_node,
4827 ffecom_2 (COMPOUND_EXPR, void_type_node,
4831 = ffecom_2 (COMPOUND_EXPR, void_type_node,
4838 case FFEINTRIN_impDERF:
4839 case FFEINTRIN_impERF:
4840 case FFEINTRIN_impDERFC:
4841 case FFEINTRIN_impERFC:
4844 case FFEINTRIN_impIARGC:
4845 /* extern int xargc; i__1 = xargc - 1; */
4846 expr_tree = ffecom_2 (MINUS_EXPR, TREE_TYPE (ffecom_tree_xargc_),
4848 convert (TREE_TYPE (ffecom_tree_xargc_),
4852 case FFEINTRIN_impSIGNAL_func:
4853 case FFEINTRIN_impSIGNAL_subr:
4859 arg1_tree = convert (ffecom_f2c_integer_type_node,
4860 ffecom_expr (arg1));
4861 arg1_tree = ffecom_1 (ADDR_EXPR,
4862 build_pointer_type (TREE_TYPE (arg1_tree)),
4865 /* Pass procedure as a pointer to it, anything else by value. */
4866 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4867 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4869 arg2_tree = ffecom_ptr_to_expr (arg2);
4870 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4874 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
4876 arg3_tree = NULL_TREE;
4878 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4879 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4880 TREE_CHAIN (arg1_tree) = arg2_tree;
4883 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4884 ffecom_gfrt_kindtype (gfrt),
4886 ((codegen_imp == FFEINTRIN_impSIGNAL_subr) ?
4890 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4891 ffebld_nonter_hook (expr));
4893 if (arg3_tree != NULL_TREE)
4895 = ffecom_modify (NULL_TREE, arg3_tree,
4896 convert (TREE_TYPE (arg3_tree),
4901 case FFEINTRIN_impALARM:
4907 arg1_tree = convert (ffecom_f2c_integer_type_node,
4908 ffecom_expr (arg1));
4909 arg1_tree = ffecom_1 (ADDR_EXPR,
4910 build_pointer_type (TREE_TYPE (arg1_tree)),
4913 /* Pass procedure as a pointer to it, anything else by value. */
4914 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4915 arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4917 arg2_tree = ffecom_ptr_to_expr (arg2);
4918 arg2_tree = convert (TREE_TYPE (null_pointer_node),
4922 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
4924 arg3_tree = NULL_TREE;
4926 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4927 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4928 TREE_CHAIN (arg1_tree) = arg2_tree;
4931 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4932 ffecom_gfrt_kindtype (gfrt),
4936 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4937 ffebld_nonter_hook (expr));
4939 if (arg3_tree != NULL_TREE)
4941 = ffecom_modify (NULL_TREE, arg3_tree,
4942 convert (TREE_TYPE (arg3_tree),
4947 case FFEINTRIN_impCHDIR_subr:
4948 case FFEINTRIN_impFDATE_subr:
4949 case FFEINTRIN_impFGET_subr:
4950 case FFEINTRIN_impFPUT_subr:
4951 case FFEINTRIN_impGETCWD_subr:
4952 case FFEINTRIN_impHOSTNM_subr:
4953 case FFEINTRIN_impSYSTEM_subr:
4954 case FFEINTRIN_impUNLINK_subr:
4956 tree arg1_len = integer_zero_node;
4960 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
4963 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
4965 arg2_tree = NULL_TREE;
4967 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4968 arg1_len = build_tree_list (NULL_TREE, arg1_len);
4969 TREE_CHAIN (arg1_tree) = arg1_len;
4972 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4973 ffecom_gfrt_kindtype (gfrt),
4977 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4978 ffebld_nonter_hook (expr));
4980 if (arg2_tree != NULL_TREE)
4982 = ffecom_modify (NULL_TREE, arg2_tree,
4983 convert (TREE_TYPE (arg2_tree),
4988 case FFEINTRIN_impEXIT:
4992 expr_tree = build_tree_list (NULL_TREE,
4993 ffecom_1 (ADDR_EXPR,
4995 (ffecom_integer_type_node),
4996 integer_zero_node));
4999 ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5000 ffecom_gfrt_kindtype (gfrt),
5004 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5005 ffebld_nonter_hook (expr));
5007 case FFEINTRIN_impFLUSH:
5009 gfrt = FFECOM_gfrtFLUSH;
5011 gfrt = FFECOM_gfrtFLUSH1;
5014 case FFEINTRIN_impCHMOD_subr:
5015 case FFEINTRIN_impLINK_subr:
5016 case FFEINTRIN_impRENAME_subr:
5017 case FFEINTRIN_impSYMLNK_subr:
5019 tree arg1_len = integer_zero_node;
5021 tree arg2_len = integer_zero_node;
5025 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5026 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
5028 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5030 arg3_tree = NULL_TREE;
5032 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5033 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5034 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5035 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5036 TREE_CHAIN (arg1_tree) = arg2_tree;
5037 TREE_CHAIN (arg2_tree) = arg1_len;
5038 TREE_CHAIN (arg1_len) = arg2_len;
5039 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5040 ffecom_gfrt_kindtype (gfrt),
5044 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5045 ffebld_nonter_hook (expr));
5046 if (arg3_tree != NULL_TREE)
5047 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5048 convert (TREE_TYPE (arg3_tree),
5053 case FFEINTRIN_impLSTAT_subr:
5054 case FFEINTRIN_impSTAT_subr:
5056 tree arg1_len = integer_zero_node;
5061 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5063 arg2_tree = ffecom_ptr_to_expr (arg2);
5066 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5068 arg3_tree = NULL_TREE;
5070 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5071 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5072 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5073 TREE_CHAIN (arg1_tree) = arg2_tree;
5074 TREE_CHAIN (arg2_tree) = arg1_len;
5075 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5076 ffecom_gfrt_kindtype (gfrt),
5080 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5081 ffebld_nonter_hook (expr));
5082 if (arg3_tree != NULL_TREE)
5083 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5084 convert (TREE_TYPE (arg3_tree),
5089 case FFEINTRIN_impFGETC_subr:
5090 case FFEINTRIN_impFPUTC_subr:
5094 tree arg2_len = integer_zero_node;
5097 arg1_tree = convert (ffecom_f2c_integer_type_node,
5098 ffecom_expr (arg1));
5099 arg1_tree = ffecom_1 (ADDR_EXPR,
5100 build_pointer_type (TREE_TYPE (arg1_tree)),
5103 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
5105 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5107 arg3_tree = NULL_TREE;
5109 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5110 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5111 arg2_len = build_tree_list (NULL_TREE, arg2_len);
5112 TREE_CHAIN (arg1_tree) = arg2_tree;
5113 TREE_CHAIN (arg2_tree) = arg2_len;
5115 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5116 ffecom_gfrt_kindtype (gfrt),
5120 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5121 ffebld_nonter_hook (expr));
5122 if (arg3_tree != NULL_TREE)
5123 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5124 convert (TREE_TYPE (arg3_tree),
5129 case FFEINTRIN_impFSTAT_subr:
5135 arg1_tree = convert (ffecom_f2c_integer_type_node,
5136 ffecom_expr (arg1));
5137 arg1_tree = ffecom_1 (ADDR_EXPR,
5138 build_pointer_type (TREE_TYPE (arg1_tree)),
5141 arg2_tree = convert (ffecom_f2c_ptr_to_integer_type_node,
5142 ffecom_ptr_to_expr (arg2));
5145 arg3_tree = NULL_TREE;
5147 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5149 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5150 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5151 TREE_CHAIN (arg1_tree) = arg2_tree;
5152 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5153 ffecom_gfrt_kindtype (gfrt),
5157 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5158 ffebld_nonter_hook (expr));
5159 if (arg3_tree != NULL_TREE) {
5160 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5161 convert (TREE_TYPE (arg3_tree),
5167 case FFEINTRIN_impKILL_subr:
5173 arg1_tree = convert (ffecom_f2c_integer_type_node,
5174 ffecom_expr (arg1));
5175 arg1_tree = ffecom_1 (ADDR_EXPR,
5176 build_pointer_type (TREE_TYPE (arg1_tree)),
5179 arg2_tree = convert (ffecom_f2c_integer_type_node,
5180 ffecom_expr (arg2));
5181 arg2_tree = ffecom_1 (ADDR_EXPR,
5182 build_pointer_type (TREE_TYPE (arg2_tree)),
5186 arg3_tree = NULL_TREE;
5188 arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5190 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5191 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5192 TREE_CHAIN (arg1_tree) = arg2_tree;
5193 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5194 ffecom_gfrt_kindtype (gfrt),
5198 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5199 ffebld_nonter_hook (expr));
5200 if (arg3_tree != NULL_TREE) {
5201 expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5202 convert (TREE_TYPE (arg3_tree),
5208 case FFEINTRIN_impCTIME_subr:
5209 case FFEINTRIN_impTTYNAM_subr:
5211 tree arg1_len = integer_zero_node;
5215 arg1_tree = ffecom_arg_ptr_to_expr (arg2, &arg1_len);
5217 arg2_tree = convert (((codegen_imp == FFEINTRIN_impCTIME_subr) ?
5218 ffecom_f2c_longint_type_node :
5219 ffecom_f2c_integer_type_node),
5220 ffecom_expr (arg1));
5221 arg2_tree = ffecom_1 (ADDR_EXPR,
5222 build_pointer_type (TREE_TYPE (arg2_tree)),
5225 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5226 arg1_len = build_tree_list (NULL_TREE, arg1_len);
5227 arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5228 TREE_CHAIN (arg1_len) = arg2_tree;
5229 TREE_CHAIN (arg1_tree) = arg1_len;
5232 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5233 ffecom_gfrt_kindtype (gfrt),
5237 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5238 ffebld_nonter_hook (expr));
5239 TREE_SIDE_EFFECTS (expr_tree) = 1;
5243 case FFEINTRIN_impIRAND:
5244 case FFEINTRIN_impRAND:
5245 /* Arg defaults to 0 (normal random case) */
5250 arg1_tree = ffecom_integer_zero_node;
5252 arg1_tree = ffecom_expr (arg1);
5253 arg1_tree = convert (ffecom_f2c_integer_type_node,
5255 arg1_tree = ffecom_1 (ADDR_EXPR,
5256 build_pointer_type (TREE_TYPE (arg1_tree)),
5258 arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5260 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5261 ffecom_gfrt_kindtype (gfrt),
5263 ((codegen_imp == FFEINTRIN_impIRAND) ?
5264 ffecom_f2c_integer_type_node :
5265 ffecom_f2c_real_type_node),
5267 dest_tree, dest, dest_used,
5269 ffebld_nonter_hook (expr));
5273 case FFEINTRIN_impFTELL_subr:
5274 case FFEINTRIN_impUMASK_subr:
5279 arg1_tree = convert (ffecom_f2c_integer_type_node,
5280 ffecom_expr (arg1));
5281 arg1_tree = ffecom_1 (ADDR_EXPR,
5282 build_pointer_type (TREE_TYPE (arg1_tree)),
5286 arg2_tree = NULL_TREE;
5288 arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
5290 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5291 ffecom_gfrt_kindtype (gfrt),
5294 build_tree_list (NULL_TREE, arg1_tree),
5295 NULL_TREE, NULL, NULL, NULL_TREE,
5297 ffebld_nonter_hook (expr));
5298 if (arg2_tree != NULL_TREE) {
5299 expr_tree = ffecom_modify (NULL_TREE, arg2_tree,
5300 convert (TREE_TYPE (arg2_tree),
5306 case FFEINTRIN_impCPU_TIME:
5307 case FFEINTRIN_impSECOND_subr:
5311 arg1_tree = ffecom_expr_w (NULL_TREE, arg1);
5314 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5315 ffecom_gfrt_kindtype (gfrt),
5319 NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5320 ffebld_nonter_hook (expr));
5323 = ffecom_modify (NULL_TREE, arg1_tree,
5324 convert (TREE_TYPE (arg1_tree),
5329 case FFEINTRIN_impDTIME_subr:
5330 case FFEINTRIN_impETIME_subr:
5335 result_tree = ffecom_expr_w (NULL_TREE, arg2);
5337 arg1_tree = ffecom_ptr_to_expr (arg1);
5339 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5340 ffecom_gfrt_kindtype (gfrt),
5343 build_tree_list (NULL_TREE, arg1_tree),
5344 NULL_TREE, NULL, NULL, NULL_TREE,
5346 ffebld_nonter_hook (expr));
5347 expr_tree = ffecom_modify (NULL_TREE, result_tree,
5348 convert (TREE_TYPE (result_tree),
5353 /* Straightforward calls of libf2c routines: */
5354 case FFEINTRIN_impABORT:
5355 case FFEINTRIN_impACCESS:
5356 case FFEINTRIN_impBESJ0:
5357 case FFEINTRIN_impBESJ1:
5358 case FFEINTRIN_impBESJN:
5359 case FFEINTRIN_impBESY0:
5360 case FFEINTRIN_impBESY1:
5361 case FFEINTRIN_impBESYN:
5362 case FFEINTRIN_impCHDIR_func:
5363 case FFEINTRIN_impCHMOD_func:
5364 case FFEINTRIN_impDATE:
5365 case FFEINTRIN_impDATE_AND_TIME:
5366 case FFEINTRIN_impDBESJ0:
5367 case FFEINTRIN_impDBESJ1:
5368 case FFEINTRIN_impDBESJN:
5369 case FFEINTRIN_impDBESY0:
5370 case FFEINTRIN_impDBESY1:
5371 case FFEINTRIN_impDBESYN:
5372 case FFEINTRIN_impDTIME_func:
5373 case FFEINTRIN_impETIME_func:
5374 case FFEINTRIN_impFGETC_func:
5375 case FFEINTRIN_impFGET_func:
5376 case FFEINTRIN_impFNUM:
5377 case FFEINTRIN_impFPUTC_func:
5378 case FFEINTRIN_impFPUT_func:
5379 case FFEINTRIN_impFSEEK:
5380 case FFEINTRIN_impFSTAT_func:
5381 case FFEINTRIN_impFTELL_func:
5382 case FFEINTRIN_impGERROR:
5383 case FFEINTRIN_impGETARG:
5384 case FFEINTRIN_impGETCWD_func:
5385 case FFEINTRIN_impGETENV:
5386 case FFEINTRIN_impGETGID:
5387 case FFEINTRIN_impGETLOG:
5388 case FFEINTRIN_impGETPID:
5389 case FFEINTRIN_impGETUID:
5390 case FFEINTRIN_impGMTIME:
5391 case FFEINTRIN_impHOSTNM_func:
5392 case FFEINTRIN_impIDATE_unix:
5393 case FFEINTRIN_impIDATE_vxt:
5394 case FFEINTRIN_impIERRNO:
5395 case FFEINTRIN_impISATTY:
5396 case FFEINTRIN_impITIME:
5397 case FFEINTRIN_impKILL_func:
5398 case FFEINTRIN_impLINK_func:
5399 case FFEINTRIN_impLNBLNK:
5400 case FFEINTRIN_impLSTAT_func:
5401 case FFEINTRIN_impLTIME:
5402 case FFEINTRIN_impMCLOCK8:
5403 case FFEINTRIN_impMCLOCK:
5404 case FFEINTRIN_impPERROR:
5405 case FFEINTRIN_impRENAME_func:
5406 case FFEINTRIN_impSECNDS:
5407 case FFEINTRIN_impSECOND_func:
5408 case FFEINTRIN_impSLEEP:
5409 case FFEINTRIN_impSRAND:
5410 case FFEINTRIN_impSTAT_func:
5411 case FFEINTRIN_impSYMLNK_func:
5412 case FFEINTRIN_impSYSTEM_CLOCK:
5413 case FFEINTRIN_impSYSTEM_func:
5414 case FFEINTRIN_impTIME8:
5415 case FFEINTRIN_impTIME_unix:
5416 case FFEINTRIN_impTIME_vxt:
5417 case FFEINTRIN_impUMASK_func:
5418 case FFEINTRIN_impUNLINK_func:
5421 case FFEINTRIN_impCTIME_func: /* CHARACTER functions not handled here. */
5422 case FFEINTRIN_impFDATE_func: /* CHARACTER functions not handled here. */
5423 case FFEINTRIN_impTTYNAM_func: /* CHARACTER functions not handled here. */
5424 case FFEINTRIN_impNONE:
5425 case FFEINTRIN_imp: /* Hush up gcc warning. */
5426 fprintf (stderr, "No %s implementation.\n",
5427 ffeintrin_name_implementation (ffebld_symter_implementation (ffebld_left (expr))));
5428 assert ("unimplemented intrinsic" == NULL);
5429 return error_mark_node;
5432 assert (gfrt != FFECOM_gfrt); /* Must have an implementation! */
5434 expr_tree = ffecom_arglist_expr_ (ffecom_gfrt_args_ (gfrt),
5435 ffebld_right (expr));
5437 return ffecom_call_ (ffecom_gfrt_tree_ (gfrt), ffecom_gfrt_kindtype (gfrt),
5438 (ffe_is_f2c_library () && ffecom_gfrt_complex_[gfrt]),
5440 expr_tree, dest_tree, dest, dest_used,
5442 ffebld_nonter_hook (expr));
5444 /* See bottom of this file for f2c transforms used to determine
5445 many of the above implementations. The info seems to confuse
5446 Emacs's C mode indentation, which is why it's been moved to
5447 the bottom of this source file. */
5451 /* For power (exponentiation) where right-hand operand is type INTEGER,
5452 generate in-line code to do it the fast way (which, if the operand
5453 is a constant, might just mean a series of multiplies). */
5455 #if FFECOM_targetCURRENT == FFECOM_targetGCC
5457 ffecom_expr_power_integer_ (ffebld expr)
5459 tree l = ffecom_expr (ffebld_left (expr));
5460 tree r = ffecom_expr (ffebld_right (expr));
5461 tree ltype = TREE_TYPE (l);
5462 tree rtype = TREE_TYPE (r);
5463 tree result = NULL_TREE;
5465 if (l == error_mark_node
5466 || r == error_mark_node)
5467 return error_mark_node;
5469 if (TREE_CODE (r) == INTEGER_CST)
5471 int sgn = tree_int_cst_sgn (r);
5474 return convert (ltype, integer_one_node);
5476 if ((TREE_CODE (ltype) == INTEGER_TYPE)
5479 /* Reciprocal of integer is either 0, -1, or 1, so after
5480 calculating that (which we leave to the back end to do
5481 or not do optimally), don't bother with any multiplying. */
5483 result = ffecom_tree_divide_ (ltype,
5484 convert (ltype, integer_one_node),
5486 NULL_TREE, NULL, NULL, NULL_TREE);
5487 r = ffecom_1 (NEGATE_EXPR,
5490 if ((TREE_INT_CST_LOW (r) & 1) == 0)
5491 result = ffecom_1 (ABS_EXPR, rtype,
5495 /* Generate appropriate series of multiplies, preceded
5496 by divide if the exponent is negative. */
5502 l = ffecom_tree_divide_ (ltype,
5503 convert (ltype, integer_one_node),
5505 NULL_TREE, NULL, NULL,
5506 ffebld_nonter_hook (expr));
5507 r = ffecom_1 (NEGATE_EXPR, rtype, r);
5508 assert (TREE_CODE (r) == INTEGER_CST);
5510 if (tree_int_cst_sgn (r) < 0)
5511 { /* The "most negative" number. */
5512 r = ffecom_1 (NEGATE_EXPR, rtype,
5513 ffecom_2 (RSHIFT_EXPR, rtype,
5517 l = ffecom_2 (MULT_EXPR, ltype,
5525 if (TREE_INT_CST_LOW (r) & 1)
5527 if (result == NULL_TREE)
5530 result = ffecom_2 (MULT_EXPR, ltype,
5535 r = ffecom_2 (RSHIFT_EXPR, rtype,
5538 if (integer_zerop (r))
5540 assert (TREE_CODE (r) == INTEGER_CST);
5543 l = ffecom_2 (MULT_EXPR, ltype,
5550 /* Though rhs isn't a constant, in-line code cannot be expanded
5551 while transforming dummies
5552 because the back end cannot be easily convinced to generate
5553 stores (MODIFY_EXPR), handle temporaries, and so on before
5554 all the appropriate rtx's have been generated for things like
5555 dummy args referenced in rhs -- which doesn't happen until
5556 store_parm_decls() is called (expand_function_start, I believe,
5557 does the actual rtx-stuffing of PARM_DECLs).
5559 So, in this case, let the caller generate the call to the
5560 run-time-library function to evaluate the power for us. */
5562 if (ffecom_transform_only_dummies_)
5565 /* Right-hand operand not a constant, expand in-line code to figure
5566 out how to do the multiplies, &c.
5568 The returned expression is expressed this way in GNU C, where l and
5571 ({ typeof (r) rtmp = r;
5572 typeof (l) ltmp = l;
5579 if ((basetypeof (l) == basetypeof (int))
5582 result = ((typeof (l)) 1) / ltmp;
5583 if ((ltmp < 0) && (((-rtmp) & 1) == 0))
5589 if ((basetypeof (l) != basetypeof (int))
5592 ltmp = ((typeof (l)) 1) / ltmp;
5596 rtmp = -(rtmp >> 1);
5604 if ((rtmp >>= 1) == 0)
5613 Note that some of the above is compile-time collapsable, such as
5614 the first part of the if statements that checks the base type of
5615 l against int. The if statements are phrased that way to suggest
5616 an easy way to generate the if/else constructs here, knowing that
5617 the back end should (and probably does) eliminate the resulting
5618 dead code (either the int case or the non-int case), something
5619 it couldn't do without the redundant phrasing, requiring explicit
5620 dead-code elimination here, which would be kind of difficult to
5627 tree basetypeof_l_is_int;
5632 = build_int_2 ((TREE_CODE (ltype) == INTEGER_TYPE), 0);
5634 se = expand_start_stmt_expr ();
5636 ffecom_start_compstmt ();
5639 rtmp = ffecom_make_tempvar ("power_r", rtype,
5640 FFETARGET_charactersizeNONE, -1);
5641 ltmp = ffecom_make_tempvar ("power_l", ltype,
5642 FFETARGET_charactersizeNONE, -1);
5643 result = ffecom_make_tempvar ("power_res", ltype,
5644 FFETARGET_charactersizeNONE, -1);
5645 if (TREE_CODE (ltype) == COMPLEX_TYPE
5646 || TREE_CODE (ltype) == RECORD_TYPE)
5647 divide = ffecom_make_tempvar ("power_div", ltype,
5648 FFETARGET_charactersizeNONE, -1);
5655 hook = ffebld_nonter_hook (expr);
5657 assert (TREE_CODE (hook) == TREE_VEC);
5658 assert (TREE_VEC_LENGTH (hook) == 4);
5659 rtmp = TREE_VEC_ELT (hook, 0);
5660 ltmp = TREE_VEC_ELT (hook, 1);
5661 result = TREE_VEC_ELT (hook, 2);
5662 divide = TREE_VEC_ELT (hook, 3);
5663 if (TREE_CODE (ltype) == COMPLEX_TYPE
5664 || TREE_CODE (ltype) == RECORD_TYPE)
5671 expand_expr_stmt (ffecom_modify (void_type_node,
5674 expand_expr_stmt (ffecom_modify (void_type_node,
5677 expand_start_cond (ffecom_truth_value
5678 (ffecom_2 (EQ_EXPR, integer_type_node,
5680 convert (rtype, integer_zero_node))),
5682 expand_expr_stmt (ffecom_modify (void_type_node,
5684 convert (ltype, integer_one_node)));
5685 expand_start_else ();
5686 if (! integer_zerop (basetypeof_l_is_int))
5688 expand_start_cond (ffecom_2 (LT_EXPR, integer_type_node,
5691 integer_zero_node)),
5693 expand_expr_stmt (ffecom_modify (void_type_node,
5697 convert (ltype, integer_one_node),
5699 NULL_TREE, NULL, NULL,
5701 expand_start_cond (ffecom_truth_value
5702 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5703 ffecom_2 (LT_EXPR, integer_type_node,
5706 integer_zero_node)),
5707 ffecom_2 (EQ_EXPR, integer_type_node,
5708 ffecom_2 (BIT_AND_EXPR,
5710 ffecom_1 (NEGATE_EXPR,
5716 integer_zero_node)))),
5718 expand_expr_stmt (ffecom_modify (void_type_node,
5720 ffecom_1 (NEGATE_EXPR,
5724 expand_start_else ();
5726 expand_expr_stmt (ffecom_modify (void_type_node,
5728 convert (ltype, integer_one_node)));
5729 expand_start_cond (ffecom_truth_value
5730 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5731 ffecom_truth_value_invert
5732 (basetypeof_l_is_int),
5733 ffecom_2 (LT_EXPR, integer_type_node,
5736 integer_zero_node)))),
5738 expand_expr_stmt (ffecom_modify (void_type_node,
5742 convert (ltype, integer_one_node),
5744 NULL_TREE, NULL, NULL,
5746 expand_expr_stmt (ffecom_modify (void_type_node,
5748 ffecom_1 (NEGATE_EXPR, rtype,
5750 expand_start_cond (ffecom_truth_value
5751 (ffecom_2 (LT_EXPR, integer_type_node,
5753 convert (rtype, integer_zero_node))),
5755 expand_expr_stmt (ffecom_modify (void_type_node,
5757 ffecom_1 (NEGATE_EXPR, rtype,
5758 ffecom_2 (RSHIFT_EXPR,
5761 integer_one_node))));
5762 expand_expr_stmt (ffecom_modify (void_type_node,
5764 ffecom_2 (MULT_EXPR, ltype,
5769 expand_start_loop (1);
5770 expand_start_cond (ffecom_truth_value
5771 (ffecom_2 (BIT_AND_EXPR, rtype,
5773 convert (rtype, integer_one_node))),
5775 expand_expr_stmt (ffecom_modify (void_type_node,
5777 ffecom_2 (MULT_EXPR, ltype,
5781 expand_exit_loop_if_false (NULL,
5783 (ffecom_modify (rtype,
5785 ffecom_2 (RSHIFT_EXPR,
5788 integer_one_node))));
5789 expand_expr_stmt (ffecom_modify (void_type_node,
5791 ffecom_2 (MULT_EXPR, ltype,
5796 if (!integer_zerop (basetypeof_l_is_int))
5798 expand_expr_stmt (result);
5800 t = ffecom_end_compstmt ();
5802 result = expand_end_stmt_expr (se);
5804 /* This code comes from c-parse.in, after its expand_end_stmt_expr. */
5806 if (TREE_CODE (t) == BLOCK)
5808 /* Make a BIND_EXPR for the BLOCK already made. */
5809 result = build (BIND_EXPR, TREE_TYPE (result),
5810 NULL_TREE, result, t);
5811 /* Remove the block from the tree at this point.
5812 It gets put back at the proper place
5813 when the BIND_EXPR is expanded. */
5824 /* ffecom_expr_transform_ -- Transform symbols in expr
5826 ffebld expr; // FFE expression.
5827 ffecom_expr_transform_ (expr);
5829 Recursive descent on expr while transforming any untransformed SYMTERs. */
5831 #if FFECOM_targetCURRENT == FFECOM_targetGCC
5833 ffecom_expr_transform_ (ffebld expr)
5838 tail_recurse: /* :::::::::::::::::::: */
5843 switch (ffebld_op (expr))
5845 case FFEBLD_opSYMTER:
5846 s = ffebld_symter (expr);
5847 t = ffesymbol_hook (s).decl_tree;
5848 if ((t == NULL_TREE)
5849 && ((ffesymbol_kind (s) != FFEINFO_kindNONE)
5850 || ((ffesymbol_where (s) != FFEINFO_whereNONE)
5851 && (ffesymbol_where (s) != FFEINFO_whereINTRINSIC))))
5853 s = ffecom_sym_transform_ (s);
5854 t = ffesymbol_hook (s).decl_tree; /* Sfunc expr non-dummy,
5857 break; /* Ok if (t == NULL) here. */
5860 ffecom_expr_transform_ (ffebld_head (expr));
5861 expr = ffebld_trail (expr);
5862 goto tail_recurse; /* :::::::::::::::::::: */
5868 switch (ffebld_arity (expr))
5871 ffecom_expr_transform_ (ffebld_left (expr));
5872 expr = ffebld_right (expr);
5873 goto tail_recurse; /* :::::::::::::::::::: */
5876 expr = ffebld_left (expr);
5877 goto tail_recurse; /* :::::::::::::::::::: */
5887 /* Make a type based on info in live f2c.h file. */
5889 #if FFECOM_targetCURRENT == FFECOM_targetGCC
5891 ffecom_f2c_make_type_ (tree *type, int tcode, const char *name)
5895 case FFECOM_f2ccodeCHAR:
5896 *type = make_signed_type (CHAR_TYPE_SIZE);
5899 case FFECOM_f2ccodeSHORT:
5900 *type = make_signed_type (SHORT_TYPE_SIZE);
5903 case FFECOM_f2ccodeINT:
5904 *type = make_signed_type (INT_TYPE_SIZE);
5907 case FFECOM_f2ccodeLONG:
5908 *type = make_signed_type (LONG_TYPE_SIZE);
5911 case FFECOM_f2ccodeLONGLONG:
5912 *type = make_signed_type (LONG_LONG_TYPE_SIZE);
5915 case FFECOM_f2ccodeCHARPTR:
5916 *type = build_pointer_type (DEFAULT_SIGNED_CHAR
5917 ? signed_char_type_node
5918 : unsigned_char_type_node);
5921 case FFECOM_f2ccodeFLOAT:
5922 *type = make_node (REAL_TYPE);
5923 TYPE_PRECISION (*type) = FLOAT_TYPE_SIZE;
5924 layout_type (*type);
5927 case FFECOM_f2ccodeDOUBLE:
5928 *type = make_node (REAL_TYPE);
5929 TYPE_PRECISION (*type) = DOUBLE_TYPE_SIZE;
5930 layout_type (*type);
5933 case FFECOM_f2ccodeLONGDOUBLE:
5934 *type = make_node (REAL_TYPE);
5935 TYPE_PRECISION (*type) = LONG_DOUBLE_TYPE_SIZE;
5936 layout_type (*type);
5939 case FFECOM_f2ccodeTWOREALS:
5940 *type = ffecom_make_complex_type_ (ffecom_f2c_real_type_node);
5943 case FFECOM_f2ccodeTWODOUBLEREALS:
5944 *type = ffecom_make_complex_type_ (ffecom_f2c_doublereal_type_node);
5948 assert ("unexpected FFECOM_f2ccodeXYZZY!" == NULL);
5949 *type = error_mark_node;
5953 pushdecl (build_decl (TYPE_DECL,
5954 ffecom_get_invented_identifier ("__g77_f2c_%s", name),
5959 #if FFECOM_targetCURRENT == FFECOM_targetGCC
5960 /* Set the f2c list-directed-I/O code for whatever (integral) type has the
5964 ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
5970 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
5971 if ((t = ffecom_tree_type[bt][j]) != NULL_TREE
5972 && compare_tree_int (TYPE_SIZE (t), size) == 0)
5974 assert (code != -1);
5975 ffecom_f2c_typecode_[bt][j] = code;
5981 /* Finish up globals after doing all program units in file
5983 Need to handle only uninitialized COMMON areas. */
5985 #if FFECOM_targetCURRENT == FFECOM_targetGCC
5987 ffecom_finish_global_ (ffeglobal global)
5993 if (ffeglobal_type (global) != FFEGLOBAL_typeCOMMON)
5996 if (ffeglobal_common_init (global))
5999 cbt = ffeglobal_hook (global);
6000 if ((cbt == NULL_TREE)
6001 || !ffeglobal_common_have_size (global))
6002 return global; /* No need to make common, never ref'd. */
6004 DECL_EXTERNAL (cbt) = 0;
6006 /* Give the array a size now. */
6008 size = build_int_2 ((ffeglobal_common_size (global)
6009 + ffeglobal_common_pad (global)) - 1,
6012 cbtype = TREE_TYPE (cbt);
6013 TYPE_DOMAIN (cbtype) = build_range_type (integer_type_node,
6016 if (!TREE_TYPE (size))
6017 TREE_TYPE (size) = TYPE_DOMAIN (cbtype);
6018 layout_type (cbtype);
6020 cbt = start_decl (cbt, FALSE);
6021 assert (cbt == ffeglobal_hook (global));
6023 finish_decl (cbt, NULL_TREE, FALSE);
6029 /* Finish up any untransformed symbols. */
6031 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6033 ffecom_finish_symbol_transform_ (ffesymbol s)
6035 if ((s == NULL) || (TREE_CODE (current_function_decl) == ERROR_MARK))
6038 /* It's easy to know to transform an untransformed symbol, to make sure
6039 we put out debugging info for it. But COMMON variables, unlike
6040 EQUIVALENCE ones, aren't given declarations in addition to the
6041 tree expressions that specify offsets, because COMMON variables
6042 can be referenced in the outer scope where only dummy arguments
6043 (PARM_DECLs) should really be seen. To be safe, just don't do any
6044 VAR_DECLs for COMMON variables when we transform them for real
6045 use, and therefore we do all the VAR_DECL creating here. */
6047 if (ffesymbol_hook (s).decl_tree == NULL_TREE)
6049 if (ffesymbol_kind (s) != FFEINFO_kindNONE
6050 || (ffesymbol_where (s) != FFEINFO_whereNONE
6051 && ffesymbol_where (s) != FFEINFO_whereINTRINSIC
6052 && ffesymbol_where (s) != FFEINFO_whereDUMMY))
6053 /* Not transformed, and not CHARACTER*(*), and not a dummy
6054 argument, which can happen only if the entry point names
6055 it "rides in on" are all invalidated for other reasons. */
6056 s = ffecom_sym_transform_ (s);
6059 if ((ffesymbol_where (s) == FFEINFO_whereCOMMON)
6060 && (ffesymbol_hook (s).decl_tree != error_mark_node))
6062 /* This isn't working, at least for dbxout. The .s file looks
6063 okay to me (burley), but in gdb 4.9 at least, the variables
6064 appear to reside somewhere outside of the common area, so
6065 it doesn't make sense to mislead anyone by generating the info
6066 on those variables until this is fixed. NOTE: Same problem
6067 with EQUIVALENCE, sadly...see similar #if later. */
6068 ffecom_member_phase2_ (ffesymbol_storage (ffesymbol_common (s)),
6069 ffesymbol_storage (s));
6076 /* Append underscore(s) to name before calling get_identifier. "us"
6077 is nonzero if the name already contains an underscore and thus
6078 needs two underscores appended. */
6080 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6082 ffecom_get_appended_identifier_ (char us, const char *name)
6088 newname = xmalloc ((i = strlen (name)) + 1
6089 + ffe_is_underscoring ()
6091 memcpy (newname, name, i);
6093 newname[i + us] = '_';
6094 newname[i + 1 + us] = '\0';
6095 id = get_identifier (newname);
6103 /* Decide whether to append underscore to name before calling
6106 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6108 ffecom_get_external_identifier_ (ffesymbol s)
6111 const char *name = ffesymbol_text (s);
6113 /* If name is a built-in name, just return it as is. */
6115 if (!ffe_is_underscoring ()
6116 || (strcmp (name, FFETARGET_nameBLANK_COMMON) == 0)
6117 #if FFETARGET_isENFORCED_MAIN_NAME
6118 || (strcmp (name, FFETARGET_nameENFORCED_NAME) == 0)
6120 || (strcmp (name, FFETARGET_nameUNNAMED_MAIN) == 0)
6122 || (strcmp (name, FFETARGET_nameUNNAMED_BLOCK_DATA) == 0))
6123 return get_identifier (name);
6125 us = ffe_is_second_underscore ()
6126 ? (strchr (name, '_') != NULL)
6129 return ffecom_get_appended_identifier_ (us, name);
6133 /* Decide whether to append underscore to internal name before calling
6136 This is for non-external, top-function-context names only. Transform
6137 identifier so it doesn't conflict with the transformed result
6138 of using a _different_ external name. E.g. if "CALL FOO" is
6139 transformed into "FOO_();", then the variable in "FOO_ = 3"
6140 must be transformed into something that does not conflict, since
6141 these two things should be independent.
6143 The transformation is as follows. If the name does not contain
6144 an underscore, there is no possible conflict, so just return.
6145 If the name does contain an underscore, then transform it just
6146 like we transform an external identifier. */
6148 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6150 ffecom_get_identifier_ (const char *name)
6152 /* If name does not contain an underscore, just return it as is. */
6154 if (!ffe_is_underscoring ()
6155 || (strchr (name, '_') == NULL))
6156 return get_identifier (name);
6158 return ffecom_get_appended_identifier_ (ffe_is_second_underscore (),
6163 /* ffecom_gen_sfuncdef_ -- Generate definition of statement function
6166 ffesymbol s; // kindFUNCTION, whereIMMEDIATE.
6167 t = ffecom_gen_sfuncdef_(s,ffesymbol_basictype(s),
6168 ffesymbol_kindtype(s));
6170 Call after setting up containing function and getting trees for all
6173 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6175 ffecom_gen_sfuncdef_ (ffesymbol s, ffeinfoBasictype bt, ffeinfoKindtype kt)
6177 ffebld expr = ffesymbol_sfexpr (s);
6181 bool charfunc = (bt == FFEINFO_basictypeCHARACTER);
6182 static bool recurse = FALSE;
6183 int old_lineno = lineno;
6184 const char *old_input_filename = input_filename;
6186 ffecom_nested_entry_ = s;
6188 /* For now, we don't have a handy pointer to where the sfunc is actually
6189 defined, though that should be easy to add to an ffesymbol. (The
6190 token/where info available might well point to the place where the type
6191 of the sfunc is declared, especially if that precedes the place where
6192 the sfunc itself is defined, which is typically the case.) We should
6193 put out a null pointer rather than point somewhere wrong, but I want to
6194 see how it works at this point. */
6196 input_filename = ffesymbol_where_filename (s);
6197 lineno = ffesymbol_where_filelinenum (s);
6199 /* Pretransform the expression so any newly discovered things belong to the
6200 outer program unit, not to the statement function. */
6202 ffecom_expr_transform_ (expr);
6204 /* Make sure no recursive invocation of this fn (a specific case of failing
6205 to pretransform an sfunc's expression, i.e. where its expression
6206 references another untransformed sfunc) happens. */
6211 push_f_function_context ();
6214 type = void_type_node;
6217 type = ffecom_tree_type[bt][kt];
6218 if (type == NULL_TREE)
6219 type = integer_type_node; /* _sym_exec_transition reports
6223 start_function (ffecom_get_identifier_ (ffesymbol_text (s)),
6224 build_function_type (type, NULL_TREE),
6225 1, /* nested/inline */
6226 0); /* TREE_PUBLIC */
6228 /* We don't worry about COMPLEX return values here, because this is
6229 entirely internal to our code, and gcc has the ability to return COMPLEX
6230 directly as a value. */
6233 { /* Prepend arg for where result goes. */
6236 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
6238 result = ffecom_get_invented_identifier ("__g77_%s", "result");
6240 ffecom_char_enhance_arg_ (&type, s); /* Ignore returned length. */
6242 type = build_pointer_type (type);
6243 result = build_decl (PARM_DECL, result, type);
6245 push_parm_decl (result);
6248 result = NULL_TREE; /* Not ref'd if !charfunc. */
6250 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (s), TRUE);
6252 store_parm_decls (0);
6254 ffecom_start_compstmt ();
6260 ffetargetCharacterSize sz = ffesymbol_size (s);
6263 result_length = build_int_2 (sz, 0);
6264 TREE_TYPE (result_length) = ffecom_f2c_ftnlen_type_node;
6266 ffecom_prepare_let_char_ (sz, expr);
6268 ffecom_prepare_end ();
6270 ffecom_let_char_ (result, result_length, sz, expr);
6271 expand_null_return ();
6275 ffecom_prepare_expr (expr);
6277 ffecom_prepare_end ();
6279 expand_return (ffecom_modify (NULL_TREE,
6280 DECL_RESULT (current_function_decl),
6281 ffecom_expr (expr)));
6285 ffecom_end_compstmt ();
6287 func = current_function_decl;
6288 finish_function (1);
6290 pop_f_function_context ();
6294 lineno = old_lineno;
6295 input_filename = old_input_filename;
6297 ffecom_nested_entry_ = NULL;
6304 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6306 ffecom_gfrt_args_ (ffecomGfrt ix)
6308 return ffecom_gfrt_argstring_[ix];
6312 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6314 ffecom_gfrt_tree_ (ffecomGfrt ix)
6316 if (ffecom_gfrt_[ix] == NULL_TREE)
6317 ffecom_make_gfrt_ (ix);
6319 return ffecom_1 (ADDR_EXPR,
6320 build_pointer_type (TREE_TYPE (ffecom_gfrt_[ix])),
6325 /* Return initialize-to-zero expression for this VAR_DECL. */
6327 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6328 /* A somewhat evil way to prevent the garbage collector
6329 from collecting 'tree' structures. */
6330 #define NUM_TRACKED_CHUNK 63
6331 static struct tree_ggc_tracker
6333 struct tree_ggc_tracker *next;
6334 tree trees[NUM_TRACKED_CHUNK];
6335 } *tracker_head = NULL;
6338 mark_tracker_head (void *arg)
6340 struct tree_ggc_tracker *head;
6343 for (head = * (struct tree_ggc_tracker **) arg;
6348 for (i = 0; i < NUM_TRACKED_CHUNK; i++)
6349 ggc_mark_tree (head->trees[i]);
6354 ffecom_save_tree_forever (tree t)
6357 if (tracker_head != NULL)
6358 for (i = 0; i < NUM_TRACKED_CHUNK; i++)
6359 if (tracker_head->trees[i] == NULL)
6361 tracker_head->trees[i] = t;
6366 /* Need to allocate a new block. */
6367 struct tree_ggc_tracker *old_head = tracker_head;
6369 tracker_head = ggc_alloc (sizeof (*tracker_head));
6370 tracker_head->next = old_head;
6371 tracker_head->trees[0] = t;
6372 for (i = 1; i < NUM_TRACKED_CHUNK; i++)
6373 tracker_head->trees[i] = NULL;
6378 ffecom_init_zero_ (tree decl)
6381 int incremental = TREE_STATIC (decl);
6382 tree type = TREE_TYPE (decl);
6386 make_decl_rtl (decl, NULL);
6387 assemble_variable (decl, TREE_PUBLIC (decl) ? 1 : 0, 0, 1);
6390 if ((TREE_CODE (type) != ARRAY_TYPE)
6391 && (TREE_CODE (type) != RECORD_TYPE)
6392 && (TREE_CODE (type) != UNION_TYPE)
6394 init = convert (type, integer_zero_node);
6395 else if (!incremental)
6397 init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
6398 TREE_CONSTANT (init) = 1;
6399 TREE_STATIC (init) = 1;
6403 assemble_zeros (int_size_in_bytes (type));
6404 init = error_mark_node;
6411 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6413 ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
6419 switch (ffebld_op (arg))
6421 case FFEBLD_opCONTER: /* For F90, check 0-length. */
6422 if (ffetarget_length_character1
6423 (ffebld_constant_character1
6424 (ffebld_conter (arg))) == 0)
6426 *maybe_tree = integer_zero_node;
6427 return convert (tree_type, integer_zero_node);
6430 *maybe_tree = integer_one_node;
6431 expr_tree = build_int_2 (*ffetarget_text_character1
6432 (ffebld_constant_character1
6433 (ffebld_conter (arg))),
6435 TREE_TYPE (expr_tree) = tree_type;
6438 case FFEBLD_opSYMTER:
6439 case FFEBLD_opARRAYREF:
6440 case FFEBLD_opFUNCREF:
6441 case FFEBLD_opSUBSTR:
6442 ffecom_char_args_ (&expr_tree, &length_tree, arg);
6444 if ((expr_tree == error_mark_node)
6445 || (length_tree == error_mark_node))
6447 *maybe_tree = error_mark_node;
6448 return error_mark_node;
6451 if (integer_zerop (length_tree))
6453 *maybe_tree = integer_zero_node;
6454 return convert (tree_type, integer_zero_node);
6458 = ffecom_1 (INDIRECT_REF,
6459 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6462 = ffecom_2 (ARRAY_REF,
6463 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6466 expr_tree = convert (tree_type, expr_tree);
6468 if (TREE_CODE (length_tree) == INTEGER_CST)
6469 *maybe_tree = integer_one_node;
6470 else /* Must check length at run time. */
6472 = ffecom_truth_value
6473 (ffecom_2 (GT_EXPR, integer_type_node,
6475 ffecom_f2c_ftnlen_zero_node));
6478 case FFEBLD_opPAREN:
6479 case FFEBLD_opCONVERT:
6480 if (ffeinfo_size (ffebld_info (arg)) == 0)
6482 *maybe_tree = integer_zero_node;
6483 return convert (tree_type, integer_zero_node);
6485 return ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6488 case FFEBLD_opCONCATENATE:
6495 expr_left = ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6497 expr_right = ffecom_intrinsic_ichar_ (tree_type, ffebld_right (arg),
6499 *maybe_tree = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
6502 expr_tree = ffecom_3 (COND_EXPR, tree_type,
6510 assert ("bad op in ICHAR" == NULL);
6511 return error_mark_node;
6516 /* ffecom_intrinsic_len_ -- Return length info for char arg (LEN())
6520 length_arg = ffecom_intrinsic_len_ (expr);
6522 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
6523 subexpressions by constructing the appropriate tree for the
6524 length-of-character-text argument in a calling sequence. */
6526 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6528 ffecom_intrinsic_len_ (ffebld expr)
6530 ffetargetCharacter1 val;
6533 switch (ffebld_op (expr))
6535 case FFEBLD_opCONTER:
6536 val = ffebld_constant_character1 (ffebld_conter (expr));
6537 length = build_int_2 (ffetarget_length_character1 (val), 0);
6538 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6541 case FFEBLD_opSYMTER:
6543 ffesymbol s = ffebld_symter (expr);
6546 item = ffesymbol_hook (s).decl_tree;
6547 if (item == NULL_TREE)
6549 s = ffecom_sym_transform_ (s);
6550 item = ffesymbol_hook (s).decl_tree;
6552 if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
6554 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
6555 length = ffesymbol_hook (s).length_tree;
6558 length = build_int_2 (ffesymbol_size (s), 0);
6559 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6562 else if (item == error_mark_node)
6563 length = error_mark_node;
6564 else /* FFEINFO_kindFUNCTION: */
6569 case FFEBLD_opARRAYREF:
6570 length = ffecom_intrinsic_len_ (ffebld_left (expr));
6573 case FFEBLD_opSUBSTR:
6577 ffebld thing = ffebld_right (expr);
6581 assert (ffebld_op (thing) == FFEBLD_opITEM);
6582 start = ffebld_head (thing);
6583 thing = ffebld_trail (thing);
6584 assert (ffebld_trail (thing) == NULL);
6585 end = ffebld_head (thing);
6587 length = ffecom_intrinsic_len_ (ffebld_left (expr));
6589 if (length == error_mark_node)
6598 length = convert (ffecom_f2c_ftnlen_type_node,
6604 start_tree = convert (ffecom_f2c_ftnlen_type_node,
6605 ffecom_expr (start));
6607 if (start_tree == error_mark_node)
6609 length = error_mark_node;
6615 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6616 ffecom_f2c_ftnlen_one_node,
6617 ffecom_2 (MINUS_EXPR,
6618 ffecom_f2c_ftnlen_type_node,
6624 end_tree = convert (ffecom_f2c_ftnlen_type_node,
6627 if (end_tree == error_mark_node)
6629 length = error_mark_node;
6633 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6634 ffecom_f2c_ftnlen_one_node,
6635 ffecom_2 (MINUS_EXPR,
6636 ffecom_f2c_ftnlen_type_node,
6637 end_tree, start_tree));
6643 case FFEBLD_opCONCATENATE:
6645 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6646 ffecom_intrinsic_len_ (ffebld_left (expr)),
6647 ffecom_intrinsic_len_ (ffebld_right (expr)));
6650 case FFEBLD_opFUNCREF:
6651 case FFEBLD_opCONVERT:
6652 length = build_int_2 (ffebld_size (expr), 0);
6653 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6657 assert ("bad op for single char arg expr" == NULL);
6658 length = ffecom_f2c_ftnlen_zero_node;
6662 assert (length != NULL_TREE);
6668 /* Handle CHARACTER assignments.
6670 Generates code to do the assignment. Used by ordinary assignment
6671 statement handler ffecom_let_stmt and by statement-function
6672 handler to generate code for a statement function. */
6674 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6676 ffecom_let_char_ (tree dest_tree, tree dest_length,
6677 ffetargetCharacterSize dest_size, ffebld source)
6679 ffecomConcatList_ catlist;
6684 if ((dest_tree == error_mark_node)
6685 || (dest_length == error_mark_node))
6688 assert (dest_tree != NULL_TREE);
6689 assert (dest_length != NULL_TREE);
6691 /* Source might be an opCONVERT, which just means it is a different size
6692 than the destination. Since the underlying implementation here handles
6693 that (directly or via the s_copy or s_cat run-time-library functions),
6694 we don't need the "convenience" of an opCONVERT that tells us to
6695 truncate or blank-pad, particularly since the resulting implementation
6696 would probably be slower than otherwise. */
6698 while (ffebld_op (source) == FFEBLD_opCONVERT)
6699 source = ffebld_left (source);
6701 catlist = ffecom_concat_list_new_ (source, dest_size);
6702 switch (ffecom_concat_list_count_ (catlist))
6704 case 0: /* Shouldn't happen, but in case it does... */
6705 ffecom_concat_list_kill_ (catlist);
6706 source_tree = null_pointer_node;
6707 source_length = ffecom_f2c_ftnlen_zero_node;
6708 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6709 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6710 TREE_CHAIN (TREE_CHAIN (expr_tree))
6711 = build_tree_list (NULL_TREE, dest_length);
6712 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6713 = build_tree_list (NULL_TREE, source_length);
6715 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6716 TREE_SIDE_EFFECTS (expr_tree) = 1;
6718 expand_expr_stmt (expr_tree);
6722 case 1: /* The (fairly) easy case. */
6723 ffecom_char_args_ (&source_tree, &source_length,
6724 ffecom_concat_list_expr_ (catlist, 0));
6725 ffecom_concat_list_kill_ (catlist);
6726 assert (source_tree != NULL_TREE);
6727 assert (source_length != NULL_TREE);
6729 if ((source_tree == error_mark_node)
6730 || (source_length == error_mark_node))
6736 = ffecom_1 (INDIRECT_REF,
6737 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6741 = ffecom_2 (ARRAY_REF,
6742 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6747 = ffecom_1 (INDIRECT_REF,
6748 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6752 = ffecom_2 (ARRAY_REF,
6753 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6758 expr_tree = ffecom_modify (void_type_node, dest_tree, source_tree);
6760 expand_expr_stmt (expr_tree);
6765 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6766 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6767 TREE_CHAIN (TREE_CHAIN (expr_tree))
6768 = build_tree_list (NULL_TREE, dest_length);
6769 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6770 = build_tree_list (NULL_TREE, source_length);
6772 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6773 TREE_SIDE_EFFECTS (expr_tree) = 1;
6775 expand_expr_stmt (expr_tree);
6779 default: /* Must actually concatenate things. */
6783 /* Heavy-duty concatenation. */
6786 int count = ffecom_concat_list_count_ (catlist);
6798 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
6799 FFETARGET_charactersizeNONE, count, TRUE);
6800 item_array = items = ffecom_push_tempvar (ffecom_f2c_address_type_node,
6801 FFETARGET_charactersizeNONE,
6807 hook = ffebld_nonter_hook (source);
6809 assert (TREE_CODE (hook) == TREE_VEC);
6810 assert (TREE_VEC_LENGTH (hook) == 2);
6811 length_array = lengths = TREE_VEC_ELT (hook, 0);
6812 item_array = items = TREE_VEC_ELT (hook, 1);
6816 for (i = 0; i < count; ++i)
6818 ffecom_char_args_ (&citem, &clength,
6819 ffecom_concat_list_expr_ (catlist, i));
6820 if ((citem == error_mark_node)
6821 || (clength == error_mark_node))
6823 ffecom_concat_list_kill_ (catlist);
6828 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
6829 ffecom_modify (void_type_node,
6830 ffecom_2 (ARRAY_REF,
6831 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
6833 build_int_2 (i, 0)),
6837 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
6838 ffecom_modify (void_type_node,
6839 ffecom_2 (ARRAY_REF,
6840 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
6842 build_int_2 (i, 0)),
6847 expr_tree = build_tree_list (NULL_TREE, dest_tree);
6848 TREE_CHAIN (expr_tree)
6849 = build_tree_list (NULL_TREE,
6850 ffecom_1 (ADDR_EXPR,
6851 build_pointer_type (TREE_TYPE (items)),
6853 TREE_CHAIN (TREE_CHAIN (expr_tree))
6854 = build_tree_list (NULL_TREE,
6855 ffecom_1 (ADDR_EXPR,
6856 build_pointer_type (TREE_TYPE (lengths)),
6858 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6861 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
6862 convert (ffecom_f2c_ftnlen_type_node,
6863 build_int_2 (count, 0))));
6864 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree))))
6865 = build_tree_list (NULL_TREE, dest_length);
6867 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCAT, expr_tree, NULL_TREE);
6868 TREE_SIDE_EFFECTS (expr_tree) = 1;
6870 expand_expr_stmt (expr_tree);
6873 ffecom_concat_list_kill_ (catlist);
6877 /* ffecom_make_gfrt_ -- Make initial info for run-time routine
6880 ffecom_make_gfrt_(ix);
6882 Assumes gfrt_[ix] is NULL_TREE, and replaces it with the FUNCTION_DECL
6883 for the indicated run-time routine (ix). */
6885 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6887 ffecom_make_gfrt_ (ffecomGfrt ix)
6892 switch (ffecom_gfrt_type_[ix])
6894 case FFECOM_rttypeVOID_:
6895 ttype = void_type_node;
6898 case FFECOM_rttypeVOIDSTAR_:
6899 ttype = TREE_TYPE (null_pointer_node); /* `void *'. */
6902 case FFECOM_rttypeFTNINT_:
6903 ttype = ffecom_f2c_ftnint_type_node;
6906 case FFECOM_rttypeINTEGER_:
6907 ttype = ffecom_f2c_integer_type_node;
6910 case FFECOM_rttypeLONGINT_:
6911 ttype = ffecom_f2c_longint_type_node;
6914 case FFECOM_rttypeLOGICAL_:
6915 ttype = ffecom_f2c_logical_type_node;
6918 case FFECOM_rttypeREAL_F2C_:
6919 ttype = double_type_node;
6922 case FFECOM_rttypeREAL_GNU_:
6923 ttype = float_type_node;
6926 case FFECOM_rttypeCOMPLEX_F2C_:
6927 ttype = void_type_node;
6930 case FFECOM_rttypeCOMPLEX_GNU_:
6931 ttype = ffecom_f2c_complex_type_node;
6934 case FFECOM_rttypeDOUBLE_:
6935 ttype = double_type_node;
6938 case FFECOM_rttypeDOUBLEREAL_:
6939 ttype = ffecom_f2c_doublereal_type_node;
6942 case FFECOM_rttypeDBLCMPLX_F2C_:
6943 ttype = void_type_node;
6946 case FFECOM_rttypeDBLCMPLX_GNU_:
6947 ttype = ffecom_f2c_doublecomplex_type_node;
6950 case FFECOM_rttypeCHARACTER_:
6951 ttype = void_type_node;
6956 assert ("bad rttype" == NULL);
6960 ttype = build_function_type (ttype, NULL_TREE);
6961 t = build_decl (FUNCTION_DECL,
6962 get_identifier (ffecom_gfrt_name_[ix]),
6964 DECL_EXTERNAL (t) = 1;
6965 TREE_READONLY (t) = ffecom_gfrt_const_[ix] ? 1 : 0;
6966 TREE_PUBLIC (t) = 1;
6967 TREE_THIS_VOLATILE (t) = ffecom_gfrt_volatile_[ix] ? 1 : 0;
6969 /* Sanity check: A function that's const cannot be volatile. */
6971 assert (ffecom_gfrt_const_[ix] ? !ffecom_gfrt_volatile_[ix] : 1);
6973 /* Sanity check: A function that's const cannot return complex. */
6975 assert (ffecom_gfrt_const_[ix] ? !ffecom_gfrt_complex_[ix] : 1);
6977 t = start_decl (t, TRUE);
6979 finish_decl (t, NULL_TREE, TRUE);
6981 ffecom_gfrt_[ix] = t;
6985 /* Phase 1 pass over each member of a COMMON/EQUIVALENCE group. */
6987 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6989 ffecom_member_phase1_ (ffestorag mst UNUSED, ffestorag st)
6991 ffesymbol s = ffestorag_symbol (st);
6993 if (ffesymbol_namelisted (s))
6994 ffecom_member_namelisted_ = TRUE;
6998 /* Phase 2 pass over each member of a COMMON/EQUIVALENCE group. Declare
6999 the member so debugger will see it. Otherwise nobody should be
7000 referencing the member. */
7002 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7004 ffecom_member_phase2_ (ffestorag mst, ffestorag st)
7012 || ((mt = ffestorag_hook (mst)) == NULL)
7013 || (mt == error_mark_node))
7017 || ((s = ffestorag_symbol (st)) == NULL))
7020 type = ffecom_type_localvar_ (s,
7021 ffesymbol_basictype (s),
7022 ffesymbol_kindtype (s));
7023 if (type == error_mark_node)
7026 t = build_decl (VAR_DECL,
7027 ffecom_get_identifier_ (ffesymbol_text (s)),
7030 TREE_STATIC (t) = TREE_STATIC (mt);
7031 DECL_INITIAL (t) = NULL_TREE;
7032 TREE_ASM_WRITTEN (t) = 1;
7036 gen_rtx (MEM, TYPE_MODE (type),
7037 plus_constant (XEXP (DECL_RTL (mt), 0),
7038 ffestorag_modulo (mst)
7039 + ffestorag_offset (st)
7040 - ffestorag_offset (mst))));
7042 t = start_decl (t, FALSE);
7044 finish_decl (t, NULL_TREE, FALSE);
7048 /* Prepare source expression for assignment into a destination perhaps known
7049 to be of a specific size. */
7052 ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size, ffebld source)
7054 ffecomConcatList_ catlist;
7059 tree tempvar = NULL_TREE;
7061 while (ffebld_op (source) == FFEBLD_opCONVERT)
7062 source = ffebld_left (source);
7064 catlist = ffecom_concat_list_new_ (source, dest_size);
7065 count = ffecom_concat_list_count_ (catlist);
7070 = ffecom_make_tempvar ("let_char_len", ffecom_f2c_ftnlen_type_node,
7071 FFETARGET_charactersizeNONE, count);
7073 = ffecom_make_tempvar ("let_char_item", ffecom_f2c_address_type_node,
7074 FFETARGET_charactersizeNONE, count);
7076 tempvar = make_tree_vec (2);
7077 TREE_VEC_ELT (tempvar, 0) = ltmp;
7078 TREE_VEC_ELT (tempvar, 1) = itmp;
7081 for (i = 0; i < count; ++i)
7082 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist, i));
7084 ffecom_concat_list_kill_ (catlist);
7088 ffebld_nonter_set_hook (source, tempvar);
7089 current_binding_level->prep_state = 1;
7093 /* ffecom_push_dummy_decls_ -- Transform dummy args, push parm decls in order
7095 Ignores STAR (alternate-return) dummies. All other get exec-transitioned
7096 (which generates their trees) and then their trees get push_parm_decl'd.
7098 The second arg is TRUE if the dummies are for a statement function, in
7099 which case lengths are not pushed for character arguments (since they are
7100 always known by both the caller and the callee, though the code allows
7101 for someday permitting CHAR*(*) stmtfunc dummies). */
7103 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7105 ffecom_push_dummy_decls_ (ffebld dummy_list, bool stmtfunc)
7112 ffecom_transform_only_dummies_ = TRUE;
7114 /* First push the parms corresponding to actual dummy "contents". */
7116 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7118 dummy = ffebld_head (dumlist);
7119 switch (ffebld_op (dummy))
7123 continue; /* Forget alternate returns. */
7128 assert (ffebld_op (dummy) == FFEBLD_opSYMTER);
7129 s = ffebld_symter (dummy);
7130 parm = ffesymbol_hook (s).decl_tree;
7131 if (parm == NULL_TREE)
7133 s = ffecom_sym_transform_ (s);
7134 parm = ffesymbol_hook (s).decl_tree;
7135 assert (parm != NULL_TREE);
7137 if (parm != error_mark_node)
7138 push_parm_decl (parm);
7141 /* Then, for CHARACTER dummies, push the parms giving their lengths. */
7143 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7145 dummy = ffebld_head (dumlist);
7146 switch (ffebld_op (dummy))
7150 continue; /* Forget alternate returns, they mean
7156 s = ffebld_symter (dummy);
7157 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
7158 continue; /* Only looking for CHARACTER arguments. */
7159 if (stmtfunc && (ffesymbol_size (s) != FFETARGET_charactersizeNONE))
7160 continue; /* Stmtfunc arg with known size needs no
7162 if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
7163 continue; /* Only looking for variables and arrays. */
7164 parm = ffesymbol_hook (s).length_tree;
7165 assert (parm != NULL_TREE);
7166 if (parm != error_mark_node)
7167 push_parm_decl (parm);
7170 ffecom_transform_only_dummies_ = FALSE;
7174 /* ffecom_start_progunit_ -- Beginning of program unit
7176 Does GNU back end stuff necessary to teach it about the start of its
7177 equivalent of a Fortran program unit. */
7179 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7181 ffecom_start_progunit_ ()
7183 ffesymbol fn = ffecom_primary_entry_;
7185 tree id; /* Identifier (name) of function. */
7186 tree type; /* Type of function. */
7187 tree result; /* Result of function. */
7188 ffeinfoBasictype bt;
7192 ffeglobalType egt = FFEGLOBAL_type;
7195 bool altentries = (ffecom_num_entrypoints_ != 0);
7198 && (ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
7199 && (ffecom_master_bt_ == FFEINFO_basictypeNONE);
7200 bool main_program = FALSE;
7201 int old_lineno = lineno;
7202 const char *old_input_filename = input_filename;
7204 assert (fn != NULL);
7205 assert (ffesymbol_hook (fn).decl_tree == NULL_TREE);
7207 input_filename = ffesymbol_where_filename (fn);
7208 lineno = ffesymbol_where_filelinenum (fn);
7210 switch (ffecom_primary_entry_kind_)
7212 case FFEINFO_kindPROGRAM:
7213 main_program = TRUE;
7214 gt = FFEGLOBAL_typeMAIN;
7215 bt = FFEINFO_basictypeNONE;
7216 kt = FFEINFO_kindtypeNONE;
7217 type = ffecom_tree_fun_type_void;
7222 case FFEINFO_kindBLOCKDATA:
7223 gt = FFEGLOBAL_typeBDATA;
7224 bt = FFEINFO_basictypeNONE;
7225 kt = FFEINFO_kindtypeNONE;
7226 type = ffecom_tree_fun_type_void;
7231 case FFEINFO_kindFUNCTION:
7232 gt = FFEGLOBAL_typeFUNC;
7233 egt = FFEGLOBAL_typeEXT;
7234 bt = ffesymbol_basictype (fn);
7235 kt = ffesymbol_kindtype (fn);
7236 if (bt == FFEINFO_basictypeNONE)
7238 ffeimplic_establish_symbol (fn);
7239 if (ffesymbol_funcresult (fn) != NULL)
7240 ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
7241 bt = ffesymbol_basictype (fn);
7242 kt = ffesymbol_kindtype (fn);
7246 charfunc = cmplxfunc = FALSE;
7247 else if (bt == FFEINFO_basictypeCHARACTER)
7248 charfunc = TRUE, cmplxfunc = FALSE;
7249 else if ((bt == FFEINFO_basictypeCOMPLEX)
7250 && ffesymbol_is_f2c (fn)
7252 charfunc = FALSE, cmplxfunc = TRUE;
7254 charfunc = cmplxfunc = FALSE;
7256 if (multi || charfunc)
7257 type = ffecom_tree_fun_type_void;
7258 else if (ffesymbol_is_f2c (fn) && !altentries)
7259 type = ffecom_tree_fun_type[bt][kt];
7261 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
7263 if ((type == NULL_TREE)
7264 || (TREE_TYPE (type) == NULL_TREE))
7265 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */
7268 case FFEINFO_kindSUBROUTINE:
7269 gt = FFEGLOBAL_typeSUBR;
7270 egt = FFEGLOBAL_typeEXT;
7271 bt = FFEINFO_basictypeNONE;
7272 kt = FFEINFO_kindtypeNONE;
7273 if (ffecom_is_altreturning_)
7274 type = ffecom_tree_subr_type;
7276 type = ffecom_tree_fun_type_void;
7282 assert ("say what??" == NULL);
7284 case FFEINFO_kindANY:
7285 gt = FFEGLOBAL_typeANY;
7286 bt = FFEINFO_basictypeNONE;
7287 kt = FFEINFO_kindtypeNONE;
7288 type = error_mark_node;
7296 id = ffecom_get_invented_identifier ("__g77_masterfun_%s",
7297 ffesymbol_text (fn));
7299 #if FFETARGET_isENFORCED_MAIN
7300 else if (main_program)
7301 id = get_identifier (FFETARGET_nameENFORCED_MAIN_NAME);
7304 id = ffecom_get_external_identifier_ (fn);
7308 0, /* nested/inline */
7309 !altentries); /* TREE_PUBLIC */
7311 TREE_USED (current_function_decl) = 1; /* Avoid spurious warning if altentries. */
7314 && ((g = ffesymbol_global (fn)) != NULL)
7315 && ((ffeglobal_type (g) == gt)
7316 || (ffeglobal_type (g) == egt)))
7318 ffeglobal_set_hook (g, current_function_decl);
7321 /* Arg handling needs exec-transitioned ffesymbols to work with. But
7322 exec-transitioning needs current_function_decl to be filled in. So we
7323 do these things in two phases. */
7326 { /* 1st arg identifies which entrypoint. */
7327 ffecom_which_entrypoint_decl_
7328 = build_decl (PARM_DECL,
7329 ffecom_get_invented_identifier ("__g77_%s",
7330 "which_entrypoint"),
7332 push_parm_decl (ffecom_which_entrypoint_decl_);
7338 { /* Arg for result (return value). */
7343 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
7345 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
7347 type = ffecom_multi_type_node_;
7349 result = ffecom_get_invented_identifier ("__g77_%s", "result");
7351 /* Make length arg _and_ enhance type info for CHAR arg itself. */
7354 length = ffecom_char_enhance_arg_ (&type, fn);
7356 length = NULL_TREE; /* Not ref'd if !charfunc. */
7358 type = build_pointer_type (type);
7359 result = build_decl (PARM_DECL, result, type);
7361 push_parm_decl (result);
7363 ffecom_multi_retval_ = result;
7365 ffecom_func_result_ = result;
7369 push_parm_decl (length);
7370 ffecom_func_length_ = length;
7374 if (ffecom_primary_entry_is_proc_)
7377 arglist = ffecom_master_arglist_;
7379 arglist = ffesymbol_dummyargs (fn);
7380 ffecom_push_dummy_decls_ (arglist, FALSE);
7383 if (TREE_CODE (current_function_decl) != ERROR_MARK)
7384 store_parm_decls (main_program ? 1 : 0);
7386 ffecom_start_compstmt ();
7387 /* Disallow temp vars at this level. */
7388 current_binding_level->prep_state = 2;
7390 lineno = old_lineno;
7391 input_filename = old_input_filename;
7393 /* This handles any symbols still untransformed, in case -g specified.
7394 This used to be done in ffecom_finish_progunit, but it turns out to
7395 be necessary to do it here so that statement functions are
7396 expanded before code. But don't bother for BLOCK DATA. */
7398 if (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
7399 ffesymbol_drive (ffecom_finish_symbol_transform_);
7403 /* ffecom_sym_transform_ -- Transform FFE sym into backend sym
7406 ffecom_sym_transform_(s);
7408 The ffesymbol_hook info for s is updated with appropriate backend info
7411 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7413 ffecom_sym_transform_ (ffesymbol s)
7415 tree t; /* Transformed thingy. */
7416 tree tlen; /* Length if CHAR*(*). */
7417 bool addr; /* Is t the address of the thingy? */
7418 ffeinfoBasictype bt;
7421 int old_lineno = lineno;
7422 const char *old_input_filename = input_filename;
7424 /* Must ensure special ASSIGN variables are declared at top of outermost
7425 block, else they'll end up in the innermost block when their first
7426 ASSIGN is seen, which leaves them out of scope when they're the
7427 subject of a GOTO or I/O statement.
7429 We make this variable even if -fugly-assign. Just let it go unused,
7430 in case it turns out there are cases where we really want to use this
7431 variable anyway (e.g. ASSIGN to INTEGER*2 variable). */
7433 if (! ffecom_transform_only_dummies_
7434 && ffesymbol_assigned (s)
7435 && ! ffesymbol_hook (s).assign_tree)
7436 s = ffecom_sym_transform_assign_ (s);
7438 if (ffesymbol_sfdummyparent (s) == NULL)
7440 input_filename = ffesymbol_where_filename (s);
7441 lineno = ffesymbol_where_filelinenum (s);
7445 ffesymbol sf = ffesymbol_sfdummyparent (s);
7447 input_filename = ffesymbol_where_filename (sf);
7448 lineno = ffesymbol_where_filelinenum (sf);
7451 bt = ffeinfo_basictype (ffebld_info (s));
7452 kt = ffeinfo_kindtype (ffebld_info (s));
7458 switch (ffesymbol_kind (s))
7460 case FFEINFO_kindNONE:
7461 switch (ffesymbol_where (s))
7463 case FFEINFO_whereDUMMY: /* Subroutine or function. */
7464 assert (ffecom_transform_only_dummies_);
7466 /* Before 0.4, this could be ENTITY/DUMMY, but see
7467 ffestu_sym_end_transition -- no longer true (in particular, if
7468 it could be an ENTITY, it _will_ be made one, so that
7469 possibility won't come through here). So we never make length
7470 arg for CHARACTER type. */
7472 t = build_decl (PARM_DECL,
7473 ffecom_get_identifier_ (ffesymbol_text (s)),
7474 ffecom_tree_ptr_to_subr_type);
7476 DECL_ARTIFICIAL (t) = 1;
7481 case FFEINFO_whereGLOBAL: /* Subroutine or function. */
7482 assert (!ffecom_transform_only_dummies_);
7484 if (((g = ffesymbol_global (s)) != NULL)
7485 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7486 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7487 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
7488 && (ffeglobal_hook (g) != NULL_TREE)
7489 && ffe_is_globals ())
7491 t = ffeglobal_hook (g);
7495 t = build_decl (FUNCTION_DECL,
7496 ffecom_get_external_identifier_ (s),
7497 ffecom_tree_subr_type); /* Assume subr. */
7498 DECL_EXTERNAL (t) = 1;
7499 TREE_PUBLIC (t) = 1;
7501 t = start_decl (t, FALSE);
7502 finish_decl (t, NULL_TREE, FALSE);
7505 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7506 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7507 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
7508 ffeglobal_set_hook (g, t);
7510 ffecom_save_tree_forever (t);
7515 assert ("NONE where unexpected" == NULL);
7517 case FFEINFO_whereANY:
7522 case FFEINFO_kindENTITY:
7523 switch (ffeinfo_where (ffesymbol_info (s)))
7526 case FFEINFO_whereCONSTANT:
7527 /* ~~Debugging info needed? */
7528 assert (!ffecom_transform_only_dummies_);
7529 t = error_mark_node; /* Shouldn't ever see this in expr. */
7532 case FFEINFO_whereLOCAL:
7533 assert (!ffecom_transform_only_dummies_);
7536 ffestorag st = ffesymbol_storage (s);
7540 && (ffestorag_size (st) == 0))
7542 t = error_mark_node;
7546 type = ffecom_type_localvar_ (s, bt, kt);
7548 if (type == error_mark_node)
7550 t = error_mark_node;
7555 && (ffestorag_parent (st) != NULL))
7556 { /* Child of EQUIVALENCE parent. */
7559 ffetargetOffset offset;
7561 est = ffestorag_parent (st);
7562 ffecom_transform_equiv_ (est);
7564 et = ffestorag_hook (est);
7565 assert (et != NULL_TREE);
7567 if (! TREE_STATIC (et))
7568 put_var_into_stack (et);
7570 offset = ffestorag_modulo (est)
7571 + ffestorag_offset (ffesymbol_storage (s))
7572 - ffestorag_offset (est);
7574 ffecom_debug_kludge_ (et, "EQUIVALENCE", s, type, offset);
7576 /* (t_type *) (((char *) &et) + offset) */
7578 t = convert (string_type_node, /* (char *) */
7579 ffecom_1 (ADDR_EXPR,
7580 build_pointer_type (TREE_TYPE (et)),
7582 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
7584 build_int_2 (offset, 0));
7585 t = convert (build_pointer_type (type),
7587 TREE_CONSTANT (t) = staticp (et);
7594 bool init = ffesymbol_is_init (s);
7596 t = build_decl (VAR_DECL,
7597 ffecom_get_identifier_ (ffesymbol_text (s)),
7601 || ffesymbol_namelisted (s)
7602 #ifdef FFECOM_sizeMAXSTACKITEM
7604 && (ffestorag_size (st) > FFECOM_sizeMAXSTACKITEM))
7606 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
7607 && (ffecom_primary_entry_kind_
7608 != FFEINFO_kindBLOCKDATA)
7609 && (ffesymbol_is_save (s) || ffe_is_saveall ())))
7610 TREE_STATIC (t) = !ffesymbol_attr (s, FFESYMBOL_attrADJUSTABLE);
7612 TREE_STATIC (t) = 0; /* No need to make static. */
7614 if (init || ffe_is_init_local_zero ())
7615 DECL_INITIAL (t) = error_mark_node;
7617 /* Keep -Wunused from complaining about var if it
7618 is used as sfunc arg or DATA implied-DO. */
7619 if (ffesymbol_attrs (s) & FFESYMBOL_attrsSFARG)
7620 DECL_IN_SYSTEM_HEADER (t) = 1;
7622 t = start_decl (t, FALSE);
7626 if (ffesymbol_init (s) != NULL)
7627 initexpr = ffecom_expr (ffesymbol_init (s));
7629 initexpr = ffecom_init_zero_ (t);
7631 else if (ffe_is_init_local_zero ())
7632 initexpr = ffecom_init_zero_ (t);
7634 initexpr = NULL_TREE; /* Not ref'd if !init. */
7636 finish_decl (t, initexpr, FALSE);
7638 if (st != NULL && DECL_SIZE (t) != error_mark_node)
7640 assert (TREE_CODE (DECL_SIZE_UNIT (t)) == INTEGER_CST);
7641 assert (0 == compare_tree_int (DECL_SIZE_UNIT (t),
7642 ffestorag_size (st)));
7648 case FFEINFO_whereRESULT:
7649 assert (!ffecom_transform_only_dummies_);
7651 if (bt == FFEINFO_basictypeCHARACTER)
7652 { /* Result is already in list of dummies, use
7654 t = ffecom_func_result_;
7655 tlen = ffecom_func_length_;
7659 if ((ffecom_num_entrypoints_ == 0)
7660 && (bt == FFEINFO_basictypeCOMPLEX)
7661 && (ffesymbol_is_f2c (ffecom_primary_entry_)))
7662 { /* Result is already in list of dummies, use
7664 t = ffecom_func_result_;
7668 if (ffecom_func_result_ != NULL_TREE)
7670 t = ffecom_func_result_;
7673 if ((ffecom_num_entrypoints_ != 0)
7674 && (ffecom_master_bt_ == FFEINFO_basictypeNONE))
7676 assert (ffecom_multi_retval_ != NULL_TREE);
7677 t = ffecom_1 (INDIRECT_REF, ffecom_multi_type_node_,
7678 ffecom_multi_retval_);
7679 t = ffecom_2 (COMPONENT_REF, ffecom_tree_type[bt][kt],
7680 t, ffecom_multi_fields_[bt][kt]);
7685 t = build_decl (VAR_DECL,
7686 ffecom_get_identifier_ (ffesymbol_text (s)),
7687 ffecom_tree_type[bt][kt]);
7688 TREE_STATIC (t) = 0; /* Put result on stack. */
7689 t = start_decl (t, FALSE);
7690 finish_decl (t, NULL_TREE, FALSE);
7692 ffecom_func_result_ = t;
7696 case FFEINFO_whereDUMMY:
7704 bool adjustable = FALSE; /* Conditionally adjustable? */
7706 type = ffecom_tree_type[bt][kt];
7707 if (ffesymbol_sfdummyparent (s) != NULL)
7709 if (current_function_decl == ffecom_outer_function_decl_)
7710 { /* Exec transition before sfunc
7711 context; get it later. */
7714 t = ffecom_get_identifier_ (ffesymbol_text
7715 (ffesymbol_sfdummyparent (s)));
7718 t = ffecom_get_identifier_ (ffesymbol_text (s));
7720 assert (ffecom_transform_only_dummies_);
7722 old_sizes = get_pending_sizes ();
7723 put_pending_sizes (old_sizes);
7725 if (bt == FFEINFO_basictypeCHARACTER)
7726 tlen = ffecom_char_enhance_arg_ (&type, s);
7727 type = ffecom_check_size_overflow_ (s, type, TRUE);
7729 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
7731 if (type == error_mark_node)
7734 dim = ffebld_head (dl);
7735 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
7736 if ((ffebld_left (dim) == NULL) || ffecom_doing_entry_)
7737 low = ffecom_integer_one_node;
7739 low = ffecom_expr (ffebld_left (dim));
7740 assert (ffebld_right (dim) != NULL);
7741 if ((ffebld_op (ffebld_right (dim)) == FFEBLD_opSTAR)
7742 || ffecom_doing_entry_)
7744 /* Used to just do high=low. But for ffecom_tree_
7745 canonize_ref_, it probably is important to correctly
7746 assess the size. E.g. given COMPLEX C(*),CFUNC and
7747 C(2)=CFUNC(C), overlap can happen, while it can't
7748 for, say, C(1)=CFUNC(C(2)). */
7749 /* Even more recently used to set to INT_MAX, but that
7750 broke when some overflow checking went into the back
7751 end. Now we just leave the upper bound unspecified. */
7755 high = ffecom_expr (ffebld_right (dim));
7757 /* Determine whether array is conditionally adjustable,
7758 to decide whether back-end magic is needed.
7760 Normally the front end uses the back-end function
7761 variable_size to wrap SAVE_EXPR's around expressions
7762 affecting the size/shape of an array so that the
7763 size/shape info doesn't change during execution
7764 of the compiled code even though variables and
7765 functions referenced in those expressions might.
7767 variable_size also makes sure those saved expressions
7768 get evaluated immediately upon entry to the
7769 compiled procedure -- the front end normally doesn't
7770 have to worry about that.
7772 However, there is a problem with this that affects
7773 g77's implementation of entry points, and that is
7774 that it is _not_ true that each invocation of the
7775 compiled procedure is permitted to evaluate
7776 array size/shape info -- because it is possible
7777 that, for some invocations, that info is invalid (in
7778 which case it is "promised" -- i.e. a violation of
7779 the Fortran standard -- that the compiled code
7780 won't reference the array or its size/shape
7781 during that particular invocation).
7783 To phrase this in C terms, consider this gcc function:
7785 void foo (int *n, float (*a)[*n])
7787 // a is "pointer to array ...", fyi.
7790 Suppose that, for some invocations, it is permitted
7791 for a caller of foo to do this:
7795 Now the _written_ code for foo can take such a call
7796 into account by either testing explicitly for whether
7797 (a == NULL) || (n == NULL) -- presumably it is
7798 not permitted to reference *a in various fashions
7799 if (n == NULL) I suppose -- or it can avoid it by
7800 looking at other info (other arguments, static/global
7803 However, this won't work in gcc 2.5.8 because it'll
7804 automatically emit the code to save the "*n"
7805 expression, which'll yield a NULL dereference for
7806 the "foo (NULL, NULL)" call, something the code
7807 for foo cannot prevent.
7809 g77 definitely needs to avoid executing such
7810 code anytime the pointer to the adjustable array
7811 is NULL, because even if its bounds expressions
7812 don't have any references to possible "absent"
7813 variables like "*n" -- say all variable references
7814 are to COMMON variables, i.e. global (though in C,
7815 local static could actually make sense) -- the
7816 expressions could yield other run-time problems
7817 for allowably "dead" values in those variables.
7819 For example, let's consider a more complicated
7825 void foo (float (*a)[i/j])
7830 The above is (essentially) quite valid for Fortran
7831 but, again, for a call like "foo (NULL);", it is
7832 permitted for i and j to be undefined when the
7833 call is made. If j happened to be zero, for
7834 example, emitting the code to evaluate "i/j"
7835 could result in a run-time error.
7837 Offhand, though I don't have my F77 or F90
7838 standards handy, it might even be valid for a
7839 bounds expression to contain a function reference,
7840 in which case I doubt it is permitted for an
7841 implementation to invoke that function in the
7842 Fortran case involved here (invocation of an
7843 alternate ENTRY point that doesn't have the adjustable
7844 array as one of its arguments).
7846 So, the code that the compiler would normally emit
7847 to preevaluate the size/shape info for an
7848 adjustable array _must not_ be executed at run time
7849 in certain cases. Specifically, for Fortran,
7850 the case is when the pointer to the adjustable
7851 array == NULL. (For gnu-ish C, it might be nice
7852 for the source code itself to specify an expression
7853 that, if TRUE, inhibits execution of the code. Or
7854 reverse the sense for elegance.)
7856 (Note that g77 could use a different test than NULL,
7857 actually, since it happens to always pass an
7858 integer to the called function that specifies which
7859 entry point is being invoked. Hmm, this might
7860 solve the next problem.)
7862 One way a user could, I suppose, write "foo" so
7863 it works is to insert COND_EXPR's for the
7864 size/shape info so the dangerous stuff isn't
7865 actually done, as in:
7867 void foo (int *n, float (*a)[(a == NULL) ? 0 : *n])
7872 The next problem is that the front end needs to
7873 be able to tell the back end about the array's
7874 decl _before_ it tells it about the conditional
7875 expression to inhibit evaluation of size/shape info,
7878 To solve this, the front end needs to be able
7879 to give the back end the expression to inhibit
7880 generation of the preevaluation code _after_
7881 it makes the decl for the adjustable array.
7883 Until then, the above example using the COND_EXPR
7884 doesn't pass muster with gcc because the "(a == NULL)"
7885 part has a reference to "a", which is still
7886 undefined at that point.
7888 g77 will therefore use a different mechanism in the
7892 && ((TREE_CODE (low) != INTEGER_CST)
7893 || (high && TREE_CODE (high) != INTEGER_CST)))
7896 #if 0 /* Old approach -- see below. */
7897 if (TREE_CODE (low) != INTEGER_CST)
7898 low = ffecom_3 (COND_EXPR, integer_type_node,
7899 ffecom_adjarray_passed_ (s),
7901 ffecom_integer_zero_node);
7903 if (high && TREE_CODE (high) != INTEGER_CST)
7904 high = ffecom_3 (COND_EXPR, integer_type_node,
7905 ffecom_adjarray_passed_ (s),
7907 ffecom_integer_zero_node);
7910 /* ~~~gcc/stor-layout.c (layout_type) should do this,
7911 probably. Fixes 950302-1.f. */
7913 if (TREE_CODE (low) != INTEGER_CST)
7914 low = variable_size (low);
7916 /* ~~~Similarly, this fixes dumb0.f. The C front end
7917 does this, which is why dumb0.c would work. */
7919 if (high && TREE_CODE (high) != INTEGER_CST)
7920 high = variable_size (high);
7925 build_range_type (ffecom_integer_type_node,
7927 type = ffecom_check_size_overflow_ (s, type, TRUE);
7930 if (type == error_mark_node)
7932 t = error_mark_node;
7936 if ((ffesymbol_sfdummyparent (s) == NULL)
7937 || (ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER))
7939 type = build_pointer_type (type);
7943 t = build_decl (PARM_DECL, t, type);
7945 DECL_ARTIFICIAL (t) = 1;
7948 /* If this arg is present in every entry point's list of
7949 dummy args, then we're done. */
7951 if (ffesymbol_numentries (s)
7952 == (ffecom_num_entrypoints_ + 1))
7957 /* If variable_size in stor-layout has been called during
7958 the above, then get_pending_sizes should have the
7959 yet-to-be-evaluated saved expressions pending.
7960 Make the whole lot of them get emitted, conditionally
7961 on whether the array decl ("t" above) is not NULL. */
7964 tree sizes = get_pending_sizes ();
7969 tem = TREE_CHAIN (tem))
7971 tree temv = TREE_VALUE (tem);
7977 = ffecom_2 (COMPOUND_EXPR,
7986 = ffecom_3 (COND_EXPR,
7993 convert (TREE_TYPE (sizes),
7994 integer_zero_node));
7995 sizes = ffecom_save_tree (sizes);
7998 = tree_cons (NULL_TREE, sizes, tem);
8002 put_pending_sizes (sizes);
8008 && (ffesymbol_numentries (s)
8009 != ffecom_num_entrypoints_ + 1))
8011 = ffecom_2 (NE_EXPR, integer_type_node,
8017 && (ffesymbol_numentries (s)
8018 != ffecom_num_entrypoints_ + 1))
8020 ffebad_start (FFEBAD_MISSING_ADJARRAY_UNSUPPORTED);
8021 ffebad_here (0, ffesymbol_where_line (s),
8022 ffesymbol_where_column (s));
8023 ffebad_string (ffesymbol_text (s));
8032 case FFEINFO_whereCOMMON:
8037 ffestorag st = ffesymbol_storage (s);
8040 cs = ffesymbol_common (s); /* The COMMON area itself. */
8041 if (st != NULL) /* Else not laid out. */
8043 ffecom_transform_common_ (cs);
8044 st = ffesymbol_storage (s);
8047 type = ffecom_type_localvar_ (s, bt, kt);
8049 cg = ffesymbol_global (cs); /* The global COMMON info. */
8051 || (ffeglobal_type (cg) != FFEGLOBAL_typeCOMMON))
8054 ct = ffeglobal_hook (cg); /* The common area's tree. */
8056 if ((ct == NULL_TREE)
8058 || (type == error_mark_node))
8059 t = error_mark_node;
8062 ffetargetOffset offset;
8065 cst = ffestorag_parent (st);
8066 assert (cst == ffesymbol_storage (cs));
8068 offset = ffestorag_modulo (cst)
8069 + ffestorag_offset (st)
8070 - ffestorag_offset (cst);
8072 ffecom_debug_kludge_ (ct, "COMMON", s, type, offset);
8074 /* (t_type *) (((char *) &ct) + offset) */
8076 t = convert (string_type_node, /* (char *) */
8077 ffecom_1 (ADDR_EXPR,
8078 build_pointer_type (TREE_TYPE (ct)),
8080 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
8082 build_int_2 (offset, 0));
8083 t = convert (build_pointer_type (type),
8085 TREE_CONSTANT (t) = 1;
8092 case FFEINFO_whereIMMEDIATE:
8093 case FFEINFO_whereGLOBAL:
8094 case FFEINFO_whereFLEETING:
8095 case FFEINFO_whereFLEETING_CADDR:
8096 case FFEINFO_whereFLEETING_IADDR:
8097 case FFEINFO_whereINTRINSIC:
8098 case FFEINFO_whereCONSTANT_SUBOBJECT:
8100 assert ("ENTITY where unheard of" == NULL);
8102 case FFEINFO_whereANY:
8103 t = error_mark_node;
8108 case FFEINFO_kindFUNCTION:
8109 switch (ffeinfo_where (ffesymbol_info (s)))
8111 case FFEINFO_whereLOCAL: /* Me. */
8112 assert (!ffecom_transform_only_dummies_);
8113 t = current_function_decl;
8116 case FFEINFO_whereGLOBAL:
8117 assert (!ffecom_transform_only_dummies_);
8119 if (((g = ffesymbol_global (s)) != NULL)
8120 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8121 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8122 && (ffeglobal_hook (g) != NULL_TREE)
8123 && ffe_is_globals ())
8125 t = ffeglobal_hook (g);
8129 if (ffesymbol_is_f2c (s)
8130 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8131 t = ffecom_tree_fun_type[bt][kt];
8133 t = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
8135 t = build_decl (FUNCTION_DECL,
8136 ffecom_get_external_identifier_ (s),
8138 DECL_EXTERNAL (t) = 1;
8139 TREE_PUBLIC (t) = 1;
8141 t = start_decl (t, FALSE);
8142 finish_decl (t, NULL_TREE, FALSE);
8145 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8146 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8147 ffeglobal_set_hook (g, t);
8149 ffecom_save_tree_forever (t);
8153 case FFEINFO_whereDUMMY:
8154 assert (ffecom_transform_only_dummies_);
8156 if (ffesymbol_is_f2c (s)
8157 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8158 t = ffecom_tree_ptr_to_fun_type[bt][kt];
8160 t = build_pointer_type
8161 (build_function_type (ffecom_tree_type[bt][kt], NULL_TREE));
8163 t = build_decl (PARM_DECL,
8164 ffecom_get_identifier_ (ffesymbol_text (s)),
8167 DECL_ARTIFICIAL (t) = 1;
8172 case FFEINFO_whereCONSTANT: /* Statement function. */
8173 assert (!ffecom_transform_only_dummies_);
8174 t = ffecom_gen_sfuncdef_ (s, bt, kt);
8177 case FFEINFO_whereINTRINSIC:
8178 assert (!ffecom_transform_only_dummies_);
8179 break; /* Let actual references generate their
8183 assert ("FUNCTION where unheard of" == NULL);
8185 case FFEINFO_whereANY:
8186 t = error_mark_node;
8191 case FFEINFO_kindSUBROUTINE:
8192 switch (ffeinfo_where (ffesymbol_info (s)))
8194 case FFEINFO_whereLOCAL: /* Me. */
8195 assert (!ffecom_transform_only_dummies_);
8196 t = current_function_decl;
8199 case FFEINFO_whereGLOBAL:
8200 assert (!ffecom_transform_only_dummies_);
8202 if (((g = ffesymbol_global (s)) != NULL)
8203 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8204 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8205 && (ffeglobal_hook (g) != NULL_TREE)
8206 && ffe_is_globals ())
8208 t = ffeglobal_hook (g);
8212 t = build_decl (FUNCTION_DECL,
8213 ffecom_get_external_identifier_ (s),
8214 ffecom_tree_subr_type);
8215 DECL_EXTERNAL (t) = 1;
8216 TREE_PUBLIC (t) = 1;
8218 t = start_decl (t, FALSE);
8219 finish_decl (t, NULL_TREE, FALSE);
8222 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8223 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8224 ffeglobal_set_hook (g, t);
8226 ffecom_save_tree_forever (t);
8230 case FFEINFO_whereDUMMY:
8231 assert (ffecom_transform_only_dummies_);
8233 t = build_decl (PARM_DECL,
8234 ffecom_get_identifier_ (ffesymbol_text (s)),
8235 ffecom_tree_ptr_to_subr_type);
8237 DECL_ARTIFICIAL (t) = 1;
8242 case FFEINFO_whereINTRINSIC:
8243 assert (!ffecom_transform_only_dummies_);
8244 break; /* Let actual references generate their
8248 assert ("SUBROUTINE where unheard of" == NULL);
8250 case FFEINFO_whereANY:
8251 t = error_mark_node;
8256 case FFEINFO_kindPROGRAM:
8257 switch (ffeinfo_where (ffesymbol_info (s)))
8259 case FFEINFO_whereLOCAL: /* Me. */
8260 assert (!ffecom_transform_only_dummies_);
8261 t = current_function_decl;
8264 case FFEINFO_whereCOMMON:
8265 case FFEINFO_whereDUMMY:
8266 case FFEINFO_whereGLOBAL:
8267 case FFEINFO_whereRESULT:
8268 case FFEINFO_whereFLEETING:
8269 case FFEINFO_whereFLEETING_CADDR:
8270 case FFEINFO_whereFLEETING_IADDR:
8271 case FFEINFO_whereIMMEDIATE:
8272 case FFEINFO_whereINTRINSIC:
8273 case FFEINFO_whereCONSTANT:
8274 case FFEINFO_whereCONSTANT_SUBOBJECT:
8276 assert ("PROGRAM where unheard of" == NULL);
8278 case FFEINFO_whereANY:
8279 t = error_mark_node;
8284 case FFEINFO_kindBLOCKDATA:
8285 switch (ffeinfo_where (ffesymbol_info (s)))
8287 case FFEINFO_whereLOCAL: /* Me. */
8288 assert (!ffecom_transform_only_dummies_);
8289 t = current_function_decl;
8292 case FFEINFO_whereGLOBAL:
8293 assert (!ffecom_transform_only_dummies_);
8295 t = build_decl (FUNCTION_DECL,
8296 ffecom_get_external_identifier_ (s),
8297 ffecom_tree_blockdata_type);
8298 DECL_EXTERNAL (t) = 1;
8299 TREE_PUBLIC (t) = 1;
8301 t = start_decl (t, FALSE);
8302 finish_decl (t, NULL_TREE, FALSE);
8304 ffecom_save_tree_forever (t);
8308 case FFEINFO_whereCOMMON:
8309 case FFEINFO_whereDUMMY:
8310 case FFEINFO_whereRESULT:
8311 case FFEINFO_whereFLEETING:
8312 case FFEINFO_whereFLEETING_CADDR:
8313 case FFEINFO_whereFLEETING_IADDR:
8314 case FFEINFO_whereIMMEDIATE:
8315 case FFEINFO_whereINTRINSIC:
8316 case FFEINFO_whereCONSTANT:
8317 case FFEINFO_whereCONSTANT_SUBOBJECT:
8319 assert ("BLOCKDATA where unheard of" == NULL);
8321 case FFEINFO_whereANY:
8322 t = error_mark_node;
8327 case FFEINFO_kindCOMMON:
8328 switch (ffeinfo_where (ffesymbol_info (s)))
8330 case FFEINFO_whereLOCAL:
8331 assert (!ffecom_transform_only_dummies_);
8332 ffecom_transform_common_ (s);
8335 case FFEINFO_whereNONE:
8336 case FFEINFO_whereCOMMON:
8337 case FFEINFO_whereDUMMY:
8338 case FFEINFO_whereGLOBAL:
8339 case FFEINFO_whereRESULT:
8340 case FFEINFO_whereFLEETING:
8341 case FFEINFO_whereFLEETING_CADDR:
8342 case FFEINFO_whereFLEETING_IADDR:
8343 case FFEINFO_whereIMMEDIATE:
8344 case FFEINFO_whereINTRINSIC:
8345 case FFEINFO_whereCONSTANT:
8346 case FFEINFO_whereCONSTANT_SUBOBJECT:
8348 assert ("COMMON where unheard of" == NULL);
8350 case FFEINFO_whereANY:
8351 t = error_mark_node;
8356 case FFEINFO_kindCONSTRUCT:
8357 switch (ffeinfo_where (ffesymbol_info (s)))
8359 case FFEINFO_whereLOCAL:
8360 assert (!ffecom_transform_only_dummies_);
8363 case FFEINFO_whereNONE:
8364 case FFEINFO_whereCOMMON:
8365 case FFEINFO_whereDUMMY:
8366 case FFEINFO_whereGLOBAL:
8367 case FFEINFO_whereRESULT:
8368 case FFEINFO_whereFLEETING:
8369 case FFEINFO_whereFLEETING_CADDR:
8370 case FFEINFO_whereFLEETING_IADDR:
8371 case FFEINFO_whereIMMEDIATE:
8372 case FFEINFO_whereINTRINSIC:
8373 case FFEINFO_whereCONSTANT:
8374 case FFEINFO_whereCONSTANT_SUBOBJECT:
8376 assert ("CONSTRUCT where unheard of" == NULL);
8378 case FFEINFO_whereANY:
8379 t = error_mark_node;
8384 case FFEINFO_kindNAMELIST:
8385 switch (ffeinfo_where (ffesymbol_info (s)))
8387 case FFEINFO_whereLOCAL:
8388 assert (!ffecom_transform_only_dummies_);
8389 t = ffecom_transform_namelist_ (s);
8392 case FFEINFO_whereNONE:
8393 case FFEINFO_whereCOMMON:
8394 case FFEINFO_whereDUMMY:
8395 case FFEINFO_whereGLOBAL:
8396 case FFEINFO_whereRESULT:
8397 case FFEINFO_whereFLEETING:
8398 case FFEINFO_whereFLEETING_CADDR:
8399 case FFEINFO_whereFLEETING_IADDR:
8400 case FFEINFO_whereIMMEDIATE:
8401 case FFEINFO_whereINTRINSIC:
8402 case FFEINFO_whereCONSTANT:
8403 case FFEINFO_whereCONSTANT_SUBOBJECT:
8405 assert ("NAMELIST where unheard of" == NULL);
8407 case FFEINFO_whereANY:
8408 t = error_mark_node;
8414 assert ("kind unheard of" == NULL);
8416 case FFEINFO_kindANY:
8417 t = error_mark_node;
8421 ffesymbol_hook (s).decl_tree = t;
8422 ffesymbol_hook (s).length_tree = tlen;
8423 ffesymbol_hook (s).addr = addr;
8425 lineno = old_lineno;
8426 input_filename = old_input_filename;
8432 /* Transform into ASSIGNable symbol.
8434 Symbol has already been transformed, but for whatever reason, the
8435 resulting decl_tree has been deemed not usable for an ASSIGN target.
8436 (E.g. it isn't wide enough to hold a pointer.) So, here we invent
8437 another local symbol of type void * and stuff that in the assign_tree
8438 argument. The F77/F90 standards allow this implementation. */
8440 #if FFECOM_targetCURRENT == FFECOM_targetGCC
8442 ffecom_sym_transform_assign_ (ffesymbol s)
8444 tree t; /* Transformed thingy. */
8445 int old_lineno = lineno;
8446 const char *old_input_filename = input_filename;
8448 if (ffesymbol_sfdummyparent (s) == NULL)
8450 input_filename = ffesymbol_where_filename (s);
8451 lineno = ffesymbol_where_filelinenum (s);
8455 ffesymbol sf = ffesymbol_sfdummyparent (s);
8457 input_filename = ffesymbol_where_filename (sf);
8458 lineno = ffesymbol_where_filelinenum (sf);
8461 assert (!ffecom_transform_only_dummies_);
8463 t = build_decl (VAR_DECL,
8464 ffecom_get_invented_identifier ("__g77_ASSIGN_%s",
8465 ffesymbol_text (s)),
8466 TREE_TYPE (null_pointer_node));
8468 switch (ffesymbol_where (s))
8470 case FFEINFO_whereLOCAL:
8471 /* Unlike for regular vars, SAVE status is easy to determine for
8472 ASSIGNed vars, since there's no initialization, there's no
8473 effective storage association (so "SAVE J" does not apply to
8474 K even given "EQUIVALENCE (J,K)"), there's no size issue
8475 to worry about, etc. */
8476 if ((ffesymbol_is_save (s) || ffe_is_saveall ())
8477 && (ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8478 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA))
8479 TREE_STATIC (t) = 1; /* SAVEd in proc, make static. */
8481 TREE_STATIC (t) = 0; /* No need to make static. */
8484 case FFEINFO_whereCOMMON:
8485 TREE_STATIC (t) = 1; /* Assume COMMONs always SAVEd. */
8488 case FFEINFO_whereDUMMY:
8489 /* Note that twinning a DUMMY means the caller won't see
8490 the ASSIGNed value. But both F77 and F90 allow implementations
8491 to do this, i.e. disallow Fortran code that would try and
8492 take advantage of actually putting a label into a variable
8493 via a dummy argument (or any other storage association, for
8495 TREE_STATIC (t) = 0;
8499 TREE_STATIC (t) = 0;
8503 t = start_decl (t, FALSE);
8504 finish_decl (t, NULL_TREE, FALSE);
8506 ffesymbol_hook (s).assign_tree = t;
8508 lineno = old_lineno;
8509 input_filename = old_input_filename;
8515 /* Implement COMMON area in back end.
8517 Because COMMON-based variables can be referenced in the dimension
8518 expressions of dummy (adjustable) arrays, and because dummies
8519 (in the gcc back end) need to be put in the outer binding level
8520 of a function (which has two binding levels, the outer holding
8521 the dummies and the inner holding the other vars), special care
8522 must be taken to handle COMMON areas.
8524 The current strategy is basically to always tell the back end about
8525 the COMMON area as a top-level external reference to just a block
8526 of storage of the master type of that area (e.g. integer, real,
8527 character, whatever -- not a structure). As a distinct action,
8528 if initial values are provided, tell the back end about the area
8529 as a top-level non-external (initialized) area and remember not to
8530 allow further initialization or expansion of the area. Meanwhile,
8531 if no initialization happens at all, tell the back end about
8532 the largest size we've seen declared so the space does get reserved.
8533 (This function doesn't handle all that stuff, but it does some
8534 of the important things.)
8536 Meanwhile, for COMMON variables themselves, just keep creating
8537 references like *((float *) (&common_area + offset)) each time
8538 we reference the variable. In other words, don't make a VAR_DECL
8539 or any kind of component reference (like we used to do before 0.4),
8540 though we might do that as well just for debugging purposes (and
8541 stuff the rtl with the appropriate offset expression). */
8543 #if FFECOM_targetCURRENT == FFECOM_targetGCC
8545 ffecom_transform_common_ (ffesymbol s)
8547 ffestorag st = ffesymbol_storage (s);
8548 ffeglobal g = ffesymbol_global (s);
8553 bool is_init = ffestorag_is_init (st);
8555 assert (st != NULL);
8558 || (ffeglobal_type (g) != FFEGLOBAL_typeCOMMON))
8561 /* First update the size of the area in global terms. */
8563 ffeglobal_size_common (s, ffestorag_size (st));
8565 if (!ffeglobal_common_init (g))
8566 is_init = FALSE; /* No explicit init, don't let erroneous joins init. */
8568 cbt = ffeglobal_hook (g);
8570 /* If we already have declared this common block for a previous program
8571 unit, and either we already initialized it or we don't have new
8572 initialization for it, just return what we have without changing it. */
8574 if ((cbt != NULL_TREE)
8576 || !DECL_EXTERNAL (cbt)))
8578 if (st->hook == NULL) ffestorag_set_hook (st, cbt);
8582 /* Process inits. */
8586 if (ffestorag_init (st) != NULL)
8590 /* Set the padding for the expression, so ffecom_expr
8591 knows to insert that many zeros. */
8592 switch (ffebld_op (sexp = ffestorag_init (st)))
8594 case FFEBLD_opCONTER:
8595 ffebld_conter_set_pad (sexp, ffestorag_modulo (st));
8598 case FFEBLD_opARRTER:
8599 ffebld_arrter_set_pad (sexp, ffestorag_modulo (st));
8602 case FFEBLD_opACCTER:
8603 ffebld_accter_set_pad (sexp, ffestorag_modulo (st));
8607 assert ("bad op for cmn init (pad)" == NULL);
8611 init = ffecom_expr (sexp);
8612 if (init == error_mark_node)
8613 { /* Hopefully the back end complained! */
8615 if (cbt != NULL_TREE)
8620 init = error_mark_node;
8625 /* cbtype must be permanently allocated! */
8627 /* Allocate the MAX of the areas so far, seen filewide. */
8628 high = build_int_2 ((ffeglobal_common_size (g)
8629 + ffeglobal_common_pad (g)) - 1, 0);
8630 TREE_TYPE (high) = ffecom_integer_type_node;
8633 cbtype = build_array_type (char_type_node,
8634 build_range_type (integer_type_node,
8638 cbtype = build_array_type (char_type_node, NULL_TREE);
8640 if (cbt == NULL_TREE)
8643 = build_decl (VAR_DECL,
8644 ffecom_get_external_identifier_ (s),
8646 TREE_STATIC (cbt) = 1;
8647 TREE_PUBLIC (cbt) = 1;
8652 TREE_TYPE (cbt) = cbtype;
8654 DECL_EXTERNAL (cbt) = init ? 0 : 1;
8655 DECL_INITIAL (cbt) = init ? error_mark_node : NULL_TREE;
8657 cbt = start_decl (cbt, TRUE);
8658 if (ffeglobal_hook (g) != NULL)
8659 assert (cbt == ffeglobal_hook (g));
8661 assert (!init || !DECL_EXTERNAL (cbt));
8663 /* Make sure that any type can live in COMMON and be referenced
8664 without getting a bus error. We could pick the most restrictive
8665 alignment of all entities actually placed in the COMMON, but
8666 this seems easy enough. */
8668 DECL_ALIGN (cbt) = BIGGEST_ALIGNMENT;
8669 DECL_USER_ALIGN (cbt) = 0;
8671 if (is_init && (ffestorag_init (st) == NULL))
8672 init = ffecom_init_zero_ (cbt);
8674 finish_decl (cbt, init, TRUE);
8677 ffestorag_set_init (st, ffebld_new_any ());
8681 assert (DECL_SIZE_UNIT (cbt) != NULL_TREE);
8682 assert (TREE_CODE (DECL_SIZE_UNIT (cbt)) == INTEGER_CST);
8683 assert (0 == compare_tree_int (DECL_SIZE_UNIT (cbt),
8684 (ffeglobal_common_size (g)
8685 + ffeglobal_common_pad (g))));
8688 ffeglobal_set_hook (g, cbt);
8690 ffestorag_set_hook (st, cbt);
8692 ffecom_save_tree_forever (cbt);
8696 /* Make master area for local EQUIVALENCE. */
8698 #if FFECOM_targetCURRENT == FFECOM_targetGCC
8700 ffecom_transform_equiv_ (ffestorag eqst)
8706 bool is_init = ffestorag_is_init (eqst);
8708 assert (eqst != NULL);
8710 eqt = ffestorag_hook (eqst);
8712 if (eqt != NULL_TREE)
8715 /* Process inits. */
8719 if (ffestorag_init (eqst) != NULL)
8723 /* Set the padding for the expression, so ffecom_expr
8724 knows to insert that many zeros. */
8725 switch (ffebld_op (sexp = ffestorag_init (eqst)))
8727 case FFEBLD_opCONTER:
8728 ffebld_conter_set_pad (sexp, ffestorag_modulo (eqst));
8731 case FFEBLD_opARRTER:
8732 ffebld_arrter_set_pad (sexp, ffestorag_modulo (eqst));
8735 case FFEBLD_opACCTER:
8736 ffebld_accter_set_pad (sexp, ffestorag_modulo (eqst));
8740 assert ("bad op for eqv init (pad)" == NULL);
8744 init = ffecom_expr (sexp);
8745 if (init == error_mark_node)
8746 init = NULL_TREE; /* Hopefully the back end complained! */
8749 init = error_mark_node;
8751 else if (ffe_is_init_local_zero ())
8752 init = error_mark_node;
8756 ffecom_member_namelisted_ = FALSE;
8757 ffestorag_drive (ffestorag_list_equivs (eqst),
8758 &ffecom_member_phase1_,
8761 high = build_int_2 ((ffestorag_size (eqst)
8762 + ffestorag_modulo (eqst)) - 1, 0);
8763 TREE_TYPE (high) = ffecom_integer_type_node;
8765 eqtype = build_array_type (char_type_node,
8766 build_range_type (ffecom_integer_type_node,
8767 ffecom_integer_zero_node,
8770 eqt = build_decl (VAR_DECL,
8771 ffecom_get_invented_identifier ("__g77_equiv_%s",
8773 (ffestorag_symbol (eqst))),
8775 DECL_EXTERNAL (eqt) = 0;
8777 || ffecom_member_namelisted_
8778 #ifdef FFECOM_sizeMAXSTACKITEM
8779 || (ffestorag_size (eqst) > FFECOM_sizeMAXSTACKITEM)
8781 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8782 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
8783 && (ffestorag_is_save (eqst) || ffe_is_saveall ())))
8784 TREE_STATIC (eqt) = 1;
8786 TREE_STATIC (eqt) = 0;
8787 TREE_PUBLIC (eqt) = 0;
8788 TREE_ADDRESSABLE (eqt) = 1; /* Ensure non-register allocation */
8789 DECL_CONTEXT (eqt) = current_function_decl;
8791 DECL_INITIAL (eqt) = error_mark_node;
8793 DECL_INITIAL (eqt) = NULL_TREE;
8795 eqt = start_decl (eqt, FALSE);
8797 /* Make sure that any type can live in EQUIVALENCE and be referenced
8798 without getting a bus error. We could pick the most restrictive
8799 alignment of all entities actually placed in the EQUIVALENCE, but
8800 this seems easy enough. */
8802 DECL_ALIGN (eqt) = BIGGEST_ALIGNMENT;
8803 DECL_USER_ALIGN (eqt) = 0;
8805 if ((!is_init && ffe_is_init_local_zero ())
8806 || (is_init && (ffestorag_init (eqst) == NULL)))
8807 init = ffecom_init_zero_ (eqt);
8809 finish_decl (eqt, init, FALSE);
8812 ffestorag_set_init (eqst, ffebld_new_any ());
8815 assert (TREE_CODE (DECL_SIZE_UNIT (eqt)) == INTEGER_CST);
8816 assert (0 == compare_tree_int (DECL_SIZE_UNIT (eqt),
8817 (ffestorag_size (eqst)
8818 + ffestorag_modulo (eqst))));
8821 ffestorag_set_hook (eqst, eqt);
8823 ffestorag_drive (ffestorag_list_equivs (eqst),
8824 &ffecom_member_phase2_,
8829 /* Implement NAMELIST in back end. See f2c/format.c for more info. */
8831 #if FFECOM_targetCURRENT == FFECOM_targetGCC
8833 ffecom_transform_namelist_ (ffesymbol s)
8836 tree nmltype = ffecom_type_namelist_ ();
8844 static int mynumber = 0;
8846 nmlt = build_decl (VAR_DECL,
8847 ffecom_get_invented_identifier ("__g77_namelist_%d",
8850 TREE_STATIC (nmlt) = 1;
8851 DECL_INITIAL (nmlt) = error_mark_node;
8853 nmlt = start_decl (nmlt, FALSE);
8855 /* Process inits. */
8857 i = strlen (ffesymbol_text (s));
8859 high = build_int_2 (i, 0);
8860 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
8862 nameinit = ffecom_build_f2c_string_ (i + 1,
8863 ffesymbol_text (s));
8864 TREE_TYPE (nameinit)
8865 = build_type_variant
8868 build_range_type (ffecom_f2c_ftnlen_type_node,
8869 ffecom_f2c_ftnlen_one_node,
8872 TREE_CONSTANT (nameinit) = 1;
8873 TREE_STATIC (nameinit) = 1;
8874 nameinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (nameinit)),
8877 varsinit = ffecom_vardesc_array_ (s);
8878 varsinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (varsinit)),
8880 TREE_CONSTANT (varsinit) = 1;
8881 TREE_STATIC (varsinit) = 1;
8886 for (i = 0, b = ffesymbol_namelist (s); b != NULL; b = ffebld_trail (b))
8889 nvarsinit = build_int_2 (i, 0);
8890 TREE_TYPE (nvarsinit) = integer_type_node;
8891 TREE_CONSTANT (nvarsinit) = 1;
8892 TREE_STATIC (nvarsinit) = 1;
8894 nmlinits = build_tree_list ((field = TYPE_FIELDS (nmltype)), nameinit);
8895 TREE_CHAIN (nmlinits) = build_tree_list ((field = TREE_CHAIN (field)),
8897 TREE_CHAIN (TREE_CHAIN (nmlinits))
8898 = build_tree_list ((field = TREE_CHAIN (field)), nvarsinit);
8900 nmlinits = build (CONSTRUCTOR, nmltype, NULL_TREE, nmlinits);
8901 TREE_CONSTANT (nmlinits) = 1;
8902 TREE_STATIC (nmlinits) = 1;
8904 finish_decl (nmlt, nmlinits, FALSE);
8906 nmlt = ffecom_1 (ADDR_EXPR, build_pointer_type (nmltype), nmlt);
8913 /* A subroutine of ffecom_tree_canonize_ref_. The incoming tree is
8914 analyzed on the assumption it is calculating a pointer to be
8915 indirected through. It must return the proper decl and offset,
8916 taking into account different units of measurements for offsets. */
8918 #if FFECOM_targetCURRENT == FFECOM_targetGCC
8920 ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
8923 switch (TREE_CODE (t))
8927 case NON_LVALUE_EXPR:
8928 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
8932 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
8933 if ((*decl == NULL_TREE)
8934 || (*decl == error_mark_node))
8937 if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST)
8939 /* An offset into COMMON. */
8940 *offset = fold (build (PLUS_EXPR, TREE_TYPE (*offset),
8941 *offset, TREE_OPERAND (t, 1)));
8942 /* Convert offset (presumably in bytes) into canonical units
8943 (presumably bits). */
8944 *offset = size_binop (MULT_EXPR,
8945 convert (bitsizetype, *offset),
8946 TYPE_SIZE (TREE_TYPE (TREE_TYPE (t))));
8949 /* Not a COMMON reference, so an unrecognized pattern. */
8950 *decl = error_mark_node;
8955 *offset = bitsize_zero_node;
8959 if (TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL)
8961 /* A reference to COMMON. */
8962 *decl = TREE_OPERAND (t, 0);
8963 *offset = bitsize_zero_node;
8968 /* Not a COMMON reference, so an unrecognized pattern. */
8969 *decl = error_mark_node;
8975 /* Given a tree that is possibly intended for use as an lvalue, return
8976 information representing a canonical view of that tree as a decl, an
8977 offset into that decl, and a size for the lvalue.
8979 If there's no applicable decl, NULL_TREE is returned for the decl,
8980 and the other fields are left undefined.
8982 If the tree doesn't fit the recognizable forms, an ERROR_MARK node
8983 is returned for the decl, and the other fields are left undefined.
8985 Otherwise, the decl returned currently is either a VAR_DECL or a
8988 The offset returned is always valid, but of course not necessarily
8989 a constant, and not necessarily converted into the appropriate
8990 type, leaving that up to the caller (so as to avoid that overhead
8991 if the decls being looked at are different anyway).
8993 If the size cannot be determined (e.g. an adjustable array),
8994 an ERROR_MARK node is returned for the size. Otherwise, the
8995 size returned is valid, not necessarily a constant, and not
8996 necessarily converted into the appropriate type as with the
8999 Note that the offset and size expressions are expressed in the
9000 base storage units (usually bits) rather than in the units of
9001 the type of the decl, because two decls with different types
9002 might overlap but with apparently non-overlapping array offsets,
9003 whereas converting the array offsets to consistant offsets will
9004 reveal the overlap. */
9006 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9008 ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
9011 /* The default path is to report a nonexistant decl. */
9017 switch (TREE_CODE (t))
9020 case IDENTIFIER_NODE:
9029 case TRUNC_DIV_EXPR:
9031 case FLOOR_DIV_EXPR:
9032 case ROUND_DIV_EXPR:
9033 case TRUNC_MOD_EXPR:
9035 case FLOOR_MOD_EXPR:
9036 case ROUND_MOD_EXPR:
9038 case EXACT_DIV_EXPR:
9039 case FIX_TRUNC_EXPR:
9041 case FIX_FLOOR_EXPR:
9042 case FIX_ROUND_EXPR:
9056 case BIT_ANDTC_EXPR:
9058 case TRUTH_ANDIF_EXPR:
9059 case TRUTH_ORIF_EXPR:
9060 case TRUTH_AND_EXPR:
9062 case TRUTH_XOR_EXPR:
9063 case TRUTH_NOT_EXPR:
9083 *offset = bitsize_zero_node;
9084 *size = TYPE_SIZE (TREE_TYPE (t));
9089 tree array = TREE_OPERAND (t, 0);
9090 tree element = TREE_OPERAND (t, 1);
9093 if ((array == NULL_TREE)
9094 || (element == NULL_TREE))
9096 *decl = error_mark_node;
9100 ffecom_tree_canonize_ref_ (decl, &init_offset, size,
9102 if ((*decl == NULL_TREE)
9103 || (*decl == error_mark_node))
9106 /* Calculate ((element - base) * NBBY) + init_offset. */
9107 *offset = fold (build (MINUS_EXPR, TREE_TYPE (element),
9109 TYPE_MIN_VALUE (TYPE_DOMAIN
9110 (TREE_TYPE (array)))));
9112 *offset = size_binop (MULT_EXPR,
9113 convert (bitsizetype, *offset),
9114 TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))));
9116 *offset = size_binop (PLUS_EXPR, init_offset, *offset);
9118 *size = TYPE_SIZE (TREE_TYPE (t));
9124 /* Most of this code is to handle references to COMMON. And so
9125 far that is useful only for calling library functions, since
9126 external (user) functions might reference common areas. But
9127 even calling an external function, it's worthwhile to decode
9128 COMMON references because if not storing into COMMON, we don't
9129 want COMMON-based arguments to gratuitously force use of a
9132 *size = TYPE_SIZE (TREE_TYPE (t));
9134 ffecom_tree_canonize_ptr_ (decl, offset,
9135 TREE_OPERAND (t, 0));
9142 case NON_LVALUE_EXPR:
9145 case COND_EXPR: /* More cases than we can handle. */
9147 case REFERENCE_EXPR:
9148 case PREDECREMENT_EXPR:
9149 case PREINCREMENT_EXPR:
9150 case POSTDECREMENT_EXPR:
9151 case POSTINCREMENT_EXPR:
9154 *decl = error_mark_node;
9160 /* Do divide operation appropriate to type of operands. */
9162 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9164 ffecom_tree_divide_ (tree tree_type, tree left, tree right,
9165 tree dest_tree, ffebld dest, bool *dest_used,
9168 if ((left == error_mark_node)
9169 || (right == error_mark_node))
9170 return error_mark_node;
9172 switch (TREE_CODE (tree_type))
9175 return ffecom_2 (TRUNC_DIV_EXPR, tree_type,
9180 if (! optimize_size)
9181 return ffecom_2 (RDIV_EXPR, tree_type,
9187 if (TREE_TYPE (tree_type)
9188 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9189 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9191 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
9193 left = ffecom_1 (ADDR_EXPR,
9194 build_pointer_type (TREE_TYPE (left)),
9196 left = build_tree_list (NULL_TREE, left);
9197 right = ffecom_1 (ADDR_EXPR,
9198 build_pointer_type (TREE_TYPE (right)),
9200 right = build_tree_list (NULL_TREE, right);
9201 TREE_CHAIN (left) = right;
9203 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9204 ffecom_gfrt_kindtype (ix),
9205 ffe_is_f2c_library (),
9208 dest_tree, dest, dest_used,
9209 NULL_TREE, TRUE, hook);
9217 if (TREE_TYPE (TYPE_FIELDS (tree_type))
9218 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9219 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */
9221 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */
9223 left = ffecom_1 (ADDR_EXPR,
9224 build_pointer_type (TREE_TYPE (left)),
9226 left = build_tree_list (NULL_TREE, left);
9227 right = ffecom_1 (ADDR_EXPR,
9228 build_pointer_type (TREE_TYPE (right)),
9230 right = build_tree_list (NULL_TREE, right);
9231 TREE_CHAIN (left) = right;
9233 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9234 ffecom_gfrt_kindtype (ix),
9235 ffe_is_f2c_library (),
9238 dest_tree, dest, dest_used,
9239 NULL_TREE, TRUE, hook);
9244 return ffecom_2 (RDIV_EXPR, tree_type,
9251 /* Build type info for non-dummy variable. */
9253 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9255 ffecom_type_localvar_ (ffesymbol s, ffeinfoBasictype bt,
9264 type = ffecom_tree_type[bt][kt];
9265 if (bt == FFEINFO_basictypeCHARACTER)
9267 hight = build_int_2 (ffesymbol_size (s), 0);
9268 TREE_TYPE (hight) = ffecom_f2c_ftnlen_type_node;
9273 build_range_type (ffecom_f2c_ftnlen_type_node,
9274 ffecom_f2c_ftnlen_one_node,
9276 type = ffecom_check_size_overflow_ (s, type, FALSE);
9279 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
9281 if (type == error_mark_node)
9284 dim = ffebld_head (dl);
9285 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
9287 if (ffebld_left (dim) == NULL)
9288 lowt = integer_one_node;
9290 lowt = ffecom_expr (ffebld_left (dim));
9292 if (TREE_CODE (lowt) != INTEGER_CST)
9293 lowt = variable_size (lowt);
9295 assert (ffebld_right (dim) != NULL);
9296 hight = ffecom_expr (ffebld_right (dim));
9298 if (TREE_CODE (hight) != INTEGER_CST)
9299 hight = variable_size (hight);
9301 type = build_array_type (type,
9302 build_range_type (ffecom_integer_type_node,
9304 type = ffecom_check_size_overflow_ (s, type, FALSE);
9311 /* Build Namelist type. */
9313 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9315 ffecom_type_namelist_ ()
9317 static tree type = NULL_TREE;
9319 if (type == NULL_TREE)
9321 static tree namefield, varsfield, nvarsfield;
9324 vardesctype = ffecom_type_vardesc_ ();
9326 type = make_node (RECORD_TYPE);
9328 vardesctype = build_pointer_type (build_pointer_type (vardesctype));
9330 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9332 varsfield = ffecom_decl_field (type, namefield, "vars", vardesctype);
9333 nvarsfield = ffecom_decl_field (type, varsfield, "nvars",
9336 TYPE_FIELDS (type) = namefield;
9339 ggc_add_tree_root (&type, 1);
9347 /* Build Vardesc type. */
9349 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9351 ffecom_type_vardesc_ ()
9353 static tree type = NULL_TREE;
9354 static tree namefield, addrfield, dimsfield, typefield;
9356 if (type == NULL_TREE)
9358 type = make_node (RECORD_TYPE);
9360 namefield = ffecom_decl_field (type, NULL_TREE, "name",
9362 addrfield = ffecom_decl_field (type, namefield, "addr",
9364 dimsfield = ffecom_decl_field (type, addrfield, "dims",
9365 ffecom_f2c_ptr_to_ftnlen_type_node);
9366 typefield = ffecom_decl_field (type, dimsfield, "type",
9369 TYPE_FIELDS (type) = namefield;
9372 ggc_add_tree_root (&type, 1);
9380 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9382 ffecom_vardesc_ (ffebld expr)
9386 assert (ffebld_op (expr) == FFEBLD_opSYMTER);
9387 s = ffebld_symter (expr);
9389 if (ffesymbol_hook (s).vardesc_tree == NULL_TREE)
9392 tree vardesctype = ffecom_type_vardesc_ ();
9400 static int mynumber = 0;
9402 var = build_decl (VAR_DECL,
9403 ffecom_get_invented_identifier ("__g77_vardesc_%d",
9406 TREE_STATIC (var) = 1;
9407 DECL_INITIAL (var) = error_mark_node;
9409 var = start_decl (var, FALSE);
9411 /* Process inits. */
9413 nameinit = ffecom_build_f2c_string_ ((i = strlen (ffesymbol_text (s)))
9415 ffesymbol_text (s));
9416 TREE_TYPE (nameinit)
9417 = build_type_variant
9420 build_range_type (integer_type_node,
9422 build_int_2 (i, 0))),
9424 TREE_CONSTANT (nameinit) = 1;
9425 TREE_STATIC (nameinit) = 1;
9426 nameinit = ffecom_1 (ADDR_EXPR,
9427 build_pointer_type (TREE_TYPE (nameinit)),
9430 addrinit = ffecom_arg_ptr_to_expr (expr, &typeinit);
9432 dimsinit = ffecom_vardesc_dims_ (s);
9434 if (typeinit == NULL_TREE)
9436 ffeinfoBasictype bt = ffesymbol_basictype (s);
9437 ffeinfoKindtype kt = ffesymbol_kindtype (s);
9438 int tc = ffecom_f2c_typecode (bt, kt);
9441 typeinit = build_int_2 (tc, (tc < 0) ? -1 : 0);
9444 typeinit = ffecom_1 (NEGATE_EXPR, TREE_TYPE (typeinit), typeinit);
9446 varinits = build_tree_list ((field = TYPE_FIELDS (vardesctype)),
9448 TREE_CHAIN (varinits) = build_tree_list ((field = TREE_CHAIN (field)),
9450 TREE_CHAIN (TREE_CHAIN (varinits))
9451 = build_tree_list ((field = TREE_CHAIN (field)), dimsinit);
9452 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (varinits)))
9453 = build_tree_list ((field = TREE_CHAIN (field)), typeinit);
9455 varinits = build (CONSTRUCTOR, vardesctype, NULL_TREE, varinits);
9456 TREE_CONSTANT (varinits) = 1;
9457 TREE_STATIC (varinits) = 1;
9459 finish_decl (var, varinits, FALSE);
9461 var = ffecom_1 (ADDR_EXPR, build_pointer_type (vardesctype), var);
9463 ffesymbol_hook (s).vardesc_tree = var;
9466 return ffesymbol_hook (s).vardesc_tree;
9470 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9472 ffecom_vardesc_array_ (ffesymbol s)
9476 tree item = NULL_TREE;
9479 static int mynumber = 0;
9481 for (i = 0, list = NULL_TREE, b = ffesymbol_namelist (s);
9483 b = ffebld_trail (b), ++i)
9487 t = ffecom_vardesc_ (ffebld_head (b));
9489 if (list == NULL_TREE)
9490 list = item = build_tree_list (NULL_TREE, t);
9493 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9494 item = TREE_CHAIN (item);
9498 item = build_array_type (build_pointer_type (ffecom_type_vardesc_ ()),
9499 build_range_type (integer_type_node,
9501 build_int_2 (i, 0)));
9502 list = build (CONSTRUCTOR, item, NULL_TREE, list);
9503 TREE_CONSTANT (list) = 1;
9504 TREE_STATIC (list) = 1;
9506 var = ffecom_get_invented_identifier ("__g77_vardesc_array_%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);
9517 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9519 ffecom_vardesc_dims_ (ffesymbol s)
9521 if (ffesymbol_dims (s) == NULL)
9522 return convert (ffecom_f2c_ptr_to_ftnlen_type_node,
9530 tree item = NULL_TREE;
9534 tree baseoff = NULL_TREE;
9535 static int mynumber = 0;
9537 numdim = build_int_2 ((int) ffesymbol_rank (s), 0);
9538 TREE_TYPE (numdim) = ffecom_f2c_ftnlen_type_node;
9540 numelem = ffecom_expr (ffesymbol_arraysize (s));
9541 TREE_TYPE (numelem) = ffecom_f2c_ftnlen_type_node;
9544 backlist = NULL_TREE;
9545 for (b = ffesymbol_dims (s), e = ffesymbol_extents (s);
9547 b = ffebld_trail (b), e = ffebld_trail (e))
9553 if (ffebld_trail (b) == NULL)
9557 t = convert (ffecom_f2c_ftnlen_type_node,
9558 ffecom_expr (ffebld_head (e)));
9560 if (list == NULL_TREE)
9561 list = item = build_tree_list (NULL_TREE, t);
9564 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9565 item = TREE_CHAIN (item);
9569 if (ffebld_left (ffebld_head (b)) == NULL)
9570 low = ffecom_integer_one_node;
9572 low = ffecom_expr (ffebld_left (ffebld_head (b)));
9573 low = convert (ffecom_f2c_ftnlen_type_node, low);
9575 back = build_tree_list (low, t);
9576 TREE_CHAIN (back) = backlist;
9580 for (item = backlist; item != NULL_TREE; item = TREE_CHAIN (item))
9582 if (TREE_VALUE (item) == NULL_TREE)
9583 baseoff = TREE_PURPOSE (item);
9585 baseoff = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
9586 TREE_PURPOSE (item),
9587 ffecom_2 (MULT_EXPR,
9588 ffecom_f2c_ftnlen_type_node,
9593 /* backlist now dead, along with all TREE_PURPOSEs on it. */
9595 baseoff = build_tree_list (NULL_TREE, baseoff);
9596 TREE_CHAIN (baseoff) = list;
9598 numelem = build_tree_list (NULL_TREE, numelem);
9599 TREE_CHAIN (numelem) = baseoff;
9601 numdim = build_tree_list (NULL_TREE, numdim);
9602 TREE_CHAIN (numdim) = numelem;
9604 item = build_array_type (ffecom_f2c_ftnlen_type_node,
9605 build_range_type (integer_type_node,
9608 ((int) ffesymbol_rank (s)
9610 list = build (CONSTRUCTOR, item, NULL_TREE, numdim);
9611 TREE_CONSTANT (list) = 1;
9612 TREE_STATIC (list) = 1;
9614 var = ffecom_get_invented_identifier ("__g77_dims_%d", mynumber++);
9615 var = build_decl (VAR_DECL, var, item);
9616 TREE_STATIC (var) = 1;
9617 DECL_INITIAL (var) = error_mark_node;
9618 var = start_decl (var, FALSE);
9619 finish_decl (var, list, FALSE);
9621 var = ffecom_1 (ADDR_EXPR, build_pointer_type (item), var);
9628 /* Essentially does a "fold (build1 (code, type, node))" while checking
9629 for certain housekeeping things.
9631 NOTE: for building an ADDR_EXPR around a FUNCTION_DECL, use
9632 ffecom_1_fn instead. */
9634 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9636 ffecom_1 (enum tree_code code, tree type, tree node)
9640 if ((node == error_mark_node)
9641 || (type == error_mark_node))
9642 return error_mark_node;
9644 if (code == ADDR_EXPR)
9646 if (!mark_addressable (node))
9647 assert ("can't mark_addressable this node!" == NULL);
9650 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
9655 item = build (COMPONENT_REF, type, node, TYPE_FIELDS (TREE_TYPE (node)));
9659 item = build (COMPONENT_REF, type, node, TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (node))));
9664 if (TREE_CODE (type) != RECORD_TYPE)
9666 item = build1 (code, type, node);
9669 node = ffecom_stabilize_aggregate_ (node);
9670 realtype = TREE_TYPE (TYPE_FIELDS (type));
9672 ffecom_2 (COMPLEX_EXPR, type,
9673 ffecom_1 (NEGATE_EXPR, realtype,
9674 ffecom_1 (REALPART_EXPR, realtype,
9676 ffecom_1 (NEGATE_EXPR, realtype,
9677 ffecom_1 (IMAGPART_EXPR, realtype,
9682 item = build1 (code, type, node);
9686 if (TREE_SIDE_EFFECTS (node))
9687 TREE_SIDE_EFFECTS (item) = 1;
9688 if ((code == ADDR_EXPR) && staticp (node))
9689 TREE_CONSTANT (item) = 1;
9694 /* Like ffecom_1 (ADDR_EXPR, TREE_TYPE (node), node), except
9695 handles TREE_CODE (node) == FUNCTION_DECL. In particular,
9696 does not set TREE_ADDRESSABLE (because calling an inline
9697 function does not mean the function needs to be separately
9700 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9702 ffecom_1_fn (tree node)
9707 if (node == error_mark_node)
9708 return error_mark_node;
9710 type = build_type_variant (TREE_TYPE (node),
9711 TREE_READONLY (node),
9712 TREE_THIS_VOLATILE (node));
9713 item = build1 (ADDR_EXPR,
9714 build_pointer_type (type), node);
9715 if (TREE_SIDE_EFFECTS (node))
9716 TREE_SIDE_EFFECTS (item) = 1;
9718 TREE_CONSTANT (item) = 1;
9723 /* Essentially does a "fold (build (code, type, node1, node2))" while
9724 checking for certain housekeeping things. */
9726 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9728 ffecom_2 (enum tree_code code, tree type, tree node1,
9733 if ((node1 == error_mark_node)
9734 || (node2 == error_mark_node)
9735 || (type == error_mark_node))
9736 return error_mark_node;
9738 switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
9740 tree a, b, c, d, realtype;
9743 assert ("no CONJ_EXPR support yet" == NULL);
9744 return error_mark_node;
9747 item = build_tree_list (TYPE_FIELDS (type), node1);
9748 TREE_CHAIN (item) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), node2);
9749 item = build (CONSTRUCTOR, type, NULL_TREE, item);
9753 if (TREE_CODE (type) != RECORD_TYPE)
9755 item = build (code, type, node1, node2);
9758 node1 = ffecom_stabilize_aggregate_ (node1);
9759 node2 = ffecom_stabilize_aggregate_ (node2);
9760 realtype = TREE_TYPE (TYPE_FIELDS (type));
9762 ffecom_2 (COMPLEX_EXPR, type,
9763 ffecom_2 (PLUS_EXPR, realtype,
9764 ffecom_1 (REALPART_EXPR, realtype,
9766 ffecom_1 (REALPART_EXPR, realtype,
9768 ffecom_2 (PLUS_EXPR, realtype,
9769 ffecom_1 (IMAGPART_EXPR, realtype,
9771 ffecom_1 (IMAGPART_EXPR, realtype,
9776 if (TREE_CODE (type) != RECORD_TYPE)
9778 item = build (code, type, node1, node2);
9781 node1 = ffecom_stabilize_aggregate_ (node1);
9782 node2 = ffecom_stabilize_aggregate_ (node2);
9783 realtype = TREE_TYPE (TYPE_FIELDS (type));
9785 ffecom_2 (COMPLEX_EXPR, type,
9786 ffecom_2 (MINUS_EXPR, realtype,
9787 ffecom_1 (REALPART_EXPR, realtype,
9789 ffecom_1 (REALPART_EXPR, realtype,
9791 ffecom_2 (MINUS_EXPR, realtype,
9792 ffecom_1 (IMAGPART_EXPR, realtype,
9794 ffecom_1 (IMAGPART_EXPR, realtype,
9799 if (TREE_CODE (type) != RECORD_TYPE)
9801 item = build (code, type, node1, node2);
9804 node1 = ffecom_stabilize_aggregate_ (node1);
9805 node2 = ffecom_stabilize_aggregate_ (node2);
9806 realtype = TREE_TYPE (TYPE_FIELDS (type));
9807 a = save_expr (ffecom_1 (REALPART_EXPR, realtype,
9809 b = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
9811 c = save_expr (ffecom_1 (REALPART_EXPR, realtype,
9813 d = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
9816 ffecom_2 (COMPLEX_EXPR, type,
9817 ffecom_2 (MINUS_EXPR, realtype,
9818 ffecom_2 (MULT_EXPR, realtype,
9821 ffecom_2 (MULT_EXPR, realtype,
9824 ffecom_2 (PLUS_EXPR, realtype,
9825 ffecom_2 (MULT_EXPR, realtype,
9828 ffecom_2 (MULT_EXPR, realtype,
9834 if ((TREE_CODE (node1) != RECORD_TYPE)
9835 && (TREE_CODE (node2) != RECORD_TYPE))
9837 item = build (code, type, node1, node2);
9840 assert (TREE_CODE (node1) == RECORD_TYPE);
9841 assert (TREE_CODE (node2) == RECORD_TYPE);
9842 node1 = ffecom_stabilize_aggregate_ (node1);
9843 node2 = ffecom_stabilize_aggregate_ (node2);
9844 realtype = TREE_TYPE (TYPE_FIELDS (type));
9846 ffecom_2 (TRUTH_ANDIF_EXPR, type,
9847 ffecom_2 (code, type,
9848 ffecom_1 (REALPART_EXPR, realtype,
9850 ffecom_1 (REALPART_EXPR, realtype,
9852 ffecom_2 (code, type,
9853 ffecom_1 (IMAGPART_EXPR, realtype,
9855 ffecom_1 (IMAGPART_EXPR, realtype,
9860 if ((TREE_CODE (node1) != RECORD_TYPE)
9861 && (TREE_CODE (node2) != RECORD_TYPE))
9863 item = build (code, type, node1, node2);
9866 assert (TREE_CODE (node1) == RECORD_TYPE);
9867 assert (TREE_CODE (node2) == RECORD_TYPE);
9868 node1 = ffecom_stabilize_aggregate_ (node1);
9869 node2 = ffecom_stabilize_aggregate_ (node2);
9870 realtype = TREE_TYPE (TYPE_FIELDS (type));
9872 ffecom_2 (TRUTH_ORIF_EXPR, type,
9873 ffecom_2 (code, type,
9874 ffecom_1 (REALPART_EXPR, realtype,
9876 ffecom_1 (REALPART_EXPR, realtype,
9878 ffecom_2 (code, type,
9879 ffecom_1 (IMAGPART_EXPR, realtype,
9881 ffecom_1 (IMAGPART_EXPR, realtype,
9886 item = build (code, type, node1, node2);
9890 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2))
9891 TREE_SIDE_EFFECTS (item) = 1;
9896 /* ffecom_2pass_advise_entrypoint -- Advise that there's this entrypoint
9898 ffesymbol s; // the ENTRY point itself
9899 if (ffecom_2pass_advise_entrypoint(s))
9900 // the ENTRY point has been accepted
9902 Does whatever compiler needs to do when it learns about the entrypoint,
9903 like determine the return type of the master function, count the
9904 number of entrypoints, etc. Returns FALSE if the return type is
9905 not compatible with the return type(s) of other entrypoint(s).
9907 NOTE: for every call to this fn that returns TRUE, _do_entrypoint must
9908 later (after _finish_progunit) be called with the same entrypoint(s)
9909 as passed to this fn for which TRUE was returned.
9912 Return FALSE if the return type conflicts with previous entrypoints. */
9914 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9916 ffecom_2pass_advise_entrypoint (ffesymbol entry)
9918 ffebld list; /* opITEM. */
9919 ffebld mlist; /* opITEM. */
9920 ffebld plist; /* opITEM. */
9921 ffebld arg; /* ffebld_head(opITEM). */
9922 ffebld item; /* opITEM. */
9923 ffesymbol s; /* ffebld_symter(arg). */
9924 ffeinfoBasictype bt = ffesymbol_basictype (entry);
9925 ffeinfoKindtype kt = ffesymbol_kindtype (entry);
9926 ffetargetCharacterSize size = ffesymbol_size (entry);
9929 if (ffecom_num_entrypoints_ == 0)
9930 { /* First entrypoint, make list of main
9931 arglist's dummies. */
9932 assert (ffecom_primary_entry_ != NULL);
9934 ffecom_master_bt_ = ffesymbol_basictype (ffecom_primary_entry_);
9935 ffecom_master_kt_ = ffesymbol_kindtype (ffecom_primary_entry_);
9936 ffecom_master_size_ = ffesymbol_size (ffecom_primary_entry_);
9938 for (plist = NULL, list = ffesymbol_dummyargs (ffecom_primary_entry_);
9940 list = ffebld_trail (list))
9942 arg = ffebld_head (list);
9943 if (ffebld_op (arg) != FFEBLD_opSYMTER)
9944 continue; /* Alternate return or some such thing. */
9945 item = ffebld_new_item (arg, NULL);
9947 ffecom_master_arglist_ = item;
9949 ffebld_set_trail (plist, item);
9954 /* If necessary, scan entry arglist for alternate returns. Do this scan
9955 apparently redundantly (it's done below to UNIONize the arglists) so
9956 that we don't complain about RETURN 1 if an offending ENTRY is the only
9957 one with an alternate return. */
9959 if (!ffecom_is_altreturning_)
9961 for (list = ffesymbol_dummyargs (entry);
9963 list = ffebld_trail (list))
9965 arg = ffebld_head (list);
9966 if (ffebld_op (arg) == FFEBLD_opSTAR)
9968 ffecom_is_altreturning_ = TRUE;
9974 /* Now check type compatibility. */
9976 switch (ffecom_master_bt_)
9978 case FFEINFO_basictypeNONE:
9979 ok = (bt != FFEINFO_basictypeCHARACTER);
9982 case FFEINFO_basictypeCHARACTER:
9984 = (bt == FFEINFO_basictypeCHARACTER)
9985 && (kt == ffecom_master_kt_)
9986 && (size == ffecom_master_size_);
9989 case FFEINFO_basictypeANY:
9990 return FALSE; /* Just don't bother. */
9993 if (bt == FFEINFO_basictypeCHARACTER)
9999 if ((bt != ffecom_master_bt_) || (kt != ffecom_master_kt_))
10001 ffecom_master_bt_ = FFEINFO_basictypeNONE;
10002 ffecom_master_kt_ = FFEINFO_kindtypeNONE;
10009 ffebad_start (FFEBAD_ENTRY_CONFLICTS);
10010 ffest_ffebad_here_current_stmt (0);
10012 return FALSE; /* Can't handle entrypoint. */
10015 /* Entrypoint type compatible with previous types. */
10017 ++ffecom_num_entrypoints_;
10019 /* Master-arg-list = UNION(Master-arg-list,entry-arg-list). */
10021 for (list = ffesymbol_dummyargs (entry);
10023 list = ffebld_trail (list))
10025 arg = ffebld_head (list);
10026 if (ffebld_op (arg) != FFEBLD_opSYMTER)
10027 continue; /* Alternate return or some such thing. */
10028 s = ffebld_symter (arg);
10029 for (plist = NULL, mlist = ffecom_master_arglist_;
10031 plist = mlist, mlist = ffebld_trail (mlist))
10032 { /* plist points to previous item for easy
10033 appending of arg. */
10034 if (ffebld_symter (ffebld_head (mlist)) == s)
10035 break; /* Already have this arg in the master list. */
10038 continue; /* Already have this arg in the master list. */
10040 /* Append this arg to the master list. */
10042 item = ffebld_new_item (arg, NULL);
10044 ffecom_master_arglist_ = item;
10046 ffebld_set_trail (plist, item);
10053 /* ffecom_2pass_do_entrypoint -- Do compilation of entrypoint
10055 ffesymbol s; // the ENTRY point itself
10056 ffecom_2pass_do_entrypoint(s);
10058 Does whatever compiler needs to do to make the entrypoint actually
10059 happen. Must be called for each entrypoint after
10060 ffecom_finish_progunit is called. */
10062 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10064 ffecom_2pass_do_entrypoint (ffesymbol entry)
10066 static int mfn_num = 0;
10067 static int ent_num;
10069 if (mfn_num != ffecom_num_fns_)
10070 { /* First entrypoint for this program unit. */
10072 mfn_num = ffecom_num_fns_;
10073 ffecom_do_entry_ (ffecom_primary_entry_, 0);
10078 --ffecom_num_entrypoints_;
10080 ffecom_do_entry_ (entry, ent_num);
10085 /* Essentially does a "fold (build (code, type, node1, node2))" while
10086 checking for certain housekeeping things. Always sets
10087 TREE_SIDE_EFFECTS. */
10089 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10091 ffecom_2s (enum tree_code code, tree type, tree node1,
10096 if ((node1 == error_mark_node)
10097 || (node2 == error_mark_node)
10098 || (type == error_mark_node))
10099 return error_mark_node;
10101 item = build (code, type, node1, node2);
10102 TREE_SIDE_EFFECTS (item) = 1;
10103 return fold (item);
10107 /* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10108 checking for certain housekeeping things. */
10110 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10112 ffecom_3 (enum tree_code code, tree type, tree node1,
10113 tree node2, tree node3)
10117 if ((node1 == error_mark_node)
10118 || (node2 == error_mark_node)
10119 || (node3 == error_mark_node)
10120 || (type == error_mark_node))
10121 return error_mark_node;
10123 item = build (code, type, node1, node2, node3);
10124 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2)
10125 || (node3 != NULL_TREE && TREE_SIDE_EFFECTS (node3)))
10126 TREE_SIDE_EFFECTS (item) = 1;
10127 return fold (item);
10131 /* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10132 checking for certain housekeeping things. Always sets
10133 TREE_SIDE_EFFECTS. */
10135 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10137 ffecom_3s (enum tree_code code, tree type, tree node1,
10138 tree node2, tree node3)
10142 if ((node1 == error_mark_node)
10143 || (node2 == error_mark_node)
10144 || (node3 == error_mark_node)
10145 || (type == error_mark_node))
10146 return error_mark_node;
10148 item = build (code, type, node1, node2, node3);
10149 TREE_SIDE_EFFECTS (item) = 1;
10150 return fold (item);
10155 /* ffecom_arg_expr -- Transform argument expr into gcc tree
10157 See use by ffecom_list_expr.
10159 If expression is NULL, returns an integer zero tree. If it is not
10160 a CHARACTER expression, returns whatever ffecom_expr
10161 returns and sets the length return value to NULL_TREE. Otherwise
10162 generates code to evaluate the character expression, returns the proper
10163 pointer to the result, but does NOT set the length return value to a tree
10164 that specifies the length of the result. (In other words, the length
10165 variable is always set to NULL_TREE, because a length is never passed.)
10168 Don't set returned length, since nobody needs it (yet; someday if
10169 we allow CHARACTER*(*) dummies to statement functions, we'll need
10172 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10174 ffecom_arg_expr (ffebld expr, tree *length)
10178 *length = NULL_TREE;
10181 return integer_zero_node;
10183 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10184 return ffecom_expr (expr);
10186 return ffecom_arg_ptr_to_expr (expr, &ign);
10190 /* Transform expression into constant argument-pointer-to-expression tree.
10192 If the expression can be transformed into a argument-pointer-to-expression
10193 tree that is constant, that is done, and the tree returned. Else
10194 NULL_TREE is returned.
10196 That way, a caller can attempt to provide compile-time initialization
10197 of a variable and, if that fails, *then* choose to start a new block
10198 and resort to using temporaries, as appropriate. */
10201 ffecom_arg_ptr_to_const_expr (ffebld expr, tree *length)
10204 return integer_zero_node;
10206 if (ffebld_op (expr) == FFEBLD_opANY)
10209 *length = error_mark_node;
10210 return error_mark_node;
10213 if (ffebld_arity (expr) == 0
10214 && (ffebld_op (expr) != FFEBLD_opSYMTER
10215 || ffebld_where (expr) == FFEINFO_whereCOMMON
10216 || ffebld_where (expr) == FFEINFO_whereGLOBAL
10217 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
10221 t = ffecom_arg_ptr_to_expr (expr, length);
10222 assert (TREE_CONSTANT (t));
10223 assert (! length || TREE_CONSTANT (*length));
10228 && ffebld_size (expr) != FFETARGET_charactersizeNONE)
10229 *length = build_int_2 (ffebld_size (expr), 0);
10231 *length = NULL_TREE;
10235 /* ffecom_arg_ptr_to_expr -- Transform argument expr into gcc tree
10237 See use by ffecom_list_ptr_to_expr.
10239 If expression is NULL, returns an integer zero tree. If it is not
10240 a CHARACTER expression, returns whatever ffecom_ptr_to_expr
10241 returns and sets the length return value to NULL_TREE. Otherwise
10242 generates code to evaluate the character expression, returns the proper
10243 pointer to the result, AND sets the length return value to a tree that
10244 specifies the length of the result.
10246 If the length argument is NULL, this is a slightly special
10247 case of building a FORMAT expression, that is, an expression that
10248 will be used at run time without regard to length. For the current
10249 implementation, which uses the libf2c library, this means it is nice
10250 to append a null byte to the end of the expression, where feasible,
10251 to make sure any diagnostic about the FORMAT string terminates at
10254 For now, treat %REF(char-expr) as the same as char-expr with a NULL
10255 length argument. This might even be seen as a feature, if a null
10256 byte can always be appended. */
10258 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10260 ffecom_arg_ptr_to_expr (ffebld expr, tree *length)
10264 ffecomConcatList_ catlist;
10266 if (length != NULL)
10267 *length = NULL_TREE;
10270 return integer_zero_node;
10272 switch (ffebld_op (expr))
10274 case FFEBLD_opPERCENT_VAL:
10275 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10276 return ffecom_expr (ffebld_left (expr));
10281 temp_exp = ffecom_arg_ptr_to_expr (ffebld_left (expr), &temp_length);
10282 if (temp_exp == error_mark_node)
10283 return error_mark_node;
10285 return ffecom_1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (temp_exp)),
10289 case FFEBLD_opPERCENT_REF:
10290 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10291 return ffecom_ptr_to_expr (ffebld_left (expr));
10292 if (length != NULL)
10294 ign_length = NULL_TREE;
10295 length = &ign_length;
10297 expr = ffebld_left (expr);
10300 case FFEBLD_opPERCENT_DESCR:
10301 switch (ffeinfo_basictype (ffebld_info (expr)))
10303 #ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10304 case FFEINFO_basictypeHOLLERITH:
10306 case FFEINFO_basictypeCHARACTER:
10307 break; /* Passed by descriptor anyway. */
10310 item = ffecom_ptr_to_expr (expr);
10311 if (item != error_mark_node)
10312 *length = TYPE_SIZE (TREE_TYPE (TREE_TYPE (item)));
10321 #ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10322 if ((ffeinfo_basictype (ffebld_info (expr)) == FFEINFO_basictypeHOLLERITH)
10323 && (length != NULL))
10324 { /* Pass Hollerith by descriptor. */
10325 ffetargetHollerith h;
10327 assert (ffebld_op (expr) == FFEBLD_opCONTER);
10328 h = ffebld_cu_val_hollerith (ffebld_constant_union
10329 (ffebld_conter (expr)));
10331 = build_int_2 (h.length, 0);
10332 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10336 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10337 return ffecom_ptr_to_expr (expr);
10339 assert (ffeinfo_kindtype (ffebld_info (expr))
10340 == FFEINFO_kindtypeCHARACTER1);
10342 while (ffebld_op (expr) == FFEBLD_opPAREN)
10343 expr = ffebld_left (expr);
10345 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
10346 switch (ffecom_concat_list_count_ (catlist))
10348 case 0: /* Shouldn't happen, but in case it does... */
10349 if (length != NULL)
10351 *length = ffecom_f2c_ftnlen_zero_node;
10352 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10354 ffecom_concat_list_kill_ (catlist);
10355 return null_pointer_node;
10357 case 1: /* The (fairly) easy case. */
10358 if (length == NULL)
10359 ffecom_char_args_with_null_ (&item, &ign_length,
10360 ffecom_concat_list_expr_ (catlist, 0));
10362 ffecom_char_args_ (&item, length,
10363 ffecom_concat_list_expr_ (catlist, 0));
10364 ffecom_concat_list_kill_ (catlist);
10365 assert (item != NULL_TREE);
10368 default: /* Must actually concatenate things. */
10373 int count = ffecom_concat_list_count_ (catlist);
10384 ffetargetCharacterSize sz;
10386 sz = ffecom_concat_list_maxlen_ (catlist);
10388 assert (sz != FFETARGET_charactersizeNONE);
10393 = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
10394 FFETARGET_charactersizeNONE, count, TRUE);
10397 = ffecom_push_tempvar (ffecom_f2c_address_type_node,
10398 FFETARGET_charactersizeNONE, count, TRUE);
10399 temporary = ffecom_push_tempvar (char_type_node,
10405 hook = ffebld_nonter_hook (expr);
10407 assert (TREE_CODE (hook) == TREE_VEC);
10408 assert (TREE_VEC_LENGTH (hook) == 3);
10409 length_array = lengths = TREE_VEC_ELT (hook, 0);
10410 item_array = items = TREE_VEC_ELT (hook, 1);
10411 temporary = TREE_VEC_ELT (hook, 2);
10415 known_length = ffecom_f2c_ftnlen_zero_node;
10417 for (i = 0; i < count; ++i)
10420 && (length == NULL))
10421 ffecom_char_args_with_null_ (&citem, &clength,
10422 ffecom_concat_list_expr_ (catlist, i));
10424 ffecom_char_args_ (&citem, &clength,
10425 ffecom_concat_list_expr_ (catlist, i));
10426 if ((citem == error_mark_node)
10427 || (clength == error_mark_node))
10429 ffecom_concat_list_kill_ (catlist);
10430 *length = error_mark_node;
10431 return error_mark_node;
10435 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
10436 ffecom_modify (void_type_node,
10437 ffecom_2 (ARRAY_REF,
10438 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
10440 build_int_2 (i, 0)),
10443 clength = ffecom_save_tree (clength);
10444 if (length != NULL)
10446 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
10450 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
10451 ffecom_modify (void_type_node,
10452 ffecom_2 (ARRAY_REF,
10453 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
10455 build_int_2 (i, 0)),
10460 temporary = ffecom_1 (ADDR_EXPR,
10461 build_pointer_type (TREE_TYPE (temporary)),
10464 item = build_tree_list (NULL_TREE, temporary);
10466 = build_tree_list (NULL_TREE,
10467 ffecom_1 (ADDR_EXPR,
10468 build_pointer_type (TREE_TYPE (items)),
10470 TREE_CHAIN (TREE_CHAIN (item))
10471 = build_tree_list (NULL_TREE,
10472 ffecom_1 (ADDR_EXPR,
10473 build_pointer_type (TREE_TYPE (lengths)),
10475 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
10478 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
10479 convert (ffecom_f2c_ftnlen_type_node,
10480 build_int_2 (count, 0))));
10481 num = build_int_2 (sz, 0);
10482 TREE_TYPE (num) = ffecom_f2c_ftnlen_type_node;
10483 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item))))
10484 = build_tree_list (NULL_TREE, num);
10486 item = ffecom_call_gfrt (FFECOM_gfrtCAT, item, NULL_TREE);
10487 TREE_SIDE_EFFECTS (item) = 1;
10488 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (temporary),
10492 if (length != NULL)
10493 *length = known_length;
10496 ffecom_concat_list_kill_ (catlist);
10497 assert (item != NULL_TREE);
10502 /* Generate call to run-time function.
10504 The first arg is the GNU Fortran Run-Time function index, the second
10505 arg is the list of arguments to pass to it. Returned is the expression
10506 (WITHOUT TREE_SIDE_EFFECTS set!) that makes the call and returns the
10507 result (which may be void). */
10509 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10511 ffecom_call_gfrt (ffecomGfrt ix, tree args, tree hook)
10513 return ffecom_call_ (ffecom_gfrt_tree_ (ix),
10514 ffecom_gfrt_kindtype (ix),
10515 ffe_is_f2c_library () && ffecom_gfrt_complex_[ix],
10516 NULL_TREE, args, NULL_TREE, NULL,
10517 NULL, NULL_TREE, TRUE, hook);
10521 /* Transform constant-union to tree. */
10523 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10525 ffecom_constantunion (ffebldConstantUnion *cu, ffeinfoBasictype bt,
10526 ffeinfoKindtype kt, tree tree_type)
10532 case FFEINFO_basictypeINTEGER:
10538 #if FFETARGET_okINTEGER1
10539 case FFEINFO_kindtypeINTEGER1:
10540 val = ffebld_cu_val_integer1 (*cu);
10544 #if FFETARGET_okINTEGER2
10545 case FFEINFO_kindtypeINTEGER2:
10546 val = ffebld_cu_val_integer2 (*cu);
10550 #if FFETARGET_okINTEGER3
10551 case FFEINFO_kindtypeINTEGER3:
10552 val = ffebld_cu_val_integer3 (*cu);
10556 #if FFETARGET_okINTEGER4
10557 case FFEINFO_kindtypeINTEGER4:
10558 val = ffebld_cu_val_integer4 (*cu);
10563 assert ("bad INTEGER constant kind type" == NULL);
10564 /* Fall through. */
10565 case FFEINFO_kindtypeANY:
10566 return error_mark_node;
10568 item = build_int_2 (val, (val < 0) ? -1 : 0);
10569 TREE_TYPE (item) = tree_type;
10573 case FFEINFO_basictypeLOGICAL:
10579 #if FFETARGET_okLOGICAL1
10580 case FFEINFO_kindtypeLOGICAL1:
10581 val = ffebld_cu_val_logical1 (*cu);
10585 #if FFETARGET_okLOGICAL2
10586 case FFEINFO_kindtypeLOGICAL2:
10587 val = ffebld_cu_val_logical2 (*cu);
10591 #if FFETARGET_okLOGICAL3
10592 case FFEINFO_kindtypeLOGICAL3:
10593 val = ffebld_cu_val_logical3 (*cu);
10597 #if FFETARGET_okLOGICAL4
10598 case FFEINFO_kindtypeLOGICAL4:
10599 val = ffebld_cu_val_logical4 (*cu);
10604 assert ("bad LOGICAL constant kind type" == NULL);
10605 /* Fall through. */
10606 case FFEINFO_kindtypeANY:
10607 return error_mark_node;
10609 item = build_int_2 (val, (val < 0) ? -1 : 0);
10610 TREE_TYPE (item) = tree_type;
10614 case FFEINFO_basictypeREAL:
10616 REAL_VALUE_TYPE val;
10620 #if FFETARGET_okREAL1
10621 case FFEINFO_kindtypeREAL1:
10622 val = ffetarget_value_real1 (ffebld_cu_val_real1 (*cu));
10626 #if FFETARGET_okREAL2
10627 case FFEINFO_kindtypeREAL2:
10628 val = ffetarget_value_real2 (ffebld_cu_val_real2 (*cu));
10632 #if FFETARGET_okREAL3
10633 case FFEINFO_kindtypeREAL3:
10634 val = ffetarget_value_real3 (ffebld_cu_val_real3 (*cu));
10638 #if FFETARGET_okREAL4
10639 case FFEINFO_kindtypeREAL4:
10640 val = ffetarget_value_real4 (ffebld_cu_val_real4 (*cu));
10645 assert ("bad REAL constant kind type" == NULL);
10646 /* Fall through. */
10647 case FFEINFO_kindtypeANY:
10648 return error_mark_node;
10650 item = build_real (tree_type, val);
10654 case FFEINFO_basictypeCOMPLEX:
10656 REAL_VALUE_TYPE real;
10657 REAL_VALUE_TYPE imag;
10658 tree el_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
10662 #if FFETARGET_okCOMPLEX1
10663 case FFEINFO_kindtypeREAL1:
10664 real = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).real);
10665 imag = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).imaginary);
10669 #if FFETARGET_okCOMPLEX2
10670 case FFEINFO_kindtypeREAL2:
10671 real = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).real);
10672 imag = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).imaginary);
10676 #if FFETARGET_okCOMPLEX3
10677 case FFEINFO_kindtypeREAL3:
10678 real = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).real);
10679 imag = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).imaginary);
10683 #if FFETARGET_okCOMPLEX4
10684 case FFEINFO_kindtypeREAL4:
10685 real = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).real);
10686 imag = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).imaginary);
10691 assert ("bad REAL constant kind type" == NULL);
10692 /* Fall through. */
10693 case FFEINFO_kindtypeANY:
10694 return error_mark_node;
10696 item = ffecom_build_complex_constant_ (tree_type,
10697 build_real (el_type, real),
10698 build_real (el_type, imag));
10702 case FFEINFO_basictypeCHARACTER:
10703 { /* Happens only in DATA and similar contexts. */
10704 ffetargetCharacter1 val;
10708 #if FFETARGET_okCHARACTER1
10709 case FFEINFO_kindtypeLOGICAL1:
10710 val = ffebld_cu_val_character1 (*cu);
10715 assert ("bad CHARACTER constant kind type" == NULL);
10716 /* Fall through. */
10717 case FFEINFO_kindtypeANY:
10718 return error_mark_node;
10720 item = build_string (ffetarget_length_character1 (val),
10721 ffetarget_text_character1 (val));
10723 = build_type_variant (build_array_type (char_type_node,
10725 (integer_type_node,
10728 (ffetarget_length_character1
10734 case FFEINFO_basictypeHOLLERITH:
10736 ffetargetHollerith h;
10738 h = ffebld_cu_val_hollerith (*cu);
10740 /* If not at least as wide as default INTEGER, widen it. */
10741 if (h.length >= FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE)
10742 item = build_string (h.length, h.text);
10745 char str[FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE];
10747 memcpy (str, h.text, h.length);
10748 memset (&str[h.length], ' ',
10749 FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE
10751 item = build_string (FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE,
10755 = build_type_variant (build_array_type (char_type_node,
10757 (integer_type_node,
10765 case FFEINFO_basictypeTYPELESS:
10767 ffetargetInteger1 ival;
10768 ffetargetTypeless tless;
10771 tless = ffebld_cu_val_typeless (*cu);
10772 error = ffetarget_convert_integer1_typeless (&ival, tless);
10773 assert (error == FFEBAD);
10775 item = build_int_2 ((int) ival, 0);
10780 assert ("not yet on constant type" == NULL);
10781 /* Fall through. */
10782 case FFEINFO_basictypeANY:
10783 return error_mark_node;
10786 TREE_CONSTANT (item) = 1;
10793 /* Transform expression into constant tree.
10795 If the expression can be transformed into a tree that is constant,
10796 that is done, and the tree returned. Else NULL_TREE is returned.
10798 That way, a caller can attempt to provide compile-time initialization
10799 of a variable and, if that fails, *then* choose to start a new block
10800 and resort to using temporaries, as appropriate. */
10803 ffecom_const_expr (ffebld expr)
10806 return integer_zero_node;
10808 if (ffebld_op (expr) == FFEBLD_opANY)
10809 return error_mark_node;
10811 if (ffebld_arity (expr) == 0
10812 && (ffebld_op (expr) != FFEBLD_opSYMTER
10814 /* ~~Enable once common/equivalence is handled properly? */
10815 || ffebld_where (expr) == FFEINFO_whereCOMMON
10817 || ffebld_where (expr) == FFEINFO_whereGLOBAL
10818 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
10822 t = ffecom_expr (expr);
10823 assert (TREE_CONSTANT (t));
10830 /* Handy way to make a field in a struct/union. */
10832 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10834 ffecom_decl_field (tree context, tree prevfield,
10835 const char *name, tree type)
10839 field = build_decl (FIELD_DECL, get_identifier (name), type);
10840 DECL_CONTEXT (field) = context;
10841 DECL_ALIGN (field) = 0;
10842 DECL_USER_ALIGN (field) = 0;
10843 if (prevfield != NULL_TREE)
10844 TREE_CHAIN (prevfield) = field;
10852 ffecom_close_include (FILE *f)
10854 #if FFECOM_GCC_INCLUDE
10855 ffecom_close_include_ (f);
10860 ffecom_decode_include_option (char *spec)
10862 #if FFECOM_GCC_INCLUDE
10863 return ffecom_decode_include_option_ (spec);
10869 /* End a compound statement (block). */
10871 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10873 ffecom_end_compstmt (void)
10875 return bison_rule_compstmt_ ();
10877 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
10879 /* ffecom_end_transition -- Perform end transition on all symbols
10881 ffecom_end_transition();
10883 Calls ffecom_sym_end_transition for each global and local symbol. */
10886 ffecom_end_transition ()
10888 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10892 if (ffe_is_ffedebug ())
10893 fprintf (dmpout, "; end_stmt_transition\n");
10895 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10896 ffecom_list_blockdata_ = NULL;
10897 ffecom_list_common_ = NULL;
10900 ffesymbol_drive (ffecom_sym_end_transition);
10901 if (ffe_is_ffedebug ())
10903 ffestorag_report ();
10904 #if FFECOM_targetCURRENT == FFECOM_targetFFE
10905 ffesymbol_report_all ();
10909 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10910 ffecom_start_progunit_ ();
10912 for (item = ffecom_list_blockdata_;
10914 item = ffebld_trail (item))
10921 static int number = 0;
10923 callee = ffebld_head (item);
10924 s = ffebld_symter (callee);
10925 t = ffesymbol_hook (s).decl_tree;
10926 if (t == NULL_TREE)
10928 s = ffecom_sym_transform_ (s);
10929 t = ffesymbol_hook (s).decl_tree;
10932 dt = build_pointer_type (TREE_TYPE (t));
10934 var = build_decl (VAR_DECL,
10935 ffecom_get_invented_identifier ("__g77_forceload_%d",
10938 DECL_EXTERNAL (var) = 0;
10939 TREE_STATIC (var) = 1;
10940 TREE_PUBLIC (var) = 0;
10941 DECL_INITIAL (var) = error_mark_node;
10942 TREE_USED (var) = 1;
10944 var = start_decl (var, FALSE);
10946 t = ffecom_1 (ADDR_EXPR, dt, t);
10948 finish_decl (var, t, FALSE);
10951 /* This handles any COMMON areas that weren't referenced but have, for
10952 example, important initial data. */
10954 for (item = ffecom_list_common_;
10956 item = ffebld_trail (item))
10957 ffecom_transform_common_ (ffebld_symter (ffebld_head (item)));
10959 ffecom_list_common_ = NULL;
10963 /* ffecom_exec_transition -- Perform exec transition on all symbols
10965 ffecom_exec_transition();
10967 Calls ffecom_sym_exec_transition for each global and local symbol.
10968 Make sure error updating not inhibited. */
10971 ffecom_exec_transition ()
10975 if (ffe_is_ffedebug ())
10976 fprintf (dmpout, "; exec_stmt_transition\n");
10978 inhibited = ffebad_inhibit ();
10979 ffebad_set_inhibit (FALSE);
10981 ffesymbol_drive (ffecom_sym_exec_transition); /* Don't retract! */
10982 ffeequiv_exec_transition (); /* Handle all pending EQUIVALENCEs. */
10983 if (ffe_is_ffedebug ())
10985 ffestorag_report ();
10986 #if FFECOM_targetCURRENT == FFECOM_targetFFE
10987 ffesymbol_report_all ();
10992 ffebad_set_inhibit (TRUE);
10995 /* Handle assignment statement.
10997 Convert dest and source using ffecom_expr, then join them
10998 with an ASSIGN op and pass the whole thing to expand_expr_stmt. */
11000 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11002 ffecom_expand_let_stmt (ffebld dest, ffebld source)
11009 if (ffeinfo_basictype (ffebld_info (dest)) != FFEINFO_basictypeCHARACTER)
11014 /* This attempts to replicate the test below, but must not be
11015 true when the test below is false. (Always err on the side
11016 of creating unused temporaries, to avoid ICEs.) */
11017 if (ffebld_op (dest) != FFEBLD_opSYMTER
11018 || ((dest_tree = ffesymbol_hook (ffebld_symter (dest)).decl_tree)
11019 && (TREE_CODE (dest_tree) != VAR_DECL
11020 || TREE_ADDRESSABLE (dest_tree))))
11022 ffecom_prepare_expr_ (source, dest);
11027 ffecom_prepare_expr_ (source, NULL);
11031 ffecom_prepare_expr_w (NULL_TREE, dest);
11033 /* For COMPLEX assignment like C1=C2, if partial overlap is possible,
11034 create a temporary through which the assignment is to take place,
11035 since MODIFY_EXPR doesn't handle partial overlap properly. */
11036 if (ffebld_basictype (dest) == FFEINFO_basictypeCOMPLEX
11037 && ffecom_possible_partial_overlap_ (dest, source))
11039 assign_temp = ffecom_make_tempvar ("complex_let",
11041 [ffebld_basictype (dest)]
11042 [ffebld_kindtype (dest)],
11043 FFETARGET_charactersizeNONE,
11047 assign_temp = NULL_TREE;
11049 ffecom_prepare_end ();
11051 dest_tree = ffecom_expr_w (NULL_TREE, dest);
11052 if (dest_tree == error_mark_node)
11055 if ((TREE_CODE (dest_tree) != VAR_DECL)
11056 || TREE_ADDRESSABLE (dest_tree))
11057 source_tree = ffecom_expr_ (source, dest_tree, dest, &dest_used,
11061 assert (! dest_used);
11063 source_tree = ffecom_expr (source);
11065 if (source_tree == error_mark_node)
11069 expr_tree = source_tree;
11070 else if (assign_temp)
11073 /* The back end understands a conceptual move (evaluate source;
11074 store into dest), so use that, in case it can determine
11075 that it is going to use, say, two registers as temporaries
11076 anyway. So don't use the temp (and someday avoid generating
11077 it, once this code starts triggering regularly). */
11078 expr_tree = ffecom_2s (MOVE_EXPR, void_type_node,
11082 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11085 expand_expr_stmt (expr_tree);
11086 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11092 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11096 expand_expr_stmt (expr_tree);
11100 ffecom_prepare_let_char_ (ffebld_size_known (dest), source);
11101 ffecom_prepare_expr_w (NULL_TREE, dest);
11103 ffecom_prepare_end ();
11105 ffecom_char_args_ (&dest_tree, &dest_length, dest);
11106 ffecom_let_char_ (dest_tree, dest_length, ffebld_size_known (dest),
11111 /* ffecom_expr -- Transform expr into gcc tree
11114 ffebld expr; // FFE expression.
11115 tree = ffecom_expr(expr);
11117 Recursive descent on expr while making corresponding tree nodes and
11118 attaching type info and such. */
11120 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11122 ffecom_expr (ffebld expr)
11124 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, FALSE, FALSE);
11128 /* Like ffecom_expr, but return tree usable for assigned GOTO or FORMAT. */
11130 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11132 ffecom_expr_assign (ffebld expr)
11134 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
11138 /* Like ffecom_expr_rw, but return tree usable for ASSIGN. */
11140 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11142 ffecom_expr_assign_w (ffebld expr)
11144 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
11148 /* Transform expr for use as into read/write tree and stabilize the
11149 reference. Not for use on CHARACTER expressions.
11151 Recursive descent on expr while making corresponding tree nodes and
11152 attaching type info and such. */
11154 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11156 ffecom_expr_rw (tree type, ffebld expr)
11158 assert (expr != NULL);
11159 /* Different target types not yet supported. */
11160 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
11162 return stabilize_reference (ffecom_expr (expr));
11166 /* Transform expr for use as into write tree and stabilize the
11167 reference. Not for use on CHARACTER expressions.
11169 Recursive descent on expr while making corresponding tree nodes and
11170 attaching type info and such. */
11172 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11174 ffecom_expr_w (tree type, ffebld expr)
11176 assert (expr != NULL);
11177 /* Different target types not yet supported. */
11178 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
11180 return stabilize_reference (ffecom_expr (expr));
11184 /* Do global stuff. */
11186 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11188 ffecom_finish_compile ()
11190 assert (ffecom_outer_function_decl_ == NULL_TREE);
11191 assert (current_function_decl == NULL_TREE);
11193 ffeglobal_drive (ffecom_finish_global_);
11197 /* Public entry point for front end to access finish_decl. */
11199 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11201 ffecom_finish_decl (tree decl, tree init, bool is_top_level)
11203 assert (!is_top_level);
11204 finish_decl (decl, init, FALSE);
11208 /* Finish a program unit. */
11210 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11212 ffecom_finish_progunit ()
11214 ffecom_end_compstmt ();
11216 ffecom_previous_function_decl_ = current_function_decl;
11217 ffecom_which_entrypoint_decl_ = NULL_TREE;
11219 finish_function (0);
11224 /* Wrapper for get_identifier. pattern is sprintf-like. */
11226 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11228 ffecom_get_invented_identifier (const char *pattern, ...)
11234 va_start (ap, pattern);
11235 if (vasprintf (&nam, pattern, ap) == 0)
11238 decl = get_identifier (nam);
11240 IDENTIFIER_INVENTED (decl) = 1;
11245 ffecom_gfrt_basictype (ffecomGfrt gfrt)
11247 assert (gfrt < FFECOM_gfrt);
11249 switch (ffecom_gfrt_type_[gfrt])
11251 case FFECOM_rttypeVOID_:
11252 case FFECOM_rttypeVOIDSTAR_:
11253 return FFEINFO_basictypeNONE;
11255 case FFECOM_rttypeFTNINT_:
11256 return FFEINFO_basictypeINTEGER;
11258 case FFECOM_rttypeINTEGER_:
11259 return FFEINFO_basictypeINTEGER;
11261 case FFECOM_rttypeLONGINT_:
11262 return FFEINFO_basictypeINTEGER;
11264 case FFECOM_rttypeLOGICAL_:
11265 return FFEINFO_basictypeLOGICAL;
11267 case FFECOM_rttypeREAL_F2C_:
11268 case FFECOM_rttypeREAL_GNU_:
11269 return FFEINFO_basictypeREAL;
11271 case FFECOM_rttypeCOMPLEX_F2C_:
11272 case FFECOM_rttypeCOMPLEX_GNU_:
11273 return FFEINFO_basictypeCOMPLEX;
11275 case FFECOM_rttypeDOUBLE_:
11276 case FFECOM_rttypeDOUBLEREAL_:
11277 return FFEINFO_basictypeREAL;
11279 case FFECOM_rttypeDBLCMPLX_F2C_:
11280 case FFECOM_rttypeDBLCMPLX_GNU_:
11281 return FFEINFO_basictypeCOMPLEX;
11283 case FFECOM_rttypeCHARACTER_:
11284 return FFEINFO_basictypeCHARACTER;
11287 return FFEINFO_basictypeANY;
11292 ffecom_gfrt_kindtype (ffecomGfrt gfrt)
11294 assert (gfrt < FFECOM_gfrt);
11296 switch (ffecom_gfrt_type_[gfrt])
11298 case FFECOM_rttypeVOID_:
11299 case FFECOM_rttypeVOIDSTAR_:
11300 return FFEINFO_kindtypeNONE;
11302 case FFECOM_rttypeFTNINT_:
11303 return FFEINFO_kindtypeINTEGER1;
11305 case FFECOM_rttypeINTEGER_:
11306 return FFEINFO_kindtypeINTEGER1;
11308 case FFECOM_rttypeLONGINT_:
11309 return FFEINFO_kindtypeINTEGER4;
11311 case FFECOM_rttypeLOGICAL_:
11312 return FFEINFO_kindtypeLOGICAL1;
11314 case FFECOM_rttypeREAL_F2C_:
11315 case FFECOM_rttypeREAL_GNU_:
11316 return FFEINFO_kindtypeREAL1;
11318 case FFECOM_rttypeCOMPLEX_F2C_:
11319 case FFECOM_rttypeCOMPLEX_GNU_:
11320 return FFEINFO_kindtypeREAL1;
11322 case FFECOM_rttypeDOUBLE_:
11323 case FFECOM_rttypeDOUBLEREAL_:
11324 return FFEINFO_kindtypeREAL2;
11326 case FFECOM_rttypeDBLCMPLX_F2C_:
11327 case FFECOM_rttypeDBLCMPLX_GNU_:
11328 return FFEINFO_kindtypeREAL2;
11330 case FFECOM_rttypeCHARACTER_:
11331 return FFEINFO_kindtypeCHARACTER1;
11334 return FFEINFO_kindtypeANY;
11348 tree double_ftype_double;
11349 tree float_ftype_float;
11350 tree ldouble_ftype_ldouble;
11351 tree ffecom_tree_ptr_to_fun_type_void;
11353 /* This block of code comes from the now-obsolete cktyps.c. It checks
11354 whether the compiler environment is buggy in known ways, some of which
11355 would, if not explicitly checked here, result in subtle bugs in g77. */
11357 if (ffe_is_do_internal_checks ())
11359 static char names[][12]
11361 {"bar", "bletch", "foo", "foobar"};
11366 name = bsearch ("foo", &names[0], ARRAY_SIZE (names), sizeof (names[0]),
11367 (int (*)(const void *, const void *)) strcmp);
11368 if (name != (char *) &names[2])
11370 assert ("bsearch doesn't work, #define FFEPROJ_BSEARCH 0 in proj.h"
11375 ul = strtoul ("123456789", NULL, 10);
11376 if (ul != 123456789L)
11378 assert ("strtoul doesn't have enough range, #define FFEPROJ_STRTOUL 0\
11379 in proj.h" == NULL);
11383 fl = atof ("56.789");
11384 if ((fl < 56.788) || (fl > 56.79))
11386 assert ("atof not type double, fix your #include <stdio.h>"
11392 #if FFECOM_GCC_INCLUDE
11393 ffecom_initialize_char_syntax_ ();
11396 ffecom_outer_function_decl_ = NULL_TREE;
11397 current_function_decl = NULL_TREE;
11398 named_labels = NULL_TREE;
11399 current_binding_level = NULL_BINDING_LEVEL;
11400 free_binding_level = NULL_BINDING_LEVEL;
11401 /* Make the binding_level structure for global names. */
11403 global_binding_level = current_binding_level;
11404 current_binding_level->prep_state = 2;
11406 build_common_tree_nodes (1);
11408 /* Define `int' and `char' first so that dbx will output them first. */
11409 pushdecl (build_decl (TYPE_DECL, get_identifier ("int"),
11410 integer_type_node));
11411 /* CHARACTER*1 is unsigned in ICHAR contexts. */
11412 char_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
11413 pushdecl (build_decl (TYPE_DECL, get_identifier ("char"),
11415 pushdecl (build_decl (TYPE_DECL, get_identifier ("long int"),
11416 long_integer_type_node));
11417 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned int"),
11418 unsigned_type_node));
11419 pushdecl (build_decl (TYPE_DECL, get_identifier ("long unsigned int"),
11420 long_unsigned_type_node));
11421 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long int"),
11422 long_long_integer_type_node));
11423 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"),
11424 long_long_unsigned_type_node));
11425 pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"),
11426 short_integer_type_node));
11427 pushdecl (build_decl (TYPE_DECL, get_identifier ("short unsigned int"),
11428 short_unsigned_type_node));
11430 /* Set the sizetype before we make other types. This *should* be the
11431 first type we create. */
11434 (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))));
11435 ffecom_typesize_pointer_
11436 = TREE_INT_CST_LOW (TYPE_SIZE (sizetype)) / BITS_PER_UNIT;
11438 build_common_tree_nodes_2 (0);
11440 /* Define both `signed char' and `unsigned char'. */
11441 pushdecl (build_decl (TYPE_DECL, get_identifier ("signed char"),
11442 signed_char_type_node));
11444 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned char"),
11445 unsigned_char_type_node));
11447 pushdecl (build_decl (TYPE_DECL, get_identifier ("float"),
11449 pushdecl (build_decl (TYPE_DECL, get_identifier ("double"),
11450 double_type_node));
11451 pushdecl (build_decl (TYPE_DECL, get_identifier ("long double"),
11452 long_double_type_node));
11454 /* For now, override what build_common_tree_nodes has done. */
11455 complex_integer_type_node = ffecom_make_complex_type_ (integer_type_node);
11456 complex_float_type_node = ffecom_make_complex_type_ (float_type_node);
11457 complex_double_type_node = ffecom_make_complex_type_ (double_type_node);
11458 complex_long_double_type_node
11459 = ffecom_make_complex_type_ (long_double_type_node);
11461 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"),
11462 complex_integer_type_node));
11463 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"),
11464 complex_float_type_node));
11465 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"),
11466 complex_double_type_node));
11467 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"),
11468 complex_long_double_type_node));
11470 pushdecl (build_decl (TYPE_DECL, get_identifier ("void"),
11472 /* We are not going to have real types in C with less than byte alignment,
11473 so we might as well not have any types that claim to have it. */
11474 TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
11475 TYPE_USER_ALIGN (void_type_node) = 0;
11477 string_type_node = build_pointer_type (char_type_node);
11479 ffecom_tree_fun_type_void
11480 = build_function_type (void_type_node, NULL_TREE);
11482 ffecom_tree_ptr_to_fun_type_void
11483 = build_pointer_type (ffecom_tree_fun_type_void);
11485 endlink = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
11488 = build_function_type (float_type_node,
11489 tree_cons (NULL_TREE, float_type_node, endlink));
11491 double_ftype_double
11492 = build_function_type (double_type_node,
11493 tree_cons (NULL_TREE, double_type_node, endlink));
11495 ldouble_ftype_ldouble
11496 = build_function_type (long_double_type_node,
11497 tree_cons (NULL_TREE, long_double_type_node,
11500 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11501 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11503 ffecom_tree_type[i][j] = NULL_TREE;
11504 ffecom_tree_fun_type[i][j] = NULL_TREE;
11505 ffecom_tree_ptr_to_fun_type[i][j] = NULL_TREE;
11506 ffecom_f2c_typecode_[i][j] = -1;
11509 /* Set up standard g77 types. Note that INTEGER and LOGICAL are set
11510 to size FLOAT_TYPE_SIZE because they have to be the same size as
11511 REAL, which also is FLOAT_TYPE_SIZE, according to the standard.
11512 Compiler options and other such stuff that change the ways these
11513 types are set should not affect this particular setup. */
11515 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1]
11516 = t = make_signed_type (FLOAT_TYPE_SIZE);
11517 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer"),
11519 type = ffetype_new ();
11521 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER1,
11523 ffetype_set_ams (type,
11524 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11525 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11526 ffetype_set_star (base_type,
11527 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11529 ffetype_set_kind (base_type, 1, type);
11530 ffecom_typesize_integer1_ = ffetype_size (type);
11531 assert (ffetype_size (type) == sizeof (ffetargetInteger1));
11533 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER1]
11534 = t = make_unsigned_type (FLOAT_TYPE_SIZE); /* HOLLERITH means unsigned. */
11535 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned"),
11538 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER2]
11539 = t = make_signed_type (CHAR_TYPE_SIZE);
11540 pushdecl (build_decl (TYPE_DECL, get_identifier ("byte"),
11542 type = ffetype_new ();
11543 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER2,
11545 ffetype_set_ams (type,
11546 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11547 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11548 ffetype_set_star (base_type,
11549 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11551 ffetype_set_kind (base_type, 3, type);
11552 assert (ffetype_size (type) == sizeof (ffetargetInteger2));
11554 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER2]
11555 = t = make_unsigned_type (CHAR_TYPE_SIZE);
11556 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned byte"),
11559 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER3]
11560 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11561 pushdecl (build_decl (TYPE_DECL, get_identifier ("word"),
11563 type = ffetype_new ();
11564 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER3,
11566 ffetype_set_ams (type,
11567 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11568 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11569 ffetype_set_star (base_type,
11570 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11572 ffetype_set_kind (base_type, 6, type);
11573 assert (ffetype_size (type) == sizeof (ffetargetInteger3));
11575 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER3]
11576 = t = make_unsigned_type (CHAR_TYPE_SIZE * 2);
11577 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned word"),
11580 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER4]
11581 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11582 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer4"),
11584 type = ffetype_new ();
11585 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER4,
11587 ffetype_set_ams (type,
11588 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11589 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11590 ffetype_set_star (base_type,
11591 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11593 ffetype_set_kind (base_type, 2, type);
11594 assert (ffetype_size (type) == sizeof (ffetargetInteger4));
11596 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER4]
11597 = t = make_unsigned_type (FLOAT_TYPE_SIZE * 2);
11598 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned4"),
11602 if (ffe_is_do_internal_checks ()
11603 && LONG_TYPE_SIZE != FLOAT_TYPE_SIZE
11604 && LONG_TYPE_SIZE != CHAR_TYPE_SIZE
11605 && LONG_TYPE_SIZE != SHORT_TYPE_SIZE
11606 && LONG_TYPE_SIZE != LONG_LONG_TYPE_SIZE)
11608 fprintf (stderr, "Sorry, no g77 support for LONG_TYPE_SIZE (%d bits) yet.\n",
11613 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL1]
11614 = t = make_signed_type (FLOAT_TYPE_SIZE);
11615 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical"),
11617 type = ffetype_new ();
11619 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL1,
11621 ffetype_set_ams (type,
11622 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11623 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11624 ffetype_set_star (base_type,
11625 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11627 ffetype_set_kind (base_type, 1, type);
11628 assert (ffetype_size (type) == sizeof (ffetargetLogical1));
11630 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL2]
11631 = t = make_signed_type (CHAR_TYPE_SIZE);
11632 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical2"),
11634 type = ffetype_new ();
11635 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL2,
11637 ffetype_set_ams (type,
11638 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11639 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11640 ffetype_set_star (base_type,
11641 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11643 ffetype_set_kind (base_type, 3, type);
11644 assert (ffetype_size (type) == sizeof (ffetargetLogical2));
11646 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL3]
11647 = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11648 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical3"),
11650 type = ffetype_new ();
11651 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL3,
11653 ffetype_set_ams (type,
11654 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11655 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11656 ffetype_set_star (base_type,
11657 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11659 ffetype_set_kind (base_type, 6, type);
11660 assert (ffetype_size (type) == sizeof (ffetargetLogical3));
11662 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL4]
11663 = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11664 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical4"),
11666 type = ffetype_new ();
11667 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL4,
11669 ffetype_set_ams (type,
11670 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11671 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11672 ffetype_set_star (base_type,
11673 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11675 ffetype_set_kind (base_type, 2, type);
11676 assert (ffetype_size (type) == sizeof (ffetargetLogical4));
11678 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
11679 = t = make_node (REAL_TYPE);
11680 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE;
11681 pushdecl (build_decl (TYPE_DECL, get_identifier ("real"),
11684 type = ffetype_new ();
11686 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREAL1,
11688 ffetype_set_ams (type,
11689 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11690 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11691 ffetype_set_star (base_type,
11692 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11694 ffetype_set_kind (base_type, 1, type);
11695 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
11696 = FFETARGET_f2cTYREAL;
11697 assert (ffetype_size (type) == sizeof (ffetargetReal1));
11699 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREALDOUBLE]
11700 = t = make_node (REAL_TYPE);
11701 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE * 2; /* Always twice REAL. */
11702 pushdecl (build_decl (TYPE_DECL, get_identifier ("double precision"),
11705 type = ffetype_new ();
11706 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREALDOUBLE,
11708 ffetype_set_ams (type,
11709 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11710 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11711 ffetype_set_star (base_type,
11712 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11714 ffetype_set_kind (base_type, 2, type);
11715 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]
11716 = FFETARGET_f2cTYDREAL;
11717 assert (ffetype_size (type) == sizeof (ffetargetReal2));
11719 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
11720 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]);
11721 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex"),
11723 type = ffetype_new ();
11725 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREAL1,
11727 ffetype_set_ams (type,
11728 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11729 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11730 ffetype_set_star (base_type,
11731 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11733 ffetype_set_kind (base_type, 1, type);
11734 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
11735 = FFETARGET_f2cTYCOMPLEX;
11736 assert (ffetype_size (type) == sizeof (ffetargetComplex1));
11738 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREALDOUBLE]
11739 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]);
11740 pushdecl (build_decl (TYPE_DECL, get_identifier ("double complex"),
11742 type = ffetype_new ();
11743 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREALDOUBLE,
11745 ffetype_set_ams (type,
11746 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11747 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11748 ffetype_set_star (base_type,
11749 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11751 ffetype_set_kind (base_type, 2,
11753 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL2]
11754 = FFETARGET_f2cTYDCOMPLEX;
11755 assert (ffetype_size (type) == sizeof (ffetargetComplex2));
11757 /* Make function and ptr-to-function types for non-CHARACTER types. */
11759 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11760 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11762 if ((t = ffecom_tree_type[i][j]) != NULL_TREE)
11764 if (i == FFEINFO_basictypeINTEGER)
11766 /* Figure out the smallest INTEGER type that can hold
11767 a pointer on this machine. */
11768 if (GET_MODE_SIZE (TYPE_MODE (t))
11769 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
11771 if ((ffecom_pointer_kind_ == FFEINFO_kindtypeNONE)
11772 || (GET_MODE_SIZE (TYPE_MODE (ffecom_tree_type[i][ffecom_pointer_kind_]))
11773 > GET_MODE_SIZE (TYPE_MODE (t))))
11774 ffecom_pointer_kind_ = j;
11777 else if (i == FFEINFO_basictypeCOMPLEX)
11778 t = void_type_node;
11779 /* For f2c compatibility, REAL functions are really
11780 implemented as DOUBLE PRECISION. */
11781 else if ((i == FFEINFO_basictypeREAL)
11782 && (j == FFEINFO_kindtypeREAL1))
11783 t = ffecom_tree_type
11784 [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2];
11786 t = ffecom_tree_fun_type[i][j] = build_function_type (t,
11788 ffecom_tree_ptr_to_fun_type[i][j] = build_pointer_type (t);
11792 /* Set up pointer types. */
11794 if (ffecom_pointer_kind_ == FFEINFO_basictypeNONE)
11795 fatal_error ("no INTEGER type can hold a pointer on this configuration");
11796 else if (0 && ffe_is_do_internal_checks ())
11797 fprintf (stderr, "Pointer type kt=%d\n", ffecom_pointer_kind_);
11798 ffetype_set_kind (ffeinfo_type (FFEINFO_basictypeINTEGER,
11799 FFEINFO_kindtypeINTEGERDEFAULT),
11801 ffeinfo_type (FFEINFO_basictypeINTEGER,
11802 ffecom_pointer_kind_));
11804 if (ffe_is_ugly_assign ())
11805 ffecom_label_kind_ = ffecom_pointer_kind_; /* Require ASSIGN etc to this. */
11807 ffecom_label_kind_ = FFEINFO_kindtypeINTEGERDEFAULT;
11808 if (0 && ffe_is_do_internal_checks ())
11809 fprintf (stderr, "Label type kt=%d\n", ffecom_label_kind_);
11811 ffecom_integer_type_node
11812 = ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1];
11813 ffecom_integer_zero_node = convert (ffecom_integer_type_node,
11814 integer_zero_node);
11815 ffecom_integer_one_node = convert (ffecom_integer_type_node,
11818 /* Yes, the "FLOAT_TYPE_SIZE" references below are intentional.
11819 Turns out that by TYLONG, runtime/libI77/lio.h really means
11820 "whatever size an ftnint is". For consistency and sanity,
11821 com.h and runtime/f2c.h.in agree that flag, ftnint, and ftlen
11822 all are INTEGER, which we also make out of whatever back-end
11823 integer type is FLOAT_TYPE_SIZE bits wide. This change, from
11824 LONG_TYPE_SIZE, for TYLONG and TYLOGICAL, was necessary to
11825 accommodate machines like the Alpha. Note that this suggests
11826 f2c and libf2c are missing a distinction perhaps needed on
11827 some machines between "int" and "long int". -- burley 0.5.5 950215 */
11829 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, FLOAT_TYPE_SIZE,
11830 FFETARGET_f2cTYLONG);
11831 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, SHORT_TYPE_SIZE,
11832 FFETARGET_f2cTYSHORT);
11833 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, CHAR_TYPE_SIZE,
11834 FFETARGET_f2cTYINT1);
11835 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, LONG_LONG_TYPE_SIZE,
11836 FFETARGET_f2cTYQUAD);
11837 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, FLOAT_TYPE_SIZE,
11838 FFETARGET_f2cTYLOGICAL);
11839 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, SHORT_TYPE_SIZE,
11840 FFETARGET_f2cTYLOGICAL2);
11841 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, CHAR_TYPE_SIZE,
11842 FFETARGET_f2cTYLOGICAL1);
11843 /* ~~~Not really such a type in libf2c, e.g. I/O support? */
11844 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, LONG_LONG_TYPE_SIZE,
11845 FFETARGET_f2cTYQUAD);
11847 /* CHARACTER stuff is all special-cased, so it is not handled in the above
11848 loop. CHARACTER items are built as arrays of unsigned char. */
11850 ffecom_tree_type[FFEINFO_basictypeCHARACTER]
11851 [FFEINFO_kindtypeCHARACTER1] = t = char_type_node;
11852 type = ffetype_new ();
11854 ffeinfo_set_type (FFEINFO_basictypeCHARACTER,
11855 FFEINFO_kindtypeCHARACTER1,
11857 ffetype_set_ams (type,
11858 TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11859 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11860 ffetype_set_kind (base_type, 1, type);
11861 assert (ffetype_size (type)
11862 == sizeof (((ffetargetCharacter1) { 0, NULL }).text[0]));
11864 ffecom_tree_fun_type[FFEINFO_basictypeCHARACTER]
11865 [FFEINFO_kindtypeCHARACTER1] = ffecom_tree_fun_type_void;
11866 ffecom_tree_ptr_to_fun_type[FFEINFO_basictypeCHARACTER]
11867 [FFEINFO_kindtypeCHARACTER1]
11868 = ffecom_tree_ptr_to_fun_type_void;
11869 ffecom_f2c_typecode_[FFEINFO_basictypeCHARACTER][FFEINFO_kindtypeCHARACTER1]
11870 = FFETARGET_f2cTYCHAR;
11872 ffecom_f2c_typecode_[FFEINFO_basictypeANY][FFEINFO_kindtypeANY]
11875 /* Make multi-return-value type and fields. */
11877 ffecom_multi_type_node_ = make_node (UNION_TYPE);
11881 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11882 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11886 if (ffecom_tree_type[i][j] == NULL_TREE)
11887 continue; /* Not supported. */
11888 sprintf (&name[0], "bt_%s_kt_%s",
11889 ffeinfo_basictype_string ((ffeinfoBasictype) i),
11890 ffeinfo_kindtype_string ((ffeinfoKindtype) j));
11891 ffecom_multi_fields_[i][j] = build_decl (FIELD_DECL,
11892 get_identifier (name),
11893 ffecom_tree_type[i][j]);
11894 DECL_CONTEXT (ffecom_multi_fields_[i][j])
11895 = ffecom_multi_type_node_;
11896 DECL_ALIGN (ffecom_multi_fields_[i][j]) = 0;
11897 DECL_USER_ALIGN (ffecom_multi_fields_[i][j]) = 0;
11898 TREE_CHAIN (ffecom_multi_fields_[i][j]) = field;
11899 field = ffecom_multi_fields_[i][j];
11902 TYPE_FIELDS (ffecom_multi_type_node_) = field;
11903 layout_type (ffecom_multi_type_node_);
11905 /* Subroutines usually return integer because they might have alternate
11908 ffecom_tree_subr_type
11909 = build_function_type (integer_type_node, NULL_TREE);
11910 ffecom_tree_ptr_to_subr_type
11911 = build_pointer_type (ffecom_tree_subr_type);
11912 ffecom_tree_blockdata_type
11913 = build_function_type (void_type_node, NULL_TREE);
11915 builtin_function ("__builtin_sqrtf", float_ftype_float,
11916 BUILT_IN_FSQRT, BUILT_IN_NORMAL, "sqrtf");
11917 builtin_function ("__builtin_fsqrt", double_ftype_double,
11918 BUILT_IN_FSQRT, BUILT_IN_NORMAL, "sqrt");
11919 builtin_function ("__builtin_sqrtl", ldouble_ftype_ldouble,
11920 BUILT_IN_FSQRT, BUILT_IN_NORMAL, "sqrtl");
11921 builtin_function ("__builtin_sinf", float_ftype_float,
11922 BUILT_IN_SIN, BUILT_IN_NORMAL, "sinf");
11923 builtin_function ("__builtin_sin", double_ftype_double,
11924 BUILT_IN_SIN, BUILT_IN_NORMAL, "sin");
11925 builtin_function ("__builtin_sinl", ldouble_ftype_ldouble,
11926 BUILT_IN_SIN, BUILT_IN_NORMAL, "sinl");
11927 builtin_function ("__builtin_cosf", float_ftype_float,
11928 BUILT_IN_COS, BUILT_IN_NORMAL, "cosf");
11929 builtin_function ("__builtin_cos", double_ftype_double,
11930 BUILT_IN_COS, BUILT_IN_NORMAL, "cos");
11931 builtin_function ("__builtin_cosl", ldouble_ftype_ldouble,
11932 BUILT_IN_COS, BUILT_IN_NORMAL, "cosl");
11935 pedantic_lvalues = FALSE;
11938 ffecom_f2c_make_type_ (&ffecom_f2c_integer_type_node,
11941 ffecom_f2c_make_type_ (&ffecom_f2c_address_type_node,
11944 ffecom_f2c_make_type_ (&ffecom_f2c_real_type_node,
11947 ffecom_f2c_make_type_ (&ffecom_f2c_doublereal_type_node,
11948 FFECOM_f2cDOUBLEREAL,
11950 ffecom_f2c_make_type_ (&ffecom_f2c_complex_type_node,
11953 ffecom_f2c_make_type_ (&ffecom_f2c_doublecomplex_type_node,
11954 FFECOM_f2cDOUBLECOMPLEX,
11956 ffecom_f2c_make_type_ (&ffecom_f2c_longint_type_node,
11959 ffecom_f2c_make_type_ (&ffecom_f2c_logical_type_node,
11962 ffecom_f2c_make_type_ (&ffecom_f2c_flag_type_node,
11965 ffecom_f2c_make_type_ (&ffecom_f2c_ftnlen_type_node,
11968 ffecom_f2c_make_type_ (&ffecom_f2c_ftnint_type_node,
11972 ffecom_f2c_ftnlen_zero_node
11973 = convert (ffecom_f2c_ftnlen_type_node, integer_zero_node);
11975 ffecom_f2c_ftnlen_one_node
11976 = convert (ffecom_f2c_ftnlen_type_node, integer_one_node);
11978 ffecom_f2c_ftnlen_two_node = build_int_2 (2, 0);
11979 TREE_TYPE (ffecom_f2c_ftnlen_two_node) = ffecom_integer_type_node;
11981 ffecom_f2c_ptr_to_ftnlen_type_node
11982 = build_pointer_type (ffecom_f2c_ftnlen_type_node);
11984 ffecom_f2c_ptr_to_ftnint_type_node
11985 = build_pointer_type (ffecom_f2c_ftnint_type_node);
11987 ffecom_f2c_ptr_to_integer_type_node
11988 = build_pointer_type (ffecom_f2c_integer_type_node);
11990 ffecom_f2c_ptr_to_real_type_node
11991 = build_pointer_type (ffecom_f2c_real_type_node);
11993 ffecom_float_zero_ = build_real (float_type_node, dconst0);
11994 ffecom_double_zero_ = build_real (double_type_node, dconst0);
11996 REAL_VALUE_TYPE point_5;
11998 #ifdef REAL_ARITHMETIC
11999 REAL_ARITHMETIC (point_5, RDIV_EXPR, dconst1, dconst2);
12003 ffecom_float_half_ = build_real (float_type_node, point_5);
12004 ffecom_double_half_ = build_real (double_type_node, point_5);
12007 /* Do "extern int xargc;". */
12009 ffecom_tree_xargc_ = build_decl (VAR_DECL,
12010 get_identifier ("f__xargc"),
12011 integer_type_node);
12012 DECL_EXTERNAL (ffecom_tree_xargc_) = 1;
12013 TREE_STATIC (ffecom_tree_xargc_) = 1;
12014 TREE_PUBLIC (ffecom_tree_xargc_) = 1;
12015 ffecom_tree_xargc_ = start_decl (ffecom_tree_xargc_, FALSE);
12016 finish_decl (ffecom_tree_xargc_, NULL_TREE, FALSE);
12018 #if 0 /* This is being fixed, and seems to be working now. */
12019 if ((FLOAT_TYPE_SIZE != 32)
12020 || (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))) != 32))
12022 warning ("configuration: REAL, INTEGER, and LOGICAL are %d bits wide,",
12023 (int) FLOAT_TYPE_SIZE);
12024 warning ("and pointers are %d bits wide, but g77 doesn't yet work",
12025 (int) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))));
12026 warning ("properly unless they all are 32 bits wide.");
12027 warning ("Please keep this in mind before you report bugs. g77 should");
12028 warning ("support non-32-bit machines better as of version 0.6.");
12032 #if 0 /* Code in ste.c that would crash has been commented out. */
12033 if (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
12034 < TYPE_PRECISION (string_type_node))
12035 /* I/O will probably crash. */
12036 warning ("configuration: char * holds %d bits, but ftnlen only %d",
12037 TYPE_PRECISION (string_type_node),
12038 TYPE_PRECISION (ffecom_f2c_ftnlen_type_node));
12041 #if 0 /* ASSIGN-related stuff has been changed to accommodate this. */
12042 if (TYPE_PRECISION (ffecom_integer_type_node)
12043 < TYPE_PRECISION (string_type_node))
12044 /* ASSIGN 10 TO I will crash. */
12045 warning ("configuration: char * holds %d bits, but INTEGER only %d --\n\
12046 ASSIGN statement might fail",
12047 TYPE_PRECISION (string_type_node),
12048 TYPE_PRECISION (ffecom_integer_type_node));
12053 /* ffecom_init_2 -- Initialize
12055 ffecom_init_2(); */
12057 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12061 assert (ffecom_outer_function_decl_ == NULL_TREE);
12062 assert (current_function_decl == NULL_TREE);
12063 assert (ffecom_which_entrypoint_decl_ == NULL_TREE);
12065 ffecom_master_arglist_ = NULL;
12067 ffecom_primary_entry_ = NULL;
12068 ffecom_is_altreturning_ = FALSE;
12069 ffecom_func_result_ = NULL_TREE;
12070 ffecom_multi_retval_ = NULL_TREE;
12074 /* ffecom_list_expr -- Transform list of exprs into gcc tree
12077 ffebld expr; // FFE opITEM list.
12078 tree = ffecom_list_expr(expr);
12080 List of actual args is transformed into corresponding gcc backend list. */
12082 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12084 ffecom_list_expr (ffebld expr)
12087 tree *plist = &list;
12088 tree trail = NULL_TREE; /* Append char length args here. */
12089 tree *ptrail = &trail;
12092 while (expr != NULL)
12094 tree texpr = ffecom_arg_expr (ffebld_head (expr), &length);
12096 if (texpr == error_mark_node)
12097 return error_mark_node;
12099 *plist = build_tree_list (NULL_TREE, texpr);
12100 plist = &TREE_CHAIN (*plist);
12101 expr = ffebld_trail (expr);
12102 if (length != NULL_TREE)
12104 *ptrail = build_tree_list (NULL_TREE, length);
12105 ptrail = &TREE_CHAIN (*ptrail);
12115 /* ffecom_list_ptr_to_expr -- Transform list of exprs into gcc tree
12118 ffebld expr; // FFE opITEM list.
12119 tree = ffecom_list_ptr_to_expr(expr);
12121 List of actual args is transformed into corresponding gcc backend list for
12122 use in calling an external procedure (vs. a statement function). */
12124 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12126 ffecom_list_ptr_to_expr (ffebld expr)
12129 tree *plist = &list;
12130 tree trail = NULL_TREE; /* Append char length args here. */
12131 tree *ptrail = &trail;
12134 while (expr != NULL)
12136 tree texpr = ffecom_arg_ptr_to_expr (ffebld_head (expr), &length);
12138 if (texpr == error_mark_node)
12139 return error_mark_node;
12141 *plist = build_tree_list (NULL_TREE, texpr);
12142 plist = &TREE_CHAIN (*plist);
12143 expr = ffebld_trail (expr);
12144 if (length != NULL_TREE)
12146 *ptrail = build_tree_list (NULL_TREE, length);
12147 ptrail = &TREE_CHAIN (*ptrail);
12157 /* Obtain gcc's LABEL_DECL tree for label. */
12159 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12161 ffecom_lookup_label (ffelab label)
12165 if (ffelab_hook (label) == NULL_TREE)
12167 char labelname[16];
12169 switch (ffelab_type (label))
12171 case FFELAB_typeLOOPEND:
12172 case FFELAB_typeNOTLOOP:
12173 case FFELAB_typeENDIF:
12174 sprintf (labelname, "%" ffelabValue_f "u", ffelab_value (label));
12175 glabel = build_decl (LABEL_DECL, get_identifier (labelname),
12177 DECL_CONTEXT (glabel) = current_function_decl;
12178 DECL_MODE (glabel) = VOIDmode;
12181 case FFELAB_typeFORMAT:
12182 glabel = build_decl (VAR_DECL,
12183 ffecom_get_invented_identifier
12184 ("__g77_format_%d", (int) ffelab_value (label)),
12185 build_type_variant (build_array_type
12189 TREE_CONSTANT (glabel) = 1;
12190 TREE_STATIC (glabel) = 1;
12191 DECL_CONTEXT (glabel) = current_function_decl;
12192 DECL_INITIAL (glabel) = NULL;
12193 make_decl_rtl (glabel, NULL);
12194 expand_decl (glabel);
12196 ffecom_save_tree_forever (glabel);
12200 case FFELAB_typeANY:
12201 glabel = error_mark_node;
12205 assert ("bad label type" == NULL);
12209 ffelab_set_hook (label, glabel);
12213 glabel = ffelab_hook (label);
12220 /* Stabilizes the arguments. Don't use this if the lhs and rhs come from
12221 a single source specification (as in the fourth argument of MVBITS).
12222 If the type is NULL_TREE, the type of lhs is used to make the type of
12223 the MODIFY_EXPR. */
12225 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12227 ffecom_modify (tree newtype, tree lhs,
12230 if (lhs == error_mark_node || rhs == error_mark_node)
12231 return error_mark_node;
12233 if (newtype == NULL_TREE)
12234 newtype = TREE_TYPE (lhs);
12236 if (TREE_SIDE_EFFECTS (lhs))
12237 lhs = stabilize_reference (lhs);
12239 return ffecom_2s (MODIFY_EXPR, newtype, lhs, rhs);
12244 /* Register source file name. */
12247 ffecom_file (const char *name)
12249 #if FFECOM_GCC_INCLUDE
12250 ffecom_file_ (name);
12254 /* ffecom_notify_init_storage -- An aggregate storage is now fully init'ed
12257 ffecom_notify_init_storage(st);
12259 Gets called when all possible units in an aggregate storage area (a LOCAL
12260 with equivalences or a COMMON) have been initialized. The initialization
12261 info either is in ffestorag_init or, if that is NULL,
12262 ffestorag_accretion:
12264 ffestorag_init may contain an opCONTER or opARRTER. opCONTER may occur
12265 even for an array if the array is one element in length!
12267 ffestorag_accretion will contain an opACCTER. It is much like an
12268 opARRTER except it has an ffebit object in it instead of just a size.
12269 The back end can use the info in the ffebit object, if it wants, to
12270 reduce the amount of actual initialization, but in any case it should
12271 kill the ffebit object when done. Also, set accretion to NULL but
12272 init to a non-NULL value.
12274 After performing initialization, DO NOT set init to NULL, because that'll
12275 tell the front end it is ok for more initialization to happen. Instead,
12276 set init to an opANY expression or some such thing that you can use to
12277 tell that you've already initialized the object.
12280 Support two-pass FFE. */
12283 ffecom_notify_init_storage (ffestorag st)
12285 ffebld init; /* The initialization expression. */
12286 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12287 ffetargetOffset size; /* The size of the entity. */
12288 ffetargetAlign pad; /* Its initial padding. */
12291 if (ffestorag_init (st) == NULL)
12293 init = ffestorag_accretion (st);
12294 assert (init != NULL);
12295 ffestorag_set_accretion (st, NULL);
12296 ffestorag_set_accretes (st, 0);
12298 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12299 /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12300 size = ffebld_accter_size (init);
12301 pad = ffebld_accter_pad (init);
12302 ffebit_kill (ffebld_accter_bits (init));
12303 ffebld_set_op (init, FFEBLD_opARRTER);
12304 ffebld_set_arrter (init, ffebld_accter (init));
12305 ffebld_arrter_set_size (init, size);
12306 ffebld_arrter_set_pad (init, size);
12310 ffestorag_set_init (st, init);
12315 init = ffestorag_init (st);
12318 #if FFECOM_ONEPASS /* Process the inits, wipe 'em out. */
12319 ffestorag_set_init (st, ffebld_new_any ());
12321 if (ffebld_op (init) == FFEBLD_opANY)
12322 return; /* Oh, we already did this! */
12324 #if FFECOM_targetCURRENT == FFECOM_targetFFE
12328 if (ffestorag_symbol (st) != NULL)
12329 s = ffestorag_symbol (st);
12331 s = ffestorag_typesymbol (st);
12333 fprintf (dmpout, "= initialize_storage \"%s\" ",
12334 (s != NULL) ? ffesymbol_text (s) : "(unnamed)");
12335 ffebld_dump (init);
12336 fputc ('\n', dmpout);
12340 #endif /* if FFECOM_ONEPASS */
12343 /* ffecom_notify_init_symbol -- A symbol is now fully init'ed
12346 ffecom_notify_init_symbol(s);
12348 Gets called when all possible units in a symbol (not placed in COMMON
12349 or involved in EQUIVALENCE, unless it as yet has no ffestorag object)
12350 have been initialized. The initialization info either is in
12351 ffesymbol_init or, if that is NULL, ffesymbol_accretion:
12353 ffesymbol_init may contain an opCONTER or opARRTER. opCONTER may occur
12354 even for an array if the array is one element in length!
12356 ffesymbol_accretion will contain an opACCTER. It is much like an
12357 opARRTER except it has an ffebit object in it instead of just a size.
12358 The back end can use the info in the ffebit object, if it wants, to
12359 reduce the amount of actual initialization, but in any case it should
12360 kill the ffebit object when done. Also, set accretion to NULL but
12361 init to a non-NULL value.
12363 After performing initialization, DO NOT set init to NULL, because that'll
12364 tell the front end it is ok for more initialization to happen. Instead,
12365 set init to an opANY expression or some such thing that you can use to
12366 tell that you've already initialized the object.
12369 Support two-pass FFE. */
12372 ffecom_notify_init_symbol (ffesymbol s)
12374 ffebld init; /* The initialization expression. */
12375 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12376 ffetargetOffset size; /* The size of the entity. */
12377 ffetargetAlign pad; /* Its initial padding. */
12380 if (ffesymbol_storage (s) == NULL)
12381 return; /* Do nothing until COMMON/EQUIVALENCE
12382 possibilities checked. */
12384 if ((ffesymbol_init (s) == NULL)
12385 && ((init = ffesymbol_accretion (s)) != NULL))
12387 ffesymbol_set_accretion (s, NULL);
12388 ffesymbol_set_accretes (s, 0);
12390 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12391 /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12392 size = ffebld_accter_size (init);
12393 pad = ffebld_accter_pad (init);
12394 ffebit_kill (ffebld_accter_bits (init));
12395 ffebld_set_op (init, FFEBLD_opARRTER);
12396 ffebld_set_arrter (init, ffebld_accter (init));
12397 ffebld_arrter_set_size (init, size);
12398 ffebld_arrter_set_pad (init, size);
12402 ffesymbol_set_init (s, init);
12407 init = ffesymbol_init (s);
12411 ffesymbol_set_init (s, ffebld_new_any ());
12413 if (ffebld_op (init) == FFEBLD_opANY)
12414 return; /* Oh, we already did this! */
12416 #if FFECOM_targetCURRENT == FFECOM_targetFFE
12417 fprintf (dmpout, "= initialize_symbol \"%s\" ", ffesymbol_text (s));
12418 ffebld_dump (init);
12419 fputc ('\n', dmpout);
12422 #endif /* if FFECOM_ONEPASS */
12425 /* ffecom_notify_primary_entry -- Learn which is the primary entry point
12428 ffecom_notify_primary_entry(s);
12430 Gets called when implicit or explicit PROGRAM statement seen or when
12431 FUNCTION, SUBROUTINE, or BLOCK DATA statement seen, with the primary
12432 global symbol that serves as the entry point. */
12435 ffecom_notify_primary_entry (ffesymbol s)
12437 ffecom_primary_entry_ = s;
12438 ffecom_primary_entry_kind_ = ffesymbol_kind (s);
12440 if ((ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
12441 || (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE))
12442 ffecom_primary_entry_is_proc_ = TRUE;
12444 ffecom_primary_entry_is_proc_ = FALSE;
12446 if (!ffe_is_silent ())
12448 if (ffecom_primary_entry_kind_ == FFEINFO_kindPROGRAM)
12449 fprintf (stderr, "%s:\n", ffesymbol_text (s));
12451 fprintf (stderr, " %s:\n", ffesymbol_text (s));
12454 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12455 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
12460 for (list = ffesymbol_dummyargs (s);
12462 list = ffebld_trail (list))
12464 arg = ffebld_head (list);
12465 if (ffebld_op (arg) == FFEBLD_opSTAR)
12467 ffecom_is_altreturning_ = TRUE;
12476 ffecom_open_include (char *name, ffewhereLine l, ffewhereColumn c)
12478 #if FFECOM_GCC_INCLUDE
12479 return ffecom_open_include_ (name, l, c);
12481 return fopen (name, "r");
12485 /* ffecom_ptr_to_expr -- Transform expr into gcc tree with & in front
12488 ffebld expr; // FFE expression.
12489 tree = ffecom_ptr_to_expr(expr);
12491 Like ffecom_expr, but sticks address-of in front of most things. */
12493 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12495 ffecom_ptr_to_expr (ffebld expr)
12498 ffeinfoBasictype bt;
12499 ffeinfoKindtype kt;
12502 assert (expr != NULL);
12504 switch (ffebld_op (expr))
12506 case FFEBLD_opSYMTER:
12507 s = ffebld_symter (expr);
12508 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
12512 ix = ffeintrin_gfrt_indirect (ffebld_symter_implementation (expr));
12513 assert (ix != FFECOM_gfrt);
12514 if ((item = ffecom_gfrt_[ix]) == NULL_TREE)
12516 ffecom_make_gfrt_ (ix);
12517 item = ffecom_gfrt_[ix];
12522 item = ffesymbol_hook (s).decl_tree;
12523 if (item == NULL_TREE)
12525 s = ffecom_sym_transform_ (s);
12526 item = ffesymbol_hook (s).decl_tree;
12529 assert (item != NULL);
12530 if (item == error_mark_node)
12532 if (!ffesymbol_hook (s).addr)
12533 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12537 case FFEBLD_opARRAYREF:
12538 return ffecom_arrayref_ (NULL_TREE, expr, 1);
12540 case FFEBLD_opCONTER:
12542 bt = ffeinfo_basictype (ffebld_info (expr));
12543 kt = ffeinfo_kindtype (ffebld_info (expr));
12545 item = ffecom_constantunion (&ffebld_constant_union
12546 (ffebld_conter (expr)), bt, kt,
12547 ffecom_tree_type[bt][kt]);
12548 if (item == error_mark_node)
12549 return error_mark_node;
12550 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12555 return error_mark_node;
12558 bt = ffeinfo_basictype (ffebld_info (expr));
12559 kt = ffeinfo_kindtype (ffebld_info (expr));
12561 item = ffecom_expr (expr);
12562 if (item == error_mark_node)
12563 return error_mark_node;
12565 /* The back end currently optimizes a bit too zealously for us, in that
12566 we fail JCB001 if the following block of code is omitted. It checks
12567 to see if the transformed expression is a symbol or array reference,
12568 and encloses it in a SAVE_EXPR if that is the case. */
12571 if ((TREE_CODE (item) == VAR_DECL)
12572 || (TREE_CODE (item) == PARM_DECL)
12573 || (TREE_CODE (item) == RESULT_DECL)
12574 || (TREE_CODE (item) == INDIRECT_REF)
12575 || (TREE_CODE (item) == ARRAY_REF)
12576 || (TREE_CODE (item) == COMPONENT_REF)
12578 || (TREE_CODE (item) == OFFSET_REF)
12580 || (TREE_CODE (item) == BUFFER_REF)
12581 || (TREE_CODE (item) == REALPART_EXPR)
12582 || (TREE_CODE (item) == IMAGPART_EXPR))
12584 item = ffecom_save_tree (item);
12587 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12592 assert ("fall-through error" == NULL);
12593 return error_mark_node;
12597 /* Obtain a temp var with given data type.
12599 size is FFETARGET_charactersizeNONE for a non-CHARACTER type
12600 or >= 0 for a CHARACTER type.
12602 elements is -1 for a scalar or > 0 for an array of type. */
12604 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12606 ffecom_make_tempvar (const char *commentary, tree type,
12607 ffetargetCharacterSize size, int elements)
12610 static int mynumber;
12612 assert (current_binding_level->prep_state < 2);
12614 if (type == error_mark_node)
12615 return error_mark_node;
12617 if (size != FFETARGET_charactersizeNONE)
12618 type = build_array_type (type,
12619 build_range_type (ffecom_f2c_ftnlen_type_node,
12620 ffecom_f2c_ftnlen_one_node,
12621 build_int_2 (size, 0)));
12622 if (elements != -1)
12623 type = build_array_type (type,
12624 build_range_type (integer_type_node,
12626 build_int_2 (elements - 1,
12628 t = build_decl (VAR_DECL,
12629 ffecom_get_invented_identifier ("__g77_%s_%d",
12634 t = start_decl (t, FALSE);
12635 finish_decl (t, NULL_TREE, FALSE);
12641 /* Prepare argument pointer to expression.
12643 Like ffecom_prepare_expr, except for expressions to be evaluated
12644 via ffecom_arg_ptr_to_expr. */
12647 ffecom_prepare_arg_ptr_to_expr (ffebld expr)
12649 /* ~~For now, it seems to be the same thing. */
12650 ffecom_prepare_expr (expr);
12654 /* End of preparations. */
12657 ffecom_prepare_end (void)
12659 int prep_state = current_binding_level->prep_state;
12661 assert (prep_state < 2);
12662 current_binding_level->prep_state = 2;
12664 return (prep_state == 1) ? TRUE : FALSE;
12667 /* Prepare expression.
12669 This is called before any code is generated for the current block.
12670 It scans the expression, declares any temporaries that might be needed
12671 during evaluation of the expression, and stores those temporaries in
12672 the appropriate "hook" fields of the expression. `dest', if not NULL,
12673 specifies the destination that ffecom_expr_ will see, in case that
12674 helps avoid generating unused temporaries.
12676 ~~Improve to avoid allocating unused temporaries by taking `dest'
12677 into account vis-a-vis aliasing requirements of complex/character
12681 ffecom_prepare_expr_ (ffebld expr, ffebld dest UNUSED)
12683 ffeinfoBasictype bt;
12684 ffeinfoKindtype kt;
12685 ffetargetCharacterSize sz;
12686 tree tempvar = NULL_TREE;
12688 assert (current_binding_level->prep_state < 2);
12693 bt = ffeinfo_basictype (ffebld_info (expr));
12694 kt = ffeinfo_kindtype (ffebld_info (expr));
12695 sz = ffeinfo_size (ffebld_info (expr));
12697 /* Generate whatever temporaries are needed to represent the result
12698 of the expression. */
12700 if (bt == FFEINFO_basictypeCHARACTER)
12702 while (ffebld_op (expr) == FFEBLD_opPAREN)
12703 expr = ffebld_left (expr);
12706 switch (ffebld_op (expr))
12709 /* Don't make temps for SYMTER, CONTER, etc. */
12710 if (ffebld_arity (expr) == 0)
12715 case FFEINFO_basictypeCOMPLEX:
12716 if (ffebld_op (expr) == FFEBLD_opFUNCREF)
12720 if (ffebld_op (ffebld_left (expr)) != FFEBLD_opSYMTER)
12723 s = ffebld_symter (ffebld_left (expr));
12724 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT
12725 || (ffesymbol_where (s) != FFEINFO_whereINTRINSIC
12726 && ! ffesymbol_is_f2c (s))
12727 || (ffesymbol_where (s) == FFEINFO_whereINTRINSIC
12728 && ! ffe_is_f2c_library ()))
12731 else if (ffebld_op (expr) == FFEBLD_opPOWER)
12733 /* Requires special treatment. There's no POW_CC function
12734 in libg2c, so POW_ZZ is used, which means we always
12735 need a double-complex temp, not a single-complex. */
12736 kt = FFEINFO_kindtypeREAL2;
12738 else if (ffebld_op (expr) != FFEBLD_opDIVIDE)
12739 /* The other ops don't need temps for complex operands. */
12742 /* ~~~Avoid making temps for some intrinsics, such as AIMAG(C),
12743 REAL(C). See 19990325-0.f, routine `check', for cases. */
12744 tempvar = ffecom_make_tempvar ("complex",
12746 [FFEINFO_basictypeCOMPLEX][kt],
12747 FFETARGET_charactersizeNONE,
12751 case FFEINFO_basictypeCHARACTER:
12752 if (ffebld_op (expr) != FFEBLD_opFUNCREF)
12755 if (sz == FFETARGET_charactersizeNONE)
12756 /* ~~Kludge alert! This should someday be fixed. */
12759 tempvar = ffecom_make_tempvar ("char", char_type_node, sz, -1);
12768 case FFEBLD_opPOWER:
12771 tree rtmp, ltmp, result;
12773 ltype = ffecom_type_expr (ffebld_left (expr));
12774 rtype = ffecom_type_expr (ffebld_right (expr));
12776 rtmp = ffecom_make_tempvar (rtype, FFETARGET_charactersizeNONE, -1);
12777 ltmp = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
12778 result = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
12780 tempvar = make_tree_vec (3);
12781 TREE_VEC_ELT (tempvar, 0) = rtmp;
12782 TREE_VEC_ELT (tempvar, 1) = ltmp;
12783 TREE_VEC_ELT (tempvar, 2) = result;
12788 case FFEBLD_opCONCATENATE:
12790 /* This gets special handling, because only one set of temps
12791 is needed for a tree of these -- the tree is treated as
12792 a flattened list of concatenations when generating code. */
12794 ffecomConcatList_ catlist;
12795 tree ltmp, itmp, result;
12799 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
12800 count = ffecom_concat_list_count_ (catlist);
12805 = ffecom_make_tempvar ("concat_len",
12806 ffecom_f2c_ftnlen_type_node,
12807 FFETARGET_charactersizeNONE, count);
12809 = ffecom_make_tempvar ("concat_item",
12810 ffecom_f2c_address_type_node,
12811 FFETARGET_charactersizeNONE, count);
12813 = ffecom_make_tempvar ("concat_res",
12815 ffecom_concat_list_maxlen_ (catlist),
12818 tempvar = make_tree_vec (3);
12819 TREE_VEC_ELT (tempvar, 0) = ltmp;
12820 TREE_VEC_ELT (tempvar, 1) = itmp;
12821 TREE_VEC_ELT (tempvar, 2) = result;
12824 for (i = 0; i < count; ++i)
12825 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist,
12828 ffecom_concat_list_kill_ (catlist);
12832 ffebld_nonter_set_hook (expr, tempvar);
12833 current_binding_level->prep_state = 1;
12838 case FFEBLD_opCONVERT:
12839 if (bt == FFEINFO_basictypeCHARACTER
12840 && ((ffebld_size_known (ffebld_left (expr))
12841 == FFETARGET_charactersizeNONE)
12842 || (ffebld_size_known (ffebld_left (expr)) >= sz)))
12843 tempvar = ffecom_make_tempvar ("convert", char_type_node, sz, -1);
12849 ffebld_nonter_set_hook (expr, tempvar);
12850 current_binding_level->prep_state = 1;
12853 /* Prepare subexpressions for this expr. */
12855 switch (ffebld_op (expr))
12857 case FFEBLD_opPERCENT_LOC:
12858 ffecom_prepare_ptr_to_expr (ffebld_left (expr));
12861 case FFEBLD_opPERCENT_VAL:
12862 case FFEBLD_opPERCENT_REF:
12863 ffecom_prepare_expr (ffebld_left (expr));
12866 case FFEBLD_opPERCENT_DESCR:
12867 ffecom_prepare_arg_ptr_to_expr (ffebld_left (expr));
12870 case FFEBLD_opITEM:
12876 item = ffebld_trail (item))
12877 if (ffebld_head (item) != NULL)
12878 ffecom_prepare_expr (ffebld_head (item));
12883 /* Need to handle character conversion specially. */
12884 switch (ffebld_arity (expr))
12887 ffecom_prepare_expr (ffebld_left (expr));
12888 ffecom_prepare_expr (ffebld_right (expr));
12892 ffecom_prepare_expr (ffebld_left (expr));
12903 /* Prepare expression for reading and writing.
12905 Like ffecom_prepare_expr, except for expressions to be evaluated
12906 via ffecom_expr_rw. */
12909 ffecom_prepare_expr_rw (tree type, ffebld expr)
12911 /* This is all we support for now. */
12912 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
12914 /* ~~For now, it seems to be the same thing. */
12915 ffecom_prepare_expr (expr);
12919 /* Prepare expression for writing.
12921 Like ffecom_prepare_expr, except for expressions to be evaluated
12922 via ffecom_expr_w. */
12925 ffecom_prepare_expr_w (tree type, ffebld expr)
12927 /* This is all we support for now. */
12928 assert (type == NULL_TREE || type == ffecom_type_expr (expr));
12930 /* ~~For now, it seems to be the same thing. */
12931 ffecom_prepare_expr (expr);
12935 /* Prepare expression for returning.
12937 Like ffecom_prepare_expr, except for expressions to be evaluated
12938 via ffecom_return_expr. */
12941 ffecom_prepare_return_expr (ffebld expr)
12943 assert (current_binding_level->prep_state < 2);
12945 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE
12946 && ffecom_is_altreturning_
12948 ffecom_prepare_expr (expr);
12951 /* Prepare pointer to expression.
12953 Like ffecom_prepare_expr, except for expressions to be evaluated
12954 via ffecom_ptr_to_expr. */
12957 ffecom_prepare_ptr_to_expr (ffebld expr)
12959 /* ~~For now, it seems to be the same thing. */
12960 ffecom_prepare_expr (expr);
12964 /* Transform expression into constant pointer-to-expression tree.
12966 If the expression can be transformed into a pointer-to-expression tree
12967 that is constant, that is done, and the tree returned. Else NULL_TREE
12970 That way, a caller can attempt to provide compile-time initialization
12971 of a variable and, if that fails, *then* choose to start a new block
12972 and resort to using temporaries, as appropriate. */
12975 ffecom_ptr_to_const_expr (ffebld expr)
12978 return integer_zero_node;
12980 if (ffebld_op (expr) == FFEBLD_opANY)
12981 return error_mark_node;
12983 if (ffebld_arity (expr) == 0
12984 && (ffebld_op (expr) != FFEBLD_opSYMTER
12985 || ffebld_where (expr) == FFEINFO_whereCOMMON
12986 || ffebld_where (expr) == FFEINFO_whereGLOBAL
12987 || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
12991 t = ffecom_ptr_to_expr (expr);
12992 assert (TREE_CONSTANT (t));
12999 /* ffecom_return_expr -- Returns return-value expr given alt return expr
13001 tree rtn; // NULL_TREE means use expand_null_return()
13002 ffebld expr; // NULL if no alt return expr to RETURN stmt
13003 rtn = ffecom_return_expr(expr);
13005 Based on the program unit type and other info (like return function
13006 type, return master function type when alternate ENTRY points,
13007 whether subroutine has any alternate RETURN points, etc), returns the
13008 appropriate expression to be returned to the caller, or NULL_TREE
13009 meaning no return value or the caller expects it to be returned somewhere
13010 else (which is handled by other parts of this module). */
13012 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13014 ffecom_return_expr (ffebld expr)
13018 switch (ffecom_primary_entry_kind_)
13020 case FFEINFO_kindPROGRAM:
13021 case FFEINFO_kindBLOCKDATA:
13025 case FFEINFO_kindSUBROUTINE:
13026 if (!ffecom_is_altreturning_)
13027 rtn = NULL_TREE; /* No alt returns, never an expr. */
13028 else if (expr == NULL)
13029 rtn = integer_zero_node;
13031 rtn = ffecom_expr (expr);
13034 case FFEINFO_kindFUNCTION:
13035 if ((ffecom_multi_retval_ != NULL_TREE)
13036 || (ffesymbol_basictype (ffecom_primary_entry_)
13037 == FFEINFO_basictypeCHARACTER)
13038 || ((ffesymbol_basictype (ffecom_primary_entry_)
13039 == FFEINFO_basictypeCOMPLEX)
13040 && (ffecom_num_entrypoints_ == 0)
13041 && ffesymbol_is_f2c (ffecom_primary_entry_)))
13042 { /* Value is returned by direct assignment
13043 into (implicit) dummy. */
13047 rtn = ffecom_func_result_;
13049 /* Spurious error if RETURN happens before first reference! So elide
13050 this code. In particular, for debugging registry, rtn should always
13051 be non-null after all, but TREE_USED won't be set until we encounter
13052 a reference in the code. Perfectly okay (but weird) code that,
13053 e.g., has "GOTO 20;10 RETURN;20 RTN=0;GOTO 10", would result in
13054 this diagnostic for no reason. Have people use -O -Wuninitialized
13055 and leave it to the back end to find obviously weird cases. */
13057 /* Used to "assert(rtn != NULL_TREE);" here, but it's kind of a valid
13058 situation; if the return value has never been referenced, it won't
13059 have a tree under 2pass mode. */
13060 if ((rtn == NULL_TREE)
13061 || !TREE_USED (rtn))
13063 ffebad_start (FFEBAD_RETURN_VALUE_UNSET);
13064 ffebad_here (0, ffesymbol_where_line (ffecom_primary_entry_),
13065 ffesymbol_where_column (ffecom_primary_entry_));
13066 ffebad_string (ffesymbol_text (ffesymbol_funcresult
13067 (ffecom_primary_entry_)));
13074 assert ("bad unit kind" == NULL);
13075 case FFEINFO_kindANY:
13076 rtn = error_mark_node;
13084 /* Do save_expr only if tree is not error_mark_node. */
13086 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13088 ffecom_save_tree (tree t)
13090 return save_expr (t);
13094 /* Start a compound statement (block). */
13096 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13098 ffecom_start_compstmt (void)
13100 bison_rule_pushlevel_ ();
13102 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
13104 /* Public entry point for front end to access start_decl. */
13106 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13108 ffecom_start_decl (tree decl, bool is_initialized)
13110 DECL_INITIAL (decl) = is_initialized ? error_mark_node : NULL_TREE;
13111 return start_decl (decl, FALSE);
13115 /* ffecom_sym_commit -- Symbol's state being committed to reality
13118 ffecom_sym_commit(s);
13120 Does whatever the backend needs when a symbol is committed after having
13121 been backtrackable for a period of time. */
13123 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13125 ffecom_sym_commit (ffesymbol s UNUSED)
13127 assert (!ffesymbol_retractable ());
13131 /* ffecom_sym_end_transition -- Perform end transition on all symbols
13133 ffecom_sym_end_transition();
13135 Does backend-specific stuff and also calls ffest_sym_end_transition
13136 to do the necessary FFE stuff.
13138 Backtracking is never enabled when this fn is called, so don't worry
13142 ffecom_sym_end_transition (ffesymbol s)
13146 assert (!ffesymbol_retractable ());
13148 s = ffest_sym_end_transition (s);
13150 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13151 if ((ffesymbol_kind (s) == FFEINFO_kindBLOCKDATA)
13152 && (ffesymbol_where (s) == FFEINFO_whereGLOBAL))
13154 ffecom_list_blockdata_
13155 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13156 FFEINTRIN_specNONE,
13157 FFEINTRIN_impNONE),
13158 ffecom_list_blockdata_);
13162 /* This is where we finally notice that a symbol has partial initialization
13163 and finalize it. */
13165 if (ffesymbol_accretion (s) != NULL)
13167 assert (ffesymbol_init (s) == NULL);
13168 ffecom_notify_init_symbol (s);
13170 else if (((st = ffesymbol_storage (s)) != NULL)
13171 && ((st = ffestorag_parent (st)) != NULL)
13172 && (ffestorag_accretion (st) != NULL))
13174 assert (ffestorag_init (st) == NULL);
13175 ffecom_notify_init_storage (st);
13178 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13179 if ((ffesymbol_kind (s) == FFEINFO_kindCOMMON)
13180 && (ffesymbol_where (s) == FFEINFO_whereLOCAL)
13181 && (ffesymbol_storage (s) != NULL))
13183 ffecom_list_common_
13184 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13185 FFEINTRIN_specNONE,
13186 FFEINTRIN_impNONE),
13187 ffecom_list_common_);
13194 /* ffecom_sym_exec_transition -- Perform exec transition on all symbols
13196 ffecom_sym_exec_transition();
13198 Does backend-specific stuff and also calls ffest_sym_exec_transition
13199 to do the necessary FFE stuff.
13201 See the long-winded description in ffecom_sym_learned for info
13202 on handling the situation where backtracking is inhibited. */
13205 ffecom_sym_exec_transition (ffesymbol s)
13207 s = ffest_sym_exec_transition (s);
13212 /* ffecom_sym_learned -- Initial or more info gained on symbol after exec
13215 s = ffecom_sym_learned(s);
13217 Called when a new symbol is seen after the exec transition or when more
13218 info (perhaps) is gained for an UNCERTAIN symbol. The symbol state when
13219 it arrives here is that all its latest info is updated already, so its
13220 state may be UNCERTAIN or UNDERSTOOD, it might already have the hook
13221 field filled in if its gone through here or exec_transition first, and
13224 The backend probably wants to check ffesymbol_retractable() to see if
13225 backtracking is in effect. If so, the FFE's changes to the symbol may
13226 be retracted (undone) or committed (ratified), at which time the
13227 appropriate ffecom_sym_retract or _commit function will be called
13230 If the backend has its own backtracking mechanism, great, use it so that
13231 committal is a simple operation. Though it doesn't make much difference,
13232 I suppose: the reason for tentative symbol evolution in the FFE is to
13233 enable error detection in weird incorrect statements early and to disable
13234 incorrect error detection on a correct statement. The backend is not
13235 likely to introduce any information that'll get involved in these
13236 considerations, so it is probably just fine that the implementation
13237 model for this fn and for _exec_transition is to not do anything
13238 (besides the required FFE stuff) if ffesymbol_retractable() returns TRUE
13239 and instead wait until ffecom_sym_commit is called (which it never
13240 will be as long as we're using ambiguity-detecting statement analysis in
13241 the FFE, which we are initially to shake out the code, but don't depend
13242 on this), otherwise go ahead and do whatever is needed.
13244 In essence, then, when this fn and _exec_transition get called while
13245 backtracking is enabled, a general mechanism would be to flag which (or
13246 both) of these were called (and in what order? neat question as to what
13247 might happen that I'm too lame to think through right now) and then when
13248 _commit is called reproduce the original calling sequence, if any, for
13249 the two fns (at which point backtracking will, of course, be disabled). */
13252 ffecom_sym_learned (ffesymbol s)
13254 ffestorag_exec_layout (s);
13259 /* ffecom_sym_retract -- Symbol's state being retracted from reality
13262 ffecom_sym_retract(s);
13264 Does whatever the backend needs when a symbol is retracted after having
13265 been backtrackable for a period of time. */
13267 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13269 ffecom_sym_retract (ffesymbol s UNUSED)
13271 assert (!ffesymbol_retractable ());
13273 #if 0 /* GCC doesn't commit any backtrackable sins,
13274 so nothing needed here. */
13275 switch (ffesymbol_hook (s).state)
13277 case 0: /* nothing happened yet. */
13280 case 1: /* exec transition happened. */
13283 case 2: /* learned happened. */
13286 case 3: /* learned then exec. */
13289 case 4: /* exec then learned. */
13293 assert ("bad hook state" == NULL);
13300 /* Create temporary gcc label. */
13302 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13304 ffecom_temp_label ()
13307 static int mynumber = 0;
13309 glabel = build_decl (LABEL_DECL,
13310 ffecom_get_invented_identifier ("__g77_label_%d",
13313 DECL_CONTEXT (glabel) = current_function_decl;
13314 DECL_MODE (glabel) = VOIDmode;
13320 /* Return an expression that is usable as an arg in a conditional context
13321 (IF, DO WHILE, .NOT., and so on).
13323 Use the one provided for the back end as of >2.6.0. */
13325 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13327 ffecom_truth_value (tree expr)
13329 return truthvalue_conversion (expr);
13333 /* Return the inversion of a truth value (the inversion of what
13334 ffecom_truth_value builds).
13336 Apparently invert_truthvalue, which is properly in the back end, is
13337 enough for now, so just use it. */
13339 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13341 ffecom_truth_value_invert (tree expr)
13343 return invert_truthvalue (ffecom_truth_value (expr));
13348 /* Return the tree that is the type of the expression, as would be
13349 returned in TREE_TYPE(ffecom_expr(expr)), without otherwise
13350 transforming the expression, generating temporaries, etc. */
13353 ffecom_type_expr (ffebld expr)
13355 ffeinfoBasictype bt;
13356 ffeinfoKindtype kt;
13359 assert (expr != NULL);
13361 bt = ffeinfo_basictype (ffebld_info (expr));
13362 kt = ffeinfo_kindtype (ffebld_info (expr));
13363 tree_type = ffecom_tree_type[bt][kt];
13365 switch (ffebld_op (expr))
13367 case FFEBLD_opCONTER:
13368 case FFEBLD_opSYMTER:
13369 case FFEBLD_opARRAYREF:
13370 case FFEBLD_opUPLUS:
13371 case FFEBLD_opPAREN:
13372 case FFEBLD_opUMINUS:
13374 case FFEBLD_opSUBTRACT:
13375 case FFEBLD_opMULTIPLY:
13376 case FFEBLD_opDIVIDE:
13377 case FFEBLD_opPOWER:
13379 case FFEBLD_opFUNCREF:
13380 case FFEBLD_opSUBRREF:
13384 case FFEBLD_opNEQV:
13386 case FFEBLD_opCONVERT:
13393 case FFEBLD_opPERCENT_LOC:
13396 case FFEBLD_opACCTER:
13397 case FFEBLD_opARRTER:
13398 case FFEBLD_opITEM:
13399 case FFEBLD_opSTAR:
13400 case FFEBLD_opBOUNDS:
13401 case FFEBLD_opREPEAT:
13402 case FFEBLD_opLABTER:
13403 case FFEBLD_opLABTOK:
13404 case FFEBLD_opIMPDO:
13405 case FFEBLD_opCONCATENATE:
13406 case FFEBLD_opSUBSTR:
13408 assert ("bad op for ffecom_type_expr" == NULL);
13409 /* Fall through. */
13411 return error_mark_node;
13415 /* Return PARM_DECL for arg#1 of master fn containing alternate ENTRY points
13417 If the PARM_DECL already exists, return it, else create it. It's an
13418 integer_type_node argument for the master function that implements a
13419 subroutine or function with more than one entrypoint and is bound at
13420 run time with the entrypoint number (0 for SUBROUTINE/FUNCTION, 1 for
13421 first ENTRY statement, and so on). */
13423 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13425 ffecom_which_entrypoint_decl ()
13427 assert (ffecom_which_entrypoint_decl_ != NULL_TREE);
13429 return ffecom_which_entrypoint_decl_;
13434 /* The following sections consists of private and public functions
13435 that have the same names and perform roughly the same functions
13436 as counterparts in the C front end. Changes in the C front end
13437 might affect how things should be done here. Only functions
13438 needed by the back end should be public here; the rest should
13439 be private (static in the C sense). Functions needed by other
13440 g77 front-end modules should be accessed by them via public
13441 ffecom_* names, which should themselves call private versions
13442 in this section so the private versions are easy to recognize
13443 when upgrading to a new gcc and finding interesting changes
13446 Functions named after rule "foo:" in c-parse.y are named
13447 "bison_rule_foo_" so they are easy to find. */
13449 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13452 bison_rule_pushlevel_ ()
13454 emit_line_note (input_filename, lineno);
13456 clear_last_expr ();
13457 expand_start_bindings (0);
13461 bison_rule_compstmt_ ()
13464 int keep = kept_level_p ();
13466 /* Make the temps go away. */
13468 current_binding_level->names = NULL_TREE;
13470 emit_line_note (input_filename, lineno);
13471 expand_end_bindings (getdecls (), keep, 0);
13472 t = poplevel (keep, 1, 0);
13477 /* Return a definition for a builtin function named NAME and whose data type
13478 is TYPE. TYPE should be a function type with argument types.
13479 FUNCTION_CODE tells later passes how to compile calls to this function.
13480 See tree.h for its possible values.
13482 If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
13483 the name to be called if we can't opencode the function. */
13486 builtin_function (const char *name, tree type, int function_code,
13487 enum built_in_class class,
13488 const char *library_name)
13490 tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
13491 DECL_EXTERNAL (decl) = 1;
13492 TREE_PUBLIC (decl) = 1;
13494 SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
13495 make_decl_rtl (decl, NULL);
13497 DECL_BUILT_IN_CLASS (decl) = class;
13498 DECL_FUNCTION_CODE (decl) = function_code;
13503 /* Handle when a new declaration NEWDECL
13504 has the same name as an old one OLDDECL
13505 in the same binding contour.
13506 Prints an error message if appropriate.
13508 If safely possible, alter OLDDECL to look like NEWDECL, and return 1.
13509 Otherwise, return 0. */
13512 duplicate_decls (tree newdecl, tree olddecl)
13514 int types_match = 1;
13515 int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
13516 && DECL_INITIAL (newdecl) != 0);
13517 tree oldtype = TREE_TYPE (olddecl);
13518 tree newtype = TREE_TYPE (newdecl);
13520 if (olddecl == newdecl)
13523 if (TREE_CODE (newtype) == ERROR_MARK
13524 || TREE_CODE (oldtype) == ERROR_MARK)
13527 /* New decl is completely inconsistent with the old one =>
13528 tell caller to replace the old one.
13529 This is always an error except in the case of shadowing a builtin. */
13530 if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
13533 /* For real parm decl following a forward decl,
13534 return 1 so old decl will be reused. */
13535 if (types_match && TREE_CODE (newdecl) == PARM_DECL
13536 && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
13539 /* The new declaration is the same kind of object as the old one.
13540 The declarations may partially match. Print warnings if they don't
13541 match enough. Ultimately, copy most of the information from the new
13542 decl to the old one, and keep using the old one. */
13544 if (TREE_CODE (olddecl) == FUNCTION_DECL
13545 && DECL_BUILT_IN (olddecl))
13547 /* A function declaration for a built-in function. */
13548 if (!TREE_PUBLIC (newdecl))
13550 else if (!types_match)
13552 /* Accept the return type of the new declaration if same modes. */
13553 tree oldreturntype = TREE_TYPE (TREE_TYPE (olddecl));
13554 tree newreturntype = TREE_TYPE (TREE_TYPE (newdecl));
13556 if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
13558 /* Function types may be shared, so we can't just modify
13559 the return type of olddecl's function type. */
13561 = build_function_type (newreturntype,
13562 TYPE_ARG_TYPES (TREE_TYPE (olddecl)));
13566 TREE_TYPE (olddecl) = newtype;
13572 else if (TREE_CODE (olddecl) == FUNCTION_DECL
13573 && DECL_SOURCE_LINE (olddecl) == 0)
13575 /* A function declaration for a predeclared function
13576 that isn't actually built in. */
13577 if (!TREE_PUBLIC (newdecl))
13579 else if (!types_match)
13581 /* If the types don't match, preserve volatility indication.
13582 Later on, we will discard everything else about the
13583 default declaration. */
13584 TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
13588 /* Copy all the DECL_... slots specified in the new decl
13589 except for any that we copy here from the old type.
13591 Past this point, we don't change OLDTYPE and NEWTYPE
13592 even if we change the types of NEWDECL and OLDDECL. */
13596 /* Merge the data types specified in the two decls. */
13597 if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
13598 TREE_TYPE (newdecl)
13599 = TREE_TYPE (olddecl)
13600 = TREE_TYPE (newdecl);
13602 /* Lay the type out, unless already done. */
13603 if (oldtype != TREE_TYPE (newdecl))
13605 if (TREE_TYPE (newdecl) != error_mark_node)
13606 layout_type (TREE_TYPE (newdecl));
13607 if (TREE_CODE (newdecl) != FUNCTION_DECL
13608 && TREE_CODE (newdecl) != TYPE_DECL
13609 && TREE_CODE (newdecl) != CONST_DECL)
13610 layout_decl (newdecl, 0);
13614 /* Since the type is OLDDECL's, make OLDDECL's size go with. */
13615 DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
13616 DECL_SIZE_UNIT (newdecl) = DECL_SIZE_UNIT (olddecl);
13617 if (TREE_CODE (olddecl) != FUNCTION_DECL)
13618 if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
13620 DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
13621 DECL_USER_ALIGN (newdecl) |= DECL_USER_ALIGN (olddecl);
13625 /* Keep the old rtl since we can safely use it. */
13626 COPY_DECL_RTL (olddecl, newdecl);
13628 /* Merge the type qualifiers. */
13629 if (DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl)
13630 && !TREE_THIS_VOLATILE (newdecl))
13631 TREE_THIS_VOLATILE (olddecl) = 0;
13632 if (TREE_READONLY (newdecl))
13633 TREE_READONLY (olddecl) = 1;
13634 if (TREE_THIS_VOLATILE (newdecl))
13636 TREE_THIS_VOLATILE (olddecl) = 1;
13637 if (TREE_CODE (newdecl) == VAR_DECL)
13638 make_var_volatile (newdecl);
13641 /* Keep source location of definition rather than declaration.
13642 Likewise, keep decl at outer scope. */
13643 if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
13644 || (DECL_CONTEXT (newdecl) != 0 && DECL_CONTEXT (olddecl) == 0))
13646 DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
13647 DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl);
13649 if (DECL_CONTEXT (olddecl) == 0
13650 && TREE_CODE (newdecl) != FUNCTION_DECL)
13651 DECL_CONTEXT (newdecl) = 0;
13654 /* Merge the unused-warning information. */
13655 if (DECL_IN_SYSTEM_HEADER (olddecl))
13656 DECL_IN_SYSTEM_HEADER (newdecl) = 1;
13657 else if (DECL_IN_SYSTEM_HEADER (newdecl))
13658 DECL_IN_SYSTEM_HEADER (olddecl) = 1;
13660 /* Merge the initialization information. */
13661 if (DECL_INITIAL (newdecl) == 0)
13662 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
13664 /* Merge the section attribute.
13665 We want to issue an error if the sections conflict but that must be
13666 done later in decl_attributes since we are called before attributes
13668 if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
13669 DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
13672 if (TREE_CODE (newdecl) == FUNCTION_DECL)
13674 DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
13675 DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
13679 /* If cannot merge, then use the new type and qualifiers,
13680 and don't preserve the old rtl. */
13683 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
13684 TREE_READONLY (olddecl) = TREE_READONLY (newdecl);
13685 TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl);
13686 TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl);
13689 /* Merge the storage class information. */
13690 /* For functions, static overrides non-static. */
13691 if (TREE_CODE (newdecl) == FUNCTION_DECL)
13693 TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
13694 /* This is since we don't automatically
13695 copy the attributes of NEWDECL into OLDDECL. */
13696 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
13697 /* If this clears `static', clear it in the identifier too. */
13698 if (! TREE_PUBLIC (olddecl))
13699 TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
13701 if (DECL_EXTERNAL (newdecl))
13703 TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
13704 DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
13705 /* An extern decl does not override previous storage class. */
13706 TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
13710 TREE_STATIC (olddecl) = TREE_STATIC (newdecl);
13711 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
13714 /* If either decl says `inline', this fn is inline,
13715 unless its definition was passed already. */
13716 if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
13717 DECL_INLINE (olddecl) = 1;
13718 DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
13720 /* Get rid of any built-in function if new arg types don't match it
13721 or if we have a function definition. */
13722 if (TREE_CODE (newdecl) == FUNCTION_DECL
13723 && DECL_BUILT_IN (olddecl)
13724 && (!types_match || new_is_definition))
13726 TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
13727 DECL_BUILT_IN_CLASS (olddecl) = NOT_BUILT_IN;
13730 /* If redeclaring a builtin function, and not a definition,
13732 Also preserve various other info from the definition. */
13733 if (TREE_CODE (newdecl) == FUNCTION_DECL && !new_is_definition)
13735 if (DECL_BUILT_IN (olddecl))
13737 DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
13738 DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
13741 DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
13742 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
13743 DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
13744 DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
13747 /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
13748 But preserve olddecl's DECL_UID. */
13750 register unsigned olddecl_uid = DECL_UID (olddecl);
13752 memcpy ((char *) olddecl + sizeof (struct tree_common),
13753 (char *) newdecl + sizeof (struct tree_common),
13754 sizeof (struct tree_decl) - sizeof (struct tree_common));
13755 DECL_UID (olddecl) = olddecl_uid;
13761 /* Finish processing of a declaration;
13762 install its initial value.
13763 If the length of an array type is not known before,
13764 it must be determined now, from the initial value, or it is an error. */
13767 finish_decl (tree decl, tree init, bool is_top_level)
13769 register tree type = TREE_TYPE (decl);
13770 int was_incomplete = (DECL_SIZE (decl) == 0);
13771 bool at_top_level = (current_binding_level == global_binding_level);
13772 bool top_level = is_top_level || at_top_level;
13774 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
13776 assert (!is_top_level || !at_top_level);
13778 if (TREE_CODE (decl) == PARM_DECL)
13779 assert (init == NULL_TREE);
13780 /* Remember that PARM_DECL doesn't have a DECL_INITIAL field per se -- it
13781 overlaps DECL_ARG_TYPE. */
13782 else if (init == NULL_TREE)
13783 assert (DECL_INITIAL (decl) == NULL_TREE);
13785 assert (DECL_INITIAL (decl) == error_mark_node);
13787 if (init != NULL_TREE)
13789 if (TREE_CODE (decl) != TYPE_DECL)
13790 DECL_INITIAL (decl) = init;
13793 /* typedef foo = bar; store the type of bar as the type of foo. */
13794 TREE_TYPE (decl) = TREE_TYPE (init);
13795 DECL_INITIAL (decl) = init = 0;
13799 /* Deduce size of array from initialization, if not already known */
13801 if (TREE_CODE (type) == ARRAY_TYPE
13802 && TYPE_DOMAIN (type) == 0
13803 && TREE_CODE (decl) != TYPE_DECL)
13805 assert (top_level);
13806 assert (was_incomplete);
13808 layout_decl (decl, 0);
13811 if (TREE_CODE (decl) == VAR_DECL)
13813 if (DECL_SIZE (decl) == NULL_TREE
13814 && TYPE_SIZE (TREE_TYPE (decl)) != NULL_TREE)
13815 layout_decl (decl, 0);
13817 if (DECL_SIZE (decl) == NULL_TREE
13818 && (TREE_STATIC (decl)
13820 /* A static variable with an incomplete type is an error if it is
13821 initialized. Also if it is not file scope. Otherwise, let it
13822 through, but if it is not `extern' then it may cause an error
13824 (DECL_INITIAL (decl) != 0 || DECL_CONTEXT (decl) != 0)
13826 /* An automatic variable with an incomplete type is an error. */
13827 !DECL_EXTERNAL (decl)))
13829 assert ("storage size not known" == NULL);
13833 if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
13834 && (DECL_SIZE (decl) != 0)
13835 && (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST))
13837 assert ("storage size not constant" == NULL);
13842 /* Output the assembler code and/or RTL code for variables and functions,
13843 unless the type is an undefined structure or union. If not, it will get
13844 done when the type is completed. */
13846 if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
13848 rest_of_decl_compilation (decl, NULL,
13849 DECL_CONTEXT (decl) == 0,
13852 if (DECL_CONTEXT (decl) != 0)
13854 /* Recompute the RTL of a local array now if it used to be an
13855 incomplete type. */
13857 && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
13859 /* If we used it already as memory, it must stay in memory. */
13860 TREE_ADDRESSABLE (decl) = TREE_USED (decl);
13861 /* If it's still incomplete now, no init will save it. */
13862 if (DECL_SIZE (decl) == 0)
13863 DECL_INITIAL (decl) = 0;
13864 expand_decl (decl);
13866 /* Compute and store the initial value. */
13867 if (TREE_CODE (decl) != FUNCTION_DECL)
13868 expand_decl_init (decl);
13871 else if (TREE_CODE (decl) == TYPE_DECL)
13873 rest_of_decl_compilation (decl, NULL,
13874 DECL_CONTEXT (decl) == 0,
13878 /* At the end of a declaration, throw away any variable type sizes of types
13879 defined inside that declaration. There is no use computing them in the
13880 following function definition. */
13881 if (current_binding_level == global_binding_level)
13882 get_pending_sizes ();
13885 /* Finish up a function declaration and compile that function
13886 all the way to assembler language output. The free the storage
13887 for the function definition.
13889 This is called after parsing the body of the function definition.
13891 NESTED is nonzero if the function being finished is nested in another. */
13894 finish_function (int nested)
13896 register tree fndecl = current_function_decl;
13898 assert (fndecl != NULL_TREE);
13899 if (TREE_CODE (fndecl) != ERROR_MARK)
13902 assert (DECL_CONTEXT (fndecl) != NULL_TREE);
13904 assert (DECL_CONTEXT (fndecl) == NULL_TREE);
13907 /* TREE_READONLY (fndecl) = 1;
13908 This caused &foo to be of type ptr-to-const-function
13909 which then got a warning when stored in a ptr-to-function variable. */
13911 poplevel (1, 0, 1);
13913 if (TREE_CODE (fndecl) != ERROR_MARK)
13915 BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
13917 /* Must mark the RESULT_DECL as being in this function. */
13919 DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
13921 /* Obey `register' declarations if `setjmp' is called in this fn. */
13922 /* Generate rtl for function exit. */
13923 expand_function_end (input_filename, lineno, 0);
13925 /* If this is a nested function, protect the local variables in the stack
13926 above us from being collected while we're compiling this function. */
13928 ggc_push_context ();
13930 /* Run the optimizers and output the assembler code for this function. */
13931 rest_of_compilation (fndecl);
13933 /* Undo the GC context switch. */
13935 ggc_pop_context ();
13938 if (TREE_CODE (fndecl) != ERROR_MARK
13940 && DECL_SAVED_INSNS (fndecl) == 0)
13942 /* Stop pointing to the local nodes about to be freed. */
13943 /* But DECL_INITIAL must remain nonzero so we know this was an actual
13944 function definition. */
13945 /* For a nested function, this is done in pop_f_function_context. */
13946 /* If rest_of_compilation set this to 0, leave it 0. */
13947 if (DECL_INITIAL (fndecl) != 0)
13948 DECL_INITIAL (fndecl) = error_mark_node;
13949 DECL_ARGUMENTS (fndecl) = 0;
13954 /* Let the error reporting routines know that we're outside a function.
13955 For a nested function, this value is used in pop_c_function_context
13956 and then reset via pop_function_context. */
13957 ffecom_outer_function_decl_ = current_function_decl = NULL;
13961 /* Plug-in replacement for identifying the name of a decl and, for a
13962 function, what we call it in diagnostics. For now, "program unit"
13963 should suffice, since it's a bit of a hassle to figure out which
13964 of several kinds of things it is. Note that it could conceivably
13965 be a statement function, which probably isn't really a program unit
13966 per se, but if that comes up, it should be easy to check (being a
13967 nested function and all). */
13969 static const char *
13970 lang_printable_name (tree decl, int v)
13972 /* Just to keep GCC quiet about the unused variable.
13973 In theory, differing values of V should produce different
13978 if (TREE_CODE (decl) == ERROR_MARK)
13979 return "erroneous code";
13980 return IDENTIFIER_POINTER (DECL_NAME (decl));
13984 /* g77's function to print out name of current function that caused
13989 lang_print_error_function (diagnostic_context *context __attribute__((unused)),
13992 static ffeglobal last_g = NULL;
13993 static ffesymbol last_s = NULL;
13998 if ((ffecom_primary_entry_ == NULL)
13999 || (ffesymbol_global (ffecom_primary_entry_) == NULL))
14007 g = ffesymbol_global (ffecom_primary_entry_);
14008 if (ffecom_nested_entry_ == NULL)
14010 s = ffecom_primary_entry_;
14011 switch (ffesymbol_kind (s))
14013 case FFEINFO_kindFUNCTION:
14017 case FFEINFO_kindSUBROUTINE:
14018 kind = "subroutine";
14021 case FFEINFO_kindPROGRAM:
14025 case FFEINFO_kindBLOCKDATA:
14026 kind = "block-data";
14030 kind = ffeinfo_kind_message (ffesymbol_kind (s));
14036 s = ffecom_nested_entry_;
14037 kind = "statement function";
14041 if ((last_g != g) || (last_s != s))
14044 fprintf (stderr, "%s: ", file);
14047 fprintf (stderr, "Outside of any program unit:\n");
14050 const char *name = ffesymbol_text (s);
14052 fprintf (stderr, "In %s `%s':\n", kind, name);
14061 /* Similar to `lookup_name' but look only at current binding level. */
14064 lookup_name_current_level (tree name)
14068 if (current_binding_level == global_binding_level)
14069 return IDENTIFIER_GLOBAL_VALUE (name);
14071 if (IDENTIFIER_LOCAL_VALUE (name) == 0)
14074 for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
14075 if (DECL_NAME (t) == name)
14081 /* Create a new `struct binding_level'. */
14083 static struct binding_level *
14084 make_binding_level ()
14087 return (struct binding_level *) xmalloc (sizeof (struct binding_level));
14090 /* Save and restore the variables in this file and elsewhere
14091 that keep track of the progress of compilation of the current function.
14092 Used for nested functions. */
14096 struct f_function *next;
14098 tree shadowed_labels;
14099 struct binding_level *binding_level;
14102 struct f_function *f_function_chain;
14104 /* Restore the variables used during compilation of a C function. */
14107 pop_f_function_context ()
14109 struct f_function *p = f_function_chain;
14112 /* Bring back all the labels that were shadowed. */
14113 for (link = shadowed_labels; link; link = TREE_CHAIN (link))
14114 if (DECL_NAME (TREE_VALUE (link)) != 0)
14115 IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)))
14116 = TREE_VALUE (link);
14118 if (current_function_decl != error_mark_node
14119 && DECL_SAVED_INSNS (current_function_decl) == 0)
14121 /* Stop pointing to the local nodes about to be freed. */
14122 /* But DECL_INITIAL must remain nonzero so we know this was an actual
14123 function definition. */
14124 DECL_INITIAL (current_function_decl) = error_mark_node;
14125 DECL_ARGUMENTS (current_function_decl) = 0;
14128 pop_function_context ();
14130 f_function_chain = p->next;
14132 named_labels = p->named_labels;
14133 shadowed_labels = p->shadowed_labels;
14134 current_binding_level = p->binding_level;
14139 /* Save and reinitialize the variables
14140 used during compilation of a C function. */
14143 push_f_function_context ()
14145 struct f_function *p
14146 = (struct f_function *) xmalloc (sizeof (struct f_function));
14148 push_function_context ();
14150 p->next = f_function_chain;
14151 f_function_chain = p;
14153 p->named_labels = named_labels;
14154 p->shadowed_labels = shadowed_labels;
14155 p->binding_level = current_binding_level;
14159 push_parm_decl (tree parm)
14161 int old_immediate_size_expand = immediate_size_expand;
14163 /* Don't try computing parm sizes now -- wait till fn is called. */
14165 immediate_size_expand = 0;
14167 /* Fill in arg stuff. */
14169 DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
14170 DECL_ARG_TYPE_AS_WRITTEN (parm) = TREE_TYPE (parm);
14171 TREE_READONLY (parm) = 1; /* All implementation args are read-only. */
14173 parm = pushdecl (parm);
14175 immediate_size_expand = old_immediate_size_expand;
14177 finish_decl (parm, NULL_TREE, FALSE);
14180 /* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, if appropriate. */
14183 pushdecl_top_level (x)
14187 register struct binding_level *b = current_binding_level;
14188 register tree f = current_function_decl;
14190 current_binding_level = global_binding_level;
14191 current_function_decl = NULL_TREE;
14193 current_binding_level = b;
14194 current_function_decl = f;
14198 /* Store the list of declarations of the current level.
14199 This is done for the parameter declarations of a function being defined,
14200 after they are modified in the light of any missing parameters. */
14206 return current_binding_level->names = decls;
14209 /* Store the parameter declarations into the current function declaration.
14210 This is called after parsing the parameter declarations, before
14211 digesting the body of the function.
14213 For an old-style definition, modify the function's type
14214 to specify at least the number of arguments. */
14217 store_parm_decls (int is_main_program UNUSED)
14219 register tree fndecl = current_function_decl;
14221 if (fndecl == error_mark_node)
14224 /* This is a chain of PARM_DECLs from old-style parm declarations. */
14225 DECL_ARGUMENTS (fndecl) = storedecls (nreverse (getdecls ()));
14227 /* Initialize the RTL code for the function. */
14229 init_function_start (fndecl, input_filename, lineno);
14231 /* Set up parameters and prepare for return, for the function. */
14233 expand_function_start (fndecl, 0);
14237 start_decl (tree decl, bool is_top_level)
14240 bool at_top_level = (current_binding_level == global_binding_level);
14241 bool top_level = is_top_level || at_top_level;
14243 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
14245 assert (!is_top_level || !at_top_level);
14247 if (DECL_INITIAL (decl) != NULL_TREE)
14249 assert (DECL_INITIAL (decl) == error_mark_node);
14250 assert (!DECL_EXTERNAL (decl));
14252 else if (top_level)
14253 assert ((TREE_STATIC (decl) == 1) || DECL_EXTERNAL (decl) == 1);
14255 /* For Fortran, we by default put things in .common when possible. */
14256 DECL_COMMON (decl) = 1;
14258 /* Add this decl to the current binding level. TEM may equal DECL or it may
14259 be a previous decl of the same name. */
14261 tem = pushdecl_top_level (decl);
14263 tem = pushdecl (decl);
14265 /* For a local variable, define the RTL now. */
14267 /* But not if this is a duplicate decl and we preserved the rtl from the
14268 previous one (which may or may not happen). */
14269 && !DECL_RTL_SET_P (tem))
14271 if (TYPE_SIZE (TREE_TYPE (tem)) != 0)
14273 else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
14274 && DECL_INITIAL (tem) != 0)
14281 /* Create the FUNCTION_DECL for a function definition.
14282 DECLSPECS and DECLARATOR are the parts of the declaration;
14283 they describe the function's name and the type it returns,
14284 but twisted together in a fashion that parallels the syntax of C.
14286 This function creates a binding context for the function body
14287 as well as setting up the FUNCTION_DECL in current_function_decl.
14289 Returns 1 on success. If the DECLARATOR is not suitable for a function
14290 (it defines a datum instead), we return 0, which tells
14291 yyparse to report a parse error.
14293 NESTED is nonzero for a function nested within another function. */
14296 start_function (tree name, tree type, int nested, int public)
14300 int old_immediate_size_expand = immediate_size_expand;
14303 shadowed_labels = 0;
14305 /* Don't expand any sizes in the return type of the function. */
14306 immediate_size_expand = 0;
14311 assert (current_function_decl != NULL_TREE);
14312 assert (DECL_CONTEXT (current_function_decl) == NULL_TREE);
14316 assert (current_function_decl == NULL_TREE);
14319 if (TREE_CODE (type) == ERROR_MARK)
14320 decl1 = current_function_decl = error_mark_node;
14323 decl1 = build_decl (FUNCTION_DECL,
14326 TREE_PUBLIC (decl1) = public ? 1 : 0;
14328 DECL_INLINE (decl1) = 1;
14329 TREE_STATIC (decl1) = 1;
14330 DECL_EXTERNAL (decl1) = 0;
14332 announce_function (decl1);
14334 /* Make the init_value nonzero so pushdecl knows this is not tentative.
14335 error_mark_node is replaced below (in poplevel) with the BLOCK. */
14336 DECL_INITIAL (decl1) = error_mark_node;
14338 /* Record the decl so that the function name is defined. If we already have
14339 a decl for this name, and it is a FUNCTION_DECL, use the old decl. */
14341 current_function_decl = pushdecl (decl1);
14345 ffecom_outer_function_decl_ = current_function_decl;
14348 current_binding_level->prep_state = 2;
14350 if (TREE_CODE (current_function_decl) != ERROR_MARK)
14352 make_decl_rtl (current_function_decl, NULL);
14354 restype = TREE_TYPE (TREE_TYPE (current_function_decl));
14355 DECL_RESULT (current_function_decl)
14356 = build_decl (RESULT_DECL, NULL_TREE, restype);
14359 if (!nested && (TREE_CODE (current_function_decl) != ERROR_MARK))
14360 TREE_ADDRESSABLE (current_function_decl) = 1;
14362 immediate_size_expand = old_immediate_size_expand;
14365 /* Here are the public functions the GNU back end needs. */
14368 convert (type, expr)
14371 register tree e = expr;
14372 register enum tree_code code = TREE_CODE (type);
14374 if (type == TREE_TYPE (e)
14375 || TREE_CODE (e) == ERROR_MARK)
14377 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
14378 return fold (build1 (NOP_EXPR, type, e));
14379 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
14380 || code == ERROR_MARK)
14381 return error_mark_node;
14382 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
14384 assert ("void value not ignored as it ought to be" == NULL);
14385 return error_mark_node;
14387 if (code == VOID_TYPE)
14388 return build1 (CONVERT_EXPR, type, e);
14389 if ((code != RECORD_TYPE)
14390 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
14391 e = ffecom_1 (REALPART_EXPR, TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e))),
14393 if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
14394 return fold (convert_to_integer (type, e));
14395 if (code == POINTER_TYPE)
14396 return fold (convert_to_pointer (type, e));
14397 if (code == REAL_TYPE)
14398 return fold (convert_to_real (type, e));
14399 if (code == COMPLEX_TYPE)
14400 return fold (convert_to_complex (type, e));
14401 if (code == RECORD_TYPE)
14402 return fold (ffecom_convert_to_complex_ (type, e));
14404 assert ("conversion to non-scalar type requested" == NULL);
14405 return error_mark_node;
14408 /* integrate_decl_tree calls this function, but since we don't use the
14409 DECL_LANG_SPECIFIC field, this is a no-op. */
14412 copy_lang_decl (node)
14417 /* Return the list of declarations of the current level.
14418 Note that this list is in reverse order unless/until
14419 you nreverse it; and when you do nreverse it, you must
14420 store the result back using `storedecls' or you will lose. */
14425 return current_binding_level->names;
14428 /* Nonzero if we are currently in the global binding level. */
14431 global_bindings_p ()
14433 return current_binding_level == global_binding_level;
14436 /* Print an error message for invalid use of an incomplete type.
14437 VALUE is the expression that was used (or 0 if that isn't known)
14438 and TYPE is the type that was invalid. */
14441 incomplete_type_error (value, type)
14445 if (TREE_CODE (type) == ERROR_MARK)
14448 assert ("incomplete type?!?" == NULL);
14451 /* Mark ARG for GC. */
14453 mark_binding_level (void *arg)
14455 struct binding_level *level = *(struct binding_level **) arg;
14459 ggc_mark_tree (level->names);
14460 ggc_mark_tree (level->blocks);
14461 ggc_mark_tree (level->this_block);
14462 level = level->level_chain;
14467 init_decl_processing ()
14469 static tree *const tree_roots[] = {
14470 ¤t_function_decl,
14472 &ffecom_tree_fun_type_void,
14473 &ffecom_integer_zero_node,
14474 &ffecom_integer_one_node,
14475 &ffecom_tree_subr_type,
14476 &ffecom_tree_ptr_to_subr_type,
14477 &ffecom_tree_blockdata_type,
14478 &ffecom_tree_xargc_,
14479 &ffecom_f2c_integer_type_node,
14480 &ffecom_f2c_ptr_to_integer_type_node,
14481 &ffecom_f2c_address_type_node,
14482 &ffecom_f2c_real_type_node,
14483 &ffecom_f2c_ptr_to_real_type_node,
14484 &ffecom_f2c_doublereal_type_node,
14485 &ffecom_f2c_complex_type_node,
14486 &ffecom_f2c_doublecomplex_type_node,
14487 &ffecom_f2c_longint_type_node,
14488 &ffecom_f2c_logical_type_node,
14489 &ffecom_f2c_flag_type_node,
14490 &ffecom_f2c_ftnlen_type_node,
14491 &ffecom_f2c_ftnlen_zero_node,
14492 &ffecom_f2c_ftnlen_one_node,
14493 &ffecom_f2c_ftnlen_two_node,
14494 &ffecom_f2c_ptr_to_ftnlen_type_node,
14495 &ffecom_f2c_ftnint_type_node,
14496 &ffecom_f2c_ptr_to_ftnint_type_node,
14497 &ffecom_outer_function_decl_,
14498 &ffecom_previous_function_decl_,
14499 &ffecom_which_entrypoint_decl_,
14500 &ffecom_float_zero_,
14501 &ffecom_float_half_,
14502 &ffecom_double_zero_,
14503 &ffecom_double_half_,
14504 &ffecom_func_result_,
14505 &ffecom_func_length_,
14506 &ffecom_multi_type_node_,
14507 &ffecom_multi_retval_,
14515 /* Record our roots. */
14516 for (i = 0; i < ARRAY_SIZE (tree_roots); i++)
14517 ggc_add_tree_root (tree_roots[i], 1);
14518 ggc_add_tree_root (&ffecom_tree_type[0][0],
14519 FFEINFO_basictype*FFEINFO_kindtype);
14520 ggc_add_tree_root (&ffecom_tree_fun_type[0][0],
14521 FFEINFO_basictype*FFEINFO_kindtype);
14522 ggc_add_tree_root (&ffecom_tree_ptr_to_fun_type[0][0],
14523 FFEINFO_basictype*FFEINFO_kindtype);
14524 ggc_add_tree_root (ffecom_gfrt_, FFECOM_gfrt);
14525 ggc_add_root (¤t_binding_level, 1, sizeof current_binding_level,
14526 mark_binding_level);
14527 ggc_add_root (&free_binding_level, 1, sizeof current_binding_level,
14528 mark_binding_level);
14529 ggc_add_root (&tracker_head, 1, sizeof tracker_head, mark_tracker_head);
14535 init_parse (filename)
14536 const char *filename;
14538 /* Open input file. */
14539 if (filename == 0 || !strcmp (filename, "-"))
14542 filename = "stdin";
14545 finput = fopen (filename, "r");
14547 fatal_io_error ("can't open %s", filename);
14549 #ifdef IO_BUFFER_SIZE
14550 setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);
14553 /* Make identifier nodes long enough for the language-specific slots. */
14554 set_identifier_size (sizeof (struct lang_identifier));
14555 decl_printable_name = lang_printable_name;
14557 print_error_function = lang_print_error_function;
14569 /* Delete the node BLOCK from the current binding level.
14570 This is used for the block inside a stmt expr ({...})
14571 so that the block can be reinserted where appropriate. */
14574 delete_block (block)
14578 if (current_binding_level->blocks == block)
14579 current_binding_level->blocks = TREE_CHAIN (block);
14580 for (t = current_binding_level->blocks; t;)
14582 if (TREE_CHAIN (t) == block)
14583 TREE_CHAIN (t) = TREE_CHAIN (block);
14585 t = TREE_CHAIN (t);
14587 TREE_CHAIN (block) = NULL;
14588 /* Clear TREE_USED which is always set by poplevel.
14589 The flag is set again if insert_block is called. */
14590 TREE_USED (block) = 0;
14594 insert_block (block)
14597 TREE_USED (block) = 1;
14598 current_binding_level->blocks
14599 = chainon (current_binding_level->blocks, block);
14602 /* Each front end provides its own. */
14603 static void ffe_init PARAMS ((void));
14604 static void ffe_finish PARAMS ((void));
14605 static void ffe_init_options PARAMS ((void));
14607 struct lang_hooks lang_hooks = {ffe_init,
14611 NULL /* post_options */};
14613 /* used by print-tree.c */
14616 lang_print_xnode (file, node, indent)
14626 ffe_terminate_0 ();
14628 if (ffe_is_ffedebug ())
14629 malloc_pool_display (malloc_pool_image ());
14638 /* Return the typed-based alias set for T, which may be an expression
14639 or a type. Return -1 if we don't do anything special. */
14642 lang_get_alias_set (t)
14643 tree t ATTRIBUTE_UNUSED;
14645 /* We do not wish to use alias-set based aliasing at all. Used in the
14646 extreme (every object with its own set, with equivalences recorded)
14647 it might be helpful, but there are problems when it comes to inlining.
14648 We get on ok with flag_argument_noalias, and alias-set aliasing does
14649 currently limit how stack slots can be reused, which is a lose. */
14654 ffe_init_options ()
14656 /* Set default options for Fortran. */
14657 flag_move_all_movables = 1;
14658 flag_reduce_all_givs = 1;
14659 flag_argument_noalias = 2;
14660 flag_errno_math = 0;
14661 flag_complex_divide_method = 1;
14667 /* If the file is output from cpp, it should contain a first line
14668 `# 1 "real-filename"', and the current design of gcc (toplev.c
14669 in particular and the way it sets up information relied on by
14670 INCLUDE) requires that we read this now, and store the
14671 "real-filename" info in master_input_filename. Ask the lexer
14672 to try doing this. */
14673 ffelex_hash_kludge (finput);
14677 mark_addressable (exp)
14680 register tree x = exp;
14682 switch (TREE_CODE (x))
14685 case COMPONENT_REF:
14687 x = TREE_OPERAND (x, 0);
14691 TREE_ADDRESSABLE (x) = 1;
14698 if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)
14699 && DECL_NONLOCAL (x))
14701 if (TREE_PUBLIC (x))
14703 assert ("address of global register var requested" == NULL);
14706 assert ("address of register variable requested" == NULL);
14708 else if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x))
14710 if (TREE_PUBLIC (x))
14712 assert ("address of global register var requested" == NULL);
14715 assert ("address of register var requested" == NULL);
14717 put_var_into_stack (x);
14720 case FUNCTION_DECL:
14721 TREE_ADDRESSABLE (x) = 1;
14722 #if 0 /* poplevel deals with this now. */
14723 if (DECL_CONTEXT (x) == 0)
14724 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
14732 /* If DECL has a cleanup, build and return that cleanup here.
14733 This is a callback called by expand_expr. */
14736 maybe_build_cleanup (decl)
14739 /* There are no cleanups in Fortran. */
14743 /* Exit a binding level.
14744 Pop the level off, and restore the state of the identifier-decl mappings
14745 that were in effect when this level was entered.
14747 If KEEP is nonzero, this level had explicit declarations, so
14748 and create a "block" (a BLOCK node) for the level
14749 to record its declarations and subblocks for symbol table output.
14751 If FUNCTIONBODY is nonzero, this level is the body of a function,
14752 so create a block as if KEEP were set and also clear out all
14755 If REVERSE is nonzero, reverse the order of decls before putting
14756 them into the BLOCK. */
14759 poplevel (keep, reverse, functionbody)
14764 register tree link;
14765 /* The chain of decls was accumulated in reverse order.
14766 Put it into forward order, just for cleanliness. */
14768 tree subblocks = current_binding_level->blocks;
14771 int block_previously_created;
14773 /* Get the decls in the order they were written.
14774 Usually current_binding_level->names is in reverse order.
14775 But parameter decls were previously put in forward order. */
14778 current_binding_level->names
14779 = decls = nreverse (current_binding_level->names);
14781 decls = current_binding_level->names;
14783 /* Output any nested inline functions within this block
14784 if they weren't already output. */
14786 for (decl = decls; decl; decl = TREE_CHAIN (decl))
14787 if (TREE_CODE (decl) == FUNCTION_DECL
14788 && ! TREE_ASM_WRITTEN (decl)
14789 && DECL_INITIAL (decl) != 0
14790 && TREE_ADDRESSABLE (decl))
14792 /* If this decl was copied from a file-scope decl
14793 on account of a block-scope extern decl,
14794 propagate TREE_ADDRESSABLE to the file-scope decl.
14796 DECL_ABSTRACT_ORIGIN can be set to itself if warn_return_type is
14797 true, since then the decl goes through save_for_inline_copying. */
14798 if (DECL_ABSTRACT_ORIGIN (decl) != 0
14799 && DECL_ABSTRACT_ORIGIN (decl) != decl)
14800 TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
14801 else if (DECL_SAVED_INSNS (decl) != 0)
14803 push_function_context ();
14804 output_inline_function (decl);
14805 pop_function_context ();
14809 /* If there were any declarations or structure tags in that level,
14810 or if this level is a function body,
14811 create a BLOCK to record them for the life of this function. */
14814 block_previously_created = (current_binding_level->this_block != 0);
14815 if (block_previously_created)
14816 block = current_binding_level->this_block;
14817 else if (keep || functionbody)
14818 block = make_node (BLOCK);
14821 BLOCK_VARS (block) = decls;
14822 BLOCK_SUBBLOCKS (block) = subblocks;
14825 /* In each subblock, record that this is its superior. */
14827 for (link = subblocks; link; link = TREE_CHAIN (link))
14828 BLOCK_SUPERCONTEXT (link) = block;
14830 /* Clear out the meanings of the local variables of this level. */
14832 for (link = decls; link; link = TREE_CHAIN (link))
14834 if (DECL_NAME (link) != 0)
14836 /* If the ident. was used or addressed via a local extern decl,
14837 don't forget that fact. */
14838 if (DECL_EXTERNAL (link))
14840 if (TREE_USED (link))
14841 TREE_USED (DECL_NAME (link)) = 1;
14842 if (TREE_ADDRESSABLE (link))
14843 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
14845 IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0;
14849 /* If the level being exited is the top level of a function,
14850 check over all the labels, and clear out the current
14851 (function local) meanings of their names. */
14855 /* If this is the top level block of a function,
14856 the vars are the function's parameters.
14857 Don't leave them in the BLOCK because they are
14858 found in the FUNCTION_DECL instead. */
14860 BLOCK_VARS (block) = 0;
14863 /* Pop the current level, and free the structure for reuse. */
14866 register struct binding_level *level = current_binding_level;
14867 current_binding_level = current_binding_level->level_chain;
14869 level->level_chain = free_binding_level;
14870 free_binding_level = level;
14873 /* Dispose of the block that we just made inside some higher level. */
14875 && current_function_decl != error_mark_node)
14876 DECL_INITIAL (current_function_decl) = block;
14879 if (!block_previously_created)
14880 current_binding_level->blocks
14881 = chainon (current_binding_level->blocks, block);
14883 /* If we did not make a block for the level just exited,
14884 any blocks made for inner levels
14885 (since they cannot be recorded as subblocks in that level)
14886 must be carried forward so they will later become subblocks
14887 of something else. */
14888 else if (subblocks)
14889 current_binding_level->blocks
14890 = chainon (current_binding_level->blocks, subblocks);
14893 TREE_USED (block) = 1;
14898 print_lang_decl (file, node, indent)
14906 print_lang_identifier (file, node, indent)
14911 print_node (file, "global", IDENTIFIER_GLOBAL_VALUE (node), indent + 4);
14912 print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4);
14916 print_lang_statistics ()
14921 print_lang_type (file, node, indent)
14928 /* Record a decl-node X as belonging to the current lexical scope.
14929 Check for errors (such as an incompatible declaration for the same
14930 name already seen in the same scope).
14932 Returns either X or an old decl for the same name.
14933 If an old decl is returned, it may have been smashed
14934 to agree with what X says. */
14941 register tree name = DECL_NAME (x);
14942 register struct binding_level *b = current_binding_level;
14944 if ((TREE_CODE (x) == FUNCTION_DECL)
14945 && (DECL_INITIAL (x) == 0)
14946 && DECL_EXTERNAL (x))
14947 DECL_CONTEXT (x) = NULL_TREE;
14949 DECL_CONTEXT (x) = current_function_decl;
14953 if (IDENTIFIER_INVENTED (name))
14956 DECL_ARTIFICIAL (x) = 1;
14958 DECL_IN_SYSTEM_HEADER (x) = 1;
14961 t = lookup_name_current_level (name);
14963 assert ((t == NULL_TREE) || (DECL_CONTEXT (x) == NULL_TREE));
14965 /* Don't push non-parms onto list for parms until we understand
14966 why we're doing this and whether it works. */
14968 assert ((b == global_binding_level)
14969 || !ffecom_transform_only_dummies_
14970 || TREE_CODE (x) == PARM_DECL);
14972 if ((t != NULL_TREE) && duplicate_decls (x, t))
14975 /* If we are processing a typedef statement, generate a whole new
14976 ..._TYPE node (which will be just an variant of the existing
14977 ..._TYPE node with identical properties) and then install the
14978 TYPE_DECL node generated to represent the typedef name as the
14979 TYPE_NAME of this brand new (duplicate) ..._TYPE node.
14981 The whole point here is to end up with a situation where each and every
14982 ..._TYPE node the compiler creates will be uniquely associated with
14983 AT MOST one node representing a typedef name. This way, even though
14984 the compiler substitutes corresponding ..._TYPE nodes for TYPE_DECL
14985 (i.e. "typedef name") nodes very early on, later parts of the
14986 compiler can always do the reverse translation and get back the
14987 corresponding typedef name. For example, given:
14989 typedef struct S MY_TYPE; MY_TYPE object;
14991 Later parts of the compiler might only know that `object' was of type
14992 `struct S' if it were not for code just below. With this code
14993 however, later parts of the compiler see something like:
14995 struct S' == struct S typedef struct S' MY_TYPE; struct S' object;
14997 And they can then deduce (from the node for type struct S') that the
14998 original object declaration was:
15002 Being able to do this is important for proper support of protoize, and
15003 also for generating precise symbolic debugging information which
15004 takes full account of the programmer's (typedef) vocabulary.
15006 Obviously, we don't want to generate a duplicate ..._TYPE node if the
15007 TYPE_DECL node that we are now processing really represents a
15008 standard built-in type.
15010 Since all standard types are effectively declared at line zero in the
15011 source file, we can easily check to see if we are working on a
15012 standard type by checking the current value of lineno. */
15014 if (TREE_CODE (x) == TYPE_DECL)
15016 if (DECL_SOURCE_LINE (x) == 0)
15018 if (TYPE_NAME (TREE_TYPE (x)) == 0)
15019 TYPE_NAME (TREE_TYPE (x)) = x;
15021 else if (TREE_TYPE (x) != error_mark_node)
15023 tree tt = TREE_TYPE (x);
15025 tt = build_type_copy (tt);
15026 TYPE_NAME (tt) = x;
15027 TREE_TYPE (x) = tt;
15031 /* This name is new in its binding level. Install the new declaration
15033 if (b == global_binding_level)
15034 IDENTIFIER_GLOBAL_VALUE (name) = x;
15036 IDENTIFIER_LOCAL_VALUE (name) = x;
15039 /* Put decls on list in reverse order. We will reverse them later if
15041 TREE_CHAIN (x) = b->names;
15047 /* Nonzero if the current level needs to have a BLOCK made. */
15054 for (decl = current_binding_level->names;
15056 decl = TREE_CHAIN (decl))
15058 if (TREE_USED (decl) || TREE_CODE (decl) != VAR_DECL
15059 || (DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl)))
15060 /* Currently, there aren't supposed to be non-artificial names
15061 at other than the top block for a function -- they're
15062 believed to always be temps. But it's wise to check anyway. */
15068 /* Enter a new binding level.
15069 If TAG_TRANSPARENT is nonzero, do so only for the name space of variables,
15070 not for that of tags. */
15073 pushlevel (tag_transparent)
15074 int tag_transparent;
15076 register struct binding_level *newlevel = NULL_BINDING_LEVEL;
15078 assert (! tag_transparent);
15080 if (current_binding_level == global_binding_level)
15085 /* Reuse or create a struct for this binding level. */
15087 if (free_binding_level)
15089 newlevel = free_binding_level;
15090 free_binding_level = free_binding_level->level_chain;
15094 newlevel = make_binding_level ();
15097 /* Add this level to the front of the chain (stack) of levels that
15100 *newlevel = clear_binding_level;
15101 newlevel->level_chain = current_binding_level;
15102 current_binding_level = newlevel;
15105 /* Set the BLOCK node for the innermost scope
15106 (the one we are currently in). */
15110 register tree block;
15112 current_binding_level->this_block = block;
15113 current_binding_level->names = chainon (current_binding_level->names,
15114 BLOCK_VARS (block));
15115 current_binding_level->blocks = chainon (current_binding_level->blocks,
15116 BLOCK_SUBBLOCKS (block));
15119 /* ~~gcc/tree.h *should* declare this, because toplev.c references it. */
15121 /* Can't 'yydebug' a front end not generated by yacc/bison! */
15124 set_yydebug (value)
15128 fprintf (stderr, "warning: no yacc/bison-generated output to debug!\n");
15132 signed_or_unsigned_type (unsignedp, type)
15138 if (! INTEGRAL_TYPE_P (type))
15140 if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
15141 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15142 if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
15143 return unsignedp ? unsigned_type_node : integer_type_node;
15144 if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node))
15145 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15146 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node))
15147 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15148 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node))
15149 return (unsignedp ? long_long_unsigned_type_node
15150 : long_long_integer_type_node);
15152 type2 = type_for_size (TYPE_PRECISION (type), unsignedp);
15153 if (type2 == NULL_TREE)
15163 tree type1 = TYPE_MAIN_VARIANT (type);
15164 ffeinfoKindtype kt;
15167 if (type1 == unsigned_char_type_node || type1 == char_type_node)
15168 return signed_char_type_node;
15169 if (type1 == unsigned_type_node)
15170 return integer_type_node;
15171 if (type1 == short_unsigned_type_node)
15172 return short_integer_type_node;
15173 if (type1 == long_unsigned_type_node)
15174 return long_integer_type_node;
15175 if (type1 == long_long_unsigned_type_node)
15176 return long_long_integer_type_node;
15177 #if 0 /* gcc/c-* files only */
15178 if (type1 == unsigned_intDI_type_node)
15179 return intDI_type_node;
15180 if (type1 == unsigned_intSI_type_node)
15181 return intSI_type_node;
15182 if (type1 == unsigned_intHI_type_node)
15183 return intHI_type_node;
15184 if (type1 == unsigned_intQI_type_node)
15185 return intQI_type_node;
15188 type2 = type_for_size (TYPE_PRECISION (type1), 0);
15189 if (type2 != NULL_TREE)
15192 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15194 type2 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
15196 if (type1 == type2)
15197 return ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15203 /* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
15204 or validate its data type for an `if' or `while' statement or ?..: exp.
15206 This preparation consists of taking the ordinary
15207 representation of an expression expr and producing a valid tree
15208 boolean expression describing whether expr is nonzero. We could
15209 simply always do build_binary_op (NE_EXPR, expr, integer_zero_node, 1),
15210 but we optimize comparisons, &&, ||, and !.
15212 The resulting type should always be `integer_type_node'. */
15215 truthvalue_conversion (expr)
15218 if (TREE_CODE (expr) == ERROR_MARK)
15221 #if 0 /* This appears to be wrong for C++. */
15222 /* These really should return error_mark_node after 2.4 is stable.
15223 But not all callers handle ERROR_MARK properly. */
15224 switch (TREE_CODE (TREE_TYPE (expr)))
15227 error ("struct type value used where scalar is required");
15228 return integer_zero_node;
15231 error ("union type value used where scalar is required");
15232 return integer_zero_node;
15235 error ("array type value used where scalar is required");
15236 return integer_zero_node;
15243 switch (TREE_CODE (expr))
15245 /* It is simpler and generates better code to have only TRUTH_*_EXPR
15246 or comparison expressions as truth values at this level. */
15248 case COMPONENT_REF:
15249 /* A one-bit unsigned bit-field is already acceptable. */
15250 if (1 == TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (expr, 1)))
15251 && TREE_UNSIGNED (TREE_OPERAND (expr, 1)))
15257 /* It is simpler and generates better code to have only TRUTH_*_EXPR
15258 or comparison expressions as truth values at this level. */
15260 if (integer_zerop (TREE_OPERAND (expr, 1)))
15261 return build_unary_op (TRUTH_NOT_EXPR, TREE_OPERAND (expr, 0), 0);
15263 case NE_EXPR: case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
15264 case TRUTH_ANDIF_EXPR:
15265 case TRUTH_ORIF_EXPR:
15266 case TRUTH_AND_EXPR:
15267 case TRUTH_OR_EXPR:
15268 case TRUTH_XOR_EXPR:
15269 TREE_TYPE (expr) = integer_type_node;
15276 return integer_zerop (expr) ? integer_zero_node : integer_one_node;
15279 return real_zerop (expr) ? integer_zero_node : integer_one_node;
15282 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0)))
15283 return build (COMPOUND_EXPR, integer_type_node,
15284 TREE_OPERAND (expr, 0), integer_one_node);
15286 return integer_one_node;
15289 return ffecom_2 ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
15290 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15292 truthvalue_conversion (TREE_OPERAND (expr, 0)),
15293 truthvalue_conversion (TREE_OPERAND (expr, 1)));
15299 /* These don't change whether an object is non-zero or zero. */
15300 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15304 /* These don't change whether an object is zero or non-zero, but
15305 we can't ignore them if their second arg has side-effects. */
15306 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
15307 return build (COMPOUND_EXPR, integer_type_node, TREE_OPERAND (expr, 1),
15308 truthvalue_conversion (TREE_OPERAND (expr, 0)));
15310 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15313 /* Distribute the conversion into the arms of a COND_EXPR. */
15314 return fold (build (COND_EXPR, integer_type_node, TREE_OPERAND (expr, 0),
15315 truthvalue_conversion (TREE_OPERAND (expr, 1)),
15316 truthvalue_conversion (TREE_OPERAND (expr, 2))));
15319 /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
15320 since that affects how `default_conversion' will behave. */
15321 if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE
15322 || TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
15324 /* fall through... */
15326 /* If this is widening the argument, we can ignore it. */
15327 if (TYPE_PRECISION (TREE_TYPE (expr))
15328 >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
15329 return truthvalue_conversion (TREE_OPERAND (expr, 0));
15333 /* With IEEE arithmetic, x - x may not equal 0, so we can't optimize
15335 if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
15336 && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE)
15338 /* fall through... */
15340 /* This and MINUS_EXPR can be changed into a comparison of the
15342 if (TREE_TYPE (TREE_OPERAND (expr, 0))
15343 == TREE_TYPE (TREE_OPERAND (expr, 1)))
15344 return ffecom_2 (NE_EXPR, integer_type_node,
15345 TREE_OPERAND (expr, 0),
15346 TREE_OPERAND (expr, 1));
15347 return ffecom_2 (NE_EXPR, integer_type_node,
15348 TREE_OPERAND (expr, 0),
15349 fold (build1 (NOP_EXPR,
15350 TREE_TYPE (TREE_OPERAND (expr, 0)),
15351 TREE_OPERAND (expr, 1))));
15354 if (integer_onep (TREE_OPERAND (expr, 1)))
15359 #if 0 /* No such thing in Fortran. */
15360 if (warn_parentheses && C_EXP_ORIGINAL_CODE (expr) == MODIFY_EXPR)
15361 warning ("suggest parentheses around assignment used as truth value");
15369 if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
15371 ((TREE_SIDE_EFFECTS (expr)
15372 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15374 truthvalue_conversion (ffecom_1 (REALPART_EXPR,
15375 TREE_TYPE (TREE_TYPE (expr)),
15377 truthvalue_conversion (ffecom_1 (IMAGPART_EXPR,
15378 TREE_TYPE (TREE_TYPE (expr)),
15381 return ffecom_2 (NE_EXPR, integer_type_node,
15383 convert (TREE_TYPE (expr), integer_zero_node));
15387 type_for_mode (mode, unsignedp)
15388 enum machine_mode mode;
15395 if (mode == TYPE_MODE (integer_type_node))
15396 return unsignedp ? unsigned_type_node : integer_type_node;
15398 if (mode == TYPE_MODE (signed_char_type_node))
15399 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15401 if (mode == TYPE_MODE (short_integer_type_node))
15402 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15404 if (mode == TYPE_MODE (long_integer_type_node))
15405 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15407 if (mode == TYPE_MODE (long_long_integer_type_node))
15408 return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
15410 #if HOST_BITS_PER_WIDE_INT >= 64
15411 if (mode == TYPE_MODE (intTI_type_node))
15412 return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
15415 if (mode == TYPE_MODE (float_type_node))
15416 return float_type_node;
15418 if (mode == TYPE_MODE (double_type_node))
15419 return double_type_node;
15421 if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
15422 return build_pointer_type (char_type_node);
15424 if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
15425 return build_pointer_type (integer_type_node);
15427 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
15428 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
15430 if (((t = ffecom_tree_type[i][j]) != NULL_TREE)
15431 && (mode == TYPE_MODE (t)))
15433 if ((i == FFEINFO_basictypeINTEGER) && unsignedp)
15434 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][j];
15444 type_for_size (bits, unsignedp)
15448 ffeinfoKindtype kt;
15451 if (bits == TYPE_PRECISION (integer_type_node))
15452 return unsignedp ? unsigned_type_node : integer_type_node;
15454 if (bits == TYPE_PRECISION (signed_char_type_node))
15455 return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15457 if (bits == TYPE_PRECISION (short_integer_type_node))
15458 return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15460 if (bits == TYPE_PRECISION (long_integer_type_node))
15461 return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15463 if (bits == TYPE_PRECISION (long_long_integer_type_node))
15464 return (unsignedp ? long_long_unsigned_type_node
15465 : long_long_integer_type_node);
15467 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15469 type_node = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15471 if ((type_node != NULL_TREE) && (bits == TYPE_PRECISION (type_node)))
15472 return unsignedp ? ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt]
15480 unsigned_type (type)
15483 tree type1 = TYPE_MAIN_VARIANT (type);
15484 ffeinfoKindtype kt;
15487 if (type1 == signed_char_type_node || type1 == char_type_node)
15488 return unsigned_char_type_node;
15489 if (type1 == integer_type_node)
15490 return unsigned_type_node;
15491 if (type1 == short_integer_type_node)
15492 return short_unsigned_type_node;
15493 if (type1 == long_integer_type_node)
15494 return long_unsigned_type_node;
15495 if (type1 == long_long_integer_type_node)
15496 return long_long_unsigned_type_node;
15497 #if 0 /* gcc/c-* files only */
15498 if (type1 == intDI_type_node)
15499 return unsigned_intDI_type_node;
15500 if (type1 == intSI_type_node)
15501 return unsigned_intSI_type_node;
15502 if (type1 == intHI_type_node)
15503 return unsigned_intHI_type_node;
15504 if (type1 == intQI_type_node)
15505 return unsigned_intQI_type_node;
15508 type2 = type_for_size (TYPE_PRECISION (type1), 1);
15509 if (type2 != NULL_TREE)
15512 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15514 type2 = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15516 if (type1 == type2)
15517 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
15525 union tree_node *t ATTRIBUTE_UNUSED;
15527 if (TREE_CODE (t) == IDENTIFIER_NODE)
15529 struct lang_identifier *i = (struct lang_identifier *) t;
15530 ggc_mark_tree (IDENTIFIER_GLOBAL_VALUE (i));
15531 ggc_mark_tree (IDENTIFIER_LOCAL_VALUE (i));
15532 ggc_mark_tree (IDENTIFIER_LABEL_VALUE (i));
15534 else if (TYPE_P (t) && TYPE_LANG_SPECIFIC (t))
15535 ggc_mark (TYPE_LANG_SPECIFIC (t));
15538 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
15540 #if FFECOM_GCC_INCLUDE
15542 /* From gcc/cccp.c, the code to handle -I. */
15544 /* Skip leading "./" from a directory name.
15545 This may yield the empty string, which represents the current directory. */
15547 static const char *
15548 skip_redundant_dir_prefix (const char *dir)
15550 while (dir[0] == '.' && dir[1] == '/')
15551 for (dir += 2; *dir == '/'; dir++)
15553 if (dir[0] == '.' && !dir[1])
15558 /* The file_name_map structure holds a mapping of file names for a
15559 particular directory. This mapping is read from the file named
15560 FILE_NAME_MAP_FILE in that directory. Such a file can be used to
15561 map filenames on a file system with severe filename restrictions,
15562 such as DOS. The format of the file name map file is just a series
15563 of lines with two tokens on each line. The first token is the name
15564 to map, and the second token is the actual name to use. */
15566 struct file_name_map
15568 struct file_name_map *map_next;
15573 #define FILE_NAME_MAP_FILE "header.gcc"
15575 /* Current maximum length of directory names in the search path
15576 for include files. (Altered as we get more of them.) */
15578 static int max_include_len = 0;
15580 struct file_name_list
15582 struct file_name_list *next;
15584 /* Mapping of file names for this directory. */
15585 struct file_name_map *name_map;
15586 /* Non-zero if name_map is valid. */
15590 static struct file_name_list *include = NULL; /* First dir to search */
15591 static struct file_name_list *last_include = NULL; /* Last in chain */
15593 /* I/O buffer structure.
15594 The `fname' field is nonzero for source files and #include files
15595 and for the dummy text used for -D and -U.
15596 It is zero for rescanning results of macro expansion
15597 and for expanding macro arguments. */
15598 #define INPUT_STACK_MAX 400
15599 static struct file_buf {
15601 /* Filename specified with #line command. */
15602 const char *nominal_fname;
15603 /* Record where in the search path this file was found.
15604 For #include_next. */
15605 struct file_name_list *dir;
15607 ffewhereColumn column;
15608 } instack[INPUT_STACK_MAX];
15610 static int last_error_tick = 0; /* Incremented each time we print it. */
15611 static int input_file_stack_tick = 0; /* Incremented when status changes. */
15613 /* Current nesting level of input sources.
15614 `instack[indepth]' is the level currently being read. */
15615 static int indepth = -1;
15617 typedef struct file_buf FILE_BUF;
15619 typedef unsigned char U_CHAR;
15621 /* table to tell if char can be part of a C identifier. */
15622 U_CHAR is_idchar[256];
15623 /* table to tell if char can be first char of a c identifier. */
15624 U_CHAR is_idstart[256];
15625 /* table to tell if c is horizontal space. */
15626 U_CHAR is_hor_space[256];
15627 /* table to tell if c is horizontal or vertical space. */
15628 static U_CHAR is_space[256];
15630 #define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
15631 #define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*p]) p++; } while (0)
15633 /* Nonzero means -I- has been seen,
15634 so don't look for #include "foo" the source-file directory. */
15635 static int ignore_srcdir;
15637 #ifndef INCLUDE_LEN_FUDGE
15638 #define INCLUDE_LEN_FUDGE 0
15641 static void append_include_chain (struct file_name_list *first,
15642 struct file_name_list *last);
15643 static FILE *open_include_file (char *filename,
15644 struct file_name_list *searchptr);
15645 static void print_containing_files (ffebadSeverity sev);
15646 static char *read_filename_string (int ch, FILE *f);
15647 static struct file_name_map *read_name_map (const char *dirname);
15649 /* Append a chain of `struct file_name_list's
15650 to the end of the main include chain.
15651 FIRST is the beginning of the chain to append, and LAST is the end. */
15654 append_include_chain (first, last)
15655 struct file_name_list *first, *last;
15657 struct file_name_list *dir;
15659 if (!first || !last)
15665 last_include->next = first;
15667 for (dir = first; ; dir = dir->next) {
15668 int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE;
15669 if (len > max_include_len)
15670 max_include_len = len;
15676 last_include = last;
15679 /* Try to open include file FILENAME. SEARCHPTR is the directory
15680 being tried from the include file search path. This function maps
15681 filenames on file systems based on information read by
15685 open_include_file (filename, searchptr)
15687 struct file_name_list *searchptr;
15689 register struct file_name_map *map;
15690 register char *from;
15693 if (searchptr && ! searchptr->got_name_map)
15695 searchptr->name_map = read_name_map (searchptr->fname
15696 ? searchptr->fname : ".");
15697 searchptr->got_name_map = 1;
15700 /* First check the mapping for the directory we are using. */
15701 if (searchptr && searchptr->name_map)
15704 if (searchptr->fname)
15705 from += strlen (searchptr->fname) + 1;
15706 for (map = searchptr->name_map; map; map = map->map_next)
15708 if (! strcmp (map->map_from, from))
15710 /* Found a match. */
15711 return fopen (map->map_to, "r");
15716 /* Try to find a mapping file for the particular directory we are
15717 looking in. Thus #include <sys/types.h> will look up sys/types.h
15718 in /usr/include/header.gcc and look up types.h in
15719 /usr/include/sys/header.gcc. */
15720 p = strrchr (filename, '/');
15721 #ifdef DIR_SEPARATOR
15722 if (! p) p = strrchr (filename, DIR_SEPARATOR);
15724 char *tmp = strrchr (filename, DIR_SEPARATOR);
15725 if (tmp != NULL && tmp > p) p = tmp;
15731 && searchptr->fname
15732 && strlen (searchptr->fname) == (size_t) (p - filename)
15733 && ! strncmp (searchptr->fname, filename, (int) (p - filename)))
15735 /* FILENAME is in SEARCHPTR, which we've already checked. */
15736 return fopen (filename, "r");
15742 map = read_name_map (".");
15746 dir = (char *) xmalloc (p - filename + 1);
15747 memcpy (dir, filename, p - filename);
15748 dir[p - filename] = '\0';
15750 map = read_name_map (dir);
15753 for (; map; map = map->map_next)
15754 if (! strcmp (map->map_from, from))
15755 return fopen (map->map_to, "r");
15757 return fopen (filename, "r");
15760 /* Print the file names and line numbers of the #include
15761 commands which led to the current file. */
15764 print_containing_files (ffebadSeverity sev)
15766 FILE_BUF *ip = NULL;
15772 /* If stack of files hasn't changed since we last printed
15773 this info, don't repeat it. */
15774 if (last_error_tick == input_file_stack_tick)
15777 for (i = indepth; i >= 0; i--)
15778 if (instack[i].fname != NULL) {
15783 /* Give up if we don't find a source file. */
15787 /* Find the other, outer source files. */
15788 for (i--; i >= 0; i--)
15789 if (instack[i].fname != NULL)
15795 str1 = "In file included";
15807 ffebad_start_msg ("%A from %B at %0%C", sev);
15808 ffebad_here (0, ip->line, ip->column);
15809 ffebad_string (str1);
15810 ffebad_string (ip->nominal_fname);
15811 ffebad_string (str2);
15815 /* Record we have printed the status as of this time. */
15816 last_error_tick = input_file_stack_tick;
15819 /* Read a space delimited string of unlimited length from a stdio
15823 read_filename_string (ch, f)
15831 set = alloc = xmalloc (len + 1);
15832 if (! is_space[ch])
15835 while ((ch = getc (f)) != EOF && ! is_space[ch])
15837 if (set - alloc == len)
15840 alloc = xrealloc (alloc, len + 1);
15841 set = alloc + len / 2;
15851 /* Read the file name map file for DIRNAME. */
15853 static struct file_name_map *
15854 read_name_map (dirname)
15855 const char *dirname;
15857 /* This structure holds a linked list of file name maps, one per
15859 struct file_name_map_list
15861 struct file_name_map_list *map_list_next;
15862 char *map_list_name;
15863 struct file_name_map *map_list_map;
15865 static struct file_name_map_list *map_list;
15866 register struct file_name_map_list *map_list_ptr;
15870 int separator_needed;
15872 dirname = skip_redundant_dir_prefix (dirname);
15874 for (map_list_ptr = map_list; map_list_ptr;
15875 map_list_ptr = map_list_ptr->map_list_next)
15876 if (! strcmp (map_list_ptr->map_list_name, dirname))
15877 return map_list_ptr->map_list_map;
15879 map_list_ptr = ((struct file_name_map_list *)
15880 xmalloc (sizeof (struct file_name_map_list)));
15881 map_list_ptr->map_list_name = xstrdup (dirname);
15882 map_list_ptr->map_list_map = NULL;
15884 dirlen = strlen (dirname);
15885 separator_needed = dirlen != 0 && dirname[dirlen - 1] != '/';
15886 name = (char *) xmalloc (dirlen + strlen (FILE_NAME_MAP_FILE) + 2);
15887 strcpy (name, dirname);
15888 name[dirlen] = '/';
15889 strcpy (name + dirlen + separator_needed, FILE_NAME_MAP_FILE);
15890 f = fopen (name, "r");
15893 map_list_ptr->map_list_map = NULL;
15898 while ((ch = getc (f)) != EOF)
15901 struct file_name_map *ptr;
15905 from = read_filename_string (ch, f);
15906 while ((ch = getc (f)) != EOF && is_hor_space[ch])
15908 to = read_filename_string (ch, f);
15910 ptr = ((struct file_name_map *)
15911 xmalloc (sizeof (struct file_name_map)));
15912 ptr->map_from = from;
15914 /* Make the real filename absolute. */
15919 ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
15920 strcpy (ptr->map_to, dirname);
15921 ptr->map_to[dirlen] = '/';
15922 strcpy (ptr->map_to + dirlen + separator_needed, to);
15926 ptr->map_next = map_list_ptr->map_list_map;
15927 map_list_ptr->map_list_map = ptr;
15929 while ((ch = getc (f)) != '\n')
15936 map_list_ptr->map_list_next = map_list;
15937 map_list = map_list_ptr;
15939 return map_list_ptr->map_list_map;
15943 ffecom_file_ (const char *name)
15947 /* Do partial setup of input buffer for the sake of generating
15948 early #line directives (when -g is in effect). */
15950 fp = &instack[++indepth];
15951 memset ((char *) fp, 0, sizeof (FILE_BUF));
15954 fp->nominal_fname = fp->fname = name;
15957 /* Initialize syntactic classifications of characters. */
15960 ffecom_initialize_char_syntax_ ()
15965 * Set up is_idchar and is_idstart tables. These should be
15966 * faster than saying (is_alpha (c) || c == '_'), etc.
15967 * Set up these things before calling any routines tthat
15970 for (i = 'a'; i <= 'z'; i++) {
15971 is_idchar[i - 'a' + 'A'] = 1;
15973 is_idstart[i - 'a' + 'A'] = 1;
15976 for (i = '0'; i <= '9'; i++)
15978 is_idchar['_'] = 1;
15979 is_idstart['_'] = 1;
15981 /* horizontal space table */
15982 is_hor_space[' '] = 1;
15983 is_hor_space['\t'] = 1;
15984 is_hor_space['\v'] = 1;
15985 is_hor_space['\f'] = 1;
15986 is_hor_space['\r'] = 1;
15989 is_space['\t'] = 1;
15990 is_space['\v'] = 1;
15991 is_space['\f'] = 1;
15992 is_space['\n'] = 1;
15993 is_space['\r'] = 1;
15997 ffecom_close_include_ (FILE *f)
16002 input_file_stack_tick++;
16004 ffewhere_line_kill (instack[indepth].line);
16005 ffewhere_column_kill (instack[indepth].column);
16009 ffecom_decode_include_option_ (char *spec)
16011 struct file_name_list *dirtmp;
16013 if (! ignore_srcdir && !strcmp (spec, "-"))
16017 dirtmp = (struct file_name_list *)
16018 xmalloc (sizeof (struct file_name_list));
16019 dirtmp->next = 0; /* New one goes on the end */
16020 dirtmp->fname = spec;
16021 dirtmp->got_name_map = 0;
16023 error ("Directory name must immediately follow -I");
16025 append_include_chain (dirtmp, dirtmp);
16030 /* Open INCLUDEd file. */
16033 ffecom_open_include_ (char *name, ffewhereLine l, ffewhereColumn c)
16036 size_t flen = strlen (fbeg);
16037 struct file_name_list *search_start = include; /* Chain of dirs to search */
16038 struct file_name_list dsp[1]; /* First in chain, if #include "..." */
16039 struct file_name_list *searchptr = 0;
16040 char *fname; /* Dynamically allocated fname buffer */
16047 dsp[0].fname = NULL;
16049 /* If -I- was specified, don't search current dir, only spec'd ones. */
16050 if (!ignore_srcdir)
16052 for (fp = &instack[indepth]; fp >= instack; fp--)
16058 if ((nam = fp->nominal_fname) != NULL)
16060 /* Found a named file. Figure out dir of the file,
16061 and put it in front of the search list. */
16062 dsp[0].next = search_start;
16063 search_start = dsp;
16065 ep = strrchr (nam, '/');
16066 #ifdef DIR_SEPARATOR
16067 if (ep == NULL) ep = strrchr (nam, DIR_SEPARATOR);
16069 char *tmp = strrchr (nam, DIR_SEPARATOR);
16070 if (tmp != NULL && tmp > ep) ep = tmp;
16074 ep = strrchr (nam, ']');
16075 if (ep == NULL) ep = strrchr (nam, '>');
16076 if (ep == NULL) ep = strrchr (nam, ':');
16077 if (ep != NULL) ep++;
16082 dsp[0].fname = (char *) xmalloc (n + 1);
16083 strncpy (dsp[0].fname, nam, n);
16084 dsp[0].fname[n] = '\0';
16085 if (n + INCLUDE_LEN_FUDGE > max_include_len)
16086 max_include_len = n + INCLUDE_LEN_FUDGE;
16089 dsp[0].fname = NULL; /* Current directory */
16090 dsp[0].got_name_map = 0;
16096 /* Allocate this permanently, because it gets stored in the definitions
16098 fname = xmalloc (max_include_len + flen + 4);
16099 /* + 2 above for slash and terminating null. */
16100 /* + 2 added for '.h' on VMS (to support '#include filename') (NOT USED
16103 /* If specified file name is absolute, just open it. */
16106 #ifdef DIR_SEPARATOR
16107 || *fbeg == DIR_SEPARATOR
16111 strncpy (fname, (char *) fbeg, flen);
16113 f = open_include_file (fname, NULL);
16119 /* Search directory path, trying to open the file.
16120 Copy each filename tried into FNAME. */
16122 for (searchptr = search_start; searchptr; searchptr = searchptr->next)
16124 if (searchptr->fname)
16126 /* The empty string in a search path is ignored.
16127 This makes it possible to turn off entirely
16128 a standard piece of the list. */
16129 if (searchptr->fname[0] == 0)
16131 strcpy (fname, skip_redundant_dir_prefix (searchptr->fname));
16132 if (fname[0] && fname[strlen (fname) - 1] != '/')
16133 strcat (fname, "/");
16134 fname[strlen (fname) + flen] = 0;
16139 strncat (fname, fbeg, flen);
16141 /* Change this 1/2 Unix 1/2 VMS file specification into a
16142 full VMS file specification */
16143 if (searchptr->fname && (searchptr->fname[0] != 0))
16145 /* Fix up the filename */
16146 hack_vms_include_specification (fname);
16150 /* This is a normal VMS filespec, so use it unchanged. */
16151 strncpy (fname, (char *) fbeg, flen);
16153 #if 0 /* Not for g77. */
16154 /* if it's '#include filename', add the missing .h */
16155 if (strchr (fname, '.') == NULL)
16156 strcat (fname, ".h");
16160 f = open_include_file (fname, searchptr);
16162 if (f == NULL && errno == EACCES)
16164 print_containing_files (FFEBAD_severityWARNING);
16165 ffebad_start_msg ("At %0, INCLUDE file %A exists, but is not readable",
16166 FFEBAD_severityWARNING);
16167 ffebad_string (fname);
16168 ffebad_here (0, l, c);
16179 /* A file that was not found. */
16181 strncpy (fname, (char *) fbeg, flen);
16183 print_containing_files (ffebad_severity (FFEBAD_OPEN_INCLUDE));
16184 ffebad_start (FFEBAD_OPEN_INCLUDE);
16185 ffebad_here (0, l, c);
16186 ffebad_string (fname);
16190 if (dsp[0].fname != NULL)
16191 free (dsp[0].fname);
16196 if (indepth >= (INPUT_STACK_MAX - 1))
16198 print_containing_files (FFEBAD_severityFATAL);
16199 ffebad_start_msg ("At %0, INCLUDE nesting too deep",
16200 FFEBAD_severityFATAL);
16201 ffebad_string (fname);
16202 ffebad_here (0, l, c);
16207 instack[indepth].line = ffewhere_line_use (l);
16208 instack[indepth].column = ffewhere_column_use (c);
16210 fp = &instack[indepth + 1];
16211 memset ((char *) fp, 0, sizeof (FILE_BUF));
16212 fp->nominal_fname = fp->fname = fname;
16213 fp->dir = searchptr;
16216 input_file_stack_tick++;
16220 #endif /* FFECOM_GCC_INCLUDE */
16222 /**INDENT* (Do not reformat this comment even with -fca option.)
16223 Data-gathering files: Given the source file listed below, compiled with
16224 f2c I obtained the output file listed after that, and from the output
16225 file I derived the above code.
16227 -------- (begin input file to f2c)
16233 double precision D1,D2
16235 call getem(A1,A2,C1,C2,I1,I2,R1,R2,D1,D2)
16262 c FFEINTRIN_impACOS
16263 call fooR(ACOS(R1))
16264 c FFEINTRIN_impAIMAG
16265 call fooR(AIMAG(C1))
16266 c FFEINTRIN_impAINT
16267 call fooR(AINT(R1))
16268 c FFEINTRIN_impALOG
16269 call fooR(ALOG(R1))
16270 c FFEINTRIN_impALOG10
16271 call fooR(ALOG10(R1))
16272 c FFEINTRIN_impAMAX0
16273 call fooR(AMAX0(I1,I2))
16274 c FFEINTRIN_impAMAX1
16275 call fooR(AMAX1(R1,R2))
16276 c FFEINTRIN_impAMIN0
16277 call fooR(AMIN0(I1,I2))
16278 c FFEINTRIN_impAMIN1
16279 call fooR(AMIN1(R1,R2))
16280 c FFEINTRIN_impAMOD
16281 call fooR(AMOD(R1,R2))
16282 c FFEINTRIN_impANINT
16283 call fooR(ANINT(R1))
16284 c FFEINTRIN_impASIN
16285 call fooR(ASIN(R1))
16286 c FFEINTRIN_impATAN
16287 call fooR(ATAN(R1))
16288 c FFEINTRIN_impATAN2
16289 call fooR(ATAN2(R1,R2))
16290 c FFEINTRIN_impCABS
16291 call fooR(CABS(C1))
16292 c FFEINTRIN_impCCOS
16293 call fooC(CCOS(C1))
16294 c FFEINTRIN_impCEXP
16295 call fooC(CEXP(C1))
16296 c FFEINTRIN_impCHAR
16297 call fooA(CHAR(I1))
16298 c FFEINTRIN_impCLOG
16299 call fooC(CLOG(C1))
16300 c FFEINTRIN_impCONJG
16301 call fooC(CONJG(C1))
16304 c FFEINTRIN_impCOSH
16305 call fooR(COSH(R1))
16306 c FFEINTRIN_impCSIN
16307 call fooC(CSIN(C1))
16308 c FFEINTRIN_impCSQRT
16309 call fooC(CSQRT(C1))
16310 c FFEINTRIN_impDABS
16311 call fooD(DABS(D1))
16312 c FFEINTRIN_impDACOS
16313 call fooD(DACOS(D1))
16314 c FFEINTRIN_impDASIN
16315 call fooD(DASIN(D1))
16316 c FFEINTRIN_impDATAN
16317 call fooD(DATAN(D1))
16318 c FFEINTRIN_impDATAN2
16319 call fooD(DATAN2(D1,D2))
16320 c FFEINTRIN_impDCOS
16321 call fooD(DCOS(D1))
16322 c FFEINTRIN_impDCOSH
16323 call fooD(DCOSH(D1))
16324 c FFEINTRIN_impDDIM
16325 call fooD(DDIM(D1,D2))
16326 c FFEINTRIN_impDEXP
16327 call fooD(DEXP(D1))
16329 call fooR(DIM(R1,R2))
16330 c FFEINTRIN_impDINT
16331 call fooD(DINT(D1))
16332 c FFEINTRIN_impDLOG
16333 call fooD(DLOG(D1))
16334 c FFEINTRIN_impDLOG10
16335 call fooD(DLOG10(D1))
16336 c FFEINTRIN_impDMAX1
16337 call fooD(DMAX1(D1,D2))
16338 c FFEINTRIN_impDMIN1
16339 call fooD(DMIN1(D1,D2))
16340 c FFEINTRIN_impDMOD
16341 call fooD(DMOD(D1,D2))
16342 c FFEINTRIN_impDNINT
16343 call fooD(DNINT(D1))
16344 c FFEINTRIN_impDPROD
16345 call fooD(DPROD(R1,R2))
16346 c FFEINTRIN_impDSIGN
16347 call fooD(DSIGN(D1,D2))
16348 c FFEINTRIN_impDSIN
16349 call fooD(DSIN(D1))
16350 c FFEINTRIN_impDSINH
16351 call fooD(DSINH(D1))
16352 c FFEINTRIN_impDSQRT
16353 call fooD(DSQRT(D1))
16354 c FFEINTRIN_impDTAN
16355 call fooD(DTAN(D1))
16356 c FFEINTRIN_impDTANH
16357 call fooD(DTANH(D1))
16360 c FFEINTRIN_impIABS
16361 call fooI(IABS(I1))
16362 c FFEINTRIN_impICHAR
16363 call fooI(ICHAR(A1))
16364 c FFEINTRIN_impIDIM
16365 call fooI(IDIM(I1,I2))
16366 c FFEINTRIN_impIDNINT
16367 call fooI(IDNINT(D1))
16368 c FFEINTRIN_impINDEX
16369 call fooI(INDEX(A1,A2))
16370 c FFEINTRIN_impISIGN
16371 call fooI(ISIGN(I1,I2))
16375 call fooL(LGE(A1,A2))
16377 call fooL(LGT(A1,A2))
16379 call fooL(LLE(A1,A2))
16381 call fooL(LLT(A1,A2))
16382 c FFEINTRIN_impMAX0
16383 call fooI(MAX0(I1,I2))
16384 c FFEINTRIN_impMAX1
16385 call fooI(MAX1(R1,R2))
16386 c FFEINTRIN_impMIN0
16387 call fooI(MIN0(I1,I2))
16388 c FFEINTRIN_impMIN1
16389 call fooI(MIN1(R1,R2))
16391 call fooI(MOD(I1,I2))
16392 c FFEINTRIN_impNINT
16393 call fooI(NINT(R1))
16394 c FFEINTRIN_impSIGN
16395 call fooR(SIGN(R1,R2))
16398 c FFEINTRIN_impSINH
16399 call fooR(SINH(R1))
16400 c FFEINTRIN_impSQRT
16401 call fooR(SQRT(R1))
16404 c FFEINTRIN_impTANH
16405 call fooR(TANH(R1))
16406 c FFEINTRIN_imp_CMPLX_C
16407 call fooC(cmplx(C1,C2))
16408 c FFEINTRIN_imp_CMPLX_D
16409 call fooZ(cmplx(D1,D2))
16410 c FFEINTRIN_imp_CMPLX_I
16411 call fooC(cmplx(I1,I2))
16412 c FFEINTRIN_imp_CMPLX_R
16413 call fooC(cmplx(R1,R2))
16414 c FFEINTRIN_imp_DBLE_C
16415 call fooD(dble(C1))
16416 c FFEINTRIN_imp_DBLE_D
16417 call fooD(dble(D1))
16418 c FFEINTRIN_imp_DBLE_I
16419 call fooD(dble(I1))
16420 c FFEINTRIN_imp_DBLE_R
16421 call fooD(dble(R1))
16422 c FFEINTRIN_imp_INT_C
16424 c FFEINTRIN_imp_INT_D
16426 c FFEINTRIN_imp_INT_I
16428 c FFEINTRIN_imp_INT_R
16430 c FFEINTRIN_imp_REAL_C
16431 call fooR(real(C1))
16432 c FFEINTRIN_imp_REAL_D
16433 call fooR(real(D1))
16434 c FFEINTRIN_imp_REAL_I
16435 call fooR(real(I1))
16436 c FFEINTRIN_imp_REAL_R
16437 call fooR(real(R1))
16439 c FFEINTRIN_imp_INT_D:
16441 c FFEINTRIN_specIDINT
16442 call fooI(IDINT(D1))
16444 c FFEINTRIN_imp_INT_R:
16446 c FFEINTRIN_specIFIX
16447 call fooI(IFIX(R1))
16448 c FFEINTRIN_specINT
16451 c FFEINTRIN_imp_REAL_D:
16453 c FFEINTRIN_specSNGL
16454 call fooR(SNGL(D1))
16456 c FFEINTRIN_imp_REAL_I:
16458 c FFEINTRIN_specFLOAT
16459 call fooR(FLOAT(I1))
16460 c FFEINTRIN_specREAL
16461 call fooR(REAL(I1))
16464 -------- (end input file to f2c)
16466 -------- (begin output from providing above input file as input to:
16467 -------- `f2c | gcc -E -C - | sed -e "s:/[*]*://:g" -e "s:[*]*[/]://:g" \
16468 -------- -e "s:^#.*$::g"')
16470 // -- translated by f2c (version 19950223).
16471 You must link the resulting object file with the libraries:
16472 -lf2c -lm (in that order)
16476 // f2c.h -- Standard Fortran to C header file //
16478 /// barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed."
16480 - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) //
16485 // F2C_INTEGER will normally be `int' but would be `long' on 16-bit systems //
16486 // we assume short, float are OK //
16487 typedef long int // long int // integer;
16488 typedef char *address;
16489 typedef short int shortint;
16490 typedef float real;
16491 typedef double doublereal;
16492 typedef struct { real r, i; } complex;
16493 typedef struct { doublereal r, i; } doublecomplex;
16494 typedef long int // long int // logical;
16495 typedef short int shortlogical;
16496 typedef char logical1;
16497 typedef char integer1;
16498 // typedef long long longint; // // system-dependent //
16503 // Extern is for use with -E //
16517 typedef long int // int or long int // flag;
16518 typedef long int // int or long int // ftnlen;
16519 typedef long int // int or long int // ftnint;
16522 //external read, write//
16531 //internal read, write//
16561 //rewind, backspace, endfile//
16573 ftnint *inex; //parameters in standard's order//
16599 union Multitype { // for multiple entry points //
16610 typedef union Multitype Multitype;
16612 typedef long Long; // No longer used; formerly in Namelist //
16614 struct Vardesc { // for Namelist //
16620 typedef struct Vardesc Vardesc;
16627 typedef struct Namelist Namelist;
16636 // procedure parameter types for -A and -C++ //
16641 typedef int // Unknown procedure type // (*U_fp)();
16642 typedef shortint (*J_fp)();
16643 typedef integer (*I_fp)();
16644 typedef real (*R_fp)();
16645 typedef doublereal (*D_fp)(), (*E_fp)();
16646 typedef // Complex // void (*C_fp)();
16647 typedef // Double Complex // void (*Z_fp)();
16648 typedef logical (*L_fp)();
16649 typedef shortlogical (*K_fp)();
16650 typedef // Character // void (*H_fp)();
16651 typedef // Subroutine // int (*S_fp)();
16653 // E_fp is for real functions when -R is not specified //
16654 typedef void C_f; // complex function //
16655 typedef void H_f; // character function //
16656 typedef void Z_f; // double complex function //
16657 typedef doublereal E_f; // real function with -R not specified //
16659 // undef any lower-case symbols that your C compiler predefines, e.g.: //
16662 // (No such symbols should be defined in a strict ANSI C compiler.
16663 We can avoid trouble with f2c-translated code by using
16664 gcc -ansi [-traditional].) //
16688 // Main program // MAIN__()
16690 // System generated locals //
16693 doublereal d__1, d__2;
16695 doublecomplex z__1, z__2, z__3;
16699 // Builtin functions //
16702 double pow_ri(), pow_di();
16706 double acos(), r_imag(), r_int(), log(), r_lg10(), r_mod(), r_nint(),
16707 asin(), atan(), atan2(), c_abs();
16708 void c_cos(), c_exp(), c_log(), r_cnjg();
16709 double cos(), cosh();
16710 void c_sin(), c_sqrt();
16711 double d_dim(), exp(), r_dim(), d_int(), d_lg10(), d_mod(), d_nint(),
16712 d_sign(), sin(), sinh(), sqrt(), tan(), tanh();
16713 integer i_dim(), i_dnnt(), i_indx(), i_sign(), i_len();
16714 logical l_ge(), l_gt(), l_le(), l_lt();
16718 // Local variables //
16719 extern // Subroutine // int fooa_(), fooc_(), food_(), fooi_(), foor_(),
16720 fool_(), fooz_(), getem_();
16721 static char a1[10], a2[10];
16722 static complex c1, c2;
16723 static doublereal d1, d2;
16724 static integer i1, i2;
16725 static real r1, r2;
16728 getem_(a1, a2, &c1, &c2, &i1, &i2, &r1, &r2, &d1, &d2, 10L, 10L);
16736 d__1 = (doublereal) i1;
16737 q__1.r = c1.r / d__1, q__1.i = c1.i / d__1;
16747 c_div(&q__1, &c1, &c2);
16749 q__1.r = c1.r / r1, q__1.i = c1.i / r1;
16751 z__1.r = c1.r / d1, z__1.i = c1.i / d1;
16754 i__1 = pow_ii(&i1, &i2);
16756 r__1 = pow_ri(&r1, &i1);
16758 d__1 = pow_di(&d1, &i1);
16760 pow_ci(&q__1, &c1, &i1);
16762 d__1 = (doublereal) r1;
16763 d__2 = (doublereal) r2;
16764 r__1 = pow_dd(&d__1, &d__2);
16766 d__2 = (doublereal) r1;
16767 d__1 = pow_dd(&d__2, &d1);
16769 d__1 = pow_dd(&d1, &d2);
16771 d__2 = (doublereal) r1;
16772 d__1 = pow_dd(&d1, &d__2);
16774 z__2.r = c1.r, z__2.i = c1.i;
16775 z__3.r = c2.r, z__3.i = c2.i;
16776 pow_zz(&z__1, &z__2, &z__3);
16777 q__1.r = z__1.r, q__1.i = z__1.i;
16779 z__2.r = c1.r, z__2.i = c1.i;
16780 z__3.r = r1, z__3.i = 0.;
16781 pow_zz(&z__1, &z__2, &z__3);
16782 q__1.r = z__1.r, q__1.i = z__1.i;
16784 z__2.r = c1.r, z__2.i = c1.i;
16785 z__3.r = d1, z__3.i = 0.;
16786 pow_zz(&z__1, &z__2, &z__3);
16788 // FFEINTRIN_impABS //
16789 r__1 = (doublereal)(( r1 ) >= 0 ? ( r1 ) : -( r1 )) ;
16791 // FFEINTRIN_impACOS //
16794 // FFEINTRIN_impAIMAG //
16795 r__1 = r_imag(&c1);
16797 // FFEINTRIN_impAINT //
16800 // FFEINTRIN_impALOG //
16803 // FFEINTRIN_impALOG10 //
16804 r__1 = r_lg10(&r1);
16806 // FFEINTRIN_impAMAX0 //
16807 r__1 = (real) (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
16809 // FFEINTRIN_impAMAX1 //
16810 r__1 = (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
16812 // FFEINTRIN_impAMIN0 //
16813 r__1 = (real) (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
16815 // FFEINTRIN_impAMIN1 //
16816 r__1 = (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
16818 // FFEINTRIN_impAMOD //
16819 r__1 = r_mod(&r1, &r2);
16821 // FFEINTRIN_impANINT //
16822 r__1 = r_nint(&r1);
16824 // FFEINTRIN_impASIN //
16827 // FFEINTRIN_impATAN //
16830 // FFEINTRIN_impATAN2 //
16831 r__1 = atan2(r1, r2);
16833 // FFEINTRIN_impCABS //
16836 // FFEINTRIN_impCCOS //
16839 // FFEINTRIN_impCEXP //
16842 // FFEINTRIN_impCHAR //
16843 *(unsigned char *)&ch__1[0] = i1;
16845 // FFEINTRIN_impCLOG //
16848 // FFEINTRIN_impCONJG //
16849 r_cnjg(&q__1, &c1);
16851 // FFEINTRIN_impCOS //
16854 // FFEINTRIN_impCOSH //
16857 // FFEINTRIN_impCSIN //
16860 // FFEINTRIN_impCSQRT //
16861 c_sqrt(&q__1, &c1);
16863 // FFEINTRIN_impDABS //
16864 d__1 = (( d1 ) >= 0 ? ( d1 ) : -( d1 )) ;
16866 // FFEINTRIN_impDACOS //
16869 // FFEINTRIN_impDASIN //
16872 // FFEINTRIN_impDATAN //
16875 // FFEINTRIN_impDATAN2 //
16876 d__1 = atan2(d1, d2);
16878 // FFEINTRIN_impDCOS //
16881 // FFEINTRIN_impDCOSH //
16884 // FFEINTRIN_impDDIM //
16885 d__1 = d_dim(&d1, &d2);
16887 // FFEINTRIN_impDEXP //
16890 // FFEINTRIN_impDIM //
16891 r__1 = r_dim(&r1, &r2);
16893 // FFEINTRIN_impDINT //
16896 // FFEINTRIN_impDLOG //
16899 // FFEINTRIN_impDLOG10 //
16900 d__1 = d_lg10(&d1);
16902 // FFEINTRIN_impDMAX1 //
16903 d__1 = (( d1 ) >= ( d2 ) ? ( d1 ) : ( d2 )) ;
16905 // FFEINTRIN_impDMIN1 //
16906 d__1 = (( d1 ) <= ( d2 ) ? ( d1 ) : ( d2 )) ;
16908 // FFEINTRIN_impDMOD //
16909 d__1 = d_mod(&d1, &d2);
16911 // FFEINTRIN_impDNINT //
16912 d__1 = d_nint(&d1);
16914 // FFEINTRIN_impDPROD //
16915 d__1 = (doublereal) r1 * r2;
16917 // FFEINTRIN_impDSIGN //
16918 d__1 = d_sign(&d1, &d2);
16920 // FFEINTRIN_impDSIN //
16923 // FFEINTRIN_impDSINH //
16926 // FFEINTRIN_impDSQRT //
16929 // FFEINTRIN_impDTAN //
16932 // FFEINTRIN_impDTANH //
16935 // FFEINTRIN_impEXP //
16938 // FFEINTRIN_impIABS //
16939 i__1 = (( i1 ) >= 0 ? ( i1 ) : -( i1 )) ;
16941 // FFEINTRIN_impICHAR //
16942 i__1 = *(unsigned char *)a1;
16944 // FFEINTRIN_impIDIM //
16945 i__1 = i_dim(&i1, &i2);
16947 // FFEINTRIN_impIDNINT //
16948 i__1 = i_dnnt(&d1);
16950 // FFEINTRIN_impINDEX //
16951 i__1 = i_indx(a1, a2, 10L, 10L);
16953 // FFEINTRIN_impISIGN //
16954 i__1 = i_sign(&i1, &i2);
16956 // FFEINTRIN_impLEN //
16957 i__1 = i_len(a1, 10L);
16959 // FFEINTRIN_impLGE //
16960 L__1 = l_ge(a1, a2, 10L, 10L);
16962 // FFEINTRIN_impLGT //
16963 L__1 = l_gt(a1, a2, 10L, 10L);
16965 // FFEINTRIN_impLLE //
16966 L__1 = l_le(a1, a2, 10L, 10L);
16968 // FFEINTRIN_impLLT //
16969 L__1 = l_lt(a1, a2, 10L, 10L);
16971 // FFEINTRIN_impMAX0 //
16972 i__1 = (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
16974 // FFEINTRIN_impMAX1 //
16975 i__1 = (integer) (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ;
16977 // FFEINTRIN_impMIN0 //
16978 i__1 = (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
16980 // FFEINTRIN_impMIN1 //
16981 i__1 = (integer) (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ;
16983 // FFEINTRIN_impMOD //
16986 // FFEINTRIN_impNINT //
16987 i__1 = i_nint(&r1);
16989 // FFEINTRIN_impSIGN //
16990 r__1 = r_sign(&r1, &r2);
16992 // FFEINTRIN_impSIN //
16995 // FFEINTRIN_impSINH //
16998 // FFEINTRIN_impSQRT //
17001 // FFEINTRIN_impTAN //
17004 // FFEINTRIN_impTANH //
17007 // FFEINTRIN_imp_CMPLX_C //
17010 q__1.r = r__1, q__1.i = r__2;
17012 // FFEINTRIN_imp_CMPLX_D //
17013 z__1.r = d1, z__1.i = d2;
17015 // FFEINTRIN_imp_CMPLX_I //
17018 q__1.r = r__1, q__1.i = r__2;
17020 // FFEINTRIN_imp_CMPLX_R //
17021 q__1.r = r1, q__1.i = r2;
17023 // FFEINTRIN_imp_DBLE_C //
17024 d__1 = (doublereal) c1.r;
17026 // FFEINTRIN_imp_DBLE_D //
17029 // FFEINTRIN_imp_DBLE_I //
17030 d__1 = (doublereal) i1;
17032 // FFEINTRIN_imp_DBLE_R //
17033 d__1 = (doublereal) r1;
17035 // FFEINTRIN_imp_INT_C //
17036 i__1 = (integer) c1.r;
17038 // FFEINTRIN_imp_INT_D //
17039 i__1 = (integer) d1;
17041 // FFEINTRIN_imp_INT_I //
17044 // FFEINTRIN_imp_INT_R //
17045 i__1 = (integer) r1;
17047 // FFEINTRIN_imp_REAL_C //
17050 // FFEINTRIN_imp_REAL_D //
17053 // FFEINTRIN_imp_REAL_I //
17056 // FFEINTRIN_imp_REAL_R //
17060 // FFEINTRIN_imp_INT_D: //
17062 // FFEINTRIN_specIDINT //
17063 i__1 = (integer) d1;
17066 // FFEINTRIN_imp_INT_R: //
17068 // FFEINTRIN_specIFIX //
17069 i__1 = (integer) r1;
17071 // FFEINTRIN_specINT //
17072 i__1 = (integer) r1;
17075 // FFEINTRIN_imp_REAL_D: //
17077 // FFEINTRIN_specSNGL //
17081 // FFEINTRIN_imp_REAL_I: //
17083 // FFEINTRIN_specFLOAT //
17086 // FFEINTRIN_specREAL //
17092 -------- (end output file from f2c)