1 /* com.c -- Implementation File (module.c template V1.0) 2 Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 3 Free Software Foundation, Inc. 4 Contributed by James Craig Burley. 5 6 This file is part of GNU Fortran. 7 8 GNU Fortran is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2, or (at your option) 11 any later version. 12 13 GNU Fortran is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with GNU Fortran; see the file COPYING. If not, write to 20 the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 21 02111-1307, USA. 22 23 Related Modules: 24 None 25 26 Description: 27 Contains compiler-specific functions. 28 29 Modifications: 30 */ 31 32 /* Understanding this module means understanding the interface between 33 the g77 front end and the gcc back end (or, perhaps, some other 34 back end). In here are the functions called by the front end proper 35 to notify whatever back end is in place about certain things, and 36 also the back-end-specific functions. It's a bear to deal with, so 37 lately I've been trying to simplify things, especially with regard 38 to the gcc-back-end-specific stuff. 39 40 Building expressions generally seems quite easy, but building decls 41 has been challenging and is undergoing revision. gcc has several 42 kinds of decls: 43 44 TYPE_DECL -- a type (int, float, struct, function, etc.) 45 CONST_DECL -- a constant of some type other than function 46 LABEL_DECL -- a variable or a constant? 47 PARM_DECL -- an argument to a function (a variable that is a dummy) 48 RESULT_DECL -- the return value of a function (a variable) 49 VAR_DECL -- other variable (can hold a ptr-to-function, struct, int, etc.) 50 FUNCTION_DECL -- a function (either the actual function or an extern ref) 51 FIELD_DECL -- a field in a struct or union (goes into types) 52 53 g77 has a set of functions that somewhat parallels the gcc front end 54 when it comes to building decls: 55 56 Internal Function (one we define, not just declare as extern): 57 if (is_nested) push_f_function_context (); 58 start_function (get_identifier ("function_name"), function_type, 59 is_nested, is_public); 60 // for each arg, build PARM_DECL and call push_parm_decl (decl) with it; 61 store_parm_decls (is_main_program); 62 ffecom_start_compstmt (); 63 // for stmts and decls inside function, do appropriate things; 64 ffecom_end_compstmt (); 65 finish_function (is_nested); 66 if (is_nested) pop_f_function_context (); 67 68 Everything Else: 69 tree d; 70 tree init; 71 // fill in external, public, static, &c for decl, and 72 // set DECL_INITIAL to error_mark_node if going to initialize 73 // set is_top_level TRUE only if not at top level and decl 74 // must go in top level (i.e. not within current function decl context) 75 d = start_decl (decl, is_top_level); 76 init = ...; // if have initializer 77 finish_decl (d, init, is_top_level); 78 79 */ 80 81 /* Include files. */ 82 83 #include "proj.h" 84 #include "flags.h" 85 #include "real.h" 86 #include "rtl.h" 87 #include "toplev.h" 88 #include "tree.h" 89 #include "output.h" /* Must follow tree.h so TREE_CODE is defined! */ 90 #include "convert.h" 91 #include "ggc.h" 92 #include "diagnostic.h" 93 #include "intl.h" 94 #include "langhooks.h" 95 #include "langhooks-def.h" 96 #include "debug.h" 97 98 /* VMS-specific definitions */ 99 #ifdef VMS 100 #include <descrip.h> 101 #define O_RDONLY 0 /* Open arg for Read/Only */ 102 #define O_WRONLY 1 /* Open arg for Write/Only */ 103 #define read(fd,buf,size) VMS_read (fd,buf,size) 104 #define write(fd,buf,size) VMS_write (fd,buf,size) 105 #define open(fname,mode,prot) VMS_open (fname,mode,prot) 106 #define fopen(fname,mode) VMS_fopen (fname,mode) 107 #define freopen(fname,mode,ofile) VMS_freopen (fname,mode,ofile) 108 #define strncat(dst,src,cnt) VMS_strncat (dst,src,cnt) 109 #define fstat(fd,stbuf) VMS_fstat (fd,stbuf) 110 static int VMS_fstat (), VMS_stat (); 111 static char * VMS_strncat (); 112 static int VMS_read (); 113 static int VMS_write (); 114 static int VMS_open (); 115 static FILE * VMS_fopen (); 116 static FILE * VMS_freopen (); 117 static void hack_vms_include_specification (); 118 typedef struct { unsigned :16, :16, :16; } vms_ino_t; 119 #define ino_t vms_ino_t 120 #define INCLUDE_LEN_FUDGE 10 /* leave room for VMS syntax conversion */ 121 #endif /* VMS */ 122 123 #define FFECOM_DETERMINE_TYPES 1 /* for com.h */ 124 #include "com.h" 125 #include "bad.h" 126 #include "bld.h" 127 #include "equiv.h" 128 #include "expr.h" 129 #include "implic.h" 130 #include "info.h" 131 #include "malloc.h" 132 #include "src.h" 133 #include "st.h" 134 #include "storag.h" 135 #include "symbol.h" 136 #include "target.h" 137 #include "top.h" 138 #include "type.h" 139 140 /* Externals defined here. */ 141 142 /* Stream for reading from the input file. */ 143 FILE *finput; 144 145 /* These definitions parallel those in c-decl.c so that code from that 146 module can be used pretty much as is. Much of these defs aren't 147 otherwise used, i.e. by g77 code per se, except some of them are used 148 to build some of them that are. The ones that are global (i.e. not 149 "static") are those that ste.c and such might use (directly 150 or by using com macros that reference them in their definitions). */ 151 152 tree string_type_node; 153 154 /* The rest of these are inventions for g77, though there might be 155 similar things in the C front end. As they are found, these 156 inventions should be renamed to be canonical. Note that only 157 the ones currently required to be global are so. */ 158 159 static GTY(()) tree ffecom_tree_fun_type_void; 160 161 tree ffecom_integer_type_node; /* Abbrev for _tree_type[blah][blah]. */ 162 tree ffecom_integer_zero_node; /* Like *_*_* with g77's integer type. */ 163 tree ffecom_integer_one_node; /* " */ 164 tree ffecom_tree_type[FFEINFO_basictype][FFEINFO_kindtype]; 165 166 /* _fun_type things are the f2c-specific versions. For -fno-f2c, 167 just use build_function_type and build_pointer_type on the 168 appropriate _tree_type array element. */ 169 170 static GTY(()) tree ffecom_tree_fun_type[FFEINFO_basictype][FFEINFO_kindtype]; 171 static GTY(()) tree 172 ffecom_tree_ptr_to_fun_type[FFEINFO_basictype][FFEINFO_kindtype]; 173 static GTY(()) tree ffecom_tree_subr_type; 174 static GTY(()) tree ffecom_tree_ptr_to_subr_type; 175 static GTY(()) tree ffecom_tree_blockdata_type; 176 177 static GTY(()) tree ffecom_tree_xargc_; 178 179 ffecomSymbol ffecom_symbol_null_ 180 = 181 { 182 NULL_TREE, 183 NULL_TREE, 184 NULL_TREE, 185 NULL_TREE, 186 false 187 }; 188 ffeinfoKindtype ffecom_pointer_kind_ = FFEINFO_basictypeNONE; 189 ffeinfoKindtype ffecom_label_kind_ = FFEINFO_basictypeNONE; 190 191 int ffecom_f2c_typecode_[FFEINFO_basictype][FFEINFO_kindtype]; 192 tree ffecom_f2c_integer_type_node; 193 static GTY(()) tree ffecom_f2c_ptr_to_integer_type_node; 194 tree ffecom_f2c_address_type_node; 195 tree ffecom_f2c_real_type_node; 196 static GTY(()) tree ffecom_f2c_ptr_to_real_type_node; 197 tree ffecom_f2c_doublereal_type_node; 198 tree ffecom_f2c_complex_type_node; 199 tree ffecom_f2c_doublecomplex_type_node; 200 tree ffecom_f2c_longint_type_node; 201 tree ffecom_f2c_logical_type_node; 202 tree ffecom_f2c_flag_type_node; 203 tree ffecom_f2c_ftnlen_type_node; 204 tree ffecom_f2c_ftnlen_zero_node; 205 tree ffecom_f2c_ftnlen_one_node; 206 tree ffecom_f2c_ftnlen_two_node; 207 tree ffecom_f2c_ptr_to_ftnlen_type_node; 208 tree ffecom_f2c_ftnint_type_node; 209 tree ffecom_f2c_ptr_to_ftnint_type_node; 210 211 /* Simple definitions and enumerations. */ 212 213 #ifndef FFECOM_sizeMAXSTACKITEM 214 #define FFECOM_sizeMAXSTACKITEM 32*1024 /* Keep user-declared things 215 larger than this # bytes 216 off stack if possible. */ 217 #endif 218 219 /* For systems that have large enough stacks, they should define 220 this to 0, and here, for ease of use later on, we just undefine 221 it if it is 0. */ 222 223 #if FFECOM_sizeMAXSTACKITEM == 0 224 #undef FFECOM_sizeMAXSTACKITEM 225 #endif 226 227 typedef enum 228 { 229 FFECOM_rttypeVOID_, 230 FFECOM_rttypeVOIDSTAR_, /* C's `void *' type. */ 231 FFECOM_rttypeFTNINT_, /* f2c's `ftnint' type. */ 232 FFECOM_rttypeINTEGER_, /* f2c's `integer' type. */ 233 FFECOM_rttypeLONGINT_, /* f2c's `longint' type. */ 234 FFECOM_rttypeLOGICAL_, /* f2c's `logical' type. */ 235 FFECOM_rttypeREAL_F2C_, /* f2c's `real' returned as `double'. */ 236 FFECOM_rttypeREAL_GNU_, /* `real' returned as such. */ 237 FFECOM_rttypeCOMPLEX_F2C_, /* f2c's `complex' returned via 1st arg. */ 238 FFECOM_rttypeCOMPLEX_GNU_, /* f2c's `complex' returned directly. */ 239 FFECOM_rttypeDOUBLE_, /* C's `double' type. */ 240 FFECOM_rttypeDOUBLEREAL_, /* f2c's `doublereal' type. */ 241 FFECOM_rttypeDBLCMPLX_F2C_, /* f2c's `doublecomplex' returned via 1st arg. */ 242 FFECOM_rttypeDBLCMPLX_GNU_, /* f2c's `doublecomplex' returned directly. */ 243 FFECOM_rttypeCHARACTER_, /* f2c `char *'/`ftnlen' pair. */ 244 FFECOM_rttype_ 245 } ffecomRttype_; 246 247 /* Internal typedefs. */ 248 249 typedef struct _ffecom_concat_list_ ffecomConcatList_; 250 251 /* Private include files. */ 252 253 254 /* Internal structure definitions. */ 255 256 struct _ffecom_concat_list_ 257 { 258 ffebld *exprs; 259 int count; 260 int max; 261 ffetargetCharacterSize minlen; 262 ffetargetCharacterSize maxlen; 263 }; 264 265 /* Static functions (internal). */ 266 267 static tree ffe_type_for_mode PARAMS ((enum machine_mode, int)); 268 static tree ffe_type_for_size PARAMS ((unsigned int, int)); 269 static tree ffe_unsigned_type PARAMS ((tree)); 270 static tree ffe_signed_type PARAMS ((tree)); 271 static tree ffe_signed_or_unsigned_type PARAMS ((int, tree)); 272 static bool ffe_mark_addressable PARAMS ((tree)); 273 static tree ffe_truthvalue_conversion PARAMS ((tree)); 274 static void ffecom_init_decl_processing PARAMS ((void)); 275 static tree ffecom_arglist_expr_ (const char *argstring, ffebld args); 276 static tree ffecom_widest_expr_type_ (ffebld list); 277 static bool ffecom_overlap_ (tree dest_decl, tree dest_offset, 278 tree dest_size, tree source_tree, 279 ffebld source, bool scalar_arg); 280 static bool ffecom_args_overlapping_ (tree dest_tree, ffebld dest, 281 tree args, tree callee_commons, 282 bool scalar_args); 283 static tree ffecom_build_f2c_string_ (int i, const char *s); 284 static tree ffecom_call_ (tree fn, ffeinfoKindtype kt, 285 bool is_f2c_complex, tree type, 286 tree args, tree dest_tree, 287 ffebld dest, bool *dest_used, 288 tree callee_commons, bool scalar_args, tree hook); 289 static tree ffecom_call_binop_ (tree fn, ffeinfoKindtype kt, 290 bool is_f2c_complex, tree type, 291 ffebld left, ffebld right, 292 tree dest_tree, ffebld dest, 293 bool *dest_used, tree callee_commons, 294 bool scalar_args, bool ref, tree hook); 295 static void ffecom_char_args_x_ (tree *xitem, tree *length, 296 ffebld expr, bool with_null); 297 static tree ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy); 298 static tree ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s); 299 static ffecomConcatList_ 300 ffecom_concat_list_gather_ (ffecomConcatList_ catlist, 301 ffebld expr, 302 ffetargetCharacterSize max); 303 static void ffecom_concat_list_kill_ (ffecomConcatList_ catlist); 304 static ffecomConcatList_ ffecom_concat_list_new_ (ffebld expr, 305 ffetargetCharacterSize max); 306 static void ffecom_debug_kludge_ (tree aggr, const char *aggr_type, 307 ffesymbol member, tree member_type, 308 ffetargetOffset offset); 309 static void ffecom_do_entry_ (ffesymbol fn, int entrynum); 310 static tree ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest, 311 bool *dest_used, bool assignp, bool widenp); 312 static tree ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree, 313 ffebld dest, bool *dest_used); 314 static tree ffecom_expr_power_integer_ (ffebld expr); 315 static void ffecom_expr_transform_ (ffebld expr); 316 static void ffecom_f2c_make_type_ (tree *type, int tcode, const char *name); 317 static void ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size, 318 int code); 319 static ffeglobal ffecom_finish_global_ (ffeglobal global); 320 static ffesymbol ffecom_finish_symbol_transform_ (ffesymbol s); 321 static tree ffecom_get_appended_identifier_ (char us, const char *text); 322 static tree ffecom_get_external_identifier_ (ffesymbol s); 323 static tree ffecom_get_identifier_ (const char *text); 324 static tree ffecom_gen_sfuncdef_ (ffesymbol s, 325 ffeinfoBasictype bt, 326 ffeinfoKindtype kt); 327 static const char *ffecom_gfrt_args_ (ffecomGfrt ix); 328 static tree ffecom_gfrt_tree_ (ffecomGfrt ix); 329 static tree ffecom_init_zero_ (tree decl); 330 static tree ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg, 331 tree *maybe_tree); 332 static tree ffecom_intrinsic_len_ (ffebld expr); 333 static void ffecom_let_char_ (tree dest_tree, 334 tree dest_length, 335 ffetargetCharacterSize dest_size, 336 ffebld source); 337 static void ffecom_make_gfrt_ (ffecomGfrt ix); 338 static void ffecom_member_phase1_ (ffestorag mst, ffestorag st); 339 static void ffecom_member_phase2_ (ffestorag mst, ffestorag st); 340 static void ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size, 341 ffebld source); 342 static void ffecom_push_dummy_decls_ (ffebld dumlist, 343 bool stmtfunc); 344 static void ffecom_start_progunit_ (void); 345 static ffesymbol ffecom_sym_transform_ (ffesymbol s); 346 static ffesymbol ffecom_sym_transform_assign_ (ffesymbol s); 347 static void ffecom_transform_common_ (ffesymbol s); 348 static void ffecom_transform_equiv_ (ffestorag st); 349 static tree ffecom_transform_namelist_ (ffesymbol s); 350 static void ffecom_tree_canonize_ptr_ (tree *decl, tree *offset, 351 tree t); 352 static void ffecom_tree_canonize_ref_ (tree *decl, tree *offset, 353 tree *size, tree tree); 354 static tree ffecom_tree_divide_ (tree tree_type, tree left, tree right, 355 tree dest_tree, ffebld dest, 356 bool *dest_used, tree hook); 357 static tree ffecom_type_localvar_ (ffesymbol s, 358 ffeinfoBasictype bt, 359 ffeinfoKindtype kt); 360 static tree ffecom_type_namelist_ (void); 361 static tree ffecom_type_vardesc_ (void); 362 static tree ffecom_vardesc_ (ffebld expr); 363 static tree ffecom_vardesc_array_ (ffesymbol s); 364 static tree ffecom_vardesc_dims_ (ffesymbol s); 365 static tree ffecom_convert_narrow_ (tree type, tree expr); 366 static tree ffecom_convert_widen_ (tree type, tree expr); 367 368 /* These are static functions that parallel those found in the C front 369 end and thus have the same names. */ 370 371 static tree bison_rule_compstmt_ (void); 372 static void bison_rule_pushlevel_ (void); 373 static void delete_block (tree block); 374 static int duplicate_decls (tree newdecl, tree olddecl); 375 static void finish_decl (tree decl, tree init, bool is_top_level); 376 static void finish_function (int nested); 377 static const char *ffe_printable_name (tree decl, int v); 378 static void ffe_print_error_function (diagnostic_context *, const char *); 379 static tree lookup_name_current_level (tree name); 380 static struct f_binding_level *make_binding_level (void); 381 static void pop_f_function_context (void); 382 static void push_f_function_context (void); 383 static void push_parm_decl (tree parm); 384 static tree pushdecl_top_level (tree decl); 385 static int kept_level_p (void); 386 static tree storedecls (tree decls); 387 static void store_parm_decls (int is_main_program); 388 static tree start_decl (tree decl, bool is_top_level); 389 static void start_function (tree name, tree type, int nested, int public); 390 static void ffecom_file_ (const char *name); 391 static void ffecom_close_include_ (FILE *f); 392 static int ffecom_decode_include_option_ (char *spec); 393 static FILE *ffecom_open_include_ (char *name, ffewhereLine l, 394 ffewhereColumn c); 395 396 /* Static objects accessed by functions in this module. */ 397 398 static ffesymbol ffecom_primary_entry_ = NULL; 399 static ffesymbol ffecom_nested_entry_ = NULL; 400 static ffeinfoKind ffecom_primary_entry_kind_; 401 static bool ffecom_primary_entry_is_proc_; 402 static GTY(()) tree ffecom_outer_function_decl_; 403 static GTY(()) tree ffecom_previous_function_decl_; 404 static GTY(()) tree ffecom_which_entrypoint_decl_; 405 static GTY(()) tree ffecom_float_zero_; 406 static GTY(()) tree ffecom_float_half_; 407 static GTY(()) tree ffecom_double_zero_; 408 static GTY(()) tree ffecom_double_half_; 409 static GTY(()) tree ffecom_func_result_;/* For functions. */ 410 static GTY(()) tree ffecom_func_length_;/* For CHARACTER fns. */ 411 static ffebld ffecom_list_blockdata_; 412 static ffebld ffecom_list_common_; 413 static ffebld ffecom_master_arglist_; 414 static ffeinfoBasictype ffecom_master_bt_; 415 static ffeinfoKindtype ffecom_master_kt_; 416 static ffetargetCharacterSize ffecom_master_size_; 417 static int ffecom_num_fns_ = 0; 418 static int ffecom_num_entrypoints_ = 0; 419 static bool ffecom_is_altreturning_ = FALSE; 420 static GTY(()) tree ffecom_multi_type_node_; 421 static GTY(()) tree ffecom_multi_retval_; 422 static GTY(()) tree 423 ffecom_multi_fields_[FFEINFO_basictype][FFEINFO_kindtype]; 424 static bool ffecom_member_namelisted_; /* _member_phase1_ namelisted? */ 425 static bool ffecom_doing_entry_ = FALSE; 426 static bool ffecom_transform_only_dummies_ = FALSE; 427 static int ffecom_typesize_pointer_; 428 static int ffecom_typesize_integer1_; 429 430 /* Holds pointer-to-function expressions. */ 431 432 static GTY(()) tree ffecom_gfrt_[FFECOM_gfrt]; 433 434 /* Holds the external names of the functions. */ 435 436 static const char *const ffecom_gfrt_name_[FFECOM_gfrt] 437 = 438 { 439 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) NAME, 440 #include "com-rt.def" 441 #undef DEFGFRT 442 }; 443 444 /* Whether the function returns. */ 445 446 static const bool ffecom_gfrt_volatile_[FFECOM_gfrt] 447 = 448 { 449 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) VOLATILE, 450 #include "com-rt.def" 451 #undef DEFGFRT 452 }; 453 454 /* Whether the function returns type complex. */ 455 456 static const bool ffecom_gfrt_complex_[FFECOM_gfrt] 457 = 458 { 459 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) COMPLEX, 460 #include "com-rt.def" 461 #undef DEFGFRT 462 }; 463 464 /* Whether the function is const 465 (i.e., has no side effects and only depends on its arguments). */ 466 467 static const bool ffecom_gfrt_const_[FFECOM_gfrt] 468 = 469 { 470 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) CONST, 471 #include "com-rt.def" 472 #undef DEFGFRT 473 }; 474 475 /* Type code for the function return value. */ 476 477 static const ffecomRttype_ ffecom_gfrt_type_[FFECOM_gfrt] 478 = 479 { 480 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) TYPE, 481 #include "com-rt.def" 482 #undef DEFGFRT 483 }; 484 485 /* String of codes for the function's arguments. */ 486 487 static const char *const ffecom_gfrt_argstring_[FFECOM_gfrt] 488 = 489 { 490 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX,CONST) ARGS, 491 #include "com-rt.def" 492 #undef DEFGFRT 493 }; 494 495 /* Internal macros. */ 496 497 /* We let tm.h override the types used here, to handle trivial differences 498 such as the choice of unsigned int or long unsigned int for size_t. 499 When machines start needing nontrivial differences in the size type, 500 it would be best to do something here to figure out automatically 501 from other information what type to use. */ 502 503 #ifndef SIZE_TYPE 504 #define SIZE_TYPE "long unsigned int" 505 #endif 506 507 #define ffecom_concat_list_count_(catlist) ((catlist).count) 508 #define ffecom_concat_list_expr_(catlist,i) ((catlist).exprs[(i)]) 509 #define ffecom_concat_list_maxlen_(catlist) ((catlist).maxlen) 510 #define ffecom_concat_list_minlen_(catlist) ((catlist).minlen) 511 512 #define ffecom_char_args_(i,l,e) ffecom_char_args_x_((i),(l),(e),FALSE) 513 #define ffecom_char_args_with_null_(i,l,e) ffecom_char_args_x_((i),(l),(e),TRUE) 514 515 /* For each binding contour we allocate a binding_level structure 516 * which records the names defined in that contour. 517 * Contours include: 518 * 0) the global one 519 * 1) one for each function definition, 520 * where internal declarations of the parameters appear. 521 * 522 * The current meaning of a name can be found by searching the levels from 523 * the current one out to the global one. 524 */ 525 526 /* Note that the information in the `names' component of the global contour 527 is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers. */ 528 529 struct f_binding_level GTY(()) 530 { 531 /* A chain of _DECL nodes for all variables, constants, functions, 532 and typedef types. These are in the reverse of the order supplied. 533 */ 534 tree names; 535 536 /* For each level (except not the global one), 537 a chain of BLOCK nodes for all the levels 538 that were entered and exited one level down. */ 539 tree blocks; 540 541 /* The BLOCK node for this level, if one has been preallocated. 542 If 0, the BLOCK is allocated (if needed) when the level is popped. */ 543 tree this_block; 544 545 /* The binding level which this one is contained in (inherits from). */ 546 struct f_binding_level *level_chain; 547 548 /* 0: no ffecom_prepare_* functions called at this level yet; 549 1: ffecom_prepare* functions called, except not ffecom_prepare_end; 550 2: ffecom_prepare_end called. */ 551 int prep_state; 552 }; 553 554 #define NULL_BINDING_LEVEL (struct f_binding_level *) NULL 555 556 /* The binding level currently in effect. */ 557 558 static GTY(()) struct f_binding_level *current_binding_level; 559 560 /* A chain of binding_level structures awaiting reuse. */ 561 562 static GTY((deletable (""))) struct f_binding_level *free_binding_level; 563 564 /* The outermost binding level, for names of file scope. 565 This is created when the compiler is started and exists 566 through the entire run. */ 567 568 static struct f_binding_level *global_binding_level; 569 570 /* Binding level structures are initialized by copying this one. */ 571 572 static const struct f_binding_level clear_binding_level 573 = 574 {NULL, NULL, NULL, NULL_BINDING_LEVEL, 0}; 575 576 /* Language-dependent contents of an identifier. */ 577 578 struct lang_identifier GTY(()) 579 { 580 struct tree_identifier common; 581 tree global_value; 582 tree local_value; 583 tree label_value; 584 bool invented; 585 }; 586 587 /* Macros for access to language-specific slots in an identifier. */ 588 /* Each of these slots contains a DECL node or null. */ 589 590 /* This represents the value which the identifier has in the 591 file-scope namespace. */ 592 #define IDENTIFIER_GLOBAL_VALUE(NODE) \ 593 (((struct lang_identifier *)(NODE))->global_value) 594 /* This represents the value which the identifier has in the current 595 scope. */ 596 #define IDENTIFIER_LOCAL_VALUE(NODE) \ 597 (((struct lang_identifier *)(NODE))->local_value) 598 /* This represents the value which the identifier has as a label in 599 the current label scope. */ 600 #define IDENTIFIER_LABEL_VALUE(NODE) \ 601 (((struct lang_identifier *)(NODE))->label_value) 602 /* This is nonzero if the identifier was "made up" by g77 code. */ 603 #define IDENTIFIER_INVENTED(NODE) \ 604 (((struct lang_identifier *)(NODE))->invented) 605 606 /* The resulting tree type. */ 607 union lang_tree_node 608 GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"), 609 chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)"))) 610 { 611 union tree_node GTY ((tag ("0"), 612 desc ("tree_node_structure (&%h)"))) 613 generic; 614 struct lang_identifier GTY ((tag ("1"))) identifier; 615 }; 616 617 /* Fortran doesn't use either of these. */ 618 struct lang_decl GTY(()) 619 { 620 }; 621 struct lang_type GTY(()) 622 { 623 }; 624 625 /* In identifiers, C uses the following fields in a special way: 626 TREE_PUBLIC to record that there was a previous local extern decl. 627 TREE_USED to record that such a decl was used. 628 TREE_ADDRESSABLE to record that the address of such a decl was used. */ 629 630 /* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function 631 that have names. Here so we can clear out their names' definitions 632 at the end of the function. */ 633 634 static GTY(()) tree named_labels; 635 636 /* A list of LABEL_DECLs from outer contexts that are currently shadowed. */ 637 638 static GTY(()) tree shadowed_labels; 639 640 /* Return the subscript expression, modified to do range-checking. 641 642 `array' is the array type to be checked against. 643 `element' is the subscript expression to check. 644 `dim' is the dimension number (starting at 0). 645 `total_dims' is the total number of dimensions (0 for CHARACTER substring). 646 `item' is the array decl or NULL_TREE. 647 */ 648 649 static tree 650 ffecom_subscript_check_ (tree array, tree element, int dim, int total_dims, 651 const char *array_name, tree item) 652 { 653 tree low = TYPE_MIN_VALUE (TYPE_DOMAIN (array)); 654 tree high = TYPE_MAX_VALUE (TYPE_DOMAIN (array)); 655 tree cond; 656 tree die; 657 tree args; 658 659 if (element == error_mark_node) 660 return element; 661 662 if (TREE_TYPE (low) != TREE_TYPE (element)) 663 { 664 if (TYPE_PRECISION (TREE_TYPE (low)) 665 > TYPE_PRECISION (TREE_TYPE (element))) 666 element = convert (TREE_TYPE (low), element); 667 else 668 { 669 low = convert (TREE_TYPE (element), low); 670 if (high) 671 high = convert (TREE_TYPE (element), high); 672 } 673 } 674 675 element = ffecom_save_tree (element); 676 if (total_dims == 0) 677 { 678 /* Special handling for substring range checks. Fortran allows the 679 end subscript < begin subscript, which means that expressions like 680 string(1:0) are valid (and yield a null string). In view of this, 681 enforce two simpler conditions: 682 1) element<=high for end-substring; 683 2) element>=low for start-substring. 684 Run-time character movement will enforce remaining conditions. 685 686 More complicated checks would be better, but present structure only 687 provides one index element at a time, so it is not possible to 688 enforce a check of both i and j in string(i:j). If it were, the 689 complete set of rules would read, 690 if ( ((j<i) && ((low<=i<=high) || (low<=j<=high))) || 691 ((low<=i<=high) && (low<=j<=high)) ) 692 ok ; 693 else 694 range error ; 695 */ 696 if (dim) 697 cond = ffecom_2 (LE_EXPR, integer_type_node, element, high); 698 else 699 cond = ffecom_2 (LE_EXPR, integer_type_node, low, element); 700 } 701 else 702 { 703 /* Array reference substring range checking. */ 704 705 cond = ffecom_2 (LE_EXPR, integer_type_node, 706 low, 707 element); 708 if (high) 709 { 710 cond = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node, 711 cond, 712 ffecom_2 (LE_EXPR, integer_type_node, 713 element, 714 high)); 715 } 716 } 717 718 /* If the array index is safe at compile-time, return element. */ 719 if (integer_nonzerop (cond)) 720 return element; 721 722 { 723 int len; 724 char *proc; 725 char *var; 726 tree arg3; 727 tree arg2; 728 tree arg1; 729 tree arg4; 730 731 switch (total_dims) 732 { 733 case 0: 734 var = concat (array_name, "[", (dim ? "end" : "start"), 735 "-substring]", NULL); 736 len = strlen (var) + 1; 737 arg1 = build_string (len, var); 738 free (var); 739 break; 740 741 case 1: 742 len = strlen (array_name) + 1; 743 arg1 = build_string (len, array_name); 744 break; 745 746 default: 747 var = xmalloc (strlen (array_name) + 40); 748 sprintf (var, "%s[subscript-%d-of-%d]", 749 array_name, 750 dim + 1, total_dims); 751 len = strlen (var) + 1; 752 arg1 = build_string (len, var); 753 free (var); 754 break; 755 } 756 757 TREE_TYPE (arg1) 758 = build_type_variant (build_array_type (char_type_node, 759 build_range_type 760 (integer_type_node, 761 integer_one_node, 762 build_int_2 (len, 0))), 763 1, 0); 764 TREE_CONSTANT (arg1) = 1; 765 TREE_STATIC (arg1) = 1; 766 arg1 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg1)), 767 arg1); 768 769 /* s_rnge adds one to the element to print it, so bias against 770 that -- want to print a faithful *subscript* value. */ 771 arg2 = convert (ffecom_f2c_ftnint_type_node, 772 ffecom_2 (MINUS_EXPR, 773 TREE_TYPE (element), 774 element, 775 convert (TREE_TYPE (element), 776 integer_one_node))); 777 778 proc = concat (input_filename, "/", 779 IDENTIFIER_POINTER (DECL_NAME (current_function_decl)), 780 NULL); 781 len = strlen (proc) + 1; 782 arg3 = build_string (len, proc); 783 784 free (proc); 785 786 TREE_TYPE (arg3) 787 = build_type_variant (build_array_type (char_type_node, 788 build_range_type 789 (integer_type_node, 790 integer_one_node, 791 build_int_2 (len, 0))), 792 1, 0); 793 TREE_CONSTANT (arg3) = 1; 794 TREE_STATIC (arg3) = 1; 795 arg3 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg3)), 796 arg3); 797 798 arg4 = convert (ffecom_f2c_ftnint_type_node, 799 build_int_2 (lineno, 0)); 800 801 arg1 = build_tree_list (NULL_TREE, arg1); 802 arg2 = build_tree_list (NULL_TREE, arg2); 803 arg3 = build_tree_list (NULL_TREE, arg3); 804 arg4 = build_tree_list (NULL_TREE, arg4); 805 TREE_CHAIN (arg3) = arg4; 806 TREE_CHAIN (arg2) = arg3; 807 TREE_CHAIN (arg1) = arg2; 808 809 args = arg1; 810 } 811 die = ffecom_call_gfrt (FFECOM_gfrtRANGE, 812 args, NULL_TREE); 813 TREE_SIDE_EFFECTS (die) = 1; 814 die = convert (void_type_node, die); 815 816 if (integer_zerop (cond) && item) 817 ffe_mark_addressable (item); 818 819 return ffecom_3 (COND_EXPR, TREE_TYPE (element), cond, element, die); 820 } 821 822 /* Return the computed element of an array reference. 823 824 `item' is NULL_TREE, or the transformed pointer to the array. 825 `expr' is the original opARRAYREF expression, which is transformed 826 if `item' is NULL_TREE. 827 `want_ptr' is nonzero if a pointer to the element, instead of 828 the element itself, is to be returned. */ 829 830 static tree 831 ffecom_arrayref_ (tree item, ffebld expr, int want_ptr) 832 { 833 ffebld dims[FFECOM_dimensionsMAX]; 834 int i; 835 int total_dims; 836 int flatten = ffe_is_flatten_arrays (); 837 int need_ptr; 838 tree array; 839 tree element; 840 tree tree_type; 841 tree tree_type_x; 842 const char *array_name; 843 ffetype type; 844 ffebld list; 845 846 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER) 847 array_name = ffesymbol_text (ffebld_symter (ffebld_left (expr))); 848 else 849 array_name = "[expr?]"; 850 851 /* Build up ARRAY_REFs in reverse order (since we're column major 852 here in Fortran land). */ 853 854 for (i = 0, list = ffebld_right (expr); 855 list != NULL; 856 ++i, list = ffebld_trail (list)) 857 { 858 dims[i] = ffebld_head (list); 859 type = ffeinfo_type (ffebld_basictype (dims[i]), 860 ffebld_kindtype (dims[i])); 861 if (! flatten 862 && ffecom_typesize_pointer_ > ffecom_typesize_integer1_ 863 && ffetype_size (type) > ffecom_typesize_integer1_) 864 /* E.g. ARRAY(INDEX), given INTEGER*8 INDEX, on a system with 64-bit 865 pointers and 32-bit integers. Do the full 64-bit pointer 866 arithmetic, for codes using arrays for nonstandard heap-like 867 work. */ 868 flatten = 1; 869 } 870 871 total_dims = i; 872 873 need_ptr = want_ptr || flatten; 874 875 if (! item) 876 { 877 if (need_ptr) 878 item = ffecom_ptr_to_expr (ffebld_left (expr)); 879 else 880 item = ffecom_expr (ffebld_left (expr)); 881 882 if (item == error_mark_node) 883 return item; 884 885 if (ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereFLEETING 886 && ! ffe_mark_addressable (item)) 887 return error_mark_node; 888 } 889 890 if (item == error_mark_node) 891 return item; 892 893 if (need_ptr) 894 { 895 tree min; 896 897 for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))); 898 i >= 0; 899 --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array))) 900 { 901 min = TYPE_MIN_VALUE (TYPE_DOMAIN (array)); 902 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE); 903 if (flag_bounds_check) 904 element = ffecom_subscript_check_ (array, element, i, total_dims, 905 array_name, item); 906 if (element == error_mark_node) 907 return element; 908 909 /* Widen integral arithmetic as desired while preserving 910 signedness. */ 911 tree_type = TREE_TYPE (element); 912 tree_type_x = tree_type; 913 if (tree_type 914 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT 915 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype)) 916 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype); 917 918 if (TREE_TYPE (min) != tree_type_x) 919 min = convert (tree_type_x, min); 920 if (TREE_TYPE (element) != tree_type_x) 921 element = convert (tree_type_x, element); 922 923 item = ffecom_2 (PLUS_EXPR, 924 build_pointer_type (TREE_TYPE (array)), 925 item, 926 size_binop (MULT_EXPR, 927 size_in_bytes (TREE_TYPE (array)), 928 convert (sizetype, 929 fold (build (MINUS_EXPR, 930 tree_type_x, 931 element, min))))); 932 } 933 if (! want_ptr) 934 { 935 item = ffecom_1 (INDIRECT_REF, 936 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))), 937 item); 938 } 939 } 940 else 941 { 942 for (--i; 943 i >= 0; 944 --i) 945 { 946 array = TYPE_MAIN_VARIANT (TREE_TYPE (item)); 947 948 element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE); 949 if (flag_bounds_check) 950 element = ffecom_subscript_check_ (array, element, i, total_dims, 951 array_name, item); 952 if (element == error_mark_node) 953 return element; 954 955 /* Widen integral arithmetic as desired while preserving 956 signedness. */ 957 tree_type = TREE_TYPE (element); 958 tree_type_x = tree_type; 959 if (tree_type 960 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT 961 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype)) 962 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype); 963 964 element = convert (tree_type_x, element); 965 966 item = ffecom_2 (ARRAY_REF, 967 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))), 968 item, 969 element); 970 } 971 } 972 973 return item; 974 } 975 976 /* This is like gcc's stabilize_reference -- in fact, most of the code 977 comes from that -- but it handles the situation where the reference 978 is going to have its subparts picked at, and it shouldn't change 979 (or trigger extra invocations of functions in the subtrees) due to 980 this. save_expr is a bit overzealous, because we don't need the 981 entire thing calculated and saved like a temp. So, for DECLs, no 982 change is needed, because these are stable aggregates, and ARRAY_REF 983 and such might well be stable too, but for things like calculations, 984 we do need to calculate a snapshot of a value before picking at it. */ 985 986 static tree 987 ffecom_stabilize_aggregate_ (tree ref) 988 { 989 tree result; 990 enum tree_code code = TREE_CODE (ref); 991 992 switch (code) 993 { 994 case VAR_DECL: 995 case PARM_DECL: 996 case RESULT_DECL: 997 /* No action is needed in this case. */ 998 return ref; 999 1000 case NOP_EXPR: 1001 case CONVERT_EXPR: 1002 case FLOAT_EXPR: 1003 case FIX_TRUNC_EXPR: 1004 case FIX_FLOOR_EXPR: 1005 case FIX_ROUND_EXPR: 1006 case FIX_CEIL_EXPR: 1007 result = build_nt (code, stabilize_reference (TREE_OPERAND (ref, 0))); 1008 break; 1009 1010 case INDIRECT_REF: 1011 result = build_nt (INDIRECT_REF, 1012 stabilize_reference_1 (TREE_OPERAND (ref, 0))); 1013 break; 1014 1015 case COMPONENT_REF: 1016 result = build_nt (COMPONENT_REF, 1017 stabilize_reference (TREE_OPERAND (ref, 0)), 1018 TREE_OPERAND (ref, 1)); 1019 break; 1020 1021 case BIT_FIELD_REF: 1022 result = build_nt (BIT_FIELD_REF, 1023 stabilize_reference (TREE_OPERAND (ref, 0)), 1024 stabilize_reference_1 (TREE_OPERAND (ref, 1)), 1025 stabilize_reference_1 (TREE_OPERAND (ref, 2))); 1026 break; 1027 1028 case ARRAY_REF: 1029 result = build_nt (ARRAY_REF, 1030 stabilize_reference (TREE_OPERAND (ref, 0)), 1031 stabilize_reference_1 (TREE_OPERAND (ref, 1))); 1032 break; 1033 1034 case COMPOUND_EXPR: 1035 result = build_nt (COMPOUND_EXPR, 1036 stabilize_reference_1 (TREE_OPERAND (ref, 0)), 1037 stabilize_reference (TREE_OPERAND (ref, 1))); 1038 break; 1039 1040 case RTL_EXPR: 1041 abort (); 1042 1043 1044 default: 1045 return save_expr (ref); 1046 1047 case ERROR_MARK: 1048 return error_mark_node; 1049 } 1050 1051 TREE_TYPE (result) = TREE_TYPE (ref); 1052 TREE_READONLY (result) = TREE_READONLY (ref); 1053 TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (ref); 1054 TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (ref); 1055 1056 return result; 1057 } 1058 1059 /* A rip-off of gcc's convert.c convert_to_complex function, 1060 reworked to handle complex implemented as C structures 1061 (RECORD_TYPE with two fields, real and imaginary `r' and `i'). */ 1062 1063 static tree 1064 ffecom_convert_to_complex_ (tree type, tree expr) 1065 { 1066 register enum tree_code form = TREE_CODE (TREE_TYPE (expr)); 1067 tree subtype; 1068 1069 assert (TREE_CODE (type) == RECORD_TYPE); 1070 1071 subtype = TREE_TYPE (TYPE_FIELDS (type)); 1072 1073 if (form == REAL_TYPE || form == INTEGER_TYPE || form == ENUMERAL_TYPE) 1074 { 1075 expr = convert (subtype, expr); 1076 return ffecom_2 (COMPLEX_EXPR, type, expr, 1077 convert (subtype, integer_zero_node)); 1078 } 1079 1080 if (form == RECORD_TYPE) 1081 { 1082 tree elt_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))); 1083 if (TYPE_MAIN_VARIANT (elt_type) == TYPE_MAIN_VARIANT (subtype)) 1084 return expr; 1085 else 1086 { 1087 expr = save_expr (expr); 1088 return ffecom_2 (COMPLEX_EXPR, 1089 type, 1090 convert (subtype, 1091 ffecom_1 (REALPART_EXPR, 1092 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))), 1093 expr)), 1094 convert (subtype, 1095 ffecom_1 (IMAGPART_EXPR, 1096 TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))), 1097 expr))); 1098 } 1099 } 1100 1101 if (form == POINTER_TYPE || form == REFERENCE_TYPE) 1102 error ("pointer value used where a complex was expected"); 1103 else 1104 error ("aggregate value used where a complex was expected"); 1105 1106 return ffecom_2 (COMPLEX_EXPR, type, 1107 convert (subtype, integer_zero_node), 1108 convert (subtype, integer_zero_node)); 1109 } 1110 1111 /* Like gcc's convert(), but crashes if widening might happen. */ 1112 1113 static tree 1114 ffecom_convert_narrow_ (type, expr) 1115 tree type, expr; 1116 { 1117 register tree e = expr; 1118 register enum tree_code code = TREE_CODE (type); 1119 1120 if (type == TREE_TYPE (e) 1121 || TREE_CODE (e) == ERROR_MARK) 1122 return e; 1123 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e))) 1124 return fold (build1 (NOP_EXPR, type, e)); 1125 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK 1126 || code == ERROR_MARK) 1127 return error_mark_node; 1128 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE) 1129 { 1130 assert ("void value not ignored as it ought to be" == NULL); 1131 return error_mark_node; 1132 } 1133 assert (code != VOID_TYPE); 1134 if ((code != RECORD_TYPE) 1135 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE)) 1136 assert ("converting COMPLEX to REAL" == NULL); 1137 assert (code != ENUMERAL_TYPE); 1138 if (code == INTEGER_TYPE) 1139 { 1140 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE 1141 && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e))) 1142 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE 1143 && (TYPE_PRECISION (type) 1144 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e)))))); 1145 return fold (convert_to_integer (type, e)); 1146 } 1147 if (code == POINTER_TYPE) 1148 { 1149 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE); 1150 return fold (convert_to_pointer (type, e)); 1151 } 1152 if (code == REAL_TYPE) 1153 { 1154 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE); 1155 assert (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e))); 1156 return fold (convert_to_real (type, e)); 1157 } 1158 if (code == COMPLEX_TYPE) 1159 { 1160 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE); 1161 assert (TYPE_PRECISION (TREE_TYPE (type)) <= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e)))); 1162 return fold (convert_to_complex (type, e)); 1163 } 1164 if (code == RECORD_TYPE) 1165 { 1166 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE); 1167 /* Check that at least the first field name agrees. */ 1168 assert (DECL_NAME (TYPE_FIELDS (type)) 1169 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e)))); 1170 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type))) 1171 <= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e))))); 1172 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type))) 1173 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e))))) 1174 return e; 1175 return fold (ffecom_convert_to_complex_ (type, e)); 1176 } 1177 1178 assert ("conversion to non-scalar type requested" == NULL); 1179 return error_mark_node; 1180 } 1181 1182 /* Like gcc's convert(), but crashes if narrowing might happen. */ 1183 1184 static tree 1185 ffecom_convert_widen_ (type, expr) 1186 tree type, expr; 1187 { 1188 register tree e = expr; 1189 register enum tree_code code = TREE_CODE (type); 1190 1191 if (type == TREE_TYPE (e) 1192 || TREE_CODE (e) == ERROR_MARK) 1193 return e; 1194 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e))) 1195 return fold (build1 (NOP_EXPR, type, e)); 1196 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK 1197 || code == ERROR_MARK) 1198 return error_mark_node; 1199 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE) 1200 { 1201 assert ("void value not ignored as it ought to be" == NULL); 1202 return error_mark_node; 1203 } 1204 assert (code != VOID_TYPE); 1205 if ((code != RECORD_TYPE) 1206 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE)) 1207 assert ("narrowing COMPLEX to REAL" == NULL); 1208 assert (code != ENUMERAL_TYPE); 1209 if (code == INTEGER_TYPE) 1210 { 1211 assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE 1212 && TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e))) 1213 || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE 1214 && (TYPE_PRECISION (type) 1215 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e)))))); 1216 return fold (convert_to_integer (type, e)); 1217 } 1218 if (code == POINTER_TYPE) 1219 { 1220 assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE); 1221 return fold (convert_to_pointer (type, e)); 1222 } 1223 if (code == REAL_TYPE) 1224 { 1225 assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE); 1226 assert (TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e))); 1227 return fold (convert_to_real (type, e)); 1228 } 1229 if (code == COMPLEX_TYPE) 1230 { 1231 assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE); 1232 assert (TYPE_PRECISION (TREE_TYPE (type)) >= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e)))); 1233 return fold (convert_to_complex (type, e)); 1234 } 1235 if (code == RECORD_TYPE) 1236 { 1237 assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE); 1238 /* Check that at least the first field name agrees. */ 1239 assert (DECL_NAME (TYPE_FIELDS (type)) 1240 == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e)))); 1241 assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type))) 1242 >= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e))))); 1243 if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type))) 1244 == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e))))) 1245 return e; 1246 return fold (ffecom_convert_to_complex_ (type, e)); 1247 } 1248 1249 assert ("conversion to non-scalar type requested" == NULL); 1250 return error_mark_node; 1251 } 1252 1253 /* Handles making a COMPLEX type, either the standard 1254 (but buggy?) gbe way, or the safer (but less elegant?) 1255 f2c way. */ 1256 1257 static tree 1258 ffecom_make_complex_type_ (tree subtype) 1259 { 1260 tree type; 1261 tree realfield; 1262 tree imagfield; 1263 1264 if (ffe_is_emulate_complex ()) 1265 { 1266 type = make_node (RECORD_TYPE); 1267 realfield = ffecom_decl_field (type, NULL_TREE, "r", subtype); 1268 imagfield = ffecom_decl_field (type, realfield, "i", subtype); 1269 TYPE_FIELDS (type) = realfield; 1270 layout_type (type); 1271 } 1272 else 1273 { 1274 type = make_node (COMPLEX_TYPE); 1275 TREE_TYPE (type) = subtype; 1276 layout_type (type); 1277 } 1278 1279 return type; 1280 } 1281 1282 /* Chooses either the gbe or the f2c way to build a 1283 complex constant. */ 1284 1285 static tree 1286 ffecom_build_complex_constant_ (tree type, tree realpart, tree imagpart) 1287 { 1288 tree bothparts; 1289 1290 if (ffe_is_emulate_complex ()) 1291 { 1292 bothparts = build_tree_list (TYPE_FIELDS (type), realpart); 1293 TREE_CHAIN (bothparts) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), imagpart); 1294 bothparts = build (CONSTRUCTOR, type, NULL_TREE, bothparts); 1295 } 1296 else 1297 { 1298 bothparts = build_complex (type, realpart, imagpart); 1299 } 1300 1301 return bothparts; 1302 } 1303 1304 static tree 1305 ffecom_arglist_expr_ (const char *c, ffebld expr) 1306 { 1307 tree list; 1308 tree *plist = &list; 1309 tree trail = NULL_TREE; /* Append char length args here. */ 1310 tree *ptrail = &trail; 1311 tree length; 1312 ffebld exprh; 1313 tree item; 1314 bool ptr = FALSE; 1315 tree wanted = NULL_TREE; 1316 static const char zed[] = "0"; 1317 1318 if (c == NULL) 1319 c = &zed[0]; 1320 1321 while (expr != NULL) 1322 { 1323 if (*c != '\0') 1324 { 1325 ptr = FALSE; 1326 if (*c == '&') 1327 { 1328 ptr = TRUE; 1329 ++c; 1330 } 1331 switch (*(c++)) 1332 { 1333 case '\0': 1334 ptr = TRUE; 1335 wanted = NULL_TREE; 1336 break; 1337 1338 case 'a': 1339 assert (ptr); 1340 wanted = NULL_TREE; 1341 break; 1342 1343 case 'c': 1344 wanted = ffecom_f2c_complex_type_node; 1345 break; 1346 1347 case 'd': 1348 wanted = ffecom_f2c_doublereal_type_node; 1349 break; 1350 1351 case 'e': 1352 wanted = ffecom_f2c_doublecomplex_type_node; 1353 break; 1354 1355 case 'f': 1356 wanted = ffecom_f2c_real_type_node; 1357 break; 1358 1359 case 'i': 1360 wanted = ffecom_f2c_integer_type_node; 1361 break; 1362 1363 case 'j': 1364 wanted = ffecom_f2c_longint_type_node; 1365 break; 1366 1367 default: 1368 assert ("bad argstring code" == NULL); 1369 wanted = NULL_TREE; 1370 break; 1371 } 1372 } 1373 1374 exprh = ffebld_head (expr); 1375 if (exprh == NULL) 1376 wanted = NULL_TREE; 1377 1378 if ((wanted == NULL_TREE) 1379 || (ptr 1380 && (TYPE_MODE 1381 (ffecom_tree_type[ffeinfo_basictype (ffebld_info (exprh))] 1382 [ffeinfo_kindtype (ffebld_info (exprh))]) 1383 == TYPE_MODE (wanted)))) 1384 *plist 1385 = build_tree_list (NULL_TREE, 1386 ffecom_arg_ptr_to_expr (exprh, 1387 &length)); 1388 else 1389 { 1390 item = ffecom_arg_expr (exprh, &length); 1391 item = ffecom_convert_widen_ (wanted, item); 1392 if (ptr) 1393 { 1394 item = ffecom_1 (ADDR_EXPR, 1395 build_pointer_type (TREE_TYPE (item)), 1396 item); 1397 } 1398 *plist 1399 = build_tree_list (NULL_TREE, 1400 item); 1401 } 1402 1403 plist = &TREE_CHAIN (*plist); 1404 expr = ffebld_trail (expr); 1405 if (length != NULL_TREE) 1406 { 1407 *ptrail = build_tree_list (NULL_TREE, length); 1408 ptrail = &TREE_CHAIN (*ptrail); 1409 } 1410 } 1411 1412 /* We've run out of args in the call; if the implementation expects 1413 more, supply null pointers for them, which the implementation can 1414 check to see if an arg was omitted. */ 1415 1416 while (*c != '\0' && *c != '0') 1417 { 1418 if (*c == '&') 1419 ++c; 1420 else 1421 assert ("missing arg to run-time routine!" == NULL); 1422 1423 switch (*(c++)) 1424 { 1425 case '\0': 1426 case 'a': 1427 case 'c': 1428 case 'd': 1429 case 'e': 1430 case 'f': 1431 case 'i': 1432 case 'j': 1433 break; 1434 1435 default: 1436 assert ("bad arg string code" == NULL); 1437 break; 1438 } 1439 *plist 1440 = build_tree_list (NULL_TREE, 1441 null_pointer_node); 1442 plist = &TREE_CHAIN (*plist); 1443 } 1444 1445 *plist = trail; 1446 1447 return list; 1448 } 1449 1450 static tree 1451 ffecom_widest_expr_type_ (ffebld list) 1452 { 1453 ffebld item; 1454 ffebld widest = NULL; 1455 ffetype type; 1456 ffetype widest_type = NULL; 1457 tree t; 1458 1459 for (; list != NULL; list = ffebld_trail (list)) 1460 { 1461 item = ffebld_head (list); 1462 if (item == NULL) 1463 continue; 1464 if ((widest != NULL) 1465 && (ffeinfo_basictype (ffebld_info (item)) 1466 != ffeinfo_basictype (ffebld_info (widest)))) 1467 continue; 1468 type = ffeinfo_type (ffeinfo_basictype (ffebld_info (item)), 1469 ffeinfo_kindtype (ffebld_info (item))); 1470 if ((widest == FFEINFO_kindtypeNONE) 1471 || (ffetype_size (type) 1472 > ffetype_size (widest_type))) 1473 { 1474 widest = item; 1475 widest_type = type; 1476 } 1477 } 1478 1479 assert (widest != NULL); 1480 t = ffecom_tree_type[ffeinfo_basictype (ffebld_info (widest))] 1481 [ffeinfo_kindtype (ffebld_info (widest))]; 1482 assert (t != NULL_TREE); 1483 return t; 1484 } 1485 1486 /* Check whether a partial overlap between two expressions is possible. 1487 1488 Can *starting* to write a portion of expr1 change the value 1489 computed (perhaps already, *partially*) by expr2? 1490 1491 Currently, this is a concern only for a COMPLEX expr1. But if it 1492 isn't in COMMON or local EQUIVALENCE, since we don't support 1493 aliasing of arguments, it isn't a concern. */ 1494 1495 static bool 1496 ffecom_possible_partial_overlap_ (ffebld expr1, ffebld expr2 ATTRIBUTE_UNUSED) 1497 { 1498 ffesymbol sym; 1499 ffestorag st; 1500 1501 switch (ffebld_op (expr1)) 1502 { 1503 case FFEBLD_opSYMTER: 1504 sym = ffebld_symter (expr1); 1505 break; 1506 1507 case FFEBLD_opARRAYREF: 1508 if (ffebld_op (ffebld_left (expr1)) != FFEBLD_opSYMTER) 1509 return FALSE; 1510 sym = ffebld_symter (ffebld_left (expr1)); 1511 break; 1512 1513 default: 1514 return FALSE; 1515 } 1516 1517 if (ffesymbol_where (sym) != FFEINFO_whereCOMMON 1518 && (ffesymbol_where (sym) != FFEINFO_whereLOCAL 1519 || ! (st = ffesymbol_storage (sym)) 1520 || ! ffestorag_parent (st))) 1521 return FALSE; 1522 1523 /* It's in COMMON or local EQUIVALENCE. */ 1524 1525 return TRUE; 1526 } 1527 1528 /* Check whether dest and source might overlap. ffebld versions of these 1529 might or might not be passed, will be NULL if not. 1530 1531 The test is really whether source_tree is modifiable and, if modified, 1532 might overlap destination such that the value(s) in the destination might 1533 change before it is finally modified. dest_* are the canonized 1534 destination itself. */ 1535 1536 static bool 1537 ffecom_overlap_ (tree dest_decl, tree dest_offset, tree dest_size, 1538 tree source_tree, ffebld source UNUSED, 1539 bool scalar_arg) 1540 { 1541 tree source_decl; 1542 tree source_offset; 1543 tree source_size; 1544 tree t; 1545 1546 if (source_tree == NULL_TREE) 1547 return FALSE; 1548 1549 switch (TREE_CODE (source_tree)) 1550 { 1551 case ERROR_MARK: 1552 case IDENTIFIER_NODE: 1553 case INTEGER_CST: 1554 case REAL_CST: 1555 case COMPLEX_CST: 1556 case STRING_CST: 1557 case CONST_DECL: 1558 case VAR_DECL: 1559 case RESULT_DECL: 1560 case FIELD_DECL: 1561 case MINUS_EXPR: 1562 case MULT_EXPR: 1563 case TRUNC_DIV_EXPR: 1564 case CEIL_DIV_EXPR: 1565 case FLOOR_DIV_EXPR: 1566 case ROUND_DIV_EXPR: 1567 case TRUNC_MOD_EXPR: 1568 case CEIL_MOD_EXPR: 1569 case FLOOR_MOD_EXPR: 1570 case ROUND_MOD_EXPR: 1571 case RDIV_EXPR: 1572 case EXACT_DIV_EXPR: 1573 case FIX_TRUNC_EXPR: 1574 case FIX_CEIL_EXPR: 1575 case FIX_FLOOR_EXPR: 1576 case FIX_ROUND_EXPR: 1577 case FLOAT_EXPR: 1578 case NEGATE_EXPR: 1579 case MIN_EXPR: 1580 case MAX_EXPR: 1581 case ABS_EXPR: 1582 case FFS_EXPR: 1583 case LSHIFT_EXPR: 1584 case RSHIFT_EXPR: 1585 case LROTATE_EXPR: 1586 case RROTATE_EXPR: 1587 case BIT_IOR_EXPR: 1588 case BIT_XOR_EXPR: 1589 case BIT_AND_EXPR: 1590 case BIT_ANDTC_EXPR: 1591 case BIT_NOT_EXPR: 1592 case TRUTH_ANDIF_EXPR: 1593 case TRUTH_ORIF_EXPR: 1594 case TRUTH_AND_EXPR: 1595 case TRUTH_OR_EXPR: 1596 case TRUTH_XOR_EXPR: 1597 case TRUTH_NOT_EXPR: 1598 case LT_EXPR: 1599 case LE_EXPR: 1600 case GT_EXPR: 1601 case GE_EXPR: 1602 case EQ_EXPR: 1603 case NE_EXPR: 1604 case COMPLEX_EXPR: 1605 case CONJ_EXPR: 1606 case REALPART_EXPR: 1607 case IMAGPART_EXPR: 1608 case LABEL_EXPR: 1609 case COMPONENT_REF: 1610 return FALSE; 1611 1612 case COMPOUND_EXPR: 1613 return ffecom_overlap_ (dest_decl, dest_offset, dest_size, 1614 TREE_OPERAND (source_tree, 1), NULL, 1615 scalar_arg); 1616 1617 case MODIFY_EXPR: 1618 return ffecom_overlap_ (dest_decl, dest_offset, dest_size, 1619 TREE_OPERAND (source_tree, 0), NULL, 1620 scalar_arg); 1621 1622 case CONVERT_EXPR: 1623 case NOP_EXPR: 1624 case NON_LVALUE_EXPR: 1625 case PLUS_EXPR: 1626 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE) 1627 return TRUE; 1628 1629 ffecom_tree_canonize_ptr_ (&source_decl, &source_offset, 1630 source_tree); 1631 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree))); 1632 break; 1633 1634 case COND_EXPR: 1635 return 1636 ffecom_overlap_ (dest_decl, dest_offset, dest_size, 1637 TREE_OPERAND (source_tree, 1), NULL, 1638 scalar_arg) 1639 || ffecom_overlap_ (dest_decl, dest_offset, dest_size, 1640 TREE_OPERAND (source_tree, 2), NULL, 1641 scalar_arg); 1642 1643 1644 case ADDR_EXPR: 1645 ffecom_tree_canonize_ref_ (&source_decl, &source_offset, 1646 &source_size, 1647 TREE_OPERAND (source_tree, 0)); 1648 break; 1649 1650 case PARM_DECL: 1651 if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE) 1652 return TRUE; 1653 1654 source_decl = source_tree; 1655 source_offset = bitsize_zero_node; 1656 source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree))); 1657 break; 1658 1659 case SAVE_EXPR: 1660 case REFERENCE_EXPR: 1661 case PREDECREMENT_EXPR: 1662 case PREINCREMENT_EXPR: 1663 case POSTDECREMENT_EXPR: 1664 case POSTINCREMENT_EXPR: 1665 case INDIRECT_REF: 1666 case ARRAY_REF: 1667 case CALL_EXPR: 1668 default: 1669 return TRUE; 1670 } 1671 1672 /* Come here when source_decl, source_offset, and source_size filled 1673 in appropriately. */ 1674 1675 if (source_decl == NULL_TREE) 1676 return FALSE; /* No decl involved, so no overlap. */ 1677 1678 if (source_decl != dest_decl) 1679 return FALSE; /* Different decl, no overlap. */ 1680 1681 if (TREE_CODE (dest_size) == ERROR_MARK) 1682 return TRUE; /* Assignment into entire assumed-size 1683 array? Shouldn't happen.... */ 1684 1685 t = ffecom_2 (LE_EXPR, integer_type_node, 1686 ffecom_2 (PLUS_EXPR, TREE_TYPE (dest_offset), 1687 dest_offset, 1688 convert (TREE_TYPE (dest_offset), 1689 dest_size)), 1690 convert (TREE_TYPE (dest_offset), 1691 source_offset)); 1692 1693 if (integer_onep (t)) 1694 return FALSE; /* Destination precedes source. */ 1695 1696 if (!scalar_arg 1697 || (source_size == NULL_TREE) 1698 || (TREE_CODE (source_size) == ERROR_MARK) 1699 || integer_zerop (source_size)) 1700 return TRUE; /* No way to tell if dest follows source. */ 1701 1702 t = ffecom_2 (LE_EXPR, integer_type_node, 1703 ffecom_2 (PLUS_EXPR, TREE_TYPE (source_offset), 1704 source_offset, 1705 convert (TREE_TYPE (source_offset), 1706 source_size)), 1707 convert (TREE_TYPE (source_offset), 1708 dest_offset)); 1709 1710 if (integer_onep (t)) 1711 return FALSE; /* Destination follows source. */ 1712 1713 return TRUE; /* Destination and source overlap. */ 1714 } 1715 1716 /* Check whether dest might overlap any of a list of arguments or is 1717 in a COMMON area the callee might know about (and thus modify). */ 1718 1719 static bool 1720 ffecom_args_overlapping_ (tree dest_tree, ffebld dest UNUSED, 1721 tree args, tree callee_commons, 1722 bool scalar_args) 1723 { 1724 tree arg; 1725 tree dest_decl; 1726 tree dest_offset; 1727 tree dest_size; 1728 1729 ffecom_tree_canonize_ref_ (&dest_decl, &dest_offset, &dest_size, 1730 dest_tree); 1731 1732 if (dest_decl == NULL_TREE) 1733 return FALSE; /* Seems unlikely! */ 1734 1735 /* If the decl cannot be determined reliably, or if its in COMMON 1736 and the callee isn't known to not futz with COMMON via other 1737 means, overlap might happen. */ 1738 1739 if ((TREE_CODE (dest_decl) == ERROR_MARK) 1740 || ((callee_commons != NULL_TREE) 1741 && TREE_PUBLIC (dest_decl))) 1742 return TRUE; 1743 1744 for (; args != NULL_TREE; args = TREE_CHAIN (args)) 1745 { 1746 if (((arg = TREE_VALUE (args)) != NULL_TREE) 1747 && ffecom_overlap_ (dest_decl, dest_offset, dest_size, 1748 arg, NULL, scalar_args)) 1749 return TRUE; 1750 } 1751 1752 return FALSE; 1753 } 1754 1755 /* Build a string for a variable name as used by NAMELIST. This means that 1756 if we're using the f2c library, we build an uppercase string, since 1757 f2c does this. */ 1758 1759 static tree 1760 ffecom_build_f2c_string_ (int i, const char *s) 1761 { 1762 if (!ffe_is_f2c_library ()) 1763 return build_string (i, s); 1764 1765 { 1766 char *tmp; 1767 const char *p; 1768 char *q; 1769 char space[34]; 1770 tree t; 1771 1772 if (((size_t) i) > ARRAY_SIZE (space)) 1773 tmp = malloc_new_ks (malloc_pool_image (), "f2c_string", i); 1774 else 1775 tmp = &space[0]; 1776 1777 for (p = s, q = tmp; *p != '\0'; ++p, ++q) 1778 *q = TOUPPER (*p); 1779 *q = '\0'; 1780 1781 t = build_string (i, tmp); 1782 1783 if (((size_t) i) > ARRAY_SIZE (space)) 1784 malloc_kill_ks (malloc_pool_image (), tmp, i); 1785 1786 return t; 1787 } 1788 } 1789 1790 /* Returns CALL_EXPR or equivalent with given type (pass NULL_TREE for 1791 type to just get whatever the function returns), handling the 1792 f2c value-returning convention, if required, by prepending 1793 to the arglist a pointer to a temporary to receive the return value. */ 1794 1795 static tree 1796 ffecom_call_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex, 1797 tree type, tree args, tree dest_tree, 1798 ffebld dest, bool *dest_used, tree callee_commons, 1799 bool scalar_args, tree hook) 1800 { 1801 tree item; 1802 tree tempvar; 1803 1804 if (dest_used != NULL) 1805 *dest_used = FALSE; 1806 1807 if (is_f2c_complex) 1808 { 1809 if ((dest_used == NULL) 1810 || (dest == NULL) 1811 || (ffeinfo_basictype (ffebld_info (dest)) 1812 != FFEINFO_basictypeCOMPLEX) 1813 || (ffeinfo_kindtype (ffebld_info (dest)) != kt) 1814 || ((type != NULL_TREE) && (TREE_TYPE (dest_tree) != type)) 1815 || ffecom_args_overlapping_ (dest_tree, dest, args, 1816 callee_commons, 1817 scalar_args)) 1818 { 1819 tempvar = hook; 1820 assert (tempvar); 1821 } 1822 else 1823 { 1824 *dest_used = TRUE; 1825 tempvar = dest_tree; 1826 type = NULL_TREE; 1827 } 1828 1829 item 1830 = build_tree_list (NULL_TREE, 1831 ffecom_1 (ADDR_EXPR, 1832 build_pointer_type (TREE_TYPE (tempvar)), 1833 tempvar)); 1834 TREE_CHAIN (item) = args; 1835 1836 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn, 1837 item, NULL_TREE); 1838 1839 if (tempvar != dest_tree) 1840 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item, tempvar); 1841 } 1842 else 1843 item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn, 1844 args, NULL_TREE); 1845 1846 if ((type != NULL_TREE) && (TREE_TYPE (item) != type)) 1847 item = ffecom_convert_narrow_ (type, item); 1848 1849 return item; 1850 } 1851 1852 /* Given two arguments, transform them and make a call to the given 1853 function via ffecom_call_. */ 1854 1855 static tree 1856 ffecom_call_binop_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex, 1857 tree type, ffebld left, ffebld right, 1858 tree dest_tree, ffebld dest, bool *dest_used, 1859 tree callee_commons, bool scalar_args, bool ref, tree hook) 1860 { 1861 tree left_tree; 1862 tree right_tree; 1863 tree left_length; 1864 tree right_length; 1865 1866 if (ref) 1867 { 1868 /* Pass arguments by reference. */ 1869 left_tree = ffecom_arg_ptr_to_expr (left, &left_length); 1870 right_tree = ffecom_arg_ptr_to_expr (right, &right_length); 1871 } 1872 else 1873 { 1874 /* Pass arguments by value. */ 1875 left_tree = ffecom_arg_expr (left, &left_length); 1876 right_tree = ffecom_arg_expr (right, &right_length); 1877 } 1878 1879 1880 left_tree = build_tree_list (NULL_TREE, left_tree); 1881 right_tree = build_tree_list (NULL_TREE, right_tree); 1882 TREE_CHAIN (left_tree) = right_tree; 1883 1884 if (left_length != NULL_TREE) 1885 { 1886 left_length = build_tree_list (NULL_TREE, left_length); 1887 TREE_CHAIN (right_tree) = left_length; 1888 } 1889 1890 if (right_length != NULL_TREE) 1891 { 1892 right_length = build_tree_list (NULL_TREE, right_length); 1893 if (left_length != NULL_TREE) 1894 TREE_CHAIN (left_length) = right_length; 1895 else 1896 TREE_CHAIN (right_tree) = right_length; 1897 } 1898 1899 return ffecom_call_ (fn, kt, is_f2c_complex, type, left_tree, 1900 dest_tree, dest, dest_used, callee_commons, 1901 scalar_args, hook); 1902 } 1903 1904 /* Return ptr/length args for char subexpression 1905 1906 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF 1907 subexpressions by constructing the appropriate trees for the ptr-to- 1908 character-text and length-of-character-text arguments in a calling 1909 sequence. 1910 1911 Note that if with_null is TRUE, and the expression is an opCONTER, 1912 a null byte is appended to the string. */ 1913 1914 static void 1915 ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null) 1916 { 1917 tree item; 1918 tree high; 1919 ffetargetCharacter1 val; 1920 ffetargetCharacterSize newlen; 1921 1922 switch (ffebld_op (expr)) 1923 { 1924 case FFEBLD_opCONTER: 1925 val = ffebld_constant_character1 (ffebld_conter (expr)); 1926 newlen = ffetarget_length_character1 (val); 1927 if (with_null) 1928 { 1929 /* Begin FFETARGET-NULL-KLUDGE. */ 1930 if (newlen != 0) 1931 ++newlen; 1932 } 1933 *length = build_int_2 (newlen, 0); 1934 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node; 1935 high = build_int_2 (newlen, 0); 1936 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node; 1937 item = build_string (newlen, 1938 ffetarget_text_character1 (val)); 1939 /* End FFETARGET-NULL-KLUDGE. */ 1940 TREE_TYPE (item) 1941 = build_type_variant 1942 (build_array_type 1943 (char_type_node, 1944 build_range_type 1945 (ffecom_f2c_ftnlen_type_node, 1946 ffecom_f2c_ftnlen_one_node, 1947 high)), 1948 1, 0); 1949 TREE_CONSTANT (item) = 1; 1950 TREE_STATIC (item) = 1; 1951 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)), 1952 item); 1953 break; 1954 1955 case FFEBLD_opSYMTER: 1956 { 1957 ffesymbol s = ffebld_symter (expr); 1958 1959 item = ffesymbol_hook (s).decl_tree; 1960 if (item == NULL_TREE) 1961 { 1962 s = ffecom_sym_transform_ (s); 1963 item = ffesymbol_hook (s).decl_tree; 1964 } 1965 if (ffesymbol_kind (s) == FFEINFO_kindENTITY) 1966 { 1967 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE) 1968 *length = ffesymbol_hook (s).length_tree; 1969 else 1970 { 1971 *length = build_int_2 (ffesymbol_size (s), 0); 1972 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node; 1973 } 1974 } 1975 else if (item == error_mark_node) 1976 *length = error_mark_node; 1977 else 1978 /* FFEINFO_kindFUNCTION. */ 1979 *length = NULL_TREE; 1980 if (!ffesymbol_hook (s).addr 1981 && (item != error_mark_node)) 1982 item = ffecom_1 (ADDR_EXPR, 1983 build_pointer_type (TREE_TYPE (item)), 1984 item); 1985 } 1986 break; 1987 1988 case FFEBLD_opARRAYREF: 1989 { 1990 ffecom_char_args_ (&item, length, ffebld_left (expr)); 1991 1992 if (item == error_mark_node || *length == error_mark_node) 1993 { 1994 item = *length = error_mark_node; 1995 break; 1996 } 1997 1998 item = ffecom_arrayref_ (item, expr, 1); 1999 } 2000 break; 2001 2002 case FFEBLD_opSUBSTR: 2003 { 2004 ffebld start; 2005 ffebld end; 2006 ffebld thing = ffebld_right (expr); 2007 tree start_tree; 2008 tree end_tree; 2009 const char *char_name; 2010 ffebld left_symter; 2011 tree array; 2012 2013 assert (ffebld_op (thing) == FFEBLD_opITEM); 2014 start = ffebld_head (thing); 2015 thing = ffebld_trail (thing); 2016 assert (ffebld_trail (thing) == NULL); 2017 end = ffebld_head (thing); 2018 2019 /* Determine name for pretty-printing range-check errors. */ 2020 for (left_symter = ffebld_left (expr); 2021 left_symter && ffebld_op (left_symter) == FFEBLD_opARRAYREF; 2022 left_symter = ffebld_left (left_symter)) 2023 ; 2024 if (ffebld_op (left_symter) == FFEBLD_opSYMTER) 2025 char_name = ffesymbol_text (ffebld_symter (left_symter)); 2026 else 2027 char_name = "[expr?]"; 2028 2029 ffecom_char_args_ (&item, length, ffebld_left (expr)); 2030 2031 if (item == error_mark_node || *length == error_mark_node) 2032 { 2033 item = *length = error_mark_node; 2034 break; 2035 } 2036 2037 array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))); 2038 2039 /* ~~~~Handle INTEGER*8 start/end, a la FFEBLD_opARRAYREF. */ 2040 2041 if (start == NULL) 2042 { 2043 if (end == NULL) 2044 ; 2045 else 2046 { 2047 end_tree = ffecom_expr (end); 2048 if (flag_bounds_check) 2049 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0, 2050 char_name, NULL_TREE); 2051 end_tree = convert (ffecom_f2c_ftnlen_type_node, 2052 end_tree); 2053 2054 if (end_tree == error_mark_node) 2055 { 2056 item = *length = error_mark_node; 2057 break; 2058 } 2059 2060 *length = end_tree; 2061 } 2062 } 2063 else 2064 { 2065 start_tree = ffecom_expr (start); 2066 if (flag_bounds_check) 2067 start_tree = ffecom_subscript_check_ (array, start_tree, 0, 0, 2068 char_name, NULL_TREE); 2069 start_tree = convert (ffecom_f2c_ftnlen_type_node, 2070 start_tree); 2071 2072 if (start_tree == error_mark_node) 2073 { 2074 item = *length = error_mark_node; 2075 break; 2076 } 2077 2078 start_tree = ffecom_save_tree (start_tree); 2079 2080 item = ffecom_2 (PLUS_EXPR, TREE_TYPE (item), 2081 item, 2082 ffecom_2 (MINUS_EXPR, 2083 TREE_TYPE (start_tree), 2084 start_tree, 2085 ffecom_f2c_ftnlen_one_node)); 2086 2087 if (end == NULL) 2088 { 2089 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node, 2090 ffecom_f2c_ftnlen_one_node, 2091 ffecom_2 (MINUS_EXPR, 2092 ffecom_f2c_ftnlen_type_node, 2093 *length, 2094 start_tree)); 2095 } 2096 else 2097 { 2098 end_tree = ffecom_expr (end); 2099 if (flag_bounds_check) 2100 end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0, 2101 char_name, NULL_TREE); 2102 end_tree = convert (ffecom_f2c_ftnlen_type_node, 2103 end_tree); 2104 2105 if (end_tree == error_mark_node) 2106 { 2107 item = *length = error_mark_node; 2108 break; 2109 } 2110 2111 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node, 2112 ffecom_f2c_ftnlen_one_node, 2113 ffecom_2 (MINUS_EXPR, 2114 ffecom_f2c_ftnlen_type_node, 2115 end_tree, start_tree)); 2116 } 2117 } 2118 } 2119 break; 2120 2121 case FFEBLD_opFUNCREF: 2122 { 2123 ffesymbol s = ffebld_symter (ffebld_left (expr)); 2124 tree tempvar; 2125 tree args; 2126 ffetargetCharacterSize size = ffeinfo_size (ffebld_info (expr)); 2127 ffecomGfrt ix; 2128 2129 if (size == FFETARGET_charactersizeNONE) 2130 /* ~~Kludge alert! This should someday be fixed. */ 2131 size = 24; 2132 2133 *length = build_int_2 (size, 0); 2134 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node; 2135 2136 if (ffeinfo_where (ffebld_info (ffebld_left (expr))) 2137 == FFEINFO_whereINTRINSIC) 2138 { 2139 if (size == 1) 2140 { 2141 /* Invocation of an intrinsic returning CHARACTER*1. */ 2142 item = ffecom_expr_intrinsic_ (expr, NULL_TREE, 2143 NULL, NULL); 2144 break; 2145 } 2146 ix = ffeintrin_gfrt_direct (ffebld_symter_implementation (ffebld_left (expr))); 2147 assert (ix != FFECOM_gfrt); 2148 item = ffecom_gfrt_tree_ (ix); 2149 } 2150 else 2151 { 2152 ix = FFECOM_gfrt; 2153 item = ffesymbol_hook (s).decl_tree; 2154 if (item == NULL_TREE) 2155 { 2156 s = ffecom_sym_transform_ (s); 2157 item = ffesymbol_hook (s).decl_tree; 2158 } 2159 if (item == error_mark_node) 2160 { 2161 item = *length = error_mark_node; 2162 break; 2163 } 2164 2165 if (!ffesymbol_hook (s).addr) 2166 item = ffecom_1_fn (item); 2167 } 2168 tempvar = ffebld_nonter_hook (expr); 2169 assert (tempvar); 2170 tempvar = ffecom_1 (ADDR_EXPR, 2171 build_pointer_type (TREE_TYPE (tempvar)), 2172 tempvar); 2173 2174 args = build_tree_list (NULL_TREE, tempvar); 2175 2176 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT) /* Sfunc args by value. */ 2177 TREE_CHAIN (args) = ffecom_list_expr (ffebld_right (expr)); 2178 else 2179 { 2180 TREE_CHAIN (args) = build_tree_list (NULL_TREE, *length); 2181 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC) 2182 { 2183 TREE_CHAIN (TREE_CHAIN (args)) 2184 = ffecom_arglist_expr_ (ffecom_gfrt_args_ (ix), 2185 ffebld_right (expr)); 2186 } 2187 else 2188 { 2189 TREE_CHAIN (TREE_CHAIN (args)) 2190 = ffecom_list_ptr_to_expr (ffebld_right (expr)); 2191 } 2192 } 2193 2194 item = ffecom_3s (CALL_EXPR, 2195 TREE_TYPE (TREE_TYPE (TREE_TYPE (item))), 2196 item, args, NULL_TREE); 2197 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item, 2198 tempvar); 2199 } 2200 break; 2201 2202 case FFEBLD_opCONVERT: 2203 2204 ffecom_char_args_ (&item, length, ffebld_left (expr)); 2205 2206 if (item == error_mark_node || *length == error_mark_node) 2207 { 2208 item = *length = error_mark_node; 2209 break; 2210 } 2211 2212 if ((ffebld_size_known (ffebld_left (expr)) 2213 == FFETARGET_charactersizeNONE) 2214 || (ffebld_size_known (ffebld_left (expr)) < (ffebld_size (expr)))) 2215 { /* Possible blank-padding needed, copy into 2216 temporary. */ 2217 tree tempvar; 2218 tree args; 2219 tree newlen; 2220 2221 tempvar = ffebld_nonter_hook (expr); 2222 assert (tempvar); 2223 tempvar = ffecom_1 (ADDR_EXPR, 2224 build_pointer_type (TREE_TYPE (tempvar)), 2225 tempvar); 2226 2227 newlen = build_int_2 (ffebld_size (expr), 0); 2228 TREE_TYPE (newlen) = ffecom_f2c_ftnlen_type_node; 2229 2230 args = build_tree_list (NULL_TREE, tempvar); 2231 TREE_CHAIN (args) = build_tree_list (NULL_TREE, item); 2232 TREE_CHAIN (TREE_CHAIN (args)) = build_tree_list (NULL_TREE, newlen); 2233 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (args))) 2234 = build_tree_list (NULL_TREE, *length); 2235 2236 item = ffecom_call_gfrt (FFECOM_gfrtCOPY, args, NULL_TREE); 2237 TREE_SIDE_EFFECTS (item) = 1; 2238 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), fold (item), 2239 tempvar); 2240 *length = newlen; 2241 } 2242 else 2243 { /* Just truncate the length. */ 2244 *length = build_int_2 (ffebld_size (expr), 0); 2245 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node; 2246 } 2247 break; 2248 2249 default: 2250 assert ("bad op for single char arg expr" == NULL); 2251 item = NULL_TREE; 2252 break; 2253 } 2254 2255 *xitem = item; 2256 } 2257 2258 /* Check the size of the type to be sure it doesn't overflow the 2259 "portable" capacities of the compiler back end. `dummy' types 2260 can generally overflow the normal sizes as long as the computations 2261 themselves don't overflow. A particular target of the back end 2262 must still enforce its size requirements, though, and the back 2263 end takes care of this in stor-layout.c. */ 2264 2265 static tree 2266 ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy) 2267 { 2268 if (TREE_CODE (type) == ERROR_MARK) 2269 return type; 2270 2271 if (TYPE_SIZE (type) == NULL_TREE) 2272 return type; 2273 2274 if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) 2275 return type; 2276 2277 /* An array is too large if size is negative or the type_size overflows 2278 or its "upper half" is larger than 3 (which would make the signed 2279 byte size and offset computations overflow). */ 2280 2281 if ((tree_int_cst_sgn (TYPE_SIZE (type)) < 0) 2282 || (!dummy && (TREE_INT_CST_HIGH (TYPE_SIZE (type)) > 3 2283 || TREE_OVERFLOW (TYPE_SIZE (type))))) 2284 { 2285 ffebad_start (FFEBAD_ARRAY_LARGE); 2286 ffebad_string (ffesymbol_text (s)); 2287 ffebad_here (0, ffesymbol_where_line (s), ffesymbol_where_column (s)); 2288 ffebad_finish (); 2289 2290 return error_mark_node; 2291 } 2292 2293 return type; 2294 } 2295 2296 /* Builds a length argument (PARM_DECL). Also wraps type in an array type 2297 where the dimension info is (1:size) where <size> is ffesymbol_size(s) if 2298 known, length_arg if not known (FFETARGET_charactersizeNONE). */ 2299 2300 static tree 2301 ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s) 2302 { 2303 ffetargetCharacterSize sz = ffesymbol_size (s); 2304 tree highval; 2305 tree tlen; 2306 tree type = *xtype; 2307 2308 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT) 2309 tlen = NULL_TREE; /* A statement function, no length passed. */ 2310 else 2311 { 2312 if (ffesymbol_where (s) == FFEINFO_whereDUMMY) 2313 tlen = ffecom_get_invented_identifier ("__g77_length_%s", 2314 ffesymbol_text (s)); 2315 else 2316 tlen = ffecom_get_invented_identifier ("__g77_%s", "length"); 2317 tlen = build_decl (PARM_DECL, tlen, ffecom_f2c_ftnlen_type_node); 2318 DECL_ARTIFICIAL (tlen) = 1; 2319 } 2320 2321 if (sz == FFETARGET_charactersizeNONE) 2322 { 2323 assert (tlen != NULL_TREE); 2324 highval = variable_size (tlen); 2325 } 2326 else 2327 { 2328 highval = build_int_2 (sz, 0); 2329 TREE_TYPE (highval) = ffecom_f2c_ftnlen_type_node; 2330 } 2331 2332 type = build_array_type (type, 2333 build_range_type (ffecom_f2c_ftnlen_type_node, 2334 ffecom_f2c_ftnlen_one_node, 2335 highval)); 2336 2337 *xtype = type; 2338 return tlen; 2339 } 2340 2341 /* ffecom_concat_list_gather_ -- Gather list of concatenated string exprs 2342 2343 ffecomConcatList_ catlist; 2344 ffebld expr; // expr of CHARACTER basictype. 2345 ffetargetCharacterSize max; // max chars to gather or _...NONE if no max 2346 catlist = ffecom_concat_list_gather_(catlist,expr,max); 2347 2348 Scans expr for character subexpressions, updates and returns catlist 2349 accordingly. */ 2350 2351 static ffecomConcatList_ 2352 ffecom_concat_list_gather_ (ffecomConcatList_ catlist, ffebld expr, 2353 ffetargetCharacterSize max) 2354 { 2355 ffetargetCharacterSize sz; 2356 2357 recurse: 2358 2359 if (expr == NULL) 2360 return catlist; 2361 2362 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen >= max)) 2363 return catlist; /* Don't append any more items. */ 2364 2365 switch (ffebld_op (expr)) 2366 { 2367 case FFEBLD_opCONTER: 2368 case FFEBLD_opSYMTER: 2369 case FFEBLD_opARRAYREF: 2370 case FFEBLD_opFUNCREF: 2371 case FFEBLD_opSUBSTR: 2372 case FFEBLD_opCONVERT: /* Callers should strip this off beforehand 2373 if they don't need to preserve it. */ 2374 if (catlist.count == catlist.max) 2375 { /* Make a (larger) list. */ 2376 ffebld *newx; 2377 int newmax; 2378 2379 newmax = (catlist.max == 0) ? 8 : catlist.max * 2; 2380 newx = malloc_new_ks (malloc_pool_image (), "catlist", 2381 newmax * sizeof (newx[0])); 2382 if (catlist.max != 0) 2383 { 2384 memcpy (newx, catlist.exprs, catlist.max * sizeof (newx[0])); 2385 malloc_kill_ks (malloc_pool_image (), catlist.exprs, 2386 catlist.max * sizeof (newx[0])); 2387 } 2388 catlist.max = newmax; 2389 catlist.exprs = newx; 2390 } 2391 if ((sz = ffebld_size_known (expr)) != FFETARGET_charactersizeNONE) 2392 catlist.minlen += sz; 2393 else 2394 ++catlist.minlen; /* Not true for F90; can be 0 length. */ 2395 if ((sz = ffebld_size_max (expr)) == FFETARGET_charactersizeNONE) 2396 catlist.maxlen = sz; 2397 else 2398 catlist.maxlen += sz; 2399 if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen > max)) 2400 { /* This item overlaps (or is beyond) the end 2401 of the destination. */ 2402 switch (ffebld_op (expr)) 2403 { 2404 case FFEBLD_opCONTER: 2405 case FFEBLD_opSYMTER: 2406 case FFEBLD_opARRAYREF: 2407 case FFEBLD_opFUNCREF: 2408 case FFEBLD_opSUBSTR: 2409 /* ~~Do useful truncations here. */ 2410 break; 2411 2412 default: 2413 assert ("op changed or inconsistent switches!" == NULL); 2414 break; 2415 } 2416 } 2417 catlist.exprs[catlist.count++] = expr; 2418 return catlist; 2419 2420 case FFEBLD_opPAREN: 2421 expr = ffebld_left (expr); 2422 goto recurse; /* :::::::::::::::::::: */ 2423 2424 case FFEBLD_opCONCATENATE: 2425 catlist = ffecom_concat_list_gather_ (catlist, ffebld_left (expr), max); 2426 expr = ffebld_right (expr); 2427 goto recurse; /* :::::::::::::::::::: */ 2428 2429 #if 0 /* Breaks passing small actual arg to larger 2430 dummy arg of sfunc */ 2431 case FFEBLD_opCONVERT: 2432 expr = ffebld_left (expr); 2433 { 2434 ffetargetCharacterSize cmax; 2435 2436 cmax = catlist.len + ffebld_size_known (expr); 2437 2438 if ((max == FFETARGET_charactersizeNONE) || (max > cmax)) 2439 max = cmax; 2440 } 2441 goto recurse; /* :::::::::::::::::::: */ 2442 #endif 2443 2444 case FFEBLD_opANY: 2445 return catlist; 2446 2447 default: 2448 assert ("bad op in _gather_" == NULL); 2449 return catlist; 2450 } 2451 } 2452 2453 /* ffecom_concat_list_kill_ -- Kill list of concatenated string exprs 2454 2455 ffecomConcatList_ catlist; 2456 ffecom_concat_list_kill_(catlist); 2457 2458 Anything allocated within the list info is deallocated. */ 2459 2460 static void 2461 ffecom_concat_list_kill_ (ffecomConcatList_ catlist) 2462 { 2463 if (catlist.max != 0) 2464 malloc_kill_ks (malloc_pool_image (), catlist.exprs, 2465 catlist.max * sizeof (catlist.exprs[0])); 2466 } 2467 2468 /* Make list of concatenated string exprs. 2469 2470 Returns a flattened list of concatenated subexpressions given a 2471 tree of such expressions. */ 2472 2473 static ffecomConcatList_ 2474 ffecom_concat_list_new_ (ffebld expr, ffetargetCharacterSize max) 2475 { 2476 ffecomConcatList_ catlist; 2477 2478 catlist.maxlen = catlist.minlen = catlist.max = catlist.count = 0; 2479 return ffecom_concat_list_gather_ (catlist, expr, max); 2480 } 2481 2482 /* Provide some kind of useful info on member of aggregate area, 2483 since current g77/gcc technology does not provide debug info 2484 on these members. */ 2485 2486 static void 2487 ffecom_debug_kludge_ (tree aggr, const char *aggr_type, ffesymbol member, 2488 tree member_type UNUSED, ffetargetOffset offset) 2489 { 2490 tree value; 2491 tree decl; 2492 int len; 2493 char *buff; 2494 char space[120]; 2495 #if 0 2496 tree type_id; 2497 2498 for (type_id = member_type; 2499 TREE_CODE (type_id) != IDENTIFIER_NODE; 2500 ) 2501 { 2502 switch (TREE_CODE (type_id)) 2503 { 2504 case INTEGER_TYPE: 2505 case REAL_TYPE: 2506 type_id = TYPE_NAME (type_id); 2507 break; 2508 2509 case ARRAY_TYPE: 2510 case COMPLEX_TYPE: 2511 type_id = TREE_TYPE (type_id); 2512 break; 2513 2514 default: 2515 assert ("no IDENTIFIER_NODE for type!" == NULL); 2516 type_id = error_mark_node; 2517 break; 2518 } 2519 } 2520 #endif 2521 2522 if (ffecom_transform_only_dummies_ 2523 || !ffe_is_debug_kludge ()) 2524 return; /* Can't do this yet, maybe later. */ 2525 2526 len = 60 2527 + strlen (aggr_type) 2528 + IDENTIFIER_LENGTH (DECL_NAME (aggr)); 2529 #if 0 2530 + IDENTIFIER_LENGTH (type_id); 2531 #endif 2532 2533 if (((size_t) len) >= ARRAY_SIZE (space)) 2534 buff = malloc_new_ks (malloc_pool_image (), "debug_kludge", len + 1); 2535 else 2536 buff = &space[0]; 2537 2538 sprintf (&buff[0], "At (%s) `%s' plus %ld bytes", 2539 aggr_type, 2540 IDENTIFIER_POINTER (DECL_NAME (aggr)), 2541 (long int) offset); 2542 2543 value = build_string (len, buff); 2544 TREE_TYPE (value) 2545 = build_type_variant (build_array_type (char_type_node, 2546 build_range_type 2547 (integer_type_node, 2548 integer_one_node, 2549 build_int_2 (strlen (buff), 0))), 2550 1, 0); 2551 decl = build_decl (VAR_DECL, 2552 ffecom_get_identifier_ (ffesymbol_text (member)), 2553 TREE_TYPE (value)); 2554 TREE_CONSTANT (decl) = 1; 2555 TREE_STATIC (decl) = 1; 2556 DECL_INITIAL (decl) = error_mark_node; 2557 DECL_IN_SYSTEM_HEADER (decl) = 1; /* Don't let -Wunused complain. */ 2558 decl = start_decl (decl, FALSE); 2559 finish_decl (decl, value, FALSE); 2560 2561 if (buff != &space[0]) 2562 malloc_kill_ks (malloc_pool_image (), buff, len + 1); 2563 } 2564 2565 /* ffecom_do_entry_ -- Do compilation of a particular entrypoint 2566 2567 ffesymbol fn; // the SUBROUTINE, FUNCTION, or ENTRY symbol itself 2568 int i; // entry# for this entrypoint (used by master fn) 2569 ffecom_do_entrypoint_(s,i); 2570 2571 Makes a public entry point that calls our private master fn (already 2572 compiled). */ 2573 2574 static void 2575 ffecom_do_entry_ (ffesymbol fn, int entrynum) 2576 { 2577 ffebld item; 2578 tree type; /* Type of function. */ 2579 tree multi_retval; /* Var holding return value (union). */ 2580 tree result; /* Var holding result. */ 2581 ffeinfoBasictype bt; 2582 ffeinfoKindtype kt; 2583 ffeglobal g; 2584 ffeglobalType gt; 2585 bool charfunc; /* All entry points return same type 2586 CHARACTER. */ 2587 bool cmplxfunc; /* Use f2c way of returning COMPLEX. */ 2588 bool multi; /* Master fn has multiple return types. */ 2589 bool altreturning = FALSE; /* This entry point has alternate returns. */ 2590 int old_lineno = lineno; 2591 const char *old_input_filename = input_filename; 2592 2593 input_filename = ffesymbol_where_filename (fn); 2594 lineno = ffesymbol_where_filelinenum (fn); 2595 2596 ffecom_doing_entry_ = TRUE; /* Don't bother with array dimensions. */ 2597 2598 switch (ffecom_primary_entry_kind_) 2599 { 2600 case FFEINFO_kindFUNCTION: 2601 2602 /* Determine actual return type for function. */ 2603 2604 gt = FFEGLOBAL_typeFUNC; 2605 bt = ffesymbol_basictype (fn); 2606 kt = ffesymbol_kindtype (fn); 2607 if (bt == FFEINFO_basictypeNONE) 2608 { 2609 ffeimplic_establish_symbol (fn); 2610 if (ffesymbol_funcresult (fn) != NULL) 2611 ffeimplic_establish_symbol (ffesymbol_funcresult (fn)); 2612 bt = ffesymbol_basictype (fn); 2613 kt = ffesymbol_kindtype (fn); 2614 } 2615 2616 if (bt == FFEINFO_basictypeCHARACTER) 2617 charfunc = TRUE, cmplxfunc = FALSE; 2618 else if ((bt == FFEINFO_basictypeCOMPLEX) 2619 && ffesymbol_is_f2c (fn)) 2620 charfunc = FALSE, cmplxfunc = TRUE; 2621 else 2622 charfunc = cmplxfunc = FALSE; 2623 2624 if (charfunc) 2625 type = ffecom_tree_fun_type_void; 2626 else if (ffesymbol_is_f2c (fn)) 2627 type = ffecom_tree_fun_type[bt][kt]; 2628 else 2629 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE); 2630 2631 if ((type == NULL_TREE) 2632 || (TREE_TYPE (type) == NULL_TREE)) 2633 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */ 2634 2635 multi = (ffecom_master_bt_ == FFEINFO_basictypeNONE); 2636 break; 2637 2638 case FFEINFO_kindSUBROUTINE: 2639 gt = FFEGLOBAL_typeSUBR; 2640 bt = FFEINFO_basictypeNONE; 2641 kt = FFEINFO_kindtypeNONE; 2642 if (ffecom_is_altreturning_) 2643 { /* Am _I_ altreturning? */ 2644 for (item = ffesymbol_dummyargs (fn); 2645 item != NULL; 2646 item = ffebld_trail (item)) 2647 { 2648 if (ffebld_op (ffebld_head (item)) == FFEBLD_opSTAR) 2649 { 2650 altreturning = TRUE; 2651 break; 2652 } 2653 } 2654 if (altreturning) 2655 type = ffecom_tree_subr_type; 2656 else 2657 type = ffecom_tree_fun_type_void; 2658 } 2659 else 2660 type = ffecom_tree_fun_type_void; 2661 charfunc = FALSE; 2662 cmplxfunc = FALSE; 2663 multi = FALSE; 2664 break; 2665 2666 default: 2667 assert ("say what??" == NULL); 2668 /* Fall through. */ 2669 case FFEINFO_kindANY: 2670 gt = FFEGLOBAL_typeANY; 2671 bt = FFEINFO_basictypeNONE; 2672 kt = FFEINFO_kindtypeNONE; 2673 type = error_mark_node; 2674 charfunc = FALSE; 2675 cmplxfunc = FALSE; 2676 multi = FALSE; 2677 break; 2678 } 2679 2680 /* build_decl uses the current lineno and input_filename to set the decl 2681 source info. So, I've putzed with ffestd and ffeste code to update that 2682 source info to point to the appropriate statement just before calling 2683 ffecom_do_entrypoint (which calls this fn). */ 2684 2685 start_function (ffecom_get_external_identifier_ (fn), 2686 type, 2687 0, /* nested/inline */ 2688 1); /* TREE_PUBLIC */ 2689 2690 if (((g = ffesymbol_global (fn)) != NULL) 2691 && ((ffeglobal_type (g) == gt) 2692 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))) 2693 { 2694 ffeglobal_set_hook (g, current_function_decl); 2695 } 2696 2697 /* Reset args in master arg list so they get retransitioned. */ 2698 2699 for (item = ffecom_master_arglist_; 2700 item != NULL; 2701 item = ffebld_trail (item)) 2702 { 2703 ffebld arg; 2704 ffesymbol s; 2705 2706 arg = ffebld_head (item); 2707 if (ffebld_op (arg) != FFEBLD_opSYMTER) 2708 continue; /* Alternate return or some such thing. */ 2709 s = ffebld_symter (arg); 2710 ffesymbol_hook (s).decl_tree = NULL_TREE; 2711 ffesymbol_hook (s).length_tree = NULL_TREE; 2712 } 2713 2714 /* Build dummy arg list for this entry point. */ 2715 2716 if (charfunc || cmplxfunc) 2717 { /* Prepend arg for where result goes. */ 2718 tree type; 2719 tree length; 2720 2721 if (charfunc) 2722 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt]; 2723 else 2724 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt]; 2725 2726 result = ffecom_get_invented_identifier ("__g77_%s", "result"); 2727 2728 /* Make length arg _and_ enhance type info for CHAR arg itself. */ 2729 2730 if (charfunc) 2731 length = ffecom_char_enhance_arg_ (&type, fn); 2732 else 2733 length = NULL_TREE; /* Not ref'd if !charfunc. */ 2734 2735 type = build_pointer_type (type); 2736 result = build_decl (PARM_DECL, result, type); 2737 2738 push_parm_decl (result); 2739 ffecom_func_result_ = result; 2740 2741 if (charfunc) 2742 { 2743 push_parm_decl (length); 2744 ffecom_func_length_ = length; 2745 } 2746 } 2747 else 2748 result = DECL_RESULT (current_function_decl); 2749 2750 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (fn), FALSE); 2751 2752 store_parm_decls (0); 2753 2754 ffecom_start_compstmt (); 2755 /* Disallow temp vars at this level. */ 2756 current_binding_level->prep_state = 2; 2757 2758 /* Make local var to hold return type for multi-type master fn. */ 2759 2760 if (multi) 2761 { 2762 multi_retval = ffecom_get_invented_identifier ("__g77_%s", 2763 "multi_retval"); 2764 multi_retval = build_decl (VAR_DECL, multi_retval, 2765 ffecom_multi_type_node_); 2766 multi_retval = start_decl (multi_retval, FALSE); 2767 finish_decl (multi_retval, NULL_TREE, FALSE); 2768 } 2769 else 2770 multi_retval = NULL_TREE; /* Not actually ref'd if !multi. */ 2771 2772 /* Here we emit the actual code for the entry point. */ 2773 2774 { 2775 ffebld list; 2776 ffebld arg; 2777 ffesymbol s; 2778 tree arglist = NULL_TREE; 2779 tree *plist = &arglist; 2780 tree prepend; 2781 tree call; 2782 tree actarg; 2783 tree master_fn; 2784 2785 /* Prepare actual arg list based on master arg list. */ 2786 2787 for (list = ffecom_master_arglist_; 2788 list != NULL; 2789 list = ffebld_trail (list)) 2790 { 2791 arg = ffebld_head (list); 2792 if (ffebld_op (arg) != FFEBLD_opSYMTER) 2793 continue; 2794 s = ffebld_symter (arg); 2795 if (ffesymbol_hook (s).decl_tree == NULL_TREE 2796 || ffesymbol_hook (s).decl_tree == error_mark_node) 2797 actarg = null_pointer_node; /* We don't have this arg. */ 2798 else 2799 actarg = ffesymbol_hook (s).decl_tree; 2800 *plist = build_tree_list (NULL_TREE, actarg); 2801 plist = &TREE_CHAIN (*plist); 2802 } 2803 2804 /* This code appends the length arguments for character 2805 variables/arrays. */ 2806 2807 for (list = ffecom_master_arglist_; 2808 list != NULL; 2809 list = ffebld_trail (list)) 2810 { 2811 arg = ffebld_head (list); 2812 if (ffebld_op (arg) != FFEBLD_opSYMTER) 2813 continue; 2814 s = ffebld_symter (arg); 2815 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER) 2816 continue; /* Only looking for CHARACTER arguments. */ 2817 if (ffesymbol_kind (s) != FFEINFO_kindENTITY) 2818 continue; /* Only looking for variables and arrays. */ 2819 if (ffesymbol_hook (s).length_tree == NULL_TREE 2820 || ffesymbol_hook (s).length_tree == error_mark_node) 2821 actarg = ffecom_f2c_ftnlen_zero_node; /* We don't have this arg. */ 2822 else 2823 actarg = ffesymbol_hook (s).length_tree; 2824 *plist = build_tree_list (NULL_TREE, actarg); 2825 plist = &TREE_CHAIN (*plist); 2826 } 2827 2828 /* Prepend character-value return info to actual arg list. */ 2829 2830 if (charfunc) 2831 { 2832 prepend = build_tree_list (NULL_TREE, ffecom_func_result_); 2833 TREE_CHAIN (prepend) 2834 = build_tree_list (NULL_TREE, ffecom_func_length_); 2835 TREE_CHAIN (TREE_CHAIN (prepend)) = arglist; 2836 arglist = prepend; 2837 } 2838 2839 /* Prepend multi-type return value to actual arg list. */ 2840 2841 if (multi) 2842 { 2843 prepend 2844 = build_tree_list (NULL_TREE, 2845 ffecom_1 (ADDR_EXPR, 2846 build_pointer_type (TREE_TYPE (multi_retval)), 2847 multi_retval)); 2848 TREE_CHAIN (prepend) = arglist; 2849 arglist = prepend; 2850 } 2851 2852 /* Prepend my entry-point number to the actual arg list. */ 2853 2854 prepend = build_tree_list (NULL_TREE, build_int_2 (entrynum, 0)); 2855 TREE_CHAIN (prepend) = arglist; 2856 arglist = prepend; 2857 2858 /* Build the call to the master function. */ 2859 2860 master_fn = ffecom_1_fn (ffecom_previous_function_decl_); 2861 call = ffecom_3s (CALL_EXPR, 2862 TREE_TYPE (TREE_TYPE (TREE_TYPE (master_fn))), 2863 master_fn, arglist, NULL_TREE); 2864 2865 /* Decide whether the master function is a function or subroutine, and 2866 handle the return value for my entry point. */ 2867 2868 if (charfunc || ((ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE) 2869 && !altreturning)) 2870 { 2871 expand_expr_stmt (call); 2872 expand_null_return (); 2873 } 2874 else if (multi && cmplxfunc) 2875 { 2876 expand_expr_stmt (call); 2877 result 2878 = ffecom_1 (INDIRECT_REF, 2879 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))), 2880 result); 2881 result = ffecom_modify (NULL_TREE, result, 2882 ffecom_2 (COMPONENT_REF, TREE_TYPE (result), 2883 multi_retval, 2884 ffecom_multi_fields_[bt][kt])); 2885 expand_expr_stmt (result); 2886 expand_null_return (); 2887 } 2888 else if (multi) 2889 { 2890 expand_expr_stmt (call); 2891 result 2892 = ffecom_modify (NULL_TREE, result, 2893 convert (TREE_TYPE (result), 2894 ffecom_2 (COMPONENT_REF, 2895 ffecom_tree_type[bt][kt], 2896 multi_retval, 2897 ffecom_multi_fields_[bt][kt]))); 2898 expand_return (result); 2899 } 2900 else if (cmplxfunc) 2901 { 2902 result 2903 = ffecom_1 (INDIRECT_REF, 2904 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))), 2905 result); 2906 result = ffecom_modify (NULL_TREE, result, call); 2907 expand_expr_stmt (result); 2908 expand_null_return (); 2909 } 2910 else 2911 { 2912 result = ffecom_modify (NULL_TREE, 2913 result, 2914 convert (TREE_TYPE (result), 2915 call)); 2916 expand_return (result); 2917 } 2918 } 2919 2920 ffecom_end_compstmt (); 2921 2922 finish_function (0); 2923 2924 lineno = old_lineno; 2925 input_filename = old_input_filename; 2926 2927 ffecom_doing_entry_ = FALSE; 2928 } 2929 2930 /* Transform expr into gcc tree with possible destination 2931 2932 Recursive descent on expr while making corresponding tree nodes and 2933 attaching type info and such. If destination supplied and compatible 2934 with temporary that would be made in certain cases, temporary isn't 2935 made, destination used instead, and dest_used flag set TRUE. */ 2936 2937 static tree 2938 ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest, 2939 bool *dest_used, bool assignp, bool widenp) 2940 { 2941 tree item; 2942 tree list; 2943 tree args; 2944 ffeinfoBasictype bt; 2945 ffeinfoKindtype kt; 2946 tree t; 2947 tree dt; /* decl_tree for an ffesymbol. */ 2948 tree tree_type, tree_type_x; 2949 tree left, right; 2950 ffesymbol s; 2951 enum tree_code code; 2952 2953 assert (expr != NULL); 2954 2955 if (dest_used != NULL) 2956 *dest_used = FALSE; 2957 2958 bt = ffeinfo_basictype (ffebld_info (expr)); 2959 kt = ffeinfo_kindtype (ffebld_info (expr)); 2960 tree_type = ffecom_tree_type[bt][kt]; 2961 2962 /* Widen integral arithmetic as desired while preserving signedness. */ 2963 tree_type_x = NULL_TREE; 2964 if (widenp && tree_type 2965 && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT 2966 && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype)) 2967 tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype); 2968 2969 switch (ffebld_op (expr)) 2970 { 2971 case FFEBLD_opACCTER: 2972 { 2973 ffebitCount i; 2974 ffebit bits = ffebld_accter_bits (expr); 2975 ffetargetOffset source_offset = 0; 2976 ffetargetOffset dest_offset = ffebld_accter_pad (expr); 2977 tree purpose; 2978 2979 assert (dest_offset == 0 2980 || (bt == FFEINFO_basictypeCHARACTER 2981 && kt == FFEINFO_kindtypeCHARACTER1)); 2982 2983 list = item = NULL; 2984 for (;;) 2985 { 2986 ffebldConstantUnion cu; 2987 ffebitCount length; 2988 bool value; 2989 ffebldConstantArray ca = ffebld_accter (expr); 2990 2991 ffebit_test (bits, source_offset, &value, &length); 2992 if (length == 0) 2993 break; 2994 2995 if (value) 2996 { 2997 for (i = 0; i < length; ++i) 2998 { 2999 cu = ffebld_constantarray_get (ca, bt, kt, 3000 source_offset + i); 3001 3002 t = ffecom_constantunion (&cu, bt, kt, tree_type); 3003 3004 if (i == 0 3005 && dest_offset != 0) 3006 purpose = build_int_2 (dest_offset, 0); 3007 else 3008 purpose = NULL_TREE; 3009 3010 if (list == NULL_TREE) 3011 list = item = build_tree_list (purpose, t); 3012 else 3013 { 3014 TREE_CHAIN (item) = build_tree_list (purpose, t); 3015 item = TREE_CHAIN (item); 3016 } 3017 } 3018 } 3019 source_offset += length; 3020 dest_offset += length; 3021 } 3022 } 3023 3024 item = build_int_2 ((ffebld_accter_size (expr) 3025 + ffebld_accter_pad (expr)) - 1, 0); 3026 ffebit_kill (ffebld_accter_bits (expr)); 3027 TREE_TYPE (item) = ffecom_integer_type_node; 3028 item 3029 = build_array_type 3030 (tree_type, 3031 build_range_type (ffecom_integer_type_node, 3032 ffecom_integer_zero_node, 3033 item)); 3034 list = build (CONSTRUCTOR, item, NULL_TREE, list); 3035 TREE_CONSTANT (list) = 1; 3036 TREE_STATIC (list) = 1; 3037 return list; 3038 3039 case FFEBLD_opARRTER: 3040 { 3041 ffetargetOffset i; 3042 3043 list = NULL_TREE; 3044 if (ffebld_arrter_pad (expr) == 0) 3045 item = NULL_TREE; 3046 else 3047 { 3048 assert (bt == FFEINFO_basictypeCHARACTER 3049 && kt == FFEINFO_kindtypeCHARACTER1); 3050 3051 /* Becomes PURPOSE first time through loop. */ 3052 item = build_int_2 (ffebld_arrter_pad (expr), 0); 3053 } 3054 3055 for (i = 0; i < ffebld_arrter_size (expr); ++i) 3056 { 3057 ffebldConstantUnion cu 3058 = ffebld_constantarray_get (ffebld_arrter (expr), bt, kt, i); 3059 3060 t = ffecom_constantunion (&cu, bt, kt, tree_type); 3061 3062 if (list == NULL_TREE) 3063 /* Assume item is PURPOSE first time through loop. */ 3064 list = item = build_tree_list (item, t); 3065 else 3066 { 3067 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t); 3068 item = TREE_CHAIN (item); 3069 } 3070 } 3071 } 3072 3073 item = build_int_2 ((ffebld_arrter_size (expr) 3074 + ffebld_arrter_pad (expr)) - 1, 0); 3075 TREE_TYPE (item) = ffecom_integer_type_node; 3076 item 3077 = build_array_type 3078 (tree_type, 3079 build_range_type (ffecom_integer_type_node, 3080 ffecom_integer_zero_node, 3081 item)); 3082 list = build (CONSTRUCTOR, item, NULL_TREE, list); 3083 TREE_CONSTANT (list) = 1; 3084 TREE_STATIC (list) = 1; 3085 return list; 3086 3087 case FFEBLD_opCONTER: 3088 assert (ffebld_conter_pad (expr) == 0); 3089 item 3090 = ffecom_constantunion (&ffebld_constant_union (ffebld_conter (expr)), 3091 bt, kt, tree_type); 3092 return item; 3093 3094 case FFEBLD_opSYMTER: 3095 if ((ffebld_symter_generic (expr) != FFEINTRIN_genNONE) 3096 || (ffebld_symter_specific (expr) != FFEINTRIN_specNONE)) 3097 return ffecom_ptr_to_expr (expr); /* Same as %REF(intrinsic). */ 3098 s = ffebld_symter (expr); 3099 t = ffesymbol_hook (s).decl_tree; 3100 3101 if (assignp) 3102 { /* ASSIGN'ed-label expr. */ 3103 if (ffe_is_ugly_assign ()) 3104 { 3105 /* User explicitly wants ASSIGN'ed variables to be at the same 3106 memory address as the variables when used in non-ASSIGN 3107 contexts. That can make old, arcane, non-standard code 3108 work, but don't try to do it when a pointer wouldn't fit 3109 in the normal variable (take other approach, and warn, 3110 instead). */ 3111 3112 if (t == NULL_TREE) 3113 { 3114 s = ffecom_sym_transform_ (s); 3115 t = ffesymbol_hook (s).decl_tree; 3116 assert (t != NULL_TREE); 3117 } 3118 3119 if (t == error_mark_node) 3120 return t; 3121 3122 if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (t))) 3123 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node)))) 3124 { 3125 if (ffesymbol_hook (s).addr) 3126 t = ffecom_1 (INDIRECT_REF, 3127 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t); 3128 return t; 3129 } 3130 3131 if (ffesymbol_hook (s).assign_tree == NULL_TREE) 3132 { 3133 /* xgettext:no-c-format */ 3134 ffebad_start_msg ("ASSIGN'ed label cannot fit into `%A' at %0 -- using wider sibling", 3135 FFEBAD_severityWARNING); 3136 ffebad_string (ffesymbol_text (s)); 3137 ffebad_here (0, ffesymbol_where_line (s), 3138 ffesymbol_where_column (s)); 3139 ffebad_finish (); 3140 } 3141 } 3142 3143 /* Don't use the normal variable's tree for ASSIGN, though mark 3144 it as in the system header (housekeeping). Use an explicit, 3145 specially created sibling that is known to be wide enough 3146 to hold pointers to labels. */ 3147 3148 if (t != NULL_TREE 3149 && TREE_CODE (t) == VAR_DECL) 3150 DECL_IN_SYSTEM_HEADER (t) = 1; /* Don't let -Wunused complain. */ 3151 3152 t = ffesymbol_hook (s).assign_tree; 3153 if (t == NULL_TREE) 3154 { 3155 s = ffecom_sym_transform_assign_ (s); 3156 t = ffesymbol_hook (s).assign_tree; 3157 assert (t != NULL_TREE); 3158 } 3159 } 3160 else 3161 { 3162 if (t == NULL_TREE) 3163 { 3164 s = ffecom_sym_transform_ (s); 3165 t = ffesymbol_hook (s).decl_tree; 3166 assert (t != NULL_TREE); 3167 } 3168 if (ffesymbol_hook (s).addr) 3169 t = ffecom_1 (INDIRECT_REF, 3170 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t); 3171 } 3172 return t; 3173 3174 case FFEBLD_opARRAYREF: 3175 return ffecom_arrayref_ (NULL_TREE, expr, 0); 3176 3177 case FFEBLD_opUPLUS: 3178 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp); 3179 return ffecom_1 (NOP_EXPR, tree_type, left); 3180 3181 case FFEBLD_opPAREN: 3182 /* ~~~Make sure Fortran rules respected here */ 3183 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp); 3184 return ffecom_1 (NOP_EXPR, tree_type, left); 3185 3186 case FFEBLD_opUMINUS: 3187 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp); 3188 if (tree_type_x) 3189 { 3190 tree_type = tree_type_x; 3191 left = convert (tree_type, left); 3192 } 3193 return ffecom_1 (NEGATE_EXPR, tree_type, left); 3194 3195 case FFEBLD_opADD: 3196 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp); 3197 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp); 3198 if (tree_type_x) 3199 { 3200 tree_type = tree_type_x; 3201 left = convert (tree_type, left); 3202 right = convert (tree_type, right); 3203 } 3204 return ffecom_2 (PLUS_EXPR, tree_type, left, right); 3205 3206 case FFEBLD_opSUBTRACT: 3207 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp); 3208 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp); 3209 if (tree_type_x) 3210 { 3211 tree_type = tree_type_x; 3212 left = convert (tree_type, left); 3213 right = convert (tree_type, right); 3214 } 3215 return ffecom_2 (MINUS_EXPR, tree_type, left, right); 3216 3217 case FFEBLD_opMULTIPLY: 3218 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp); 3219 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp); 3220 if (tree_type_x) 3221 { 3222 tree_type = tree_type_x; 3223 left = convert (tree_type, left); 3224 right = convert (tree_type, right); 3225 } 3226 return ffecom_2 (MULT_EXPR, tree_type, left, right); 3227 3228 case FFEBLD_opDIVIDE: 3229 left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp); 3230 right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp); 3231 if (tree_type_x) 3232 { 3233 tree_type = tree_type_x; 3234 left = convert (tree_type, left); 3235 right = convert (tree_type, right); 3236 } 3237 return ffecom_tree_divide_ (tree_type, left, right, 3238 dest_tree, dest, dest_used, 3239 ffebld_nonter_hook (expr)); 3240 3241 case FFEBLD_opPOWER: 3242 { 3243 ffebld left = ffebld_left (expr); 3244 ffebld right = ffebld_right (expr); 3245 ffecomGfrt code; 3246 ffeinfoKindtype rtkt; 3247 ffeinfoKindtype ltkt; 3248 bool ref = TRUE; 3249 3250 switch (ffeinfo_basictype (ffebld_info (right))) 3251 { 3252 3253 case FFEINFO_basictypeINTEGER: 3254 if (1 || optimize) 3255 { 3256 item = ffecom_expr_power_integer_ (expr); 3257 if (item != NULL_TREE) 3258 return item; 3259 } 3260 3261 rtkt = FFEINFO_kindtypeINTEGER1; 3262 switch (ffeinfo_basictype (ffebld_info (left))) 3263 { 3264 case FFEINFO_basictypeINTEGER: 3265 if ((ffeinfo_kindtype (ffebld_info (left)) 3266 == FFEINFO_kindtypeINTEGER4) 3267 || (ffeinfo_kindtype (ffebld_info (right)) 3268 == FFEINFO_kindtypeINTEGER4)) 3269 { 3270 code = FFECOM_gfrtPOW_QQ; 3271 ltkt = FFEINFO_kindtypeINTEGER4; 3272 rtkt = FFEINFO_kindtypeINTEGER4; 3273 } 3274 else 3275 { 3276 code = FFECOM_gfrtPOW_II; 3277 ltkt = FFEINFO_kindtypeINTEGER1; 3278 } 3279 break; 3280 3281 case FFEINFO_basictypeREAL: 3282 if (ffeinfo_kindtype (ffebld_info (left)) 3283 == FFEINFO_kindtypeREAL1) 3284 { 3285 code = FFECOM_gfrtPOW_RI; 3286 ltkt = FFEINFO_kindtypeREAL1; 3287 } 3288 else 3289 { 3290 code = FFECOM_gfrtPOW_DI; 3291 ltkt = FFEINFO_kindtypeREAL2; 3292 } 3293 break; 3294 3295 case FFEINFO_basictypeCOMPLEX: 3296 if (ffeinfo_kindtype (ffebld_info (left)) 3297 == FFEINFO_kindtypeREAL1) 3298 { 3299 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */ 3300 ltkt = FFEINFO_kindtypeREAL1; 3301 } 3302 else 3303 { 3304 code = FFECOM_gfrtPOW_ZI; /* Overlapping result okay. */ 3305 ltkt = FFEINFO_kindtypeREAL2; 3306 } 3307 break; 3308 3309 default: 3310 assert ("bad pow_*i" == NULL); 3311 code = FFECOM_gfrtPOW_CI; /* Overlapping result okay. */ 3312 ltkt = FFEINFO_kindtypeREAL1; 3313 break; 3314 } 3315 if (ffeinfo_kindtype (ffebld_info (left)) != ltkt) 3316 left = ffeexpr_convert (left, NULL, NULL, 3317 ffeinfo_basictype (ffebld_info (left)), 3318 ltkt, 0, 3319 FFETARGET_charactersizeNONE, 3320 FFEEXPR_contextLET); 3321 if (ffeinfo_kindtype (ffebld_info (right)) != rtkt) 3322 right = ffeexpr_convert (right, NULL, NULL, 3323 FFEINFO_basictypeINTEGER, 3324 rtkt, 0, 3325 FFETARGET_charactersizeNONE, 3326 FFEEXPR_contextLET); 3327 break; 3328 3329 case FFEINFO_basictypeREAL: 3330 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1) 3331 left = ffeexpr_convert (left, NULL, NULL, FFEINFO_basictypeREAL, 3332 FFEINFO_kindtypeREALDOUBLE, 0, 3333 FFETARGET_charactersizeNONE, 3334 FFEEXPR_contextLET); 3335 if (ffeinfo_kindtype (ffebld_info (right)) 3336 == FFEINFO_kindtypeREAL1) 3337 right = ffeexpr_convert (right, NULL, NULL, 3338 FFEINFO_basictypeREAL, 3339 FFEINFO_kindtypeREALDOUBLE, 0, 3340 FFETARGET_charactersizeNONE, 3341 FFEEXPR_contextLET); 3342 /* We used to call FFECOM_gfrtPOW_DD here, 3343 which passes arguments by reference. */ 3344 code = FFECOM_gfrtL_POW; 3345 /* Pass arguments by value. */ 3346 ref = FALSE; 3347 break; 3348 3349 case FFEINFO_basictypeCOMPLEX: 3350 if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1) 3351 left = ffeexpr_convert (left, NULL, NULL, 3352 FFEINFO_basictypeCOMPLEX, 3353 FFEINFO_kindtypeREALDOUBLE, 0, 3354 FFETARGET_charactersizeNONE, 3355 FFEEXPR_contextLET); 3356 if (ffeinfo_kindtype (ffebld_info (right)) 3357 == FFEINFO_kindtypeREAL1) 3358 right = ffeexpr_convert (right, NULL, NULL, 3359 FFEINFO_basictypeCOMPLEX, 3360 FFEINFO_kindtypeREALDOUBLE, 0, 3361 FFETARGET_charactersizeNONE, 3362 FFEEXPR_contextLET); 3363 code = FFECOM_gfrtPOW_ZZ; /* Overlapping result okay. */ 3364 ref = TRUE; /* Pass arguments by reference. */ 3365 break; 3366 3367 default: 3368 assert ("bad pow_x*" == NULL); 3369 code = FFECOM_gfrtPOW_II; 3370 break; 3371 } 3372 return ffecom_call_binop_ (ffecom_gfrt_tree_ (code), 3373 ffecom_gfrt_kindtype (code), 3374 (ffe_is_f2c_library () 3375 && ffecom_gfrt_complex_[code]), 3376 tree_type, left, right, 3377 dest_tree, dest, dest_used, 3378 NULL_TREE, FALSE, ref, 3379 ffebld_nonter_hook (expr)); 3380 } 3381 3382 case FFEBLD_opNOT: 3383 switch (bt) 3384 { 3385 case FFEINFO_basictypeLOGICAL: 3386 item = ffecom_truth_value_invert (ffecom_expr (ffebld_left (expr))); 3387 return convert (tree_type, item); 3388 3389 case FFEINFO_basictypeINTEGER: 3390 return ffecom_1 (BIT_NOT_EXPR, tree_type, 3391 ffecom_expr (ffebld_left (expr))); 3392 3393 default: 3394 assert ("NOT bad basictype" == NULL); 3395 /* Fall through. */ 3396 case FFEINFO_basictypeANY: 3397 return error_mark_node; 3398 } 3399 break; 3400 3401 case FFEBLD_opFUNCREF: 3402 assert (ffeinfo_basictype (ffebld_info (expr)) 3403 != FFEINFO_basictypeCHARACTER); 3404 /* Fall through. */ 3405 case FFEBLD_opSUBRREF: 3406 if (ffeinfo_where (ffebld_info (ffebld_left (expr))) 3407 == FFEINFO_whereINTRINSIC) 3408 { /* Invocation of an intrinsic. */ 3409 item = ffecom_expr_intrinsic_ (expr, dest_tree, dest, 3410 dest_used); 3411 return item; 3412 } 3413 s = ffebld_symter (ffebld_left (expr)); 3414 dt = ffesymbol_hook (s).decl_tree; 3415 if (dt == NULL_TREE) 3416 { 3417 s = ffecom_sym_transform_ (s); 3418 dt = ffesymbol_hook (s).decl_tree; 3419 } 3420 if (dt == error_mark_node) 3421 return dt; 3422 3423 if (ffesymbol_hook (s).addr) 3424 item = dt; 3425 else 3426 item = ffecom_1_fn (dt); 3427 3428 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT) 3429 args = ffecom_list_expr (ffebld_right (expr)); 3430 else 3431 args = ffecom_list_ptr_to_expr (ffebld_right (expr)); 3432 3433 if (args == error_mark_node) 3434 return error_mark_node; 3435 3436 item = ffecom_call_ (item, kt, 3437 ffesymbol_is_f2c (s) 3438 && (bt == FFEINFO_basictypeCOMPLEX) 3439 && (ffesymbol_where (s) 3440 != FFEINFO_whereCONSTANT), 3441 tree_type, 3442 args, 3443 dest_tree, dest, dest_used, 3444 error_mark_node, FALSE, 3445 ffebld_nonter_hook (expr)); 3446 TREE_SIDE_EFFECTS (item) = 1; 3447 return item; 3448 3449 case FFEBLD_opAND: 3450 switch (bt) 3451 { 3452 case FFEINFO_basictypeLOGICAL: 3453 item 3454 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node, 3455 ffecom_truth_value (ffecom_expr (ffebld_left (expr))), 3456 ffecom_truth_value (ffecom_expr (ffebld_right (expr)))); 3457 return convert (tree_type, item); 3458 3459 case FFEINFO_basictypeINTEGER: 3460 return ffecom_2 (BIT_AND_EXPR, tree_type, 3461 ffecom_expr (ffebld_left (expr)), 3462 ffecom_expr (ffebld_right (expr))); 3463 3464 default: 3465 assert ("AND bad basictype" == NULL); 3466 /* Fall through. */ 3467 case FFEINFO_basictypeANY: 3468 return error_mark_node; 3469 } 3470 break; 3471 3472 case FFEBLD_opOR: 3473 switch (bt) 3474 { 3475 case FFEINFO_basictypeLOGICAL: 3476 item 3477 = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node, 3478 ffecom_truth_value (ffecom_expr (ffebld_left (expr))), 3479 ffecom_truth_value (ffecom_expr (ffebld_right (expr)))); 3480 return convert (tree_type, item); 3481 3482 case FFEINFO_basictypeINTEGER: 3483 return ffecom_2 (BIT_IOR_EXPR, tree_type, 3484 ffecom_expr (ffebld_left (expr)), 3485 ffecom_expr (ffebld_right (expr))); 3486 3487 default: 3488 assert ("OR bad basictype" == NULL); 3489 /* Fall through. */ 3490 case FFEINFO_basictypeANY: 3491 return error_mark_node; 3492 } 3493 break; 3494 3495 case FFEBLD_opXOR: 3496 case FFEBLD_opNEQV: 3497 switch (bt) 3498 { 3499 case FFEINFO_basictypeLOGICAL: 3500 item 3501 = ffecom_2 (NE_EXPR, integer_type_node, 3502 ffecom_expr (ffebld_left (expr)), 3503 ffecom_expr (ffebld_right (expr))); 3504 return convert (tree_type, ffecom_truth_value (item)); 3505 3506 case FFEINFO_basictypeINTEGER: 3507 return ffecom_2 (BIT_XOR_EXPR, tree_type, 3508 ffecom_expr (ffebld_left (expr)), 3509 ffecom_expr (ffebld_right (expr))); 3510 3511 default: 3512 assert ("XOR/NEQV bad basictype" == NULL); 3513 /* Fall through. */ 3514 case FFEINFO_basictypeANY: 3515 return error_mark_node; 3516 } 3517 break; 3518 3519 case FFEBLD_opEQV: 3520 switch (bt) 3521 { 3522 case FFEINFO_basictypeLOGICAL: 3523 item 3524 = ffecom_2 (EQ_EXPR, integer_type_node, 3525 ffecom_expr (ffebld_left (expr)), 3526 ffecom_expr (ffebld_right (expr))); 3527 return convert (tree_type, ffecom_truth_value (item)); 3528 3529 case FFEINFO_basictypeINTEGER: 3530 return 3531 ffecom_1 (BIT_NOT_EXPR, tree_type, 3532 ffecom_2 (BIT_XOR_EXPR, tree_type, 3533 ffecom_expr (ffebld_left (expr)), 3534 ffecom_expr (ffebld_right (expr)))); 3535 3536 default: 3537 assert ("EQV bad basictype" == NULL); 3538 /* Fall through. */ 3539 case FFEINFO_basictypeANY: 3540 return error_mark_node; 3541 } 3542 break; 3543 3544 case FFEBLD_opCONVERT: 3545 if (ffebld_op (ffebld_left (expr)) == FFEBLD_opANY) 3546 return error_mark_node; 3547 3548 switch (bt) 3549 { 3550 case FFEINFO_basictypeLOGICAL: 3551 case FFEINFO_basictypeINTEGER: 3552 case FFEINFO_basictypeREAL: 3553 return convert (tree_type, ffecom_expr (ffebld_left (expr))); 3554 3555 case FFEINFO_basictypeCOMPLEX: 3556 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr)))) 3557 { 3558 case FFEINFO_basictypeINTEGER: 3559 case FFEINFO_basictypeLOGICAL: 3560 case FFEINFO_basictypeREAL: 3561 item = ffecom_expr (ffebld_left (expr)); 3562 if (item == error_mark_node) 3563 return error_mark_node; 3564 /* convert() takes care of converting to the subtype first, 3565 at least in gcc-2.7.2. */ 3566 item = convert (tree_type, item); 3567 return item; 3568 3569 case FFEINFO_basictypeCOMPLEX: 3570 return convert (tree_type, ffecom_expr (ffebld_left (expr))); 3571 3572 default: 3573 assert ("CONVERT COMPLEX bad basictype" == NULL); 3574 /* Fall through. */ 3575 case FFEINFO_basictypeANY: 3576 return error_mark_node; 3577 } 3578 break; 3579 3580 default: 3581 assert ("CONVERT bad basictype" == NULL); 3582 /* Fall through. */ 3583 case FFEINFO_basictypeANY: 3584 return error_mark_node; 3585 } 3586 break; 3587 3588 case FFEBLD_opLT: 3589 code = LT_EXPR; 3590 goto relational; /* :::::::::::::::::::: */ 3591 3592 case FFEBLD_opLE: 3593 code = LE_EXPR; 3594 goto relational; /* :::::::::::::::::::: */ 3595 3596 case FFEBLD_opEQ: 3597 code = EQ_EXPR; 3598 goto relational; /* :::::::::::::::::::: */ 3599 3600 case FFEBLD_opNE: 3601 code = NE_EXPR; 3602 goto relational; /* :::::::::::::::::::: */ 3603 3604 case FFEBLD_opGT: 3605 code = GT_EXPR; 3606 goto relational; /* :::::::::::::::::::: */ 3607 3608 case FFEBLD_opGE: 3609 code = GE_EXPR; 3610 3611 relational: /* :::::::::::::::::::: */ 3612 switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr)))) 3613 { 3614 case FFEINFO_basictypeLOGICAL: 3615 case FFEINFO_basictypeINTEGER: 3616 case FFEINFO_basictypeREAL: 3617 item = ffecom_2 (code, integer_type_node, 3618 ffecom_expr (ffebld_left (expr)), 3619 ffecom_expr (ffebld_right (expr))); 3620 return convert (tree_type, item); 3621 3622 case FFEINFO_basictypeCOMPLEX: 3623 assert (code == EQ_EXPR || code == NE_EXPR); 3624 { 3625 tree real_type; 3626 tree arg1 = ffecom_expr (ffebld_left (expr)); 3627 tree arg2 = ffecom_expr (ffebld_right (expr)); 3628 3629 if (arg1 == error_mark_node || arg2 == error_mark_node) 3630 return error_mark_node; 3631 3632 arg1 = ffecom_save_tree (arg1); 3633 arg2 = ffecom_save_tree (arg2); 3634 3635 if (TREE_CODE (TREE_TYPE (arg1)) == COMPLEX_TYPE) 3636 { 3637 real_type = TREE_TYPE (TREE_TYPE (arg1)); 3638 assert (real_type == TREE_TYPE (TREE_TYPE (arg2))); 3639 } 3640 else 3641 { 3642 real_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg1))); 3643 assert (real_type == TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg2)))); 3644 } 3645 3646 item 3647 = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node, 3648 ffecom_2 (EQ_EXPR, integer_type_node, 3649 ffecom_1 (REALPART_EXPR, real_type, arg1), 3650 ffecom_1 (REALPART_EXPR, real_type, arg2)), 3651 ffecom_2 (EQ_EXPR, integer_type_node, 3652 ffecom_1 (IMAGPART_EXPR, real_type, arg1), 3653 ffecom_1 (IMAGPART_EXPR, real_type, 3654 arg2))); 3655 if (code == EQ_EXPR) 3656 item = ffecom_truth_value (item); 3657 else 3658 item = ffecom_truth_value_invert (item); 3659 return convert (tree_type, item); 3660 } 3661 3662 case FFEINFO_basictypeCHARACTER: 3663 { 3664 ffebld left = ffebld_left (expr); 3665 ffebld right = ffebld_right (expr); 3666 tree left_tree; 3667 tree right_tree; 3668 tree left_length; 3669 tree right_length; 3670 3671 /* f2c run-time functions do the implicit blank-padding for us, 3672 so we don't usually have to implement blank-padding ourselves. 3673 (The exception is when we pass an argument to a separately 3674 compiled statement function -- if we know the arg is not the 3675 same length as the dummy, we must truncate or extend it. If 3676 we "inline" statement functions, that necessity goes away as 3677 well.) 3678 3679 Strip off the CONVERT operators that blank-pad. (Truncation by 3680 CONVERT shouldn't happen here, but it can happen in 3681 assignments.) */ 3682 3683 while (ffebld_op (left) == FFEBLD_opCONVERT) 3684 left = ffebld_left (left); 3685 while (ffebld_op (right) == FFEBLD_opCONVERT) 3686 right = ffebld_left (right); 3687 3688 left_tree = ffecom_arg_ptr_to_expr (left, &left_length); 3689 right_tree = ffecom_arg_ptr_to_expr (right, &right_length); 3690 3691 if (left_tree == error_mark_node || left_length == error_mark_node 3692 || right_tree == error_mark_node 3693 || right_length == error_mark_node) 3694 return error_mark_node; 3695 3696 if ((ffebld_size_known (left) == 1) 3697 && (ffebld_size_known (right) == 1)) 3698 { 3699 left_tree 3700 = ffecom_1 (INDIRECT_REF, 3701 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))), 3702 left_tree); 3703 right_tree 3704 = ffecom_1 (INDIRECT_REF, 3705 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))), 3706 right_tree); 3707 3708 item 3709 = ffecom_2 (code, integer_type_node, 3710 ffecom_2 (ARRAY_REF, 3711 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))), 3712 left_tree, 3713 integer_one_node), 3714 ffecom_2 (ARRAY_REF, 3715 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))), 3716 right_tree, 3717 integer_one_node)); 3718 } 3719 else 3720 { 3721 item = build_tree_list (NULL_TREE, left_tree); 3722 TREE_CHAIN (item) = build_tree_list (NULL_TREE, right_tree); 3723 TREE_CHAIN (TREE_CHAIN (item)) = build_tree_list (NULL_TREE, 3724 left_length); 3725 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item))) 3726 = build_tree_list (NULL_TREE, right_length); 3727 item = ffecom_call_gfrt (FFECOM_gfrtCMP, item, NULL_TREE); 3728 item = ffecom_2 (code, integer_type_node, 3729 item, 3730 convert (TREE_TYPE (item), 3731 integer_zero_node)); 3732 } 3733 item = convert (tree_type, item); 3734 } 3735 3736 return item; 3737 3738 default: 3739 assert ("relational bad basictype" == NULL); 3740 /* Fall through. */ 3741 case FFEINFO_basictypeANY: 3742 return error_mark_node; 3743 } 3744 break; 3745 3746 case FFEBLD_opPERCENT_LOC: 3747 item = ffecom_arg_ptr_to_expr (ffebld_left (expr), &list); 3748 return convert (tree_type, item); 3749 3750 case FFEBLD_opPERCENT_VAL: 3751 item = ffecom_arg_expr (ffebld_left (expr), &list); 3752 return convert (tree_type, item); 3753 3754 case FFEBLD_opITEM: 3755 case FFEBLD_opSTAR: 3756 case FFEBLD_opBOUNDS: 3757 case FFEBLD_opREPEAT: 3758 case FFEBLD_opLABTER: 3759 case FFEBLD_opLABTOK: 3760 case FFEBLD_opIMPDO: 3761 case FFEBLD_opCONCATENATE: 3762 case FFEBLD_opSUBSTR: 3763 default: 3764 assert ("bad op" == NULL); 3765 /* Fall through. */ 3766 case FFEBLD_opANY: 3767 return error_mark_node; 3768 } 3769 3770 #if 1 3771 assert ("didn't think anything got here anymore!!" == NULL); 3772 #else 3773 switch (ffebld_arity (expr)) 3774 { 3775 case 2: 3776 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr)); 3777 TREE_OPERAND (item, 1) = ffecom_expr (ffebld_right (expr)); 3778 if (TREE_OPERAND (item, 0) == error_mark_node 3779 || TREE_OPERAND (item, 1) == error_mark_node) 3780 return error_mark_node; 3781 break; 3782 3783 case 1: 3784 TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr)); 3785 if (TREE_OPERAND (item, 0) == error_mark_node) 3786 return error_mark_node; 3787 break; 3788 3789 default: 3790 break; 3791 } 3792 3793 return fold (item); 3794 #endif 3795 } 3796 3797 /* Returns the tree that does the intrinsic invocation. 3798 3799 Note: this function applies only to intrinsics returning 3800 CHARACTER*1 or non-CHARACTER results, and to intrinsic 3801 subroutines. */ 3802 3803 static tree 3804 ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree, 3805 ffebld dest, bool *dest_used) 3806 { 3807 tree expr_tree; 3808 tree saved_expr1; /* For those who need it. */ 3809 tree saved_expr2; /* For those who need it. */ 3810 ffeinfoBasictype bt; 3811 ffeinfoKindtype kt; 3812 tree tree_type; 3813 tree arg1_type; 3814 tree real_type; /* REAL type corresponding to COMPLEX. */ 3815 tree tempvar; 3816 ffebld list = ffebld_right (expr); /* List of (some) args. */ 3817 ffebld arg1; /* For handy reference. */ 3818 ffebld arg2; 3819 ffebld arg3; 3820 ffeintrinImp codegen_imp; 3821 ffecomGfrt gfrt; 3822 3823 assert (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER); 3824 3825 if (dest_used != NULL) 3826 *dest_used = FALSE; 3827 3828 bt = ffeinfo_basictype (ffebld_info (expr)); 3829 kt = ffeinfo_kindtype (ffebld_info (expr)); 3830 tree_type = ffecom_tree_type[bt][kt]; 3831 3832 if (list != NULL) 3833 { 3834 arg1 = ffebld_head (list); 3835 if (arg1 != NULL && ffebld_op (arg1) == FFEBLD_opANY) 3836 return error_mark_node; 3837 if ((list = ffebld_trail (list)) != NULL) 3838 { 3839 arg2 = ffebld_head (list); 3840 if (arg2 != NULL && ffebld_op (arg2) == FFEBLD_opANY) 3841 return error_mark_node; 3842 if ((list = ffebld_trail (list)) != NULL) 3843 { 3844 arg3 = ffebld_head (list); 3845 if (arg3 != NULL && ffebld_op (arg3) == FFEBLD_opANY) 3846 return error_mark_node; 3847 } 3848 else 3849 arg3 = NULL; 3850 } 3851 else 3852 arg2 = arg3 = NULL; 3853 } 3854 else 3855 arg1 = arg2 = arg3 = NULL; 3856 3857 /* <list> ends up at the opITEM of the 3rd arg, or NULL if there are < 3 3858 args. This is used by the MAX/MIN expansions. */ 3859 3860 if (arg1 != NULL) 3861 arg1_type = ffecom_tree_type 3862 [ffeinfo_basictype (ffebld_info (arg1))] 3863 [ffeinfo_kindtype (ffebld_info (arg1))]; 3864 else 3865 arg1_type = NULL_TREE; /* Really not needed, but might catch bugs 3866 here. */ 3867 3868 /* There are several ways for each of the cases in the following switch 3869 statements to exit (from simplest to use to most complicated): 3870 3871 break; (when expr_tree == NULL) 3872 3873 A standard call is made to the specific intrinsic just as if it had been 3874 passed in as a dummy procedure and called as any old procedure. This 3875 method can produce slower code but in some cases it's the easiest way for 3876 now. However, if a (presumably faster) direct call is available, 3877 that is used, so this is the easiest way in many more cases now. 3878 3879 gfrt = FFECOM_gfrtWHATEVER; 3880 break; 3881 3882 gfrt contains the gfrt index of a library function to call, passing the 3883 argument(s) by value rather than by reference. Used when a more 3884 careful choice of library function is needed than that provided 3885 by the vanilla `break;'. 3886 3887 return expr_tree; 3888 3889 The expr_tree has been completely set up and is ready to be returned 3890 as is. No further actions are taken. Use this when the tree is not 3891 in the simple form for one of the arity_n labels. */ 3892 3893 /* For info on how the switch statement cases were written, see the files 3894 enclosed in comments below the switch statement. */ 3895 3896 codegen_imp = ffebld_symter_implementation (ffebld_left (expr)); 3897 gfrt = ffeintrin_gfrt_direct (codegen_imp); 3898 if (gfrt == FFECOM_gfrt) 3899 gfrt = ffeintrin_gfrt_indirect (codegen_imp); 3900 3901 switch (codegen_imp) 3902 { 3903 case FFEINTRIN_impABS: 3904 case FFEINTRIN_impCABS: 3905 case FFEINTRIN_impCDABS: 3906 case FFEINTRIN_impDABS: 3907 case FFEINTRIN_impIABS: 3908 if (ffeinfo_basictype (ffebld_info (arg1)) 3909 == FFEINFO_basictypeCOMPLEX) 3910 { 3911 if (kt == FFEINFO_kindtypeREAL1) 3912 gfrt = FFECOM_gfrtCABS; 3913 else if (kt == FFEINFO_kindtypeREAL2) 3914 gfrt = FFECOM_gfrtCDABS; 3915 break; 3916 } 3917 return ffecom_1 (ABS_EXPR, tree_type, 3918 convert (tree_type, ffecom_expr (arg1))); 3919 3920 case FFEINTRIN_impACOS: 3921 case FFEINTRIN_impDACOS: 3922 break; 3923 3924 case FFEINTRIN_impAIMAG: 3925 case FFEINTRIN_impDIMAG: 3926 case FFEINTRIN_impIMAGPART: 3927 if (TREE_CODE (arg1_type) == COMPLEX_TYPE) 3928 arg1_type = TREE_TYPE (arg1_type); 3929 else 3930 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type)); 3931 3932 return 3933 convert (tree_type, 3934 ffecom_1 (IMAGPART_EXPR, arg1_type, 3935 ffecom_expr (arg1))); 3936 3937 case FFEINTRIN_impAINT: 3938 case FFEINTRIN_impDINT: 3939 #if 0 3940 /* ~~Someday implement FIX_TRUNC_EXPR yielding same type as arg. */ 3941 return ffecom_1 (FIX_TRUNC_EXPR, tree_type, ffecom_expr (arg1)); 3942 #else /* in the meantime, must use floor to avoid range problems with ints */ 3943 /* r__1 = r1 >= 0 ? floor(r1) : -floor(-r1); */ 3944 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1)); 3945 return 3946 convert (tree_type, 3947 ffecom_3 (COND_EXPR, double_type_node, 3948 ffecom_truth_value 3949 (ffecom_2 (GE_EXPR, integer_type_node, 3950 saved_expr1, 3951 convert (arg1_type, 3952 ffecom_float_zero_))), 3953 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR, 3954 build_tree_list (NULL_TREE, 3955 convert (double_type_node, 3956 saved_expr1)), 3957 NULL_TREE), 3958 ffecom_1 (NEGATE_EXPR, double_type_node, 3959 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR, 3960 build_tree_list (NULL_TREE, 3961 convert (double_type_node, 3962 ffecom_1 (NEGATE_EXPR, 3963 arg1_type, 3964 saved_expr1))), 3965 NULL_TREE) 3966 )) 3967 ); 3968 #endif 3969 3970 case FFEINTRIN_impANINT: 3971 case FFEINTRIN_impDNINT: 3972 #if 0 /* This way of doing it won't handle real 3973 numbers of large magnitudes. */ 3974 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1)); 3975 expr_tree = convert (tree_type, 3976 convert (integer_type_node, 3977 ffecom_3 (COND_EXPR, tree_type, 3978 ffecom_truth_value 3979 (ffecom_2 (GE_EXPR, 3980 integer_type_node, 3981 saved_expr1, 3982 ffecom_float_zero_)), 3983 ffecom_2 (PLUS_EXPR, 3984 tree_type, 3985 saved_expr1, 3986 ffecom_float_half_), 3987 ffecom_2 (MINUS_EXPR, 3988 tree_type, 3989 saved_expr1, 3990 ffecom_float_half_)))); 3991 return expr_tree; 3992 #else /* So we instead call floor. */ 3993 /* r__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1) */ 3994 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1)); 3995 return 3996 convert (tree_type, 3997 ffecom_3 (COND_EXPR, double_type_node, 3998 ffecom_truth_value 3999 (ffecom_2 (GE_EXPR, integer_type_node, 4000 saved_expr1, 4001 convert (arg1_type, 4002 ffecom_float_zero_))), 4003 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR, 4004 build_tree_list (NULL_TREE, 4005 convert (double_type_node, 4006 ffecom_2 (PLUS_EXPR, 4007 arg1_type, 4008 saved_expr1, 4009 convert (arg1_type, 4010 ffecom_float_half_)))), 4011 NULL_TREE), 4012 ffecom_1 (NEGATE_EXPR, double_type_node, 4013 ffecom_call_gfrt (FFECOM_gfrtL_FLOOR, 4014 build_tree_list (NULL_TREE, 4015 convert (double_type_node, 4016 ffecom_2 (MINUS_EXPR, 4017 arg1_type, 4018 convert (arg1_type, 4019 ffecom_float_half_), 4020 saved_expr1))), 4021 NULL_TREE)) 4022 ) 4023 ); 4024 #endif 4025 4026 case FFEINTRIN_impASIN: 4027 case FFEINTRIN_impDASIN: 4028 case FFEINTRIN_impATAN: 4029 case FFEINTRIN_impDATAN: 4030 case FFEINTRIN_impATAN2: 4031 case FFEINTRIN_impDATAN2: 4032 break; 4033 4034 case FFEINTRIN_impCHAR: 4035 case FFEINTRIN_impACHAR: 4036 tempvar = ffebld_nonter_hook (expr); 4037 assert (tempvar); 4038 { 4039 tree tmv = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (tempvar))); 4040 4041 expr_tree = ffecom_modify (tmv, 4042 ffecom_2 (ARRAY_REF, tmv, tempvar, 4043 integer_one_node), 4044 convert (tmv, ffecom_expr (arg1))); 4045 } 4046 expr_tree = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), 4047 expr_tree, 4048 tempvar); 4049 expr_tree = ffecom_1 (ADDR_EXPR, 4050 build_pointer_type (TREE_TYPE (expr_tree)), 4051 expr_tree); 4052 return expr_tree; 4053 4054 case FFEINTRIN_impCMPLX: 4055 case FFEINTRIN_impDCMPLX: 4056 if (arg2 == NULL) 4057 return 4058 convert (tree_type, ffecom_expr (arg1)); 4059 4060 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt]; 4061 return 4062 ffecom_2 (COMPLEX_EXPR, tree_type, 4063 convert (real_type, ffecom_expr (arg1)), 4064 convert (real_type, 4065 ffecom_expr (arg2))); 4066 4067 case FFEINTRIN_impCOMPLEX: 4068 return 4069 ffecom_2 (COMPLEX_EXPR, tree_type, 4070 ffecom_expr (arg1), 4071 ffecom_expr (arg2)); 4072 4073 case FFEINTRIN_impCONJG: 4074 case FFEINTRIN_impDCONJG: 4075 { 4076 tree arg1_tree; 4077 4078 real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt]; 4079 arg1_tree = ffecom_save_tree (ffecom_expr (arg1)); 4080 return 4081 ffecom_2 (COMPLEX_EXPR, tree_type, 4082 ffecom_1 (REALPART_EXPR, real_type, arg1_tree), 4083 ffecom_1 (NEGATE_EXPR, real_type, 4084 ffecom_1 (IMAGPART_EXPR, real_type, arg1_tree))); 4085 } 4086 4087 case FFEINTRIN_impCOS: 4088 case FFEINTRIN_impCCOS: 4089 case FFEINTRIN_impCDCOS: 4090 case FFEINTRIN_impDCOS: 4091 if (bt == FFEINFO_basictypeCOMPLEX) 4092 { 4093 if (kt == FFEINFO_kindtypeREAL1) 4094 gfrt = FFECOM_gfrtCCOS; /* Overlapping result okay. */ 4095 else if (kt == FFEINFO_kindtypeREAL2) 4096 gfrt = FFECOM_gfrtCDCOS; /* Overlapping result okay. */ 4097 } 4098 break; 4099 4100 case FFEINTRIN_impCOSH: 4101 case FFEINTRIN_impDCOSH: 4102 break; 4103 4104 case FFEINTRIN_impDBLE: 4105 case FFEINTRIN_impDFLOAT: 4106 case FFEINTRIN_impDREAL: 4107 case FFEINTRIN_impFLOAT: 4108 case FFEINTRIN_impIDINT: 4109 case FFEINTRIN_impIFIX: 4110 case FFEINTRIN_impINT2: 4111 case FFEINTRIN_impINT8: 4112 case FFEINTRIN_impINT: 4113 case FFEINTRIN_impLONG: 4114 case FFEINTRIN_impREAL: 4115 case FFEINTRIN_impSHORT: 4116 case FFEINTRIN_impSNGL: 4117 return convert (tree_type, ffecom_expr (arg1)); 4118 4119 case FFEINTRIN_impDIM: 4120 case FFEINTRIN_impDDIM: 4121 case FFEINTRIN_impIDIM: 4122 saved_expr1 = ffecom_save_tree (convert (tree_type, 4123 ffecom_expr (arg1))); 4124 saved_expr2 = ffecom_save_tree (convert (tree_type, 4125 ffecom_expr (arg2))); 4126 return 4127 ffecom_3 (COND_EXPR, tree_type, 4128 ffecom_truth_value 4129 (ffecom_2 (GT_EXPR, integer_type_node, 4130 saved_expr1, 4131 saved_expr2)), 4132 ffecom_2 (MINUS_EXPR, tree_type, 4133 saved_expr1, 4134 saved_expr2), 4135 convert (tree_type, ffecom_float_zero_)); 4136 4137 case FFEINTRIN_impDPROD: 4138 return 4139 ffecom_2 (MULT_EXPR, tree_type, 4140 convert (tree_type, ffecom_expr (arg1)), 4141 convert (tree_type, ffecom_expr (arg2))); 4142 4143 case FFEINTRIN_impEXP: 4144 case FFEINTRIN_impCDEXP: 4145 case FFEINTRIN_impCEXP: 4146 case FFEINTRIN_impDEXP: 4147 if (bt == FFEINFO_basictypeCOMPLEX) 4148 { 4149 if (kt == FFEINFO_kindtypeREAL1) 4150 gfrt = FFECOM_gfrtCEXP; /* Overlapping result okay. */ 4151 else if (kt == FFEINFO_kindtypeREAL2) 4152 gfrt = FFECOM_gfrtCDEXP; /* Overlapping result okay. */ 4153 } 4154 break; 4155 4156 case FFEINTRIN_impICHAR: 4157 case FFEINTRIN_impIACHAR: 4158 #if 0 /* The simple approach. */ 4159 ffecom_char_args_ (&expr_tree, &saved_expr1 /* Ignored */ , arg1); 4160 expr_tree 4161 = ffecom_1 (INDIRECT_REF, 4162 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))), 4163 expr_tree); 4164 expr_tree 4165 = ffecom_2 (ARRAY_REF, 4166 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))), 4167 expr_tree, 4168 integer_one_node); 4169 return convert (tree_type, expr_tree); 4170 #else /* The more interesting (and more optimal) approach. */ 4171 expr_tree = ffecom_intrinsic_ichar_ (tree_type, arg1, &saved_expr1); 4172 expr_tree = ffecom_3 (COND_EXPR, tree_type, 4173 saved_expr1, 4174 expr_tree, 4175 convert (tree_type, integer_zero_node)); 4176 return expr_tree; 4177 #endif 4178 4179 case FFEINTRIN_impINDEX: 4180 break; 4181 4182 case FFEINTRIN_impLEN: 4183 #if 0 4184 break; /* The simple approach. */ 4185 #else 4186 return ffecom_intrinsic_len_ (arg1); /* The more optimal approach. */ 4187 #endif 4188 4189 case FFEINTRIN_impLGE: 4190 case FFEINTRIN_impLGT: 4191 case FFEINTRIN_impLLE: 4192 case FFEINTRIN_impLLT: 4193 break; 4194 4195 case FFEINTRIN_impLOG: 4196 case FFEINTRIN_impALOG: 4197 case FFEINTRIN_impCDLOG: 4198 case FFEINTRIN_impCLOG: 4199 case FFEINTRIN_impDLOG: 4200 if (bt == FFEINFO_basictypeCOMPLEX) 4201 { 4202 if (kt == FFEINFO_kindtypeREAL1) 4203 gfrt = FFECOM_gfrtCLOG; /* Overlapping result okay. */ 4204 else if (kt == FFEINFO_kindtypeREAL2) 4205 gfrt = FFECOM_gfrtCDLOG; /* Overlapping result okay. */ 4206 } 4207 break; 4208 4209 case FFEINTRIN_impLOG10: 4210 case FFEINTRIN_impALOG10: 4211 case FFEINTRIN_impDLOG10: 4212 if (gfrt != FFECOM_gfrt) 4213 break; /* Already picked one, stick with it. */ 4214 4215 if (kt == FFEINFO_kindtypeREAL1) 4216 /* We used to call FFECOM_gfrtALOG10 here. */ 4217 gfrt = FFECOM_gfrtL_LOG10; 4218 else if (kt == FFEINFO_kindtypeREAL2) 4219 /* We used to call FFECOM_gfrtDLOG10 here. */ 4220 gfrt = FFECOM_gfrtL_LOG10; 4221 break; 4222 4223 case FFEINTRIN_impMAX: 4224 case FFEINTRIN_impAMAX0: 4225 case FFEINTRIN_impAMAX1: 4226 case FFEINTRIN_impDMAX1: 4227 case FFEINTRIN_impMAX0: 4228 case FFEINTRIN_impMAX1: 4229 if (bt != ffeinfo_basictype (ffebld_info (arg1))) 4230 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr)); 4231 else 4232 arg1_type = tree_type; 4233 expr_tree = ffecom_2 (MAX_EXPR, arg1_type, 4234 convert (arg1_type, ffecom_expr (arg1)), 4235 convert (arg1_type, ffecom_expr (arg2))); 4236 for (; list != NULL; list = ffebld_trail (list)) 4237 { 4238 if ((ffebld_head (list) == NULL) 4239 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY)) 4240 continue; 4241 expr_tree = ffecom_2 (MAX_EXPR, arg1_type, 4242 expr_tree, 4243 convert (arg1_type, 4244 ffecom_expr (ffebld_head (list)))); 4245 } 4246 return convert (tree_type, expr_tree); 4247 4248 case FFEINTRIN_impMIN: 4249 case FFEINTRIN_impAMIN0: 4250 case FFEINTRIN_impAMIN1: 4251 case FFEINTRIN_impDMIN1: 4252 case FFEINTRIN_impMIN0: 4253 case FFEINTRIN_impMIN1: 4254 if (bt != ffeinfo_basictype (ffebld_info (arg1))) 4255 arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr)); 4256 else 4257 arg1_type = tree_type; 4258 expr_tree = ffecom_2 (MIN_EXPR, arg1_type, 4259 convert (arg1_type, ffecom_expr (arg1)), 4260 convert (arg1_type, ffecom_expr (arg2))); 4261 for (; list != NULL; list = ffebld_trail (list)) 4262 { 4263 if ((ffebld_head (list) == NULL) 4264 || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY)) 4265 continue; 4266 expr_tree = ffecom_2 (MIN_EXPR, arg1_type, 4267 expr_tree, 4268 convert (arg1_type, 4269 ffecom_expr (ffebld_head (list)))); 4270 } 4271 return convert (tree_type, expr_tree); 4272 4273 case FFEINTRIN_impMOD: 4274 case FFEINTRIN_impAMOD: 4275 case FFEINTRIN_impDMOD: 4276 if (bt != FFEINFO_basictypeREAL) 4277 return ffecom_2 (TRUNC_MOD_EXPR, tree_type, 4278 convert (tree_type, ffecom_expr (arg1)), 4279 convert (tree_type, ffecom_expr (arg2))); 4280 4281 if (kt == FFEINFO_kindtypeREAL1) 4282 /* We used to call FFECOM_gfrtAMOD here. */ 4283 gfrt = FFECOM_gfrtL_FMOD; 4284 else if (kt == FFEINFO_kindtypeREAL2) 4285 /* We used to call FFECOM_gfrtDMOD here. */ 4286 gfrt = FFECOM_gfrtL_FMOD; 4287 break; 4288 4289 case FFEINTRIN_impNINT: 4290 case FFEINTRIN_impIDNINT: 4291 #if 0 4292 /* ~~Ideally FIX_ROUND_EXPR would be implemented, but it ain't yet. */ 4293 return ffecom_1 (FIX_ROUND_EXPR, tree_type, ffecom_expr (arg1)); 4294 #else 4295 /* i__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1); */ 4296 saved_expr1 = ffecom_save_tree (ffecom_expr (arg1)); 4297 return 4298 convert (ffecom_integer_type_node, 4299 ffecom_3 (COND_EXPR, arg1_type, 4300 ffecom_truth_value 4301 (ffecom_2 (GE_EXPR, integer_type_node, 4302 saved_expr1, 4303 convert (arg1_type, 4304 ffecom_float_zero_))), 4305 ffecom_2 (PLUS_EXPR, arg1_type, 4306 saved_expr1, 4307 convert (arg1_type, 4308 ffecom_float_half_)), 4309 ffecom_2 (MINUS_EXPR, arg1_type, 4310 saved_expr1, 4311 convert (arg1_type, 4312 ffecom_float_half_)))); 4313 #endif 4314 4315 case FFEINTRIN_impSIGN: 4316 case FFEINTRIN_impDSIGN: 4317 case FFEINTRIN_impISIGN: 4318 { 4319 tree arg2_tree = ffecom_expr (arg2); 4320 4321 saved_expr1 4322 = ffecom_save_tree 4323 (ffecom_1 (ABS_EXPR, tree_type, 4324 convert (tree_type, 4325 ffecom_expr (arg1)))); 4326 expr_tree 4327 = ffecom_3 (COND_EXPR, tree_type, 4328 ffecom_truth_value 4329 (ffecom_2 (GE_EXPR, integer_type_node, 4330 arg2_tree, 4331 convert (TREE_TYPE (arg2_tree), 4332 integer_zero_node))), 4333 saved_expr1, 4334 ffecom_1 (NEGATE_EXPR, tree_type, saved_expr1)); 4335 /* Make sure SAVE_EXPRs get referenced early enough. */ 4336 expr_tree 4337 = ffecom_2 (COMPOUND_EXPR, tree_type, 4338 convert (void_type_node, saved_expr1), 4339 expr_tree); 4340 } 4341 return expr_tree; 4342 4343 case FFEINTRIN_impSIN: 4344 case FFEINTRIN_impCDSIN: 4345 case FFEINTRIN_impCSIN: 4346 case FFEINTRIN_impDSIN: 4347 if (bt == FFEINFO_basictypeCOMPLEX) 4348 { 4349 if (kt == FFEINFO_kindtypeREAL1) 4350 gfrt = FFECOM_gfrtCSIN; /* Overlapping result okay. */ 4351 else if (kt == FFEINFO_kindtypeREAL2) 4352 gfrt = FFECOM_gfrtCDSIN; /* Overlapping result okay. */ 4353 } 4354 break; 4355 4356 case FFEINTRIN_impSINH: 4357 case FFEINTRIN_impDSINH: 4358 break; 4359 4360 case FFEINTRIN_impSQRT: 4361 case FFEINTRIN_impCDSQRT: 4362 case FFEINTRIN_impCSQRT: 4363 case FFEINTRIN_impDSQRT: 4364 if (bt == FFEINFO_basictypeCOMPLEX) 4365 { 4366 if (kt == FFEINFO_kindtypeREAL1) 4367 gfrt = FFECOM_gfrtCSQRT; /* Overlapping result okay. */ 4368 else if (kt == FFEINFO_kindtypeREAL2) 4369 gfrt = FFECOM_gfrtCDSQRT; /* Overlapping result okay. */ 4370 } 4371 break; 4372 4373 case FFEINTRIN_impTAN: 4374 case FFEINTRIN_impDTAN: 4375 case FFEINTRIN_impTANH: 4376 case FFEINTRIN_impDTANH: 4377 break; 4378 4379 case FFEINTRIN_impREALPART: 4380 if (TREE_CODE (arg1_type) == COMPLEX_TYPE) 4381 arg1_type = TREE_TYPE (arg1_type); 4382 else 4383 arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type)); 4384 4385 return 4386 convert (tree_type, 4387 ffecom_1 (REALPART_EXPR, arg1_type, 4388 ffecom_expr (arg1))); 4389 4390 case FFEINTRIN_impIAND: 4391 case FFEINTRIN_impAND: 4392 return ffecom_2 (BIT_AND_EXPR, tree_type, 4393 convert (tree_type, 4394 ffecom_expr (arg1)), 4395 convert (tree_type, 4396 ffecom_expr (arg2))); 4397 4398 case FFEINTRIN_impIOR: 4399 case FFEINTRIN_impOR: 4400 return ffecom_2 (BIT_IOR_EXPR, tree_type, 4401 convert (tree_type, 4402 ffecom_expr (arg1)), 4403 convert (tree_type, 4404 ffecom_expr (arg2))); 4405 4406 case FFEINTRIN_impIEOR: 4407 case FFEINTRIN_impXOR: 4408 return ffecom_2 (BIT_XOR_EXPR, tree_type, 4409 convert (tree_type, 4410 ffecom_expr (arg1)), 4411 convert (tree_type, 4412 ffecom_expr (arg2))); 4413 4414 case FFEINTRIN_impLSHIFT: 4415 return ffecom_2 (LSHIFT_EXPR, tree_type, 4416 ffecom_expr (arg1), 4417 convert (integer_type_node, 4418 ffecom_expr (arg2))); 4419 4420 case FFEINTRIN_impRSHIFT: 4421 return ffecom_2 (RSHIFT_EXPR, tree_type, 4422 ffecom_expr (arg1), 4423 convert (integer_type_node, 4424 ffecom_expr (arg2))); 4425 4426 case FFEINTRIN_impNOT: 4427 return ffecom_1 (BIT_NOT_EXPR, tree_type, ffecom_expr (arg1)); 4428 4429 case FFEINTRIN_impBIT_SIZE: 4430 return convert (tree_type, TYPE_SIZE (arg1_type)); 4431 4432 case FFEINTRIN_impBTEST: 4433 { 4434 ffetargetLogical1 target_true; 4435 ffetargetLogical1 target_false; 4436 tree true_tree; 4437 tree false_tree; 4438 4439 ffetarget_logical1 (&target_true, TRUE); 4440 ffetarget_logical1 (&target_false, FALSE); 4441 if (target_true == 1) 4442 true_tree = convert (tree_type, integer_one_node); 4443 else 4444 true_tree = convert (tree_type, build_int_2 (target_true, 0)); 4445 if (target_false == 0) 4446 false_tree = convert (tree_type, integer_zero_node); 4447 else 4448 false_tree = convert (tree_type, build_int_2 (target_false, 0)); 4449 4450 return 4451 ffecom_3 (COND_EXPR, tree_type, 4452 ffecom_truth_value 4453 (ffecom_2 (EQ_EXPR, integer_type_node, 4454 ffecom_2 (BIT_AND_EXPR, arg1_type, 4455 ffecom_expr (arg1), 4456 ffecom_2 (LSHIFT_EXPR, arg1_type, 4457 convert (arg1_type, 4458 integer_one_node), 4459 convert (integer_type_node, 4460 ffecom_expr (arg2)))), 4461 convert (arg1_type, 4462 integer_zero_node))), 4463 false_tree, 4464 true_tree); 4465 } 4466 4467 case FFEINTRIN_impIBCLR: 4468 return 4469 ffecom_2 (BIT_AND_EXPR, tree_type, 4470 ffecom_expr (arg1), 4471 ffecom_1 (BIT_NOT_EXPR, tree_type, 4472 ffecom_2 (LSHIFT_EXPR, tree_type, 4473 convert (tree_type, 4474 integer_one_node), 4475 convert (integer_type_node, 4476 ffecom_expr (arg2))))); 4477 4478 case FFEINTRIN_impIBITS: 4479 { 4480 tree arg3_tree = ffecom_save_tree (convert (integer_type_node, 4481 ffecom_expr (arg3))); 4482 tree uns_type 4483 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt]; 4484 4485 expr_tree 4486 = ffecom_2 (BIT_AND_EXPR, tree_type, 4487 ffecom_2 (RSHIFT_EXPR, tree_type, 4488 ffecom_expr (arg1), 4489 convert (integer_type_node, 4490 ffecom_expr (arg2))), 4491 convert (tree_type, 4492 ffecom_2 (RSHIFT_EXPR, uns_type, 4493 ffecom_1 (BIT_NOT_EXPR, 4494 uns_type, 4495 convert (uns_type, 4496 integer_zero_node)), 4497 ffecom_2 (MINUS_EXPR, 4498 integer_type_node, 4499 TYPE_SIZE (uns_type), 4500 arg3_tree)))); 4501 /* Fix up, because the RSHIFT_EXPR above can't shift over TYPE_SIZE. */ 4502 expr_tree 4503 = ffecom_3 (COND_EXPR, tree_type, 4504 ffecom_truth_value 4505 (ffecom_2 (NE_EXPR, integer_type_node, 4506 arg3_tree, 4507 integer_zero_node)), 4508 expr_tree, 4509 convert (tree_type, integer_zero_node)); 4510 } 4511 return expr_tree; 4512 4513 case FFEINTRIN_impIBSET: 4514 return 4515 ffecom_2 (BIT_IOR_EXPR, tree_type, 4516 ffecom_expr (arg1), 4517 ffecom_2 (LSHIFT_EXPR, tree_type, 4518 convert (tree_type, integer_one_node), 4519 convert (integer_type_node, 4520 ffecom_expr (arg2)))); 4521 4522 case FFEINTRIN_impISHFT: 4523 { 4524 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1)); 4525 tree arg2_tree = ffecom_save_tree (convert (integer_type_node, 4526 ffecom_expr (arg2))); 4527 tree uns_type 4528 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt]; 4529 4530 expr_tree 4531 = ffecom_3 (COND_EXPR, tree_type, 4532 ffecom_truth_value 4533 (ffecom_2 (GE_EXPR, integer_type_node, 4534 arg2_tree, 4535 integer_zero_node)), 4536 ffecom_2 (LSHIFT_EXPR, tree_type, 4537 arg1_tree, 4538 arg2_tree), 4539 convert (tree_type, 4540 ffecom_2 (RSHIFT_EXPR, uns_type, 4541 convert (uns_type, arg1_tree), 4542 ffecom_1 (NEGATE_EXPR, 4543 integer_type_node, 4544 arg2_tree)))); 4545 /* Fix up, because {L|R}SHIFT_EXPR don't go over TYPE_SIZE bounds. */ 4546 expr_tree 4547 = ffecom_3 (COND_EXPR, tree_type, 4548 ffecom_truth_value 4549 (ffecom_2 (NE_EXPR, integer_type_node, 4550 ffecom_1 (ABS_EXPR, 4551 integer_type_node, 4552 arg2_tree), 4553 TYPE_SIZE (uns_type))), 4554 expr_tree, 4555 convert (tree_type, integer_zero_node)); 4556 /* Make sure SAVE_EXPRs get referenced early enough. */ 4557 expr_tree 4558 = ffecom_2 (COMPOUND_EXPR, tree_type, 4559 convert (void_type_node, arg1_tree), 4560 ffecom_2 (COMPOUND_EXPR, tree_type, 4561 convert (void_type_node, arg2_tree), 4562 expr_tree)); 4563 } 4564 return expr_tree; 4565 4566 case FFEINTRIN_impISHFTC: 4567 { 4568 tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1)); 4569 tree arg2_tree = ffecom_save_tree (convert (integer_type_node, 4570 ffecom_expr (arg2))); 4571 tree arg3_tree = (arg3 == NULL) ? TYPE_SIZE (tree_type) 4572 : ffecom_save_tree (convert (integer_type_node, ffecom_expr (arg3))); 4573 tree shift_neg; 4574 tree shift_pos; 4575 tree mask_arg1; 4576 tree masked_arg1; 4577 tree uns_type 4578 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt]; 4579 4580 mask_arg1 4581 = ffecom_2 (LSHIFT_EXPR, tree_type, 4582 ffecom_1 (BIT_NOT_EXPR, tree_type, 4583 convert (tree_type, integer_zero_node)), 4584 arg3_tree); 4585 /* Fix up, because LSHIFT_EXPR above can't shift over TYPE_SIZE. */ 4586 mask_arg1 4587 = ffecom_3 (COND_EXPR, tree_type, 4588 ffecom_truth_value 4589 (ffecom_2 (NE_EXPR, integer_type_node, 4590 arg3_tree, 4591 TYPE_SIZE (uns_type))), 4592 mask_arg1, 4593 convert (tree_type, integer_zero_node)); 4594 mask_arg1 = ffecom_save_tree (mask_arg1); 4595 masked_arg1 4596 = ffecom_2 (BIT_AND_EXPR, tree_type, 4597 arg1_tree, 4598 ffecom_1 (BIT_NOT_EXPR, tree_type, 4599 mask_arg1)); 4600 masked_arg1 = ffecom_save_tree (masked_arg1); 4601 shift_neg 4602 = ffecom_2 (BIT_IOR_EXPR, tree_type, 4603 convert (tree_type, 4604 ffecom_2 (RSHIFT_EXPR, uns_type, 4605 convert (uns_type, masked_arg1), 4606 ffecom_1 (NEGATE_EXPR, 4607 integer_type_node, 4608 arg2_tree))), 4609 ffecom_2 (LSHIFT_EXPR, tree_type, 4610 arg1_tree, 4611 ffecom_2 (PLUS_EXPR, integer_type_node, 4612 arg2_tree, 4613 arg3_tree))); 4614 shift_pos 4615 = ffecom_2 (BIT_IOR_EXPR, tree_type, 4616 ffecom_2 (LSHIFT_EXPR, tree_type, 4617 arg1_tree, 4618 arg2_tree), 4619 convert (tree_type, 4620 ffecom_2 (RSHIFT_EXPR, uns_type, 4621 convert (uns_type, masked_arg1), 4622 ffecom_2 (MINUS_EXPR, 4623 integer_type_node, 4624 arg3_tree, 4625 arg2_tree)))); 4626 expr_tree 4627 = ffecom_3 (COND_EXPR, tree_type, 4628 ffecom_truth_value 4629 (ffecom_2 (LT_EXPR, integer_type_node, 4630 arg2_tree, 4631 integer_zero_node)), 4632 shift_neg, 4633 shift_pos); 4634 expr_tree 4635 = ffecom_2 (BIT_IOR_EXPR, tree_type, 4636 ffecom_2 (BIT_AND_EXPR, tree_type, 4637 mask_arg1, 4638 arg1_tree), 4639 ffecom_2 (BIT_AND_EXPR, tree_type, 4640 ffecom_1 (BIT_NOT_EXPR, tree_type, 4641 mask_arg1), 4642 expr_tree)); 4643 expr_tree 4644 = ffecom_3 (COND_EXPR, tree_type, 4645 ffecom_truth_value 4646 (ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node, 4647 ffecom_2 (EQ_EXPR, integer_type_node, 4648 ffecom_1 (ABS_EXPR, 4649 integer_type_node, 4650 arg2_tree), 4651 arg3_tree), 4652 ffecom_2 (EQ_EXPR, integer_type_node, 4653 arg2_tree, 4654 integer_zero_node))), 4655 arg1_tree, 4656 expr_tree); 4657 /* Make sure SAVE_EXPRs get referenced early enough. */ 4658 expr_tree 4659 = ffecom_2 (COMPOUND_EXPR, tree_type, 4660 convert (void_type_node, arg1_tree), 4661 ffecom_2 (COMPOUND_EXPR, tree_type, 4662 convert (void_type_node, arg2_tree), 4663 ffecom_2 (COMPOUND_EXPR, tree_type, 4664 convert (void_type_node, 4665 mask_arg1), 4666 ffecom_2 (COMPOUND_EXPR, tree_type, 4667 convert (void_type_node, 4668 masked_arg1), 4669 expr_tree)))); 4670 expr_tree 4671 = ffecom_2 (COMPOUND_EXPR, tree_type, 4672 convert (void_type_node, 4673 arg3_tree), 4674 expr_tree); 4675 } 4676 return expr_tree; 4677 4678 case FFEINTRIN_impLOC: 4679 { 4680 tree arg1_tree = ffecom_expr (arg1); 4681 4682 expr_tree 4683 = convert (tree_type, 4684 ffecom_1 (ADDR_EXPR, 4685 build_pointer_type (TREE_TYPE (arg1_tree)), 4686 arg1_tree)); 4687 } 4688 return expr_tree; 4689 4690 case FFEINTRIN_impMVBITS: 4691 { 4692 tree arg1_tree; 4693 tree arg2_tree; 4694 tree arg3_tree; 4695 ffebld arg4 = ffebld_head (ffebld_trail (list)); 4696 tree arg4_tree; 4697 tree arg4_type; 4698 ffebld arg5 = ffebld_head (ffebld_trail (ffebld_trail (list))); 4699 tree arg5_tree; 4700 tree prep_arg1; 4701 tree prep_arg4; 4702 tree arg5_plus_arg3; 4703 4704 arg2_tree = convert (integer_type_node, 4705 ffecom_expr (arg2)); 4706 arg3_tree = ffecom_save_tree (convert (integer_type_node, 4707 ffecom_expr (arg3))); 4708 arg4_tree = ffecom_expr_rw (NULL_TREE, arg4); 4709 arg4_type = TREE_TYPE (arg4_tree); 4710 4711 arg1_tree = ffecom_save_tree (convert (arg4_type, 4712 ffecom_expr (arg1))); 4713 4714 arg5_tree = ffecom_save_tree (convert (integer_type_node, 4715 ffecom_expr (arg5))); 4716 4717 prep_arg1 4718 = ffecom_2 (LSHIFT_EXPR, arg4_type, 4719 ffecom_2 (BIT_AND_EXPR, arg4_type, 4720 ffecom_2 (RSHIFT_EXPR, arg4_type, 4721 arg1_tree, 4722 arg2_tree), 4723 ffecom_1 (BIT_NOT_EXPR, arg4_type, 4724 ffecom_2 (LSHIFT_EXPR, arg4_type, 4725 ffecom_1 (BIT_NOT_EXPR, 4726 arg4_type, 4727 convert 4728 (arg4_type, 4729 integer_zero_node)), 4730 arg3_tree))), 4731 arg5_tree); 4732 arg5_plus_arg3 4733 = ffecom_save_tree (ffecom_2 (PLUS_EXPR, arg4_type, 4734 arg5_tree, 4735 arg3_tree)); 4736 prep_arg4 4737 = ffecom_2 (LSHIFT_EXPR, arg4_type, 4738 ffecom_1 (BIT_NOT_EXPR, arg4_type, 4739 convert (arg4_type, 4740 integer_zero_node)), 4741 arg5_plus_arg3); 4742 /* Fix up, because LSHIFT_EXPR above can't shift over TYPE_SIZE. */ 4743 prep_arg4 4744 = ffecom_3 (COND_EXPR, arg4_type, 4745 ffecom_truth_value 4746 (ffecom_2 (NE_EXPR, integer_type_node, 4747 arg5_plus_arg3, 4748 convert (TREE_TYPE (arg5_plus_arg3), 4749 TYPE_SIZE (arg4_type)))), 4750 prep_arg4, 4751 convert (arg4_type, integer_zero_node)); 4752 prep_arg4 4753 = ffecom_2 (BIT_AND_EXPR, arg4_type, 4754 arg4_tree, 4755 ffecom_2 (BIT_IOR_EXPR, arg4_type, 4756 prep_arg4, 4757 ffecom_1 (BIT_NOT_EXPR, arg4_type, 4758 ffecom_2 (LSHIFT_EXPR, arg4_type, 4759 ffecom_1 (BIT_NOT_EXPR, 4760 arg4_type, 4761 convert 4762 (arg4_type, 4763 integer_zero_node)), 4764 arg5_tree)))); 4765 prep_arg1 4766 = ffecom_2 (BIT_IOR_EXPR, arg4_type, 4767 prep_arg1, 4768 prep_arg4); 4769 /* Fix up (twice), because LSHIFT_EXPR above 4770 can't shift over TYPE_SIZE. */ 4771 prep_arg1 4772 = ffecom_3 (COND_EXPR, arg4_type, 4773 ffecom_truth_value 4774 (ffecom_2 (NE_EXPR, integer_type_node, 4775 arg3_tree, 4776 convert (TREE_TYPE (arg3_tree), 4777 integer_zero_node))), 4778 prep_arg1, 4779 arg4_tree); 4780 prep_arg1 4781 = ffecom_3 (COND_EXPR, arg4_type, 4782 ffecom_truth_value 4783 (ffecom_2 (NE_EXPR, integer_type_node, 4784 arg3_tree, 4785 convert (TREE_TYPE (arg3_tree), 4786 TYPE_SIZE (arg4_type)))), 4787 prep_arg1, 4788 arg1_tree); 4789 expr_tree 4790 = ffecom_2s (MODIFY_EXPR, void_type_node, 4791 arg4_tree, 4792 prep_arg1); 4793 /* Make sure SAVE_EXPRs get referenced early enough. */ 4794 expr_tree 4795 = ffecom_2 (COMPOUND_EXPR, void_type_node, 4796 arg1_tree, 4797 ffecom_2 (COMPOUND_EXPR, void_type_node, 4798 arg3_tree, 4799 ffecom_2 (COMPOUND_EXPR, void_type_node, 4800 arg5_tree, 4801 ffecom_2 (COMPOUND_EXPR, void_type_node, 4802 arg5_plus_arg3, 4803 expr_tree)))); 4804 expr_tree 4805 = ffecom_2 (COMPOUND_EXPR, void_type_node, 4806 arg4_tree, 4807 expr_tree); 4808 4809 } 4810 return expr_tree; 4811 4812 case FFEINTRIN_impDERF: 4813 case FFEINTRIN_impERF: 4814 case FFEINTRIN_impDERFC: 4815 case FFEINTRIN_impERFC: 4816 break; 4817 4818 case FFEINTRIN_impIARGC: 4819 /* extern int xargc; i__1 = xargc - 1; */ 4820 expr_tree = ffecom_2 (MINUS_EXPR, TREE_TYPE (ffecom_tree_xargc_), 4821 ffecom_tree_xargc_, 4822 convert (TREE_TYPE (ffecom_tree_xargc_), 4823 integer_one_node)); 4824 return expr_tree; 4825 4826 case FFEINTRIN_impSIGNAL_func: 4827 case FFEINTRIN_impSIGNAL_subr: 4828 { 4829 tree arg1_tree; 4830 tree arg2_tree; 4831 tree arg3_tree; 4832 4833 arg1_tree = convert (ffecom_f2c_integer_type_node, 4834 ffecom_expr (arg1)); 4835 arg1_tree = ffecom_1 (ADDR_EXPR, 4836 build_pointer_type (TREE_TYPE (arg1_tree)), 4837 arg1_tree); 4838 4839 /* Pass procedure as a pointer to it, anything else by value. */ 4840 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY) 4841 arg2_tree = convert (integer_type_node, ffecom_expr (arg2)); 4842 else 4843 arg2_tree = ffecom_ptr_to_expr (arg2); 4844 arg2_tree = convert (TREE_TYPE (null_pointer_node), 4845 arg2_tree); 4846 4847 if (arg3 != NULL) 4848 arg3_tree = ffecom_expr_w (NULL_TREE, arg3); 4849 else 4850 arg3_tree = NULL_TREE; 4851 4852 arg1_tree = build_tree_list (NULL_TREE, arg1_tree); 4853 arg2_tree = build_tree_list (NULL_TREE, arg2_tree); 4854 TREE_CHAIN (arg1_tree) = arg2_tree; 4855 4856 expr_tree 4857 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt), 4858 ffecom_gfrt_kindtype (gfrt), 4859 FALSE, 4860 ((codegen_imp == FFEINTRIN_impSIGNAL_subr) ? 4861 NULL_TREE : 4862 tree_type), 4863 arg1_tree, 4864 NULL_TREE, NULL, NULL, NULL_TREE, TRUE, 4865 ffebld_nonter_hook (expr)); 4866 4867 if (arg3_tree != NULL_TREE) 4868 expr_tree 4869 = ffecom_modify (NULL_TREE, arg3_tree, 4870 convert (TREE_TYPE (arg3_tree), 4871 expr_tree)); 4872 } 4873 return expr_tree; 4874 4875 case FFEINTRIN_impALARM: 4876 { 4877 tree arg1_tree; 4878 tree arg2_tree; 4879 tree arg3_tree; 4880 4881 arg1_tree = convert (ffecom_f2c_integer_type_node, 4882 ffecom_expr (arg1)); 4883 arg1_tree = ffecom_1 (ADDR_EXPR, 4884 build_pointer_type (TREE_TYPE (arg1_tree)), 4885 arg1_tree); 4886 4887 /* Pass procedure as a pointer to it, anything else by value. */ 4888 if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY) 4889 arg2_tree = convert (integer_type_node, ffecom_expr (arg2)); 4890 else 4891 arg2_tree = ffecom_ptr_to_expr (arg2); 4892 arg2_tree = convert (TREE_TYPE (null_pointer_node), 4893 arg2_tree); 4894 4895 if (arg3 != NULL) 4896 arg3_tree = ffecom_expr_w (NULL_TREE, arg3); 4897 else 4898 arg3_tree = NULL_TREE; 4899 4900 arg1_tree = build_tree_list (NULL_TREE, arg1_tree); 4901 arg2_tree = build_tree_list (NULL_TREE, arg2_tree); 4902 TREE_CHAIN (arg1_tree) = arg2_tree; 4903 4904 expr_tree 4905 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt), 4906 ffecom_gfrt_kindtype (gfrt), 4907 FALSE, 4908 NULL_TREE, 4909 arg1_tree, 4910 NULL_TREE, NULL, NULL, NULL_TREE, TRUE, 4911 ffebld_nonter_hook (expr)); 4912 4913 if (arg3_tree != NULL_TREE) 4914 expr_tree 4915 = ffecom_modify (NULL_TREE, arg3_tree, 4916 convert (TREE_TYPE (arg3_tree), 4917 expr_tree)); 4918 } 4919 return expr_tree; 4920 4921 case FFEINTRIN_impCHDIR_subr: 4922 case FFEINTRIN_impFDATE_subr: 4923 case FFEINTRIN_impFGET_subr: 4924 case FFEINTRIN_impFPUT_subr: 4925 case FFEINTRIN_impGETCWD_subr: 4926 case FFEINTRIN_impHOSTNM_subr: 4927 case FFEINTRIN_impSYSTEM_subr: 4928 case FFEINTRIN_impUNLINK_subr: 4929 { 4930 tree arg1_len = integer_zero_node; 4931 tree arg1_tree; 4932 tree arg2_tree; 4933 4934 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len); 4935 4936 if (arg2 != NULL) 4937 arg2_tree = ffecom_expr_w (NULL_TREE, arg2); 4938 else 4939 arg2_tree = NULL_TREE; 4940 4941 arg1_tree = build_tree_list (NULL_TREE, arg1_tree); 4942 arg1_len = build_tree_list (NULL_TREE, arg1_len); 4943 TREE_CHAIN (arg1_tree) = arg1_len; 4944 4945 expr_tree 4946 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt), 4947 ffecom_gfrt_kindtype (gfrt), 4948 FALSE, 4949 NULL_TREE, 4950 arg1_tree, 4951 NULL_TREE, NULL, NULL, NULL_TREE, TRUE, 4952 ffebld_nonter_hook (expr)); 4953 4954 if (arg2_tree != NULL_TREE) 4955 expr_tree 4956 = ffecom_modify (NULL_TREE, arg2_tree, 4957 convert (TREE_TYPE (arg2_tree), 4958 expr_tree)); 4959 } 4960 return expr_tree; 4961 4962 case FFEINTRIN_impEXIT: 4963 if (arg1 != NULL) 4964 break; 4965 4966 expr_tree = build_tree_list (NULL_TREE, 4967 ffecom_1 (ADDR_EXPR, 4968 build_pointer_type 4969 (ffecom_integer_type_node), 4970 integer_zero_node)); 4971 4972 return 4973 ffecom_call_ (ffecom_gfrt_tree_ (gfrt), 4974 ffecom_gfrt_kindtype (gfrt), 4975 FALSE, 4976 void_type_node, 4977 expr_tree, 4978 NULL_TREE, NULL, NULL, NULL_TREE, TRUE, 4979 ffebld_nonter_hook (expr)); 4980 4981 case FFEINTRIN_impFLUSH: 4982 if (arg1 == NULL) 4983 gfrt = FFECOM_gfrtFLUSH; 4984 else 4985 gfrt = FFECOM_gfrtFLUSH1; 4986 break; 4987 4988 case FFEINTRIN_impCHMOD_subr: 4989 case FFEINTRIN_impLINK_subr: 4990 case FFEINTRIN_impRENAME_subr: 4991 case FFEINTRIN_impSYMLNK_subr: 4992 { 4993 tree arg1_len = integer_zero_node; 4994 tree arg1_tree; 4995 tree arg2_len = integer_zero_node; 4996 tree arg2_tree; 4997 tree arg3_tree; 4998 4999 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len); 5000 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len); 5001 if (arg3 != NULL) 5002 arg3_tree = ffecom_expr_w (NULL_TREE, arg3); 5003 else 5004 arg3_tree = NULL_TREE; 5005 5006 arg1_tree = build_tree_list (NULL_TREE, arg1_tree); 5007 arg1_len = build_tree_list (NULL_TREE, arg1_len); 5008 arg2_tree = build_tree_list (NULL_TREE, arg2_tree); 5009 arg2_len = build_tree_list (NULL_TREE, arg2_len); 5010 TREE_CHAIN (arg1_tree) = arg2_tree; 5011 TREE_CHAIN (arg2_tree) = arg1_len; 5012 TREE_CHAIN (arg1_len) = arg2_len; 5013 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt), 5014 ffecom_gfrt_kindtype (gfrt), 5015 FALSE, 5016 NULL_TREE, 5017 arg1_tree, 5018 NULL_TREE, NULL, NULL, NULL_TREE, TRUE, 5019 ffebld_nonter_hook (expr)); 5020 if (arg3_tree != NULL_TREE) 5021 expr_tree = ffecom_modify (NULL_TREE, arg3_tree, 5022 convert (TREE_TYPE (arg3_tree), 5023 expr_tree)); 5024 } 5025 return expr_tree; 5026 5027 case FFEINTRIN_impLSTAT_subr: 5028 case FFEINTRIN_impSTAT_subr: 5029 { 5030 tree arg1_len = integer_zero_node; 5031 tree arg1_tree; 5032 tree arg2_tree; 5033 tree arg3_tree; 5034 5035 arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len); 5036 5037 arg2_tree = ffecom_ptr_to_expr (arg2); 5038 5039 if (arg3 != NULL) 5040 arg3_tree = ffecom_expr_w (NULL_TREE, arg3); 5041 else 5042 arg3_tree = NULL_TREE; 5043 5044 arg1_tree = build_tree_list (NULL_TREE, arg1_tree); 5045 arg1_len = build_tree_list (NULL_TREE, arg1_len); 5046 arg2_tree = build_tree_list (NULL_TREE, arg2_tree); 5047 TREE_CHAIN (arg1_tree) = arg2_tree; 5048 TREE_CHAIN (arg2_tree) = arg1_len; 5049 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt), 5050 ffecom_gfrt_kindtype (gfrt), 5051 FALSE, 5052 NULL_TREE, 5053 arg1_tree, 5054 NULL_TREE, NULL, NULL, NULL_TREE, TRUE, 5055 ffebld_nonter_hook (expr)); 5056 if (arg3_tree != NULL_TREE) 5057 expr_tree = ffecom_modify (NULL_TREE, arg3_tree, 5058 convert (TREE_TYPE (arg3_tree), 5059 expr_tree)); 5060 } 5061 return expr_tree; 5062 5063 case FFEINTRIN_impFGETC_subr: 5064 case FFEINTRIN_impFPUTC_subr: 5065 { 5066 tree arg1_tree; 5067 tree arg2_tree; 5068 tree arg2_len = integer_zero_node; 5069 tree arg3_tree; 5070 5071 arg1_tree = convert (ffecom_f2c_integer_type_node, 5072 ffecom_expr (arg1)); 5073 arg1_tree = ffecom_1 (ADDR_EXPR, 5074 build_pointer_type (TREE_TYPE (arg1_tree)), 5075 arg1_tree); 5076 5077 arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len); 5078 if (arg3 != NULL) 5079 arg3_tree = ffecom_expr_w (NULL_TREE, arg3); 5080 else 5081 arg3_tree = NULL_TREE; 5082 5083 arg1_tree = build_tree_list (NULL_TREE, arg1_tree); 5084 arg2_tree = build_tree_list (NULL_TREE, arg2_tree); 5085 arg2_len = build_tree_list (NULL_TREE, arg2_len); 5086 TREE_CHAIN (arg1_tree) = arg2_tree; 5087 TREE_CHAIN (arg2_tree) = arg2_len; 5088 5089 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt), 5090 ffecom_gfrt_kindtype (gfrt), 5091 FALSE, 5092 NULL_TREE, 5093 arg1_tree, 5094 NULL_TREE, NULL, NULL, NULL_TREE, TRUE, 5095 ffebld_nonter_hook (expr)); 5096 if (arg3_tree != NULL_TREE) 5097 expr_tree = ffecom_modify (NULL_TREE, arg3_tree, 5098 convert (TREE_TYPE (arg3_tree), 5099 expr_tree)); 5100 } 5101 return expr_tree; 5102 5103 case FFEINTRIN_impFSTAT_subr: 5104 { 5105 tree arg1_tree; 5106 tree arg2_tree; 5107 tree arg3_tree; 5108 5109 arg1_tree = convert (ffecom_f2c_integer_type_node, 5110 ffecom_expr (arg1)); 5111 arg1_tree = ffecom_1 (ADDR_EXPR, 5112 build_pointer_type (TREE_TYPE (arg1_tree)), 5113 arg1_tree); 5114 5115 arg2_tree = convert (ffecom_f2c_ptr_to_integer_type_node, 5116 ffecom_ptr_to_expr (arg2)); 5117 5118 if (arg3 == NULL) 5119 arg3_tree = NULL_TREE; 5120 else 5121 arg3_tree = ffecom_expr_w (NULL_TREE, arg3); 5122 5123 arg1_tree = build_tree_list (NULL_TREE, arg1_tree); 5124 arg2_tree = build_tree_list (NULL_TREE, arg2_tree); 5125 TREE_CHAIN (arg1_tree) = arg2_tree; 5126 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt), 5127 ffecom_gfrt_kindtype (gfrt), 5128 FALSE, 5129 NULL_TREE, 5130 arg1_tree, 5131 NULL_TREE, NULL, NULL, NULL_TREE, TRUE, 5132 ffebld_nonter_hook (expr)); 5133 if (arg3_tree != NULL_TREE) { 5134 expr_tree = ffecom_modify (NULL_TREE, arg3_tree, 5135 convert (TREE_TYPE (arg3_tree), 5136 expr_tree)); 5137 } 5138 } 5139 return expr_tree; 5140 5141 case FFEINTRIN_impKILL_subr: 5142 { 5143 tree arg1_tree; 5144 tree arg2_tree; 5145 tree arg3_tree; 5146 5147 arg1_tree = convert (ffecom_f2c_integer_type_node, 5148 ffecom_expr (arg1)); 5149 arg1_tree = ffecom_1 (ADDR_EXPR, 5150 build_pointer_type (TREE_TYPE (arg1_tree)), 5151 arg1_tree); 5152 5153 arg2_tree = convert (ffecom_f2c_integer_type_node, 5154 ffecom_expr (arg2)); 5155 arg2_tree = ffecom_1 (ADDR_EXPR, 5156 build_pointer_type (TREE_TYPE (arg2_tree)), 5157 arg2_tree); 5158 5159 if (arg3 == NULL) 5160 arg3_tree = NULL_TREE; 5161 else 5162 arg3_tree = ffecom_expr_w (NULL_TREE, arg3); 5163 5164 arg1_tree = build_tree_list (NULL_TREE, arg1_tree); 5165 arg2_tree = build_tree_list (NULL_TREE, arg2_tree); 5166 TREE_CHAIN (arg1_tree) = arg2_tree; 5167 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt), 5168 ffecom_gfrt_kindtype (gfrt), 5169 FALSE, 5170 NULL_TREE, 5171 arg1_tree, 5172 NULL_TREE, NULL, NULL, NULL_TREE, TRUE, 5173 ffebld_nonter_hook (expr)); 5174 if (arg3_tree != NULL_TREE) { 5175 expr_tree = ffecom_modify (NULL_TREE, arg3_tree, 5176 convert (TREE_TYPE (arg3_tree), 5177 expr_tree)); 5178 } 5179 } 5180 return expr_tree; 5181 5182 case FFEINTRIN_impCTIME_subr: 5183 case FFEINTRIN_impTTYNAM_subr: 5184 { 5185 tree arg1_len = integer_zero_node; 5186 tree arg1_tree; 5187 tree arg2_tree; 5188 5189 arg1_tree = ffecom_arg_ptr_to_expr (arg2, &arg1_len); 5190 5191 arg2_tree = convert (((codegen_imp == FFEINTRIN_impCTIME_subr) ? 5192 ffecom_f2c_longint_type_node : 5193 ffecom_f2c_integer_type_node), 5194 ffecom_expr (arg1)); 5195 arg2_tree = ffecom_1 (ADDR_EXPR, 5196 build_pointer_type (TREE_TYPE (arg2_tree)), 5197 arg2_tree); 5198 5199 arg1_tree = build_tree_list (NULL_TREE, arg1_tree); 5200 arg1_len = build_tree_list (NULL_TREE, arg1_len); 5201 arg2_tree = build_tree_list (NULL_TREE, arg2_tree); 5202 TREE_CHAIN (arg1_len) = arg2_tree; 5203 TREE_CHAIN (arg1_tree) = arg1_len; 5204 5205 expr_tree 5206 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt), 5207 ffecom_gfrt_kindtype (gfrt), 5208 FALSE, 5209 NULL_TREE, 5210 arg1_tree, 5211 NULL_TREE, NULL, NULL, NULL_TREE, TRUE, 5212 ffebld_nonter_hook (expr)); 5213 TREE_SIDE_EFFECTS (expr_tree) = 1; 5214 } 5215 return expr_tree; 5216 5217 case FFEINTRIN_impIRAND: 5218 case FFEINTRIN_impRAND: 5219 /* Arg defaults to 0 (normal random case) */ 5220 { 5221 tree arg1_tree; 5222 5223 if (arg1 == NULL) 5224 arg1_tree = ffecom_integer_zero_node; 5225 else 5226 arg1_tree = ffecom_expr (arg1); 5227 arg1_tree = convert (ffecom_f2c_integer_type_node, 5228 arg1_tree); 5229 arg1_tree = ffecom_1 (ADDR_EXPR, 5230 build_pointer_type (TREE_TYPE (arg1_tree)), 5231 arg1_tree); 5232 arg1_tree = build_tree_list (NULL_TREE, arg1_tree); 5233 5234 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt), 5235 ffecom_gfrt_kindtype (gfrt), 5236 FALSE, 5237 ((codegen_imp == FFEINTRIN_impIRAND) ? 5238 ffecom_f2c_integer_type_node : 5239 ffecom_f2c_real_type_node), 5240 arg1_tree, 5241 dest_tree, dest, dest_used, 5242 NULL_TREE, TRUE, 5243 ffebld_nonter_hook (expr)); 5244 } 5245 return expr_tree; 5246 5247 case FFEINTRIN_impFTELL_subr: 5248 case FFEINTRIN_impUMASK_subr: 5249 { 5250 tree arg1_tree; 5251 tree arg2_tree; 5252 5253 arg1_tree = convert (ffecom_f2c_integer_type_node, 5254 ffecom_expr (arg1)); 5255 arg1_tree = ffecom_1 (ADDR_EXPR, 5256 build_pointer_type (TREE_TYPE (arg1_tree)), 5257 arg1_tree); 5258 5259 if (arg2 == NULL) 5260 arg2_tree = NULL_TREE; 5261 else 5262 arg2_tree = ffecom_expr_w (NULL_TREE, arg2); 5263 5264 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt), 5265 ffecom_gfrt_kindtype (gfrt), 5266 FALSE, 5267 NULL_TREE, 5268 build_tree_list (NULL_TREE, arg1_tree), 5269 NULL_TREE, NULL, NULL, NULL_TREE, 5270 TRUE, 5271 ffebld_nonter_hook (expr)); 5272 if (arg2_tree != NULL_TREE) { 5273 expr_tree = ffecom_modify (NULL_TREE, arg2_tree, 5274 convert (TREE_TYPE (arg2_tree), 5275 expr_tree)); 5276 } 5277 } 5278 return expr_tree; 5279 5280 case FFEINTRIN_impCPU_TIME: 5281 case FFEINTRIN_impSECOND_subr: 5282 { 5283 tree arg1_tree; 5284 5285 arg1_tree = ffecom_expr_w (NULL_TREE, arg1); 5286 5287 expr_tree 5288 = ffecom_call_ (ffecom_gfrt_tree_ (gfrt), 5289 ffecom_gfrt_kindtype (gfrt), 5290 FALSE, 5291 NULL_TREE, 5292 NULL_TREE, 5293 NULL_TREE, NULL, NULL, NULL_TREE, TRUE, 5294 ffebld_nonter_hook (expr)); 5295 5296 expr_tree 5297 = ffecom_modify (NULL_TREE, arg1_tree, 5298 convert (TREE_TYPE (arg1_tree), 5299 expr_tree)); 5300 } 5301 return expr_tree; 5302 5303 case FFEINTRIN_impDTIME_subr: 5304 case FFEINTRIN_impETIME_subr: 5305 { 5306 tree arg1_tree; 5307 tree result_tree; 5308 5309 result_tree = ffecom_expr_w (NULL_TREE, arg2); 5310 5311 arg1_tree = ffecom_ptr_to_expr (arg1); 5312 5313 expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt), 5314 ffecom_gfrt_kindtype (gfrt), 5315 FALSE, 5316 NULL_TREE, 5317 build_tree_list (NULL_TREE, arg1_tree), 5318 NULL_TREE, NULL, NULL, NULL_TREE, 5319 TRUE, 5320 ffebld_nonter_hook (expr)); 5321 expr_tree = ffecom_modify (NULL_TREE, result_tree, 5322 convert (TREE_TYPE (result_tree), 5323 expr_tree)); 5324 } 5325 return expr_tree; 5326 5327 /* Straightforward calls of libf2c routines: */ 5328 case FFEINTRIN_impABORT: 5329 case FFEINTRIN_impACCESS: 5330 case FFEINTRIN_impBESJ0: 5331 case FFEINTRIN_impBESJ1: 5332 case FFEINTRIN_impBESJN: 5333 case FFEINTRIN_impBESY0: 5334 case FFEINTRIN_impBESY1: 5335 case FFEINTRIN_impBESYN: 5336 case FFEINTRIN_impCHDIR_func: 5337 case FFEINTRIN_impCHMOD_func: 5338 case FFEINTRIN_impDATE: 5339 case FFEINTRIN_impDATE_AND_TIME: 5340 case FFEINTRIN_impDBESJ0: 5341 case FFEINTRIN_impDBESJ1: 5342 case FFEINTRIN_impDBESJN: 5343 case FFEINTRIN_impDBESY0: 5344 case FFEINTRIN_impDBESY1: 5345 case FFEINTRIN_impDBESYN: 5346 case FFEINTRIN_impDTIME_func: 5347 case FFEINTRIN_impETIME_func: 5348 case FFEINTRIN_impFGETC_func: 5349 case FFEINTRIN_impFGET_func: 5350 case FFEINTRIN_impFNUM: 5351 case FFEINTRIN_impFPUTC_func: 5352 case FFEINTRIN_impFPUT_func: 5353 case FFEINTRIN_impFSEEK: 5354 case FFEINTRIN_impFSTAT_func: 5355 case FFEINTRIN_impFTELL_func: 5356 case FFEINTRIN_impGERROR: 5357 case FFEINTRIN_impGETARG: 5358 case FFEINTRIN_impGETCWD_func: 5359 case FFEINTRIN_impGETENV: 5360 case FFEINTRIN_impGETGID: 5361 case FFEINTRIN_impGETLOG: 5362 case FFEINTRIN_impGETPID: 5363 case FFEINTRIN_impGETUID: 5364 case FFEINTRIN_impGMTIME: 5365 case FFEINTRIN_impHOSTNM_func: 5366 case FFEINTRIN_impIDATE_unix: 5367 case FFEINTRIN_impIDATE_vxt: 5368 case FFEINTRIN_impIERRNO: 5369 case FFEINTRIN_impISATTY: 5370 case FFEINTRIN_impITIME: 5371 case FFEINTRIN_impKILL_func: 5372 case FFEINTRIN_impLINK_func: 5373 case FFEINTRIN_impLNBLNK: 5374 case FFEINTRIN_impLSTAT_func: 5375 case FFEINTRIN_impLTIME: 5376 case FFEINTRIN_impMCLOCK8: 5377 case FFEINTRIN_impMCLOCK: 5378 case FFEINTRIN_impPERROR: 5379 case FFEINTRIN_impRENAME_func: 5380 case FFEINTRIN_impSECNDS: 5381 case FFEINTRIN_impSECOND_func: 5382 case FFEINTRIN_impSLEEP: 5383 case FFEINTRIN_impSRAND: 5384 case FFEINTRIN_impSTAT_func: 5385 case FFEINTRIN_impSYMLNK_func: 5386 case FFEINTRIN_impSYSTEM_CLOCK: 5387 case FFEINTRIN_impSYSTEM_func: 5388 case FFEINTRIN_impTIME8: 5389 case FFEINTRIN_impTIME_unix: 5390 case FFEINTRIN_impTIME_vxt: 5391 case FFEINTRIN_impUMASK_func: 5392 case FFEINTRIN_impUNLINK_func: 5393 break; 5394 5395 case FFEINTRIN_impCTIME_func: /* CHARACTER functions not handled here. */ 5396 case FFEINTRIN_impFDATE_func: /* CHARACTER functions not handled here. */ 5397 case FFEINTRIN_impTTYNAM_func: /* CHARACTER functions not handled here. */ 5398 case FFEINTRIN_impNONE: 5399 case FFEINTRIN_imp: /* Hush up gcc warning. */ 5400 fprintf (stderr, "No %s implementation.\n", 5401 ffeintrin_name_implementation (ffebld_symter_implementation (ffebld_left (expr)))); 5402 assert ("unimplemented intrinsic" == NULL); 5403 return error_mark_node; 5404 } 5405 5406 assert (gfrt != FFECOM_gfrt); /* Must have an implementation! */ 5407 5408 expr_tree = ffecom_arglist_expr_ (ffecom_gfrt_args_ (gfrt), 5409 ffebld_right (expr)); 5410 5411 return ffecom_call_ (ffecom_gfrt_tree_ (gfrt), ffecom_gfrt_kindtype (gfrt), 5412 (ffe_is_f2c_library () && ffecom_gfrt_complex_[gfrt]), 5413 tree_type, 5414 expr_tree, dest_tree, dest, dest_used, 5415 NULL_TREE, TRUE, 5416 ffebld_nonter_hook (expr)); 5417 5418 /* See bottom of this file for f2c transforms used to determine 5419 many of the above implementations. The info seems to confuse 5420 Emacs's C mode indentation, which is why it's been moved to 5421 the bottom of this source file. */ 5422 } 5423 5424 /* For power (exponentiation) where right-hand operand is type INTEGER, 5425 generate in-line code to do it the fast way (which, if the operand 5426 is a constant, might just mean a series of multiplies). */ 5427 5428 static tree 5429 ffecom_expr_power_integer_ (ffebld expr) 5430 { 5431 tree l = ffecom_expr (ffebld_left (expr)); 5432 tree r = ffecom_expr (ffebld_right (expr)); 5433 tree ltype = TREE_TYPE (l); 5434 tree rtype = TREE_TYPE (r); 5435 tree result = NULL_TREE; 5436 5437 if (l == error_mark_node 5438 || r == error_mark_node) 5439 return error_mark_node; 5440 5441 if (TREE_CODE (r) == INTEGER_CST) 5442 { 5443 int sgn = tree_int_cst_sgn (r); 5444 5445 if (sgn == 0) 5446 return convert (ltype, integer_one_node); 5447 5448 if ((TREE_CODE (ltype) == INTEGER_TYPE) 5449 && (sgn < 0)) 5450 { 5451 /* Reciprocal of integer is either 0, -1, or 1, so after 5452 calculating that (which we leave to the back end to do 5453 or not do optimally), don't bother with any multiplying. */ 5454 5455 result = ffecom_tree_divide_ (ltype, 5456 convert (ltype, integer_one_node), 5457 l, 5458 NULL_TREE, NULL, NULL, NULL_TREE); 5459 r = ffecom_1 (NEGATE_EXPR, 5460 rtype, 5461 r); 5462 if ((TREE_INT_CST_LOW (r) & 1) == 0) 5463 result = ffecom_1 (ABS_EXPR, rtype, 5464 result); 5465 } 5466 5467 /* Generate appropriate series of multiplies, preceded 5468 by divide if the exponent is negative. */ 5469 5470 l = save_expr (l); 5471 5472 if (sgn < 0) 5473 { 5474 l = ffecom_tree_divide_ (ltype, 5475 convert (ltype, integer_one_node), 5476 l, 5477 NULL_TREE, NULL, NULL, 5478 ffebld_nonter_hook (expr)); 5479 r = ffecom_1 (NEGATE_EXPR, rtype, r); 5480 assert (TREE_CODE (r) == INTEGER_CST); 5481 5482 if (tree_int_cst_sgn (r) < 0) 5483 { /* The "most negative" number. */ 5484 r = ffecom_1 (NEGATE_EXPR, rtype, 5485 ffecom_2 (RSHIFT_EXPR, rtype, 5486 r, 5487 integer_one_node)); 5488 l = save_expr (l); 5489 l = ffecom_2 (MULT_EXPR, ltype, 5490 l, 5491 l); 5492 } 5493 } 5494 5495 for (;;) 5496 { 5497 if (TREE_INT_CST_LOW (r) & 1) 5498 { 5499 if (result == NULL_TREE) 5500 result = l; 5501 else 5502 result = ffecom_2 (MULT_EXPR, ltype, 5503 result, 5504 l); 5505 } 5506 5507 r = ffecom_2 (RSHIFT_EXPR, rtype, 5508 r, 5509 integer_one_node); 5510 if (integer_zerop (r)) 5511 break; 5512 assert (TREE_CODE (r) == INTEGER_CST); 5513 5514 l = save_expr (l); 5515 l = ffecom_2 (MULT_EXPR, ltype, 5516 l, 5517 l); 5518 } 5519 return result; 5520 } 5521 5522 /* Though rhs isn't a constant, in-line code cannot be expanded 5523 while transforming dummies 5524 because the back end cannot be easily convinced to generate 5525 stores (MODIFY_EXPR), handle temporaries, and so on before 5526 all the appropriate rtx's have been generated for things like 5527 dummy args referenced in rhs -- which doesn't happen until 5528 store_parm_decls() is called (expand_function_start, I believe, 5529 does the actual rtx-stuffing of PARM_DECLs). 5530 5531 So, in this case, let the caller generate the call to the 5532 run-time-library function to evaluate the power for us. */ 5533 5534 if (ffecom_transform_only_dummies_) 5535 return NULL_TREE; 5536 5537 /* Right-hand operand not a constant, expand in-line code to figure 5538 out how to do the multiplies, &c. 5539 5540 The returned expression is expressed this way in GNU C, where l and 5541 r are the "inputs": 5542 5543 ({ typeof (r) rtmp = r; 5544 typeof (l) ltmp = l; 5545 typeof (l) result; 5546 5547 if (rtmp == 0) 5548 result = 1; 5549 else 5550 { 5551 if ((basetypeof (l) == basetypeof (int)) 5552 && (rtmp < 0)) 5553 { 5554 result = ((typeof (l)) 1) / ltmp; 5555 if ((ltmp < 0) && (((-rtmp) & 1) == 0)) 5556 result = -result; 5557 } 5558 else 5559 { 5560 result = 1; 5561 if ((basetypeof (l) != basetypeof (int)) 5562 && (rtmp < 0)) 5563 { 5564 ltmp = ((typeof (l)) 1) / ltmp; 5565 rtmp = -rtmp; 5566 if (rtmp < 0) 5567 { 5568 rtmp = -(rtmp >> 1); 5569 ltmp *= ltmp; 5570 } 5571 } 5572 for (;;) 5573 { 5574 if (rtmp & 1) 5575 result *= ltmp; 5576 if ((rtmp >>= 1) == 0) 5577 break; 5578 ltmp *= ltmp; 5579 } 5580 } 5581 } 5582 result; 5583 }) 5584 5585 Note that some of the above is compile-time collapsable, such as 5586 the first part of the if statements that checks the base type of 5587 l against int. The if statements are phrased that way to suggest 5588 an easy way to generate the if/else constructs here, knowing that 5589 the back end should (and probably does) eliminate the resulting 5590 dead code (either the int case or the non-int case), something 5591 it couldn't do without the redundant phrasing, requiring explicit 5592 dead-code elimination here, which would be kind of difficult to 5593 read. */ 5594 5595 { 5596 tree rtmp; 5597 tree ltmp; 5598 tree divide; 5599 tree basetypeof_l_is_int; 5600 tree se; 5601 tree t; 5602 5603 basetypeof_l_is_int 5604 = build_int_2 ((TREE_CODE (ltype) == INTEGER_TYPE), 0); 5605 5606 se = expand_start_stmt_expr (/*has_scope=*/1); 5607 5608 ffecom_start_compstmt (); 5609 5610 rtmp = ffecom_make_tempvar ("power_r", rtype, 5611 FFETARGET_charactersizeNONE, -1); 5612 ltmp = ffecom_make_tempvar ("power_l", ltype, 5613 FFETARGET_charactersizeNONE, -1); 5614 result = ffecom_make_tempvar ("power_res", ltype, 5615 FFETARGET_charactersizeNONE, -1); 5616 if (TREE_CODE (ltype) == COMPLEX_TYPE 5617 || TREE_CODE (ltype) == RECORD_TYPE) 5618 divide = ffecom_make_tempvar ("power_div", ltype, 5619 FFETARGET_charactersizeNONE, -1); 5620 else 5621 divide = NULL_TREE; 5622 5623 expand_expr_stmt (ffecom_modify (void_type_node, 5624 rtmp, 5625 r)); 5626 expand_expr_stmt (ffecom_modify (void_type_node, 5627 ltmp, 5628 l)); 5629 expand_start_cond (ffecom_truth_value 5630 (ffecom_2 (EQ_EXPR, integer_type_node, 5631 rtmp, 5632 convert (rtype, integer_zero_node))), 5633 0); 5634 expand_expr_stmt (ffecom_modify (void_type_node, 5635 result, 5636 convert (ltype, integer_one_node))); 5637 expand_start_else (); 5638 if (! integer_zerop (basetypeof_l_is_int)) 5639 { 5640 expand_start_cond (ffecom_2 (LT_EXPR, integer_type_node, 5641 rtmp, 5642 convert (rtype, 5643 integer_zero_node)), 5644 0); 5645 expand_expr_stmt (ffecom_modify (void_type_node, 5646 result, 5647 ffecom_tree_divide_ 5648 (ltype, 5649 convert (ltype, integer_one_node), 5650 ltmp, 5651 NULL_TREE, NULL, NULL, 5652 divide))); 5653 expand_start_cond (ffecom_truth_value 5654 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node, 5655 ffecom_2 (LT_EXPR, integer_type_node, 5656 ltmp, 5657 convert (ltype, 5658 integer_zero_node)), 5659 ffecom_2 (EQ_EXPR, integer_type_node, 5660 ffecom_2 (BIT_AND_EXPR, 5661 rtype, 5662 ffecom_1 (NEGATE_EXPR, 5663 rtype, 5664 rtmp), 5665 convert (rtype, 5666 integer_one_node)), 5667 convert (rtype, 5668 integer_zero_node)))), 5669 0); 5670 expand_expr_stmt (ffecom_modify (void_type_node, 5671 result, 5672 ffecom_1 (NEGATE_EXPR, 5673 ltype, 5674 result))); 5675 expand_end_cond (); 5676 expand_start_else (); 5677 } 5678 expand_expr_stmt (ffecom_modify (void_type_node, 5679 result, 5680 convert (ltype, integer_one_node))); 5681 expand_start_cond (ffecom_truth_value 5682 (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node, 5683 ffecom_truth_value_invert 5684 (basetypeof_l_is_int), 5685 ffecom_2 (LT_EXPR, integer_type_node, 5686 rtmp, 5687 convert (rtype, 5688 integer_zero_node)))), 5689 0); 5690 expand_expr_stmt (ffecom_modify (void_type_node, 5691 ltmp, 5692 ffecom_tree_divide_ 5693 (ltype, 5694 convert (ltype, integer_one_node), 5695 ltmp, 5696 NULL_TREE, NULL, NULL, 5697 divide))); 5698 expand_expr_stmt (ffecom_modify (void_type_node, 5699 rtmp, 5700 ffecom_1 (NEGATE_EXPR, rtype, 5701 rtmp))); 5702 expand_start_cond (ffecom_truth_value 5703 (ffecom_2 (LT_EXPR, integer_type_node, 5704 rtmp, 5705 convert (rtype, integer_zero_node))), 5706 0); 5707 expand_expr_stmt (ffecom_modify (void_type_node, 5708 rtmp, 5709 ffecom_1 (NEGATE_EXPR, rtype, 5710 ffecom_2 (RSHIFT_EXPR, 5711 rtype, 5712 rtmp, 5713 integer_one_node)))); 5714 expand_expr_stmt (ffecom_modify (void_type_node, 5715 ltmp, 5716 ffecom_2 (MULT_EXPR, ltype, 5717 ltmp, 5718 ltmp))); 5719 expand_end_cond (); 5720 expand_end_cond (); 5721 expand_start_loop (1); 5722 expand_start_cond (ffecom_truth_value 5723 (ffecom_2 (BIT_AND_EXPR, rtype, 5724 rtmp, 5725 convert (rtype, integer_one_node))), 5726 0); 5727 expand_expr_stmt (ffecom_modify (void_type_node, 5728 result, 5729 ffecom_2 (MULT_EXPR, ltype, 5730 result, 5731 ltmp))); 5732 expand_end_cond (); 5733 expand_exit_loop_if_false (NULL, 5734 ffecom_truth_value 5735 (ffecom_modify (rtype, 5736 rtmp, 5737 ffecom_2 (RSHIFT_EXPR, 5738 rtype, 5739 rtmp, 5740 integer_one_node)))); 5741 expand_expr_stmt (ffecom_modify (void_type_node, 5742 ltmp, 5743 ffecom_2 (MULT_EXPR, ltype, 5744 ltmp, 5745 ltmp))); 5746 expand_end_loop (); 5747 expand_end_cond (); 5748 if (!integer_zerop (basetypeof_l_is_int)) 5749 expand_end_cond (); 5750 expand_expr_stmt (result); 5751 5752 t = ffecom_end_compstmt (); 5753 5754 result = expand_end_stmt_expr (se); 5755 5756 /* This code comes from c-parse.in, after its expand_end_stmt_expr. */ 5757 5758 if (TREE_CODE (t) == BLOCK) 5759 { 5760 /* Make a BIND_EXPR for the BLOCK already made. */ 5761 result = build (BIND_EXPR, TREE_TYPE (result), 5762 NULL_TREE, result, t); 5763 /* Remove the block from the tree at this point. 5764 It gets put back at the proper place 5765 when the BIND_EXPR is expanded. */ 5766 delete_block (t); 5767 } 5768 else 5769 result = t; 5770 } 5771 5772 return result; 5773 } 5774 5775 /* ffecom_expr_transform_ -- Transform symbols in expr 5776 5777 ffebld expr; // FFE expression. 5778 ffecom_expr_transform_ (expr); 5779 5780 Recursive descent on expr while transforming any untransformed SYMTERs. */ 5781 5782 static void 5783 ffecom_expr_transform_ (ffebld expr) 5784 { 5785 tree t; 5786 ffesymbol s; 5787 5788 tail_recurse: 5789 5790 if (expr == NULL) 5791 return; 5792 5793 switch (ffebld_op (expr)) 5794 { 5795 case FFEBLD_opSYMTER: 5796 s = ffebld_symter (expr); 5797 t = ffesymbol_hook (s).decl_tree; 5798 if ((t == NULL_TREE) 5799 && ((ffesymbol_kind (s) != FFEINFO_kindNONE) 5800 || ((ffesymbol_where (s) != FFEINFO_whereNONE) 5801 && (ffesymbol_where (s) != FFEINFO_whereINTRINSIC)))) 5802 { 5803 s = ffecom_sym_transform_ (s); 5804 t = ffesymbol_hook (s).decl_tree; /* Sfunc expr non-dummy, 5805 DIMENSION expr? */ 5806 } 5807 break; /* Ok if (t == NULL) here. */ 5808 5809 case FFEBLD_opITEM: 5810 ffecom_expr_transform_ (ffebld_head (expr)); 5811 expr = ffebld_trail (expr); 5812 goto tail_recurse; /* :::::::::::::::::::: */ 5813 5814 default: 5815 break; 5816 } 5817 5818 switch (ffebld_arity (expr)) 5819 { 5820 case 2: 5821 ffecom_expr_transform_ (ffebld_left (expr)); 5822 expr = ffebld_right (expr); 5823 goto tail_recurse; /* :::::::::::::::::::: */ 5824 5825 case 1: 5826 expr = ffebld_left (expr); 5827 goto tail_recurse; /* :::::::::::::::::::: */ 5828 5829 default: 5830 break; 5831 } 5832 5833 return; 5834 } 5835 5836 /* Make a type based on info in live f2c.h file. */ 5837 5838 static void 5839 ffecom_f2c_make_type_ (tree *type, int tcode, const char *name) 5840 { 5841 switch (tcode) 5842 { 5843 case FFECOM_f2ccodeCHAR: 5844 *type = make_signed_type (CHAR_TYPE_SIZE); 5845 break; 5846 5847 case FFECOM_f2ccodeSHORT: 5848 *type = make_signed_type (SHORT_TYPE_SIZE); 5849 break; 5850 5851 case FFECOM_f2ccodeINT: 5852 *type = make_signed_type (INT_TYPE_SIZE); 5853 break; 5854 5855 case FFECOM_f2ccodeLONG: 5856 *type = make_signed_type (LONG_TYPE_SIZE); 5857 break; 5858 5859 case FFECOM_f2ccodeLONGLONG: 5860 *type = make_signed_type (LONG_LONG_TYPE_SIZE); 5861 break; 5862 5863 case FFECOM_f2ccodeCHARPTR: 5864 *type = build_pointer_type (DEFAULT_SIGNED_CHAR 5865 ? signed_char_type_node 5866 : unsigned_char_type_node); 5867 break; 5868 5869 case FFECOM_f2ccodeFLOAT: 5870 *type = make_node (REAL_TYPE); 5871 TYPE_PRECISION (*type) = FLOAT_TYPE_SIZE; 5872 layout_type (*type); 5873 break; 5874 5875 case FFECOM_f2ccodeDOUBLE: 5876 *type = make_node (REAL_TYPE); 5877 TYPE_PRECISION (*type) = DOUBLE_TYPE_SIZE; 5878 layout_type (*type); 5879 break; 5880 5881 case FFECOM_f2ccodeLONGDOUBLE: 5882 *type = make_node (REAL_TYPE); 5883 TYPE_PRECISION (*type) = LONG_DOUBLE_TYPE_SIZE; 5884 layout_type (*type); 5885 break; 5886 5887 case FFECOM_f2ccodeTWOREALS: 5888 *type = ffecom_make_complex_type_ (ffecom_f2c_real_type_node); 5889 break; 5890 5891 case FFECOM_f2ccodeTWODOUBLEREALS: 5892 *type = ffecom_make_complex_type_ (ffecom_f2c_doublereal_type_node); 5893 break; 5894 5895 default: 5896 assert ("unexpected FFECOM_f2ccodeXYZZY!" == NULL); 5897 *type = error_mark_node; 5898 return; 5899 } 5900 5901 pushdecl (build_decl (TYPE_DECL, 5902 ffecom_get_invented_identifier ("__g77_f2c_%s", name), 5903 *type)); 5904 } 5905 5906 /* Set the f2c list-directed-I/O code for whatever (integral) type has the 5907 given size. */ 5908 5909 static void 5910 ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size, 5911 int code) 5912 { 5913 int j; 5914 tree t; 5915 5916 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j) 5917 if ((t = ffecom_tree_type[bt][j]) != NULL_TREE 5918 && compare_tree_int (TYPE_SIZE (t), size) == 0) 5919 { 5920 assert (code != -1); 5921 ffecom_f2c_typecode_[bt][j] = code; 5922 code = -1; 5923 } 5924 } 5925 5926 /* Finish up globals after doing all program units in file 5927 5928 Need to handle only uninitialized COMMON areas. */ 5929 5930 static ffeglobal 5931 ffecom_finish_global_ (ffeglobal global) 5932 { 5933 tree cbtype; 5934 tree cbt; 5935 tree size; 5936 5937 if (ffeglobal_type (global) != FFEGLOBAL_typeCOMMON) 5938 return global; 5939 5940 if (ffeglobal_common_init (global)) 5941 return global; 5942 5943 cbt = ffeglobal_hook (global); 5944 if ((cbt == NULL_TREE) 5945 || !ffeglobal_common_have_size (global)) 5946 return global; /* No need to make common, never ref'd. */ 5947 5948 DECL_EXTERNAL (cbt) = 0; 5949 5950 /* Give the array a size now. */ 5951 5952 size = build_int_2 ((ffeglobal_common_size (global) 5953 + ffeglobal_common_pad (global)) - 1, 5954 0); 5955 5956 cbtype = TREE_TYPE (cbt); 5957 TYPE_DOMAIN (cbtype) = build_range_type (integer_type_node, 5958 integer_zero_node, 5959 size); 5960 if (!TREE_TYPE (size)) 5961 TREE_TYPE (size) = TYPE_DOMAIN (cbtype); 5962 layout_type (cbtype); 5963 5964 cbt = start_decl (cbt, FALSE); 5965 assert (cbt == ffeglobal_hook (global)); 5966 5967 finish_decl (cbt, NULL_TREE, FALSE); 5968 5969 return global; 5970 } 5971 5972 /* Finish up any untransformed symbols. */ 5973 5974 static ffesymbol 5975 ffecom_finish_symbol_transform_ (ffesymbol s) 5976 { 5977 if ((s == NULL) || (TREE_CODE (current_function_decl) == ERROR_MARK)) 5978 return s; 5979 5980 /* It's easy to know to transform an untransformed symbol, to make sure 5981 we put out debugging info for it. But COMMON variables, unlike 5982 EQUIVALENCE ones, aren't given declarations in addition to the 5983 tree expressions that specify offsets, because COMMON variables 5984 can be referenced in the outer scope where only dummy arguments 5985 (PARM_DECLs) should really be seen. To be safe, just don't do any 5986 VAR_DECLs for COMMON variables when we transform them for real 5987 use, and therefore we do all the VAR_DECL creating here. */ 5988 5989 if (ffesymbol_hook (s).decl_tree == NULL_TREE) 5990 { 5991 if (ffesymbol_kind (s) != FFEINFO_kindNONE 5992 || (ffesymbol_where (s) != FFEINFO_whereNONE 5993 && ffesymbol_where (s) != FFEINFO_whereINTRINSIC 5994 && ffesymbol_where (s) != FFEINFO_whereDUMMY)) 5995 /* Not transformed, and not CHARACTER*(*), and not a dummy 5996 argument, which can happen only if the entry point names 5997 it "rides in on" are all invalidated for other reasons. */ 5998 s = ffecom_sym_transform_ (s); 5999 } 6000 6001 if ((ffesymbol_where (s) == FFEINFO_whereCOMMON) 6002 && (ffesymbol_hook (s).decl_tree != error_mark_node)) 6003 { 6004 /* This isn't working, at least for dbxout. The .s file looks 6005 okay to me (burley), but in gdb 4.9 at least, the variables 6006 appear to reside somewhere outside of the common area, so 6007 it doesn't make sense to mislead anyone by generating the info 6008 on those variables until this is fixed. NOTE: Same problem 6009 with EQUIVALENCE, sadly...see similar #if later. */ 6010 ffecom_member_phase2_ (ffesymbol_storage (ffesymbol_common (s)), 6011 ffesymbol_storage (s)); 6012 } 6013 6014 return s; 6015 } 6016 6017 /* Append underscore(s) to name before calling get_identifier. "us" 6018 is nonzero if the name already contains an underscore and thus 6019 needs two underscores appended. */ 6020 6021 static tree 6022 ffecom_get_appended_identifier_ (char us, const char *name) 6023 { 6024 int i; 6025 char *newname; 6026 tree id; 6027 6028 newname = xmalloc ((i = strlen (name)) + 1 6029 + ffe_is_underscoring () 6030 + us); 6031 memcpy (newname, name, i); 6032 newname[i] = '_'; 6033 newname[i + us] = '_'; 6034 newname[i + 1 + us] = '\0'; 6035 id = get_identifier (newname); 6036 6037 free (newname); 6038 6039 return id; 6040 } 6041 6042 /* Decide whether to append underscore to name before calling 6043 get_identifier. */ 6044 6045 static tree 6046 ffecom_get_external_identifier_ (ffesymbol s) 6047 { 6048 char us; 6049 const char *name = ffesymbol_text (s); 6050 6051 /* If name is a built-in name, just return it as is. */ 6052 6053 if (!ffe_is_underscoring () 6054 || (strcmp (name, FFETARGET_nameBLANK_COMMON) == 0) 6055 #if FFETARGET_isENFORCED_MAIN_NAME 6056 || (strcmp (name, FFETARGET_nameENFORCED_NAME) == 0) 6057 #else 6058 || (strcmp (name, FFETARGET_nameUNNAMED_MAIN) == 0) 6059 #endif 6060 || (strcmp (name, FFETARGET_nameUNNAMED_BLOCK_DATA) == 0)) 6061 return get_identifier (name); 6062 6063 us = ffe_is_second_underscore () 6064 ? (strchr (name, '_') != NULL) 6065 : 0; 6066 6067 return ffecom_get_appended_identifier_ (us, name); 6068 } 6069 6070 /* Decide whether to append underscore to internal name before calling 6071 get_identifier. 6072 6073 This is for non-external, top-function-context names only. Transform 6074 identifier so it doesn't conflict with the transformed result 6075 of using a _different_ external name. E.g. if "CALL FOO" is 6076 transformed into "FOO_();", then the variable in "FOO_ = 3" 6077 must be transformed into something that does not conflict, since 6078 these two things should be independent. 6079 6080 The transformation is as follows. If the name does not contain 6081 an underscore, there is no possible conflict, so just return. 6082 If the name does contain an underscore, then transform it just 6083 like we transform an external identifier. */ 6084 6085 static tree 6086 ffecom_get_identifier_ (const char *name) 6087 { 6088 /* If name does not contain an underscore, just return it as is. */ 6089 6090 if (!ffe_is_underscoring () 6091 || (strchr (name, '_') == NULL)) 6092 return get_identifier (name); 6093 6094 return ffecom_get_appended_identifier_ (ffe_is_second_underscore (), 6095 name); 6096 } 6097 6098 /* ffecom_gen_sfuncdef_ -- Generate definition of statement function 6099 6100 tree t; 6101 ffesymbol s; // kindFUNCTION, whereIMMEDIATE. 6102 t = ffecom_gen_sfuncdef_(s,ffesymbol_basictype(s), 6103 ffesymbol_kindtype(s)); 6104 6105 Call after setting up containing function and getting trees for all 6106 other symbols. */ 6107 6108 static tree 6109 ffecom_gen_sfuncdef_ (ffesymbol s, ffeinfoBasictype bt, ffeinfoKindtype kt) 6110 { 6111 ffebld expr = ffesymbol_sfexpr (s); 6112 tree type; 6113 tree func; 6114 tree result; 6115 bool charfunc = (bt == FFEINFO_basictypeCHARACTER); 6116 static bool recurse = FALSE; 6117 int old_lineno = lineno; 6118 const char *old_input_filename = input_filename; 6119 6120 ffecom_nested_entry_ = s; 6121 6122 /* For now, we don't have a handy pointer to where the sfunc is actually 6123 defined, though that should be easy to add to an ffesymbol. (The 6124 token/where info available might well point to the place where the type 6125 of the sfunc is declared, especially if that precedes the place where 6126 the sfunc itself is defined, which is typically the case.) We should 6127 put out a null pointer rather than point somewhere wrong, but I want to 6128 see how it works at this point. */ 6129 6130 input_filename = ffesymbol_where_filename (s); 6131 lineno = ffesymbol_where_filelinenum (s); 6132 6133 /* Pretransform the expression so any newly discovered things belong to the 6134 outer program unit, not to the statement function. */ 6135 6136 ffecom_expr_transform_ (expr); 6137 6138 /* Make sure no recursive invocation of this fn (a specific case of failing 6139 to pretransform an sfunc's expression, i.e. where its expression 6140 references another untransformed sfunc) happens. */ 6141 6142 assert (!recurse); 6143 recurse = TRUE; 6144 6145 push_f_function_context (); 6146 6147 if (charfunc) 6148 type = void_type_node; 6149 else 6150 { 6151 type = ffecom_tree_type[bt][kt]; 6152 if (type == NULL_TREE) 6153 type = integer_type_node; /* _sym_exec_transition reports 6154 error. */ 6155 } 6156 6157 start_function (ffecom_get_identifier_ (ffesymbol_text (s)), 6158 build_function_type (type, NULL_TREE), 6159 1, /* nested/inline */ 6160 0); /* TREE_PUBLIC */ 6161 6162 /* We don't worry about COMPLEX return values here, because this is 6163 entirely internal to our code, and gcc has the ability to return COMPLEX 6164 directly as a value. */ 6165 6166 if (charfunc) 6167 { /* Prepend arg for where result goes. */ 6168 tree type; 6169 6170 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt]; 6171 6172 result = ffecom_get_invented_identifier ("__g77_%s", "result"); 6173 6174 ffecom_char_enhance_arg_ (&type, s); /* Ignore returned length. */ 6175 6176 type = build_pointer_type (type); 6177 result = build_decl (PARM_DECL, result, type); 6178 6179 push_parm_decl (result); 6180 } 6181 else 6182 result = NULL_TREE; /* Not ref'd if !charfunc. */ 6183 6184 ffecom_push_dummy_decls_ (ffesymbol_dummyargs (s), TRUE); 6185 6186 store_parm_decls (0); 6187 6188 ffecom_start_compstmt (); 6189 6190 if (expr != NULL) 6191 { 6192 if (charfunc) 6193 { 6194 ffetargetCharacterSize sz = ffesymbol_size (s); 6195 tree result_length; 6196 6197 result_length = build_int_2 (sz, 0); 6198 TREE_TYPE (result_length) = ffecom_f2c_ftnlen_type_node; 6199 6200 ffecom_prepare_let_char_ (sz, expr); 6201 6202 ffecom_prepare_end (); 6203 6204 ffecom_let_char_ (result, result_length, sz, expr); 6205 expand_null_return (); 6206 } 6207 else 6208 { 6209 ffecom_prepare_expr (expr); 6210 6211 ffecom_prepare_end (); 6212 6213 expand_return (ffecom_modify (NULL_TREE, 6214 DECL_RESULT (current_function_decl), 6215 ffecom_expr (expr))); 6216 } 6217 } 6218 6219 ffecom_end_compstmt (); 6220 6221 func = current_function_decl; 6222 finish_function (1); 6223 6224 pop_f_function_context (); 6225 6226 recurse = FALSE; 6227 6228 lineno = old_lineno; 6229 input_filename = old_input_filename; 6230 6231 ffecom_nested_entry_ = NULL; 6232 6233 return func; 6234 } 6235 6236 static const char * 6237 ffecom_gfrt_args_ (ffecomGfrt ix) 6238 { 6239 return ffecom_gfrt_argstring_[ix]; 6240 } 6241 6242 static tree 6243 ffecom_gfrt_tree_ (ffecomGfrt ix) 6244 { 6245 if (ffecom_gfrt_[ix] == NULL_TREE) 6246 ffecom_make_gfrt_ (ix); 6247 6248 return ffecom_1 (ADDR_EXPR, 6249 build_pointer_type (TREE_TYPE (ffecom_gfrt_[ix])), 6250 ffecom_gfrt_[ix]); 6251 } 6252 6253 /* Return initialize-to-zero expression for this VAR_DECL. */ 6254 6255 /* A somewhat evil way to prevent the garbage collector 6256 from collecting 'tree' structures. */ 6257 #define NUM_TRACKED_CHUNK 63 6258 struct tree_ggc_tracker GTY(()) 6259 { 6260 struct tree_ggc_tracker *next; 6261 tree trees[NUM_TRACKED_CHUNK]; 6262 }; 6263 static GTY(()) struct tree_ggc_tracker *tracker_head; 6264 6265 void 6266 ffecom_save_tree_forever (tree t) 6267 { 6268 int i; 6269 if (tracker_head != NULL) 6270 for (i = 0; i < NUM_TRACKED_CHUNK; i++) 6271 if (tracker_head->trees[i] == NULL) 6272 { 6273 tracker_head->trees[i] = t; 6274 return; 6275 } 6276 6277 { 6278 /* Need to allocate a new block. */ 6279 struct tree_ggc_tracker *old_head = tracker_head; 6280 6281 tracker_head = ggc_alloc (sizeof (*tracker_head)); 6282 tracker_head->next = old_head; 6283 tracker_head->trees[0] = t; 6284 for (i = 1; i < NUM_TRACKED_CHUNK; i++) 6285 tracker_head->trees[i] = NULL; 6286 } 6287 } 6288 6289 static tree 6290 ffecom_init_zero_ (tree decl) 6291 { 6292 tree init; 6293 int incremental = TREE_STATIC (decl); 6294 tree type = TREE_TYPE (decl); 6295 6296 if (incremental) 6297 { 6298 make_decl_rtl (decl, NULL); 6299 assemble_variable (decl, TREE_PUBLIC (decl) ? 1 : 0, 0, 1); 6300 } 6301 6302 if ((TREE_CODE (type) != ARRAY_TYPE) 6303 && (TREE_CODE (type) != RECORD_TYPE) 6304 && (TREE_CODE (type) != UNION_TYPE) 6305 && !incremental) 6306 init = convert (type, integer_zero_node); 6307 else if (!incremental) 6308 { 6309 init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE); 6310 TREE_CONSTANT (init) = 1; 6311 TREE_STATIC (init) = 1; 6312 } 6313 else 6314 { 6315 assemble_zeros (int_size_in_bytes (type)); 6316 init = error_mark_node; 6317 } 6318 6319 return init; 6320 } 6321 6322 static tree 6323 ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg, 6324 tree *maybe_tree) 6325 { 6326 tree expr_tree; 6327 tree length_tree; 6328 6329 switch (ffebld_op (arg)) 6330 { 6331 case FFEBLD_opCONTER: /* For F90, check 0-length. */ 6332 if (ffetarget_length_character1 6333 (ffebld_constant_character1 6334 (ffebld_conter (arg))) == 0) 6335 { 6336 *maybe_tree = integer_zero_node; 6337 return convert (tree_type, integer_zero_node); 6338 } 6339 6340 *maybe_tree = integer_one_node; 6341 expr_tree = build_int_2 (*ffetarget_text_character1 6342 (ffebld_constant_character1 6343 (ffebld_conter (arg))), 6344 0); 6345 TREE_TYPE (expr_tree) = tree_type; 6346 return expr_tree; 6347 6348 case FFEBLD_opSYMTER: 6349 case FFEBLD_opARRAYREF: 6350 case FFEBLD_opFUNCREF: 6351 case FFEBLD_opSUBSTR: 6352 ffecom_char_args_ (&expr_tree, &length_tree, arg); 6353 6354 if ((expr_tree == error_mark_node) 6355 || (length_tree == error_mark_node)) 6356 { 6357 *maybe_tree = error_mark_node; 6358 return error_mark_node; 6359 } 6360 6361 if (integer_zerop (length_tree)) 6362 { 6363 *maybe_tree = integer_zero_node; 6364 return convert (tree_type, integer_zero_node); 6365 } 6366 6367 expr_tree 6368 = ffecom_1 (INDIRECT_REF, 6369 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))), 6370 expr_tree); 6371 expr_tree 6372 = ffecom_2 (ARRAY_REF, 6373 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))), 6374 expr_tree, 6375 integer_one_node); 6376 expr_tree = convert (tree_type, expr_tree); 6377 6378 if (TREE_CODE (length_tree) == INTEGER_CST) 6379 *maybe_tree = integer_one_node; 6380 else /* Must check length at run time. */ 6381 *maybe_tree 6382 = ffecom_truth_value 6383 (ffecom_2 (GT_EXPR, integer_type_node, 6384 length_tree, 6385 ffecom_f2c_ftnlen_zero_node)); 6386 return expr_tree; 6387 6388 case FFEBLD_opPAREN: 6389 case FFEBLD_opCONVERT: 6390 if (ffeinfo_size (ffebld_info (arg)) == 0) 6391 { 6392 *maybe_tree = integer_zero_node; 6393 return convert (tree_type, integer_zero_node); 6394 } 6395 return ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg), 6396 maybe_tree); 6397 6398 case FFEBLD_opCONCATENATE: 6399 { 6400 tree maybe_left; 6401 tree maybe_right; 6402 tree expr_left; 6403 tree expr_right; 6404 6405 expr_left = ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg), 6406 &maybe_left); 6407 expr_right = ffecom_intrinsic_ichar_ (tree_type, ffebld_right (arg), 6408 &maybe_right); 6409 *maybe_tree = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node, 6410 maybe_left, 6411 maybe_right); 6412 expr_tree = ffecom_3 (COND_EXPR, tree_type, 6413 maybe_left, 6414 expr_left, 6415 expr_right); 6416 return expr_tree; 6417 } 6418 6419 default: 6420 assert ("bad op in ICHAR" == NULL); 6421 return error_mark_node; 6422 } 6423 } 6424 6425 /* ffecom_intrinsic_len_ -- Return length info for char arg (LEN()) 6426 6427 tree length_arg; 6428 ffebld expr; 6429 length_arg = ffecom_intrinsic_len_ (expr); 6430 6431 Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF 6432 subexpressions by constructing the appropriate tree for the 6433 length-of-character-text argument in a calling sequence. */ 6434 6435 static tree 6436 ffecom_intrinsic_len_ (ffebld expr) 6437 { 6438 ffetargetCharacter1 val; 6439 tree length; 6440 6441 switch (ffebld_op (expr)) 6442 { 6443 case FFEBLD_opCONTER: 6444 val = ffebld_constant_character1 (ffebld_conter (expr)); 6445 length = build_int_2 (ffetarget_length_character1 (val), 0); 6446 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node; 6447 break; 6448 6449 case FFEBLD_opSYMTER: 6450 { 6451 ffesymbol s = ffebld_symter (expr); 6452 tree item; 6453 6454 item = ffesymbol_hook (s).decl_tree; 6455 if (item == NULL_TREE) 6456 { 6457 s = ffecom_sym_transform_ (s); 6458 item = ffesymbol_hook (s).decl_tree; 6459 } 6460 if (ffesymbol_kind (s) == FFEINFO_kindENTITY) 6461 { 6462 if (ffesymbol_size (s) == FFETARGET_charactersizeNONE) 6463 length = ffesymbol_hook (s).length_tree; 6464 else 6465 { 6466 length = build_int_2 (ffesymbol_size (s), 0); 6467 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node; 6468 } 6469 } 6470 else if (item == error_mark_node) 6471 length = error_mark_node; 6472 else /* FFEINFO_kindFUNCTION: */ 6473 length = NULL_TREE; 6474 } 6475 break; 6476 6477 case FFEBLD_opARRAYREF: 6478 length = ffecom_intrinsic_len_ (ffebld_left (expr)); 6479 break; 6480 6481 case FFEBLD_opSUBSTR: 6482 { 6483 ffebld start; 6484 ffebld end; 6485 ffebld thing = ffebld_right (expr); 6486 tree start_tree; 6487 tree end_tree; 6488 6489 assert (ffebld_op (thing) == FFEBLD_opITEM); 6490 start = ffebld_head (thing); 6491 thing = ffebld_trail (thing); 6492 assert (ffebld_trail (thing) == NULL); 6493 end = ffebld_head (thing); 6494 6495 length = ffecom_intrinsic_len_ (ffebld_left (expr)); 6496 6497 if (length == error_mark_node) 6498 break; 6499 6500 if (start == NULL) 6501 { 6502 if (end == NULL) 6503 ; 6504 else 6505 { 6506 length = convert (ffecom_f2c_ftnlen_type_node, 6507 ffecom_expr (end)); 6508 } 6509 } 6510 else 6511 { 6512 start_tree = convert (ffecom_f2c_ftnlen_type_node, 6513 ffecom_expr (start)); 6514 6515 if (start_tree == error_mark_node) 6516 { 6517 length = error_mark_node; 6518 break; 6519 } 6520 6521 if (end == NULL) 6522 { 6523 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node, 6524 ffecom_f2c_ftnlen_one_node, 6525 ffecom_2 (MINUS_EXPR, 6526 ffecom_f2c_ftnlen_type_node, 6527 length, 6528 start_tree)); 6529 } 6530 else 6531 { 6532 end_tree = convert (ffecom_f2c_ftnlen_type_node, 6533 ffecom_expr (end)); 6534 6535 if (end_tree == error_mark_node) 6536 { 6537 length = error_mark_node; 6538 break; 6539 } 6540 6541 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node, 6542 ffecom_f2c_ftnlen_one_node, 6543 ffecom_2 (MINUS_EXPR, 6544 ffecom_f2c_ftnlen_type_node, 6545 end_tree, start_tree)); 6546 } 6547 } 6548 } 6549 break; 6550 6551 case FFEBLD_opCONCATENATE: 6552 length 6553 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node, 6554 ffecom_intrinsic_len_ (ffebld_left (expr)), 6555 ffecom_intrinsic_len_ (ffebld_right (expr))); 6556 break; 6557 6558 case FFEBLD_opFUNCREF: 6559 case FFEBLD_opCONVERT: 6560 length = build_int_2 (ffebld_size (expr), 0); 6561 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node; 6562 break; 6563 6564 default: 6565 assert ("bad op for single char arg expr" == NULL); 6566 length = ffecom_f2c_ftnlen_zero_node; 6567 break; 6568 } 6569 6570 assert (length != NULL_TREE); 6571 6572 return length; 6573 } 6574 6575 /* Handle CHARACTER assignments. 6576 6577 Generates code to do the assignment. Used by ordinary assignment 6578 statement handler ffecom_let_stmt and by statement-function 6579 handler to generate code for a statement function. */ 6580 6581 static void 6582 ffecom_let_char_ (tree dest_tree, tree dest_length, 6583 ffetargetCharacterSize dest_size, ffebld source) 6584 { 6585 ffecomConcatList_ catlist; 6586 tree source_length; 6587 tree source_tree; 6588 tree expr_tree; 6589 6590 if ((dest_tree == error_mark_node) 6591 || (dest_length == error_mark_node)) 6592 return; 6593 6594 assert (dest_tree != NULL_TREE); 6595 assert (dest_length != NULL_TREE); 6596 6597 /* Source might be an opCONVERT, which just means it is a different size 6598 than the destination. Since the underlying implementation here handles 6599 that (directly or via the s_copy or s_cat run-time-library functions), 6600 we don't need the "convenience" of an opCONVERT that tells us to 6601 truncate or blank-pad, particularly since the resulting implementation 6602 would probably be slower than otherwise. */ 6603 6604 while (ffebld_op (source) == FFEBLD_opCONVERT) 6605 source = ffebld_left (source); 6606 6607 catlist = ffecom_concat_list_new_ (source, dest_size); 6608 switch (ffecom_concat_list_count_ (catlist)) 6609 { 6610 case 0: /* Shouldn't happen, but in case it does... */ 6611 ffecom_concat_list_kill_ (catlist); 6612 source_tree = null_pointer_node; 6613 source_length = ffecom_f2c_ftnlen_zero_node; 6614 expr_tree = build_tree_list (NULL_TREE, dest_tree); 6615 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree); 6616 TREE_CHAIN (TREE_CHAIN (expr_tree)) 6617 = build_tree_list (NULL_TREE, dest_length); 6618 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree))) 6619 = build_tree_list (NULL_TREE, source_length); 6620 6621 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE); 6622 TREE_SIDE_EFFECTS (expr_tree) = 1; 6623 6624 expand_expr_stmt (expr_tree); 6625 6626 return; 6627 6628 case 1: /* The (fairly) easy case. */ 6629 ffecom_char_args_ (&source_tree, &source_length, 6630 ffecom_concat_list_expr_ (catlist, 0)); 6631 ffecom_concat_list_kill_ (catlist); 6632 assert (source_tree != NULL_TREE); 6633 assert (source_length != NULL_TREE); 6634 6635 if ((source_tree == error_mark_node) 6636 || (source_length == error_mark_node)) 6637 return; 6638 6639 if (dest_size == 1) 6640 { 6641 dest_tree 6642 = ffecom_1 (INDIRECT_REF, 6643 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE 6644 (dest_tree))), 6645 dest_tree); 6646 dest_tree 6647 = ffecom_2 (ARRAY_REF, 6648 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE 6649 (dest_tree))), 6650 dest_tree, 6651 integer_one_node); 6652 source_tree 6653 = ffecom_1 (INDIRECT_REF, 6654 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE 6655 (source_tree))), 6656 source_tree); 6657 source_tree 6658 = ffecom_2 (ARRAY_REF, 6659 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE 6660 (source_tree))), 6661 source_tree, 6662 integer_one_node); 6663 6664 expr_tree = ffecom_modify (void_type_node, dest_tree, source_tree); 6665 6666 expand_expr_stmt (expr_tree); 6667 6668 return; 6669 } 6670 6671 expr_tree = build_tree_list (NULL_TREE, dest_tree); 6672 TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree); 6673 TREE_CHAIN (TREE_CHAIN (expr_tree)) 6674 = build_tree_list (NULL_TREE, dest_length); 6675 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree))) 6676 = build_tree_list (NULL_TREE, source_length); 6677 6678 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE); 6679 TREE_SIDE_EFFECTS (expr_tree) = 1; 6680 6681 expand_expr_stmt (expr_tree); 6682 6683 return; 6684 6685 default: /* Must actually concatenate things. */ 6686 break; 6687 } 6688 6689 /* Heavy-duty concatenation. */ 6690 6691 { 6692 int count = ffecom_concat_list_count_ (catlist); 6693 int i; 6694 tree lengths; 6695 tree items; 6696 tree length_array; 6697 tree item_array; 6698 tree citem; 6699 tree clength; 6700 6701 { 6702 tree hook; 6703 6704 hook = ffebld_nonter_hook (source); 6705 assert (hook); 6706 assert (TREE_CODE (hook) == TREE_VEC); 6707 assert (TREE_VEC_LENGTH (hook) == 2); 6708 length_array = lengths = TREE_VEC_ELT (hook, 0); 6709 item_array = items = TREE_VEC_ELT (hook, 1); 6710 } 6711 6712 for (i = 0; i < count; ++i) 6713 { 6714 ffecom_char_args_ (&citem, &clength, 6715 ffecom_concat_list_expr_ (catlist, i)); 6716 if ((citem == error_mark_node) 6717 || (clength == error_mark_node)) 6718 { 6719 ffecom_concat_list_kill_ (catlist); 6720 return; 6721 } 6722 6723 items 6724 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items), 6725 ffecom_modify (void_type_node, 6726 ffecom_2 (ARRAY_REF, 6727 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))), 6728 item_array, 6729 build_int_2 (i, 0)), 6730 citem), 6731 items); 6732 lengths 6733 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths), 6734 ffecom_modify (void_type_node, 6735 ffecom_2 (ARRAY_REF, 6736 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))), 6737 length_array, 6738 build_int_2 (i, 0)), 6739 clength), 6740 lengths); 6741 } 6742 6743 expr_tree = build_tree_list (NULL_TREE, dest_tree); 6744 TREE_CHAIN (expr_tree) 6745 = build_tree_list (NULL_TREE, 6746 ffecom_1 (ADDR_EXPR, 6747 build_pointer_type (TREE_TYPE (items)), 6748 items)); 6749 TREE_CHAIN (TREE_CHAIN (expr_tree)) 6750 = build_tree_list (NULL_TREE, 6751 ffecom_1 (ADDR_EXPR, 6752 build_pointer_type (TREE_TYPE (lengths)), 6753 lengths)); 6754 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree))) 6755 = build_tree_list 6756 (NULL_TREE, 6757 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node, 6758 convert (ffecom_f2c_ftnlen_type_node, 6759 build_int_2 (count, 0)))); 6760 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))) 6761 = build_tree_list (NULL_TREE, dest_length); 6762 6763 expr_tree = ffecom_call_gfrt (FFECOM_gfrtCAT, expr_tree, NULL_TREE); 6764 TREE_SIDE_EFFECTS (expr_tree) = 1; 6765 6766 expand_expr_stmt (expr_tree); 6767 } 6768 6769 ffecom_concat_list_kill_ (catlist); 6770 } 6771 6772 /* ffecom_make_gfrt_ -- Make initial info for run-time routine 6773 6774 ffecomGfrt ix; 6775 ffecom_make_gfrt_(ix); 6776 6777 Assumes gfrt_[ix] is NULL_TREE, and replaces it with the FUNCTION_DECL 6778 for the indicated run-time routine (ix). */ 6779 6780 static void 6781 ffecom_make_gfrt_ (ffecomGfrt ix) 6782 { 6783 tree t; 6784 tree ttype; 6785 6786 switch (ffecom_gfrt_type_[ix]) 6787 { 6788 case FFECOM_rttypeVOID_: 6789 ttype = void_type_node; 6790 break; 6791 6792 case FFECOM_rttypeVOIDSTAR_: 6793 ttype = TREE_TYPE (null_pointer_node); /* `void *'. */ 6794 break; 6795 6796 case FFECOM_rttypeFTNINT_: 6797 ttype = ffecom_f2c_ftnint_type_node; 6798 break; 6799 6800 case FFECOM_rttypeINTEGER_: 6801 ttype = ffecom_f2c_integer_type_node; 6802 break; 6803 6804 case FFECOM_rttypeLONGINT_: 6805 ttype = ffecom_f2c_longint_type_node; 6806 break; 6807 6808 case FFECOM_rttypeLOGICAL_: 6809 ttype = ffecom_f2c_logical_type_node; 6810 break; 6811 6812 case FFECOM_rttypeREAL_F2C_: 6813 ttype = double_type_node; 6814 break; 6815 6816 case FFECOM_rttypeREAL_GNU_: 6817 ttype = float_type_node; 6818 break; 6819 6820 case FFECOM_rttypeCOMPLEX_F2C_: 6821 ttype = void_type_node; 6822 break; 6823 6824 case FFECOM_rttypeCOMPLEX_GNU_: 6825 ttype = ffecom_f2c_complex_type_node; 6826 break; 6827 6828 case FFECOM_rttypeDOUBLE_: 6829 ttype = double_type_node; 6830 break; 6831 6832 case FFECOM_rttypeDOUBLEREAL_: 6833 ttype = ffecom_f2c_doublereal_type_node; 6834 break; 6835 6836 case FFECOM_rttypeDBLCMPLX_F2C_: 6837 ttype = void_type_node; 6838 break; 6839 6840 case FFECOM_rttypeDBLCMPLX_GNU_: 6841 ttype = ffecom_f2c_doublecomplex_type_node; 6842 break; 6843 6844 case FFECOM_rttypeCHARACTER_: 6845 ttype = void_type_node; 6846 break; 6847 6848 default: 6849 ttype = NULL; 6850 assert ("bad rttype" == NULL); 6851 break; 6852 } 6853 6854 ttype = build_function_type (ttype, NULL_TREE); 6855 t = build_decl (FUNCTION_DECL, 6856 get_identifier (ffecom_gfrt_name_[ix]), 6857 ttype); 6858 DECL_EXTERNAL (t) = 1; 6859 TREE_READONLY (t) = ffecom_gfrt_const_[ix] ? 1 : 0; 6860 TREE_PUBLIC (t) = 1; 6861 TREE_THIS_VOLATILE (t) = ffecom_gfrt_volatile_[ix] ? 1 : 0; 6862 6863 /* Sanity check: A function that's const cannot be volatile. */ 6864 6865 assert (ffecom_gfrt_const_[ix] ? !ffecom_gfrt_volatile_[ix] : 1); 6866 6867 /* Sanity check: A function that's const cannot return complex. */ 6868 6869 assert (ffecom_gfrt_const_[ix] ? !ffecom_gfrt_complex_[ix] : 1); 6870 6871 t = start_decl (t, TRUE); 6872 6873 finish_decl (t, NULL_TREE, TRUE); 6874 6875 ffecom_gfrt_[ix] = t; 6876 } 6877 6878 /* Phase 1 pass over each member of a COMMON/EQUIVALENCE group. */ 6879 6880 static void 6881 ffecom_member_phase1_ (ffestorag mst UNUSED, ffestorag st) 6882 { 6883 ffesymbol s = ffestorag_symbol (st); 6884 6885 if (ffesymbol_namelisted (s)) 6886 ffecom_member_namelisted_ = TRUE; 6887 } 6888 6889 /* Phase 2 pass over each member of a COMMON/EQUIVALENCE group. Declare 6890 the member so debugger will see it. Otherwise nobody should be 6891 referencing the member. */ 6892 6893 static void 6894 ffecom_member_phase2_ (ffestorag mst, ffestorag st) 6895 { 6896 ffesymbol s; 6897 tree t; 6898 tree mt; 6899 tree type; 6900 6901 if ((mst == NULL) 6902 || ((mt = ffestorag_hook (mst)) == NULL) 6903 || (mt == error_mark_node)) 6904 return; 6905 6906 if ((st == NULL) 6907 || ((s = ffestorag_symbol (st)) == NULL)) 6908 return; 6909 6910 type = ffecom_type_localvar_ (s, 6911 ffesymbol_basictype (s), 6912 ffesymbol_kindtype (s)); 6913 if (type == error_mark_node) 6914 return; 6915 6916 t = build_decl (VAR_DECL, 6917 ffecom_get_identifier_ (ffesymbol_text (s)), 6918 type); 6919 6920 TREE_STATIC (t) = TREE_STATIC (mt); 6921 DECL_INITIAL (t) = NULL_TREE; 6922 TREE_ASM_WRITTEN (t) = 1; 6923 TREE_USED (t) = 1; 6924 6925 SET_DECL_RTL (t, 6926 gen_rtx (MEM, TYPE_MODE (type), 6927 plus_constant (XEXP (DECL_RTL (mt), 0), 6928 ffestorag_modulo (mst) 6929 + ffestorag_offset (st) 6930 - ffestorag_offset (mst)))); 6931 6932 t = start_decl (t, FALSE); 6933 6934 finish_decl (t, NULL_TREE, FALSE); 6935 } 6936 6937 /* Prepare source expression for assignment into a destination perhaps known 6938 to be of a specific size. */ 6939 6940 static void 6941 ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size, ffebld source) 6942 { 6943 ffecomConcatList_ catlist; 6944 int count; 6945 int i; 6946 tree ltmp; 6947 tree itmp; 6948 tree tempvar = NULL_TREE; 6949 6950 while (ffebld_op (source) == FFEBLD_opCONVERT) 6951 source = ffebld_left (source); 6952 6953 catlist = ffecom_concat_list_new_ (source, dest_size); 6954 count = ffecom_concat_list_count_ (catlist); 6955 6956 if (count >= 2) 6957 { 6958 ltmp 6959 = ffecom_make_tempvar ("let_char_len", ffecom_f2c_ftnlen_type_node, 6960 FFETARGET_charactersizeNONE, count); 6961 itmp 6962 = ffecom_make_tempvar ("let_char_item", ffecom_f2c_address_type_node, 6963 FFETARGET_charactersizeNONE, count); 6964 6965 tempvar = make_tree_vec (2); 6966 TREE_VEC_ELT (tempvar, 0) = ltmp; 6967 TREE_VEC_ELT (tempvar, 1) = itmp; 6968 } 6969 6970 for (i = 0; i < count; ++i) 6971 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist, i)); 6972 6973 ffecom_concat_list_kill_ (catlist); 6974 6975 if (tempvar) 6976 { 6977 ffebld_nonter_set_hook (source, tempvar); 6978 current_binding_level->prep_state = 1; 6979 } 6980 } 6981 6982 /* ffecom_push_dummy_decls_ -- Transform dummy args, push parm decls in order 6983 6984 Ignores STAR (alternate-return) dummies. All other get exec-transitioned 6985 (which generates their trees) and then their trees get push_parm_decl'd. 6986 6987 The second arg is TRUE if the dummies are for a statement function, in 6988 which case lengths are not pushed for character arguments (since they are 6989 always known by both the caller and the callee, though the code allows 6990 for someday permitting CHAR*(*) stmtfunc dummies). */ 6991 6992 static void 6993 ffecom_push_dummy_decls_ (ffebld dummy_list, bool stmtfunc) 6994 { 6995 ffebld dummy; 6996 ffebld dumlist; 6997 ffesymbol s; 6998 tree parm; 6999 7000 ffecom_transform_only_dummies_ = TRUE; 7001 7002 /* First push the parms corresponding to actual dummy "contents". */ 7003 7004 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist)) 7005 { 7006 dummy = ffebld_head (dumlist); 7007 switch (ffebld_op (dummy)) 7008 { 7009 case FFEBLD_opSTAR: 7010 case FFEBLD_opANY: 7011 continue; /* Forget alternate returns. */ 7012 7013 default: 7014 break; 7015 } 7016 assert (ffebld_op (dummy) == FFEBLD_opSYMTER); 7017 s = ffebld_symter (dummy); 7018 parm = ffesymbol_hook (s).decl_tree; 7019 if (parm == NULL_TREE) 7020 { 7021 s = ffecom_sym_transform_ (s); 7022 parm = ffesymbol_hook (s).decl_tree; 7023 assert (parm != NULL_TREE); 7024 } 7025 if (parm != error_mark_node) 7026 push_parm_decl (parm); 7027 } 7028 7029 /* Then, for CHARACTER dummies, push the parms giving their lengths. */ 7030 7031 for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist)) 7032 { 7033 dummy = ffebld_head (dumlist); 7034 switch (ffebld_op (dummy)) 7035 { 7036 case FFEBLD_opSTAR: 7037 case FFEBLD_opANY: 7038 continue; /* Forget alternate returns, they mean 7039 NOTHING! */ 7040 7041 default: 7042 break; 7043 } 7044 s = ffebld_symter (dummy); 7045 if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER) 7046 continue; /* Only looking for CHARACTER arguments. */ 7047 if (stmtfunc && (ffesymbol_size (s) != FFETARGET_charactersizeNONE)) 7048 continue; /* Stmtfunc arg with known size needs no 7049 length param. */ 7050 if (ffesymbol_kind (s) != FFEINFO_kindENTITY) 7051 continue; /* Only looking for variables and arrays. */ 7052 parm = ffesymbol_hook (s).length_tree; 7053 assert (parm != NULL_TREE); 7054 if (parm != error_mark_node) 7055 push_parm_decl (parm); 7056 } 7057 7058 ffecom_transform_only_dummies_ = FALSE; 7059 } 7060 7061 /* ffecom_start_progunit_ -- Beginning of program unit 7062 7063 Does GNU back end stuff necessary to teach it about the start of its 7064 equivalent of a Fortran program unit. */ 7065 7066 static void 7067 ffecom_start_progunit_ () 7068 { 7069 ffesymbol fn = ffecom_primary_entry_; 7070 ffebld arglist; 7071 tree id; /* Identifier (name) of function. */ 7072 tree type; /* Type of function. */ 7073 tree result; /* Result of function. */ 7074 ffeinfoBasictype bt; 7075 ffeinfoKindtype kt; 7076 ffeglobal g; 7077 ffeglobalType gt; 7078 ffeglobalType egt = FFEGLOBAL_type; 7079 bool charfunc; 7080 bool cmplxfunc; 7081 bool altentries = (ffecom_num_entrypoints_ != 0); 7082 bool multi 7083 = altentries 7084 && (ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION) 7085 && (ffecom_master_bt_ == FFEINFO_basictypeNONE); 7086 bool main_program = FALSE; 7087 int old_lineno = lineno; 7088 const char *old_input_filename = input_filename; 7089 7090 assert (fn != NULL); 7091 assert (ffesymbol_hook (fn).decl_tree == NULL_TREE); 7092 7093 input_filename = ffesymbol_where_filename (fn); 7094 lineno = ffesymbol_where_filelinenum (fn); 7095 7096 switch (ffecom_primary_entry_kind_) 7097 { 7098 case FFEINFO_kindPROGRAM: 7099 main_program = TRUE; 7100 gt = FFEGLOBAL_typeMAIN; 7101 bt = FFEINFO_basictypeNONE; 7102 kt = FFEINFO_kindtypeNONE; 7103 type = ffecom_tree_fun_type_void; 7104 charfunc = FALSE; 7105 cmplxfunc = FALSE; 7106 break; 7107 7108 case FFEINFO_kindBLOCKDATA: 7109 gt = FFEGLOBAL_typeBDATA; 7110 bt = FFEINFO_basictypeNONE; 7111 kt = FFEINFO_kindtypeNONE; 7112 type = ffecom_tree_fun_type_void; 7113 charfunc = FALSE; 7114 cmplxfunc = FALSE; 7115 break; 7116 7117 case FFEINFO_kindFUNCTION: 7118 gt = FFEGLOBAL_typeFUNC; 7119 egt = FFEGLOBAL_typeEXT; 7120 bt = ffesymbol_basictype (fn); 7121 kt = ffesymbol_kindtype (fn); 7122 if (bt == FFEINFO_basictypeNONE) 7123 { 7124 ffeimplic_establish_symbol (fn); 7125 if (ffesymbol_funcresult (fn) != NULL) 7126 ffeimplic_establish_symbol (ffesymbol_funcresult (fn)); 7127 bt = ffesymbol_basictype (fn); 7128 kt = ffesymbol_kindtype (fn); 7129 } 7130 7131 if (multi) 7132 charfunc = cmplxfunc = FALSE; 7133 else if (bt == FFEINFO_basictypeCHARACTER) 7134 charfunc = TRUE, cmplxfunc = FALSE; 7135 else if ((bt == FFEINFO_basictypeCOMPLEX) 7136 && ffesymbol_is_f2c (fn) 7137 && !altentries) 7138 charfunc = FALSE, cmplxfunc = TRUE; 7139 else 7140 charfunc = cmplxfunc = FALSE; 7141 7142 if (multi || charfunc) 7143 type = ffecom_tree_fun_type_void; 7144 else if (ffesymbol_is_f2c (fn) && !altentries) 7145 type = ffecom_tree_fun_type[bt][kt]; 7146 else 7147 type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE); 7148 7149 if ((type == NULL_TREE) 7150 || (TREE_TYPE (type) == NULL_TREE)) 7151 type = ffecom_tree_fun_type_void; /* _sym_exec_transition. */ 7152 break; 7153 7154 case FFEINFO_kindSUBROUTINE: 7155 gt = FFEGLOBAL_typeSUBR; 7156 egt = FFEGLOBAL_typeEXT; 7157 bt = FFEINFO_basictypeNONE; 7158 kt = FFEINFO_kindtypeNONE; 7159 if (ffecom_is_altreturning_) 7160 type = ffecom_tree_subr_type; 7161 else 7162 type = ffecom_tree_fun_type_void; 7163 charfunc = FALSE; 7164 cmplxfunc = FALSE; 7165 break; 7166 7167 default: 7168 assert ("say what??" == NULL); 7169 /* Fall through. */ 7170 case FFEINFO_kindANY: 7171 gt = FFEGLOBAL_typeANY; 7172 bt = FFEINFO_basictypeNONE; 7173 kt = FFEINFO_kindtypeNONE; 7174 type = error_mark_node; 7175 charfunc = FALSE; 7176 cmplxfunc = FALSE; 7177 break; 7178 } 7179 7180 if (altentries) 7181 { 7182 id = ffecom_get_invented_identifier ("__g77_masterfun_%s", 7183 ffesymbol_text (fn)); 7184 } 7185 #if FFETARGET_isENFORCED_MAIN 7186 else if (main_program) 7187 id = get_identifier (FFETARGET_nameENFORCED_MAIN_NAME); 7188 #endif 7189 else 7190 id = ffecom_get_external_identifier_ (fn); 7191 7192 start_function (id, 7193 type, 7194 0, /* nested/inline */ 7195 !altentries); /* TREE_PUBLIC */ 7196 7197 TREE_USED (current_function_decl) = 1; /* Avoid spurious warning if altentries. */ 7198 7199 if (!altentries 7200 && ((g = ffesymbol_global (fn)) != NULL) 7201 && ((ffeglobal_type (g) == gt) 7202 || (ffeglobal_type (g) == egt))) 7203 { 7204 ffeglobal_set_hook (g, current_function_decl); 7205 } 7206 7207 /* Arg handling needs exec-transitioned ffesymbols to work with. But 7208 exec-transitioning needs current_function_decl to be filled in. So we 7209 do these things in two phases. */ 7210 7211 if (altentries) 7212 { /* 1st arg identifies which entrypoint. */ 7213 ffecom_which_entrypoint_decl_ 7214 = build_decl (PARM_DECL, 7215 ffecom_get_invented_identifier ("__g77_%s", 7216 "which_entrypoint"), 7217 integer_type_node); 7218 push_parm_decl (ffecom_which_entrypoint_decl_); 7219 } 7220 7221 if (charfunc 7222 || cmplxfunc 7223 || multi) 7224 { /* Arg for result (return value). */ 7225 tree type; 7226 tree length; 7227 7228 if (charfunc) 7229 type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt]; 7230 else if (cmplxfunc) 7231 type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt]; 7232 else 7233 type = ffecom_multi_type_node_; 7234 7235 result = ffecom_get_invented_identifier ("__g77_%s", "result"); 7236 7237 /* Make length arg _and_ enhance type info for CHAR arg itself. */ 7238 7239 if (charfunc) 7240 length = ffecom_char_enhance_arg_ (&type, fn); 7241 else 7242 length = NULL_TREE; /* Not ref'd if !charfunc. */ 7243 7244 type = build_pointer_type (type); 7245 result = build_decl (PARM_DECL, result, type); 7246 7247 push_parm_decl (result); 7248 if (multi) 7249 ffecom_multi_retval_ = result; 7250 else 7251 ffecom_func_result_ = result; 7252 7253 if (charfunc) 7254 { 7255 push_parm_decl (length); 7256 ffecom_func_length_ = length; 7257 } 7258 } 7259 7260 if (ffecom_primary_entry_is_proc_) 7261 { 7262 if (altentries) 7263 arglist = ffecom_master_arglist_; 7264 else 7265 arglist = ffesymbol_dummyargs (fn); 7266 ffecom_push_dummy_decls_ (arglist, FALSE); 7267 } 7268 7269 if (TREE_CODE (current_function_decl) != ERROR_MARK) 7270 store_parm_decls (main_program ? 1 : 0); 7271 7272 ffecom_start_compstmt (); 7273 /* Disallow temp vars at this level. */ 7274 current_binding_level->prep_state = 2; 7275 7276 lineno = old_lineno; 7277 input_filename = old_input_filename; 7278 7279 /* This handles any symbols still untransformed, in case -g specified. 7280 This used to be done in ffecom_finish_progunit, but it turns out to 7281 be necessary to do it here so that statement functions are 7282 expanded before code. But don't bother for BLOCK DATA. */ 7283 7284 if (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA) 7285 ffesymbol_drive (ffecom_finish_symbol_transform_); 7286 } 7287 7288 /* ffecom_sym_transform_ -- Transform FFE sym into backend sym 7289 7290 ffesymbol s; 7291 ffecom_sym_transform_(s); 7292 7293 The ffesymbol_hook info for s is updated with appropriate backend info 7294 on the symbol. */ 7295 7296 static ffesymbol 7297 ffecom_sym_transform_ (ffesymbol s) 7298 { 7299 tree t; /* Transformed thingy. */ 7300 tree tlen; /* Length if CHAR*(*). */ 7301 bool addr; /* Is t the address of the thingy? */ 7302 ffeinfoBasictype bt; 7303 ffeinfoKindtype kt; 7304 ffeglobal g; 7305 int old_lineno = lineno; 7306 const char *old_input_filename = input_filename; 7307 7308 /* Must ensure special ASSIGN variables are declared at top of outermost 7309 block, else they'll end up in the innermost block when their first 7310 ASSIGN is seen, which leaves them out of scope when they're the 7311 subject of a GOTO or I/O statement. 7312 7313 We make this variable even if -fugly-assign. Just let it go unused, 7314 in case it turns out there are cases where we really want to use this 7315 variable anyway (e.g. ASSIGN to INTEGER*2 variable). */ 7316 7317 if (! ffecom_transform_only_dummies_ 7318 && ffesymbol_assigned (s) 7319 && ! ffesymbol_hook (s).assign_tree) 7320 s = ffecom_sym_transform_assign_ (s); 7321 7322 if (ffesymbol_sfdummyparent (s) == NULL) 7323 { 7324 input_filename = ffesymbol_where_filename (s); 7325 lineno = ffesymbol_where_filelinenum (s); 7326 } 7327 else 7328 { 7329 ffesymbol sf = ffesymbol_sfdummyparent (s); 7330 7331 input_filename = ffesymbol_where_filename (sf); 7332 lineno = ffesymbol_where_filelinenum (sf); 7333 } 7334 7335 bt = ffeinfo_basictype (ffebld_info (s)); 7336 kt = ffeinfo_kindtype (ffebld_info (s)); 7337 7338 t = NULL_TREE; 7339 tlen = NULL_TREE; 7340 addr = FALSE; 7341 7342 switch (ffesymbol_kind (s)) 7343 { 7344 case FFEINFO_kindNONE: 7345 switch (ffesymbol_where (s)) 7346 { 7347 case FFEINFO_whereDUMMY: /* Subroutine or function. */ 7348 assert (ffecom_transform_only_dummies_); 7349 7350 /* Before 0.4, this could be ENTITY/DUMMY, but see 7351 ffestu_sym_end_transition -- no longer true (in particular, if 7352 it could be an ENTITY, it _will_ be made one, so that 7353 possibility won't come through here). So we never make length 7354 arg for CHARACTER type. */ 7355 7356 t = build_decl (PARM_DECL, 7357 ffecom_get_identifier_ (ffesymbol_text (s)), 7358 ffecom_tree_ptr_to_subr_type); 7359 DECL_ARTIFICIAL (t) = 1; 7360 addr = TRUE; 7361 break; 7362 7363 case FFEINFO_whereGLOBAL: /* Subroutine or function. */ 7364 assert (!ffecom_transform_only_dummies_); 7365 7366 if (((g = ffesymbol_global (s)) != NULL) 7367 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR) 7368 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC) 7369 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)) 7370 && (ffeglobal_hook (g) != NULL_TREE) 7371 && ffe_is_globals ()) 7372 { 7373 t = ffeglobal_hook (g); 7374 break; 7375 } 7376 7377 t = build_decl (FUNCTION_DECL, 7378 ffecom_get_external_identifier_ (s), 7379 ffecom_tree_subr_type); /* Assume subr. */ 7380 DECL_EXTERNAL (t) = 1; 7381 TREE_PUBLIC (t) = 1; 7382 7383 t = start_decl (t, FALSE); 7384 finish_decl (t, NULL_TREE, FALSE); 7385 7386 if ((g != NULL) 7387 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR) 7388 || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC) 7389 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))) 7390 ffeglobal_set_hook (g, t); 7391 7392 ffecom_save_tree_forever (t); 7393 7394 break; 7395 7396 default: 7397 assert ("NONE where unexpected" == NULL); 7398 /* Fall through. */ 7399 case FFEINFO_whereANY: 7400 break; 7401 } 7402 break; 7403 7404 case FFEINFO_kindENTITY: 7405 switch (ffeinfo_where (ffesymbol_info (s))) 7406 { 7407 7408 case FFEINFO_whereCONSTANT: 7409 /* ~~Debugging info needed? */ 7410 assert (!ffecom_transform_only_dummies_); 7411 t = error_mark_node; /* Shouldn't ever see this in expr. */ 7412 break; 7413 7414 case FFEINFO_whereLOCAL: 7415 assert (!ffecom_transform_only_dummies_); 7416 7417 { 7418 ffestorag st = ffesymbol_storage (s); 7419 tree type; 7420 7421 if ((st != NULL) 7422 && (ffestorag_size (st) == 0)) 7423 { 7424 t = error_mark_node; 7425 break; 7426 } 7427 7428 type = ffecom_type_localvar_ (s, bt, kt); 7429 7430 if (type == error_mark_node) 7431 { 7432 t = error_mark_node; 7433 break; 7434 } 7435 7436 if ((st != NULL) 7437 && (ffestorag_parent (st) != NULL)) 7438 { /* Child of EQUIVALENCE parent. */ 7439 ffestorag est; 7440 tree et; 7441 ffetargetOffset offset; 7442 7443 est = ffestorag_parent (st); 7444 ffecom_transform_equiv_ (est); 7445 7446 et = ffestorag_hook (est); 7447 assert (et != NULL_TREE); 7448 7449 if (! TREE_STATIC (et)) 7450 put_var_into_stack (et, /*rescan=*/true); 7451 7452 offset = ffestorag_modulo (est) 7453 + ffestorag_offset (ffesymbol_storage (s)) 7454 - ffestorag_offset (est); 7455 7456 ffecom_debug_kludge_ (et, "EQUIVALENCE", s, type, offset); 7457 7458 /* (t_type *) (((char *) &et) + offset) */ 7459 7460 t = convert (string_type_node, /* (char *) */ 7461 ffecom_1 (ADDR_EXPR, 7462 build_pointer_type (TREE_TYPE (et)), 7463 et)); 7464 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t), 7465 t, 7466 build_int_2 (offset, 0)); 7467 t = convert (build_pointer_type (type), 7468 t); 7469 TREE_CONSTANT (t) = staticp (et); 7470 7471 addr = TRUE; 7472 } 7473 else 7474 { 7475 tree initexpr; 7476 bool init = ffesymbol_is_init (s); 7477 7478 t = build_decl (VAR_DECL, 7479 ffecom_get_identifier_ (ffesymbol_text (s)), 7480 type); 7481 7482 if (init 7483 || ffesymbol_namelisted (s) 7484 #ifdef FFECOM_sizeMAXSTACKITEM 7485 || ((st != NULL) 7486 && (ffestorag_size (st) > FFECOM_sizeMAXSTACKITEM)) 7487 #endif 7488 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM) 7489 && (ffecom_primary_entry_kind_ 7490 != FFEINFO_kindBLOCKDATA) 7491 && (ffesymbol_is_save (s) || ffe_is_saveall ()))) 7492 TREE_STATIC (t) = !ffesymbol_attr (s, FFESYMBOL_attrADJUSTABLE); 7493 else 7494 TREE_STATIC (t) = 0; /* No need to make static. */ 7495 7496 if (init || ffe_is_init_local_zero ()) 7497 DECL_INITIAL (t) = error_mark_node; 7498 7499 /* Keep -Wunused from complaining about var if it 7500 is used as sfunc arg or DATA implied-DO. */ 7501 if (ffesymbol_attrs (s) & FFESYMBOL_attrsSFARG) 7502 DECL_IN_SYSTEM_HEADER (t) = 1; 7503 7504 t = start_decl (t, FALSE); 7505 7506 if (init) 7507 { 7508 if (ffesymbol_init (s) != NULL) 7509 initexpr = ffecom_expr (ffesymbol_init (s)); 7510 else 7511 initexpr = ffecom_init_zero_ (t); 7512 } 7513 else if (ffe_is_init_local_zero ()) 7514 initexpr = ffecom_init_zero_ (t); 7515 else 7516 initexpr = NULL_TREE; /* Not ref'd if !init. */ 7517 7518 finish_decl (t, initexpr, FALSE); 7519 7520 if (st != NULL && DECL_SIZE (t) != error_mark_node) 7521 { 7522 assert (TREE_CODE (DECL_SIZE_UNIT (t)) == INTEGER_CST); 7523 assert (0 == compare_tree_int (DECL_SIZE_UNIT (t), 7524 ffestorag_size (st))); 7525 } 7526 } 7527 } 7528 break; 7529 7530 case FFEINFO_whereRESULT: 7531 assert (!ffecom_transform_only_dummies_); 7532 7533 if (bt == FFEINFO_basictypeCHARACTER) 7534 { /* Result is already in list of dummies, use 7535 it (& length). */ 7536 t = ffecom_func_result_; 7537 tlen = ffecom_func_length_; 7538 addr = TRUE; 7539 break; 7540 } 7541 if ((ffecom_num_entrypoints_ == 0) 7542 && (bt == FFEINFO_basictypeCOMPLEX) 7543 && (ffesymbol_is_f2c (ffecom_primary_entry_))) 7544 { /* Result is already in list of dummies, use 7545 it. */ 7546 t = ffecom_func_result_; 7547 addr = TRUE; 7548 break; 7549 } 7550 if (ffecom_func_result_ != NULL_TREE) 7551 { 7552 t = ffecom_func_result_; 7553 break; 7554 } 7555 if ((ffecom_num_entrypoints_ != 0) 7556 && (ffecom_master_bt_ == FFEINFO_basictypeNONE)) 7557 { 7558 assert (ffecom_multi_retval_ != NULL_TREE); 7559 t = ffecom_1 (INDIRECT_REF, ffecom_multi_type_node_, 7560 ffecom_multi_retval_); 7561 t = ffecom_2 (COMPONENT_REF, ffecom_tree_type[bt][kt], 7562 t, ffecom_multi_fields_[bt][kt]); 7563 7564 break; 7565 } 7566 7567 t = build_decl (VAR_DECL, 7568 ffecom_get_identifier_ (ffesymbol_text (s)), 7569 ffecom_tree_type[bt][kt]); 7570 TREE_STATIC (t) = 0; /* Put result on stack. */ 7571 t = start_decl (t, FALSE); 7572 finish_decl (t, NULL_TREE, FALSE); 7573 7574 ffecom_func_result_ = t; 7575 7576 break; 7577 7578 case FFEINFO_whereDUMMY: 7579 { 7580 tree type; 7581 ffebld dl; 7582 ffebld dim; 7583 tree low; 7584 tree high; 7585 tree old_sizes; 7586 bool adjustable = FALSE; /* Conditionally adjustable? */ 7587 7588 type = ffecom_tree_type[bt][kt]; 7589 if (ffesymbol_sfdummyparent (s) != NULL) 7590 { 7591 if (current_function_decl == ffecom_outer_function_decl_) 7592 { /* Exec transition before sfunc 7593 context; get it later. */ 7594 break; 7595 } 7596 t = ffecom_get_identifier_ (ffesymbol_text 7597 (ffesymbol_sfdummyparent (s))); 7598 } 7599 else 7600 t = ffecom_get_identifier_ (ffesymbol_text (s)); 7601 7602 assert (ffecom_transform_only_dummies_); 7603 7604 old_sizes = get_pending_sizes (); 7605 put_pending_sizes (old_sizes); 7606 7607 if (bt == FFEINFO_basictypeCHARACTER) 7608 tlen = ffecom_char_enhance_arg_ (&type, s); 7609 type = ffecom_check_size_overflow_ (s, type, TRUE); 7610 7611 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl)) 7612 { 7613 if (type == error_mark_node) 7614 break; 7615 7616 dim = ffebld_head (dl); 7617 assert (ffebld_op (dim) == FFEBLD_opBOUNDS); 7618 if ((ffebld_left (dim) == NULL) || ffecom_doing_entry_) 7619 low = ffecom_integer_one_node; 7620 else 7621 low = ffecom_expr (ffebld_left (dim)); 7622 assert (ffebld_right (dim) != NULL); 7623 if ((ffebld_op (ffebld_right (dim)) == FFEBLD_opSTAR) 7624 || ffecom_doing_entry_) 7625 { 7626 /* Used to just do high=low. But for ffecom_tree_ 7627 canonize_ref_, it probably is important to correctly 7628 assess the size. E.g. given COMPLEX C(*),CFUNC and 7629 C(2)=CFUNC(C), overlap can happen, while it can't 7630 for, say, C(1)=CFUNC(C(2)). */ 7631 /* Even more recently used to set to INT_MAX, but that 7632 broke when some overflow checking went into the back 7633 end. Now we just leave the upper bound unspecified. */ 7634 high = NULL; 7635 } 7636 else 7637 high = ffecom_expr (ffebld_right (dim)); 7638 7639 /* Determine whether array is conditionally adjustable, 7640 to decide whether back-end magic is needed. 7641 7642 Normally the front end uses the back-end function 7643 variable_size to wrap SAVE_EXPR's around expressions 7644 affecting the size/shape of an array so that the 7645 size/shape info doesn't change during execution 7646 of the compiled code even though variables and 7647 functions referenced in those expressions might. 7648 7649 variable_size also makes sure those saved expressions 7650 get evaluated immediately upon entry to the 7651 compiled procedure -- the front end normally doesn't 7652 have to worry about that. 7653 7654 However, there is a problem with this that affects 7655 g77's implementation of entry points, and that is 7656 that it is _not_ true that each invocation of the 7657 compiled procedure is permitted to evaluate 7658 array size/shape info -- because it is possible 7659 that, for some invocations, that info is invalid (in 7660 which case it is "promised" -- i.e. a violation of 7661 the Fortran standard -- that the compiled code 7662 won't reference the array or its size/shape 7663 during that particular invocation). 7664 7665 To phrase this in C terms, consider this gcc function: 7666 7667 void foo (int *n, float (*a)[*n]) 7668 { 7669 // a is "pointer to array ...", fyi. 7670 } 7671 7672 Suppose that, for some invocations, it is permitted 7673 for a caller of foo to do this: 7674 7675 foo (NULL, NULL); 7676 7677 Now the _written_ code for foo can take such a call 7678 into account by either testing explicitly for whether 7679 (a == NULL) || (n == NULL) -- presumably it is 7680 not permitted to reference *a in various fashions 7681 if (n == NULL) I suppose -- or it can avoid it by 7682 looking at other info (other arguments, static/global 7683 data, etc.). 7684 7685 However, this won't work in gcc 2.5.8 because it'll 7686 automatically emit the code to save the "*n" 7687 expression, which'll yield a NULL dereference for 7688 the "foo (NULL, NULL)" call, something the code 7689 for foo cannot prevent. 7690 7691 g77 definitely needs to avoid executing such 7692 code anytime the pointer to the adjustable array 7693 is NULL, because even if its bounds expressions 7694 don't have any references to possible "absent" 7695 variables like "*n" -- say all variable references 7696 are to COMMON variables, i.e. global (though in C, 7697 local static could actually make sense) -- the 7698 expressions could yield other run-time problems 7699 for allowably "dead" values in those variables. 7700 7701 For example, let's consider a more complicated 7702 version of foo: 7703 7704 extern int i; 7705 extern int j; 7706 7707 void foo (float (*a)[i/j]) 7708 { 7709 ... 7710 } 7711 7712 The above is (essentially) quite valid for Fortran 7713 but, again, for a call like "foo (NULL);", it is 7714 permitted for i and j to be undefined when the 7715 call is made. If j happened to be zero, for 7716 example, emitting the code to evaluate "i/j" 7717 could result in a run-time error. 7718 7719 Offhand, though I don't have my F77 or F90 7720 standards handy, it might even be valid for a 7721 bounds expression to contain a function reference, 7722 in which case I doubt it is permitted for an 7723 implementation to invoke that function in the 7724 Fortran case involved here (invocation of an 7725 alternate ENTRY point that doesn't have the adjustable 7726 array as one of its arguments). 7727 7728 So, the code that the compiler would normally emit 7729 to preevaluate the size/shape info for an 7730 adjustable array _must not_ be executed at run time 7731 in certain cases. Specifically, for Fortran, 7732 the case is when the pointer to the adjustable 7733 array == NULL. (For gnu-ish C, it might be nice 7734 for the source code itself to specify an expression 7735 that, if TRUE, inhibits execution of the code. Or 7736 reverse the sense for elegance.) 7737 7738 (Note that g77 could use a different test than NULL, 7739 actually, since it happens to always pass an 7740 integer to the called function that specifies which 7741 entry point is being invoked. Hmm, this might 7742 solve the next problem.) 7743 7744 One way a user could, I suppose, write "foo" so 7745 it works is to insert COND_EXPR's for the 7746 size/shape info so the dangerous stuff isn't 7747 actually done, as in: 7748 7749 void foo (int *n, float (*a)[(a == NULL) ? 0 : *n]) 7750 { 7751 ... 7752 } 7753 7754 The next problem is that the front end needs to 7755 be able to tell the back end about the array's 7756 decl _before_ it tells it about the conditional 7757 expression to inhibit evaluation of size/shape info, 7758 as shown above. 7759 7760 To solve this, the front end needs to be able 7761 to give the back end the expression to inhibit 7762 generation of the preevaluation code _after_ 7763 it makes the decl for the adjustable array. 7764 7765 Until then, the above example using the COND_EXPR 7766 doesn't pass muster with gcc because the "(a == NULL)" 7767 part has a reference to "a", which is still 7768 undefined at that point. 7769 7770 g77 will therefore use a different mechanism in the 7771 meantime. */ 7772 7773 if (!adjustable 7774 && ((TREE_CODE (low) != INTEGER_CST) 7775 || (high && TREE_CODE (high) != INTEGER_CST))) 7776 adjustable = TRUE; 7777 7778 #if 0 /* Old approach -- see below. */ 7779 if (TREE_CODE (low) != INTEGER_CST) 7780 low = ffecom_3 (COND_EXPR, integer_type_node, 7781 ffecom_adjarray_passed_ (s), 7782 low, 7783 ffecom_integer_zero_node); 7784 7785 if (high && TREE_CODE (high) != INTEGER_CST) 7786 high = ffecom_3 (COND_EXPR, integer_type_node, 7787 ffecom_adjarray_passed_ (s), 7788 high, 7789 ffecom_integer_zero_node); 7790 #endif 7791 7792 /* ~~~gcc/stor-layout.c (layout_type) should do this, 7793 probably. Fixes 950302-1.f. */ 7794 7795 if (TREE_CODE (low) != INTEGER_CST) 7796 low = variable_size (low); 7797 7798 /* ~~~Similarly, this fixes dumb0.f. The C front end 7799 does this, which is why dumb0.c would work. */ 7800 7801 if (high && TREE_CODE (high) != INTEGER_CST) 7802 high = variable_size (high); 7803 7804 type 7805 = build_array_type 7806 (type, 7807 build_range_type (ffecom_integer_type_node, 7808 low, high)); 7809 type = ffecom_check_size_overflow_ (s, type, TRUE); 7810 } 7811 7812 if (type == error_mark_node) 7813 { 7814 t = error_mark_node; 7815 break; 7816 } 7817 7818 if ((ffesymbol_sfdummyparent (s) == NULL) 7819 || (ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER)) 7820 { 7821 type = build_pointer_type (type); 7822 addr = TRUE; 7823 } 7824 7825 t = build_decl (PARM_DECL, t, type); 7826 DECL_ARTIFICIAL (t) = 1; 7827 7828 /* If this arg is present in every entry point's list of 7829 dummy args, then we're done. */ 7830 7831 if (ffesymbol_numentries (s) 7832 == (ffecom_num_entrypoints_ + 1)) 7833 break; 7834 7835 #if 1 7836 7837 /* If variable_size in stor-layout has been called during 7838 the above, then get_pending_sizes should have the 7839 yet-to-be-evaluated saved expressions pending. 7840 Make the whole lot of them get emitted, conditionally 7841 on whether the array decl ("t" above) is not NULL. */ 7842 7843 { 7844 tree sizes = get_pending_sizes (); 7845 tree tem; 7846 7847 for (tem = sizes; 7848 tem != old_sizes; 7849 tem = TREE_CHAIN (tem)) 7850 { 7851 tree temv = TREE_VALUE (tem); 7852 7853 if (sizes == tem) 7854 sizes = temv; 7855 else 7856 sizes 7857 = ffecom_2 (COMPOUND_EXPR, 7858 TREE_TYPE (sizes), 7859 temv, 7860 sizes); 7861 } 7862 7863 if (sizes != tem) 7864 { 7865 sizes 7866 = ffecom_3 (COND_EXPR, 7867 TREE_TYPE (sizes), 7868 ffecom_2 (NE_EXPR, 7869 integer_type_node, 7870 t, 7871 null_pointer_node), 7872 sizes, 7873 convert (TREE_TYPE (sizes), 7874 integer_zero_node)); 7875 sizes = ffecom_save_tree (sizes); 7876 7877 sizes 7878 = tree_cons (NULL_TREE, sizes, tem); 7879 } 7880 7881 if (sizes) 7882 put_pending_sizes (sizes); 7883 } 7884 7885 #else 7886 #if 0 7887 if (adjustable 7888 && (ffesymbol_numentries (s) 7889 != ffecom_num_entrypoints_ + 1)) 7890 DECL_SOMETHING (t) 7891 = ffecom_2 (NE_EXPR, integer_type_node, 7892 t, 7893 null_pointer_node); 7894 #else 7895 #if 0 7896 if (adjustable 7897 && (ffesymbol_numentries (s) 7898 != ffecom_num_entrypoints_ + 1)) 7899 { 7900 ffebad_start (FFEBAD_MISSING_ADJARRAY_UNSUPPORTED); 7901 ffebad_here (0, ffesymbol_where_line (s), 7902 ffesymbol_where_column (s)); 7903 ffebad_string (ffesymbol_text (s)); 7904 ffebad_finish (); 7905 } 7906 #endif 7907 #endif 7908 #endif 7909 } 7910 break; 7911 7912 case FFEINFO_whereCOMMON: 7913 { 7914 ffesymbol cs; 7915 ffeglobal cg; 7916 tree ct; 7917 ffestorag st = ffesymbol_storage (s); 7918 tree type; 7919 7920 cs = ffesymbol_common (s); /* The COMMON area itself. */ 7921 if (st != NULL) /* Else not laid out. */ 7922 { 7923 ffecom_transform_common_ (cs); 7924 st = ffesymbol_storage (s); 7925 } 7926 7927 type = ffecom_type_localvar_ (s, bt, kt); 7928 7929 cg = ffesymbol_global (cs); /* The global COMMON info. */ 7930 if ((cg == NULL) 7931 || (ffeglobal_type (cg) != FFEGLOBAL_typeCOMMON)) 7932 ct = NULL_TREE; 7933 else 7934 ct = ffeglobal_hook (cg); /* The common area's tree. */ 7935 7936 if ((ct == NULL_TREE) 7937 || (st == NULL) 7938 || (type == error_mark_node)) 7939 t = error_mark_node; 7940 else 7941 { 7942 ffetargetOffset offset; 7943 ffestorag cst; 7944 7945 cst = ffestorag_parent (st); 7946 assert (cst == ffesymbol_storage (cs)); 7947 7948 offset = ffestorag_modulo (cst) 7949 + ffestorag_offset (st) 7950 - ffestorag_offset (cst); 7951 7952 ffecom_debug_kludge_ (ct, "COMMON", s, type, offset); 7953 7954 /* (t_type *) (((char *) &ct) + offset) */ 7955 7956 t = convert (string_type_node, /* (char *) */ 7957 ffecom_1 (ADDR_EXPR, 7958 build_pointer_type (TREE_TYPE (ct)), 7959 ct)); 7960 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t), 7961 t, 7962 build_int_2 (offset, 0)); 7963 t = convert (build_pointer_type (type), 7964 t); 7965 TREE_CONSTANT (t) = 1; 7966 7967 addr = TRUE; 7968 } 7969 } 7970 break; 7971 7972 case FFEINFO_whereIMMEDIATE: 7973 case FFEINFO_whereGLOBAL: 7974 case FFEINFO_whereFLEETING: 7975 case FFEINFO_whereFLEETING_CADDR: 7976 case FFEINFO_whereFLEETING_IADDR: 7977 case FFEINFO_whereINTRINSIC: 7978 case FFEINFO_whereCONSTANT_SUBOBJECT: 7979 default: 7980 assert ("ENTITY where unheard of" == NULL); 7981 /* Fall through. */ 7982 case FFEINFO_whereANY: 7983 t = error_mark_node; 7984 break; 7985 } 7986 break; 7987 7988 case FFEINFO_kindFUNCTION: 7989 switch (ffeinfo_where (ffesymbol_info (s))) 7990 { 7991 case FFEINFO_whereLOCAL: /* Me. */ 7992 assert (!ffecom_transform_only_dummies_); 7993 t = current_function_decl; 7994 break; 7995 7996 case FFEINFO_whereGLOBAL: 7997 assert (!ffecom_transform_only_dummies_); 7998 7999 if (((g = ffesymbol_global (s)) != NULL) 8000 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC) 8001 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)) 8002 && (ffeglobal_hook (g) != NULL_TREE) 8003 && ffe_is_globals ()) 8004 { 8005 t = ffeglobal_hook (g); 8006 break; 8007 } 8008 8009 if (ffesymbol_is_f2c (s) 8010 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT)) 8011 t = ffecom_tree_fun_type[bt][kt]; 8012 else 8013 t = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE); 8014 8015 t = build_decl (FUNCTION_DECL, 8016 ffecom_get_external_identifier_ (s), 8017 t); 8018 DECL_EXTERNAL (t) = 1; 8019 TREE_PUBLIC (t) = 1; 8020 8021 t = start_decl (t, FALSE); 8022 finish_decl (t, NULL_TREE, FALSE); 8023 8024 if ((g != NULL) 8025 && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC) 8026 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))) 8027 ffeglobal_set_hook (g, t); 8028 8029 ffecom_save_tree_forever (t); 8030 8031 break; 8032 8033 case FFEINFO_whereDUMMY: 8034 assert (ffecom_transform_only_dummies_); 8035 8036 if (ffesymbol_is_f2c (s) 8037 && (ffesymbol_where (s) != FFEINFO_whereCONSTANT)) 8038 t = ffecom_tree_ptr_to_fun_type[bt][kt]; 8039 else 8040 t = build_pointer_type 8041 (build_function_type (ffecom_tree_type[bt][kt], NULL_TREE)); 8042 8043 t = build_decl (PARM_DECL, 8044 ffecom_get_identifier_ (ffesymbol_text (s)), 8045 t); 8046 DECL_ARTIFICIAL (t) = 1; 8047 addr = TRUE; 8048 break; 8049 8050 case FFEINFO_whereCONSTANT: /* Statement function. */ 8051 assert (!ffecom_transform_only_dummies_); 8052 t = ffecom_gen_sfuncdef_ (s, bt, kt); 8053 break; 8054 8055 case FFEINFO_whereINTRINSIC: 8056 assert (!ffecom_transform_only_dummies_); 8057 break; /* Let actual references generate their 8058 decls. */ 8059 8060 default: 8061 assert ("FUNCTION where unheard of" == NULL); 8062 /* Fall through. */ 8063 case FFEINFO_whereANY: 8064 t = error_mark_node; 8065 break; 8066 } 8067 break; 8068 8069 case FFEINFO_kindSUBROUTINE: 8070 switch (ffeinfo_where (ffesymbol_info (s))) 8071 { 8072 case FFEINFO_whereLOCAL: /* Me. */ 8073 assert (!ffecom_transform_only_dummies_); 8074 t = current_function_decl; 8075 break; 8076 8077 case FFEINFO_whereGLOBAL: 8078 assert (!ffecom_transform_only_dummies_); 8079 8080 if (((g = ffesymbol_global (s)) != NULL) 8081 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR) 8082 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)) 8083 && (ffeglobal_hook (g) != NULL_TREE) 8084 && ffe_is_globals ()) 8085 { 8086 t = ffeglobal_hook (g); 8087 break; 8088 } 8089 8090 t = build_decl (FUNCTION_DECL, 8091 ffecom_get_external_identifier_ (s), 8092 ffecom_tree_subr_type); 8093 DECL_EXTERNAL (t) = 1; 8094 TREE_PUBLIC (t) = 1; 8095 8096 t = start_decl (t, ffe_is_globals ()); 8097 finish_decl (t, NULL_TREE, ffe_is_globals ()); 8098 8099 if ((g != NULL) 8100 && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR) 8101 || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))) 8102 ffeglobal_set_hook (g, t); 8103 8104 ffecom_save_tree_forever (t); 8105 8106 break; 8107 8108 case FFEINFO_whereDUMMY: 8109 assert (ffecom_transform_only_dummies_); 8110 8111 t = build_decl (PARM_DECL, 8112 ffecom_get_identifier_ (ffesymbol_text (s)), 8113 ffecom_tree_ptr_to_subr_type); 8114 DECL_ARTIFICIAL (t) = 1; 8115 addr = TRUE; 8116 break; 8117 8118 case FFEINFO_whereINTRINSIC: 8119 assert (!ffecom_transform_only_dummies_); 8120 break; /* Let actual references generate their 8121 decls. */ 8122 8123 default: 8124 assert ("SUBROUTINE where unheard of" == NULL); 8125 /* Fall through. */ 8126 case FFEINFO_whereANY: 8127 t = error_mark_node; 8128 break; 8129 } 8130 break; 8131 8132 case FFEINFO_kindPROGRAM: 8133 switch (ffeinfo_where (ffesymbol_info (s))) 8134 { 8135 case FFEINFO_whereLOCAL: /* Me. */ 8136 assert (!ffecom_transform_only_dummies_); 8137 t = current_function_decl; 8138 break; 8139 8140 case FFEINFO_whereCOMMON: 8141 case FFEINFO_whereDUMMY: 8142 case FFEINFO_whereGLOBAL: 8143 case FFEINFO_whereRESULT: 8144 case FFEINFO_whereFLEETING: 8145 case FFEINFO_whereFLEETING_CADDR: 8146 case FFEINFO_whereFLEETING_IADDR: 8147 case FFEINFO_whereIMMEDIATE: 8148 case FFEINFO_whereINTRINSIC: 8149 case FFEINFO_whereCONSTANT: 8150 case FFEINFO_whereCONSTANT_SUBOBJECT: 8151 default: 8152 assert ("PROGRAM where unheard of" == NULL); 8153 /* Fall through. */ 8154 case FFEINFO_whereANY: 8155 t = error_mark_node; 8156 break; 8157 } 8158 break; 8159 8160 case FFEINFO_kindBLOCKDATA: 8161 switch (ffeinfo_where (ffesymbol_info (s))) 8162 { 8163 case FFEINFO_whereLOCAL: /* Me. */ 8164 assert (!ffecom_transform_only_dummies_); 8165 t = current_function_decl; 8166 break; 8167 8168 case FFEINFO_whereGLOBAL: 8169 assert (!ffecom_transform_only_dummies_); 8170 8171 t = build_decl (FUNCTION_DECL, 8172 ffecom_get_external_identifier_ (s), 8173 ffecom_tree_blockdata_type); 8174 DECL_EXTERNAL (t) = 1; 8175 TREE_PUBLIC (t) = 1; 8176 8177 t = start_decl (t, FALSE); 8178 finish_decl (t, NULL_TREE, FALSE); 8179 8180 ffecom_save_tree_forever (t); 8181 8182 break; 8183 8184 case FFEINFO_whereCOMMON: 8185 case FFEINFO_whereDUMMY: 8186 case FFEINFO_whereRESULT: 8187 case FFEINFO_whereFLEETING: 8188 case FFEINFO_whereFLEETING_CADDR: 8189 case FFEINFO_whereFLEETING_IADDR: 8190 case FFEINFO_whereIMMEDIATE: 8191 case FFEINFO_whereINTRINSIC: 8192 case FFEINFO_whereCONSTANT: 8193 case FFEINFO_whereCONSTANT_SUBOBJECT: 8194 default: 8195 assert ("BLOCKDATA where unheard of" == NULL); 8196 /* Fall through. */ 8197 case FFEINFO_whereANY: 8198 t = error_mark_node; 8199 break; 8200 } 8201 break; 8202 8203 case FFEINFO_kindCOMMON: 8204 switch (ffeinfo_where (ffesymbol_info (s))) 8205 { 8206 case FFEINFO_whereLOCAL: 8207 assert (!ffecom_transform_only_dummies_); 8208 ffecom_transform_common_ (s); 8209 break; 8210 8211 case FFEINFO_whereNONE: 8212 case FFEINFO_whereCOMMON: 8213 case FFEINFO_whereDUMMY: 8214 case FFEINFO_whereGLOBAL: 8215 case FFEINFO_whereRESULT: 8216 case FFEINFO_whereFLEETING: 8217 case FFEINFO_whereFLEETING_CADDR: 8218 case FFEINFO_whereFLEETING_IADDR: 8219 case FFEINFO_whereIMMEDIATE: 8220 case FFEINFO_whereINTRINSIC: 8221 case FFEINFO_whereCONSTANT: 8222 case FFEINFO_whereCONSTANT_SUBOBJECT: 8223 default: 8224 assert ("COMMON where unheard of" == NULL); 8225 /* Fall through. */ 8226 case FFEINFO_whereANY: 8227 t = error_mark_node; 8228 break; 8229 } 8230 break; 8231 8232 case FFEINFO_kindCONSTRUCT: 8233 switch (ffeinfo_where (ffesymbol_info (s))) 8234 { 8235 case FFEINFO_whereLOCAL: 8236 assert (!ffecom_transform_only_dummies_); 8237 break; 8238 8239 case FFEINFO_whereNONE: 8240 case FFEINFO_whereCOMMON: 8241 case FFEINFO_whereDUMMY: 8242 case FFEINFO_whereGLOBAL: 8243 case FFEINFO_whereRESULT: 8244 case FFEINFO_whereFLEETING: 8245 case FFEINFO_whereFLEETING_CADDR: 8246 case FFEINFO_whereFLEETING_IADDR: 8247 case FFEINFO_whereIMMEDIATE: 8248 case FFEINFO_whereINTRINSIC: 8249 case FFEINFO_whereCONSTANT: 8250 case FFEINFO_whereCONSTANT_SUBOBJECT: 8251 default: 8252 assert ("CONSTRUCT where unheard of" == NULL); 8253 /* Fall through. */ 8254 case FFEINFO_whereANY: 8255 t = error_mark_node; 8256 break; 8257 } 8258 break; 8259 8260 case FFEINFO_kindNAMELIST: 8261 switch (ffeinfo_where (ffesymbol_info (s))) 8262 { 8263 case FFEINFO_whereLOCAL: 8264 assert (!ffecom_transform_only_dummies_); 8265 t = ffecom_transform_namelist_ (s); 8266 break; 8267 8268 case FFEINFO_whereNONE: 8269 case FFEINFO_whereCOMMON: 8270 case FFEINFO_whereDUMMY: 8271 case FFEINFO_whereGLOBAL: 8272 case FFEINFO_whereRESULT: 8273 case FFEINFO_whereFLEETING: 8274 case FFEINFO_whereFLEETING_CADDR: 8275 case FFEINFO_whereFLEETING_IADDR: 8276 case FFEINFO_whereIMMEDIATE: 8277 case FFEINFO_whereINTRINSIC: 8278 case FFEINFO_whereCONSTANT: 8279 case FFEINFO_whereCONSTANT_SUBOBJECT: 8280 default: 8281 assert ("NAMELIST where unheard of" == NULL); 8282 /* Fall through. */ 8283 case FFEINFO_whereANY: 8284 t = error_mark_node; 8285 break; 8286 } 8287 break; 8288 8289 default: 8290 assert ("kind unheard of" == NULL); 8291 /* Fall through. */ 8292 case FFEINFO_kindANY: 8293 t = error_mark_node; 8294 break; 8295 } 8296 8297 ffesymbol_hook (s).decl_tree = t; 8298 ffesymbol_hook (s).length_tree = tlen; 8299 ffesymbol_hook (s).addr = addr; 8300 8301 lineno = old_lineno; 8302 input_filename = old_input_filename; 8303 8304 return s; 8305 } 8306 8307 /* Transform into ASSIGNable symbol. 8308 8309 Symbol has already been transformed, but for whatever reason, the 8310 resulting decl_tree has been deemed not usable for an ASSIGN target. 8311 (E.g. it isn't wide enough to hold a pointer.) So, here we invent 8312 another local symbol of type void * and stuff that in the assign_tree 8313 argument. The F77/F90 standards allow this implementation. */ 8314 8315 static ffesymbol 8316 ffecom_sym_transform_assign_ (ffesymbol s) 8317 { 8318 tree t; /* Transformed thingy. */ 8319 int old_lineno = lineno; 8320 const char *old_input_filename = input_filename; 8321 8322 if (ffesymbol_sfdummyparent (s) == NULL) 8323 { 8324 input_filename = ffesymbol_where_filename (s); 8325 lineno = ffesymbol_where_filelinenum (s); 8326 } 8327 else 8328 { 8329 ffesymbol sf = ffesymbol_sfdummyparent (s); 8330 8331 input_filename = ffesymbol_where_filename (sf); 8332 lineno = ffesymbol_where_filelinenum (sf); 8333 } 8334 8335 assert (!ffecom_transform_only_dummies_); 8336 8337 t = build_decl (VAR_DECL, 8338 ffecom_get_invented_identifier ("__g77_ASSIGN_%s", 8339 ffesymbol_text (s)), 8340 TREE_TYPE (null_pointer_node)); 8341 8342 switch (ffesymbol_where (s)) 8343 { 8344 case FFEINFO_whereLOCAL: 8345 /* Unlike for regular vars, SAVE status is easy to determine for 8346 ASSIGNed vars, since there's no initialization, there's no 8347 effective storage association (so "SAVE J" does not apply to 8348 K even given "EQUIVALENCE (J,K)"), there's no size issue 8349 to worry about, etc. */ 8350 if ((ffesymbol_is_save (s) || ffe_is_saveall ()) 8351 && (ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM) 8352 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)) 8353 TREE_STATIC (t) = 1; /* SAVEd in proc, make static. */ 8354 else 8355 TREE_STATIC (t) = 0; /* No need to make static. */ 8356 break; 8357 8358 case FFEINFO_whereCOMMON: 8359 TREE_STATIC (t) = 1; /* Assume COMMONs always SAVEd. */ 8360 break; 8361 8362 case FFEINFO_whereDUMMY: 8363 /* Note that twinning a DUMMY means the caller won't see 8364 the ASSIGNed value. But both F77 and F90 allow implementations 8365 to do this, i.e. disallow Fortran code that would try and 8366 take advantage of actually putting a label into a variable 8367 via a dummy argument (or any other storage association, for 8368 that matter). */ 8369 TREE_STATIC (t) = 0; 8370 break; 8371 8372 default: 8373 TREE_STATIC (t) = 0; 8374 break; 8375 } 8376 8377 t = start_decl (t, FALSE); 8378 finish_decl (t, NULL_TREE, FALSE); 8379 8380 ffesymbol_hook (s).assign_tree = t; 8381 8382 lineno = old_lineno; 8383 input_filename = old_input_filename; 8384 8385 return s; 8386 } 8387 8388 /* Implement COMMON area in back end. 8389 8390 Because COMMON-based variables can be referenced in the dimension 8391 expressions of dummy (adjustable) arrays, and because dummies 8392 (in the gcc back end) need to be put in the outer binding level 8393 of a function (which has two binding levels, the outer holding 8394 the dummies and the inner holding the other vars), special care 8395 must be taken to handle COMMON areas. 8396 8397 The current strategy is basically to always tell the back end about 8398 the COMMON area as a top-level external reference to just a block 8399 of storage of the master type of that area (e.g. integer, real, 8400 character, whatever -- not a structure). As a distinct action, 8401 if initial values are provided, tell the back end about the area 8402 as a top-level non-external (initialized) area and remember not to 8403 allow further initialization or expansion of the area. Meanwhile, 8404 if no initialization happens at all, tell the back end about 8405 the largest size we've seen declared so the space does get reserved. 8406 (This function doesn't handle all that stuff, but it does some 8407 of the important things.) 8408 8409 Meanwhile, for COMMON variables themselves, just keep creating 8410 references like *((float *) (&common_area + offset)) each time 8411 we reference the variable. In other words, don't make a VAR_DECL 8412 or any kind of component reference (like we used to do before 0.4), 8413 though we might do that as well just for debugging purposes (and 8414 stuff the rtl with the appropriate offset expression). */ 8415 8416 static void 8417 ffecom_transform_common_ (ffesymbol s) 8418 { 8419 ffestorag st = ffesymbol_storage (s); 8420 ffeglobal g = ffesymbol_global (s); 8421 tree cbt; 8422 tree cbtype; 8423 tree init; 8424 tree high; 8425 bool is_init = ffestorag_is_init (st); 8426 8427 assert (st != NULL); 8428 8429 if ((g == NULL) 8430 || (ffeglobal_type (g) != FFEGLOBAL_typeCOMMON)) 8431 return; 8432 8433 /* First update the size of the area in global terms. */ 8434 8435 ffeglobal_size_common (s, ffestorag_size (st)); 8436 8437 if (!ffeglobal_common_init (g)) 8438 is_init = FALSE; /* No explicit init, don't let erroneous joins init. */ 8439 8440 cbt = ffeglobal_hook (g); 8441 8442 /* If we already have declared this common block for a previous program 8443 unit, and either we already initialized it or we don't have new 8444 initialization for it, just return what we have without changing it. */ 8445 8446 if ((cbt != NULL_TREE) 8447 && (!is_init 8448 || !DECL_EXTERNAL (cbt))) 8449 { 8450 if (st->hook == NULL) ffestorag_set_hook (st, cbt); 8451 return; 8452 } 8453 8454 /* Process inits. */ 8455 8456 if (is_init) 8457 { 8458 if (ffestorag_init (st) != NULL) 8459 { 8460 ffebld sexp; 8461 8462 /* Set the padding for the expression, so ffecom_expr 8463 knows to insert that many zeros. */ 8464 switch (ffebld_op (sexp = ffestorag_init (st))) 8465 { 8466 case FFEBLD_opCONTER: 8467 ffebld_conter_set_pad (sexp, ffestorag_modulo (st)); 8468 break; 8469 8470 case FFEBLD_opARRTER: 8471 ffebld_arrter_set_pad (sexp, ffestorag_modulo (st)); 8472 break; 8473 8474 case FFEBLD_opACCTER: 8475 ffebld_accter_set_pad (sexp, ffestorag_modulo (st)); 8476 break; 8477 8478 default: 8479 assert ("bad op for cmn init (pad)" == NULL); 8480 break; 8481 } 8482 8483 init = ffecom_expr (sexp); 8484 if (init == error_mark_node) 8485 { /* Hopefully the back end complained! */ 8486 init = NULL_TREE; 8487 if (cbt != NULL_TREE) 8488 return; 8489 } 8490 } 8491 else 8492 init = error_mark_node; 8493 } 8494 else 8495 init = NULL_TREE; 8496 8497 /* cbtype must be permanently allocated! */ 8498 8499 /* Allocate the MAX of the areas so far, seen filewide. */ 8500 high = build_int_2 ((ffeglobal_common_size (g) 8501 + ffeglobal_common_pad (g)) - 1, 0); 8502 TREE_TYPE (high) = ffecom_integer_type_node; 8503 8504 if (init) 8505 cbtype = build_array_type (char_type_node, 8506 build_range_type (integer_type_node, 8507 integer_zero_node, 8508 high)); 8509 else 8510 cbtype = build_array_type (char_type_node, NULL_TREE); 8511 8512 if (cbt == NULL_TREE) 8513 { 8514 cbt 8515 = build_decl (VAR_DECL, 8516 ffecom_get_external_identifier_ (s), 8517 cbtype); 8518 TREE_STATIC (cbt) = 1; 8519 TREE_PUBLIC (cbt) = 1; 8520 } 8521 else 8522 { 8523 assert (is_init); 8524 TREE_TYPE (cbt) = cbtype; 8525 } 8526 DECL_EXTERNAL (cbt) = init ? 0 : 1; 8527 DECL_INITIAL (cbt) = init ? error_mark_node : NULL_TREE; 8528 8529 cbt = start_decl (cbt, TRUE); 8530 if (ffeglobal_hook (g) != NULL) 8531 assert (cbt == ffeglobal_hook (g)); 8532 8533 assert (!init || !DECL_EXTERNAL (cbt)); 8534 8535 /* Make sure that any type can live in COMMON and be referenced 8536 without getting a bus error. We could pick the most restrictive 8537 alignment of all entities actually placed in the COMMON, but 8538 this seems easy enough. */ 8539 8540 DECL_ALIGN (cbt) = BIGGEST_ALIGNMENT; 8541 DECL_USER_ALIGN (cbt) = 0; 8542 8543 if (is_init && (ffestorag_init (st) == NULL)) 8544 init = ffecom_init_zero_ (cbt); 8545 8546 finish_decl (cbt, init, TRUE); 8547 8548 if (is_init) 8549 ffestorag_set_init (st, ffebld_new_any ()); 8550 8551 if (init) 8552 { 8553 assert (DECL_SIZE_UNIT (cbt) != NULL_TREE); 8554 assert (TREE_CODE (DECL_SIZE_UNIT (cbt)) == INTEGER_CST); 8555 assert (0 == compare_tree_int (DECL_SIZE_UNIT (cbt), 8556 (ffeglobal_common_size (g) 8557 + ffeglobal_common_pad (g)))); 8558 } 8559 8560 ffeglobal_set_hook (g, cbt); 8561 8562 ffestorag_set_hook (st, cbt); 8563 8564 ffecom_save_tree_forever (cbt); 8565 } 8566 8567 /* Make master area for local EQUIVALENCE. */ 8568 8569 static void 8570 ffecom_transform_equiv_ (ffestorag eqst) 8571 { 8572 tree eqt; 8573 tree eqtype; 8574 tree init; 8575 tree high; 8576 bool is_init = ffestorag_is_init (eqst); 8577 8578 assert (eqst != NULL); 8579 8580 eqt = ffestorag_hook (eqst); 8581 8582 if (eqt != NULL_TREE) 8583 return; 8584 8585 /* Process inits. */ 8586 8587 if (is_init) 8588 { 8589 if (ffestorag_init (eqst) != NULL) 8590 { 8591 ffebld sexp; 8592 8593 /* Set the padding for the expression, so ffecom_expr 8594 knows to insert that many zeros. */ 8595 switch (ffebld_op (sexp = ffestorag_init (eqst))) 8596 { 8597 case FFEBLD_opCONTER: 8598 ffebld_conter_set_pad (sexp, ffestorag_modulo (eqst)); 8599 break; 8600 8601 case FFEBLD_opARRTER: 8602 ffebld_arrter_set_pad (sexp, ffestorag_modulo (eqst)); 8603 break; 8604 8605 case FFEBLD_opACCTER: 8606 ffebld_accter_set_pad (sexp, ffestorag_modulo (eqst)); 8607 break; 8608 8609 default: 8610 assert ("bad op for eqv init (pad)" == NULL); 8611 break; 8612 } 8613 8614 init = ffecom_expr (sexp); 8615 if (init == error_mark_node) 8616 init = NULL_TREE; /* Hopefully the back end complained! */ 8617 } 8618 else 8619 init = error_mark_node; 8620 } 8621 else if (ffe_is_init_local_zero ()) 8622 init = error_mark_node; 8623 else 8624 init = NULL_TREE; 8625 8626 ffecom_member_namelisted_ = FALSE; 8627 ffestorag_drive (ffestorag_list_equivs (eqst), 8628 &ffecom_member_phase1_, 8629 eqst); 8630 8631 high = build_int_2 ((ffestorag_size (eqst) 8632 + ffestorag_modulo (eqst)) - 1, 0); 8633 TREE_TYPE (high) = ffecom_integer_type_node; 8634 8635 eqtype = build_array_type (char_type_node, 8636 build_range_type (ffecom_integer_type_node, 8637 ffecom_integer_zero_node, 8638 high)); 8639 8640 eqt = build_decl (VAR_DECL, 8641 ffecom_get_invented_identifier ("__g77_equiv_%s", 8642 ffesymbol_text 8643 (ffestorag_symbol (eqst))), 8644 eqtype); 8645 DECL_EXTERNAL (eqt) = 0; 8646 if (is_init 8647 || ffecom_member_namelisted_ 8648 #ifdef FFECOM_sizeMAXSTACKITEM 8649 || (ffestorag_size (eqst) > FFECOM_sizeMAXSTACKITEM) 8650 #endif 8651 || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM) 8652 && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA) 8653 && (ffestorag_is_save (eqst) || ffe_is_saveall ()))) 8654 TREE_STATIC (eqt) = 1; 8655 else 8656 TREE_STATIC (eqt) = 0; 8657 TREE_PUBLIC (eqt) = 0; 8658 TREE_ADDRESSABLE (eqt) = 1; /* Ensure non-register allocation */ 8659 DECL_CONTEXT (eqt) = current_function_decl; 8660 if (init) 8661 DECL_INITIAL (eqt) = error_mark_node; 8662 else 8663 DECL_INITIAL (eqt) = NULL_TREE; 8664 8665 eqt = start_decl (eqt, FALSE); 8666 8667 /* Make sure that any type can live in EQUIVALENCE and be referenced 8668 without getting a bus error. We could pick the most restrictive 8669 alignment of all entities actually placed in the EQUIVALENCE, but 8670 this seems easy enough. */ 8671 8672 DECL_ALIGN (eqt) = BIGGEST_ALIGNMENT; 8673 DECL_USER_ALIGN (eqt) = 0; 8674 8675 if ((!is_init && ffe_is_init_local_zero ()) 8676 || (is_init && (ffestorag_init (eqst) == NULL))) 8677 init = ffecom_init_zero_ (eqt); 8678 8679 finish_decl (eqt, init, FALSE); 8680 8681 if (is_init) 8682 ffestorag_set_init (eqst, ffebld_new_any ()); 8683 8684 { 8685 assert (TREE_CODE (DECL_SIZE_UNIT (eqt)) == INTEGER_CST); 8686 assert (0 == compare_tree_int (DECL_SIZE_UNIT (eqt), 8687 (ffestorag_size (eqst) 8688 + ffestorag_modulo (eqst)))); 8689 } 8690 8691 ffestorag_set_hook (eqst, eqt); 8692 8693 ffestorag_drive (ffestorag_list_equivs (eqst), 8694 &ffecom_member_phase2_, 8695 eqst); 8696 } 8697 8698 /* Implement NAMELIST in back end. See f2c/format.c for more info. */ 8699 8700 static tree 8701 ffecom_transform_namelist_ (ffesymbol s) 8702 { 8703 tree nmlt; 8704 tree nmltype = ffecom_type_namelist_ (); 8705 tree nmlinits; 8706 tree nameinit; 8707 tree varsinit; 8708 tree nvarsinit; 8709 tree field; 8710 tree high; 8711 int i; 8712 static int mynumber = 0; 8713 8714 nmlt = build_decl (VAR_DECL, 8715 ffecom_get_invented_identifier ("__g77_namelist_%d", 8716 mynumber++), 8717 nmltype); 8718 TREE_STATIC (nmlt) = 1; 8719 DECL_INITIAL (nmlt) = error_mark_node; 8720 8721 nmlt = start_decl (nmlt, FALSE); 8722 8723 /* Process inits. */ 8724 8725 i = strlen (ffesymbol_text (s)); 8726 8727 high = build_int_2 (i, 0); 8728 TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node; 8729 8730 nameinit = ffecom_build_f2c_string_ (i + 1, 8731 ffesymbol_text (s)); 8732 TREE_TYPE (nameinit) 8733 = build_type_variant 8734 (build_array_type 8735 (char_type_node, 8736 build_range_type (ffecom_f2c_ftnlen_type_node, 8737 ffecom_f2c_ftnlen_one_node, 8738 high)), 8739 1, 0); 8740 TREE_CONSTANT (nameinit) = 1; 8741 TREE_STATIC (nameinit) = 1; 8742 nameinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (nameinit)), 8743 nameinit); 8744 8745 varsinit = ffecom_vardesc_array_ (s); 8746 varsinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (varsinit)), 8747 varsinit); 8748 TREE_CONSTANT (varsinit) = 1; 8749 TREE_STATIC (varsinit) = 1; 8750 8751 { 8752 ffebld b; 8753 8754 for (i = 0, b = ffesymbol_namelist (s); b != NULL; b = ffebld_trail (b)) 8755 ++i; 8756 } 8757 nvarsinit = build_int_2 (i, 0); 8758 TREE_TYPE (nvarsinit) = integer_type_node; 8759 TREE_CONSTANT (nvarsinit) = 1; 8760 TREE_STATIC (nvarsinit) = 1; 8761 8762 nmlinits = build_tree_list ((field = TYPE_FIELDS (nmltype)), nameinit); 8763 TREE_CHAIN (nmlinits) = build_tree_list ((field = TREE_CHAIN (field)), 8764 varsinit); 8765 TREE_CHAIN (TREE_CHAIN (nmlinits)) 8766 = build_tree_list ((field = TREE_CHAIN (field)), nvarsinit); 8767 8768 nmlinits = build (CONSTRUCTOR, nmltype, NULL_TREE, nmlinits); 8769 TREE_CONSTANT (nmlinits) = 1; 8770 TREE_STATIC (nmlinits) = 1; 8771 8772 finish_decl (nmlt, nmlinits, FALSE); 8773 8774 nmlt = ffecom_1 (ADDR_EXPR, build_pointer_type (nmltype), nmlt); 8775 8776 return nmlt; 8777 } 8778 8779 /* A subroutine of ffecom_tree_canonize_ref_. The incoming tree is 8780 analyzed on the assumption it is calculating a pointer to be 8781 indirected through. It must return the proper decl and offset, 8782 taking into account different units of measurements for offsets. */ 8783 8784 static void 8785 ffecom_tree_canonize_ptr_ (tree *decl, tree *offset, 8786 tree t) 8787 { 8788 switch (TREE_CODE (t)) 8789 { 8790 case NOP_EXPR: 8791 case CONVERT_EXPR: 8792 case NON_LVALUE_EXPR: 8793 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0)); 8794 break; 8795 8796 case PLUS_EXPR: 8797 ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0)); 8798 if ((*decl == NULL_TREE) 8799 || (*decl == error_mark_node)) 8800 break; 8801 8802 if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST) 8803 { 8804 /* An offset into COMMON. */ 8805 *offset = fold (build (PLUS_EXPR, TREE_TYPE (*offset), 8806 *offset, TREE_OPERAND (t, 1))); 8807 /* Convert offset (presumably in bytes) into canonical units 8808 (presumably bits). */ 8809 *offset = size_binop (MULT_EXPR, 8810 convert (bitsizetype, *offset), 8811 TYPE_SIZE (TREE_TYPE (TREE_TYPE (t)))); 8812 break; 8813 } 8814 /* Not a COMMON reference, so an unrecognized pattern. */ 8815 *decl = error_mark_node; 8816 break; 8817 8818 case PARM_DECL: 8819 *decl = t; 8820 *offset = bitsize_zero_node; 8821 break; 8822 8823 case ADDR_EXPR: 8824 if (TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL) 8825 { 8826 /* A reference to COMMON. */ 8827 *decl = TREE_OPERAND (t, 0); 8828 *offset = bitsize_zero_node; 8829 break; 8830 } 8831 /* Fall through. */ 8832 default: 8833 /* Not a COMMON reference, so an unrecognized pattern. */ 8834 *decl = error_mark_node; 8835 break; 8836 } 8837 } 8838 8839 /* Given a tree that is possibly intended for use as an lvalue, return 8840 information representing a canonical view of that tree as a decl, an 8841 offset into that decl, and a size for the lvalue. 8842 8843 If there's no applicable decl, NULL_TREE is returned for the decl, 8844 and the other fields are left undefined. 8845 8846 If the tree doesn't fit the recognizable forms, an ERROR_MARK node 8847 is returned for the decl, and the other fields are left undefined. 8848 8849 Otherwise, the decl returned currently is either a VAR_DECL or a 8850 PARM_DECL. 8851 8852 The offset returned is always valid, but of course not necessarily 8853 a constant, and not necessarily converted into the appropriate 8854 type, leaving that up to the caller (so as to avoid that overhead 8855 if the decls being looked at are different anyway). 8856 8857 If the size cannot be determined (e.g. an adjustable array), 8858 an ERROR_MARK node is returned for the size. Otherwise, the 8859 size returned is valid, not necessarily a constant, and not 8860 necessarily converted into the appropriate type as with the 8861 offset. 8862 8863 Note that the offset and size expressions are expressed in the 8864 base storage units (usually bits) rather than in the units of 8865 the type of the decl, because two decls with different types 8866 might overlap but with apparently non-overlapping array offsets, 8867 whereas converting the array offsets to consistant offsets will 8868 reveal the overlap. */ 8869 8870 static void 8871 ffecom_tree_canonize_ref_ (tree *decl, tree *offset, 8872 tree *size, tree t) 8873 { 8874 /* The default path is to report a nonexistant decl. */ 8875 *decl = NULL_TREE; 8876 8877 if (t == NULL_TREE) 8878 return; 8879 8880 switch (TREE_CODE (t)) 8881 { 8882 case ERROR_MARK: 8883 case IDENTIFIER_NODE: 8884 case INTEGER_CST: 8885 case REAL_CST: 8886 case COMPLEX_CST: 8887 case STRING_CST: 8888 case CONST_DECL: 8889 case PLUS_EXPR: 8890 case MINUS_EXPR: 8891 case MULT_EXPR: 8892 case TRUNC_DIV_EXPR: 8893 case CEIL_DIV_EXPR: 8894 case FLOOR_DIV_EXPR: 8895 case ROUND_DIV_EXPR: 8896 case TRUNC_MOD_EXPR: 8897 case CEIL_MOD_EXPR: 8898 case FLOOR_MOD_EXPR: 8899 case ROUND_MOD_EXPR: 8900 case RDIV_EXPR: 8901 case EXACT_DIV_EXPR: 8902 case FIX_TRUNC_EXPR: 8903 case FIX_CEIL_EXPR: 8904 case FIX_FLOOR_EXPR: 8905 case FIX_ROUND_EXPR: 8906 case FLOAT_EXPR: 8907 case NEGATE_EXPR: 8908 case MIN_EXPR: 8909 case MAX_EXPR: 8910 case ABS_EXPR: 8911 case FFS_EXPR: 8912 case LSHIFT_EXPR: 8913 case RSHIFT_EXPR: 8914 case LROTATE_EXPR: 8915 case RROTATE_EXPR: 8916 case BIT_IOR_EXPR: 8917 case BIT_XOR_EXPR: 8918 case BIT_AND_EXPR: 8919 case BIT_ANDTC_EXPR: 8920 case BIT_NOT_EXPR: 8921 case TRUTH_ANDIF_EXPR: 8922 case TRUTH_ORIF_EXPR: 8923 case TRUTH_AND_EXPR: 8924 case TRUTH_OR_EXPR: 8925 case TRUTH_XOR_EXPR: 8926 case TRUTH_NOT_EXPR: 8927 case LT_EXPR: 8928 case LE_EXPR: 8929 case GT_EXPR: 8930 case GE_EXPR: 8931 case EQ_EXPR: 8932 case NE_EXPR: 8933 case COMPLEX_EXPR: 8934 case CONJ_EXPR: 8935 case REALPART_EXPR: 8936 case IMAGPART_EXPR: 8937 case LABEL_EXPR: 8938 case COMPONENT_REF: 8939 case COMPOUND_EXPR: 8940 case ADDR_EXPR: 8941 return; 8942 8943 case VAR_DECL: 8944 case PARM_DECL: 8945 *decl = t; 8946 *offset = bitsize_zero_node; 8947 *size = TYPE_SIZE (TREE_TYPE (t)); 8948 return; 8949 8950 case ARRAY_REF: 8951 { 8952 tree array = TREE_OPERAND (t, 0); 8953 tree element = TREE_OPERAND (t, 1); 8954 tree init_offset; 8955 8956 if ((array == NULL_TREE) 8957 || (element == NULL_TREE)) 8958 { 8959 *decl = error_mark_node; 8960 return; 8961 } 8962 8963 ffecom_tree_canonize_ref_ (decl, &init_offset, size, 8964 array); 8965 if ((*decl == NULL_TREE) 8966 || (*decl == error_mark_node)) 8967 return; 8968 8969 /* Calculate ((element - base) * NBBY) + init_offset. */ 8970 *offset = fold (build (MINUS_EXPR, TREE_TYPE (element), 8971 element, 8972 TYPE_MIN_VALUE (TYPE_DOMAIN 8973 (TREE_TYPE (array))))); 8974 8975 *offset = size_binop (MULT_EXPR, 8976 convert (bitsizetype, *offset), 8977 TYPE_SIZE (TREE_TYPE (TREE_TYPE (array)))); 8978 8979 *offset = size_binop (PLUS_EXPR, init_offset, *offset); 8980 8981 *size = TYPE_SIZE (TREE_TYPE (t)); 8982 return; 8983 } 8984 8985 case INDIRECT_REF: 8986 8987 /* Most of this code is to handle references to COMMON. And so 8988 far that is useful only for calling library functions, since 8989 external (user) functions might reference common areas. But 8990 even calling an external function, it's worthwhile to decode 8991 COMMON references because if not storing into COMMON, we don't 8992 want COMMON-based arguments to gratuitously force use of a 8993 temporary. */ 8994 8995 *size = TYPE_SIZE (TREE_TYPE (t)); 8996 8997 ffecom_tree_canonize_ptr_ (decl, offset, 8998 TREE_OPERAND (t, 0)); 8999 9000 return; 9001 9002 case CONVERT_EXPR: 9003 case NOP_EXPR: 9004 case MODIFY_EXPR: 9005 case NON_LVALUE_EXPR: 9006 case RESULT_DECL: 9007 case FIELD_DECL: 9008 case COND_EXPR: /* More cases than we can handle. */ 9009 case SAVE_EXPR: 9010 case REFERENCE_EXPR: 9011 case PREDECREMENT_EXPR: 9012 case PREINCREMENT_EXPR: 9013 case POSTDECREMENT_EXPR: 9014 case POSTINCREMENT_EXPR: 9015 case CALL_EXPR: 9016 default: 9017 *decl = error_mark_node; 9018 return; 9019 } 9020 } 9021 9022 /* Do divide operation appropriate to type of operands. */ 9023 9024 static tree 9025 ffecom_tree_divide_ (tree tree_type, tree left, tree right, 9026 tree dest_tree, ffebld dest, bool *dest_used, 9027 tree hook) 9028 { 9029 if ((left == error_mark_node) 9030 || (right == error_mark_node)) 9031 return error_mark_node; 9032 9033 switch (TREE_CODE (tree_type)) 9034 { 9035 case INTEGER_TYPE: 9036 return ffecom_2 (TRUNC_DIV_EXPR, tree_type, 9037 left, 9038 right); 9039 9040 case COMPLEX_TYPE: 9041 if (! optimize_size) 9042 return ffecom_2 (RDIV_EXPR, tree_type, 9043 left, 9044 right); 9045 { 9046 ffecomGfrt ix; 9047 9048 if (TREE_TYPE (tree_type) 9049 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]) 9050 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */ 9051 else 9052 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */ 9053 9054 left = ffecom_1 (ADDR_EXPR, 9055 build_pointer_type (TREE_TYPE (left)), 9056 left); 9057 left = build_tree_list (NULL_TREE, left); 9058 right = ffecom_1 (ADDR_EXPR, 9059 build_pointer_type (TREE_TYPE (right)), 9060 right); 9061 right = build_tree_list (NULL_TREE, right); 9062 TREE_CHAIN (left) = right; 9063 9064 return ffecom_call_ (ffecom_gfrt_tree_ (ix), 9065 ffecom_gfrt_kindtype (ix), 9066 ffe_is_f2c_library (), 9067 tree_type, 9068 left, 9069 dest_tree, dest, dest_used, 9070 NULL_TREE, TRUE, hook); 9071 } 9072 break; 9073 9074 case RECORD_TYPE: 9075 { 9076 ffecomGfrt ix; 9077 9078 if (TREE_TYPE (TYPE_FIELDS (tree_type)) 9079 == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]) 9080 ix = FFECOM_gfrtDIV_CC; /* Overlapping result okay. */ 9081 else 9082 ix = FFECOM_gfrtDIV_ZZ; /* Overlapping result okay. */ 9083 9084 left = ffecom_1 (ADDR_EXPR, 9085 build_pointer_type (TREE_TYPE (left)), 9086 left); 9087 left = build_tree_list (NULL_TREE, left); 9088 right = ffecom_1 (ADDR_EXPR, 9089 build_pointer_type (TREE_TYPE (right)), 9090 right); 9091 right = build_tree_list (NULL_TREE, right); 9092 TREE_CHAIN (left) = right; 9093 9094 return ffecom_call_ (ffecom_gfrt_tree_ (ix), 9095 ffecom_gfrt_kindtype (ix), 9096 ffe_is_f2c_library (), 9097 tree_type, 9098 left, 9099 dest_tree, dest, dest_used, 9100 NULL_TREE, TRUE, hook); 9101 } 9102 break; 9103 9104 default: 9105 return ffecom_2 (RDIV_EXPR, tree_type, 9106 left, 9107 right); 9108 } 9109 } 9110 9111 /* Build type info for non-dummy variable. */ 9112 9113 static tree 9114 ffecom_type_localvar_ (ffesymbol s, ffeinfoBasictype bt, 9115 ffeinfoKindtype kt) 9116 { 9117 tree type; 9118 ffebld dl; 9119 ffebld dim; 9120 tree lowt; 9121 tree hight; 9122 9123 type = ffecom_tree_type[bt][kt]; 9124 if (bt == FFEINFO_basictypeCHARACTER) 9125 { 9126 hight = build_int_2 (ffesymbol_size (s), 0); 9127 TREE_TYPE (hight) = ffecom_f2c_ftnlen_type_node; 9128 9129 type 9130 = build_array_type 9131 (type, 9132 build_range_type (ffecom_f2c_ftnlen_type_node, 9133 ffecom_f2c_ftnlen_one_node, 9134 hight)); 9135 type = ffecom_check_size_overflow_ (s, type, FALSE); 9136 } 9137 9138 for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl)) 9139 { 9140 if (type == error_mark_node) 9141 break; 9142 9143 dim = ffebld_head (dl); 9144 assert (ffebld_op (dim) == FFEBLD_opBOUNDS); 9145 9146 if (ffebld_left (dim) == NULL) 9147 lowt = integer_one_node; 9148 else 9149 lowt = ffecom_expr (ffebld_left (dim)); 9150 9151 if (TREE_CODE (lowt) != INTEGER_CST) 9152 lowt = variable_size (lowt); 9153 9154 assert (ffebld_right (dim) != NULL); 9155 hight = ffecom_expr (ffebld_right (dim)); 9156 9157 if (TREE_CODE (hight) != INTEGER_CST) 9158 hight = variable_size (hight); 9159 9160 type = build_array_type (type, 9161 build_range_type (ffecom_integer_type_node, 9162 lowt, hight)); 9163 type = ffecom_check_size_overflow_ (s, type, FALSE); 9164 } 9165 9166 return type; 9167 } 9168 9169 /* Build Namelist type. */ 9170 9171 static GTY(()) tree ffecom_type_namelist_var; 9172 static tree 9173 ffecom_type_namelist_ () 9174 { 9175 if (ffecom_type_namelist_var == NULL_TREE) 9176 { 9177 tree namefield, varsfield, nvarsfield, vardesctype, type; 9178 9179 vardesctype = ffecom_type_vardesc_ (); 9180 9181 type = make_node (RECORD_TYPE); 9182 9183 vardesctype = build_pointer_type (build_pointer_type (vardesctype)); 9184 9185 namefield = ffecom_decl_field (type, NULL_TREE, "name", 9186 string_type_node); 9187 varsfield = ffecom_decl_field (type, namefield, "vars", vardesctype); 9188 nvarsfield = ffecom_decl_field (type, varsfield, "nvars", 9189 integer_type_node); 9190 9191 TYPE_FIELDS (type) = namefield; 9192 layout_type (type); 9193 9194 ffecom_type_namelist_var = type; 9195 } 9196 9197 return ffecom_type_namelist_var; 9198 } 9199 9200 /* Build Vardesc type. */ 9201 9202 static GTY(()) tree ffecom_type_vardesc_var; 9203 static tree 9204 ffecom_type_vardesc_ () 9205 { 9206 if (ffecom_type_vardesc_var == NULL_TREE) 9207 { 9208 tree namefield, addrfield, dimsfield, typefield, type; 9209 type = make_node (RECORD_TYPE); 9210 9211 namefield = ffecom_decl_field (type, NULL_TREE, "name", 9212 string_type_node); 9213 addrfield = ffecom_decl_field (type, namefield, "addr", 9214 string_type_node); 9215 dimsfield = ffecom_decl_field (type, addrfield, "dims", 9216 ffecom_f2c_ptr_to_ftnlen_type_node); 9217 typefield = ffecom_decl_field (type, dimsfield, "type", 9218 integer_type_node); 9219 9220 TYPE_FIELDS (type) = namefield; 9221 layout_type (type); 9222 9223 ffecom_type_vardesc_var = type; 9224 } 9225 9226 return ffecom_type_vardesc_var; 9227 } 9228 9229 static tree 9230 ffecom_vardesc_ (ffebld expr) 9231 { 9232 ffesymbol s; 9233 9234 assert (ffebld_op (expr) == FFEBLD_opSYMTER); 9235 s = ffebld_symter (expr); 9236 9237 if (ffesymbol_hook (s).vardesc_tree == NULL_TREE) 9238 { 9239 int i; 9240 tree vardesctype = ffecom_type_vardesc_ (); 9241 tree var; 9242 tree nameinit; 9243 tree dimsinit; 9244 tree addrinit; 9245 tree typeinit; 9246 tree field; 9247 tree varinits; 9248 static int mynumber = 0; 9249 9250 var = build_decl (VAR_DECL, 9251 ffecom_get_invented_identifier ("__g77_vardesc_%d", 9252 mynumber++), 9253 vardesctype); 9254 TREE_STATIC (var) = 1; 9255 DECL_INITIAL (var) = error_mark_node; 9256 9257 var = start_decl (var, FALSE); 9258 9259 /* Process inits. */ 9260 9261 nameinit = ffecom_build_f2c_string_ ((i = strlen (ffesymbol_text (s))) 9262 + 1, 9263 ffesymbol_text (s)); 9264 TREE_TYPE (nameinit) 9265 = build_type_variant 9266 (build_array_type 9267 (char_type_node, 9268 build_range_type (integer_type_node, 9269 integer_one_node, 9270 build_int_2 (i, 0))), 9271 1, 0); 9272 TREE_CONSTANT (nameinit) = 1; 9273 TREE_STATIC (nameinit) = 1; 9274 nameinit = ffecom_1 (ADDR_EXPR, 9275 build_pointer_type (TREE_TYPE (nameinit)), 9276 nameinit); 9277 9278 addrinit = ffecom_arg_ptr_to_expr (expr, &typeinit); 9279 9280 dimsinit = ffecom_vardesc_dims_ (s); 9281 9282 if (typeinit == NULL_TREE) 9283 { 9284 ffeinfoBasictype bt = ffesymbol_basictype (s); 9285 ffeinfoKindtype kt = ffesymbol_kindtype (s); 9286 int tc = ffecom_f2c_typecode (bt, kt); 9287 9288 assert (tc != -1); 9289 typeinit = build_int_2 (tc, (tc < 0) ? -1 : 0); 9290 } 9291 else 9292 typeinit = ffecom_1 (NEGATE_EXPR, TREE_TYPE (typeinit), typeinit); 9293 9294 varinits = build_tree_list ((field = TYPE_FIELDS (vardesctype)), 9295 nameinit); 9296 TREE_CHAIN (varinits) = build_tree_list ((field = TREE_CHAIN (field)), 9297 addrinit); 9298 TREE_CHAIN (TREE_CHAIN (varinits)) 9299 = build_tree_list ((field = TREE_CHAIN (field)), dimsinit); 9300 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (varinits))) 9301 = build_tree_list ((field = TREE_CHAIN (field)), typeinit); 9302 9303 varinits = build (CONSTRUCTOR, vardesctype, NULL_TREE, varinits); 9304 TREE_CONSTANT (varinits) = 1; 9305 TREE_STATIC (varinits) = 1; 9306 9307 finish_decl (var, varinits, FALSE); 9308 9309 var = ffecom_1 (ADDR_EXPR, build_pointer_type (vardesctype), var); 9310 9311 ffesymbol_hook (s).vardesc_tree = var; 9312 } 9313 9314 return ffesymbol_hook (s).vardesc_tree; 9315 } 9316 9317 static tree 9318 ffecom_vardesc_array_ (ffesymbol s) 9319 { 9320 ffebld b; 9321 tree list; 9322 tree item = NULL_TREE; 9323 tree var; 9324 int i; 9325 static int mynumber = 0; 9326 9327 for (i = 0, list = NULL_TREE, b = ffesymbol_namelist (s); 9328 b != NULL; 9329 b = ffebld_trail (b), ++i) 9330 { 9331 tree t; 9332 9333 t = ffecom_vardesc_ (ffebld_head (b)); 9334 9335 if (list == NULL_TREE) 9336 list = item = build_tree_list (NULL_TREE, t); 9337 else 9338 { 9339 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t); 9340 item = TREE_CHAIN (item); 9341 } 9342 } 9343 9344 item = build_array_type (build_pointer_type (ffecom_type_vardesc_ ()), 9345 build_range_type (integer_type_node, 9346 integer_one_node, 9347 build_int_2 (i, 0))); 9348 list = build (CONSTRUCTOR, item, NULL_TREE, list); 9349 TREE_CONSTANT (list) = 1; 9350 TREE_STATIC (list) = 1; 9351 9352 var = ffecom_get_invented_identifier ("__g77_vardesc_array_%d", mynumber++); 9353 var = build_decl (VAR_DECL, var, item); 9354 TREE_STATIC (var) = 1; 9355 DECL_INITIAL (var) = error_mark_node; 9356 var = start_decl (var, FALSE); 9357 finish_decl (var, list, FALSE); 9358 9359 return var; 9360 } 9361 9362 static tree 9363 ffecom_vardesc_dims_ (ffesymbol s) 9364 { 9365 if (ffesymbol_dims (s) == NULL) 9366 return convert (ffecom_f2c_ptr_to_ftnlen_type_node, 9367 integer_zero_node); 9368 9369 { 9370 ffebld b; 9371 ffebld e; 9372 tree list; 9373 tree backlist; 9374 tree item = NULL_TREE; 9375 tree var; 9376 tree numdim; 9377 tree numelem; 9378 tree baseoff = NULL_TREE; 9379 static int mynumber = 0; 9380 9381 numdim = build_int_2 ((int) ffesymbol_rank (s), 0); 9382 TREE_TYPE (numdim) = ffecom_f2c_ftnlen_type_node; 9383 9384 numelem = ffecom_expr (ffesymbol_arraysize (s)); 9385 TREE_TYPE (numelem) = ffecom_f2c_ftnlen_type_node; 9386 9387 list = NULL_TREE; 9388 backlist = NULL_TREE; 9389 for (b = ffesymbol_dims (s), e = ffesymbol_extents (s); 9390 b != NULL; 9391 b = ffebld_trail (b), e = ffebld_trail (e)) 9392 { 9393 tree t; 9394 tree low; 9395 tree back; 9396 9397 if (ffebld_trail (b) == NULL) 9398 t = NULL_TREE; 9399 else 9400 { 9401 t = convert (ffecom_f2c_ftnlen_type_node, 9402 ffecom_expr (ffebld_head (e))); 9403 9404 if (list == NULL_TREE) 9405 list = item = build_tree_list (NULL_TREE, t); 9406 else 9407 { 9408 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t); 9409 item = TREE_CHAIN (item); 9410 } 9411 } 9412 9413 if (ffebld_left (ffebld_head (b)) == NULL) 9414 low = ffecom_integer_one_node; 9415 else 9416 low = ffecom_expr (ffebld_left (ffebld_head (b))); 9417 low = convert (ffecom_f2c_ftnlen_type_node, low); 9418 9419 back = build_tree_list (low, t); 9420 TREE_CHAIN (back) = backlist; 9421 backlist = back; 9422 } 9423 9424 for (item = backlist; item != NULL_TREE; item = TREE_CHAIN (item)) 9425 { 9426 if (TREE_VALUE (item) == NULL_TREE) 9427 baseoff = TREE_PURPOSE (item); 9428 else 9429 baseoff = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node, 9430 TREE_PURPOSE (item), 9431 ffecom_2 (MULT_EXPR, 9432 ffecom_f2c_ftnlen_type_node, 9433 TREE_VALUE (item), 9434 baseoff)); 9435 } 9436 9437 /* backlist now dead, along with all TREE_PURPOSEs on it. */ 9438 9439 baseoff = build_tree_list (NULL_TREE, baseoff); 9440 TREE_CHAIN (baseoff) = list; 9441 9442 numelem = build_tree_list (NULL_TREE, numelem); 9443 TREE_CHAIN (numelem) = baseoff; 9444 9445 numdim = build_tree_list (NULL_TREE, numdim); 9446 TREE_CHAIN (numdim) = numelem; 9447 9448 item = build_array_type (ffecom_f2c_ftnlen_type_node, 9449 build_range_type (integer_type_node, 9450 integer_zero_node, 9451 build_int_2 9452 ((int) ffesymbol_rank (s) 9453 + 2, 0))); 9454 list = build (CONSTRUCTOR, item, NULL_TREE, numdim); 9455 TREE_CONSTANT (list) = 1; 9456 TREE_STATIC (list) = 1; 9457 9458 var = ffecom_get_invented_identifier ("__g77_dims_%d", mynumber++); 9459 var = build_decl (VAR_DECL, var, item); 9460 TREE_STATIC (var) = 1; 9461 DECL_INITIAL (var) = error_mark_node; 9462 var = start_decl (var, FALSE); 9463 finish_decl (var, list, FALSE); 9464 9465 var = ffecom_1 (ADDR_EXPR, build_pointer_type (item), var); 9466 9467 return var; 9468 } 9469 } 9470 9471 /* Essentially does a "fold (build1 (code, type, node))" while checking 9472 for certain housekeeping things. 9473 9474 NOTE: for building an ADDR_EXPR around a FUNCTION_DECL, use 9475 ffecom_1_fn instead. */ 9476 9477 tree 9478 ffecom_1 (enum tree_code code, tree type, tree node) 9479 { 9480 tree item; 9481 9482 if ((node == error_mark_node) 9483 || (type == error_mark_node)) 9484 return error_mark_node; 9485 9486 if (code == ADDR_EXPR) 9487 { 9488 if (!ffe_mark_addressable (node)) 9489 assert ("can't mark_addressable this node!" == NULL); 9490 } 9491 9492 switch (ffe_is_emulate_complex () ? code : NOP_EXPR) 9493 { 9494 tree realtype; 9495 9496 case REALPART_EXPR: 9497 item = build (COMPONENT_REF, type, node, TYPE_FIELDS (TREE_TYPE (node))); 9498 break; 9499 9500 case IMAGPART_EXPR: 9501 item = build (COMPONENT_REF, type, node, TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (node)))); 9502 break; 9503 9504 9505 case NEGATE_EXPR: 9506 if (TREE_CODE (type) != RECORD_TYPE) 9507 { 9508 item = build1 (code, type, node); 9509 break; 9510 } 9511 node = ffecom_stabilize_aggregate_ (node); 9512 realtype = TREE_TYPE (TYPE_FIELDS (type)); 9513 item = 9514 ffecom_2 (COMPLEX_EXPR, type, 9515 ffecom_1 (NEGATE_EXPR, realtype, 9516 ffecom_1 (REALPART_EXPR, realtype, 9517 node)), 9518 ffecom_1 (NEGATE_EXPR, realtype, 9519 ffecom_1 (IMAGPART_EXPR, realtype, 9520 node))); 9521 break; 9522 9523 default: 9524 item = build1 (code, type, node); 9525 break; 9526 } 9527 9528 if (TREE_SIDE_EFFECTS (node)) 9529 TREE_SIDE_EFFECTS (item) = 1; 9530 if (code == ADDR_EXPR && staticp (node)) 9531 TREE_CONSTANT (item) = 1; 9532 else if (code == INDIRECT_REF) 9533 TREE_READONLY (item) = TYPE_READONLY (type); 9534 return fold (item); 9535 } 9536 9537 /* Like ffecom_1 (ADDR_EXPR, TREE_TYPE (node), node), except 9538 handles TREE_CODE (node) == FUNCTION_DECL. In particular, 9539 does not set TREE_ADDRESSABLE (because calling an inline 9540 function does not mean the function needs to be separately 9541 compiled). */ 9542 9543 tree 9544 ffecom_1_fn (tree node) 9545 { 9546 tree item; 9547 tree type; 9548 9549 if (node == error_mark_node) 9550 return error_mark_node; 9551 9552 type = build_type_variant (TREE_TYPE (node), 9553 TREE_READONLY (node), 9554 TREE_THIS_VOLATILE (node)); 9555 item = build1 (ADDR_EXPR, 9556 build_pointer_type (type), node); 9557 if (TREE_SIDE_EFFECTS (node)) 9558 TREE_SIDE_EFFECTS (item) = 1; 9559 if (staticp (node)) 9560 TREE_CONSTANT (item) = 1; 9561 return fold (item); 9562 } 9563 9564 /* Essentially does a "fold (build (code, type, node1, node2))" while 9565 checking for certain housekeeping things. */ 9566 9567 tree 9568 ffecom_2 (enum tree_code code, tree type, tree node1, 9569 tree node2) 9570 { 9571 tree item; 9572 9573 if ((node1 == error_mark_node) 9574 || (node2 == error_mark_node) 9575 || (type == error_mark_node)) 9576 return error_mark_node; 9577 9578 switch (ffe_is_emulate_complex () ? code : NOP_EXPR) 9579 { 9580 tree a, b, c, d, realtype; 9581 9582 case CONJ_EXPR: 9583 assert ("no CONJ_EXPR support yet" == NULL); 9584 return error_mark_node; 9585 9586 case COMPLEX_EXPR: 9587 item = build_tree_list (TYPE_FIELDS (type), node1); 9588 TREE_CHAIN (item) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), node2); 9589 item = build (CONSTRUCTOR, type, NULL_TREE, item); 9590 break; 9591 9592 case PLUS_EXPR: 9593 if (TREE_CODE (type) != RECORD_TYPE) 9594 { 9595 item = build (code, type, node1, node2); 9596 break; 9597 } 9598 node1 = ffecom_stabilize_aggregate_ (node1); 9599 node2 = ffecom_stabilize_aggregate_ (node2); 9600 realtype = TREE_TYPE (TYPE_FIELDS (type)); 9601 item = 9602 ffecom_2 (COMPLEX_EXPR, type, 9603 ffecom_2 (PLUS_EXPR, realtype, 9604 ffecom_1 (REALPART_EXPR, realtype, 9605 node1), 9606 ffecom_1 (REALPART_EXPR, realtype, 9607 node2)), 9608 ffecom_2 (PLUS_EXPR, realtype, 9609 ffecom_1 (IMAGPART_EXPR, realtype, 9610 node1), 9611 ffecom_1 (IMAGPART_EXPR, realtype, 9612 node2))); 9613 break; 9614 9615 case MINUS_EXPR: 9616 if (TREE_CODE (type) != RECORD_TYPE) 9617 { 9618 item = build (code, type, node1, node2); 9619 break; 9620 } 9621 node1 = ffecom_stabilize_aggregate_ (node1); 9622 node2 = ffecom_stabilize_aggregate_ (node2); 9623 realtype = TREE_TYPE (TYPE_FIELDS (type)); 9624 item = 9625 ffecom_2 (COMPLEX_EXPR, type, 9626 ffecom_2 (MINUS_EXPR, realtype, 9627 ffecom_1 (REALPART_EXPR, realtype, 9628 node1), 9629 ffecom_1 (REALPART_EXPR, realtype, 9630 node2)), 9631 ffecom_2 (MINUS_EXPR, realtype, 9632 ffecom_1 (IMAGPART_EXPR, realtype, 9633 node1), 9634 ffecom_1 (IMAGPART_EXPR, realtype, 9635 node2))); 9636 break; 9637 9638 case MULT_EXPR: 9639 if (TREE_CODE (type) != RECORD_TYPE) 9640 { 9641 item = build (code, type, node1, node2); 9642 break; 9643 } 9644 node1 = ffecom_stabilize_aggregate_ (node1); 9645 node2 = ffecom_stabilize_aggregate_ (node2); 9646 realtype = TREE_TYPE (TYPE_FIELDS (type)); 9647 a = save_expr (ffecom_1 (REALPART_EXPR, realtype, 9648 node1)); 9649 b = save_expr (ffecom_1 (IMAGPART_EXPR, realtype, 9650 node1)); 9651 c = save_expr (ffecom_1 (REALPART_EXPR, realtype, 9652 node2)); 9653 d = save_expr (ffecom_1 (IMAGPART_EXPR, realtype, 9654 node2)); 9655 item = 9656 ffecom_2 (COMPLEX_EXPR, type, 9657 ffecom_2 (MINUS_EXPR, realtype, 9658 ffecom_2 (MULT_EXPR, realtype, 9659 a, 9660 c), 9661 ffecom_2 (MULT_EXPR, realtype, 9662 b, 9663 d)), 9664 ffecom_2 (PLUS_EXPR, realtype, 9665 ffecom_2 (MULT_EXPR, realtype, 9666 a, 9667 d), 9668 ffecom_2 (MULT_EXPR, realtype, 9669 c, 9670 b))); 9671 break; 9672 9673 case EQ_EXPR: 9674 if ((TREE_CODE (node1) != RECORD_TYPE) 9675 && (TREE_CODE (node2) != RECORD_TYPE)) 9676 { 9677 item = build (code, type, node1, node2); 9678 break; 9679 } 9680 assert (TREE_CODE (node1) == RECORD_TYPE); 9681 assert (TREE_CODE (node2) == RECORD_TYPE); 9682 node1 = ffecom_stabilize_aggregate_ (node1); 9683 node2 = ffecom_stabilize_aggregate_ (node2); 9684 realtype = TREE_TYPE (TYPE_FIELDS (type)); 9685 item = 9686 ffecom_2 (TRUTH_ANDIF_EXPR, type, 9687 ffecom_2 (code, type, 9688 ffecom_1 (REALPART_EXPR, realtype, 9689 node1), 9690 ffecom_1 (REALPART_EXPR, realtype, 9691 node2)), 9692 ffecom_2 (code, type, 9693 ffecom_1 (IMAGPART_EXPR, realtype, 9694 node1), 9695 ffecom_1 (IMAGPART_EXPR, realtype, 9696 node2))); 9697 break; 9698 9699 case NE_EXPR: 9700 if ((TREE_CODE (node1) != RECORD_TYPE) 9701 && (TREE_CODE (node2) != RECORD_TYPE)) 9702 { 9703 item = build (code, type, node1, node2); 9704 break; 9705 } 9706 assert (TREE_CODE (node1) == RECORD_TYPE); 9707 assert (TREE_CODE (node2) == RECORD_TYPE); 9708 node1 = ffecom_stabilize_aggregate_ (node1); 9709 node2 = ffecom_stabilize_aggregate_ (node2); 9710 realtype = TREE_TYPE (TYPE_FIELDS (type)); 9711 item = 9712 ffecom_2 (TRUTH_ORIF_EXPR, type, 9713 ffecom_2 (code, type, 9714 ffecom_1 (REALPART_EXPR, realtype, 9715 node1), 9716 ffecom_1 (REALPART_EXPR, realtype, 9717 node2)), 9718 ffecom_2 (code, type, 9719 ffecom_1 (IMAGPART_EXPR, realtype, 9720 node1), 9721 ffecom_1 (IMAGPART_EXPR, realtype, 9722 node2))); 9723 break; 9724 9725 default: 9726 item = build (code, type, node1, node2); 9727 break; 9728 } 9729 9730 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2)) 9731 TREE_SIDE_EFFECTS (item) = 1; 9732 return fold (item); 9733 } 9734 9735 /* ffecom_2pass_advise_entrypoint -- Advise that there's this entrypoint 9736 9737 ffesymbol s; // the ENTRY point itself 9738 if (ffecom_2pass_advise_entrypoint(s)) 9739 // the ENTRY point has been accepted 9740 9741 Does whatever compiler needs to do when it learns about the entrypoint, 9742 like determine the return type of the master function, count the 9743 number of entrypoints, etc. Returns FALSE if the return type is 9744 not compatible with the return type(s) of other entrypoint(s). 9745 9746 NOTE: for every call to this fn that returns TRUE, _do_entrypoint must 9747 later (after _finish_progunit) be called with the same entrypoint(s) 9748 as passed to this fn for which TRUE was returned. 9749 9750 03-Jan-92 JCB 2.0 9751 Return FALSE if the return type conflicts with previous entrypoints. */ 9752 9753 bool 9754 ffecom_2pass_advise_entrypoint (ffesymbol entry) 9755 { 9756 ffebld list; /* opITEM. */ 9757 ffebld mlist; /* opITEM. */ 9758 ffebld plist; /* opITEM. */ 9759 ffebld arg; /* ffebld_head(opITEM). */ 9760 ffebld item; /* opITEM. */ 9761 ffesymbol s; /* ffebld_symter(arg). */ 9762 ffeinfoBasictype bt = ffesymbol_basictype (entry); 9763 ffeinfoKindtype kt = ffesymbol_kindtype (entry); 9764 ffetargetCharacterSize size = ffesymbol_size (entry); 9765 bool ok; 9766 9767 if (ffecom_num_entrypoints_ == 0) 9768 { /* First entrypoint, make list of main 9769 arglist's dummies. */ 9770 assert (ffecom_primary_entry_ != NULL); 9771 9772 ffecom_master_bt_ = ffesymbol_basictype (ffecom_primary_entry_); 9773 ffecom_master_kt_ = ffesymbol_kindtype (ffecom_primary_entry_); 9774 ffecom_master_size_ = ffesymbol_size (ffecom_primary_entry_); 9775 9776 for (plist = NULL, list = ffesymbol_dummyargs (ffecom_primary_entry_); 9777 list != NULL; 9778 list = ffebld_trail (list)) 9779 { 9780 arg = ffebld_head (list); 9781 if (ffebld_op (arg) != FFEBLD_opSYMTER) 9782 continue; /* Alternate return or some such thing. */ 9783 item = ffebld_new_item (arg, NULL); 9784 if (plist == NULL) 9785 ffecom_master_arglist_ = item; 9786 else 9787 ffebld_set_trail (plist, item); 9788 plist = item; 9789 } 9790 } 9791 9792 /* If necessary, scan entry arglist for alternate returns. Do this scan 9793 apparently redundantly (it's done below to UNIONize the arglists) so 9794 that we don't complain about RETURN 1 if an offending ENTRY is the only 9795 one with an alternate return. */ 9796 9797 if (!ffecom_is_altreturning_) 9798 { 9799 for (list = ffesymbol_dummyargs (entry); 9800 list != NULL; 9801 list = ffebld_trail (list)) 9802 { 9803 arg = ffebld_head (list); 9804 if (ffebld_op (arg) == FFEBLD_opSTAR) 9805 { 9806 ffecom_is_altreturning_ = TRUE; 9807 break; 9808 } 9809 } 9810 } 9811 9812 /* Now check type compatibility. */ 9813 9814 switch (ffecom_master_bt_) 9815 { 9816 case FFEINFO_basictypeNONE: 9817 ok = (bt != FFEINFO_basictypeCHARACTER); 9818 break; 9819 9820 case FFEINFO_basictypeCHARACTER: 9821 ok 9822 = (bt == FFEINFO_basictypeCHARACTER) 9823 && (kt == ffecom_master_kt_) 9824 && (size == ffecom_master_size_); 9825 break; 9826 9827 case FFEINFO_basictypeANY: 9828 return FALSE; /* Just don't bother. */ 9829 9830 default: 9831 if (bt == FFEINFO_basictypeCHARACTER) 9832 { 9833 ok = FALSE; 9834 break; 9835 } 9836 ok = TRUE; 9837 if ((bt != ffecom_master_bt_) || (kt != ffecom_master_kt_)) 9838 { 9839 ffecom_master_bt_ = FFEINFO_basictypeNONE; 9840 ffecom_master_kt_ = FFEINFO_kindtypeNONE; 9841 } 9842 break; 9843 } 9844 9845 if (!ok) 9846 { 9847 ffebad_start (FFEBAD_ENTRY_CONFLICTS); 9848 ffest_ffebad_here_current_stmt (0); 9849 ffebad_finish (); 9850 return FALSE; /* Can't handle entrypoint. */ 9851 } 9852 9853 /* Entrypoint type compatible with previous types. */ 9854 9855 ++ffecom_num_entrypoints_; 9856 9857 /* Master-arg-list = UNION(Master-arg-list,entry-arg-list). */ 9858 9859 for (list = ffesymbol_dummyargs (entry); 9860 list != NULL; 9861 list = ffebld_trail (list)) 9862 { 9863 arg = ffebld_head (list); 9864 if (ffebld_op (arg) != FFEBLD_opSYMTER) 9865 continue; /* Alternate return or some such thing. */ 9866 s = ffebld_symter (arg); 9867 for (plist = NULL, mlist = ffecom_master_arglist_; 9868 mlist != NULL; 9869 plist = mlist, mlist = ffebld_trail (mlist)) 9870 { /* plist points to previous item for easy 9871 appending of arg. */ 9872 if (ffebld_symter (ffebld_head (mlist)) == s) 9873 break; /* Already have this arg in the master list. */ 9874 } 9875 if (mlist != NULL) 9876 continue; /* Already have this arg in the master list. */ 9877 9878 /* Append this arg to the master list. */ 9879 9880 item = ffebld_new_item (arg, NULL); 9881 if (plist == NULL) 9882 ffecom_master_arglist_ = item; 9883 else 9884 ffebld_set_trail (plist, item); 9885 } 9886 9887 return TRUE; 9888 } 9889 9890 /* ffecom_2pass_do_entrypoint -- Do compilation of entrypoint 9891 9892 ffesymbol s; // the ENTRY point itself 9893 ffecom_2pass_do_entrypoint(s); 9894 9895 Does whatever compiler needs to do to make the entrypoint actually 9896 happen. Must be called for each entrypoint after 9897 ffecom_finish_progunit is called. */ 9898 9899 void 9900 ffecom_2pass_do_entrypoint (ffesymbol entry) 9901 { 9902 static int mfn_num = 0; 9903 static int ent_num; 9904 9905 if (mfn_num != ffecom_num_fns_) 9906 { /* First entrypoint for this program unit. */ 9907 ent_num = 1; 9908 mfn_num = ffecom_num_fns_; 9909 ffecom_do_entry_ (ffecom_primary_entry_, 0); 9910 } 9911 else 9912 ++ent_num; 9913 9914 --ffecom_num_entrypoints_; 9915 9916 ffecom_do_entry_ (entry, ent_num); 9917 } 9918 9919 /* Essentially does a "fold (build (code, type, node1, node2))" while 9920 checking for certain housekeeping things. Always sets 9921 TREE_SIDE_EFFECTS. */ 9922 9923 tree 9924 ffecom_2s (enum tree_code code, tree type, tree node1, 9925 tree node2) 9926 { 9927 tree item; 9928 9929 if ((node1 == error_mark_node) 9930 || (node2 == error_mark_node) 9931 || (type == error_mark_node)) 9932 return error_mark_node; 9933 9934 item = build (code, type, node1, node2); 9935 TREE_SIDE_EFFECTS (item) = 1; 9936 return fold (item); 9937 } 9938 9939 /* Essentially does a "fold (build (code, type, node1, node2, node3))" while 9940 checking for certain housekeeping things. */ 9941 9942 tree 9943 ffecom_3 (enum tree_code code, tree type, tree node1, 9944 tree node2, tree node3) 9945 { 9946 tree item; 9947 9948 if ((node1 == error_mark_node) 9949 || (node2 == error_mark_node) 9950 || (node3 == error_mark_node) 9951 || (type == error_mark_node)) 9952 return error_mark_node; 9953 9954 item = build (code, type, node1, node2, node3); 9955 if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2) 9956 || (node3 != NULL_TREE && TREE_SIDE_EFFECTS (node3))) 9957 TREE_SIDE_EFFECTS (item) = 1; 9958 return fold (item); 9959 } 9960 9961 /* Essentially does a "fold (build (code, type, node1, node2, node3))" while 9962 checking for certain housekeeping things. Always sets 9963 TREE_SIDE_EFFECTS. */ 9964 9965 tree 9966 ffecom_3s (enum tree_code code, tree type, tree node1, 9967 tree node2, tree node3) 9968 { 9969 tree item; 9970 9971 if ((node1 == error_mark_node) 9972 || (node2 == error_mark_node) 9973 || (node3 == error_mark_node) 9974 || (type == error_mark_node)) 9975 return error_mark_node; 9976 9977 item = build (code, type, node1, node2, node3); 9978 TREE_SIDE_EFFECTS (item) = 1; 9979 return fold (item); 9980 } 9981 9982 /* ffecom_arg_expr -- Transform argument expr into gcc tree 9983 9984 See use by ffecom_list_expr. 9985 9986 If expression is NULL, returns an integer zero tree. If it is not 9987 a CHARACTER expression, returns whatever ffecom_expr 9988 returns and sets the length return value to NULL_TREE. Otherwise 9989 generates code to evaluate the character expression, returns the proper 9990 pointer to the result, but does NOT set the length return value to a tree 9991 that specifies the length of the result. (In other words, the length 9992 variable is always set to NULL_TREE, because a length is never passed.) 9993 9994 21-Dec-91 JCB 1.1 9995 Don't set returned length, since nobody needs it (yet; someday if 9996 we allow CHARACTER*(*) dummies to statement functions, we'll need 9997 it). */ 9998 9999 tree 10000 ffecom_arg_expr (ffebld expr, tree *length) 10001 { 10002 tree ign; 10003 10004 *length = NULL_TREE; 10005 10006 if (expr == NULL) 10007 return integer_zero_node; 10008 10009 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER) 10010 return ffecom_expr (expr); 10011 10012 return ffecom_arg_ptr_to_expr (expr, &ign); 10013 } 10014 10015 /* Transform expression into constant argument-pointer-to-expression tree. 10016 10017 If the expression can be transformed into a argument-pointer-to-expression 10018 tree that is constant, that is done, and the tree returned. Else 10019 NULL_TREE is returned. 10020 10021 That way, a caller can attempt to provide compile-time initialization 10022 of a variable and, if that fails, *then* choose to start a new block 10023 and resort to using temporaries, as appropriate. */ 10024 10025 tree 10026 ffecom_arg_ptr_to_const_expr (ffebld expr, tree *length) 10027 { 10028 if (! expr) 10029 return integer_zero_node; 10030 10031 if (ffebld_op (expr) == FFEBLD_opANY) 10032 { 10033 if (length) 10034 *length = error_mark_node; 10035 return error_mark_node; 10036 } 10037 10038 if (ffebld_arity (expr) == 0 10039 && (ffebld_op (expr) != FFEBLD_opSYMTER 10040 || ffebld_where (expr) == FFEINFO_whereCOMMON 10041 || ffebld_where (expr) == FFEINFO_whereGLOBAL 10042 || ffebld_where (expr) == FFEINFO_whereINTRINSIC)) 10043 { 10044 tree t; 10045 10046 t = ffecom_arg_ptr_to_expr (expr, length); 10047 assert (TREE_CONSTANT (t)); 10048 assert (! length || TREE_CONSTANT (*length)); 10049 return t; 10050 } 10051 10052 if (length 10053 && ffebld_size (expr) != FFETARGET_charactersizeNONE) 10054 *length = build_int_2 (ffebld_size (expr), 0); 10055 else if (length) 10056 *length = NULL_TREE; 10057 return NULL_TREE; 10058 } 10059 10060 /* ffecom_arg_ptr_to_expr -- Transform argument expr into gcc tree 10061 10062 See use by ffecom_list_ptr_to_expr. 10063 10064 If expression is NULL, returns an integer zero tree. If it is not 10065 a CHARACTER expression, returns whatever ffecom_ptr_to_expr 10066 returns and sets the length return value to NULL_TREE. Otherwise 10067 generates code to evaluate the character expression, returns the proper 10068 pointer to the result, AND sets the length return value to a tree that 10069 specifies the length of the result. 10070 10071 If the length argument is NULL, this is a slightly special 10072 case of building a FORMAT expression, that is, an expression that 10073 will be used at run time without regard to length. For the current 10074 implementation, which uses the libf2c library, this means it is nice 10075 to append a null byte to the end of the expression, where feasible, 10076 to make sure any diagnostic about the FORMAT string terminates at 10077 some useful point. 10078 10079 For now, treat %REF(char-expr) as the same as char-expr with a NULL 10080 length argument. This might even be seen as a feature, if a null 10081 byte can always be appended. */ 10082 10083 tree 10084 ffecom_arg_ptr_to_expr (ffebld expr, tree *length) 10085 { 10086 tree item; 10087 tree ign_length; 10088 ffecomConcatList_ catlist; 10089 10090 if (length != NULL) 10091 *length = NULL_TREE; 10092 10093 if (expr == NULL) 10094 return integer_zero_node; 10095 10096 switch (ffebld_op (expr)) 10097 { 10098 case FFEBLD_opPERCENT_VAL: 10099 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER) 10100 return ffecom_expr (ffebld_left (expr)); 10101 { 10102 tree temp_exp; 10103 tree temp_length; 10104 10105 temp_exp = ffecom_arg_ptr_to_expr (ffebld_left (expr), &temp_length); 10106 if (temp_exp == error_mark_node) 10107 return error_mark_node; 10108 10109 return ffecom_1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (temp_exp)), 10110 temp_exp); 10111 } 10112 10113 case FFEBLD_opPERCENT_REF: 10114 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER) 10115 return ffecom_ptr_to_expr (ffebld_left (expr)); 10116 if (length != NULL) 10117 { 10118 ign_length = NULL_TREE; 10119 length = &ign_length; 10120 } 10121 expr = ffebld_left (expr); 10122 break; 10123 10124 case FFEBLD_opPERCENT_DESCR: 10125 switch (ffeinfo_basictype (ffebld_info (expr))) 10126 { 10127 #ifdef PASS_HOLLERITH_BY_DESCRIPTOR 10128 case FFEINFO_basictypeHOLLERITH: 10129 #endif 10130 case FFEINFO_basictypeCHARACTER: 10131 break; /* Passed by descriptor anyway. */ 10132 10133 default: 10134 item = ffecom_ptr_to_expr (expr); 10135 if (item != error_mark_node) 10136 *length = TYPE_SIZE (TREE_TYPE (TREE_TYPE (item))); 10137 break; 10138 } 10139 break; 10140 10141 default: 10142 break; 10143 } 10144 10145 #ifdef PASS_HOLLERITH_BY_DESCRIPTOR 10146 if ((ffeinfo_basictype (ffebld_info (expr)) == FFEINFO_basictypeHOLLERITH) 10147 && (length != NULL)) 10148 { /* Pass Hollerith by descriptor. */ 10149 ffetargetHollerith h; 10150 10151 assert (ffebld_op (expr) == FFEBLD_opCONTER); 10152 h = ffebld_cu_val_hollerith (ffebld_constant_union 10153 (ffebld_conter (expr))); 10154 *length 10155 = build_int_2 (h.length, 0); 10156 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node; 10157 } 10158 #endif 10159 10160 if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER) 10161 return ffecom_ptr_to_expr (expr); 10162 10163 assert (ffeinfo_kindtype (ffebld_info (expr)) 10164 == FFEINFO_kindtypeCHARACTER1); 10165 10166 while (ffebld_op (expr) == FFEBLD_opPAREN) 10167 expr = ffebld_left (expr); 10168 10169 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE); 10170 switch (ffecom_concat_list_count_ (catlist)) 10171 { 10172 case 0: /* Shouldn't happen, but in case it does... */ 10173 if (length != NULL) 10174 { 10175 *length = ffecom_f2c_ftnlen_zero_node; 10176 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node; 10177 } 10178 ffecom_concat_list_kill_ (catlist); 10179 return null_pointer_node; 10180 10181 case 1: /* The (fairly) easy case. */ 10182 if (length == NULL) 10183 ffecom_char_args_with_null_ (&item, &ign_length, 10184 ffecom_concat_list_expr_ (catlist, 0)); 10185 else 10186 ffecom_char_args_ (&item, length, 10187 ffecom_concat_list_expr_ (catlist, 0)); 10188 ffecom_concat_list_kill_ (catlist); 10189 assert (item != NULL_TREE); 10190 return item; 10191 10192 default: /* Must actually concatenate things. */ 10193 break; 10194 } 10195 10196 { 10197 int count = ffecom_concat_list_count_ (catlist); 10198 int i; 10199 tree lengths; 10200 tree items; 10201 tree length_array; 10202 tree item_array; 10203 tree citem; 10204 tree clength; 10205 tree temporary; 10206 tree num; 10207 tree known_length; 10208 ffetargetCharacterSize sz; 10209 10210 sz = ffecom_concat_list_maxlen_ (catlist); 10211 /* ~~Kludge! */ 10212 assert (sz != FFETARGET_charactersizeNONE); 10213 10214 { 10215 tree hook; 10216 10217 hook = ffebld_nonter_hook (expr); 10218 assert (hook); 10219 assert (TREE_CODE (hook) == TREE_VEC); 10220 assert (TREE_VEC_LENGTH (hook) == 3); 10221 length_array = lengths = TREE_VEC_ELT (hook, 0); 10222 item_array = items = TREE_VEC_ELT (hook, 1); 10223 temporary = TREE_VEC_ELT (hook, 2); 10224 } 10225 10226 known_length = ffecom_f2c_ftnlen_zero_node; 10227 10228 for (i = 0; i < count; ++i) 10229 { 10230 if ((i == count) 10231 && (length == NULL)) 10232 ffecom_char_args_with_null_ (&citem, &clength, 10233 ffecom_concat_list_expr_ (catlist, i)); 10234 else 10235 ffecom_char_args_ (&citem, &clength, 10236 ffecom_concat_list_expr_ (catlist, i)); 10237 if ((citem == error_mark_node) 10238 || (clength == error_mark_node)) 10239 { 10240 ffecom_concat_list_kill_ (catlist); 10241 *length = error_mark_node; 10242 return error_mark_node; 10243 } 10244 10245 items 10246 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items), 10247 ffecom_modify (void_type_node, 10248 ffecom_2 (ARRAY_REF, 10249 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))), 10250 item_array, 10251 build_int_2 (i, 0)), 10252 citem), 10253 items); 10254 clength = ffecom_save_tree (clength); 10255 if (length != NULL) 10256 known_length 10257 = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node, 10258 known_length, 10259 clength); 10260 lengths 10261 = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths), 10262 ffecom_modify (void_type_node, 10263 ffecom_2 (ARRAY_REF, 10264 TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))), 10265 length_array, 10266 build_int_2 (i, 0)), 10267 clength), 10268 lengths); 10269 } 10270 10271 temporary = ffecom_1 (ADDR_EXPR, 10272 build_pointer_type (TREE_TYPE (temporary)), 10273 temporary); 10274 10275 item = build_tree_list (NULL_TREE, temporary); 10276 TREE_CHAIN (item) 10277 = build_tree_list (NULL_TREE, 10278 ffecom_1 (ADDR_EXPR, 10279 build_pointer_type (TREE_TYPE (items)), 10280 items)); 10281 TREE_CHAIN (TREE_CHAIN (item)) 10282 = build_tree_list (NULL_TREE, 10283 ffecom_1 (ADDR_EXPR, 10284 build_pointer_type (TREE_TYPE (lengths)), 10285 lengths)); 10286 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item))) 10287 = build_tree_list 10288 (NULL_TREE, 10289 ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node, 10290 convert (ffecom_f2c_ftnlen_type_node, 10291 build_int_2 (count, 0)))); 10292 num = build_int_2 (sz, 0); 10293 TREE_TYPE (num) = ffecom_f2c_ftnlen_type_node; 10294 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))) 10295 = build_tree_list (NULL_TREE, num); 10296 10297 item = ffecom_call_gfrt (FFECOM_gfrtCAT, item, NULL_TREE); 10298 TREE_SIDE_EFFECTS (item) = 1; 10299 item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (temporary), 10300 item, 10301 temporary); 10302 10303 if (length != NULL) 10304 *length = known_length; 10305 } 10306 10307 ffecom_concat_list_kill_ (catlist); 10308 assert (item != NULL_TREE); 10309 return item; 10310 } 10311 10312 /* Generate call to run-time function. 10313 10314 The first arg is the GNU Fortran Run-Time function index, the second 10315 arg is the list of arguments to pass to it. Returned is the expression 10316 (WITHOUT TREE_SIDE_EFFECTS set!) that makes the call and returns the 10317 result (which may be void). */ 10318 10319 tree 10320 ffecom_call_gfrt (ffecomGfrt ix, tree args, tree hook) 10321 { 10322 return ffecom_call_ (ffecom_gfrt_tree_ (ix), 10323 ffecom_gfrt_kindtype (ix), 10324 ffe_is_f2c_library () && ffecom_gfrt_complex_[ix], 10325 NULL_TREE, args, NULL_TREE, NULL, 10326 NULL, NULL_TREE, TRUE, hook); 10327 } 10328 10329 /* Transform constant-union to tree. */ 10330 10331 tree 10332 ffecom_constantunion (ffebldConstantUnion *cu, ffeinfoBasictype bt, 10333 ffeinfoKindtype kt, tree tree_type) 10334 { 10335 tree item; 10336 10337 switch (bt) 10338 { 10339 case FFEINFO_basictypeINTEGER: 10340 { 10341 int val; 10342 10343 switch (kt) 10344 { 10345 #if FFETARGET_okINTEGER1 10346 case FFEINFO_kindtypeINTEGER1: 10347 val = ffebld_cu_val_integer1 (*cu); 10348 break; 10349 #endif 10350 10351 #if FFETARGET_okINTEGER2 10352 case FFEINFO_kindtypeINTEGER2: 10353 val = ffebld_cu_val_integer2 (*cu); 10354 break; 10355 #endif 10356 10357 #if FFETARGET_okINTEGER3 10358 case FFEINFO_kindtypeINTEGER3: 10359 val = ffebld_cu_val_integer3 (*cu); 10360 break; 10361 #endif 10362 10363 #if FFETARGET_okINTEGER4 10364 case FFEINFO_kindtypeINTEGER4: 10365 val = ffebld_cu_val_integer4 (*cu); 10366 break; 10367 #endif 10368 10369 default: 10370 assert ("bad INTEGER constant kind type" == NULL); 10371 /* Fall through. */ 10372 case FFEINFO_kindtypeANY: 10373 return error_mark_node; 10374 } 10375 item = build_int_2 (val, (val < 0) ? -1 : 0); 10376 TREE_TYPE (item) = tree_type; 10377 } 10378 break; 10379 10380 case FFEINFO_basictypeLOGICAL: 10381 { 10382 int val; 10383 10384 switch (kt) 10385 { 10386 #if FFETARGET_okLOGICAL1 10387 case FFEINFO_kindtypeLOGICAL1: 10388 val = ffebld_cu_val_logical1 (*cu); 10389 break; 10390 #endif 10391 10392 #if FFETARGET_okLOGICAL2 10393 case FFEINFO_kindtypeLOGICAL2: 10394 val = ffebld_cu_val_logical2 (*cu); 10395 break; 10396 #endif 10397 10398 #if FFETARGET_okLOGICAL3 10399 case FFEINFO_kindtypeLOGICAL3: 10400 val = ffebld_cu_val_logical3 (*cu); 10401 break; 10402 #endif 10403 10404 #if FFETARGET_okLOGICAL4 10405 case FFEINFO_kindtypeLOGICAL4: 10406 val = ffebld_cu_val_logical4 (*cu); 10407 break; 10408 #endif 10409 10410 default: 10411 assert ("bad LOGICAL constant kind type" == NULL); 10412 /* Fall through. */ 10413 case FFEINFO_kindtypeANY: 10414 return error_mark_node; 10415 } 10416 item = build_int_2 (val, (val < 0) ? -1 : 0); 10417 TREE_TYPE (item) = tree_type; 10418 } 10419 break; 10420 10421 case FFEINFO_basictypeREAL: 10422 { 10423 REAL_VALUE_TYPE val; 10424 10425 switch (kt) 10426 { 10427 #if FFETARGET_okREAL1 10428 case FFEINFO_kindtypeREAL1: 10429 val = ffetarget_value_real1 (ffebld_cu_val_real1 (*cu)); 10430 break; 10431 #endif 10432 10433 #if FFETARGET_okREAL2 10434 case FFEINFO_kindtypeREAL2: 10435 val = ffetarget_value_real2 (ffebld_cu_val_real2 (*cu)); 10436 break; 10437 #endif 10438 10439 #if FFETARGET_okREAL3 10440 case FFEINFO_kindtypeREAL3: 10441 val = ffetarget_value_real3 (ffebld_cu_val_real3 (*cu)); 10442 break; 10443 #endif 10444 10445 #if FFETARGET_okREAL4 10446 case FFEINFO_kindtypeREAL4: 10447 val = ffetarget_value_real4 (ffebld_cu_val_real4 (*cu)); 10448 break; 10449 #endif 10450 10451 default: 10452 assert ("bad REAL constant kind type" == NULL); 10453 /* Fall through. */ 10454 case FFEINFO_kindtypeANY: 10455 return error_mark_node; 10456 } 10457 item = build_real (tree_type, val); 10458 } 10459 break; 10460 10461 case FFEINFO_basictypeCOMPLEX: 10462 { 10463 REAL_VALUE_TYPE real; 10464 REAL_VALUE_TYPE imag; 10465 tree el_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt]; 10466 10467 switch (kt) 10468 { 10469 #if FFETARGET_okCOMPLEX1 10470 case FFEINFO_kindtypeREAL1: 10471 real = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).real); 10472 imag = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).imaginary); 10473 break; 10474 #endif 10475 10476 #if FFETARGET_okCOMPLEX2 10477 case FFEINFO_kindtypeREAL2: 10478 real = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).real); 10479 imag = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).imaginary); 10480 break; 10481 #endif 10482 10483 #if FFETARGET_okCOMPLEX3 10484 case FFEINFO_kindtypeREAL3: 10485 real = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).real); 10486 imag = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).imaginary); 10487 break; 10488 #endif 10489 10490 #if FFETARGET_okCOMPLEX4 10491 case FFEINFO_kindtypeREAL4: 10492 real = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).real); 10493 imag = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).imaginary); 10494 break; 10495 #endif 10496 10497 default: 10498 assert ("bad REAL constant kind type" == NULL); 10499 /* Fall through. */ 10500 case FFEINFO_kindtypeANY: 10501 return error_mark_node; 10502 } 10503 item = ffecom_build_complex_constant_ (tree_type, 10504 build_real (el_type, real), 10505 build_real (el_type, imag)); 10506 } 10507 break; 10508 10509 case FFEINFO_basictypeCHARACTER: 10510 { /* Happens only in DATA and similar contexts. */ 10511 ffetargetCharacter1 val; 10512 10513 switch (kt) 10514 { 10515 #if FFETARGET_okCHARACTER1 10516 case FFEINFO_kindtypeLOGICAL1: 10517 val = ffebld_cu_val_character1 (*cu); 10518 break; 10519 #endif 10520 10521 default: 10522 assert ("bad CHARACTER constant kind type" == NULL); 10523 /* Fall through. */ 10524 case FFEINFO_kindtypeANY: 10525 return error_mark_node; 10526 } 10527 item = build_string (ffetarget_length_character1 (val), 10528 ffetarget_text_character1 (val)); 10529 TREE_TYPE (item) 10530 = build_type_variant (build_array_type (char_type_node, 10531 build_range_type 10532 (integer_type_node, 10533 integer_one_node, 10534 build_int_2 10535 (ffetarget_length_character1 10536 (val), 0))), 10537 1, 0); 10538 } 10539 break; 10540 10541 case FFEINFO_basictypeHOLLERITH: 10542 { 10543 ffetargetHollerith h; 10544 10545 h = ffebld_cu_val_hollerith (*cu); 10546 10547 /* If not at least as wide as default INTEGER, widen it. */ 10548 if (h.length >= FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE) 10549 item = build_string (h.length, h.text); 10550 else 10551 { 10552 char str[FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE]; 10553 10554 memcpy (str, h.text, h.length); 10555 memset (&str[h.length], ' ', 10556 FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE 10557 - h.length); 10558 item = build_string (FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE, 10559 str); 10560 } 10561 TREE_TYPE (item) 10562 = build_type_variant (build_array_type (char_type_node, 10563 build_range_type 10564 (integer_type_node, 10565 integer_one_node, 10566 build_int_2 10567 (h.length, 0))), 10568 1, 0); 10569 } 10570 break; 10571 10572 case FFEINFO_basictypeTYPELESS: 10573 { 10574 ffetargetInteger1 ival; 10575 ffetargetTypeless tless; 10576 ffebad error; 10577 10578 tless = ffebld_cu_val_typeless (*cu); 10579 error = ffetarget_convert_integer1_typeless (&ival, tless); 10580 assert (error == FFEBAD); 10581 10582 item = build_int_2 ((int) ival, 0); 10583 } 10584 break; 10585 10586 default: 10587 assert ("not yet on constant type" == NULL); 10588 /* Fall through. */ 10589 case FFEINFO_basictypeANY: 10590 return error_mark_node; 10591 } 10592 10593 TREE_CONSTANT (item) = 1; 10594 10595 return item; 10596 } 10597 10598 /* Transform constant-union to tree, with the type known. */ 10599 10600 tree 10601 ffecom_constantunion_with_type (ffebldConstantUnion *cu, 10602 tree tree_type, ffebldConst ct) 10603 { 10604 tree item; 10605 10606 int val; 10607 10608 switch (ct) 10609 { 10610 #if FFETARGET_okINTEGER1 10611 case FFEBLD_constINTEGER1: 10612 val = ffebld_cu_val_integer1 (*cu); 10613 item = build_int_2 (val, (val < 0) ? -1 : 0); 10614 break; 10615 #endif 10616 #if FFETARGET_okINTEGER2 10617 case FFEBLD_constINTEGER2: 10618 val = ffebld_cu_val_integer2 (*cu); 10619 item = build_int_2 (val, (val < 0) ? -1 : 0); 10620 break; 10621 #endif 10622 #if FFETARGET_okINTEGER3 10623 case FFEBLD_constINTEGER3: 10624 val = ffebld_cu_val_integer3 (*cu); 10625 item = build_int_2 (val, (val < 0) ? -1 : 0); 10626 break; 10627 #endif 10628 #if FFETARGET_okINTEGER4 10629 case FFEBLD_constINTEGER4: 10630 val = ffebld_cu_val_integer4 (*cu); 10631 item = build_int_2 (val, (val < 0) ? -1 : 0); 10632 break; 10633 #endif 10634 #if FFETARGET_okLOGICAL1 10635 case FFEBLD_constLOGICAL1: 10636 val = ffebld_cu_val_logical1 (*cu); 10637 item = build_int_2 (val, (val < 0) ? -1 : 0); 10638 break; 10639 #endif 10640 #if FFETARGET_okLOGICAL2 10641 case FFEBLD_constLOGICAL2: 10642 val = ffebld_cu_val_logical2 (*cu); 10643 item = build_int_2 (val, (val < 0) ? -1 : 0); 10644 break; 10645 #endif 10646 #if FFETARGET_okLOGICAL3 10647 case FFEBLD_constLOGICAL3: 10648 val = ffebld_cu_val_logical3 (*cu); 10649 item = build_int_2 (val, (val < 0) ? -1 : 0); 10650 break; 10651 #endif 10652 #if FFETARGET_okLOGICAL4 10653 case FFEBLD_constLOGICAL4: 10654 val = ffebld_cu_val_logical4 (*cu); 10655 item = build_int_2 (val, (val < 0) ? -1 : 0); 10656 break; 10657 #endif 10658 default: 10659 assert ("constant type not supported"==NULL); 10660 return error_mark_node; 10661 break; 10662 } 10663 10664 TREE_TYPE (item) = tree_type; 10665 10666 TREE_CONSTANT (item) = 1; 10667 10668 return item; 10669 } 10670 /* Transform expression into constant tree. 10671 10672 If the expression can be transformed into a tree that is constant, 10673 that is done, and the tree returned. Else NULL_TREE is returned. 10674 10675 That way, a caller can attempt to provide compile-time initialization 10676 of a variable and, if that fails, *then* choose to start a new block 10677 and resort to using temporaries, as appropriate. */ 10678 10679 tree 10680 ffecom_const_expr (ffebld expr) 10681 { 10682 if (! expr) 10683 return integer_zero_node; 10684 10685 if (ffebld_op (expr) == FFEBLD_opANY) 10686 return error_mark_node; 10687 10688 if (ffebld_arity (expr) == 0 10689 && (ffebld_op (expr) != FFEBLD_opSYMTER 10690 #if NEWCOMMON 10691 /* ~~Enable once common/equivalence is handled properly? */ 10692 || ffebld_where (expr) == FFEINFO_whereCOMMON 10693 #endif 10694 || ffebld_where (expr) == FFEINFO_whereGLOBAL 10695 || ffebld_where (expr) == FFEINFO_whereINTRINSIC)) 10696 { 10697 tree t; 10698 10699 t = ffecom_expr (expr); 10700 assert (TREE_CONSTANT (t)); 10701 return t; 10702 } 10703 10704 return NULL_TREE; 10705 } 10706 10707 /* Handy way to make a field in a struct/union. */ 10708 10709 tree 10710 ffecom_decl_field (tree context, tree prevfield, 10711 const char *name, tree type) 10712 { 10713 tree field; 10714 10715 field = build_decl (FIELD_DECL, get_identifier (name), type); 10716 DECL_CONTEXT (field) = context; 10717 DECL_ALIGN (field) = 0; 10718 DECL_USER_ALIGN (field) = 0; 10719 if (prevfield != NULL_TREE) 10720 TREE_CHAIN (prevfield) = field; 10721 10722 return field; 10723 } 10724 10725 void 10726 ffecom_close_include (FILE *f) 10727 { 10728 ffecom_close_include_ (f); 10729 } 10730 10731 int 10732 ffecom_decode_include_option (char *spec) 10733 { 10734 return ffecom_decode_include_option_ (spec); 10735 } 10736 10737 /* End a compound statement (block). */ 10738 10739 tree 10740 ffecom_end_compstmt (void) 10741 { 10742 return bison_rule_compstmt_ (); 10743 } 10744 10745 /* ffecom_end_transition -- Perform end transition on all symbols 10746 10747 ffecom_end_transition(); 10748 10749 Calls ffecom_sym_end_transition for each global and local symbol. */ 10750 10751 void 10752 ffecom_end_transition () 10753 { 10754 ffebld item; 10755 10756 if (ffe_is_ffedebug ()) 10757 fprintf (dmpout, "; end_stmt_transition\n"); 10758 10759 ffecom_list_blockdata_ = NULL; 10760 ffecom_list_common_ = NULL; 10761 10762 ffesymbol_drive (ffecom_sym_end_transition); 10763 if (ffe_is_ffedebug ()) 10764 { 10765 ffestorag_report (); 10766 } 10767 10768 ffecom_start_progunit_ (); 10769 10770 for (item = ffecom_list_blockdata_; 10771 item != NULL; 10772 item = ffebld_trail (item)) 10773 { 10774 ffebld callee; 10775 ffesymbol s; 10776 tree dt; 10777 tree t; 10778 tree var; 10779 static int number = 0; 10780 10781 callee = ffebld_head (item); 10782 s = ffebld_symter (callee); 10783 t = ffesymbol_hook (s).decl_tree; 10784 if (t == NULL_TREE) 10785 { 10786 s = ffecom_sym_transform_ (s); 10787 t = ffesymbol_hook (s).decl_tree; 10788 } 10789 10790 dt = build_pointer_type (TREE_TYPE (t)); 10791 10792 var = build_decl (VAR_DECL, 10793 ffecom_get_invented_identifier ("__g77_forceload_%d", 10794 number++), 10795 dt); 10796 DECL_EXTERNAL (var) = 0; 10797 TREE_STATIC (var) = 1; 10798 TREE_PUBLIC (var) = 0; 10799 DECL_INITIAL (var) = error_mark_node; 10800 TREE_USED (var) = 1; 10801 10802 var = start_decl (var, FALSE); 10803 10804 t = ffecom_1 (ADDR_EXPR, dt, t); 10805 10806 finish_decl (var, t, FALSE); 10807 } 10808 10809 /* This handles any COMMON areas that weren't referenced but have, for 10810 example, important initial data. */ 10811 10812 for (item = ffecom_list_common_; 10813 item != NULL; 10814 item = ffebld_trail (item)) 10815 ffecom_transform_common_ (ffebld_symter (ffebld_head (item))); 10816 10817 ffecom_list_common_ = NULL; 10818 } 10819 10820 /* ffecom_exec_transition -- Perform exec transition on all symbols 10821 10822 ffecom_exec_transition(); 10823 10824 Calls ffecom_sym_exec_transition for each global and local symbol. 10825 Make sure error updating not inhibited. */ 10826 10827 void 10828 ffecom_exec_transition () 10829 { 10830 bool inhibited; 10831 10832 if (ffe_is_ffedebug ()) 10833 fprintf (dmpout, "; exec_stmt_transition\n"); 10834 10835 inhibited = ffebad_inhibit (); 10836 ffebad_set_inhibit (FALSE); 10837 10838 ffesymbol_drive (ffecom_sym_exec_transition); /* Don't retract! */ 10839 ffeequiv_exec_transition (); /* Handle all pending EQUIVALENCEs. */ 10840 if (ffe_is_ffedebug ()) 10841 { 10842 ffestorag_report (); 10843 } 10844 10845 if (inhibited) 10846 ffebad_set_inhibit (TRUE); 10847 } 10848 10849 /* Handle assignment statement. 10850 10851 Convert dest and source using ffecom_expr, then join them 10852 with an ASSIGN op and pass the whole thing to expand_expr_stmt. */ 10853 10854 void 10855 ffecom_expand_let_stmt (ffebld dest, ffebld source) 10856 { 10857 tree dest_tree; 10858 tree dest_length; 10859 tree source_tree; 10860 tree expr_tree; 10861 10862 if (ffeinfo_basictype (ffebld_info (dest)) != FFEINFO_basictypeCHARACTER) 10863 { 10864 bool dest_used; 10865 tree assign_temp; 10866 10867 /* This attempts to replicate the test below, but must not be 10868 true when the test below is false. (Always err on the side 10869 of creating unused temporaries, to avoid ICEs.) */ 10870 if (ffebld_op (dest) != FFEBLD_opSYMTER 10871 || ((dest_tree = ffesymbol_hook (ffebld_symter (dest)).decl_tree) 10872 && (TREE_CODE (dest_tree) != VAR_DECL 10873 || TREE_ADDRESSABLE (dest_tree)))) 10874 { 10875 ffecom_prepare_expr_ (source, dest); 10876 dest_used = TRUE; 10877 } 10878 else 10879 { 10880 ffecom_prepare_expr_ (source, NULL); 10881 dest_used = FALSE; 10882 } 10883 10884 ffecom_prepare_expr_w (NULL_TREE, dest); 10885 10886 /* For COMPLEX assignment like C1=C2, if partial overlap is possible, 10887 create a temporary through which the assignment is to take place, 10888 since MODIFY_EXPR doesn't handle partial overlap properly. */ 10889 if (ffebld_basictype (dest) == FFEINFO_basictypeCOMPLEX 10890 && ffecom_possible_partial_overlap_ (dest, source)) 10891 { 10892 assign_temp = ffecom_make_tempvar ("complex_let", 10893 ffecom_tree_type 10894 [ffebld_basictype (dest)] 10895 [ffebld_kindtype (dest)], 10896 FFETARGET_charactersizeNONE, 10897 -1); 10898 } 10899 else 10900 assign_temp = NULL_TREE; 10901 10902 ffecom_prepare_end (); 10903 10904 dest_tree = ffecom_expr_w (NULL_TREE, dest); 10905 if (dest_tree == error_mark_node) 10906 return; 10907 10908 if ((TREE_CODE (dest_tree) != VAR_DECL) 10909 || TREE_ADDRESSABLE (dest_tree)) 10910 source_tree = ffecom_expr_ (source, dest_tree, dest, &dest_used, 10911 FALSE, FALSE); 10912 else 10913 { 10914 assert (! dest_used); 10915 dest_used = FALSE; 10916 source_tree = ffecom_expr (source); 10917 } 10918 if (source_tree == error_mark_node) 10919 return; 10920 10921 if (dest_used) 10922 expr_tree = source_tree; 10923 else if (assign_temp) 10924 { 10925 #ifdef MOVE_EXPR 10926 /* The back end understands a conceptual move (evaluate source; 10927 store into dest), so use that, in case it can determine 10928 that it is going to use, say, two registers as temporaries 10929 anyway. So don't use the temp (and someday avoid generating 10930 it, once this code starts triggering regularly). */ 10931 expr_tree = ffecom_2s (MOVE_EXPR, void_type_node, 10932 dest_tree, 10933 source_tree); 10934 #else 10935 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node, 10936 assign_temp, 10937 source_tree); 10938 expand_expr_stmt (expr_tree); 10939 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node, 10940 dest_tree, 10941 assign_temp); 10942 #endif 10943 } 10944 else 10945 expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node, 10946 dest_tree, 10947 source_tree); 10948 10949 expand_expr_stmt (expr_tree); 10950 return; 10951 } 10952 10953 ffecom_prepare_let_char_ (ffebld_size_known (dest), source); 10954 ffecom_prepare_expr_w (NULL_TREE, dest); 10955 10956 ffecom_prepare_end (); 10957 10958 ffecom_char_args_ (&dest_tree, &dest_length, dest); 10959 ffecom_let_char_ (dest_tree, dest_length, ffebld_size_known (dest), 10960 source); 10961 } 10962 10963 /* ffecom_expr -- Transform expr into gcc tree 10964 10965 tree t; 10966 ffebld expr; // FFE expression. 10967 tree = ffecom_expr(expr); 10968 10969 Recursive descent on expr while making corresponding tree nodes and 10970 attaching type info and such. */ 10971 10972 tree 10973 ffecom_expr (ffebld expr) 10974 { 10975 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, FALSE, FALSE); 10976 } 10977 10978 /* Like ffecom_expr, but return tree usable for assigned GOTO or FORMAT. */ 10979 10980 tree 10981 ffecom_expr_assign (ffebld expr) 10982 { 10983 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE); 10984 } 10985 10986 /* Like ffecom_expr_rw, but return tree usable for ASSIGN. */ 10987 10988 tree 10989 ffecom_expr_assign_w (ffebld expr) 10990 { 10991 return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE); 10992 } 10993 10994 /* Transform expr for use as into read/write tree and stabilize the 10995 reference. Not for use on CHARACTER expressions. 10996 10997 Recursive descent on expr while making corresponding tree nodes and 10998 attaching type info and such. */ 10999 11000 tree 11001 ffecom_expr_rw (tree type, ffebld expr) 11002 { 11003 assert (expr != NULL); 11004 /* Different target types not yet supported. */ 11005 assert (type == NULL_TREE || type == ffecom_type_expr (expr)); 11006 11007 return stabilize_reference (ffecom_expr (expr)); 11008 } 11009 11010 /* Transform expr for use as into write tree and stabilize the 11011 reference. Not for use on CHARACTER expressions. 11012 11013 Recursive descent on expr while making corresponding tree nodes and 11014 attaching type info and such. */ 11015 11016 tree 11017 ffecom_expr_w (tree type, ffebld expr) 11018 { 11019 assert (expr != NULL); 11020 /* Different target types not yet supported. */ 11021 assert (type == NULL_TREE || type == ffecom_type_expr (expr)); 11022 11023 return stabilize_reference (ffecom_expr (expr)); 11024 } 11025 11026 /* Do global stuff. */ 11027 11028 void 11029 ffecom_finish_compile () 11030 { 11031 assert (ffecom_outer_function_decl_ == NULL_TREE); 11032 assert (current_function_decl == NULL_TREE); 11033 11034 ffeglobal_drive (ffecom_finish_global_); 11035 } 11036 11037 /* Public entry point for front end to access finish_decl. */ 11038 11039 void 11040 ffecom_finish_decl (tree decl, tree init, bool is_top_level) 11041 { 11042 assert (!is_top_level); 11043 finish_decl (decl, init, FALSE); 11044 } 11045 11046 /* Finish a program unit. */ 11047 11048 void 11049 ffecom_finish_progunit () 11050 { 11051 ffecom_end_compstmt (); 11052 11053 ffecom_previous_function_decl_ = current_function_decl; 11054 ffecom_which_entrypoint_decl_ = NULL_TREE; 11055 11056 finish_function (0); 11057 } 11058 11059 /* Wrapper for get_identifier. pattern is sprintf-like. */ 11060 11061 tree 11062 ffecom_get_invented_identifier (const char *pattern, ...) 11063 { 11064 tree decl; 11065 char *nam; 11066 va_list ap; 11067 11068 va_start (ap, pattern); 11069 if (vasprintf (&nam, pattern, ap) == 0) 11070 abort (); 11071 va_end (ap); 11072 decl = get_identifier (nam); 11073 free (nam); 11074 IDENTIFIER_INVENTED (decl) = 1; 11075 return decl; 11076 } 11077 11078 ffeinfoBasictype 11079 ffecom_gfrt_basictype (ffecomGfrt gfrt) 11080 { 11081 assert (gfrt < FFECOM_gfrt); 11082 11083 switch (ffecom_gfrt_type_[gfrt]) 11084 { 11085 case FFECOM_rttypeVOID_: 11086 case FFECOM_rttypeVOIDSTAR_: 11087 return FFEINFO_basictypeNONE; 11088 11089 case FFECOM_rttypeFTNINT_: 11090 return FFEINFO_basictypeINTEGER; 11091 11092 case FFECOM_rttypeINTEGER_: 11093 return FFEINFO_basictypeINTEGER; 11094 11095 case FFECOM_rttypeLONGINT_: 11096 return FFEINFO_basictypeINTEGER; 11097 11098 case FFECOM_rttypeLOGICAL_: 11099 return FFEINFO_basictypeLOGICAL; 11100 11101 case FFECOM_rttypeREAL_F2C_: 11102 case FFECOM_rttypeREAL_GNU_: 11103 return FFEINFO_basictypeREAL; 11104 11105 case FFECOM_rttypeCOMPLEX_F2C_: 11106 case FFECOM_rttypeCOMPLEX_GNU_: 11107 return FFEINFO_basictypeCOMPLEX; 11108 11109 case FFECOM_rttypeDOUBLE_: 11110 case FFECOM_rttypeDOUBLEREAL_: 11111 return FFEINFO_basictypeREAL; 11112 11113 case FFECOM_rttypeDBLCMPLX_F2C_: 11114 case FFECOM_rttypeDBLCMPLX_GNU_: 11115 return FFEINFO_basictypeCOMPLEX; 11116 11117 case FFECOM_rttypeCHARACTER_: 11118 return FFEINFO_basictypeCHARACTER; 11119 11120 default: 11121 return FFEINFO_basictypeANY; 11122 } 11123 } 11124 11125 ffeinfoKindtype 11126 ffecom_gfrt_kindtype (ffecomGfrt gfrt) 11127 { 11128 assert (gfrt < FFECOM_gfrt); 11129 11130 switch (ffecom_gfrt_type_[gfrt]) 11131 { 11132 case FFECOM_rttypeVOID_: 11133 case FFECOM_rttypeVOIDSTAR_: 11134 return FFEINFO_kindtypeNONE; 11135 11136 case FFECOM_rttypeFTNINT_: 11137 return FFEINFO_kindtypeINTEGER1; 11138 11139 case FFECOM_rttypeINTEGER_: 11140 return FFEINFO_kindtypeINTEGER1; 11141 11142 case FFECOM_rttypeLONGINT_: 11143 return FFEINFO_kindtypeINTEGER4; 11144 11145 case FFECOM_rttypeLOGICAL_: 11146 return FFEINFO_kindtypeLOGICAL1; 11147 11148 case FFECOM_rttypeREAL_F2C_: 11149 case FFECOM_rttypeREAL_GNU_: 11150 return FFEINFO_kindtypeREAL1; 11151 11152 case FFECOM_rttypeCOMPLEX_F2C_: 11153 case FFECOM_rttypeCOMPLEX_GNU_: 11154 return FFEINFO_kindtypeREAL1; 11155 11156 case FFECOM_rttypeDOUBLE_: 11157 case FFECOM_rttypeDOUBLEREAL_: 11158 return FFEINFO_kindtypeREAL2; 11159 11160 case FFECOM_rttypeDBLCMPLX_F2C_: 11161 case FFECOM_rttypeDBLCMPLX_GNU_: 11162 return FFEINFO_kindtypeREAL2; 11163 11164 case FFECOM_rttypeCHARACTER_: 11165 return FFEINFO_kindtypeCHARACTER1; 11166 11167 default: 11168 return FFEINFO_kindtypeANY; 11169 } 11170 } 11171 11172 void 11173 ffecom_init_0 () 11174 { 11175 tree endlink; 11176 int i; 11177 int j; 11178 tree t; 11179 tree field; 11180 ffetype type; 11181 ffetype base_type; 11182 tree double_ftype_double; 11183 tree float_ftype_float; 11184 tree ldouble_ftype_ldouble; 11185 tree ffecom_tree_ptr_to_fun_type_void; 11186 11187 /* This block of code comes from the now-obsolete cktyps.c. It checks 11188 whether the compiler environment is buggy in known ways, some of which 11189 would, if not explicitly checked here, result in subtle bugs in g77. */ 11190 11191 if (ffe_is_do_internal_checks ()) 11192 { 11193 static const char names[][12] 11194 = 11195 {"bar", "bletch", "foo", "foobar"}; 11196 const char *name; 11197 unsigned long ul; 11198 double fl; 11199 11200 name = bsearch ("foo", &names[0], ARRAY_SIZE (names), sizeof (names[0]), 11201 (int (*)(const void *, const void *)) strcmp); 11202 if (name != &names[2][0]) 11203 { 11204 assert ("bsearch doesn't work, #define FFEPROJ_BSEARCH 0 in proj.h" 11205 == NULL); 11206 abort (); 11207 } 11208 11209 ul = strtoul ("123456789", NULL, 10); 11210 if (ul != 123456789L) 11211 { 11212 assert ("strtoul doesn't have enough range, #define FFEPROJ_STRTOUL 0\ 11213 in proj.h" == NULL); 11214 abort (); 11215 } 11216 11217 fl = atof ("56.789"); 11218 if ((fl < 56.788) || (fl > 56.79)) 11219 { 11220 assert ("atof not type double, fix your #include <stdio.h>" 11221 == NULL); 11222 abort (); 11223 } 11224 } 11225 11226 ffecom_outer_function_decl_ = NULL_TREE; 11227 current_function_decl = NULL_TREE; 11228 named_labels = NULL_TREE; 11229 current_binding_level = NULL_BINDING_LEVEL; 11230 free_binding_level = NULL_BINDING_LEVEL; 11231 /* Make the binding_level structure for global names. */ 11232 pushlevel (0); 11233 global_binding_level = current_binding_level; 11234 current_binding_level->prep_state = 2; 11235 11236 build_common_tree_nodes (1); 11237 11238 /* Define `int' and `char' first so that dbx will output them first. */ 11239 pushdecl (build_decl (TYPE_DECL, get_identifier ("int"), 11240 integer_type_node)); 11241 /* CHARACTER*1 is unsigned in ICHAR contexts. */ 11242 char_type_node = make_unsigned_type (CHAR_TYPE_SIZE); 11243 pushdecl (build_decl (TYPE_DECL, get_identifier ("char"), 11244 char_type_node)); 11245 pushdecl (build_decl (TYPE_DECL, get_identifier ("long int"), 11246 long_integer_type_node)); 11247 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned int"), 11248 unsigned_type_node)); 11249 pushdecl (build_decl (TYPE_DECL, get_identifier ("long unsigned int"), 11250 long_unsigned_type_node)); 11251 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long int"), 11252 long_long_integer_type_node)); 11253 pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"), 11254 long_long_unsigned_type_node)); 11255 pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"), 11256 short_integer_type_node)); 11257 pushdecl (build_decl (TYPE_DECL, get_identifier ("short unsigned int"), 11258 short_unsigned_type_node)); 11259 11260 /* Set the sizetype before we make other types. This *should* be the 11261 first type we create. */ 11262 11263 set_sizetype 11264 (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE)))); 11265 ffecom_typesize_pointer_ 11266 = TREE_INT_CST_LOW (TYPE_SIZE (sizetype)) / BITS_PER_UNIT; 11267 11268 build_common_tree_nodes_2 (0); 11269 11270 /* Define both `signed char' and `unsigned char'. */ 11271 pushdecl (build_decl (TYPE_DECL, get_identifier ("signed char"), 11272 signed_char_type_node)); 11273 11274 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned char"), 11275 unsigned_char_type_node)); 11276 11277 pushdecl (build_decl (TYPE_DECL, get_identifier ("float"), 11278 float_type_node)); 11279 pushdecl (build_decl (TYPE_DECL, get_identifier ("double"), 11280 double_type_node)); 11281 pushdecl (build_decl (TYPE_DECL, get_identifier ("long double"), 11282 long_double_type_node)); 11283 11284 /* For now, override what build_common_tree_nodes has done. */ 11285 complex_integer_type_node = ffecom_make_complex_type_ (integer_type_node); 11286 complex_float_type_node = ffecom_make_complex_type_ (float_type_node); 11287 complex_double_type_node = ffecom_make_complex_type_ (double_type_node); 11288 complex_long_double_type_node 11289 = ffecom_make_complex_type_ (long_double_type_node); 11290 11291 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"), 11292 complex_integer_type_node)); 11293 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"), 11294 complex_float_type_node)); 11295 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"), 11296 complex_double_type_node)); 11297 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"), 11298 complex_long_double_type_node)); 11299 11300 pushdecl (build_decl (TYPE_DECL, get_identifier ("void"), 11301 void_type_node)); 11302 /* We are not going to have real types in C with less than byte alignment, 11303 so we might as well not have any types that claim to have it. */ 11304 TYPE_ALIGN (void_type_node) = BITS_PER_UNIT; 11305 TYPE_USER_ALIGN (void_type_node) = 0; 11306 11307 string_type_node = build_pointer_type (char_type_node); 11308 11309 ffecom_tree_fun_type_void 11310 = build_function_type (void_type_node, NULL_TREE); 11311 11312 ffecom_tree_ptr_to_fun_type_void 11313 = build_pointer_type (ffecom_tree_fun_type_void); 11314 11315 endlink = tree_cons (NULL_TREE, void_type_node, NULL_TREE); 11316 11317 float_ftype_float 11318 = build_function_type (float_type_node, 11319 tree_cons (NULL_TREE, float_type_node, endlink)); 11320 11321 double_ftype_double 11322 = build_function_type (double_type_node, 11323 tree_cons (NULL_TREE, double_type_node, endlink)); 11324 11325 ldouble_ftype_ldouble 11326 = build_function_type (long_double_type_node, 11327 tree_cons (NULL_TREE, long_double_type_node, 11328 endlink)); 11329 11330 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i) 11331 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j) 11332 { 11333 ffecom_tree_type[i][j] = NULL_TREE; 11334 ffecom_tree_fun_type[i][j] = NULL_TREE; 11335 ffecom_tree_ptr_to_fun_type[i][j] = NULL_TREE; 11336 ffecom_f2c_typecode_[i][j] = -1; 11337 } 11338 11339 /* Set up standard g77 types. Note that INTEGER and LOGICAL are set 11340 to size FLOAT_TYPE_SIZE because they have to be the same size as 11341 REAL, which also is FLOAT_TYPE_SIZE, according to the standard. 11342 Compiler options and other such stuff that change the ways these 11343 types are set should not affect this particular setup. */ 11344 11345 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1] 11346 = t = make_signed_type (FLOAT_TYPE_SIZE); 11347 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer"), 11348 t)); 11349 type = ffetype_new (); 11350 base_type = type; 11351 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER1, 11352 type); 11353 ffetype_set_ams (type, 11354 TYPE_ALIGN (t) / BITS_PER_UNIT, 0, 11355 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT); 11356 ffetype_set_star (base_type, 11357 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE, 11358 type); 11359 ffetype_set_kind (base_type, 1, type); 11360 ffecom_typesize_integer1_ = ffetype_size (type); 11361 assert (ffetype_size (type) == sizeof (ffetargetInteger1)); 11362 11363 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER1] 11364 = t = make_unsigned_type (FLOAT_TYPE_SIZE); /* HOLLERITH means unsigned. */ 11365 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned"), 11366 t)); 11367 11368 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER2] 11369 = t = make_signed_type (CHAR_TYPE_SIZE); 11370 pushdecl (build_decl (TYPE_DECL, get_identifier ("byte"), 11371 t)); 11372 type = ffetype_new (); 11373 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER2, 11374 type); 11375 ffetype_set_ams (type, 11376 TYPE_ALIGN (t) / BITS_PER_UNIT, 0, 11377 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT); 11378 ffetype_set_star (base_type, 11379 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE, 11380 type); 11381 ffetype_set_kind (base_type, 3, type); 11382 assert (ffetype_size (type) == sizeof (ffetargetInteger2)); 11383 11384 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER2] 11385 = t = make_unsigned_type (CHAR_TYPE_SIZE); 11386 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned byte"), 11387 t)); 11388 11389 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER3] 11390 = t = make_signed_type (CHAR_TYPE_SIZE * 2); 11391 pushdecl (build_decl (TYPE_DECL, get_identifier ("word"), 11392 t)); 11393 type = ffetype_new (); 11394 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER3, 11395 type); 11396 ffetype_set_ams (type, 11397 TYPE_ALIGN (t) / BITS_PER_UNIT, 0, 11398 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT); 11399 ffetype_set_star (base_type, 11400 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE, 11401 type); 11402 ffetype_set_kind (base_type, 6, type); 11403 assert (ffetype_size (type) == sizeof (ffetargetInteger3)); 11404 11405 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER3] 11406 = t = make_unsigned_type (CHAR_TYPE_SIZE * 2); 11407 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned word"), 11408 t)); 11409 11410 ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER4] 11411 = t = make_signed_type (FLOAT_TYPE_SIZE * 2); 11412 pushdecl (build_decl (TYPE_DECL, get_identifier ("integer4"), 11413 t)); 11414 type = ffetype_new (); 11415 ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER4, 11416 type); 11417 ffetype_set_ams (type, 11418 TYPE_ALIGN (t) / BITS_PER_UNIT, 0, 11419 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT); 11420 ffetype_set_star (base_type, 11421 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE, 11422 type); 11423 ffetype_set_kind (base_type, 2, type); 11424 assert (ffetype_size (type) == sizeof (ffetargetInteger4)); 11425 11426 ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER4] 11427 = t = make_unsigned_type (FLOAT_TYPE_SIZE * 2); 11428 pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned4"), 11429 t)); 11430 11431 #if 0 11432 if (ffe_is_do_internal_checks () 11433 && LONG_TYPE_SIZE != FLOAT_TYPE_SIZE 11434 && LONG_TYPE_SIZE != CHAR_TYPE_SIZE 11435 && LONG_TYPE_SIZE != SHORT_TYPE_SIZE 11436 && LONG_TYPE_SIZE != LONG_LONG_TYPE_SIZE) 11437 { 11438 fprintf (stderr, "Sorry, no g77 support for LONG_TYPE_SIZE (%d bits) yet.\n", 11439 LONG_TYPE_SIZE); 11440 } 11441 #endif 11442 11443 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL1] 11444 = t = make_signed_type (FLOAT_TYPE_SIZE); 11445 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical"), 11446 t)); 11447 type = ffetype_new (); 11448 base_type = type; 11449 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL1, 11450 type); 11451 ffetype_set_ams (type, 11452 TYPE_ALIGN (t) / BITS_PER_UNIT, 0, 11453 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT); 11454 ffetype_set_star (base_type, 11455 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE, 11456 type); 11457 ffetype_set_kind (base_type, 1, type); 11458 assert (ffetype_size (type) == sizeof (ffetargetLogical1)); 11459 11460 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL2] 11461 = t = make_signed_type (CHAR_TYPE_SIZE); 11462 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical2"), 11463 t)); 11464 type = ffetype_new (); 11465 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL2, 11466 type); 11467 ffetype_set_ams (type, 11468 TYPE_ALIGN (t) / BITS_PER_UNIT, 0, 11469 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT); 11470 ffetype_set_star (base_type, 11471 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE, 11472 type); 11473 ffetype_set_kind (base_type, 3, type); 11474 assert (ffetype_size (type) == sizeof (ffetargetLogical2)); 11475 11476 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL3] 11477 = t = make_signed_type (CHAR_TYPE_SIZE * 2); 11478 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical3"), 11479 t)); 11480 type = ffetype_new (); 11481 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL3, 11482 type); 11483 ffetype_set_ams (type, 11484 TYPE_ALIGN (t) / BITS_PER_UNIT, 0, 11485 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT); 11486 ffetype_set_star (base_type, 11487 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE, 11488 type); 11489 ffetype_set_kind (base_type, 6, type); 11490 assert (ffetype_size (type) == sizeof (ffetargetLogical3)); 11491 11492 ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL4] 11493 = t = make_signed_type (FLOAT_TYPE_SIZE * 2); 11494 pushdecl (build_decl (TYPE_DECL, get_identifier ("logical4"), 11495 t)); 11496 type = ffetype_new (); 11497 ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL4, 11498 type); 11499 ffetype_set_ams (type, 11500 TYPE_ALIGN (t) / BITS_PER_UNIT, 0, 11501 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT); 11502 ffetype_set_star (base_type, 11503 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE, 11504 type); 11505 ffetype_set_kind (base_type, 2, type); 11506 assert (ffetype_size (type) == sizeof (ffetargetLogical4)); 11507 11508 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1] 11509 = t = make_node (REAL_TYPE); 11510 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE; 11511 pushdecl (build_decl (TYPE_DECL, get_identifier ("real"), 11512 t)); 11513 layout_type (t); 11514 type = ffetype_new (); 11515 base_type = type; 11516 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREAL1, 11517 type); 11518 ffetype_set_ams (type, 11519 TYPE_ALIGN (t) / BITS_PER_UNIT, 0, 11520 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT); 11521 ffetype_set_star (base_type, 11522 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE, 11523 type); 11524 ffetype_set_kind (base_type, 1, type); 11525 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1] 11526 = FFETARGET_f2cTYREAL; 11527 assert (ffetype_size (type) == sizeof (ffetargetReal1)); 11528 11529 ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREALDOUBLE] 11530 = t = make_node (REAL_TYPE); 11531 TYPE_PRECISION (t) = FLOAT_TYPE_SIZE * 2; /* Always twice REAL. */ 11532 pushdecl (build_decl (TYPE_DECL, get_identifier ("double precision"), 11533 t)); 11534 layout_type (t); 11535 type = ffetype_new (); 11536 ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREALDOUBLE, 11537 type); 11538 ffetype_set_ams (type, 11539 TYPE_ALIGN (t) / BITS_PER_UNIT, 0, 11540 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT); 11541 ffetype_set_star (base_type, 11542 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE, 11543 type); 11544 ffetype_set_kind (base_type, 2, type); 11545 ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2] 11546 = FFETARGET_f2cTYDREAL; 11547 assert (ffetype_size (type) == sizeof (ffetargetReal2)); 11548 11549 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1] 11550 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]); 11551 pushdecl (build_decl (TYPE_DECL, get_identifier ("complex"), 11552 t)); 11553 type = ffetype_new (); 11554 base_type = type; 11555 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREAL1, 11556 type); 11557 ffetype_set_ams (type, 11558 TYPE_ALIGN (t) / BITS_PER_UNIT, 0, 11559 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT); 11560 ffetype_set_star (base_type, 11561 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE, 11562 type); 11563 ffetype_set_kind (base_type, 1, type); 11564 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1] 11565 = FFETARGET_f2cTYCOMPLEX; 11566 assert (ffetype_size (type) == sizeof (ffetargetComplex1)); 11567 11568 ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREALDOUBLE] 11569 = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]); 11570 pushdecl (build_decl (TYPE_DECL, get_identifier ("double complex"), 11571 t)); 11572 type = ffetype_new (); 11573 ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREALDOUBLE, 11574 type); 11575 ffetype_set_ams (type, 11576 TYPE_ALIGN (t) / BITS_PER_UNIT, 0, 11577 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT); 11578 ffetype_set_star (base_type, 11579 TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE, 11580 type); 11581 ffetype_set_kind (base_type, 2, 11582 type); 11583 ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL2] 11584 = FFETARGET_f2cTYDCOMPLEX; 11585 assert (ffetype_size (type) == sizeof (ffetargetComplex2)); 11586 11587 /* Make function and ptr-to-function types for non-CHARACTER types. */ 11588 11589 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i) 11590 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j) 11591 { 11592 if ((t = ffecom_tree_type[i][j]) != NULL_TREE) 11593 { 11594 if (i == FFEINFO_basictypeINTEGER) 11595 { 11596 /* Figure out the smallest INTEGER type that can hold 11597 a pointer on this machine. */ 11598 if (GET_MODE_SIZE (TYPE_MODE (t)) 11599 >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node)))) 11600 { 11601 if ((ffecom_pointer_kind_ == FFEINFO_kindtypeNONE) 11602 || (GET_MODE_SIZE (TYPE_MODE (ffecom_tree_type[i][ffecom_pointer_kind_])) 11603 > GET_MODE_SIZE (TYPE_MODE (t)))) 11604 ffecom_pointer_kind_ = j; 11605 } 11606 } 11607 else if (i == FFEINFO_basictypeCOMPLEX) 11608 t = void_type_node; 11609 /* For f2c compatibility, REAL functions are really 11610 implemented as DOUBLE PRECISION. */ 11611 else if ((i == FFEINFO_basictypeREAL) 11612 && (j == FFEINFO_kindtypeREAL1)) 11613 t = ffecom_tree_type 11614 [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]; 11615 11616 t = ffecom_tree_fun_type[i][j] = build_function_type (t, 11617 NULL_TREE); 11618 ffecom_tree_ptr_to_fun_type[i][j] = build_pointer_type (t); 11619 } 11620 } 11621 11622 /* Set up pointer types. */ 11623 11624 if (ffecom_pointer_kind_ == FFEINFO_basictypeNONE) 11625 fatal_error ("no INTEGER type can hold a pointer on this configuration"); 11626 else if (0 && ffe_is_do_internal_checks ()) 11627 fprintf (stderr, "Pointer type kt=%d\n", ffecom_pointer_kind_); 11628 ffetype_set_kind (ffeinfo_type (FFEINFO_basictypeINTEGER, 11629 FFEINFO_kindtypeINTEGERDEFAULT), 11630 7, 11631 ffeinfo_type (FFEINFO_basictypeINTEGER, 11632 ffecom_pointer_kind_)); 11633 11634 if (ffe_is_ugly_assign ()) 11635 ffecom_label_kind_ = ffecom_pointer_kind_; /* Require ASSIGN etc to this. */ 11636 else 11637 ffecom_label_kind_ = FFEINFO_kindtypeINTEGERDEFAULT; 11638 if (0 && ffe_is_do_internal_checks ()) 11639 fprintf (stderr, "Label type kt=%d\n", ffecom_label_kind_); 11640 11641 ffecom_integer_type_node 11642 = ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1]; 11643 ffecom_integer_zero_node = convert (ffecom_integer_type_node, 11644 integer_zero_node); 11645 ffecom_integer_one_node = convert (ffecom_integer_type_node, 11646 integer_one_node); 11647 11648 /* Yes, the "FLOAT_TYPE_SIZE" references below are intentional. 11649 Turns out that by TYLONG, runtime/libI77/lio.h really means 11650 "whatever size an ftnint is". For consistency and sanity, 11651 com.h and runtime/f2c.h.in agree that flag, ftnint, and ftlen 11652 all are INTEGER, which we also make out of whatever back-end 11653 integer type is FLOAT_TYPE_SIZE bits wide. This change, from 11654 LONG_TYPE_SIZE, for TYLONG and TYLOGICAL, was necessary to 11655 accommodate machines like the Alpha. Note that this suggests 11656 f2c and libf2c are missing a distinction perhaps needed on 11657 some machines between "int" and "long int". -- burley 0.5.5 950215 */ 11658 11659 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, FLOAT_TYPE_SIZE, 11660 FFETARGET_f2cTYLONG); 11661 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, SHORT_TYPE_SIZE, 11662 FFETARGET_f2cTYSHORT); 11663 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, CHAR_TYPE_SIZE, 11664 FFETARGET_f2cTYINT1); 11665 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, LONG_LONG_TYPE_SIZE, 11666 FFETARGET_f2cTYQUAD); 11667 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, FLOAT_TYPE_SIZE, 11668 FFETARGET_f2cTYLOGICAL); 11669 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, SHORT_TYPE_SIZE, 11670 FFETARGET_f2cTYLOGICAL2); 11671 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, CHAR_TYPE_SIZE, 11672 FFETARGET_f2cTYLOGICAL1); 11673 /* ~~~Not really such a type in libf2c, e.g. I/O support? */ 11674 ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, LONG_LONG_TYPE_SIZE, 11675 FFETARGET_f2cTYQUAD); 11676 11677 /* CHARACTER stuff is all special-cased, so it is not handled in the above 11678 loop. CHARACTER items are built as arrays of unsigned char. */ 11679 11680 ffecom_tree_type[FFEINFO_basictypeCHARACTER] 11681 [FFEINFO_kindtypeCHARACTER1] = t = char_type_node; 11682 type = ffetype_new (); 11683 base_type = type; 11684 ffeinfo_set_type (FFEINFO_basictypeCHARACTER, 11685 FFEINFO_kindtypeCHARACTER1, 11686 type); 11687 ffetype_set_ams (type, 11688 TYPE_ALIGN (t) / BITS_PER_UNIT, 0, 11689 TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT); 11690 ffetype_set_kind (base_type, 1, type); 11691 assert (ffetype_size (type) 11692 == sizeof (((ffetargetCharacter1) { 0, NULL }).text[0])); 11693 11694 ffecom_tree_fun_type[FFEINFO_basictypeCHARACTER] 11695 [FFEINFO_kindtypeCHARACTER1] = ffecom_tree_fun_type_void; 11696 ffecom_tree_ptr_to_fun_type[FFEINFO_basictypeCHARACTER] 11697 [FFEINFO_kindtypeCHARACTER1] 11698 = ffecom_tree_ptr_to_fun_type_void; 11699 ffecom_f2c_typecode_[FFEINFO_basictypeCHARACTER][FFEINFO_kindtypeCHARACTER1] 11700 = FFETARGET_f2cTYCHAR; 11701 11702 ffecom_f2c_typecode_[FFEINFO_basictypeANY][FFEINFO_kindtypeANY] 11703 = 0; 11704 11705 /* Make multi-return-value type and fields. */ 11706 11707 ffecom_multi_type_node_ = make_node (UNION_TYPE); 11708 11709 field = NULL_TREE; 11710 11711 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i) 11712 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j) 11713 { 11714 char name[30]; 11715 11716 if (ffecom_tree_type[i][j] == NULL_TREE) 11717 continue; /* Not supported. */ 11718 sprintf (&name[0], "bt_%s_kt_%s", 11719 ffeinfo_basictype_string ((ffeinfoBasictype) i), 11720 ffeinfo_kindtype_string ((ffeinfoKindtype) j)); 11721 ffecom_multi_fields_[i][j] = build_decl (FIELD_DECL, 11722 get_identifier (name), 11723 ffecom_tree_type[i][j]); 11724 DECL_CONTEXT (ffecom_multi_fields_[i][j]) 11725 = ffecom_multi_type_node_; 11726 DECL_ALIGN (ffecom_multi_fields_[i][j]) = 0; 11727 DECL_USER_ALIGN (ffecom_multi_fields_[i][j]) = 0; 11728 TREE_CHAIN (ffecom_multi_fields_[i][j]) = field; 11729 field = ffecom_multi_fields_[i][j]; 11730 } 11731 11732 TYPE_FIELDS (ffecom_multi_type_node_) = field; 11733 layout_type (ffecom_multi_type_node_); 11734 11735 /* Subroutines usually return integer because they might have alternate 11736 returns. */ 11737 11738 ffecom_tree_subr_type 11739 = build_function_type (integer_type_node, NULL_TREE); 11740 ffecom_tree_ptr_to_subr_type 11741 = build_pointer_type (ffecom_tree_subr_type); 11742 ffecom_tree_blockdata_type 11743 = build_function_type (void_type_node, NULL_TREE); 11744 11745 builtin_function ("__builtin_sqrtf", float_ftype_float, 11746 BUILT_IN_SQRTF, BUILT_IN_NORMAL, "sqrtf", NULL_TREE); 11747 builtin_function ("__builtin_sqrt", double_ftype_double, 11748 BUILT_IN_SQRT, BUILT_IN_NORMAL, "sqrt", NULL_TREE); 11749 builtin_function ("__builtin_sqrtl", ldouble_ftype_ldouble, 11750 BUILT_IN_SQRTL, BUILT_IN_NORMAL, "sqrtl", NULL_TREE); 11751 builtin_function ("__builtin_sinf", float_ftype_float, 11752 BUILT_IN_SINF, BUILT_IN_NORMAL, "sinf", NULL_TREE); 11753 builtin_function ("__builtin_sin", double_ftype_double, 11754 BUILT_IN_SIN, BUILT_IN_NORMAL, "sin", NULL_TREE); 11755 builtin_function ("__builtin_sinl", ldouble_ftype_ldouble, 11756 BUILT_IN_SINL, BUILT_IN_NORMAL, "sinl", NULL_TREE); 11757 builtin_function ("__builtin_cosf", float_ftype_float, 11758 BUILT_IN_COSF, BUILT_IN_NORMAL, "cosf", NULL_TREE); 11759 builtin_function ("__builtin_cos", double_ftype_double, 11760 BUILT_IN_COS, BUILT_IN_NORMAL, "cos", NULL_TREE); 11761 builtin_function ("__builtin_cosl", ldouble_ftype_ldouble, 11762 BUILT_IN_COSL, BUILT_IN_NORMAL, "cosl", NULL_TREE); 11763 11764 pedantic_lvalues = FALSE; 11765 11766 ffecom_f2c_make_type_ (&ffecom_f2c_integer_type_node, 11767 FFECOM_f2cINTEGER, 11768 "integer"); 11769 ffecom_f2c_make_type_ (&ffecom_f2c_address_type_node, 11770 FFECOM_f2cADDRESS, 11771 "address"); 11772 ffecom_f2c_make_type_ (&ffecom_f2c_real_type_node, 11773 FFECOM_f2cREAL, 11774 "real"); 11775 ffecom_f2c_make_type_ (&ffecom_f2c_doublereal_type_node, 11776 FFECOM_f2cDOUBLEREAL, 11777 "doublereal"); 11778 ffecom_f2c_make_type_ (&ffecom_f2c_complex_type_node, 11779 FFECOM_f2cCOMPLEX, 11780 "complex"); 11781 ffecom_f2c_make_type_ (&ffecom_f2c_doublecomplex_type_node, 11782 FFECOM_f2cDOUBLECOMPLEX, 11783 "doublecomplex"); 11784 ffecom_f2c_make_type_ (&ffecom_f2c_longint_type_node, 11785 FFECOM_f2cLONGINT, 11786 "longint"); 11787 ffecom_f2c_make_type_ (&ffecom_f2c_logical_type_node, 11788 FFECOM_f2cLOGICAL, 11789 "logical"); 11790 ffecom_f2c_make_type_ (&ffecom_f2c_flag_type_node, 11791 FFECOM_f2cFLAG, 11792 "flag"); 11793 ffecom_f2c_make_type_ (&ffecom_f2c_ftnlen_type_node, 11794 FFECOM_f2cFTNLEN, 11795 "ftnlen"); 11796 ffecom_f2c_make_type_ (&ffecom_f2c_ftnint_type_node, 11797 FFECOM_f2cFTNINT, 11798 "ftnint"); 11799 11800 ffecom_f2c_ftnlen_zero_node 11801 = convert (ffecom_f2c_ftnlen_type_node, integer_zero_node); 11802 11803 ffecom_f2c_ftnlen_one_node 11804 = convert (ffecom_f2c_ftnlen_type_node, integer_one_node); 11805 11806 ffecom_f2c_ftnlen_two_node = build_int_2 (2, 0); 11807 TREE_TYPE (ffecom_f2c_ftnlen_two_node) = ffecom_integer_type_node; 11808 11809 ffecom_f2c_ptr_to_ftnlen_type_node 11810 = build_pointer_type (ffecom_f2c_ftnlen_type_node); 11811 11812 ffecom_f2c_ptr_to_ftnint_type_node 11813 = build_pointer_type (ffecom_f2c_ftnint_type_node); 11814 11815 ffecom_f2c_ptr_to_integer_type_node 11816 = build_pointer_type (ffecom_f2c_integer_type_node); 11817 11818 ffecom_f2c_ptr_to_real_type_node 11819 = build_pointer_type (ffecom_f2c_real_type_node); 11820 11821 ffecom_float_zero_ = build_real (float_type_node, dconst0); 11822 ffecom_double_zero_ = build_real (double_type_node, dconst0); 11823 { 11824 REAL_VALUE_TYPE point_5; 11825 11826 REAL_ARITHMETIC (point_5, RDIV_EXPR, dconst1, dconst2); 11827 ffecom_float_half_ = build_real (float_type_node, point_5); 11828 ffecom_double_half_ = build_real (double_type_node, point_5); 11829 } 11830 11831 /* Do "extern int xargc;". */ 11832 11833 ffecom_tree_xargc_ = build_decl (VAR_DECL, 11834 get_identifier ("f__xargc"), 11835 integer_type_node); 11836 DECL_EXTERNAL (ffecom_tree_xargc_) = 1; 11837 TREE_STATIC (ffecom_tree_xargc_) = 1; 11838 TREE_PUBLIC (ffecom_tree_xargc_) = 1; 11839 ffecom_tree_xargc_ = start_decl (ffecom_tree_xargc_, FALSE); 11840 finish_decl (ffecom_tree_xargc_, NULL_TREE, FALSE); 11841 11842 #if 0 /* This is being fixed, and seems to be working now. */ 11843 if ((FLOAT_TYPE_SIZE != 32) 11844 || (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))) != 32)) 11845 { 11846 warning ("configuration: REAL, INTEGER, and LOGICAL are %d bits wide,", 11847 (int) FLOAT_TYPE_SIZE); 11848 warning ("and pointers are %d bits wide, but g77 doesn't yet work", 11849 (int) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node)))); 11850 warning ("properly unless they all are 32 bits wide"); 11851 warning ("Please keep this in mind before you report bugs."); 11852 } 11853 #endif 11854 11855 #if 0 /* Code in ste.c that would crash has been commented out. */ 11856 if (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node) 11857 < TYPE_PRECISION (string_type_node)) 11858 /* I/O will probably crash. */ 11859 warning ("configuration: char * holds %d bits, but ftnlen only %d", 11860 TYPE_PRECISION (string_type_node), 11861 TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)); 11862 #endif 11863 11864 #if 0 /* ASSIGN-related stuff has been changed to accommodate this. */ 11865 if (TYPE_PRECISION (ffecom_integer_type_node) 11866 < TYPE_PRECISION (string_type_node)) 11867 /* ASSIGN 10 TO I will crash. */ 11868 warning ("configuration: char * holds %d bits, but INTEGER only %d --\n\ 11869 ASSIGN statement might fail", 11870 TYPE_PRECISION (string_type_node), 11871 TYPE_PRECISION (ffecom_integer_type_node)); 11872 #endif 11873 } 11874 11875 /* ffecom_init_2 -- Initialize 11876 11877 ffecom_init_2(); */ 11878 11879 void 11880 ffecom_init_2 () 11881 { 11882 assert (ffecom_outer_function_decl_ == NULL_TREE); 11883 assert (current_function_decl == NULL_TREE); 11884 assert (ffecom_which_entrypoint_decl_ == NULL_TREE); 11885 11886 ffecom_master_arglist_ = NULL; 11887 ++ffecom_num_fns_; 11888 ffecom_primary_entry_ = NULL; 11889 ffecom_is_altreturning_ = FALSE; 11890 ffecom_func_result_ = NULL_TREE; 11891 ffecom_multi_retval_ = NULL_TREE; 11892 } 11893 11894 /* ffecom_list_expr -- Transform list of exprs into gcc tree 11895 11896 tree t; 11897 ffebld expr; // FFE opITEM list. 11898 tree = ffecom_list_expr(expr); 11899 11900 List of actual args is transformed into corresponding gcc backend list. */ 11901 11902 tree 11903 ffecom_list_expr (ffebld expr) 11904 { 11905 tree list; 11906 tree *plist = &list; 11907 tree trail = NULL_TREE; /* Append char length args here. */ 11908 tree *ptrail = &trail; 11909 tree length; 11910 11911 while (expr != NULL) 11912 { 11913 tree texpr = ffecom_arg_expr (ffebld_head (expr), &length); 11914 11915 if (texpr == error_mark_node) 11916 return error_mark_node; 11917 11918 *plist = build_tree_list (NULL_TREE, texpr); 11919 plist = &TREE_CHAIN (*plist); 11920 expr = ffebld_trail (expr); 11921 if (length != NULL_TREE) 11922 { 11923 *ptrail = build_tree_list (NULL_TREE, length); 11924 ptrail = &TREE_CHAIN (*ptrail); 11925 } 11926 } 11927 11928 *plist = trail; 11929 11930 return list; 11931 } 11932 11933 /* ffecom_list_ptr_to_expr -- Transform list of exprs into gcc tree 11934 11935 tree t; 11936 ffebld expr; // FFE opITEM list. 11937 tree = ffecom_list_ptr_to_expr(expr); 11938 11939 List of actual args is transformed into corresponding gcc backend list for 11940 use in calling an external procedure (vs. a statement function). */ 11941 11942 tree 11943 ffecom_list_ptr_to_expr (ffebld expr) 11944 { 11945 tree list; 11946 tree *plist = &list; 11947 tree trail = NULL_TREE; /* Append char length args here. */ 11948 tree *ptrail = &trail; 11949 tree length; 11950 11951 while (expr != NULL) 11952 { 11953 tree texpr = ffecom_arg_ptr_to_expr (ffebld_head (expr), &length); 11954 11955 if (texpr == error_mark_node) 11956 return error_mark_node; 11957 11958 *plist = build_tree_list (NULL_TREE, texpr); 11959 plist = &TREE_CHAIN (*plist); 11960 expr = ffebld_trail (expr); 11961 if (length != NULL_TREE) 11962 { 11963 *ptrail = build_tree_list (NULL_TREE, length); 11964 ptrail = &TREE_CHAIN (*ptrail); 11965 } 11966 } 11967 11968 *plist = trail; 11969 11970 return list; 11971 } 11972 11973 /* Obtain gcc's LABEL_DECL tree for label. */ 11974 11975 tree 11976 ffecom_lookup_label (ffelab label) 11977 { 11978 tree glabel; 11979 11980 if (ffelab_hook (label) == NULL_TREE) 11981 { 11982 char labelname[16]; 11983 11984 switch (ffelab_type (label)) 11985 { 11986 case FFELAB_typeLOOPEND: 11987 case FFELAB_typeNOTLOOP: 11988 case FFELAB_typeENDIF: 11989 sprintf (labelname, "%" ffelabValue_f "u", ffelab_value (label)); 11990 glabel = build_decl (LABEL_DECL, get_identifier (labelname), 11991 void_type_node); 11992 DECL_CONTEXT (glabel) = current_function_decl; 11993 DECL_MODE (glabel) = VOIDmode; 11994 break; 11995 11996 case FFELAB_typeFORMAT: 11997 glabel = build_decl (VAR_DECL, 11998 ffecom_get_invented_identifier 11999 ("__g77_format_%d", (int) ffelab_value (label)), 12000 build_type_variant (build_array_type 12001 (char_type_node, 12002 NULL_TREE), 12003 1, 0)); 12004 TREE_CONSTANT (glabel) = 1; 12005 TREE_STATIC (glabel) = 1; 12006 DECL_CONTEXT (glabel) = current_function_decl; 12007 DECL_INITIAL (glabel) = NULL; 12008 make_decl_rtl (glabel, NULL); 12009 expand_decl (glabel); 12010 12011 ffecom_save_tree_forever (glabel); 12012 12013 break; 12014 12015 case FFELAB_typeANY: 12016 glabel = error_mark_node; 12017 break; 12018 12019 default: 12020 assert ("bad label type" == NULL); 12021 glabel = NULL; 12022 break; 12023 } 12024 ffelab_set_hook (label, glabel); 12025 } 12026 else 12027 { 12028 glabel = ffelab_hook (label); 12029 } 12030 12031 return glabel; 12032 } 12033 12034 /* Stabilizes the arguments. Don't use this if the lhs and rhs come from 12035 a single source specification (as in the fourth argument of MVBITS). 12036 If the type is NULL_TREE, the type of lhs is used to make the type of 12037 the MODIFY_EXPR. */ 12038 12039 tree 12040 ffecom_modify (tree newtype, tree lhs, 12041 tree rhs) 12042 { 12043 if (lhs == error_mark_node || rhs == error_mark_node) 12044 return error_mark_node; 12045 12046 if (newtype == NULL_TREE) 12047 newtype = TREE_TYPE (lhs); 12048 12049 if (TREE_SIDE_EFFECTS (lhs)) 12050 lhs = stabilize_reference (lhs); 12051 12052 return ffecom_2s (MODIFY_EXPR, newtype, lhs, rhs); 12053 } 12054 12055 /* Register source file name. */ 12056 12057 void 12058 ffecom_file (const char *name) 12059 { 12060 ffecom_file_ (name); 12061 } 12062 12063 /* ffecom_notify_init_storage -- An aggregate storage is now fully init'ed 12064 12065 ffestorag st; 12066 ffecom_notify_init_storage(st); 12067 12068 Gets called when all possible units in an aggregate storage area (a LOCAL 12069 with equivalences or a COMMON) have been initialized. The initialization 12070 info either is in ffestorag_init or, if that is NULL, 12071 ffestorag_accretion: 12072 12073 ffestorag_init may contain an opCONTER or opARRTER. opCONTER may occur 12074 even for an array if the array is one element in length! 12075 12076 ffestorag_accretion will contain an opACCTER. It is much like an 12077 opARRTER except it has an ffebit object in it instead of just a size. 12078 The back end can use the info in the ffebit object, if it wants, to 12079 reduce the amount of actual initialization, but in any case it should 12080 kill the ffebit object when done. Also, set accretion to NULL but 12081 init to a non-NULL value. 12082 12083 After performing initialization, DO NOT set init to NULL, because that'll 12084 tell the front end it is ok for more initialization to happen. Instead, 12085 set init to an opANY expression or some such thing that you can use to 12086 tell that you've already initialized the object. 12087 12088 27-Oct-91 JCB 1.1 12089 Support two-pass FFE. */ 12090 12091 void 12092 ffecom_notify_init_storage (ffestorag st) 12093 { 12094 ffebld init; /* The initialization expression. */ 12095 12096 if (ffestorag_init (st) == NULL) 12097 { 12098 init = ffestorag_accretion (st); 12099 assert (init != NULL); 12100 ffestorag_set_accretion (st, NULL); 12101 ffestorag_set_accretes (st, 0); 12102 ffestorag_set_init (st, init); 12103 } 12104 } 12105 12106 /* ffecom_notify_init_symbol -- A symbol is now fully init'ed 12107 12108 ffesymbol s; 12109 ffecom_notify_init_symbol(s); 12110 12111 Gets called when all possible units in a symbol (not placed in COMMON 12112 or involved in EQUIVALENCE, unless it as yet has no ffestorag object) 12113 have been initialized. The initialization info either is in 12114 ffesymbol_init or, if that is NULL, ffesymbol_accretion: 12115 12116 ffesymbol_init may contain an opCONTER or opARRTER. opCONTER may occur 12117 even for an array if the array is one element in length! 12118 12119 ffesymbol_accretion will contain an opACCTER. It is much like an 12120 opARRTER except it has an ffebit object in it instead of just a size. 12121 The back end can use the info in the ffebit object, if it wants, to 12122 reduce the amount of actual initialization, but in any case it should 12123 kill the ffebit object when done. Also, set accretion to NULL but 12124 init to a non-NULL value. 12125 12126 After performing initialization, DO NOT set init to NULL, because that'll 12127 tell the front end it is ok for more initialization to happen. Instead, 12128 set init to an opANY expression or some such thing that you can use to 12129 tell that you've already initialized the object. 12130 12131 27-Oct-91 JCB 1.1 12132 Support two-pass FFE. */ 12133 12134 void 12135 ffecom_notify_init_symbol (ffesymbol s) 12136 { 12137 ffebld init; /* The initialization expression. */ 12138 12139 if (ffesymbol_storage (s) == NULL) 12140 return; /* Do nothing until COMMON/EQUIVALENCE 12141 possibilities checked. */ 12142 12143 if ((ffesymbol_init (s) == NULL) 12144 && ((init = ffesymbol_accretion (s)) != NULL)) 12145 { 12146 ffesymbol_set_accretion (s, NULL); 12147 ffesymbol_set_accretes (s, 0); 12148 ffesymbol_set_init (s, init); 12149 } 12150 } 12151 12152 /* ffecom_notify_primary_entry -- Learn which is the primary entry point 12153 12154 ffesymbol s; 12155 ffecom_notify_primary_entry(s); 12156 12157 Gets called when implicit or explicit PROGRAM statement seen or when 12158 FUNCTION, SUBROUTINE, or BLOCK DATA statement seen, with the primary 12159 global symbol that serves as the entry point. */ 12160 12161 void 12162 ffecom_notify_primary_entry (ffesymbol s) 12163 { 12164 ffecom_primary_entry_ = s; 12165 ffecom_primary_entry_kind_ = ffesymbol_kind (s); 12166 12167 if ((ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION) 12168 || (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)) 12169 ffecom_primary_entry_is_proc_ = TRUE; 12170 else 12171 ffecom_primary_entry_is_proc_ = FALSE; 12172 12173 if (!ffe_is_silent ()) 12174 { 12175 if (ffecom_primary_entry_kind_ == FFEINFO_kindPROGRAM) 12176 fprintf (stderr, "%s:\n", ffesymbol_text (s)); 12177 else 12178 fprintf (stderr, " %s:\n", ffesymbol_text (s)); 12179 } 12180 12181 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE) 12182 { 12183 ffebld list; 12184 ffebld arg; 12185 12186 for (list = ffesymbol_dummyargs (s); 12187 list != NULL; 12188 list = ffebld_trail (list)) 12189 { 12190 arg = ffebld_head (list); 12191 if (ffebld_op (arg) == FFEBLD_opSTAR) 12192 { 12193 ffecom_is_altreturning_ = TRUE; 12194 break; 12195 } 12196 } 12197 } 12198 } 12199 12200 FILE * 12201 ffecom_open_include (char *name, ffewhereLine l, ffewhereColumn c) 12202 { 12203 return ffecom_open_include_ (name, l, c); 12204 } 12205 12206 /* ffecom_ptr_to_expr -- Transform expr into gcc tree with & in front 12207 12208 tree t; 12209 ffebld expr; // FFE expression. 12210 tree = ffecom_ptr_to_expr(expr); 12211 12212 Like ffecom_expr, but sticks address-of in front of most things. */ 12213 12214 tree 12215 ffecom_ptr_to_expr (ffebld expr) 12216 { 12217 tree item; 12218 ffeinfoBasictype bt; 12219 ffeinfoKindtype kt; 12220 ffesymbol s; 12221 12222 assert (expr != NULL); 12223 12224 switch (ffebld_op (expr)) 12225 { 12226 case FFEBLD_opSYMTER: 12227 s = ffebld_symter (expr); 12228 if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC) 12229 { 12230 ffecomGfrt ix; 12231 12232 ix = ffeintrin_gfrt_indirect (ffebld_symter_implementation (expr)); 12233 assert (ix != FFECOM_gfrt); 12234 if ((item = ffecom_gfrt_[ix]) == NULL_TREE) 12235 { 12236 ffecom_make_gfrt_ (ix); 12237 item = ffecom_gfrt_[ix]; 12238 } 12239 } 12240 else 12241 { 12242 item = ffesymbol_hook (s).decl_tree; 12243 if (item == NULL_TREE) 12244 { 12245 s = ffecom_sym_transform_ (s); 12246 item = ffesymbol_hook (s).decl_tree; 12247 } 12248 } 12249 assert (item != NULL); 12250 if (item == error_mark_node) 12251 return item; 12252 if (!ffesymbol_hook (s).addr) 12253 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)), 12254 item); 12255 return item; 12256 12257 case FFEBLD_opARRAYREF: 12258 return ffecom_arrayref_ (NULL_TREE, expr, 1); 12259 12260 case FFEBLD_opCONTER: 12261 12262 bt = ffeinfo_basictype (ffebld_info (expr)); 12263 kt = ffeinfo_kindtype (ffebld_info (expr)); 12264 12265 item = ffecom_constantunion (&ffebld_constant_union 12266 (ffebld_conter (expr)), bt, kt, 12267 ffecom_tree_type[bt][kt]); 12268 if (item == error_mark_node) 12269 return error_mark_node; 12270 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)), 12271 item); 12272 return item; 12273 12274 case FFEBLD_opANY: 12275 return error_mark_node; 12276 12277 default: 12278 bt = ffeinfo_basictype (ffebld_info (expr)); 12279 kt = ffeinfo_kindtype (ffebld_info (expr)); 12280 12281 item = ffecom_expr (expr); 12282 if (item == error_mark_node) 12283 return error_mark_node; 12284 12285 /* The back end currently optimizes a bit too zealously for us, in that 12286 we fail JCB001 if the following block of code is omitted. It checks 12287 to see if the transformed expression is a symbol or array reference, 12288 and encloses it in a SAVE_EXPR if that is the case. */ 12289 12290 STRIP_NOPS (item); 12291 if ((TREE_CODE (item) == VAR_DECL) 12292 || (TREE_CODE (item) == PARM_DECL) 12293 || (TREE_CODE (item) == RESULT_DECL) 12294 || (TREE_CODE (item) == INDIRECT_REF) 12295 || (TREE_CODE (item) == ARRAY_REF) 12296 || (TREE_CODE (item) == COMPONENT_REF) 12297 #ifdef OFFSET_REF 12298 || (TREE_CODE (item) == OFFSET_REF) 12299 #endif 12300 || (TREE_CODE (item) == BUFFER_REF) 12301 || (TREE_CODE (item) == REALPART_EXPR) 12302 || (TREE_CODE (item) == IMAGPART_EXPR)) 12303 { 12304 item = ffecom_save_tree (item); 12305 } 12306 12307 item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)), 12308 item); 12309 return item; 12310 } 12311 12312 assert ("fall-through error" == NULL); 12313 return error_mark_node; 12314 } 12315 12316 /* Obtain a temp var with given data type. 12317 12318 size is FFETARGET_charactersizeNONE for a non-CHARACTER type 12319 or >= 0 for a CHARACTER type. 12320 12321 elements is -1 for a scalar or > 0 for an array of type. */ 12322 12323 tree 12324 ffecom_make_tempvar (const char *commentary, tree type, 12325 ffetargetCharacterSize size, int elements) 12326 { 12327 tree t; 12328 static int mynumber; 12329 12330 assert (current_binding_level->prep_state < 2); 12331 12332 if (type == error_mark_node) 12333 return error_mark_node; 12334 12335 if (size != FFETARGET_charactersizeNONE) 12336 type = build_array_type (type, 12337 build_range_type (ffecom_f2c_ftnlen_type_node, 12338 ffecom_f2c_ftnlen_one_node, 12339 build_int_2 (size, 0))); 12340 if (elements != -1) 12341 type = build_array_type (type, 12342 build_range_type (integer_type_node, 12343 integer_zero_node, 12344 build_int_2 (elements - 1, 12345 0))); 12346 t = build_decl (VAR_DECL, 12347 ffecom_get_invented_identifier ("__g77_%s_%d", 12348 commentary, 12349 mynumber++), 12350 type); 12351 12352 t = start_decl (t, FALSE); 12353 finish_decl (t, NULL_TREE, FALSE); 12354 12355 return t; 12356 } 12357 12358 /* Prepare argument pointer to expression. 12359 12360 Like ffecom_prepare_expr, except for expressions to be evaluated 12361 via ffecom_arg_ptr_to_expr. */ 12362 12363 void 12364 ffecom_prepare_arg_ptr_to_expr (ffebld expr) 12365 { 12366 /* ~~For now, it seems to be the same thing. */ 12367 ffecom_prepare_expr (expr); 12368 return; 12369 } 12370 12371 /* End of preparations. */ 12372 12373 bool 12374 ffecom_prepare_end (void) 12375 { 12376 int prep_state = current_binding_level->prep_state; 12377 12378 assert (prep_state < 2); 12379 current_binding_level->prep_state = 2; 12380 12381 return (prep_state == 1) ? TRUE : FALSE; 12382 } 12383 12384 /* Prepare expression. 12385 12386 This is called before any code is generated for the current block. 12387 It scans the expression, declares any temporaries that might be needed 12388 during evaluation of the expression, and stores those temporaries in 12389 the appropriate "hook" fields of the expression. `dest', if not NULL, 12390 specifies the destination that ffecom_expr_ will see, in case that 12391 helps avoid generating unused temporaries. 12392 12393 ~~Improve to avoid allocating unused temporaries by taking `dest' 12394 into account vis-a-vis aliasing requirements of complex/character 12395 functions. */ 12396 12397 void 12398 ffecom_prepare_expr_ (ffebld expr, ffebld dest UNUSED) 12399 { 12400 ffeinfoBasictype bt; 12401 ffeinfoKindtype kt; 12402 ffetargetCharacterSize sz; 12403 tree tempvar = NULL_TREE; 12404 12405 assert (current_binding_level->prep_state < 2); 12406 12407 if (! expr) 12408 return; 12409 12410 bt = ffeinfo_basictype (ffebld_info (expr)); 12411 kt = ffeinfo_kindtype (ffebld_info (expr)); 12412 sz = ffeinfo_size (ffebld_info (expr)); 12413 12414 /* Generate whatever temporaries are needed to represent the result 12415 of the expression. */ 12416 12417 if (bt == FFEINFO_basictypeCHARACTER) 12418 { 12419 while (ffebld_op (expr) == FFEBLD_opPAREN) 12420 expr = ffebld_left (expr); 12421 } 12422 12423 switch (ffebld_op (expr)) 12424 { 12425 default: 12426 /* Don't make temps for SYMTER, CONTER, etc. */ 12427 if (ffebld_arity (expr) == 0) 12428 break; 12429 12430 switch (bt) 12431 { 12432 case FFEINFO_basictypeCOMPLEX: 12433 if (ffebld_op (expr) == FFEBLD_opFUNCREF) 12434 { 12435 ffesymbol s; 12436 12437 if (ffebld_op (ffebld_left (expr)) != FFEBLD_opSYMTER) 12438 break; 12439 12440 s = ffebld_symter (ffebld_left (expr)); 12441 if (ffesymbol_where (s) == FFEINFO_whereCONSTANT 12442 || (ffesymbol_where (s) != FFEINFO_whereINTRINSIC 12443 && ! ffesymbol_is_f2c (s)) 12444 || (ffesymbol_where (s) == FFEINFO_whereINTRINSIC 12445 && ! ffe_is_f2c_library ())) 12446 break; 12447 } 12448 else if (ffebld_op (expr) == FFEBLD_opPOWER) 12449 { 12450 /* Requires special treatment. There's no POW_CC function 12451 in libg2c, so POW_ZZ is used, which means we always 12452 need a double-complex temp, not a single-complex. */ 12453 kt = FFEINFO_kindtypeREAL2; 12454 } 12455 else if (ffebld_op (expr) != FFEBLD_opDIVIDE) 12456 /* The other ops don't need temps for complex operands. */ 12457 break; 12458 12459 /* ~~~Avoid making temps for some intrinsics, such as AIMAG(C), 12460 REAL(C). See 19990325-0.f, routine `check', for cases. */ 12461 tempvar = ffecom_make_tempvar ("complex", 12462 ffecom_tree_type 12463 [FFEINFO_basictypeCOMPLEX][kt], 12464 FFETARGET_charactersizeNONE, 12465 -1); 12466 break; 12467 12468 case FFEINFO_basictypeCHARACTER: 12469 if (ffebld_op (expr) != FFEBLD_opFUNCREF) 12470 break; 12471 12472 if (sz == FFETARGET_charactersizeNONE) 12473 /* ~~Kludge alert! This should someday be fixed. */ 12474 sz = 24; 12475 12476 tempvar = ffecom_make_tempvar ("char", char_type_node, sz, -1); 12477 break; 12478 12479 default: 12480 break; 12481 } 12482 break; 12483 12484 case FFEBLD_opCONCATENATE: 12485 { 12486 /* This gets special handling, because only one set of temps 12487 is needed for a tree of these -- the tree is treated as 12488 a flattened list of concatenations when generating code. */ 12489 12490 ffecomConcatList_ catlist; 12491 tree ltmp, itmp, result; 12492 int count; 12493 int i; 12494 12495 catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE); 12496 count = ffecom_concat_list_count_ (catlist); 12497 12498 if (count >= 2) 12499 { 12500 ltmp 12501 = ffecom_make_tempvar ("concat_len", 12502 ffecom_f2c_ftnlen_type_node, 12503 FFETARGET_charactersizeNONE, count); 12504 itmp 12505 = ffecom_make_tempvar ("concat_item", 12506 ffecom_f2c_address_type_node, 12507 FFETARGET_charactersizeNONE, count); 12508 result 12509 = ffecom_make_tempvar ("concat_res", 12510 char_type_node, 12511 ffecom_concat_list_maxlen_ (catlist), 12512 -1); 12513 12514 tempvar = make_tree_vec (3); 12515 TREE_VEC_ELT (tempvar, 0) = ltmp; 12516 TREE_VEC_ELT (tempvar, 1) = itmp; 12517 TREE_VEC_ELT (tempvar, 2) = result; 12518 } 12519 12520 for (i = 0; i < count; ++i) 12521 ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist, 12522 i)); 12523 12524 ffecom_concat_list_kill_ (catlist); 12525 12526 if (tempvar) 12527 { 12528 ffebld_nonter_set_hook (expr, tempvar); 12529 current_binding_level->prep_state = 1; 12530 } 12531 } 12532 return; 12533 12534 case FFEBLD_opCONVERT: 12535 if (bt == FFEINFO_basictypeCHARACTER 12536 && ((ffebld_size_known (ffebld_left (expr)) 12537 == FFETARGET_charactersizeNONE) 12538 || (ffebld_size_known (ffebld_left (expr)) >= sz))) 12539 tempvar = ffecom_make_tempvar ("convert", char_type_node, sz, -1); 12540 break; 12541 } 12542 12543 if (tempvar) 12544 { 12545 ffebld_nonter_set_hook (expr, tempvar); 12546 current_binding_level->prep_state = 1; 12547 } 12548 12549 /* Prepare subexpressions for this expr. */ 12550 12551 switch (ffebld_op (expr)) 12552 { 12553 case FFEBLD_opPERCENT_LOC: 12554 ffecom_prepare_ptr_to_expr (ffebld_left (expr)); 12555 break; 12556 12557 case FFEBLD_opPERCENT_VAL: 12558 case FFEBLD_opPERCENT_REF: 12559 ffecom_prepare_expr (ffebld_left (expr)); 12560 break; 12561 12562 case FFEBLD_opPERCENT_DESCR: 12563 ffecom_prepare_arg_ptr_to_expr (ffebld_left (expr)); 12564 break; 12565 12566 case FFEBLD_opITEM: 12567 { 12568 ffebld item; 12569 12570 for (item = expr; 12571 item != NULL; 12572 item = ffebld_trail (item)) 12573 if (ffebld_head (item) != NULL) 12574 ffecom_prepare_expr (ffebld_head (item)); 12575 } 12576 break; 12577 12578 default: 12579 /* Need to handle character conversion specially. */ 12580 switch (ffebld_arity (expr)) 12581 { 12582 case 2: 12583 ffecom_prepare_expr (ffebld_left (expr)); 12584 ffecom_prepare_expr (ffebld_right (expr)); 12585 break; 12586 12587 case 1: 12588 ffecom_prepare_expr (ffebld_left (expr)); 12589 break; 12590 12591 default: 12592 break; 12593 } 12594 } 12595 12596 return; 12597 } 12598 12599 /* Prepare expression for reading and writing. 12600 12601 Like ffecom_prepare_expr, except for expressions to be evaluated 12602 via ffecom_expr_rw. */ 12603 12604 void 12605 ffecom_prepare_expr_rw (tree type, ffebld expr) 12606 { 12607 /* This is all we support for now. */ 12608 assert (type == NULL_TREE || type == ffecom_type_expr (expr)); 12609 12610 /* ~~For now, it seems to be the same thing. */ 12611 ffecom_prepare_expr (expr); 12612 return; 12613 } 12614 12615 /* Prepare expression for writing. 12616 12617 Like ffecom_prepare_expr, except for expressions to be evaluated 12618 via ffecom_expr_w. */ 12619 12620 void 12621 ffecom_prepare_expr_w (tree type, ffebld expr) 12622 { 12623 /* This is all we support for now. */ 12624 assert (type == NULL_TREE || type == ffecom_type_expr (expr)); 12625 12626 /* ~~For now, it seems to be the same thing. */ 12627 ffecom_prepare_expr (expr); 12628 return; 12629 } 12630 12631 /* Prepare expression for returning. 12632 12633 Like ffecom_prepare_expr, except for expressions to be evaluated 12634 via ffecom_return_expr. */ 12635 12636 void 12637 ffecom_prepare_return_expr (ffebld expr) 12638 { 12639 assert (current_binding_level->prep_state < 2); 12640 12641 if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE 12642 && ffecom_is_altreturning_ 12643 && expr != NULL) 12644 ffecom_prepare_expr (expr); 12645 } 12646 12647 /* Prepare pointer to expression. 12648 12649 Like ffecom_prepare_expr, except for expressions to be evaluated 12650 via ffecom_ptr_to_expr. */ 12651 12652 void 12653 ffecom_prepare_ptr_to_expr (ffebld expr) 12654 { 12655 /* ~~For now, it seems to be the same thing. */ 12656 ffecom_prepare_expr (expr); 12657 return; 12658 } 12659 12660 /* Transform expression into constant pointer-to-expression tree. 12661 12662 If the expression can be transformed into a pointer-to-expression tree 12663 that is constant, that is done, and the tree returned. Else NULL_TREE 12664 is returned. 12665 12666 That way, a caller can attempt to provide compile-time initialization 12667 of a variable and, if that fails, *then* choose to start a new block 12668 and resort to using temporaries, as appropriate. */ 12669 12670 tree 12671 ffecom_ptr_to_const_expr (ffebld expr) 12672 { 12673 if (! expr) 12674 return integer_zero_node; 12675 12676 if (ffebld_op (expr) == FFEBLD_opANY) 12677 return error_mark_node; 12678 12679 if (ffebld_arity (expr) == 0 12680 && (ffebld_op (expr) != FFEBLD_opSYMTER 12681 || ffebld_where (expr) == FFEINFO_whereCOMMON 12682 || ffebld_where (expr) == FFEINFO_whereGLOBAL 12683 || ffebld_where (expr) == FFEINFO_whereINTRINSIC)) 12684 { 12685 tree t; 12686 12687 t = ffecom_ptr_to_expr (expr); 12688 assert (TREE_CONSTANT (t)); 12689 return t; 12690 } 12691 12692 return NULL_TREE; 12693 } 12694 12695 /* ffecom_return_expr -- Returns return-value expr given alt return expr 12696 12697 tree rtn; // NULL_TREE means use expand_null_return() 12698 ffebld expr; // NULL if no alt return expr to RETURN stmt 12699 rtn = ffecom_return_expr(expr); 12700 12701 Based on the program unit type and other info (like return function 12702 type, return master function type when alternate ENTRY points, 12703 whether subroutine has any alternate RETURN points, etc), returns the 12704 appropriate expression to be returned to the caller, or NULL_TREE 12705 meaning no return value or the caller expects it to be returned somewhere 12706 else (which is handled by other parts of this module). */ 12707 12708 tree 12709 ffecom_return_expr (ffebld expr) 12710 { 12711 tree rtn; 12712 12713 switch (ffecom_primary_entry_kind_) 12714 { 12715 case FFEINFO_kindPROGRAM: 12716 case FFEINFO_kindBLOCKDATA: 12717 rtn = NULL_TREE; 12718 break; 12719 12720 case FFEINFO_kindSUBROUTINE: 12721 if (!ffecom_is_altreturning_) 12722 rtn = NULL_TREE; /* No alt returns, never an expr. */ 12723 else if (expr == NULL) 12724 rtn = integer_zero_node; 12725 else 12726 rtn = ffecom_expr (expr); 12727 break; 12728 12729 case FFEINFO_kindFUNCTION: 12730 if ((ffecom_multi_retval_ != NULL_TREE) 12731 || (ffesymbol_basictype (ffecom_primary_entry_) 12732 == FFEINFO_basictypeCHARACTER) 12733 || ((ffesymbol_basictype (ffecom_primary_entry_) 12734 == FFEINFO_basictypeCOMPLEX) 12735 && (ffecom_num_entrypoints_ == 0) 12736 && ffesymbol_is_f2c (ffecom_primary_entry_))) 12737 { /* Value is returned by direct assignment 12738 into (implicit) dummy. */ 12739 rtn = NULL_TREE; 12740 break; 12741 } 12742 rtn = ffecom_func_result_; 12743 #if 0 12744 /* Spurious error if RETURN happens before first reference! So elide 12745 this code. In particular, for debugging registry, rtn should always 12746 be non-null after all, but TREE_USED won't be set until we encounter 12747 a reference in the code. Perfectly okay (but weird) code that, 12748 e.g., has "GOTO 20;10 RETURN;20 RTN=0;GOTO 10", would result in 12749 this diagnostic for no reason. Have people use -O -Wuninitialized 12750 and leave it to the back end to find obviously weird cases. */ 12751 12752 /* Used to "assert(rtn != NULL_TREE);" here, but it's kind of a valid 12753 situation; if the return value has never been referenced, it won't 12754 have a tree under 2pass mode. */ 12755 if ((rtn == NULL_TREE) 12756 || !TREE_USED (rtn)) 12757 { 12758 ffebad_start (FFEBAD_RETURN_VALUE_UNSET); 12759 ffebad_here (0, ffesymbol_where_line (ffecom_primary_entry_), 12760 ffesymbol_where_column (ffecom_primary_entry_)); 12761 ffebad_string (ffesymbol_text (ffesymbol_funcresult 12762 (ffecom_primary_entry_))); 12763 ffebad_finish (); 12764 } 12765 #endif 12766 break; 12767 12768 default: 12769 assert ("bad unit kind" == NULL); 12770 case FFEINFO_kindANY: 12771 rtn = error_mark_node; 12772 break; 12773 } 12774 12775 return rtn; 12776 } 12777 12778 /* Do save_expr only if tree is not error_mark_node. */ 12779 12780 tree 12781 ffecom_save_tree (tree t) 12782 { 12783 return save_expr (t); 12784 } 12785 12786 /* Start a compound statement (block). */ 12787 12788 void 12789 ffecom_start_compstmt (void) 12790 { 12791 bison_rule_pushlevel_ (); 12792 } 12793 12794 /* Public entry point for front end to access start_decl. */ 12795 12796 tree 12797 ffecom_start_decl (tree decl, bool is_initialized) 12798 { 12799 DECL_INITIAL (decl) = is_initialized ? error_mark_node : NULL_TREE; 12800 return start_decl (decl, FALSE); 12801 } 12802 12803 /* ffecom_sym_commit -- Symbol's state being committed to reality 12804 12805 ffesymbol s; 12806 ffecom_sym_commit(s); 12807 12808 Does whatever the backend needs when a symbol is committed after having 12809 been backtrackable for a period of time. */ 12810 12811 void 12812 ffecom_sym_commit (ffesymbol s UNUSED) 12813 { 12814 assert (!ffesymbol_retractable ()); 12815 } 12816 12817 /* ffecom_sym_end_transition -- Perform end transition on all symbols 12818 12819 ffecom_sym_end_transition(); 12820 12821 Does backend-specific stuff and also calls ffest_sym_end_transition 12822 to do the necessary FFE stuff. 12823 12824 Backtracking is never enabled when this fn is called, so don't worry 12825 about it. */ 12826 12827 ffesymbol 12828 ffecom_sym_end_transition (ffesymbol s) 12829 { 12830 ffestorag st; 12831 12832 assert (!ffesymbol_retractable ()); 12833 12834 s = ffest_sym_end_transition (s); 12835 12836 if ((ffesymbol_kind (s) == FFEINFO_kindBLOCKDATA) 12837 && (ffesymbol_where (s) == FFEINFO_whereGLOBAL)) 12838 { 12839 ffecom_list_blockdata_ 12840 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE, 12841 FFEINTRIN_specNONE, 12842 FFEINTRIN_impNONE), 12843 ffecom_list_blockdata_); 12844 } 12845 12846 /* This is where we finally notice that a symbol has partial initialization 12847 and finalize it. */ 12848 12849 if (ffesymbol_accretion (s) != NULL) 12850 { 12851 assert (ffesymbol_init (s) == NULL); 12852 ffecom_notify_init_symbol (s); 12853 } 12854 else if (((st = ffesymbol_storage (s)) != NULL) 12855 && ((st = ffestorag_parent (st)) != NULL) 12856 && (ffestorag_accretion (st) != NULL)) 12857 { 12858 assert (ffestorag_init (st) == NULL); 12859 ffecom_notify_init_storage (st); 12860 } 12861 12862 if ((ffesymbol_kind (s) == FFEINFO_kindCOMMON) 12863 && (ffesymbol_where (s) == FFEINFO_whereLOCAL) 12864 && (ffesymbol_storage (s) != NULL)) 12865 { 12866 ffecom_list_common_ 12867 = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE, 12868 FFEINTRIN_specNONE, 12869 FFEINTRIN_impNONE), 12870 ffecom_list_common_); 12871 } 12872 12873 return s; 12874 } 12875 12876 /* ffecom_sym_exec_transition -- Perform exec transition on all symbols 12877 12878 ffecom_sym_exec_transition(); 12879 12880 Does backend-specific stuff and also calls ffest_sym_exec_transition 12881 to do the necessary FFE stuff. 12882 12883 See the long-winded description in ffecom_sym_learned for info 12884 on handling the situation where backtracking is inhibited. */ 12885 12886 ffesymbol 12887 ffecom_sym_exec_transition (ffesymbol s) 12888 { 12889 s = ffest_sym_exec_transition (s); 12890 12891 return s; 12892 } 12893 12894 /* ffecom_sym_learned -- Initial or more info gained on symbol after exec 12895 12896 ffesymbol s; 12897 s = ffecom_sym_learned(s); 12898 12899 Called when a new symbol is seen after the exec transition or when more 12900 info (perhaps) is gained for an UNCERTAIN symbol. The symbol state when 12901 it arrives here is that all its latest info is updated already, so its 12902 state may be UNCERTAIN or UNDERSTOOD, it might already have the hook 12903 field filled in if its gone through here or exec_transition first, and 12904 so on. 12905 12906 The backend probably wants to check ffesymbol_retractable() to see if 12907 backtracking is in effect. If so, the FFE's changes to the symbol may 12908 be retracted (undone) or committed (ratified), at which time the 12909 appropriate ffecom_sym_retract or _commit function will be called 12910 for that function. 12911 12912 If the backend has its own backtracking mechanism, great, use it so that 12913 committal is a simple operation. Though it doesn't make much difference, 12914 I suppose: the reason for tentative symbol evolution in the FFE is to 12915 enable error detection in weird incorrect statements early and to disable 12916 incorrect error detection on a correct statement. The backend is not 12917 likely to introduce any information that'll get involved in these 12918 considerations, so it is probably just fine that the implementation 12919 model for this fn and for _exec_transition is to not do anything 12920 (besides the required FFE stuff) if ffesymbol_retractable() returns TRUE 12921 and instead wait until ffecom_sym_commit is called (which it never 12922 will be as long as we're using ambiguity-detecting statement analysis in 12923 the FFE, which we are initially to shake out the code, but don't depend 12924 on this), otherwise go ahead and do whatever is needed. 12925 12926 In essence, then, when this fn and _exec_transition get called while 12927 backtracking is enabled, a general mechanism would be to flag which (or 12928 both) of these were called (and in what order? neat question as to what 12929 might happen that I'm too lame to think through right now) and then when 12930 _commit is called reproduce the original calling sequence, if any, for 12931 the two fns (at which point backtracking will, of course, be disabled). */ 12932 12933 ffesymbol 12934 ffecom_sym_learned (ffesymbol s) 12935 { 12936 ffestorag_exec_layout (s); 12937 12938 return s; 12939 } 12940 12941 /* ffecom_sym_retract -- Symbol's state being retracted from reality 12942 12943 ffesymbol s; 12944 ffecom_sym_retract(s); 12945 12946 Does whatever the backend needs when a symbol is retracted after having 12947 been backtrackable for a period of time. */ 12948 12949 void 12950 ffecom_sym_retract (ffesymbol s UNUSED) 12951 { 12952 assert (!ffesymbol_retractable ()); 12953 12954 #if 0 /* GCC doesn't commit any backtrackable sins, 12955 so nothing needed here. */ 12956 switch (ffesymbol_hook (s).state) 12957 { 12958 case 0: /* nothing happened yet. */ 12959 break; 12960 12961 case 1: /* exec transition happened. */ 12962 break; 12963 12964 case 2: /* learned happened. */ 12965 break; 12966 12967 case 3: /* learned then exec. */ 12968 break; 12969 12970 case 4: /* exec then learned. */ 12971 break; 12972 12973 default: 12974 assert ("bad hook state" == NULL); 12975 break; 12976 } 12977 #endif 12978 } 12979 12980 /* Create temporary gcc label. */ 12981 12982 tree 12983 ffecom_temp_label () 12984 { 12985 tree glabel; 12986 static int mynumber = 0; 12987 12988 glabel = build_decl (LABEL_DECL, 12989 ffecom_get_invented_identifier ("__g77_label_%d", 12990 mynumber++), 12991 void_type_node); 12992 DECL_CONTEXT (glabel) = current_function_decl; 12993 DECL_MODE (glabel) = VOIDmode; 12994 12995 return glabel; 12996 } 12997 12998 /* Return an expression that is usable as an arg in a conditional context 12999 (IF, DO WHILE, .NOT., and so on). 13000 13001 Use the one provided for the back end as of >2.6.0. */ 13002 13003 tree 13004 ffecom_truth_value (tree expr) 13005 { 13006 return ffe_truthvalue_conversion (expr); 13007 } 13008 13009 /* Return the inversion of a truth value (the inversion of what 13010 ffecom_truth_value builds). 13011 13012 Apparently invert_truthvalue, which is properly in the back end, is 13013 enough for now, so just use it. */ 13014 13015 tree 13016 ffecom_truth_value_invert (tree expr) 13017 { 13018 return invert_truthvalue (ffecom_truth_value (expr)); 13019 } 13020 13021 /* Return the tree that is the type of the expression, as would be 13022 returned in TREE_TYPE(ffecom_expr(expr)), without otherwise 13023 transforming the expression, generating temporaries, etc. */ 13024 13025 tree 13026 ffecom_type_expr (ffebld expr) 13027 { 13028 ffeinfoBasictype bt; 13029 ffeinfoKindtype kt; 13030 tree tree_type; 13031 13032 assert (expr != NULL); 13033 13034 bt = ffeinfo_basictype (ffebld_info (expr)); 13035 kt = ffeinfo_kindtype (ffebld_info (expr)); 13036 tree_type = ffecom_tree_type[bt][kt]; 13037 13038 switch (ffebld_op (expr)) 13039 { 13040 case FFEBLD_opCONTER: 13041 case FFEBLD_opSYMTER: 13042 case FFEBLD_opARRAYREF: 13043 case FFEBLD_opUPLUS: 13044 case FFEBLD_opPAREN: 13045 case FFEBLD_opUMINUS: 13046 case FFEBLD_opADD: 13047 case FFEBLD_opSUBTRACT: 13048 case FFEBLD_opMULTIPLY: 13049 case FFEBLD_opDIVIDE: 13050 case FFEBLD_opPOWER: 13051 case FFEBLD_opNOT: 13052 case FFEBLD_opFUNCREF: 13053 case FFEBLD_opSUBRREF: 13054 case FFEBLD_opAND: 13055 case FFEBLD_opOR: 13056 case FFEBLD_opXOR: 13057 case FFEBLD_opNEQV: 13058 case FFEBLD_opEQV: 13059 case FFEBLD_opCONVERT: 13060 case FFEBLD_opLT: 13061 case FFEBLD_opLE: 13062 case FFEBLD_opEQ: 13063 case FFEBLD_opNE: 13064 case FFEBLD_opGT: 13065 case FFEBLD_opGE: 13066 case FFEBLD_opPERCENT_LOC: 13067 return tree_type; 13068 13069 case FFEBLD_opACCTER: 13070 case FFEBLD_opARRTER: 13071 case FFEBLD_opITEM: 13072 case FFEBLD_opSTAR: 13073 case FFEBLD_opBOUNDS: 13074 case FFEBLD_opREPEAT: 13075 case FFEBLD_opLABTER: 13076 case FFEBLD_opLABTOK: 13077 case FFEBLD_opIMPDO: 13078 case FFEBLD_opCONCATENATE: 13079 case FFEBLD_opSUBSTR: 13080 default: 13081 assert ("bad op for ffecom_type_expr" == NULL); 13082 /* Fall through. */ 13083 case FFEBLD_opANY: 13084 return error_mark_node; 13085 } 13086 } 13087 13088 /* Return PARM_DECL for arg#1 of master fn containing alternate ENTRY points 13089 13090 If the PARM_DECL already exists, return it, else create it. It's an 13091 integer_type_node argument for the master function that implements a 13092 subroutine or function with more than one entrypoint and is bound at 13093 run time with the entrypoint number (0 for SUBROUTINE/FUNCTION, 1 for 13094 first ENTRY statement, and so on). */ 13095 13096 tree 13097 ffecom_which_entrypoint_decl () 13098 { 13099 assert (ffecom_which_entrypoint_decl_ != NULL_TREE); 13100 13101 return ffecom_which_entrypoint_decl_; 13102 } 13103 13104 /* The following sections consists of private and public functions 13105 that have the same names and perform roughly the same functions 13106 as counterparts in the C front end. Changes in the C front end 13107 might affect how things should be done here. Only functions 13108 needed by the back end should be public here; the rest should 13109 be private (static in the C sense). Functions needed by other 13110 g77 front-end modules should be accessed by them via public 13111 ffecom_* names, which should themselves call private versions 13112 in this section so the private versions are easy to recognize 13113 when upgrading to a new gcc and finding interesting changes 13114 in the front end. 13115 13116 Functions named after rule "foo:" in c-parse.y are named 13117 "bison_rule_foo_" so they are easy to find. */ 13118 13119 static void 13120 bison_rule_pushlevel_ () 13121 { 13122 emit_line_note (input_filename, lineno); 13123 pushlevel (0); 13124 clear_last_expr (); 13125 expand_start_bindings (0); 13126 } 13127 13128 static tree 13129 bison_rule_compstmt_ () 13130 { 13131 tree t; 13132 int keep = kept_level_p (); 13133 13134 /* Make the temps go away. */ 13135 if (! keep) 13136 current_binding_level->names = NULL_TREE; 13137 13138 emit_line_note (input_filename, lineno); 13139 expand_end_bindings (getdecls (), keep, 0); 13140 t = poplevel (keep, 1, 0); 13141 13142 return t; 13143 } 13144 13145 /* Return a definition for a builtin function named NAME and whose data type 13146 is TYPE. TYPE should be a function type with argument types. 13147 FUNCTION_CODE tells later passes how to compile calls to this function. 13148 See tree.h for its possible values. 13149 13150 If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME, 13151 the name to be called if we can't opencode the function. If 13152 ATTRS is nonzero, use that for the function's attribute list. */ 13153 13154 tree 13155 builtin_function (const char *name, tree type, int function_code, 13156 enum built_in_class class, 13157 const char *library_name, 13158 tree attrs ATTRIBUTE_UNUSED) 13159 { 13160 tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type); 13161 DECL_EXTERNAL (decl) = 1; 13162 TREE_PUBLIC (decl) = 1; 13163 if (library_name) 13164 SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name)); 13165 make_decl_rtl (decl, NULL); 13166 pushdecl (decl); 13167 DECL_BUILT_IN_CLASS (decl) = class; 13168 DECL_FUNCTION_CODE (decl) = function_code; 13169 13170 return decl; 13171 } 13172 13173 /* Handle when a new declaration NEWDECL 13174 has the same name as an old one OLDDECL 13175 in the same binding contour. 13176 Prints an error message if appropriate. 13177 13178 If safely possible, alter OLDDECL to look like NEWDECL, and return 1. 13179 Otherwise, return 0. */ 13180 13181 static int 13182 duplicate_decls (tree newdecl, tree olddecl) 13183 { 13184 int types_match = 1; 13185 int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL 13186 && DECL_INITIAL (newdecl) != 0); 13187 tree oldtype = TREE_TYPE (olddecl); 13188 tree newtype = TREE_TYPE (newdecl); 13189 13190 if (olddecl == newdecl) 13191 return 1; 13192 13193 if (TREE_CODE (newtype) == ERROR_MARK 13194 || TREE_CODE (oldtype) == ERROR_MARK) 13195 types_match = 0; 13196 13197 /* New decl is completely inconsistent with the old one => 13198 tell caller to replace the old one. 13199 This is always an error except in the case of shadowing a builtin. */ 13200 if (TREE_CODE (olddecl) != TREE_CODE (newdecl)) 13201 return 0; 13202 13203 /* For real parm decl following a forward decl, 13204 return 1 so old decl will be reused. */ 13205 if (types_match && TREE_CODE (newdecl) == PARM_DECL 13206 && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl)) 13207 return 1; 13208 13209 /* The new declaration is the same kind of object as the old one. 13210 The declarations may partially match. Print warnings if they don't 13211 match enough. Ultimately, copy most of the information from the new 13212 decl to the old one, and keep using the old one. */ 13213 13214 if (TREE_CODE (olddecl) == FUNCTION_DECL 13215 && DECL_BUILT_IN (olddecl)) 13216 { 13217 /* A function declaration for a built-in function. */ 13218 if (!TREE_PUBLIC (newdecl)) 13219 return 0; 13220 else if (!types_match) 13221 { 13222 /* Accept the return type of the new declaration if same modes. */ 13223 tree oldreturntype = TREE_TYPE (TREE_TYPE (olddecl)); 13224 tree newreturntype = TREE_TYPE (TREE_TYPE (newdecl)); 13225 13226 if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype)) 13227 { 13228 /* Function types may be shared, so we can't just modify 13229 the return type of olddecl's function type. */ 13230 tree newtype 13231 = build_function_type (newreturntype, 13232 TYPE_ARG_TYPES (TREE_TYPE (olddecl))); 13233 13234 types_match = 1; 13235 if (types_match) 13236 TREE_TYPE (olddecl) = newtype; 13237 } 13238 } 13239 if (!types_match) 13240 return 0; 13241 } 13242 else if (TREE_CODE (olddecl) == FUNCTION_DECL 13243 && DECL_SOURCE_LINE (olddecl) == 0) 13244 { 13245 /* A function declaration for a predeclared function 13246 that isn't actually built in. */ 13247 if (!TREE_PUBLIC (newdecl)) 13248 return 0; 13249 else if (!types_match) 13250 { 13251 /* If the types don't match, preserve volatility indication. 13252 Later on, we will discard everything else about the 13253 default declaration. */ 13254 TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl); 13255 } 13256 } 13257 13258 /* Copy all the DECL_... slots specified in the new decl 13259 except for any that we copy here from the old type. 13260 13261 Past this point, we don't change OLDTYPE and NEWTYPE 13262 even if we change the types of NEWDECL and OLDDECL. */ 13263 13264 if (types_match) 13265 { 13266 /* Merge the data types specified in the two decls. */ 13267 if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl)) 13268 TREE_TYPE (newdecl) 13269 = TREE_TYPE (olddecl) 13270 = TREE_TYPE (newdecl); 13271 13272 /* Lay the type out, unless already done. */ 13273 if (oldtype != TREE_TYPE (newdecl)) 13274 { 13275 if (TREE_TYPE (newdecl) != error_mark_node) 13276 layout_type (TREE_TYPE (newdecl)); 13277 if (TREE_CODE (newdecl) != FUNCTION_DECL 13278 && TREE_CODE (newdecl) != TYPE_DECL 13279 && TREE_CODE (newdecl) != CONST_DECL) 13280 layout_decl (newdecl, 0); 13281 } 13282 else 13283 { 13284 /* Since the type is OLDDECL's, make OLDDECL's size go with. */ 13285 DECL_SIZE (newdecl) = DECL_SIZE (olddecl); 13286 DECL_SIZE_UNIT (newdecl) = DECL_SIZE_UNIT (olddecl); 13287 if (TREE_CODE (olddecl) != FUNCTION_DECL) 13288 if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl)) 13289 { 13290 DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl); 13291 DECL_USER_ALIGN (newdecl) |= DECL_USER_ALIGN (olddecl); 13292 } 13293 } 13294 13295 /* Keep the old rtl since we can safely use it. */ 13296 COPY_DECL_RTL (olddecl, newdecl); 13297 13298 /* Merge the type qualifiers. */ 13299 if (DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl) 13300 && !TREE_THIS_VOLATILE (newdecl)) 13301 TREE_THIS_VOLATILE (olddecl) = 0; 13302 if (TREE_READONLY (newdecl)) 13303 TREE_READONLY (olddecl) = 1; 13304 if (TREE_THIS_VOLATILE (newdecl)) 13305 { 13306 TREE_THIS_VOLATILE (olddecl) = 1; 13307 if (TREE_CODE (newdecl) == VAR_DECL) 13308 make_var_volatile (newdecl); 13309 } 13310 13311 /* Keep source location of definition rather than declaration. 13312 Likewise, keep decl at outer scope. */ 13313 if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0) 13314 || (DECL_CONTEXT (newdecl) != 0 && DECL_CONTEXT (olddecl) == 0)) 13315 { 13316 DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl); 13317 DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl); 13318 13319 if (DECL_CONTEXT (olddecl) == 0 13320 && TREE_CODE (newdecl) != FUNCTION_DECL) 13321 DECL_CONTEXT (newdecl) = 0; 13322 } 13323 13324 /* Merge the unused-warning information. */ 13325 if (DECL_IN_SYSTEM_HEADER (olddecl)) 13326 DECL_IN_SYSTEM_HEADER (newdecl) = 1; 13327 else if (DECL_IN_SYSTEM_HEADER (newdecl)) 13328 DECL_IN_SYSTEM_HEADER (olddecl) = 1; 13329 13330 /* Merge the initialization information. */ 13331 if (DECL_INITIAL (newdecl) == 0) 13332 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl); 13333 13334 /* Merge the section attribute. 13335 We want to issue an error if the sections conflict but that must be 13336 done later in decl_attributes since we are called before attributes 13337 are assigned. */ 13338 if (DECL_SECTION_NAME (newdecl) == NULL_TREE) 13339 DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl); 13340 13341 if (TREE_CODE (newdecl) == FUNCTION_DECL) 13342 { 13343 DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl); 13344 DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl); 13345 } 13346 } 13347 /* If cannot merge, then use the new type and qualifiers, 13348 and don't preserve the old rtl. */ 13349 else 13350 { 13351 TREE_TYPE (olddecl) = TREE_TYPE (newdecl); 13352 TREE_READONLY (olddecl) = TREE_READONLY (newdecl); 13353 TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl); 13354 TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl); 13355 } 13356 13357 /* Merge the storage class information. */ 13358 /* For functions, static overrides non-static. */ 13359 if (TREE_CODE (newdecl) == FUNCTION_DECL) 13360 { 13361 TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl); 13362 /* This is since we don't automatically 13363 copy the attributes of NEWDECL into OLDDECL. */ 13364 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl); 13365 /* If this clears `static', clear it in the identifier too. */ 13366 if (! TREE_PUBLIC (olddecl)) 13367 TREE_PUBLIC (DECL_NAME (olddecl)) = 0; 13368 } 13369 if (DECL_EXTERNAL (newdecl)) 13370 { 13371 TREE_STATIC (newdecl) = TREE_STATIC (olddecl); 13372 DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl); 13373 /* An extern decl does not override previous storage class. */ 13374 TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl); 13375 } 13376 else 13377 { 13378 TREE_STATIC (olddecl) = TREE_STATIC (newdecl); 13379 TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl); 13380 } 13381 13382 /* If either decl says `inline', this fn is inline, 13383 unless its definition was passed already. */ 13384 if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0) 13385 DECL_INLINE (olddecl) = 1; 13386 DECL_INLINE (newdecl) = DECL_INLINE (olddecl); 13387 13388 /* Get rid of any built-in function if new arg types don't match it 13389 or if we have a function definition. */ 13390 if (TREE_CODE (newdecl) == FUNCTION_DECL 13391 && DECL_BUILT_IN (olddecl) 13392 && (!types_match || new_is_definition)) 13393 { 13394 TREE_TYPE (olddecl) = TREE_TYPE (newdecl); 13395 DECL_BUILT_IN_CLASS (olddecl) = NOT_BUILT_IN; 13396 } 13397 13398 /* If redeclaring a builtin function, and not a definition, 13399 it stays built in. 13400 Also preserve various other info from the definition. */ 13401 if (TREE_CODE (newdecl) == FUNCTION_DECL && !new_is_definition) 13402 { 13403 if (DECL_BUILT_IN (olddecl)) 13404 { 13405 DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl); 13406 DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl); 13407 } 13408 13409 DECL_RESULT (newdecl) = DECL_RESULT (olddecl); 13410 DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl); 13411 DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl); 13412 DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl); 13413 } 13414 13415 /* Copy most of the decl-specific fields of NEWDECL into OLDDECL. 13416 But preserve olddecl's DECL_UID. */ 13417 { 13418 register unsigned olddecl_uid = DECL_UID (olddecl); 13419 13420 memcpy ((char *) olddecl + sizeof (struct tree_common), 13421 (char *) newdecl + sizeof (struct tree_common), 13422 sizeof (struct tree_decl) - sizeof (struct tree_common)); 13423 DECL_UID (olddecl) = olddecl_uid; 13424 } 13425 13426 return 1; 13427 } 13428 13429 /* Finish processing of a declaration; 13430 install its initial value. 13431 If the length of an array type is not known before, 13432 it must be determined now, from the initial value, or it is an error. */ 13433 13434 static void 13435 finish_decl (tree decl, tree init, bool is_top_level) 13436 { 13437 register tree type = TREE_TYPE (decl); 13438 int was_incomplete = (DECL_SIZE (decl) == 0); 13439 bool at_top_level = (current_binding_level == global_binding_level); 13440 bool top_level = is_top_level || at_top_level; 13441 13442 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top 13443 level anyway. */ 13444 assert (!is_top_level || !at_top_level); 13445 13446 if (TREE_CODE (decl) == PARM_DECL) 13447 assert (init == NULL_TREE); 13448 /* Remember that PARM_DECL doesn't have a DECL_INITIAL field per se -- it 13449 overlaps DECL_ARG_TYPE. */ 13450 else if (init == NULL_TREE) 13451 assert (DECL_INITIAL (decl) == NULL_TREE); 13452 else 13453 assert (DECL_INITIAL (decl) == error_mark_node); 13454 13455 if (init != NULL_TREE) 13456 { 13457 if (TREE_CODE (decl) != TYPE_DECL) 13458 DECL_INITIAL (decl) = init; 13459 else 13460 { 13461 /* typedef foo = bar; store the type of bar as the type of foo. */ 13462 TREE_TYPE (decl) = TREE_TYPE (init); 13463 DECL_INITIAL (decl) = init = 0; 13464 } 13465 } 13466 13467 /* Deduce size of array from initialization, if not already known */ 13468 13469 if (TREE_CODE (type) == ARRAY_TYPE 13470 && TYPE_DOMAIN (type) == 0 13471 && TREE_CODE (decl) != TYPE_DECL) 13472 { 13473 assert (top_level); 13474 assert (was_incomplete); 13475 13476 layout_decl (decl, 0); 13477 } 13478 13479 if (TREE_CODE (decl) == VAR_DECL) 13480 { 13481 if (DECL_SIZE (decl) == NULL_TREE 13482 && TYPE_SIZE (TREE_TYPE (decl)) != NULL_TREE) 13483 layout_decl (decl, 0); 13484 13485 if (DECL_SIZE (decl) == NULL_TREE 13486 && (TREE_STATIC (decl) 13487 ? 13488 /* A static variable with an incomplete type is an error if it is 13489 initialized. Also if it is not file scope. Otherwise, let it 13490 through, but if it is not `extern' then it may cause an error 13491 message later. */ 13492 (DECL_INITIAL (decl) != 0 || DECL_CONTEXT (decl) != 0) 13493 : 13494 /* An automatic variable with an incomplete type is an error. */ 13495 !DECL_EXTERNAL (decl))) 13496 { 13497 assert ("storage size not known" == NULL); 13498 abort (); 13499 } 13500 13501 if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl)) 13502 && (DECL_SIZE (decl) != 0) 13503 && (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)) 13504 { 13505 assert ("storage size not constant" == NULL); 13506 abort (); 13507 } 13508 } 13509 13510 /* Output the assembler code and/or RTL code for variables and functions, 13511 unless the type is an undefined structure or union. If not, it will get 13512 done when the type is completed. */ 13513 13514 if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL) 13515 { 13516 rest_of_decl_compilation (decl, NULL, 13517 DECL_CONTEXT (decl) == 0, 13518 0); 13519 13520 if (DECL_CONTEXT (decl) != 0) 13521 { 13522 /* Recompute the RTL of a local array now if it used to be an 13523 incomplete type. */ 13524 if (was_incomplete 13525 && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl)) 13526 { 13527 /* If we used it already as memory, it must stay in memory. */ 13528 TREE_ADDRESSABLE (decl) = TREE_USED (decl); 13529 /* If it's still incomplete now, no init will save it. */ 13530 if (DECL_SIZE (decl) == 0) 13531 DECL_INITIAL (decl) = 0; 13532 expand_decl (decl); 13533 } 13534 /* Compute and store the initial value. */ 13535 if (TREE_CODE (decl) != FUNCTION_DECL) 13536 expand_decl_init (decl); 13537 } 13538 } 13539 else if (TREE_CODE (decl) == TYPE_DECL) 13540 { 13541 rest_of_decl_compilation (decl, NULL, 13542 DECL_CONTEXT (decl) == 0, 13543 0); 13544 } 13545 13546 /* At the end of a declaration, throw away any variable type sizes of types 13547 defined inside that declaration. There is no use computing them in the 13548 following function definition. */ 13549 if (current_binding_level == global_binding_level) 13550 get_pending_sizes (); 13551 } 13552 13553 /* Finish up a function declaration and compile that function 13554 all the way to assembler language output. The free the storage 13555 for the function definition. 13556 13557 This is called after parsing the body of the function definition. 13558 13559 NESTED is nonzero if the function being finished is nested in another. */ 13560 13561 static void 13562 finish_function (int nested) 13563 { 13564 register tree fndecl = current_function_decl; 13565 13566 assert (fndecl != NULL_TREE); 13567 if (TREE_CODE (fndecl) != ERROR_MARK) 13568 { 13569 if (nested) 13570 assert (DECL_CONTEXT (fndecl) != NULL_TREE); 13571 else 13572 assert (DECL_CONTEXT (fndecl) == NULL_TREE); 13573 } 13574 13575 /* TREE_READONLY (fndecl) = 1; 13576 This caused &foo to be of type ptr-to-const-function 13577 which then got a warning when stored in a ptr-to-function variable. */ 13578 13579 poplevel (1, 0, 1); 13580 13581 if (TREE_CODE (fndecl) != ERROR_MARK) 13582 { 13583 BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl; 13584 13585 /* Must mark the RESULT_DECL as being in this function. */ 13586 13587 DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl; 13588 13589 /* Obey `register' declarations if `setjmp' is called in this fn. */ 13590 /* Generate rtl for function exit. */ 13591 expand_function_end (input_filename, lineno, 0); 13592 13593 /* If this is a nested function, protect the local variables in the stack 13594 above us from being collected while we're compiling this function. */ 13595 if (nested) 13596 ggc_push_context (); 13597 13598 /* Run the optimizers and output the assembler code for this function. */ 13599 rest_of_compilation (fndecl); 13600 13601 /* Undo the GC context switch. */ 13602 if (nested) 13603 ggc_pop_context (); 13604 } 13605 13606 if (TREE_CODE (fndecl) != ERROR_MARK 13607 && !nested 13608 && DECL_SAVED_INSNS (fndecl) == 0) 13609 { 13610 /* Stop pointing to the local nodes about to be freed. */ 13611 /* But DECL_INITIAL must remain nonzero so we know this was an actual 13612 function definition. */ 13613 /* For a nested function, this is done in pop_f_function_context. */ 13614 /* If rest_of_compilation set this to 0, leave it 0. */ 13615 if (DECL_INITIAL (fndecl) != 0) 13616 DECL_INITIAL (fndecl) = error_mark_node; 13617 DECL_ARGUMENTS (fndecl) = 0; 13618 } 13619 13620 if (!nested) 13621 { 13622 /* Let the error reporting routines know that we're outside a function. 13623 For a nested function, this value is used in pop_c_function_context 13624 and then reset via pop_function_context. */ 13625 ffecom_outer_function_decl_ = current_function_decl = NULL; 13626 } 13627 } 13628 13629 /* Plug-in replacement for identifying the name of a decl and, for a 13630 function, what we call it in diagnostics. For now, "program unit" 13631 should suffice, since it's a bit of a hassle to figure out which 13632 of several kinds of things it is. Note that it could conceivably 13633 be a statement function, which probably isn't really a program unit 13634 per se, but if that comes up, it should be easy to check (being a 13635 nested function and all). */ 13636 13637 static const char * 13638 ffe_printable_name (tree decl, int v) 13639 { 13640 /* Just to keep GCC quiet about the unused variable. 13641 In theory, differing values of V should produce different 13642 output. */ 13643 switch (v) 13644 { 13645 default: 13646 if (TREE_CODE (decl) == ERROR_MARK) 13647 return "erroneous code"; 13648 return IDENTIFIER_POINTER (DECL_NAME (decl)); 13649 } 13650 } 13651 13652 /* g77's function to print out name of current function that caused 13653 an error. */ 13654 13655 static void 13656 ffe_print_error_function (diagnostic_context *context __attribute__((unused)), 13657 const char *file) 13658 { 13659 static ffeglobal last_g = NULL; 13660 static ffesymbol last_s = NULL; 13661 ffeglobal g; 13662 ffesymbol s; 13663 const char *kind; 13664 13665 if ((ffecom_primary_entry_ == NULL) 13666 || (ffesymbol_global (ffecom_primary_entry_) == NULL)) 13667 { 13668 g = NULL; 13669 s = NULL; 13670 kind = NULL; 13671 } 13672 else 13673 { 13674 g = ffesymbol_global (ffecom_primary_entry_); 13675 if (ffecom_nested_entry_ == NULL) 13676 { 13677 s = ffecom_primary_entry_; 13678 kind = _(ffeinfo_kind_message (ffesymbol_kind (s))); 13679 } 13680 else 13681 { 13682 s = ffecom_nested_entry_; 13683 kind = _("In statement function"); 13684 } 13685 } 13686 13687 if ((last_g != g) || (last_s != s)) 13688 { 13689 if (file) 13690 fprintf (stderr, "%s: ", file); 13691 13692 if (s == NULL) 13693 fprintf (stderr, _("Outside of any program unit:\n")); 13694 else 13695 { 13696 const char *name = ffesymbol_text (s); 13697 13698 fprintf (stderr, "%s `%s':\n", kind, name); 13699 } 13700 13701 last_g = g; 13702 last_s = s; 13703 } 13704 } 13705 13706 /* Similar to `lookup_name' but look only at current binding level. */ 13707 13708 static tree 13709 lookup_name_current_level (tree name) 13710 { 13711 register tree t; 13712 13713 if (current_binding_level == global_binding_level) 13714 return IDENTIFIER_GLOBAL_VALUE (name); 13715 13716 if (IDENTIFIER_LOCAL_VALUE (name) == 0) 13717 return 0; 13718 13719 for (t = current_binding_level->names; t; t = TREE_CHAIN (t)) 13720 if (DECL_NAME (t) == name) 13721 break; 13722 13723 return t; 13724 } 13725 13726 /* Create a new `struct f_binding_level'. */ 13727 13728 static struct f_binding_level * 13729 make_binding_level () 13730 { 13731 /* NOSTRICT */ 13732 return ggc_alloc (sizeof (struct f_binding_level)); 13733 } 13734 13735 /* Save and restore the variables in this file and elsewhere 13736 that keep track of the progress of compilation of the current function. 13737 Used for nested functions. */ 13738 13739 struct f_function 13740 { 13741 struct f_function *next; 13742 tree named_labels; 13743 tree shadowed_labels; 13744 struct f_binding_level *binding_level; 13745 }; 13746 13747 struct f_function *f_function_chain; 13748 13749 /* Restore the variables used during compilation of a C function. */ 13750 13751 static void 13752 pop_f_function_context () 13753 { 13754 struct f_function *p = f_function_chain; 13755 tree link; 13756 13757 /* Bring back all the labels that were shadowed. */ 13758 for (link = shadowed_labels; link; link = TREE_CHAIN (link)) 13759 if (DECL_NAME (TREE_VALUE (link)) != 0) 13760 IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link))) 13761 = TREE_VALUE (link); 13762 13763 if (current_function_decl != error_mark_node 13764 && DECL_SAVED_INSNS (current_function_decl) == 0) 13765 { 13766 /* Stop pointing to the local nodes about to be freed. */ 13767 /* But DECL_INITIAL must remain nonzero so we know this was an actual 13768 function definition. */ 13769 DECL_INITIAL (current_function_decl) = error_mark_node; 13770 DECL_ARGUMENTS (current_function_decl) = 0; 13771 } 13772 13773 pop_function_context (); 13774 13775 f_function_chain = p->next; 13776 13777 named_labels = p->named_labels; 13778 shadowed_labels = p->shadowed_labels; 13779 current_binding_level = p->binding_level; 13780 13781 free (p); 13782 } 13783 13784 /* Save and reinitialize the variables 13785 used during compilation of a C function. */ 13786 13787 static void 13788 push_f_function_context () 13789 { 13790 struct f_function *p 13791 = (struct f_function *) xmalloc (sizeof (struct f_function)); 13792 13793 push_function_context (); 13794 13795 p->next = f_function_chain; 13796 f_function_chain = p; 13797 13798 p->named_labels = named_labels; 13799 p->shadowed_labels = shadowed_labels; 13800 p->binding_level = current_binding_level; 13801 } 13802 13803 static void 13804 push_parm_decl (tree parm) 13805 { 13806 int old_immediate_size_expand = immediate_size_expand; 13807 13808 /* Don't try computing parm sizes now -- wait till fn is called. */ 13809 13810 immediate_size_expand = 0; 13811 13812 /* Fill in arg stuff. */ 13813 13814 DECL_ARG_TYPE (parm) = TREE_TYPE (parm); 13815 DECL_ARG_TYPE_AS_WRITTEN (parm) = TREE_TYPE (parm); 13816 TREE_READONLY (parm) = 1; /* All implementation args are read-only. */ 13817 13818 parm = pushdecl (parm); 13819 13820 immediate_size_expand = old_immediate_size_expand; 13821 13822 finish_decl (parm, NULL_TREE, FALSE); 13823 } 13824 13825 /* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, if appropriate. */ 13826 13827 static tree 13828 pushdecl_top_level (x) 13829 tree x; 13830 { 13831 register tree t; 13832 register struct f_binding_level *b = current_binding_level; 13833 register tree f = current_function_decl; 13834 13835 current_binding_level = global_binding_level; 13836 current_function_decl = NULL_TREE; 13837 t = pushdecl (x); 13838 current_binding_level = b; 13839 current_function_decl = f; 13840 return t; 13841 } 13842 13843 /* Store the list of declarations of the current level. 13844 This is done for the parameter declarations of a function being defined, 13845 after they are modified in the light of any missing parameters. */ 13846 13847 static tree 13848 storedecls (decls) 13849 tree decls; 13850 { 13851 return current_binding_level->names = decls; 13852 } 13853 13854 /* Store the parameter declarations into the current function declaration. 13855 This is called after parsing the parameter declarations, before 13856 digesting the body of the function. 13857 13858 For an old-style definition, modify the function's type 13859 to specify at least the number of arguments. */ 13860 13861 static void 13862 store_parm_decls (int is_main_program UNUSED) 13863 { 13864 register tree fndecl = current_function_decl; 13865 13866 if (fndecl == error_mark_node) 13867 return; 13868 13869 /* This is a chain of PARM_DECLs from old-style parm declarations. */ 13870 DECL_ARGUMENTS (fndecl) = storedecls (nreverse (getdecls ())); 13871 13872 /* Initialize the RTL code for the function. */ 13873 13874 init_function_start (fndecl, input_filename, lineno); 13875 13876 /* Set up parameters and prepare for return, for the function. */ 13877 13878 expand_function_start (fndecl, 0); 13879 } 13880 13881 static tree 13882 start_decl (tree decl, bool is_top_level) 13883 { 13884 register tree tem; 13885 bool at_top_level = (current_binding_level == global_binding_level); 13886 bool top_level = is_top_level || at_top_level; 13887 13888 /* Caller should pass TRUE for is_top_level only if we wouldn't be at top 13889 level anyway. */ 13890 assert (!is_top_level || !at_top_level); 13891 13892 if (DECL_INITIAL (decl) != NULL_TREE) 13893 { 13894 assert (DECL_INITIAL (decl) == error_mark_node); 13895 assert (!DECL_EXTERNAL (decl)); 13896 } 13897 else if (top_level) 13898 assert ((TREE_STATIC (decl) == 1) || DECL_EXTERNAL (decl) == 1); 13899 13900 /* For Fortran, we by default put things in .common when possible. */ 13901 DECL_COMMON (decl) = 1; 13902 13903 /* Add this decl to the current binding level. TEM may equal DECL or it may 13904 be a previous decl of the same name. */ 13905 if (is_top_level) 13906 tem = pushdecl_top_level (decl); 13907 else 13908 tem = pushdecl (decl); 13909 13910 /* For a local variable, define the RTL now. */ 13911 if (!top_level 13912 /* But not if this is a duplicate decl and we preserved the rtl from the 13913 previous one (which may or may not happen). */ 13914 && !DECL_RTL_SET_P (tem)) 13915 { 13916 if (TYPE_SIZE (TREE_TYPE (tem)) != 0) 13917 expand_decl (tem); 13918 else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE 13919 && DECL_INITIAL (tem) != 0) 13920 expand_decl (tem); 13921 } 13922 13923 return tem; 13924 } 13925 13926 /* Create the FUNCTION_DECL for a function definition. 13927 DECLSPECS and DECLARATOR are the parts of the declaration; 13928 they describe the function's name and the type it returns, 13929 but twisted together in a fashion that parallels the syntax of C. 13930 13931 This function creates a binding context for the function body 13932 as well as setting up the FUNCTION_DECL in current_function_decl. 13933 13934 Returns 1 on success. If the DECLARATOR is not suitable for a function 13935 (it defines a datum instead), we return 0, which tells 13936 ffe_parse_file to report a parse error. 13937 13938 NESTED is nonzero for a function nested within another function. */ 13939 13940 static void 13941 start_function (tree name, tree type, int nested, int public) 13942 { 13943 tree decl1; 13944 tree restype; 13945 int old_immediate_size_expand = immediate_size_expand; 13946 13947 named_labels = 0; 13948 shadowed_labels = 0; 13949 13950 /* Don't expand any sizes in the return type of the function. */ 13951 immediate_size_expand = 0; 13952 13953 if (nested) 13954 { 13955 assert (!public); 13956 assert (current_function_decl != NULL_TREE); 13957 assert (DECL_CONTEXT (current_function_decl) == NULL_TREE); 13958 } 13959 else 13960 { 13961 assert (current_function_decl == NULL_TREE); 13962 } 13963 13964 if (TREE_CODE (type) == ERROR_MARK) 13965 decl1 = current_function_decl = error_mark_node; 13966 else 13967 { 13968 decl1 = build_decl (FUNCTION_DECL, 13969 name, 13970 type); 13971 TREE_PUBLIC (decl1) = public ? 1 : 0; 13972 if (nested) 13973 DECL_INLINE (decl1) = 1; 13974 TREE_STATIC (decl1) = 1; 13975 DECL_EXTERNAL (decl1) = 0; 13976 13977 announce_function (decl1); 13978 13979 /* Make the init_value nonzero so pushdecl knows this is not tentative. 13980 error_mark_node is replaced below (in poplevel) with the BLOCK. */ 13981 DECL_INITIAL (decl1) = error_mark_node; 13982 13983 /* Record the decl so that the function name is defined. If we already have 13984 a decl for this name, and it is a FUNCTION_DECL, use the old decl. */ 13985 13986 current_function_decl = pushdecl (decl1); 13987 } 13988 13989 if (!nested) 13990 ffecom_outer_function_decl_ = current_function_decl; 13991 13992 pushlevel (0); 13993 current_binding_level->prep_state = 2; 13994 13995 if (TREE_CODE (current_function_decl) != ERROR_MARK) 13996 { 13997 make_decl_rtl (current_function_decl, NULL); 13998 13999 restype = TREE_TYPE (TREE_TYPE (current_function_decl)); 14000 DECL_RESULT (current_function_decl) 14001 = build_decl (RESULT_DECL, NULL_TREE, restype); 14002 } 14003 14004 if (!nested && (TREE_CODE (current_function_decl) != ERROR_MARK)) 14005 TREE_ADDRESSABLE (current_function_decl) = 1; 14006 14007 immediate_size_expand = old_immediate_size_expand; 14008 } 14009 14010 /* Here are the public functions the GNU back end needs. */ 14011 14012 tree 14013 convert (type, expr) 14014 tree type, expr; 14015 { 14016 register tree e = expr; 14017 register enum tree_code code = TREE_CODE (type); 14018 14019 if (type == TREE_TYPE (e) 14020 || TREE_CODE (e) == ERROR_MARK) 14021 return e; 14022 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e))) 14023 return fold (build1 (NOP_EXPR, type, e)); 14024 if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK 14025 || code == ERROR_MARK) 14026 return error_mark_node; 14027 if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE) 14028 { 14029 assert ("void value not ignored as it ought to be" == NULL); 14030 return error_mark_node; 14031 } 14032 if (code == VOID_TYPE) 14033 return build1 (CONVERT_EXPR, type, e); 14034 if ((code != RECORD_TYPE) 14035 && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE)) 14036 e = ffecom_1 (REALPART_EXPR, TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e))), 14037 e); 14038 if (code == INTEGER_TYPE || code == ENUMERAL_TYPE) 14039 return fold (convert_to_integer (type, e)); 14040 if (code == POINTER_TYPE) 14041 return fold (convert_to_pointer (type, e)); 14042 if (code == REAL_TYPE) 14043 return fold (convert_to_real (type, e)); 14044 if (code == COMPLEX_TYPE) 14045 return fold (convert_to_complex (type, e)); 14046 if (code == RECORD_TYPE) 14047 return fold (ffecom_convert_to_complex_ (type, e)); 14048 14049 assert ("conversion to non-scalar type requested" == NULL); 14050 return error_mark_node; 14051 } 14052 14053 /* Return the list of declarations of the current level. 14054 Note that this list is in reverse order unless/until 14055 you nreverse it; and when you do nreverse it, you must 14056 store the result back using `storedecls' or you will lose. */ 14057 14058 tree 14059 getdecls () 14060 { 14061 return current_binding_level->names; 14062 } 14063 14064 /* Nonzero if we are currently in the global binding level. */ 14065 14066 int 14067 global_bindings_p () 14068 { 14069 return current_binding_level == global_binding_level; 14070 } 14071 14072 static void 14073 ffecom_init_decl_processing () 14074 { 14075 malloc_init (); 14076 14077 ffe_init_0 (); 14078 } 14079 14080 /* Delete the node BLOCK from the current binding level. 14081 This is used for the block inside a stmt expr ({...}) 14082 so that the block can be reinserted where appropriate. */ 14083 14084 static void 14085 delete_block (block) 14086 tree block; 14087 { 14088 tree t; 14089 if (current_binding_level->blocks == block) 14090 current_binding_level->blocks = TREE_CHAIN (block); 14091 for (t = current_binding_level->blocks; t;) 14092 { 14093 if (TREE_CHAIN (t) == block) 14094 TREE_CHAIN (t) = TREE_CHAIN (block); 14095 else 14096 t = TREE_CHAIN (t); 14097 } 14098 TREE_CHAIN (block) = NULL; 14099 /* Clear TREE_USED which is always set by poplevel. 14100 The flag is set again if insert_block is called. */ 14101 TREE_USED (block) = 0; 14102 } 14103 14104 void 14105 insert_block (block) 14106 tree block; 14107 { 14108 TREE_USED (block) = 1; 14109 current_binding_level->blocks 14110 = chainon (current_binding_level->blocks, block); 14111 } 14112 14113 /* Each front end provides its own. */ 14114 static const char *ffe_init PARAMS ((const char *)); 14115 static void ffe_finish PARAMS ((void)); 14116 static void ffe_init_options PARAMS ((void)); 14117 static void ffe_print_identifier PARAMS ((FILE *, tree, int)); 14118 14119 struct language_function GTY(()) 14120 { 14121 int unused; 14122 }; 14123 14124 #undef LANG_HOOKS_NAME 14125 #define LANG_HOOKS_NAME "GNU F77" 14126 #undef LANG_HOOKS_INIT 14127 #define LANG_HOOKS_INIT ffe_init 14128 #undef LANG_HOOKS_FINISH 14129 #define LANG_HOOKS_FINISH ffe_finish 14130 #undef LANG_HOOKS_INIT_OPTIONS 14131 #define LANG_HOOKS_INIT_OPTIONS ffe_init_options 14132 #undef LANG_HOOKS_DECODE_OPTION 14133 #define LANG_HOOKS_DECODE_OPTION ffe_decode_option 14134 #undef LANG_HOOKS_PARSE_FILE 14135 #define LANG_HOOKS_PARSE_FILE ffe_parse_file 14136 #undef LANG_HOOKS_MARK_ADDRESSABLE 14137 #define LANG_HOOKS_MARK_ADDRESSABLE ffe_mark_addressable 14138 #undef LANG_HOOKS_PRINT_IDENTIFIER 14139 #define LANG_HOOKS_PRINT_IDENTIFIER ffe_print_identifier 14140 #undef LANG_HOOKS_DECL_PRINTABLE_NAME 14141 #define LANG_HOOKS_DECL_PRINTABLE_NAME ffe_printable_name 14142 #undef LANG_HOOKS_PRINT_ERROR_FUNCTION 14143 #define LANG_HOOKS_PRINT_ERROR_FUNCTION ffe_print_error_function 14144 #undef LANG_HOOKS_TRUTHVALUE_CONVERSION 14145 #define LANG_HOOKS_TRUTHVALUE_CONVERSION ffe_truthvalue_conversion 14146 14147 #undef LANG_HOOKS_TYPE_FOR_MODE 14148 #define LANG_HOOKS_TYPE_FOR_MODE ffe_type_for_mode 14149 #undef LANG_HOOKS_TYPE_FOR_SIZE 14150 #define LANG_HOOKS_TYPE_FOR_SIZE ffe_type_for_size 14151 #undef LANG_HOOKS_SIGNED_TYPE 14152 #define LANG_HOOKS_SIGNED_TYPE ffe_signed_type 14153 #undef LANG_HOOKS_UNSIGNED_TYPE 14154 #define LANG_HOOKS_UNSIGNED_TYPE ffe_unsigned_type 14155 #undef LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE 14156 #define LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE ffe_signed_or_unsigned_type 14157 14158 /* We do not wish to use alias-set based aliasing at all. Used in the 14159 extreme (every object with its own set, with equivalences recorded) it 14160 might be helpful, but there are problems when it comes to inlining. We 14161 get on ok with flag_argument_noalias, and alias-set aliasing does 14162 currently limit how stack slots can be reused, which is a lose. */ 14163 #undef LANG_HOOKS_GET_ALIAS_SET 14164 #define LANG_HOOKS_GET_ALIAS_SET hook_get_alias_set_0 14165 14166 const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; 14167 14168 /* Table indexed by tree code giving a string containing a character 14169 classifying the tree code. Possibilities are 14170 t, d, s, c, r, <, 1, 2 and e. See tree.def for details. */ 14171 14172 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE, 14173 14174 const char tree_code_type[] = { 14175 #include "tree.def" 14176 }; 14177 #undef DEFTREECODE 14178 14179 /* Table indexed by tree code giving number of expression 14180 operands beyond the fixed part of the node structure. 14181 Not used for types or decls. */ 14182 14183 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH, 14184 14185 const unsigned char tree_code_length[] = { 14186 #include "tree.def" 14187 }; 14188 #undef DEFTREECODE 14189 14190 /* Names of tree components. 14191 Used for printing out the tree and error messages. */ 14192 #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME, 14193 14194 const char *const tree_code_name[] = { 14195 #include "tree.def" 14196 }; 14197 #undef DEFTREECODE 14198 14199 static const char * 14200 ffe_init (filename) 14201 const char *filename; 14202 { 14203 /* Open input file. */ 14204 if (filename == 0 || !strcmp (filename, "-")) 14205 { 14206 finput = stdin; 14207 filename = "stdin"; 14208 } 14209 else 14210 finput = fopen (filename, "r"); 14211 if (finput == 0) 14212 fatal_io_error ("can't open %s", filename); 14213 14214 #ifdef IO_BUFFER_SIZE 14215 setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE); 14216 #endif 14217 14218 ffecom_init_decl_processing (); 14219 14220 /* If the file is output from cpp, it should contain a first line 14221 `# 1 "real-filename"', and the current design of gcc (toplev.c 14222 in particular and the way it sets up information relied on by 14223 INCLUDE) requires that we read this now, and store the 14224 "real-filename" info in master_input_filename. Ask the lexer 14225 to try doing this. */ 14226 ffelex_hash_kludge (finput); 14227 14228 /* FIXME: The ffelex_hash_kludge code needs to be cleaned up to 14229 return the new file name. */ 14230 if (main_input_filename) 14231 filename = main_input_filename; 14232 14233 return filename; 14234 } 14235 14236 static void 14237 ffe_finish () 14238 { 14239 ffe_terminate_0 (); 14240 14241 if (ffe_is_ffedebug ()) 14242 malloc_pool_display (malloc_pool_image ()); 14243 14244 fclose (finput); 14245 } 14246 14247 static void 14248 ffe_init_options () 14249 { 14250 /* Set default options for Fortran. */ 14251 flag_move_all_movables = 1; 14252 flag_reduce_all_givs = 1; 14253 flag_argument_noalias = 2; 14254 flag_merge_constants = 2; 14255 flag_errno_math = 0; 14256 flag_complex_divide_method = 1; 14257 } 14258 14259 static bool 14260 ffe_mark_addressable (exp) 14261 tree exp; 14262 { 14263 register tree x = exp; 14264 while (1) 14265 switch (TREE_CODE (x)) 14266 { 14267 case ADDR_EXPR: 14268 case COMPONENT_REF: 14269 case ARRAY_REF: 14270 x = TREE_OPERAND (x, 0); 14271 break; 14272 14273 case CONSTRUCTOR: 14274 TREE_ADDRESSABLE (x) = 1; 14275 return true; 14276 14277 case VAR_DECL: 14278 case CONST_DECL: 14279 case PARM_DECL: 14280 case RESULT_DECL: 14281 if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x) 14282 && DECL_NONLOCAL (x)) 14283 { 14284 if (TREE_PUBLIC (x)) 14285 { 14286 assert ("address of global register var requested" == NULL); 14287 return false; 14288 } 14289 assert ("address of register variable requested" == NULL); 14290 } 14291 else if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)) 14292 { 14293 if (TREE_PUBLIC (x)) 14294 { 14295 assert ("address of global register var requested" == NULL); 14296 return false; 14297 } 14298 assert ("address of register var requested" == NULL); 14299 } 14300 put_var_into_stack (x, /*rescan=*/true); 14301 14302 /* drops in */ 14303 case FUNCTION_DECL: 14304 TREE_ADDRESSABLE (x) = 1; 14305 #if 0 /* poplevel deals with this now. */ 14306 if (DECL_CONTEXT (x) == 0) 14307 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1; 14308 #endif 14309 14310 default: 14311 return true; 14312 } 14313 } 14314 14315 /* Exit a binding level. 14316 Pop the level off, and restore the state of the identifier-decl mappings 14317 that were in effect when this level was entered. 14318 14319 If KEEP is nonzero, this level had explicit declarations, so 14320 and create a "block" (a BLOCK node) for the level 14321 to record its declarations and subblocks for symbol table output. 14322 14323 If FUNCTIONBODY is nonzero, this level is the body of a function, 14324 so create a block as if KEEP were set and also clear out all 14325 label names. 14326 14327 If REVERSE is nonzero, reverse the order of decls before putting 14328 them into the BLOCK. */ 14329 14330 tree 14331 poplevel (keep, reverse, functionbody) 14332 int keep; 14333 int reverse; 14334 int functionbody; 14335 { 14336 register tree link; 14337 /* The chain of decls was accumulated in reverse order. 14338 Put it into forward order, just for cleanliness. */ 14339 tree decls; 14340 tree subblocks = current_binding_level->blocks; 14341 tree block = 0; 14342 tree decl; 14343 int block_previously_created; 14344 14345 /* Get the decls in the order they were written. 14346 Usually current_binding_level->names is in reverse order. 14347 But parameter decls were previously put in forward order. */ 14348 14349 if (reverse) 14350 current_binding_level->names 14351 = decls = nreverse (current_binding_level->names); 14352 else 14353 decls = current_binding_level->names; 14354 14355 /* Output any nested inline functions within this block 14356 if they weren't already output. */ 14357 14358 for (decl = decls; decl; decl = TREE_CHAIN (decl)) 14359 if (TREE_CODE (decl) == FUNCTION_DECL 14360 && ! TREE_ASM_WRITTEN (decl) 14361 && DECL_INITIAL (decl) != 0 14362 && TREE_ADDRESSABLE (decl)) 14363 { 14364 /* If this decl was copied from a file-scope decl 14365 on account of a block-scope extern decl, 14366 propagate TREE_ADDRESSABLE to the file-scope decl. 14367 14368 DECL_ABSTRACT_ORIGIN can be set to itself if warn_return_type is 14369 true, since then the decl goes through save_for_inline_copying. */ 14370 if (DECL_ABSTRACT_ORIGIN (decl) != 0 14371 && DECL_ABSTRACT_ORIGIN (decl) != decl) 14372 TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1; 14373 else if (DECL_SAVED_INSNS (decl) != 0) 14374 { 14375 push_function_context (); 14376 output_inline_function (decl); 14377 pop_function_context (); 14378 } 14379 } 14380 14381 /* If there were any declarations or structure tags in that level, 14382 or if this level is a function body, 14383 create a BLOCK to record them for the life of this function. */ 14384 14385 block = 0; 14386 block_previously_created = (current_binding_level->this_block != 0); 14387 if (block_previously_created) 14388 block = current_binding_level->this_block; 14389 else if (keep || functionbody) 14390 block = make_node (BLOCK); 14391 if (block != 0) 14392 { 14393 BLOCK_VARS (block) = decls; 14394 BLOCK_SUBBLOCKS (block) = subblocks; 14395 } 14396 14397 /* In each subblock, record that this is its superior. */ 14398 14399 for (link = subblocks; link; link = TREE_CHAIN (link)) 14400 BLOCK_SUPERCONTEXT (link) = block; 14401 14402 /* Clear out the meanings of the local variables of this level. */ 14403 14404 for (link = decls; link; link = TREE_CHAIN (link)) 14405 { 14406 if (DECL_NAME (link) != 0) 14407 { 14408 /* If the ident. was used or addressed via a local extern decl, 14409 don't forget that fact. */ 14410 if (DECL_EXTERNAL (link)) 14411 { 14412 if (TREE_USED (link)) 14413 TREE_USED (DECL_NAME (link)) = 1; 14414 if (TREE_ADDRESSABLE (link)) 14415 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1; 14416 } 14417 IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0; 14418 } 14419 } 14420 14421 /* If the level being exited is the top level of a function, 14422 check over all the labels, and clear out the current 14423 (function local) meanings of their names. */ 14424 14425 if (functionbody) 14426 { 14427 /* If this is the top level block of a function, 14428 the vars are the function's parameters. 14429 Don't leave them in the BLOCK because they are 14430 found in the FUNCTION_DECL instead. */ 14431 14432 BLOCK_VARS (block) = 0; 14433 } 14434 14435 /* Pop the current level, and free the structure for reuse. */ 14436 14437 { 14438 register struct f_binding_level *level = current_binding_level; 14439 current_binding_level = current_binding_level->level_chain; 14440 14441 level->level_chain = free_binding_level; 14442 free_binding_level = level; 14443 } 14444 14445 /* Dispose of the block that we just made inside some higher level. */ 14446 if (functionbody 14447 && current_function_decl != error_mark_node) 14448 DECL_INITIAL (current_function_decl) = block; 14449 else if (block) 14450 { 14451 if (!block_previously_created) 14452 current_binding_level->blocks 14453 = chainon (current_binding_level->blocks, block); 14454 } 14455 /* If we did not make a block for the level just exited, 14456 any blocks made for inner levels 14457 (since they cannot be recorded as subblocks in that level) 14458 must be carried forward so they will later become subblocks 14459 of something else. */ 14460 else if (subblocks) 14461 current_binding_level->blocks 14462 = chainon (current_binding_level->blocks, subblocks); 14463 14464 if (block) 14465 TREE_USED (block) = 1; 14466 return block; 14467 } 14468 14469 static void 14470 ffe_print_identifier (file, node, indent) 14471 FILE *file; 14472 tree node; 14473 int indent; 14474 { 14475 print_node (file, "global", IDENTIFIER_GLOBAL_VALUE (node), indent + 4); 14476 print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4); 14477 } 14478 14479 /* Record a decl-node X as belonging to the current lexical scope. 14480 Check for errors (such as an incompatible declaration for the same 14481 name already seen in the same scope). 14482 14483 Returns either X or an old decl for the same name. 14484 If an old decl is returned, it may have been smashed 14485 to agree with what X says. */ 14486 14487 tree 14488 pushdecl (x) 14489 tree x; 14490 { 14491 register tree t; 14492 register tree name = DECL_NAME (x); 14493 register struct f_binding_level *b = current_binding_level; 14494 14495 if ((TREE_CODE (x) == FUNCTION_DECL) 14496 && (DECL_INITIAL (x) == 0) 14497 && DECL_EXTERNAL (x)) 14498 DECL_CONTEXT (x) = NULL_TREE; 14499 else 14500 DECL_CONTEXT (x) = current_function_decl; 14501 14502 if (name) 14503 { 14504 if (IDENTIFIER_INVENTED (name)) 14505 { 14506 DECL_ARTIFICIAL (x) = 1; 14507 DECL_IN_SYSTEM_HEADER (x) = 1; 14508 } 14509 14510 t = lookup_name_current_level (name); 14511 14512 assert ((t == NULL_TREE) || (DECL_CONTEXT (x) == NULL_TREE)); 14513 14514 /* Don't push non-parms onto list for parms until we understand 14515 why we're doing this and whether it works. */ 14516 14517 assert ((b == global_binding_level) 14518 || !ffecom_transform_only_dummies_ 14519 || TREE_CODE (x) == PARM_DECL); 14520 14521 if ((t != NULL_TREE) && duplicate_decls (x, t)) 14522 return t; 14523 14524 /* If we are processing a typedef statement, generate a whole new 14525 ..._TYPE node (which will be just an variant of the existing 14526 ..._TYPE node with identical properties) and then install the 14527 TYPE_DECL node generated to represent the typedef name as the 14528 TYPE_NAME of this brand new (duplicate) ..._TYPE node. 14529 14530 The whole point here is to end up with a situation where each and every 14531 ..._TYPE node the compiler creates will be uniquely associated with 14532 AT MOST one node representing a typedef name. This way, even though 14533 the compiler substitutes corresponding ..._TYPE nodes for TYPE_DECL 14534 (i.e. "typedef name") nodes very early on, later parts of the 14535 compiler can always do the reverse translation and get back the 14536 corresponding typedef name. For example, given: 14537 14538 typedef struct S MY_TYPE; MY_TYPE object; 14539 14540 Later parts of the compiler might only know that `object' was of type 14541 `struct S' if it were not for code just below. With this code 14542 however, later parts of the compiler see something like: 14543 14544 struct S' == struct S typedef struct S' MY_TYPE; struct S' object; 14545 14546 And they can then deduce (from the node for type struct S') that the 14547 original object declaration was: 14548 14549 MY_TYPE object; 14550 14551 Being able to do this is important for proper support of protoize, and 14552 also for generating precise symbolic debugging information which 14553 takes full account of the programmer's (typedef) vocabulary. 14554 14555 Obviously, we don't want to generate a duplicate ..._TYPE node if the 14556 TYPE_DECL node that we are now processing really represents a 14557 standard built-in type. 14558 14559 Since all standard types are effectively declared at line zero in the 14560 source file, we can easily check to see if we are working on a 14561 standard type by checking the current value of lineno. */ 14562 14563 if (TREE_CODE (x) == TYPE_DECL) 14564 { 14565 if (DECL_SOURCE_LINE (x) == 0) 14566 { 14567 if (TYPE_NAME (TREE_TYPE (x)) == 0) 14568 TYPE_NAME (TREE_TYPE (x)) = x; 14569 } 14570 else if (TREE_TYPE (x) != error_mark_node) 14571 { 14572 tree tt = TREE_TYPE (x); 14573 14574 tt = build_type_copy (tt); 14575 TYPE_NAME (tt) = x; 14576 TREE_TYPE (x) = tt; 14577 } 14578 } 14579 14580 /* This name is new in its binding level. Install the new declaration 14581 and return it. */ 14582 if (b == global_binding_level) 14583 IDENTIFIER_GLOBAL_VALUE (name) = x; 14584 else 14585 IDENTIFIER_LOCAL_VALUE (name) = x; 14586 } 14587 14588 /* Put decls on list in reverse order. We will reverse them later if 14589 necessary. */ 14590 TREE_CHAIN (x) = b->names; 14591 b->names = x; 14592 14593 return x; 14594 } 14595 14596 /* Nonzero if the current level needs to have a BLOCK made. */ 14597 14598 static int 14599 kept_level_p () 14600 { 14601 tree decl; 14602 14603 for (decl = current_binding_level->names; 14604 decl; 14605 decl = TREE_CHAIN (decl)) 14606 { 14607 if (TREE_USED (decl) || TREE_CODE (decl) != VAR_DECL 14608 || (DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl))) 14609 /* Currently, there aren't supposed to be non-artificial names 14610 at other than the top block for a function -- they're 14611 believed to always be temps. But it's wise to check anyway. */ 14612 return 1; 14613 } 14614 return 0; 14615 } 14616 14617 /* Enter a new binding level. 14618 If TAG_TRANSPARENT is nonzero, do so only for the name space of variables, 14619 not for that of tags. */ 14620 14621 void 14622 pushlevel (tag_transparent) 14623 int tag_transparent; 14624 { 14625 register struct f_binding_level *newlevel = NULL_BINDING_LEVEL; 14626 14627 assert (! tag_transparent); 14628 14629 if (current_binding_level == global_binding_level) 14630 { 14631 named_labels = 0; 14632 } 14633 14634 /* Reuse or create a struct for this binding level. */ 14635 14636 if (free_binding_level) 14637 { 14638 newlevel = free_binding_level; 14639 free_binding_level = free_binding_level->level_chain; 14640 } 14641 else 14642 { 14643 newlevel = make_binding_level (); 14644 } 14645 14646 /* Add this level to the front of the chain (stack) of levels that 14647 are active. */ 14648 14649 *newlevel = clear_binding_level; 14650 newlevel->level_chain = current_binding_level; 14651 current_binding_level = newlevel; 14652 } 14653 14654 /* Set the BLOCK node for the innermost scope 14655 (the one we are currently in). */ 14656 14657 void 14658 set_block (block) 14659 register tree block; 14660 { 14661 current_binding_level->this_block = block; 14662 current_binding_level->names = chainon (current_binding_level->names, 14663 BLOCK_VARS (block)); 14664 current_binding_level->blocks = chainon (current_binding_level->blocks, 14665 BLOCK_SUBBLOCKS (block)); 14666 } 14667 14668 static tree 14669 ffe_signed_or_unsigned_type (unsignedp, type) 14670 int unsignedp; 14671 tree type; 14672 { 14673 tree type2; 14674 14675 if (! INTEGRAL_TYPE_P (type)) 14676 return type; 14677 if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node)) 14678 return unsignedp ? unsigned_char_type_node : signed_char_type_node; 14679 if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)) 14680 return unsignedp ? unsigned_type_node : integer_type_node; 14681 if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node)) 14682 return unsignedp ? short_unsigned_type_node : short_integer_type_node; 14683 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node)) 14684 return unsignedp ? long_unsigned_type_node : long_integer_type_node; 14685 if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node)) 14686 return (unsignedp ? long_long_unsigned_type_node 14687 : long_long_integer_type_node); 14688 14689 type2 = ffe_type_for_size (TYPE_PRECISION (type), unsignedp); 14690 if (type2 == NULL_TREE) 14691 return type; 14692 14693 return type2; 14694 } 14695 14696 static tree 14697 ffe_signed_type (type) 14698 tree type; 14699 { 14700 tree type1 = TYPE_MAIN_VARIANT (type); 14701 ffeinfoKindtype kt; 14702 tree type2; 14703 14704 if (type1 == unsigned_char_type_node || type1 == char_type_node) 14705 return signed_char_type_node; 14706 if (type1 == unsigned_type_node) 14707 return integer_type_node; 14708 if (type1 == short_unsigned_type_node) 14709 return short_integer_type_node; 14710 if (type1 == long_unsigned_type_node) 14711 return long_integer_type_node; 14712 if (type1 == long_long_unsigned_type_node) 14713 return long_long_integer_type_node; 14714 #if 0 /* gcc/c-* files only */ 14715 if (type1 == unsigned_intDI_type_node) 14716 return intDI_type_node; 14717 if (type1 == unsigned_intSI_type_node) 14718 return intSI_type_node; 14719 if (type1 == unsigned_intHI_type_node) 14720 return intHI_type_node; 14721 if (type1 == unsigned_intQI_type_node) 14722 return intQI_type_node; 14723 #endif 14724 14725 type2 = ffe_type_for_size (TYPE_PRECISION (type1), 0); 14726 if (type2 != NULL_TREE) 14727 return type2; 14728 14729 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt) 14730 { 14731 type2 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt]; 14732 14733 if (type1 == type2) 14734 return ffecom_tree_type[FFEINFO_basictypeINTEGER][kt]; 14735 } 14736 14737 return type; 14738 } 14739 14740 /* Prepare expr to be an argument of a TRUTH_NOT_EXPR, 14741 or validate its data type for an `if' or `while' statement or ?..: exp. 14742 14743 This preparation consists of taking the ordinary 14744 representation of an expression expr and producing a valid tree 14745 boolean expression describing whether expr is nonzero. We could 14746 simply always do build_binary_op (NE_EXPR, expr, integer_zero_node, 1), 14747 but we optimize comparisons, &&, ||, and !. 14748 14749 The resulting type should always be `integer_type_node'. */ 14750 14751 static tree 14752 ffe_truthvalue_conversion (expr) 14753 tree expr; 14754 { 14755 if (TREE_CODE (expr) == ERROR_MARK) 14756 return expr; 14757 14758 #if 0 /* This appears to be wrong for C++. */ 14759 /* These really should return error_mark_node after 2.4 is stable. 14760 But not all callers handle ERROR_MARK properly. */ 14761 switch (TREE_CODE (TREE_TYPE (expr))) 14762 { 14763 case RECORD_TYPE: 14764 error ("struct type value used where scalar is required"); 14765 return integer_zero_node; 14766 14767 case UNION_TYPE: 14768 error ("union type value used where scalar is required"); 14769 return integer_zero_node; 14770 14771 case ARRAY_TYPE: 14772 error ("array type value used where scalar is required"); 14773 return integer_zero_node; 14774 14775 default: 14776 break; 14777 } 14778 #endif /* 0 */ 14779 14780 switch (TREE_CODE (expr)) 14781 { 14782 /* It is simpler and generates better code to have only TRUTH_*_EXPR 14783 or comparison expressions as truth values at this level. */ 14784 #if 0 14785 case COMPONENT_REF: 14786 /* A one-bit unsigned bit-field is already acceptable. */ 14787 if (1 == TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (expr, 1))) 14788 && TREE_UNSIGNED (TREE_OPERAND (expr, 1))) 14789 return expr; 14790 break; 14791 #endif 14792 14793 case EQ_EXPR: 14794 /* It is simpler and generates better code to have only TRUTH_*_EXPR 14795 or comparison expressions as truth values at this level. */ 14796 #if 0 14797 if (integer_zerop (TREE_OPERAND (expr, 1))) 14798 return build_unary_op (TRUTH_NOT_EXPR, TREE_OPERAND (expr, 0), 0); 14799 #endif 14800 case NE_EXPR: case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR: 14801 case TRUTH_ANDIF_EXPR: 14802 case TRUTH_ORIF_EXPR: 14803 case TRUTH_AND_EXPR: 14804 case TRUTH_OR_EXPR: 14805 case TRUTH_XOR_EXPR: 14806 TREE_TYPE (expr) = integer_type_node; 14807 return expr; 14808 14809 case ERROR_MARK: 14810 return expr; 14811 14812 case INTEGER_CST: 14813 return integer_zerop (expr) ? integer_zero_node : integer_one_node; 14814 14815 case REAL_CST: 14816 return real_zerop (expr) ? integer_zero_node : integer_one_node; 14817 14818 case ADDR_EXPR: 14819 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0))) 14820 return build (COMPOUND_EXPR, integer_type_node, 14821 TREE_OPERAND (expr, 0), integer_one_node); 14822 else 14823 return integer_one_node; 14824 14825 case COMPLEX_EXPR: 14826 return ffecom_2 ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)) 14827 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR), 14828 integer_type_node, 14829 ffe_truthvalue_conversion (TREE_OPERAND (expr, 0)), 14830 ffe_truthvalue_conversion (TREE_OPERAND (expr, 1))); 14831 14832 case NEGATE_EXPR: 14833 case ABS_EXPR: 14834 case FLOAT_EXPR: 14835 case FFS_EXPR: 14836 /* These don't change whether an object is nonzero or zero. */ 14837 return ffe_truthvalue_conversion (TREE_OPERAND (expr, 0)); 14838 14839 case LROTATE_EXPR: 14840 case RROTATE_EXPR: 14841 /* These don't change whether an object is zero or nonzero, but 14842 we can't ignore them if their second arg has side-effects. */ 14843 if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))) 14844 return build (COMPOUND_EXPR, integer_type_node, TREE_OPERAND (expr, 1), 14845 ffe_truthvalue_conversion (TREE_OPERAND (expr, 0))); 14846 else 14847 return ffe_truthvalue_conversion (TREE_OPERAND (expr, 0)); 14848 14849 case COND_EXPR: 14850 { 14851 /* Distribute the conversion into the arms of a COND_EXPR. */ 14852 tree arg1 = TREE_OPERAND (expr, 1); 14853 tree arg2 = TREE_OPERAND (expr, 2); 14854 if (! VOID_TYPE_P (TREE_TYPE (arg1))) 14855 arg1 = ffe_truthvalue_conversion (arg1); 14856 if (! VOID_TYPE_P (TREE_TYPE (arg2))) 14857 arg2 = ffe_truthvalue_conversion (arg2); 14858 return fold (build (COND_EXPR, integer_type_node, 14859 TREE_OPERAND (expr, 0), arg1, arg2)); 14860 } 14861 14862 case CONVERT_EXPR: 14863 /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE, 14864 since that affects how `default_conversion' will behave. */ 14865 if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE 14866 || TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE) 14867 break; 14868 /* fall through... */ 14869 case NOP_EXPR: 14870 /* If this is widening the argument, we can ignore it. */ 14871 if (TYPE_PRECISION (TREE_TYPE (expr)) 14872 >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0)))) 14873 return ffe_truthvalue_conversion (TREE_OPERAND (expr, 0)); 14874 break; 14875 14876 case MINUS_EXPR: 14877 /* With IEEE arithmetic, x - x may not equal 0, so we can't optimize 14878 this case. */ 14879 if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT 14880 && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE) 14881 break; 14882 /* fall through... */ 14883 case BIT_XOR_EXPR: 14884 /* This and MINUS_EXPR can be changed into a comparison of the 14885 two objects. */ 14886 if (TREE_TYPE (TREE_OPERAND (expr, 0)) 14887 == TREE_TYPE (TREE_OPERAND (expr, 1))) 14888 return ffecom_2 (NE_EXPR, integer_type_node, 14889 TREE_OPERAND (expr, 0), 14890 TREE_OPERAND (expr, 1)); 14891 return ffecom_2 (NE_EXPR, integer_type_node, 14892 TREE_OPERAND (expr, 0), 14893 fold (build1 (NOP_EXPR, 14894 TREE_TYPE (TREE_OPERAND (expr, 0)), 14895 TREE_OPERAND (expr, 1)))); 14896 14897 case BIT_AND_EXPR: 14898 if (integer_onep (TREE_OPERAND (expr, 1))) 14899 return expr; 14900 break; 14901 14902 case MODIFY_EXPR: 14903 #if 0 /* No such thing in Fortran. */ 14904 if (warn_parentheses && C_EXP_ORIGINAL_CODE (expr) == MODIFY_EXPR) 14905 warning ("suggest parentheses around assignment used as truth value"); 14906 #endif 14907 break; 14908 14909 default: 14910 break; 14911 } 14912 14913 if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE) 14914 return (ffecom_2 14915 ((TREE_SIDE_EFFECTS (expr) 14916 ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR), 14917 integer_type_node, 14918 ffe_truthvalue_conversion (ffecom_1 (REALPART_EXPR, 14919 TREE_TYPE (TREE_TYPE (expr)), 14920 expr)), 14921 ffe_truthvalue_conversion (ffecom_1 (IMAGPART_EXPR, 14922 TREE_TYPE (TREE_TYPE (expr)), 14923 expr)))); 14924 14925 return ffecom_2 (NE_EXPR, integer_type_node, 14926 expr, 14927 convert (TREE_TYPE (expr), integer_zero_node)); 14928 } 14929 14930 static tree 14931 ffe_type_for_mode (mode, unsignedp) 14932 enum machine_mode mode; 14933 int unsignedp; 14934 { 14935 int i; 14936 int j; 14937 tree t; 14938 14939 if (mode == TYPE_MODE (integer_type_node)) 14940 return unsignedp ? unsigned_type_node : integer_type_node; 14941 14942 if (mode == TYPE_MODE (signed_char_type_node)) 14943 return unsignedp ? unsigned_char_type_node : signed_char_type_node; 14944 14945 if (mode == TYPE_MODE (short_integer_type_node)) 14946 return unsignedp ? short_unsigned_type_node : short_integer_type_node; 14947 14948 if (mode == TYPE_MODE (long_integer_type_node)) 14949 return unsignedp ? long_unsigned_type_node : long_integer_type_node; 14950 14951 if (mode == TYPE_MODE (long_long_integer_type_node)) 14952 return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node; 14953 14954 #if HOST_BITS_PER_WIDE_INT >= 64 14955 if (mode == TYPE_MODE (intTI_type_node)) 14956 return unsignedp ? unsigned_intTI_type_node : intTI_type_node; 14957 #endif 14958 14959 if (mode == TYPE_MODE (float_type_node)) 14960 return float_type_node; 14961 14962 if (mode == TYPE_MODE (double_type_node)) 14963 return double_type_node; 14964 14965 if (mode == TYPE_MODE (long_double_type_node)) 14966 return long_double_type_node; 14967 14968 if (mode == TYPE_MODE (build_pointer_type (char_type_node))) 14969 return build_pointer_type (char_type_node); 14970 14971 if (mode == TYPE_MODE (build_pointer_type (integer_type_node))) 14972 return build_pointer_type (integer_type_node); 14973 14974 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i) 14975 for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j) 14976 { 14977 if (((t = ffecom_tree_type[i][j]) != NULL_TREE) 14978 && (mode == TYPE_MODE (t))) 14979 { 14980 if ((i == FFEINFO_basictypeINTEGER) && unsignedp) 14981 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][j]; 14982 else 14983 return t; 14984 } 14985 } 14986 14987 return 0; 14988 } 14989 14990 static tree 14991 ffe_type_for_size (bits, unsignedp) 14992 unsigned bits; 14993 int unsignedp; 14994 { 14995 ffeinfoKindtype kt; 14996 tree type_node; 14997 14998 if (bits == TYPE_PRECISION (integer_type_node)) 14999 return unsignedp ? unsigned_type_node : integer_type_node; 15000 15001 if (bits == TYPE_PRECISION (signed_char_type_node)) 15002 return unsignedp ? unsigned_char_type_node : signed_char_type_node; 15003 15004 if (bits == TYPE_PRECISION (short_integer_type_node)) 15005 return unsignedp ? short_unsigned_type_node : short_integer_type_node; 15006 15007 if (bits == TYPE_PRECISION (long_integer_type_node)) 15008 return unsignedp ? long_unsigned_type_node : long_integer_type_node; 15009 15010 if (bits == TYPE_PRECISION (long_long_integer_type_node)) 15011 return (unsignedp ? long_long_unsigned_type_node 15012 : long_long_integer_type_node); 15013 15014 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt) 15015 { 15016 type_node = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt]; 15017 15018 if ((type_node != NULL_TREE) && (bits == TYPE_PRECISION (type_node))) 15019 return unsignedp ? ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt] 15020 : type_node; 15021 } 15022 15023 return 0; 15024 } 15025 15026 static tree 15027 ffe_unsigned_type (type) 15028 tree type; 15029 { 15030 tree type1 = TYPE_MAIN_VARIANT (type); 15031 ffeinfoKindtype kt; 15032 tree type2; 15033 15034 if (type1 == signed_char_type_node || type1 == char_type_node) 15035 return unsigned_char_type_node; 15036 if (type1 == integer_type_node) 15037 return unsigned_type_node; 15038 if (type1 == short_integer_type_node) 15039 return short_unsigned_type_node; 15040 if (type1 == long_integer_type_node) 15041 return long_unsigned_type_node; 15042 if (type1 == long_long_integer_type_node) 15043 return long_long_unsigned_type_node; 15044 #if 0 /* gcc/c-* files only */ 15045 if (type1 == intDI_type_node) 15046 return unsigned_intDI_type_node; 15047 if (type1 == intSI_type_node) 15048 return unsigned_intSI_type_node; 15049 if (type1 == intHI_type_node) 15050 return unsigned_intHI_type_node; 15051 if (type1 == intQI_type_node) 15052 return unsigned_intQI_type_node; 15053 #endif 15054 15055 type2 = ffe_type_for_size (TYPE_PRECISION (type1), 1); 15056 if (type2 != NULL_TREE) 15057 return type2; 15058 15059 for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt) 15060 { 15061 type2 = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt]; 15062 15063 if (type1 == type2) 15064 return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt]; 15065 } 15066 15067 return type; 15068 } 15069 15070 /* From gcc/cccp.c, the code to handle -I. */ 15071 15072 /* Skip leading "./" from a directory name. 15073 This may yield the empty string, which represents the current directory. */ 15074 15075 static const char * 15076 skip_redundant_dir_prefix (const char *dir) 15077 { 15078 while (dir[0] == '.' && dir[1] == '/') 15079 for (dir += 2; *dir == '/'; dir++) 15080 continue; 15081 if (dir[0] == '.' && !dir[1]) 15082 dir++; 15083 return dir; 15084 } 15085 15086 /* The file_name_map structure holds a mapping of file names for a 15087 particular directory. This mapping is read from the file named 15088 FILE_NAME_MAP_FILE in that directory. Such a file can be used to 15089 map filenames on a file system with severe filename restrictions, 15090 such as DOS. The format of the file name map file is just a series 15091 of lines with two tokens on each line. The first token is the name 15092 to map, and the second token is the actual name to use. */ 15093 15094 struct file_name_map 15095 { 15096 struct file_name_map *map_next; 15097 char *map_from; 15098 char *map_to; 15099 }; 15100 15101 #define FILE_NAME_MAP_FILE "header.gcc" 15102 15103 /* Current maximum length of directory names in the search path 15104 for include files. (Altered as we get more of them.) */ 15105 15106 static int max_include_len = 0; 15107 15108 struct file_name_list 15109 { 15110 struct file_name_list *next; 15111 char *fname; 15112 /* Mapping of file names for this directory. */ 15113 struct file_name_map *name_map; 15114 /* Nonzero if name_map is valid. */ 15115 int got_name_map; 15116 }; 15117 15118 static struct file_name_list *include = NULL; /* First dir to search */ 15119 static struct file_name_list *last_include = NULL; /* Last in chain */ 15120 15121 /* I/O buffer structure. 15122 The `fname' field is nonzero for source files and #include files 15123 and for the dummy text used for -D and -U. 15124 It is zero for rescanning results of macro expansion 15125 and for expanding macro arguments. */ 15126 #define INPUT_STACK_MAX 400 15127 static struct file_buf { 15128 const char *fname; 15129 /* Filename specified with #line command. */ 15130 const char *nominal_fname; 15131 /* Record where in the search path this file was found. 15132 For #include_next. */ 15133 struct file_name_list *dir; 15134 ffewhereLine line; 15135 ffewhereColumn column; 15136 } instack[INPUT_STACK_MAX]; 15137 15138 static int last_error_tick = 0; /* Incremented each time we print it. */ 15139 static int input_file_stack_tick = 0; /* Incremented when status changes. */ 15140 15141 /* Current nesting level of input sources. 15142 `instack[indepth]' is the level currently being read. */ 15143 static int indepth = -1; 15144 15145 typedef struct file_buf FILE_BUF; 15146 15147 /* Nonzero means -I- has been seen, 15148 so don't look for #include "foo" the source-file directory. */ 15149 static int ignore_srcdir; 15150 15151 #ifndef INCLUDE_LEN_FUDGE 15152 #define INCLUDE_LEN_FUDGE 0 15153 #endif 15154 15155 static void append_include_chain (struct file_name_list *first, 15156 struct file_name_list *last); 15157 static FILE *open_include_file (char *filename, 15158 struct file_name_list *searchptr); 15159 static void print_containing_files (ffebadSeverity sev); 15160 static char *read_filename_string (int ch, FILE *f); 15161 static struct file_name_map *read_name_map (const char *dirname); 15162 15163 /* Append a chain of `struct file_name_list's 15164 to the end of the main include chain. 15165 FIRST is the beginning of the chain to append, and LAST is the end. */ 15166 15167 static void 15168 append_include_chain (first, last) 15169 struct file_name_list *first, *last; 15170 { 15171 struct file_name_list *dir; 15172 15173 if (!first || !last) 15174 return; 15175 15176 if (include == 0) 15177 include = first; 15178 else 15179 last_include->next = first; 15180 15181 for (dir = first; ; dir = dir->next) { 15182 int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE; 15183 if (len > max_include_len) 15184 max_include_len = len; 15185 if (dir == last) 15186 break; 15187 } 15188 15189 last->next = NULL; 15190 last_include = last; 15191 } 15192 15193 /* Try to open include file FILENAME. SEARCHPTR is the directory 15194 being tried from the include file search path. This function maps 15195 filenames on file systems based on information read by 15196 read_name_map. */ 15197 15198 static FILE * 15199 open_include_file (filename, searchptr) 15200 char *filename; 15201 struct file_name_list *searchptr; 15202 { 15203 register struct file_name_map *map; 15204 register char *from; 15205 char *p, *dir; 15206 15207 if (searchptr && ! searchptr->got_name_map) 15208 { 15209 searchptr->name_map = read_name_map (searchptr->fname 15210 ? searchptr->fname : "."); 15211 searchptr->got_name_map = 1; 15212 } 15213 15214 /* First check the mapping for the directory we are using. */ 15215 if (searchptr && searchptr->name_map) 15216 { 15217 from = filename; 15218 if (searchptr->fname) 15219 from += strlen (searchptr->fname) + 1; 15220 for (map = searchptr->name_map; map; map = map->map_next) 15221 { 15222 if (! strcmp (map->map_from, from)) 15223 { 15224 /* Found a match. */ 15225 return fopen (map->map_to, "r"); 15226 } 15227 } 15228 } 15229 15230 /* Try to find a mapping file for the particular directory we are 15231 looking in. Thus #include <sys/types.h> will look up sys/types.h 15232 in /usr/include/header.gcc and look up types.h in 15233 /usr/include/sys/header.gcc. */ 15234 p = strrchr (filename, '/'); 15235 #ifdef DIR_SEPARATOR 15236 if (! p) p = strrchr (filename, DIR_SEPARATOR); 15237 else { 15238 char *tmp = strrchr (filename, DIR_SEPARATOR); 15239 if (tmp != NULL && tmp > p) p = tmp; 15240 } 15241 #endif 15242 if (! p) 15243 p = filename; 15244 if (searchptr 15245 && searchptr->fname 15246 && strlen (searchptr->fname) == (size_t) (p - filename) 15247 && ! strncmp (searchptr->fname, filename, (int) (p - filename))) 15248 { 15249 /* FILENAME is in SEARCHPTR, which we've already checked. */ 15250 return fopen (filename, "r"); 15251 } 15252 15253 if (p == filename) 15254 { 15255 from = filename; 15256 map = read_name_map ("."); 15257 } 15258 else 15259 { 15260 dir = (char *) xmalloc (p - filename + 1); 15261 memcpy (dir, filename, p - filename); 15262 dir[p - filename] = '\0'; 15263 from = p + 1; 15264 map = read_name_map (dir); 15265 free (dir); 15266 } 15267 for (; map; map = map->map_next) 15268 if (! strcmp (map->map_from, from)) 15269 return fopen (map->map_to, "r"); 15270 15271 return fopen (filename, "r"); 15272 } 15273 15274 /* Print the file names and line numbers of the #include 15275 commands which led to the current file. */ 15276 15277 static void 15278 print_containing_files (ffebadSeverity sev) 15279 { 15280 FILE_BUF *ip = NULL; 15281 int i; 15282 int first = 1; 15283 const char *str1; 15284 const char *str2; 15285 15286 /* If stack of files hasn't changed since we last printed 15287 this info, don't repeat it. */ 15288 if (last_error_tick == input_file_stack_tick) 15289 return; 15290 15291 for (i = indepth; i >= 0; i--) 15292 if (instack[i].fname != NULL) { 15293 ip = &instack[i]; 15294 break; 15295 } 15296 15297 /* Give up if we don't find a source file. */ 15298 if (ip == NULL) 15299 return; 15300 15301 /* Find the other, outer source files. */ 15302 for (i--; i >= 0; i--) 15303 if (instack[i].fname != NULL) 15304 { 15305 ip = &instack[i]; 15306 if (first) 15307 { 15308 first = 0; 15309 str1 = "In file included"; 15310 } 15311 else 15312 { 15313 str1 = "... ..."; 15314 } 15315 15316 if (i == 1) 15317 str2 = ":"; 15318 else 15319 str2 = ""; 15320 15321 /* xgettext:no-c-format */ 15322 ffebad_start_msg ("%A from %B at %0%C", sev); 15323 ffebad_here (0, ip->line, ip->column); 15324 ffebad_string (str1); 15325 ffebad_string (ip->nominal_fname); 15326 ffebad_string (str2); 15327 ffebad_finish (); 15328 } 15329 15330 /* Record we have printed the status as of this time. */ 15331 last_error_tick = input_file_stack_tick; 15332 } 15333 15334 /* Read a space delimited string of unlimited length from a stdio 15335 file. */ 15336 15337 static char * 15338 read_filename_string (ch, f) 15339 int ch; 15340 FILE *f; 15341 { 15342 char *alloc, *set; 15343 int len; 15344 15345 len = 20; 15346 set = alloc = xmalloc (len + 1); 15347 if (! ISSPACE (ch)) 15348 { 15349 *set++ = ch; 15350 while ((ch = getc (f)) != EOF && ! ISSPACE (ch)) 15351 { 15352 if (set - alloc == len) 15353 { 15354 len *= 2; 15355 alloc = xrealloc (alloc, len + 1); 15356 set = alloc + len / 2; 15357 } 15358 *set++ = ch; 15359 } 15360 } 15361 *set = '\0'; 15362 ungetc (ch, f); 15363 return alloc; 15364 } 15365 15366 /* Read the file name map file for DIRNAME. */ 15367 15368 static struct file_name_map * 15369 read_name_map (dirname) 15370 const char *dirname; 15371 { 15372 /* This structure holds a linked list of file name maps, one per 15373 directory. */ 15374 struct file_name_map_list 15375 { 15376 struct file_name_map_list *map_list_next; 15377 char *map_list_name; 15378 struct file_name_map *map_list_map; 15379 }; 15380 static struct file_name_map_list *map_list; 15381 register struct file_name_map_list *map_list_ptr; 15382 char *name; 15383 FILE *f; 15384 size_t dirlen; 15385 int separator_needed; 15386 15387 dirname = skip_redundant_dir_prefix (dirname); 15388 15389 for (map_list_ptr = map_list; map_list_ptr; 15390 map_list_ptr = map_list_ptr->map_list_next) 15391 if (! strcmp (map_list_ptr->map_list_name, dirname)) 15392 return map_list_ptr->map_list_map; 15393 15394 map_list_ptr = ((struct file_name_map_list *) 15395 xmalloc (sizeof (struct file_name_map_list))); 15396 map_list_ptr->map_list_name = xstrdup (dirname); 15397 map_list_ptr->map_list_map = NULL; 15398 15399 dirlen = strlen (dirname); 15400 separator_needed = dirlen != 0 && dirname[dirlen - 1] != '/'; 15401 if (separator_needed) 15402 name = concat (dirname, "/", FILE_NAME_MAP_FILE, NULL); 15403 else 15404 name = concat (dirname, FILE_NAME_MAP_FILE, NULL); 15405 f = fopen (name, "r"); 15406 free (name); 15407 if (!f) 15408 map_list_ptr->map_list_map = NULL; 15409 else 15410 { 15411 int ch; 15412 15413 while ((ch = getc (f)) != EOF) 15414 { 15415 char *from, *to; 15416 struct file_name_map *ptr; 15417 15418 if (ISSPACE (ch)) 15419 continue; 15420 from = read_filename_string (ch, f); 15421 while ((ch = getc (f)) != EOF && ISSPACE (ch) && ch != '\n') 15422 ; 15423 to = read_filename_string (ch, f); 15424 15425 ptr = ((struct file_name_map *) 15426 xmalloc (sizeof (struct file_name_map))); 15427 ptr->map_from = from; 15428 15429 /* Make the real filename absolute. */ 15430 if (*to == '/') 15431 ptr->map_to = to; 15432 else 15433 { 15434 if (separator_needed) 15435 ptr->map_to = concat (dirname, "/", to, NULL); 15436 else 15437 ptr->map_to = concat (dirname, to, NULL); 15438 free (to); 15439 } 15440 15441 ptr->map_next = map_list_ptr->map_list_map; 15442 map_list_ptr->map_list_map = ptr; 15443 15444 while ((ch = getc (f)) != '\n') 15445 if (ch == EOF) 15446 break; 15447 } 15448 fclose (f); 15449 } 15450 15451 map_list_ptr->map_list_next = map_list; 15452 map_list = map_list_ptr; 15453 15454 return map_list_ptr->map_list_map; 15455 } 15456 15457 static void 15458 ffecom_file_ (const char *name) 15459 { 15460 FILE_BUF *fp; 15461 15462 /* Do partial setup of input buffer for the sake of generating 15463 early #line directives (when -g is in effect). */ 15464 15465 fp = &instack[++indepth]; 15466 memset ((char *) fp, 0, sizeof (FILE_BUF)); 15467 if (name == NULL) 15468 name = ""; 15469 fp->nominal_fname = fp->fname = name; 15470 } 15471 15472 static void 15473 ffecom_close_include_ (FILE *f) 15474 { 15475 fclose (f); 15476 15477 indepth--; 15478 input_file_stack_tick++; 15479 15480 ffewhere_line_kill (instack[indepth].line); 15481 ffewhere_column_kill (instack[indepth].column); 15482 } 15483 15484 static int 15485 ffecom_decode_include_option_ (char *spec) 15486 { 15487 struct file_name_list *dirtmp; 15488 15489 if (! ignore_srcdir && !strcmp (spec, "-")) 15490 ignore_srcdir = 1; 15491 else 15492 { 15493 dirtmp = (struct file_name_list *) 15494 xmalloc (sizeof (struct file_name_list)); 15495 dirtmp->next = 0; /* New one goes on the end */ 15496 dirtmp->fname = spec; 15497 dirtmp->got_name_map = 0; 15498 if (spec[0] == 0) 15499 error ("directory name must immediately follow -I"); 15500 else 15501 append_include_chain (dirtmp, dirtmp); 15502 } 15503 return 1; 15504 } 15505 15506 /* Open INCLUDEd file. */ 15507 15508 static FILE * 15509 ffecom_open_include_ (char *name, ffewhereLine l, ffewhereColumn c) 15510 { 15511 char *fbeg = name; 15512 size_t flen = strlen (fbeg); 15513 struct file_name_list *search_start = include; /* Chain of dirs to search */ 15514 struct file_name_list dsp[1]; /* First in chain, if #include "..." */ 15515 struct file_name_list *searchptr = 0; 15516 char *fname; /* Dynamically allocated fname buffer */ 15517 FILE *f; 15518 FILE_BUF *fp; 15519 15520 if (flen == 0) 15521 return NULL; 15522 15523 dsp[0].fname = NULL; 15524 15525 /* If -I- was specified, don't search current dir, only spec'd ones. */ 15526 if (!ignore_srcdir) 15527 { 15528 for (fp = &instack[indepth]; fp >= instack; fp--) 15529 { 15530 int n; 15531 char *ep; 15532 const char *nam; 15533 15534 if ((nam = fp->nominal_fname) != NULL) 15535 { 15536 /* Found a named file. Figure out dir of the file, 15537 and put it in front of the search list. */ 15538 dsp[0].next = search_start; 15539 search_start = dsp; 15540 #ifndef VMS 15541 ep = strrchr (nam, '/'); 15542 #ifdef DIR_SEPARATOR 15543 if (ep == NULL) ep = strrchr (nam, DIR_SEPARATOR); 15544 else { 15545 char *tmp = strrchr (nam, DIR_SEPARATOR); 15546 if (tmp != NULL && tmp > ep) ep = tmp; 15547 } 15548 #endif 15549 #else /* VMS */ 15550 ep = strrchr (nam, ']'); 15551 if (ep == NULL) ep = strrchr (nam, '>'); 15552 if (ep == NULL) ep = strrchr (nam, ':'); 15553 if (ep != NULL) ep++; 15554 #endif /* VMS */ 15555 if (ep != NULL) 15556 { 15557 n = ep - nam; 15558 dsp[0].fname = (char *) xmalloc (n + 1); 15559 strncpy (dsp[0].fname, nam, n); 15560 dsp[0].fname[n] = '\0'; 15561 if (n + INCLUDE_LEN_FUDGE > max_include_len) 15562 max_include_len = n + INCLUDE_LEN_FUDGE; 15563 } 15564 else 15565 dsp[0].fname = NULL; /* Current directory */ 15566 dsp[0].got_name_map = 0; 15567 break; 15568 } 15569 } 15570 } 15571 15572 /* Allocate this permanently, because it gets stored in the definitions 15573 of macros. */ 15574 fname = xmalloc (max_include_len + flen + 4); 15575 /* + 2 above for slash and terminating null. */ 15576 /* + 2 added for '.h' on VMS (to support '#include filename') (NOT USED 15577 for g77 yet). */ 15578 15579 /* If specified file name is absolute, just open it. */ 15580 15581 if (*fbeg == '/' 15582 #ifdef DIR_SEPARATOR 15583 || *fbeg == DIR_SEPARATOR 15584 #endif 15585 ) 15586 { 15587 strncpy (fname, (char *) fbeg, flen); 15588 fname[flen] = 0; 15589 f = open_include_file (fname, NULL); 15590 } 15591 else 15592 { 15593 f = NULL; 15594 15595 /* Search directory path, trying to open the file. 15596 Copy each filename tried into FNAME. */ 15597 15598 for (searchptr = search_start; searchptr; searchptr = searchptr->next) 15599 { 15600 if (searchptr->fname) 15601 { 15602 /* The empty string in a search path is ignored. 15603 This makes it possible to turn off entirely 15604 a standard piece of the list. */ 15605 if (searchptr->fname[0] == 0) 15606 continue; 15607 strcpy (fname, skip_redundant_dir_prefix (searchptr->fname)); 15608 if (fname[0] && fname[strlen (fname) - 1] != '/') 15609 strcat (fname, "/"); 15610 fname[strlen (fname) + flen] = 0; 15611 } 15612 else 15613 fname[0] = 0; 15614 15615 strncat (fname, fbeg, flen); 15616 #ifdef VMS 15617 /* Change this 1/2 Unix 1/2 VMS file specification into a 15618 full VMS file specification */ 15619 if (searchptr->fname && (searchptr->fname[0] != 0)) 15620 { 15621 /* Fix up the filename */ 15622 hack_vms_include_specification (fname); 15623 } 15624 else 15625 { 15626 /* This is a normal VMS filespec, so use it unchanged. */ 15627 strncpy (fname, (char *) fbeg, flen); 15628 fname[flen] = 0; 15629 #if 0 /* Not for g77. */ 15630 /* if it's '#include filename', add the missing .h */ 15631 if (strchr (fname, '.') == NULL) 15632 strcat (fname, ".h"); 15633 #endif 15634 } 15635 #endif /* VMS */ 15636 f = open_include_file (fname, searchptr); 15637 #ifdef EACCES 15638 if (f == NULL && errno == EACCES) 15639 { 15640 print_containing_files (FFEBAD_severityWARNING); 15641 /* xgettext:no-c-format */ 15642 ffebad_start_msg ("At %0, INCLUDE file %A exists, but is not readable", 15643 FFEBAD_severityWARNING); 15644 ffebad_string (fname); 15645 ffebad_here (0, l, c); 15646 ffebad_finish (); 15647 } 15648 #endif 15649 if (f != NULL) 15650 break; 15651 } 15652 } 15653 15654 if (f == NULL) 15655 { 15656 /* A file that was not found. */ 15657 15658 strncpy (fname, (char *) fbeg, flen); 15659 fname[flen] = 0; 15660 print_containing_files (ffebad_severity (FFEBAD_OPEN_INCLUDE)); 15661 ffebad_start (FFEBAD_OPEN_INCLUDE); 15662 ffebad_here (0, l, c); 15663 ffebad_string (fname); 15664 ffebad_finish (); 15665 } 15666 15667 if (dsp[0].fname != NULL) 15668 free (dsp[0].fname); 15669 15670 if (f == NULL) 15671 return NULL; 15672 15673 if (indepth >= (INPUT_STACK_MAX - 1)) 15674 { 15675 print_containing_files (FFEBAD_severityFATAL); 15676 /* xgettext:no-c-format */ 15677 ffebad_start_msg ("At %0, INCLUDE nesting too deep", 15678 FFEBAD_severityFATAL); 15679 ffebad_string (fname); 15680 ffebad_here (0, l, c); 15681 ffebad_finish (); 15682 return NULL; 15683 } 15684 15685 instack[indepth].line = ffewhere_line_use (l); 15686 instack[indepth].column = ffewhere_column_use (c); 15687 15688 fp = &instack[indepth + 1]; 15689 memset ((char *) fp, 0, sizeof (FILE_BUF)); 15690 fp->nominal_fname = fp->fname = fname; 15691 fp->dir = searchptr; 15692 15693 indepth++; 15694 input_file_stack_tick++; 15695 15696 return f; 15697 } 15698 15699 /**INDENT* (Do not reformat this comment even with -fca option.) 15700 Data-gathering files: Given the source file listed below, compiled with 15701 f2c I obtained the output file listed after that, and from the output 15702 file I derived the above code. 15703 15704 -------- (begin input file to f2c) 15705 implicit none 15706 character*10 A1,A2 15707 complex C1,C2 15708 integer I1,I2 15709 real R1,R2 15710 double precision D1,D2 15711 C 15712 call getem(A1,A2,C1,C2,I1,I2,R1,R2,D1,D2) 15713 c / 15714 call fooI(I1/I2) 15715 call fooR(R1/I1) 15716 call fooD(D1/I1) 15717 call fooC(C1/I1) 15718 call fooR(R1/R2) 15719 call fooD(R1/D1) 15720 call fooD(D1/D2) 15721 call fooD(D1/R1) 15722 call fooC(C1/C2) 15723 call fooC(C1/R1) 15724 call fooZ(C1/D1) 15725 c ** 15726 call fooI(I1**I2) 15727 call fooR(R1**I1) 15728 call fooD(D1**I1) 15729 call fooC(C1**I1) 15730 call fooR(R1**R2) 15731 call fooD(R1**D1) 15732 call fooD(D1**D2) 15733 call fooD(D1**R1) 15734 call fooC(C1**C2) 15735 call fooC(C1**R1) 15736 call fooZ(C1**D1) 15737 c FFEINTRIN_impABS 15738 call fooR(ABS(R1)) 15739 c FFEINTRIN_impACOS 15740 call fooR(ACOS(R1)) 15741 c FFEINTRIN_impAIMAG 15742 call fooR(AIMAG(C1)) 15743 c FFEINTRIN_impAINT 15744 call fooR(AINT(R1)) 15745 c FFEINTRIN_impALOG 15746 call fooR(ALOG(R1)) 15747 c FFEINTRIN_impALOG10 15748 call fooR(ALOG10(R1)) 15749 c FFEINTRIN_impAMAX0 15750 call fooR(AMAX0(I1,I2)) 15751 c FFEINTRIN_impAMAX1 15752 call fooR(AMAX1(R1,R2)) 15753 c FFEINTRIN_impAMIN0 15754 call fooR(AMIN0(I1,I2)) 15755 c FFEINTRIN_impAMIN1 15756 call fooR(AMIN1(R1,R2)) 15757 c FFEINTRIN_impAMOD 15758 call fooR(AMOD(R1,R2)) 15759 c FFEINTRIN_impANINT 15760 call fooR(ANINT(R1)) 15761 c FFEINTRIN_impASIN 15762 call fooR(ASIN(R1)) 15763 c FFEINTRIN_impATAN 15764 call fooR(ATAN(R1)) 15765 c FFEINTRIN_impATAN2 15766 call fooR(ATAN2(R1,R2)) 15767 c FFEINTRIN_impCABS 15768 call fooR(CABS(C1)) 15769 c FFEINTRIN_impCCOS 15770 call fooC(CCOS(C1)) 15771 c FFEINTRIN_impCEXP 15772 call fooC(CEXP(C1)) 15773 c FFEINTRIN_impCHAR 15774 call fooA(CHAR(I1)) 15775 c FFEINTRIN_impCLOG 15776 call fooC(CLOG(C1)) 15777 c FFEINTRIN_impCONJG 15778 call fooC(CONJG(C1)) 15779 c FFEINTRIN_impCOS 15780 call fooR(COS(R1)) 15781 c FFEINTRIN_impCOSH 15782 call fooR(COSH(R1)) 15783 c FFEINTRIN_impCSIN 15784 call fooC(CSIN(C1)) 15785 c FFEINTRIN_impCSQRT 15786 call fooC(CSQRT(C1)) 15787 c FFEINTRIN_impDABS 15788 call fooD(DABS(D1)) 15789 c FFEINTRIN_impDACOS 15790 call fooD(DACOS(D1)) 15791 c FFEINTRIN_impDASIN 15792 call fooD(DASIN(D1)) 15793 c FFEINTRIN_impDATAN 15794 call fooD(DATAN(D1)) 15795 c FFEINTRIN_impDATAN2 15796 call fooD(DATAN2(D1,D2)) 15797 c FFEINTRIN_impDCOS 15798 call fooD(DCOS(D1)) 15799 c FFEINTRIN_impDCOSH 15800 call fooD(DCOSH(D1)) 15801 c FFEINTRIN_impDDIM 15802 call fooD(DDIM(D1,D2)) 15803 c FFEINTRIN_impDEXP 15804 call fooD(DEXP(D1)) 15805 c FFEINTRIN_impDIM 15806 call fooR(DIM(R1,R2)) 15807 c FFEINTRIN_impDINT 15808 call fooD(DINT(D1)) 15809 c FFEINTRIN_impDLOG 15810 call fooD(DLOG(D1)) 15811 c FFEINTRIN_impDLOG10 15812 call fooD(DLOG10(D1)) 15813 c FFEINTRIN_impDMAX1 15814 call fooD(DMAX1(D1,D2)) 15815 c FFEINTRIN_impDMIN1 15816 call fooD(DMIN1(D1,D2)) 15817 c FFEINTRIN_impDMOD 15818 call fooD(DMOD(D1,D2)) 15819 c FFEINTRIN_impDNINT 15820 call fooD(DNINT(D1)) 15821 c FFEINTRIN_impDPROD 15822 call fooD(DPROD(R1,R2)) 15823 c FFEINTRIN_impDSIGN 15824 call fooD(DSIGN(D1,D2)) 15825 c FFEINTRIN_impDSIN 15826 call fooD(DSIN(D1)) 15827 c FFEINTRIN_impDSINH 15828 call fooD(DSINH(D1)) 15829 c FFEINTRIN_impDSQRT 15830 call fooD(DSQRT(D1)) 15831 c FFEINTRIN_impDTAN 15832 call fooD(DTAN(D1)) 15833 c FFEINTRIN_impDTANH 15834 call fooD(DTANH(D1)) 15835 c FFEINTRIN_impEXP 15836 call fooR(EXP(R1)) 15837 c FFEINTRIN_impIABS 15838 call fooI(IABS(I1)) 15839 c FFEINTRIN_impICHAR 15840 call fooI(ICHAR(A1)) 15841 c FFEINTRIN_impIDIM 15842 call fooI(IDIM(I1,I2)) 15843 c FFEINTRIN_impIDNINT 15844 call fooI(IDNINT(D1)) 15845 c FFEINTRIN_impINDEX 15846 call fooI(INDEX(A1,A2)) 15847 c FFEINTRIN_impISIGN 15848 call fooI(ISIGN(I1,I2)) 15849 c FFEINTRIN_impLEN 15850 call fooI(LEN(A1)) 15851 c FFEINTRIN_impLGE 15852 call fooL(LGE(A1,A2)) 15853 c FFEINTRIN_impLGT 15854 call fooL(LGT(A1,A2)) 15855 c FFEINTRIN_impLLE 15856 call fooL(LLE(A1,A2)) 15857 c FFEINTRIN_impLLT 15858 call fooL(LLT(A1,A2)) 15859 c FFEINTRIN_impMAX0 15860 call fooI(MAX0(I1,I2)) 15861 c FFEINTRIN_impMAX1 15862 call fooI(MAX1(R1,R2)) 15863 c FFEINTRIN_impMIN0 15864 call fooI(MIN0(I1,I2)) 15865 c FFEINTRIN_impMIN1 15866 call fooI(MIN1(R1,R2)) 15867 c FFEINTRIN_impMOD 15868 call fooI(MOD(I1,I2)) 15869 c FFEINTRIN_impNINT 15870 call fooI(NINT(R1)) 15871 c FFEINTRIN_impSIGN 15872 call fooR(SIGN(R1,R2)) 15873 c FFEINTRIN_impSIN 15874 call fooR(SIN(R1)) 15875 c FFEINTRIN_impSINH 15876 call fooR(SINH(R1)) 15877 c FFEINTRIN_impSQRT 15878 call fooR(SQRT(R1)) 15879 c FFEINTRIN_impTAN 15880 call fooR(TAN(R1)) 15881 c FFEINTRIN_impTANH 15882 call fooR(TANH(R1)) 15883 c FFEINTRIN_imp_CMPLX_C 15884 call fooC(cmplx(C1,C2)) 15885 c FFEINTRIN_imp_CMPLX_D 15886 call fooZ(cmplx(D1,D2)) 15887 c FFEINTRIN_imp_CMPLX_I 15888 call fooC(cmplx(I1,I2)) 15889 c FFEINTRIN_imp_CMPLX_R 15890 call fooC(cmplx(R1,R2)) 15891 c FFEINTRIN_imp_DBLE_C 15892 call fooD(dble(C1)) 15893 c FFEINTRIN_imp_DBLE_D 15894 call fooD(dble(D1)) 15895 c FFEINTRIN_imp_DBLE_I 15896 call fooD(dble(I1)) 15897 c FFEINTRIN_imp_DBLE_R 15898 call fooD(dble(R1)) 15899 c FFEINTRIN_imp_INT_C 15900 call fooI(int(C1)) 15901 c FFEINTRIN_imp_INT_D 15902 call fooI(int(D1)) 15903 c FFEINTRIN_imp_INT_I 15904 call fooI(int(I1)) 15905 c FFEINTRIN_imp_INT_R 15906 call fooI(int(R1)) 15907 c FFEINTRIN_imp_REAL_C 15908 call fooR(real(C1)) 15909 c FFEINTRIN_imp_REAL_D 15910 call fooR(real(D1)) 15911 c FFEINTRIN_imp_REAL_I 15912 call fooR(real(I1)) 15913 c FFEINTRIN_imp_REAL_R 15914 call fooR(real(R1)) 15915 c 15916 c FFEINTRIN_imp_INT_D: 15917 c 15918 c FFEINTRIN_specIDINT 15919 call fooI(IDINT(D1)) 15920 c 15921 c FFEINTRIN_imp_INT_R: 15922 c 15923 c FFEINTRIN_specIFIX 15924 call fooI(IFIX(R1)) 15925 c FFEINTRIN_specINT 15926 call fooI(INT(R1)) 15927 c 15928 c FFEINTRIN_imp_REAL_D: 15929 c 15930 c FFEINTRIN_specSNGL 15931 call fooR(SNGL(D1)) 15932 c 15933 c FFEINTRIN_imp_REAL_I: 15934 c 15935 c FFEINTRIN_specFLOAT 15936 call fooR(FLOAT(I1)) 15937 c FFEINTRIN_specREAL 15938 call fooR(REAL(I1)) 15939 c 15940 end 15941 -------- (end input file to f2c) 15942 15943 -------- (begin output from providing above input file as input to: 15944 -------- `f2c | gcc -E -C - | sed -e "s:/[*]*://:g" -e "s:[*]*[/]://:g" \ 15945 -------- -e "s:^#.*$::g"') 15946 15947 // -- translated by f2c (version 19950223). 15948 You must link the resulting object file with the libraries: 15949 -lf2c -lm (in that order) 15950 // 15951 15952 15953 // f2c.h -- Standard Fortran to C header file // 15954 15955 /// barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed." 15956 15957 - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) // 15958 15959 15960 15961 15962 // F2C_INTEGER will normally be `int' but would be `long' on 16-bit systems // 15963 // we assume short, float are OK // 15964 typedef long int // long int // integer; 15965 typedef char *address; 15966 typedef short int shortint; 15967 typedef float real; 15968 typedef double doublereal; 15969 typedef struct { real r, i; } complex; 15970 typedef struct { doublereal r, i; } doublecomplex; 15971 typedef long int // long int // logical; 15972 typedef short int shortlogical; 15973 typedef char logical1; 15974 typedef char integer1; 15975 // typedef long long longint; // // system-dependent // 15976 15977 15978 15979 15980 // Extern is for use with -E // 15981 15982 15983 15984 15985 // I/O stuff // 15986 15987 15988 15989 15990 15991 15992 15993 15994 typedef long int // int or long int // flag; 15995 typedef long int // int or long int // ftnlen; 15996 typedef long int // int or long int // ftnint; 15997 15998 15999 //external read, write// 16000 typedef struct 16001 { flag cierr; 16002 ftnint ciunit; 16003 flag ciend; 16004 char *cifmt; 16005 ftnint cirec; 16006 } cilist; 16007 16008 //internal read, write// 16009 typedef struct 16010 { flag icierr; 16011 char *iciunit; 16012 flag iciend; 16013 char *icifmt; 16014 ftnint icirlen; 16015 ftnint icirnum; 16016 } icilist; 16017 16018 //open// 16019 typedef struct 16020 { flag oerr; 16021 ftnint ounit; 16022 char *ofnm; 16023 ftnlen ofnmlen; 16024 char *osta; 16025 char *oacc; 16026 char *ofm; 16027 ftnint orl; 16028 char *oblnk; 16029 } olist; 16030 16031 //close// 16032 typedef struct 16033 { flag cerr; 16034 ftnint cunit; 16035 char *csta; 16036 } cllist; 16037 16038 //rewind, backspace, endfile// 16039 typedef struct 16040 { flag aerr; 16041 ftnint aunit; 16042 } alist; 16043 16044 // inquire // 16045 typedef struct 16046 { flag inerr; 16047 ftnint inunit; 16048 char *infile; 16049 ftnlen infilen; 16050 ftnint *inex; //parameters in standard's order// 16051 ftnint *inopen; 16052 ftnint *innum; 16053 ftnint *innamed; 16054 char *inname; 16055 ftnlen innamlen; 16056 char *inacc; 16057 ftnlen inacclen; 16058 char *inseq; 16059 ftnlen inseqlen; 16060 char *indir; 16061 ftnlen indirlen; 16062 char *infmt; 16063 ftnlen infmtlen; 16064 char *inform; 16065 ftnint informlen; 16066 char *inunf; 16067 ftnlen inunflen; 16068 ftnint *inrecl; 16069 ftnint *innrec; 16070 char *inblank; 16071 ftnlen inblanklen; 16072 } inlist; 16073 16074 16075 16076 union Multitype { // for multiple entry points // 16077 integer1 g; 16078 shortint h; 16079 integer i; 16080 // longint j; // 16081 real r; 16082 doublereal d; 16083 complex c; 16084 doublecomplex z; 16085 }; 16086 16087 typedef union Multitype Multitype; 16088 16089 typedef long Long; // No longer used; formerly in Namelist // 16090 16091 struct Vardesc { // for Namelist // 16092 char *name; 16093 char *addr; 16094 ftnlen *dims; 16095 int type; 16096 }; 16097 typedef struct Vardesc Vardesc; 16098 16099 struct Namelist { 16100 char *name; 16101 Vardesc **vars; 16102 int nvars; 16103 }; 16104 typedef struct Namelist Namelist; 16105 16106 16107 16108 16109 16110 16111 16112 16113 // procedure parameter types for -A and -C++ // 16114 16115 16116 16117 16118 typedef int // Unknown procedure type // (*U_fp)(); 16119 typedef shortint (*J_fp)(); 16120 typedef integer (*I_fp)(); 16121 typedef real (*R_fp)(); 16122 typedef doublereal (*D_fp)(), (*E_fp)(); 16123 typedef // Complex // void (*C_fp)(); 16124 typedef // Double Complex // void (*Z_fp)(); 16125 typedef logical (*L_fp)(); 16126 typedef shortlogical (*K_fp)(); 16127 typedef // Character // void (*H_fp)(); 16128 typedef // Subroutine // int (*S_fp)(); 16129 16130 // E_fp is for real functions when -R is not specified // 16131 typedef void C_f; // complex function // 16132 typedef void H_f; // character function // 16133 typedef void Z_f; // double complex function // 16134 typedef doublereal E_f; // real function with -R not specified // 16135 16136 // undef any lower-case symbols that your C compiler predefines, e.g.: // 16137 16138 16139 // (No such symbols should be defined in a strict ANSI C compiler. 16140 We can avoid trouble with f2c-translated code by using 16141 gcc -ansi.) // 16142 16143 16144 16145 16146 16147 16148 16149 16150 16151 16152 16153 16154 16155 16156 16157 16158 16159 16160 16161 16162 16163 16164 16165 // Main program // MAIN__() 16166 { 16167 // System generated locals // 16168 integer i__1; 16169 real r__1, r__2; 16170 doublereal d__1, d__2; 16171 complex q__1; 16172 doublecomplex z__1, z__2, z__3; 16173 logical L__1; 16174 char ch__1[1]; 16175 16176 // Builtin functions // 16177 void c_div(); 16178 integer pow_ii(); 16179 double pow_ri(), pow_di(); 16180 void pow_ci(); 16181 double pow_dd(); 16182 void pow_zz(); 16183 double acos(), r_imag(), r_int(), log(), r_lg10(), r_mod(), r_nint(), 16184 asin(), atan(), atan2(), c_abs(); 16185 void c_cos(), c_exp(), c_log(), r_cnjg(); 16186 double cos(), cosh(); 16187 void c_sin(), c_sqrt(); 16188 double d_dim(), exp(), r_dim(), d_int(), d_lg10(), d_mod(), d_nint(), 16189 d_sign(), sin(), sinh(), sqrt(), tan(), tanh(); 16190 integer i_dim(), i_dnnt(), i_indx(), i_sign(), i_len(); 16191 logical l_ge(), l_gt(), l_le(), l_lt(); 16192 integer i_nint(); 16193 double r_sign(); 16194 16195 // Local variables // 16196 extern // Subroutine // int fooa_(), fooc_(), food_(), fooi_(), foor_(), 16197 fool_(), fooz_(), getem_(); 16198 static char a1[10], a2[10]; 16199 static complex c1, c2; 16200 static doublereal d1, d2; 16201 static integer i1, i2; 16202 static real r1, r2; 16203 16204 16205 getem_(a1, a2, &c1, &c2, &i1, &i2, &r1, &r2, &d1, &d2, 10L, 10L); 16206 // / // 16207 i__1 = i1 / i2; 16208 fooi_(&i__1); 16209 r__1 = r1 / i1; 16210 foor_(&r__1); 16211 d__1 = d1 / i1; 16212 food_(&d__1); 16213 d__1 = (doublereal) i1; 16214 q__1.r = c1.r / d__1, q__1.i = c1.i / d__1; 16215 fooc_(&q__1); 16216 r__1 = r1 / r2; 16217 foor_(&r__1); 16218 d__1 = r1 / d1; 16219 food_(&d__1); 16220 d__1 = d1 / d2; 16221 food_(&d__1); 16222 d__1 = d1 / r1; 16223 food_(&d__1); 16224 c_div(&q__1, &c1, &c2); 16225 fooc_(&q__1); 16226 q__1.r = c1.r / r1, q__1.i = c1.i / r1; 16227 fooc_(&q__1); 16228 z__1.r = c1.r / d1, z__1.i = c1.i / d1; 16229 fooz_(&z__1); 16230 // ** // 16231 i__1 = pow_ii(&i1, &i2); 16232 fooi_(&i__1); 16233 r__1 = pow_ri(&r1, &i1); 16234 foor_(&r__1); 16235 d__1 = pow_di(&d1, &i1); 16236 food_(&d__1); 16237 pow_ci(&q__1, &c1, &i1); 16238 fooc_(&q__1); 16239 d__1 = (doublereal) r1; 16240 d__2 = (doublereal) r2; 16241 r__1 = pow_dd(&d__1, &d__2); 16242 foor_(&r__1); 16243 d__2 = (doublereal) r1; 16244 d__1 = pow_dd(&d__2, &d1); 16245 food_(&d__1); 16246 d__1 = pow_dd(&d1, &d2); 16247 food_(&d__1); 16248 d__2 = (doublereal) r1; 16249 d__1 = pow_dd(&d1, &d__2); 16250 food_(&d__1); 16251 z__2.r = c1.r, z__2.i = c1.i; 16252 z__3.r = c2.r, z__3.i = c2.i; 16253 pow_zz(&z__1, &z__2, &z__3); 16254 q__1.r = z__1.r, q__1.i = z__1.i; 16255 fooc_(&q__1); 16256 z__2.r = c1.r, z__2.i = c1.i; 16257 z__3.r = r1, z__3.i = 0.; 16258 pow_zz(&z__1, &z__2, &z__3); 16259 q__1.r = z__1.r, q__1.i = z__1.i; 16260 fooc_(&q__1); 16261 z__2.r = c1.r, z__2.i = c1.i; 16262 z__3.r = d1, z__3.i = 0.; 16263 pow_zz(&z__1, &z__2, &z__3); 16264 fooz_(&z__1); 16265 // FFEINTRIN_impABS // 16266 r__1 = (doublereal)(( r1 ) >= 0 ? ( r1 ) : -( r1 )) ; 16267 foor_(&r__1); 16268 // FFEINTRIN_impACOS // 16269 r__1 = acos(r1); 16270 foor_(&r__1); 16271 // FFEINTRIN_impAIMAG // 16272 r__1 = r_imag(&c1); 16273 foor_(&r__1); 16274 // FFEINTRIN_impAINT // 16275 r__1 = r_int(&r1); 16276 foor_(&r__1); 16277 // FFEINTRIN_impALOG // 16278 r__1 = log(r1); 16279 foor_(&r__1); 16280 // FFEINTRIN_impALOG10 // 16281 r__1 = r_lg10(&r1); 16282 foor_(&r__1); 16283 // FFEINTRIN_impAMAX0 // 16284 r__1 = (real) (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ; 16285 foor_(&r__1); 16286 // FFEINTRIN_impAMAX1 // 16287 r__1 = (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ; 16288 foor_(&r__1); 16289 // FFEINTRIN_impAMIN0 // 16290 r__1 = (real) (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ; 16291 foor_(&r__1); 16292 // FFEINTRIN_impAMIN1 // 16293 r__1 = (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ; 16294 foor_(&r__1); 16295 // FFEINTRIN_impAMOD // 16296 r__1 = r_mod(&r1, &r2); 16297 foor_(&r__1); 16298 // FFEINTRIN_impANINT // 16299 r__1 = r_nint(&r1); 16300 foor_(&r__1); 16301 // FFEINTRIN_impASIN // 16302 r__1 = asin(r1); 16303 foor_(&r__1); 16304 // FFEINTRIN_impATAN // 16305 r__1 = atan(r1); 16306 foor_(&r__1); 16307 // FFEINTRIN_impATAN2 // 16308 r__1 = atan2(r1, r2); 16309 foor_(&r__1); 16310 // FFEINTRIN_impCABS // 16311 r__1 = c_abs(&c1); 16312 foor_(&r__1); 16313 // FFEINTRIN_impCCOS // 16314 c_cos(&q__1, &c1); 16315 fooc_(&q__1); 16316 // FFEINTRIN_impCEXP // 16317 c_exp(&q__1, &c1); 16318 fooc_(&q__1); 16319 // FFEINTRIN_impCHAR // 16320 *(unsigned char *)&ch__1[0] = i1; 16321 fooa_(ch__1, 1L); 16322 // FFEINTRIN_impCLOG // 16323 c_log(&q__1, &c1); 16324 fooc_(&q__1); 16325 // FFEINTRIN_impCONJG // 16326 r_cnjg(&q__1, &c1); 16327 fooc_(&q__1); 16328 // FFEINTRIN_impCOS // 16329 r__1 = cos(r1); 16330 foor_(&r__1); 16331 // FFEINTRIN_impCOSH // 16332 r__1 = cosh(r1); 16333 foor_(&r__1); 16334 // FFEINTRIN_impCSIN // 16335 c_sin(&q__1, &c1); 16336 fooc_(&q__1); 16337 // FFEINTRIN_impCSQRT // 16338 c_sqrt(&q__1, &c1); 16339 fooc_(&q__1); 16340 // FFEINTRIN_impDABS // 16341 d__1 = (( d1 ) >= 0 ? ( d1 ) : -( d1 )) ; 16342 food_(&d__1); 16343 // FFEINTRIN_impDACOS // 16344 d__1 = acos(d1); 16345 food_(&d__1); 16346 // FFEINTRIN_impDASIN // 16347 d__1 = asin(d1); 16348 food_(&d__1); 16349 // FFEINTRIN_impDATAN // 16350 d__1 = atan(d1); 16351 food_(&d__1); 16352 // FFEINTRIN_impDATAN2 // 16353 d__1 = atan2(d1, d2); 16354 food_(&d__1); 16355 // FFEINTRIN_impDCOS // 16356 d__1 = cos(d1); 16357 food_(&d__1); 16358 // FFEINTRIN_impDCOSH // 16359 d__1 = cosh(d1); 16360 food_(&d__1); 16361 // FFEINTRIN_impDDIM // 16362 d__1 = d_dim(&d1, &d2); 16363 food_(&d__1); 16364 // FFEINTRIN_impDEXP // 16365 d__1 = exp(d1); 16366 food_(&d__1); 16367 // FFEINTRIN_impDIM // 16368 r__1 = r_dim(&r1, &r2); 16369 foor_(&r__1); 16370 // FFEINTRIN_impDINT // 16371 d__1 = d_int(&d1); 16372 food_(&d__1); 16373 // FFEINTRIN_impDLOG // 16374 d__1 = log(d1); 16375 food_(&d__1); 16376 // FFEINTRIN_impDLOG10 // 16377 d__1 = d_lg10(&d1); 16378 food_(&d__1); 16379 // FFEINTRIN_impDMAX1 // 16380 d__1 = (( d1 ) >= ( d2 ) ? ( d1 ) : ( d2 )) ; 16381 food_(&d__1); 16382 // FFEINTRIN_impDMIN1 // 16383 d__1 = (( d1 ) <= ( d2 ) ? ( d1 ) : ( d2 )) ; 16384 food_(&d__1); 16385 // FFEINTRIN_impDMOD // 16386 d__1 = d_mod(&d1, &d2); 16387 food_(&d__1); 16388 // FFEINTRIN_impDNINT // 16389 d__1 = d_nint(&d1); 16390 food_(&d__1); 16391 // FFEINTRIN_impDPROD // 16392 d__1 = (doublereal) r1 * r2; 16393 food_(&d__1); 16394 // FFEINTRIN_impDSIGN // 16395 d__1 = d_sign(&d1, &d2); 16396 food_(&d__1); 16397 // FFEINTRIN_impDSIN // 16398 d__1 = sin(d1); 16399 food_(&d__1); 16400 // FFEINTRIN_impDSINH // 16401 d__1 = sinh(d1); 16402 food_(&d__1); 16403 // FFEINTRIN_impDSQRT // 16404 d__1 = sqrt(d1); 16405 food_(&d__1); 16406 // FFEINTRIN_impDTAN // 16407 d__1 = tan(d1); 16408 food_(&d__1); 16409 // FFEINTRIN_impDTANH // 16410 d__1 = tanh(d1); 16411 food_(&d__1); 16412 // FFEINTRIN_impEXP // 16413 r__1 = exp(r1); 16414 foor_(&r__1); 16415 // FFEINTRIN_impIABS // 16416 i__1 = (( i1 ) >= 0 ? ( i1 ) : -( i1 )) ; 16417 fooi_(&i__1); 16418 // FFEINTRIN_impICHAR // 16419 i__1 = *(unsigned char *)a1; 16420 fooi_(&i__1); 16421 // FFEINTRIN_impIDIM // 16422 i__1 = i_dim(&i1, &i2); 16423 fooi_(&i__1); 16424 // FFEINTRIN_impIDNINT // 16425 i__1 = i_dnnt(&d1); 16426 fooi_(&i__1); 16427 // FFEINTRIN_impINDEX // 16428 i__1 = i_indx(a1, a2, 10L, 10L); 16429 fooi_(&i__1); 16430 // FFEINTRIN_impISIGN // 16431 i__1 = i_sign(&i1, &i2); 16432 fooi_(&i__1); 16433 // FFEINTRIN_impLEN // 16434 i__1 = i_len(a1, 10L); 16435 fooi_(&i__1); 16436 // FFEINTRIN_impLGE // 16437 L__1 = l_ge(a1, a2, 10L, 10L); 16438 fool_(&L__1); 16439 // FFEINTRIN_impLGT // 16440 L__1 = l_gt(a1, a2, 10L, 10L); 16441 fool_(&L__1); 16442 // FFEINTRIN_impLLE // 16443 L__1 = l_le(a1, a2, 10L, 10L); 16444 fool_(&L__1); 16445 // FFEINTRIN_impLLT // 16446 L__1 = l_lt(a1, a2, 10L, 10L); 16447 fool_(&L__1); 16448 // FFEINTRIN_impMAX0 // 16449 i__1 = (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ; 16450 fooi_(&i__1); 16451 // FFEINTRIN_impMAX1 // 16452 i__1 = (integer) (doublereal)(( r1 ) >= ( r2 ) ? ( r1 ) : ( r2 )) ; 16453 fooi_(&i__1); 16454 // FFEINTRIN_impMIN0 // 16455 i__1 = (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ; 16456 fooi_(&i__1); 16457 // FFEINTRIN_impMIN1 // 16458 i__1 = (integer) (doublereal)(( r1 ) <= ( r2 ) ? ( r1 ) : ( r2 )) ; 16459 fooi_(&i__1); 16460 // FFEINTRIN_impMOD // 16461 i__1 = i1 % i2; 16462 fooi_(&i__1); 16463 // FFEINTRIN_impNINT // 16464 i__1 = i_nint(&r1); 16465 fooi_(&i__1); 16466 // FFEINTRIN_impSIGN // 16467 r__1 = r_sign(&r1, &r2); 16468 foor_(&r__1); 16469 // FFEINTRIN_impSIN // 16470 r__1 = sin(r1); 16471 foor_(&r__1); 16472 // FFEINTRIN_impSINH // 16473 r__1 = sinh(r1); 16474 foor_(&r__1); 16475 // FFEINTRIN_impSQRT // 16476 r__1 = sqrt(r1); 16477 foor_(&r__1); 16478 // FFEINTRIN_impTAN // 16479 r__1 = tan(r1); 16480 foor_(&r__1); 16481 // FFEINTRIN_impTANH // 16482 r__1 = tanh(r1); 16483 foor_(&r__1); 16484 // FFEINTRIN_imp_CMPLX_C // 16485 r__1 = c1.r; 16486 r__2 = c2.r; 16487 q__1.r = r__1, q__1.i = r__2; 16488 fooc_(&q__1); 16489 // FFEINTRIN_imp_CMPLX_D // 16490 z__1.r = d1, z__1.i = d2; 16491 fooz_(&z__1); 16492 // FFEINTRIN_imp_CMPLX_I // 16493 r__1 = (real) i1; 16494 r__2 = (real) i2; 16495 q__1.r = r__1, q__1.i = r__2; 16496 fooc_(&q__1); 16497 // FFEINTRIN_imp_CMPLX_R // 16498 q__1.r = r1, q__1.i = r2; 16499 fooc_(&q__1); 16500 // FFEINTRIN_imp_DBLE_C // 16501 d__1 = (doublereal) c1.r; 16502 food_(&d__1); 16503 // FFEINTRIN_imp_DBLE_D // 16504 d__1 = d1; 16505 food_(&d__1); 16506 // FFEINTRIN_imp_DBLE_I // 16507 d__1 = (doublereal) i1; 16508 food_(&d__1); 16509 // FFEINTRIN_imp_DBLE_R // 16510 d__1 = (doublereal) r1; 16511 food_(&d__1); 16512 // FFEINTRIN_imp_INT_C // 16513 i__1 = (integer) c1.r; 16514 fooi_(&i__1); 16515 // FFEINTRIN_imp_INT_D // 16516 i__1 = (integer) d1; 16517 fooi_(&i__1); 16518 // FFEINTRIN_imp_INT_I // 16519 i__1 = i1; 16520 fooi_(&i__1); 16521 // FFEINTRIN_imp_INT_R // 16522 i__1 = (integer) r1; 16523 fooi_(&i__1); 16524 // FFEINTRIN_imp_REAL_C // 16525 r__1 = c1.r; 16526 foor_(&r__1); 16527 // FFEINTRIN_imp_REAL_D // 16528 r__1 = (real) d1; 16529 foor_(&r__1); 16530 // FFEINTRIN_imp_REAL_I // 16531 r__1 = (real) i1; 16532 foor_(&r__1); 16533 // FFEINTRIN_imp_REAL_R // 16534 r__1 = r1; 16535 foor_(&r__1); 16536 16537 // FFEINTRIN_imp_INT_D: // 16538 16539 // FFEINTRIN_specIDINT // 16540 i__1 = (integer) d1; 16541 fooi_(&i__1); 16542 16543 // FFEINTRIN_imp_INT_R: // 16544 16545 // FFEINTRIN_specIFIX // 16546 i__1 = (integer) r1; 16547 fooi_(&i__1); 16548 // FFEINTRIN_specINT // 16549 i__1 = (integer) r1; 16550 fooi_(&i__1); 16551 16552 // FFEINTRIN_imp_REAL_D: // 16553 16554 // FFEINTRIN_specSNGL // 16555 r__1 = (real) d1; 16556 foor_(&r__1); 16557 16558 // FFEINTRIN_imp_REAL_I: // 16559 16560 // FFEINTRIN_specFLOAT // 16561 r__1 = (real) i1; 16562 foor_(&r__1); 16563 // FFEINTRIN_specREAL // 16564 r__1 = (real) i1; 16565 foor_(&r__1); 16566 16567 } // MAIN__ // 16568 16569 -------- (end output file from f2c) 16570 16571 */ 16572 16573 #include "gt-f-com.h" 16574 #include "gtype-f.h" 16575