Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
00001 /* 00002 00003 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00004 00005 This program is free software; you can redistribute it and/or modify it 00006 under the terms of version 2 of the GNU General Public License as 00007 published by the Free Software Foundation. 00008 00009 This program is distributed in the hope that it would be useful, but 00010 WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00012 00013 Further, this software is distributed without any warranty that it is 00014 free of the rightful claim of any third person regarding infringement 00015 or the like. Any license provided herein, whether implied or 00016 otherwise, applies only to this software file. Patent licenses, if 00017 any, provided herein do not apply to combinations of this program with 00018 other software, or any other product whatsoever. 00019 00020 You should have received a copy of the GNU General Public License along 00021 with this program; if not, write the Free Software Foundation, Inc., 59 00022 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00023 00024 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00025 Mountain View, CA 94043, or: 00026 00027 http://www.sgi.com 00028 00029 For further information regarding this notice, see: 00030 00031 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00032 00033 */ 00034 00035 00036 /* ==================================================================== 00037 * ==================================================================== 00038 * 00039 00040 * 00041 * Revision history: 00042 * 12-Apr-95 - Original Version 00043 * 00044 * Description: 00045 * 00046 * Translate a WN subtree to Fortran by means of an inorder recursive 00047 * descent traversal of the WHIRL IR. Note that the routines to 00048 * handle expressions, statements, and loads/stores have been 00049 * separated into different source files. However, the interfaces 00050 * to those source-files should only ever be accessed from this file. 00051 * 00052 * WN2F_translate: 00053 * Translates an arbitrary WN tree into a sequence of tokens, 00054 * appended to the end of the given token-buffer. The task of 00055 * translation will be dispatched to a member in a set of 00056 * "handler" routines, and these handler routines should 00057 * only be called from this routine. 00058 * 00059 * ==================================================================== 00060 * ==================================================================== 00061 */ 00062 00063 #ifdef _KEEP_RCS_ID 00064 /*REFERENCED*/ 00065 #endif 00066 00067 #include <alloca.h> 00068 #include <set> 00069 00070 #include "x_string.h" // for strcasecmp() 00071 #include "whirl2f_common.h" 00072 #include "PUinfo.h" /* From be/whirl2c directory */ 00073 #include "wn2f.h" 00074 #include "wn2f_stmt.h" /* Only used by this module */ 00075 #include "wn2f_pragma.h" /* Only used by this module */ 00076 #include "wn2f_expr.h" /* Only used by this module */ 00077 #include "wn2f_load_store.h" /* Only used by this module */ 00078 #include "wn2f_io.h" /* Only used by this module */ 00079 #include "st2f.h" 00080 #include "ty2f.h" 00081 #include "tcon2f.h" 00082 #include "unparse_target.h" 00083 #include "ty_ftn.h" 00084 00085 extern WN_MAP *W2F_Construct_Map; /* Defined in w2f_driver.c */ 00086 extern BOOL W2F_Prompf_Emission; /* Defined in w2f_driver.c */ 00087 char * sgi_comment_str = "CSGI$ " ; 00088 00089 00090 static BOOL PU_Need_End_Contains = FALSE; // f90 needs CONTAINS/END around nested procs. 00091 static BOOL PU_Dangling_Contains = FALSE; // f90 have done CONTAINS, need END... 00092 static INT32 PU_Host_Func_Id = 0 ; // func id for END/CONTAINS 00093 00094 WN* PU_Body=NULL; 00095 00096 static void WN2F_End_Routine_Strings(TOKEN_BUFFER tokens, INT32 func_id); 00097 00098 /*---------------- Buffers to hold intermediate results ----------------*/ 00099 /*----------------------------------------------------------------------*/ 00100 00101 /* Should be initialized when entering a PU block and reclaimed 00102 * when exiting a PU block. 00103 */ 00104 TOKEN_BUFFER Data_Stmt_Tokens = NULL; /* Defined in init2f.c */ 00105 00106 00107 /*-------------------- Function handle for each OPR -------------------*/ 00108 /*---------------------------------------------------------------------*/ 00109 00110 /* Type of handler-functions for translation from WHIRL to Fortran. 00111 */ 00112 typedef WN2F_STATUS (*WN2F_HANDLER_FUNC)(TOKEN_BUFFER, WN*, WN2F_CONTEXT); 00113 00114 00115 /* Declarations of top-level and exceptional handler-functions for 00116 * translation from WHIRL to Fortran. The others are declared through 00117 * "wn2f_stmt.h", "wn2f_expr.h", and "wn2f_load_store.h". 00118 */ 00119 static WN2F_STATUS 00120 WN2F_ignore(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context); 00121 static WN2F_STATUS 00122 WN2F_unsupported(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context); 00123 static WN2F_STATUS 00124 WN2F_func_entry(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context); 00125 static WN2F_STATUS 00126 WN2F_altentry(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context); 00127 static WN2F_STATUS 00128 WN2F_comment(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context); 00129 00130 00131 /* WN2F_Handler[] maps an OPR (../common/com/opcode_gen_core.h) to 00132 * the handler-function that translates it to Fortran. This table 00133 * will be dynamically initialized through WN2F_initialize(). This 00134 * dynamic initialization ensures that the initiated elements of the 00135 * table are valid regardless of future changes to the OPERATOR 00136 * enumeration. Operators not yet correctly handled by whirl2f, and 00137 * therefore not present in the WN2F_Opr_Handler_list[], will be 00138 * handled by WN2F_unsupported(). 00139 */ 00140 #define NUMBER_OF_OPERATORS (OPERATOR_LAST + 1) 00141 static WN2F_HANDLER_FUNC WN2F_Handler[NUMBER_OF_OPERATORS]; 00142 00143 typedef struct WN2F_Opr_Handler 00144 { 00145 OPERATOR opr; 00146 WN2F_HANDLER_FUNC handler; 00147 } WN2F_OPR_HANDLER; 00148 00149 #define NUMBER_OF_OPR_HANDLERS \ 00150 (sizeof(WN2F_Opr_Handler_List) / sizeof(WN2F_OPR_HANDLER)) 00151 00152 static const WN2F_OPR_HANDLER WN2F_Opr_Handler_List[] = 00153 { 00154 {OPR_FUNC_ENTRY, &WN2F_func_entry}, 00155 {OPR_BLOCK, &WN2F_block}, 00156 {OPR_REGION_EXIT, &WN2F_goto}, 00157 /* {OPR_SWITCH, &WN2F_switch}, Not a Fortran construct! */ 00158 {OPR_COMPGOTO, &WN2F_compgoto}, 00159 {OPR_DO_LOOP, &WN2F_do_loop}, 00160 {OPR_DO_WHILE, &WN2F_do_while}, 00161 {OPR_WHILE_DO, &WN2F_while_do}, 00162 {OPR_IF, &WN2F_if}, 00163 {OPR_GOTO, &WN2F_goto}, 00164 {OPR_AGOTO, &WN2F_agoto}, 00165 {OPR_ALTENTRY, &WN2F_altentry}, 00166 {OPR_FALSEBR, &WN2F_condbr}, 00167 {OPR_TRUEBR, &WN2F_condbr}, 00168 {OPR_RETURN, &WN2F_return}, 00169 {OPR_RETURN_VAL, &WN2F_return_val}, 00170 {OPR_LABEL, &WN2F_label}, 00171 {OPR_ISTORE, &WN2F_istore}, 00172 {OPR_PSTORE, &WN2F_pstore}, 00173 {OPR_ISTOREX, &WN2F_istorex}, 00174 {OPR_MSTORE, &WN2F_mstore}, 00175 {OPR_STID, &WN2F_stid}, 00176 {OPR_PSTID, &WN2F_pstid}, 00177 {OPR_CALL, &WN2F_call}, 00178 {OPR_INTRINSIC_CALL, &WN2F_intrinsic_call}, 00179 {OPR_ICALL, &WN2F_call}, 00180 {OPR_PICCALL, &WN2F_call}, 00181 {OPR_EVAL, &WN2F_eval}, 00182 {OPR_PREFETCH, &WN2F_prefetch}, 00183 {OPR_PREFETCHX, &WN2F_prefetch}, 00184 {OPR_PRAGMA, &WN2F_pragma}, 00185 {OPR_XPRAGMA, &WN2F_pragma}, 00186 {OPR_IO, &WN2F_io}, 00187 {OPR_COMMENT, &WN2F_comment}, 00188 {OPR_ILOAD, &WN2F_iload}, 00189 {OPR_ILOADX, &WN2F_iloadx}, 00190 {OPR_MLOAD, &WN2F_mload}, 00191 {OPR_ARRAY, &WN2F_array}, 00192 00193 {OPR_ARRAYEXP,&WN2F_arrayexp}, 00194 {OPR_ARRSECTION,&WN2F_arrsection}, 00195 {OPR_TRIPLET,&WN2F_triplet}, 00196 {OPR_SRCTRIPLET,&WN2F_src_triplet}, 00197 {OPR_WHERE,&WN2F_where}, 00198 {OPR_INTRINSIC_OP, &WN2F_intrinsic_op}, 00199 {OPR_TAS, &WN2F_tas}, 00200 {OPR_SELECT, &WN2F_select}, 00201 {OPR_CVT, &WN2F_cvt}, 00202 {OPR_CVTL, &WN2F_cvtl}, 00203 {OPR_NEG, &WN2F_unaryop}, 00204 {OPR_ABS, &WN2F_unaryop}, 00205 {OPR_SQRT, &WN2F_unaryop}, 00206 {OPR_REALPART, &WN2F_realpart}, 00207 {OPR_IMAGPART, &WN2F_imagpart}, 00208 {OPR_PAREN, &WN2F_paren}, 00209 {OPR_RND, &WN2F_unaryop}, 00210 {OPR_TRUNC, &WN2F_unaryop}, 00211 {OPR_CEIL, &WN2F_ceil}, 00212 {OPR_FLOOR, &WN2F_floor}, 00213 {OPR_BNOT, &WN2F_unaryop}, 00214 {OPR_LNOT, &WN2F_unaryop}, 00215 {OPR_ADD, &WN2F_binaryop}, 00216 {OPR_SUB, &WN2F_binaryop}, 00217 {OPR_MPY, &WN2F_binaryop}, 00218 {OPR_DIV, &WN2F_binaryop}, 00219 {OPR_MOD, &WN2F_binaryop}, 00220 {OPR_REM, &WN2F_binaryop}, 00221 {OPR_MAX, &WN2F_binaryop}, 00222 {OPR_MIN, &WN2F_binaryop}, 00223 {OPR_BAND, &WN2F_binaryop}, 00224 {OPR_BIOR, &WN2F_binaryop}, 00225 {OPR_BNOR, &WN2F_bnor}, 00226 {OPR_BXOR, &WN2F_binaryop}, 00227 {OPR_LAND, &WN2F_binaryop}, 00228 {OPR_LIOR, &WN2F_binaryop}, 00229 {OPR_CAND, &WN2F_binaryop}, 00230 {OPR_CIOR, &WN2F_binaryop}, 00231 {OPR_SHL, &WN2F_binaryop}, 00232 {OPR_ASHR, &WN2F_ashr}, 00233 {OPR_LSHR, &WN2F_lshr}, 00234 {OPR_COMPLEX, &WN2F_complex}, 00235 {OPR_RECIP, &WN2F_recip}, 00236 {OPR_RSQRT, &WN2F_rsqrt}, 00237 {OPR_MADD, &WN2F_madd}, 00238 {OPR_MSUB, &WN2F_msub}, 00239 {OPR_NMADD, &WN2F_nmadd}, 00240 {OPR_NMSUB, &WN2F_nmsub}, 00241 {OPR_EQ, &WN2F_eq}, 00242 {OPR_NE, &WN2F_ne}, 00243 {OPR_GT, &WN2F_binaryop}, 00244 {OPR_GE, &WN2F_binaryop}, 00245 {OPR_LT, &WN2F_binaryop}, 00246 {OPR_LE, &WN2F_binaryop}, 00247 {OPR_LDID, &WN2F_ldid}, 00248 {OPR_LDA, &WN2F_lda}, 00249 {OPR_CONST, &WN2F_const}, 00250 {OPR_INTCONST, &WN2F_intconst}, 00251 {OPR_PARM, &WN2F_parm}, 00252 {OPR_TRAP, &WN2F_ignore}, 00253 {OPR_ASSERT, &WN2F_ignore}, 00254 {OPR_FORWARD_BARRIER, &WN2F_ignore}, 00255 {OPR_BACKWARD_BARRIER, &WN2F_ignore}, 00256 {OPR_ALLOCA, &WN2F_alloca}, 00257 {OPR_DEALLOCA, &WN2F_dealloca}, 00258 {OPR_USE, &WN2F_use_stmt}, 00259 {OPR_IMPLICIT_BND, &WN2F_implicit_bnd}, 00260 {OPR_NAMELIST, &WN2F_namelist_stmt}, 00261 {OPR_INTERFACE, &WN2F_interface_blk}, 00262 {OPR_SWITCH,&WN2F_switch}, 00263 {OPR_CASEGOTO,&WN2F_casegoto}, 00264 {OPR_NULLIFY,&WN2F_nullify_stmt}, 00265 {OPR_ARRAY_CONSTRUCT,&WN2F_ar_construct}, 00266 {OPR_IMPLIED_DO,&WN2F_noio_implied_do}, 00267 {OPR_IDNAME, &WN2F_idname}, 00268 {OPR_STRCTFLD, &WN2F_strctfld}, 00269 {OPR_COMMA, &WN2F_comma} 00270 00271 }; /* WN2F_Opr_Handler_List */ 00272 00273 00274 /*------------------ Statement newline directives ----------------------*/ 00275 /*----------------------------------------------------------------------*/ 00276 00277 void 00278 WN2F_Stmt_Newline(TOKEN_BUFFER tokens, 00279 const char *label, 00280 SRCPOS srcpos, 00281 WN2F_CONTEXT context) 00282 { 00283 if (WN2F_CONTEXT_no_newline(context)) 00284 { 00285 if (W2F_File[W2F_LOC_FILE] != NULL) 00286 Append_Srcpos_Map(tokens, srcpos); 00287 } 00288 else 00289 { 00290 if (W2F_Emit_Linedirs) 00291 Append_Srcpos_Directive(tokens, srcpos); 00292 Append_F77_Indented_Newline(tokens, 1, label); 00293 if (W2F_File[W2F_LOC_FILE] != NULL) 00294 Append_Srcpos_Map(tokens, srcpos); 00295 } 00296 } /* WN2F_Stmt_Newline */ 00297 00298 00299 /*--------------------------- Prompf processing ------------------------*/ 00300 /*----------------------------------------------------------------------*/ 00301 00302 00303 static void 00304 WN2F_Begin_Prompf_Transformed_Func(TOKEN_BUFFER tokens, INT32 func_id) 00305 { 00306 Append_F77_Directive_Newline(tokens, sgi_comment_str) ; 00307 Append_Token_String(tokens, "start"); 00308 Append_Token_String(tokens, Number_as_String(func_id, "%llu")); 00309 } 00310 00311 static void 00312 WN2F_End_Prompf_Transformed_Func(TOKEN_BUFFER tokens, INT32 func_id) 00313 { 00314 Append_F77_Directive_Newline(tokens, sgi_comment_str) ; 00315 Append_Token_String(tokens, "end"); 00316 Append_Token_String(tokens, Number_as_String(func_id, "%llu")); 00317 } 00318 00319 00320 /*------------ Translation of addressing and dereferencing -------------*/ 00321 /*----------------------------------------------------------------------*/ 00322 00323 /* just used to maintain the state of the recursions when */ 00324 /* marking FLDs in nested addresses */ 00325 00326 class LOC_INFO{ 00327 00328 private: 00329 FLD_PATH_INFO * _flds_left; /* points to tail of fld_path */ 00330 STAB_OFFSET _off; /* offset of last FLD used in fld_path */ 00331 BOOL _base_is_array; /* was ST of address an array? */ 00332 00333 public: 00334 WN * _nested_addr; 00335 00336 LOC_INFO(FLD_PATH_INFO * path) { 00337 _flds_left = path; 00338 00339 _off = 0; 00340 _nested_addr = NULL; 00341 _base_is_array = FALSE ; 00342 } 00343 00344 void WN2F_Find_And_Mark_Nested_Address(WN * addr); 00345 #ifdef FMZDBG 00346 void debugpathinfo(void); 00347 #endif 00348 }; 00349 00350 #ifdef FMZDBG 00351 void LOC_INFO:: 00352 debugpathinfo(void) 00353 { 00354 FLD_PATH_INFO *fld_path_test; 00355 fld_path_test = _flds_left; 00356 printf("****In the file LOC_INFO::debugpathinf******\n"); 00357 while (fld_path_test) 00358 { 00359 printf("\t***Field name in the path is :: %s\n", 00360 FLD_name(fld_path_test->fld)); 00361 if (fld_path_test->arr_wn) 00362 printf("\t***WN opr is %d \n", 00363 WN_operator(fld_path_test->arr_wn)); 00364 else 00365 printf("\t***no WN find in the path\n"); 00366 00367 fld_path_test = fld_path_test->next; 00368 00369 } 00370 00371 printf("****Out of the file LOC_INFO::debugpathinf******\n"); 00372 } 00373 #endif 00374 00375 void LOC_INFO:: 00376 WN2F_Find_And_Mark_Nested_Address(WN * addr) 00377 { 00378 /* If this address expression contains nested ARRAY nodes */ 00379 /* (and isn't a character expression), the ARRAYs refer */ 00380 /* to structure components, eg: aaa(1).kkk(3) yields */ 00381 /* ARRAY(ADD(const,ARRAY(LDA)). Add a pointer to the */ 00382 /* array elements of the fld path, associating each with */ 00383 /* corresponding OPC_ARRAY. TY2F_Translate_Fld_Path will */ 00384 /* write the subscript list. */ 00385 00386 00387 /* In general, just the lowest LDID/LDA remains to be */ 00388 /* processed, however if the lowest ARRAY node is not a */ 00389 /* fld, and belongs to the address ST, then return that */ 00390 /* ARRAY. */ 00391 switch (WN_operator(addr)) 00392 { 00393 case OPR_ARRAY: 00394 case OPR_ARRSECTION: 00395 { 00396 WN * kid; 00397 #if 0 00398 if (WN_operator(addr)==OPR_ARRAYEXP) 00399 addr = WN_kid0(addr); 00400 #endif 00401 kid = WN_kid0(addr); 00402 WN2F_Find_And_Mark_Nested_Address(kid); 00403 if ((_flds_left && _flds_left->arr_elt) && 00404 (!(_base_is_array))) 00405 { 00406 _flds_left-> arr_wn = addr; 00407 _flds_left = TY2F_Point_At_Path(_flds_left,_off); 00408 } 00409 else 00410 _nested_addr = addr; 00411 00412 _base_is_array = FALSE; 00413 } 00414 break; 00415 00416 00417 case OPR_ARRAYEXP: 00418 WN * kid; 00419 kid = WN_kid0(addr); 00420 WN2F_Find_And_Mark_Nested_Address(kid); 00421 _base_is_array = FALSE; 00422 break; 00423 00424 case OPR_ADD: 00425 { 00426 WN * cnst = WN_kid0(addr); 00427 WN * othr = WN_kid1(addr); 00428 00429 if (WN_operator(cnst) != OPR_INTCONST) 00430 { 00431 cnst = WN_kid1(addr); 00432 othr = WN_kid0(addr); 00433 } 00434 WN2F_Find_And_Mark_Nested_Address(othr); 00435 _off = WN_const_val(cnst); 00436 _base_is_array = FALSE; 00437 } 00438 break; 00439 00440 case OPR_LDID: 00441 _off = 0; 00442 _nested_addr = addr; 00443 _flds_left = TY2F_Point_At_Path(_flds_left,_off); 00444 _base_is_array = ((TY_kind(WN_ty(addr)) == KIND_POINTER) && 00445 (TY_kind(TY_pointed(WN_ty(addr))) == KIND_ARRAY)); 00446 break; 00447 00448 case OPR_LDA: 00449 _off = WN_lda_offset(addr); 00450 _nested_addr = addr; 00451 _base_is_array = ((TY_kind(WN_ty(addr)) == KIND_POINTER) && 00452 (TY_kind(TY_pointed(WN_ty(addr))) == KIND_ARRAY || 00453 TY_is_f90_deferred_shape(TY_pointed(WN_ty(addr))))); 00454 break; 00455 00456 case OPR_ILOAD: 00457 _off = 0; 00458 _nested_addr = addr; 00459 _flds_left = TY2F_Point_At_Path(_flds_left,0); 00460 _base_is_array = ((TY_kind(WN_ty(addr)) == KIND_POINTER) && 00461 (TY_kind(TY_pointed(WN_ty(addr))) == KIND_ARRAY)); 00462 break; 00463 00464 default: 00465 00466 ASSERT_WARN((0), 00467 (DIAG_W2F_UNEXPECTED_OPC,"WN2F_Find_And_Mark_Nested_Address")); 00468 00469 break; 00470 } 00471 return; 00472 } 00473 00474 00475 extern WN_OFFSET 00476 WN2F_Sum_Offsets(WN *addr) 00477 { 00478 /* Accumulate any offsets (ADDs) in this address */ 00479 /* tree. Used for computing Fld paths */ 00480 00481 BOOL sum = 0; 00482 00483 switch (WN_operator(addr)) 00484 { 00485 case OPR_ARRAY: 00486 case OPR_ARRAYEXP: 00487 case OPR_ARRSECTION: 00488 sum += WN2F_Sum_Offsets(WN_kid0(addr)); 00489 break; 00490 00491 case OPR_ADD: 00492 sum += WN2F_Sum_Offsets(WN_kid0(addr)); 00493 sum += WN2F_Sum_Offsets(WN_kid1(addr)); 00494 break; 00495 00496 case OPR_INTCONST: 00497 sum = WN_const_val(addr); 00498 break; 00499 } 00500 return sum; 00501 } 00502 00503 00504 void 00505 WN2F_Address_Of(TOKEN_BUFFER tokens) 00506 { 00507 Prepend_Token_Special(tokens, '('); 00508 Prepend_Token_String(tokens, "loc%"); 00509 Append_Token_Special(tokens, '('); 00510 } /* WN2F_Address_Of */ 00511 00512 WN2F_STATUS 00513 WN2F_Offset_Symref(TOKEN_BUFFER tokens, 00514 ST *st, /* base-symbol */ 00515 TY_IDX addr_ty, /* expected base-address type */ 00516 TY_IDX object_ty, /* object type */ 00517 STAB_OFFSET offset, /* offset from base-address */ 00518 WN2F_CONTEXT context) 00519 { 00520 /* Given a symbol and an offset within the location of the symbol, 00521 * append a Fortran expression to "tokens" to access an object 00522 * of the given "object_ty" at this location. 00523 * 00524 * The base symbol will unconditionally be treated as having an 00525 * lvalue (address) type as given by "addr_ty", except when "deref" 00526 * is TRUE, when the rvalue of the base-symbol is assumed to have 00527 * the "addr_ty" and must either explicitly (for POINTER variables) 00528 * or implicitly (for pass by reference arguments) be dereferenced. 00529 * Note that for a compatible base-type and object-type, this is simply 00530 * a reference to the given ST_name(); in all other cases we expect 00531 * the object_ty to be a field (FLD) within the base-type (KIND_STRUCT) 00532 * or an offset within an array. 00533 * 00534 * Note that we must have special handling for common-blocks and 00535 * equivalences. Note that "addr_ty" may be different from 00536 * "Stab_Pointer_To(ST_type(st))", both for "deref" cases and 00537 * ptr_as_array variables. 00538 */ 00539 TY_IDX base_ty = TY_pointed(addr_ty); 00540 const BOOL deref_val = WN2F_CONTEXT_deref_addr(context); 00541 BOOL deref_fld; 00542 void (*translate_var_ref)(TOKEN_BUFFER, ST *); 00543 00544 00545 #ifdef __USE_COMMON_BLOCK_NAME__ 00546 00547 /* Do the symbol translation from the base of BASED symbols */ 00548 if (Stab_Is_Based_At_Common_Or_Equivalence(st)) 00549 { 00550 offset += ST_ofst(st); /* offset of based symbol */ 00551 st = ST_base(st); /* replace based symbol with its base */ 00552 00553 base_ty = ST_type(st); 00554 addr_ty = Stab_Pointer_To(base_ty); 00555 Set_BE_ST_w2fc_referenced(st); 00556 } 00557 00558 /* Do the symbol translation from the base of fully split common symbols */ 00559 if (ST_is_split_common(st)) 00560 { 00561 #if 0 00562 offset += Stab_Full_Split_Offset(st); /* offset of split common now zero. */ 00563 #endif 00564 Clear_BE_ST_w2fc_referenced(st); 00565 st = ST_full(st); 00566 Set_BE_ST_w2fc_referenced(st); 00567 base_ty = ST_type(st); 00568 00569 if (TY_is_Pointer(base_ty)) 00570 base_ty = TY_pointed(base_ty); 00571 00572 if (TY_is_f90_pointer(base_ty)) 00573 base_ty = TY_pointed(base_ty); 00574 00575 addr_ty = Stab_Pointer_To(base_ty); 00576 } 00577 #endif 00578 00579 00580 /* Select variable-reference translation function */ 00581 if (deref_val && 00582 ST_sclass(st) != SCLASS_FORMAL && 00583 TY_Is_Pointer(ST_type(st)) && !TY_is_f90_pointer(ST_type(st))) 00584 { 00585 /* An explicitly dereference */ 00586 translate_var_ref = &ST2F_deref_translate; 00587 } 00588 else 00589 { 00590 /* A direct reference or an implicit dereference */ 00591 translate_var_ref = &ST2F_use_translate; 00592 } 00593 00594 if (WN2F_Can_Assign_Types(base_ty, object_ty) || 00595 (TY_kind(base_ty) == KIND_FUNCTION && 00596 TY_kind(base_ty) == TY_kind(object_ty) && 00597 TY_kind(object_ty) != KIND_STRUCT )) 00598 { 00599 /* Since the types are compatible, we cannot have an offset 00600 * into one of the objects. Simply generate a reference to 00601 * the symbol. 00602 */ 00603 00604 ASSERT_WARN(offset==0, (DIAG_W2F_UNEXPEXTED_OFFSET, 00605 offset, "WN2F_Offset_Symref")); 00606 00607 translate_var_ref(tokens, st); 00608 } 00609 else if (TY_Is_Array(base_ty)) 00610 { 00611 ASSERT_DBG_WARN(WN2F_Can_Assign_Types(TY_AR_etype(base_ty), object_ty), 00612 (DIAG_W2F_INCOMPATIBLE_TYS, "WN2F_Offset_Symref")); 00613 00614 if (TY_Is_Character_String(base_ty)) 00615 { 00616 # if 0 00617 Append_Token_String(tokens, "ichar"); 00618 Append_Token_Special(tokens, '('); 00619 # endif 00620 translate_var_ref(tokens, st); 00621 TY2F_Translate_ArrayElt(tokens, base_ty, offset); 00622 #if 0 00623 Append_Token_Special(tokens, ')'); 00624 #endif 00625 00626 } 00627 else 00628 { 00629 translate_var_ref(tokens, st); 00630 if (!WN2F_CONTEXT_has_no_arr_elmt(context)) { 00631 TY2F_Translate_ArrayElt(tokens, base_ty, offset); 00632 reset_WN2F_CONTEXT_has_no_arr_elmt(context); 00633 } 00634 } 00635 } 00636 else /* incompatible base and object types */ 00637 { 00638 00639 #if 0 //we use OPR_STRCTFLD to get the fld_path--FMZ August 2005 00640 /* we add OPR_STRCTFLD for X%Y, fld_path calculate no longer needed */ 00641 FLD_PATH_INFO *fld_path; 00642 00643 00644 /* Get the path to the (undereferenced) object type. 00645 * 00646 * The following should no longer be necessary, since the 00647 * appropriate dereferencing of a field should happen in the 00648 * translation of the field-path, not through a change of the 00649 * object type in the context. 00650 * 00651 * if (deref) 00652 * fld_path = 00653 * TY2F_Get_Fld_Path(base_ty, Stab_Pointer_To(object_ty), offset); 00654 * else 00655 */ 00656 00657 /* We only dereference a field when the base need not be 00658 * dereferenced. We never need to have both dereferenced, 00659 * since pointers cannot occur in RECORDS and common/ 00660 * equivalence blocks cannot be referenced through pointer 00661 * identifiers. 00662 */ 00663 deref_fld = (deref_val && !TY_Is_Pointer(ST_type(st)))? TRUE : FALSE; 00664 if (deref_fld) 00665 object_ty = Stab_Pointer_To(object_ty); 00666 00667 fld_path = TY2F_Get_Fld_Path(base_ty, object_ty, offset); 00668 00669 if (fld_path == NULL) 00670 { 00671 /* return vars for entry points may have equivalence classes */ 00672 /* without anything at offset 0. Just put out the ST of the */ 00673 /* return variable, as we don't put out the equivalence group */ 00674 00675 if (ST_is_return_var(st)) 00676 (void)translate_var_ref(tokens, st); 00677 else 00678 { 00679 ASSERT_DBG_WARN(FALSE, 00680 (DIAG_W2F_NONEXISTENT_FLD_PATH, 00681 "WN2F_Offset_Symref")); 00682 Append_Token_String(tokens, "SOMEWHERE_IN"); 00683 Append_Token_Special(tokens, '('); 00684 (void)translate_var_ref(tokens, st); 00685 Append_Token_Special(tokens, ')'); 00686 } 00687 } 00688 else 00689 { 00690 // if (!Stab_Is_Common_Block(st) && !Stab_Is_Equivalence_Block(st)) 00691 { 00692 /* Base the path at the st object, and separate it from 00693 * the remainder of the path with the field selection 00694 * operator ('.'). 00695 */ 00696 (void)translate_var_ref(tokens, st); 00697 TY2F_Fld_Separator(tokens); 00698 } 00699 # if 0 00700 if (Stab_Is_Equivalence_Block(st) && 00701 (ST_is_return_var(st) || 00702 (PUinfo_current_func != NULL && 00703 (PUINFO_RETURN_TO_PARAM && st == PUINFO_RETURN_PARAM)))) 00704 TY2F_Translate_Fld_Path(tokens, fld_path, 00705 deref_fld,FALSE, TRUE,context); 00706 else 00707 # endif 00708 00709 TY2F_Translate_Fld_Path(tokens, fld_path, 00710 deref_fld, 00711 // (Stab_Is_Common_Block(st) || 00712 // Stab_Is_Equivalence_Block(st)), 00713 FALSE , 00714 FALSE/*as_is*/, 00715 context); 00716 00717 TY2F_Free_Fld_Path(fld_path); 00718 } /* if (the field was found) */ 00719 #else 00720 (void)translate_var_ref(tokens, st); 00721 #endif 00722 00723 } /* if (base-type is compatible with object-type */ 00724 00725 return EMPTY_WN2F_STATUS; 00726 } /* WN2F_Offset_Symref */ 00727 00728 00729 WN2F_STATUS 00730 WN2F_Offset_Memref(TOKEN_BUFFER tokens, 00731 WN *addr, /* base-address expression */ 00732 TY_IDX addr_ty, /* expected base-address type */ 00733 TY_IDX object_ty, /* object type */ 00734 STAB_OFFSET offset, /* offset from base-address */ 00735 WN2F_CONTEXT context) 00736 { 00737 /* Given an address expression and an offset from this address, 00738 * append a Fortran expression to "tokens" to access an object 00739 * of the given "object_ty" at this offset address. I.e. this 00740 * is a dereferencing operation on the base-address. The resultant 00741 * value (e.g. after a struct-field access) may be further 00742 * dereferenced. 00743 * 00744 * The address expression is unconditionally treated as an expression 00745 * of the addr_ty. 00746 * 00747 * For non-zero offsets, or when "!WN2F_Can_Assign_Types(object_ty, 00748 * TY_pointed(addr_ty))", we expect the base-address to denote the 00749 * address of a structure or an array, where an object of the given 00750 * object_ty can be found at the given offset. 00751 * 00752 * Since Fortran does not have an explicit (only implicit) dereference 00753 * operation we cannot first calculate the address and then 00754 * dereference. This constrains the kind of expression we may handle 00755 * here. Note that equivalences and common-blocks always should be 00756 * accessed through an LDID or an LDA(?) node. 00757 */ 00758 00759 const BOOL deref_fld = WN2F_CONTEXT_deref_addr(context); 00760 00761 /* Prepare to dereference the base-address expression */ 00762 set_WN2F_CONTEXT_deref_addr(context); 00763 00764 if (WN2F_Is_Address_Preg(addr,addr_ty)) 00765 { 00766 /* Optimizer may put address PREGS into ARRAYs */ 00767 /* and high level type is more or less useless */ 00768 /* just go with WN tree ADDs etc. */ 00769 00770 (void)WN2F_translate(tokens, addr, context); 00771 00772 if (offset != 0) 00773 { 00774 Append_Token_Special(tokens, '+'); 00775 Append_Token_String(tokens, Number_as_String(offset, "%lld")); 00776 } 00777 } 00778 else 00779 { 00780 00781 TY_IDX base_ty = TY_pointed(addr_ty); 00782 00783 00784 // deferred shape or f90 pointer 00785 // base_ty and object_ty not proper set in some cases 00786 if (TY_Is_Array(base_ty) && 00787 TY_is_f90_deferred_shape(base_ty) && 00788 !TY_Is_Array(object_ty) ) 00789 base_ty = TY_AR_etype(base_ty); 00790 00791 if (WN2F_Can_Assign_Types(base_ty, object_ty)) 00792 { 00793 /* Since the types are compatible, we cannot have an offset 00794 * into one of the objects, and we further dispatch the task 00795 * of translation. 00796 */ 00797 00798 /* Since we do not generate dope vector for pointer, we could have 00799 this kind of situation: such as ---FMZ 00800 type mytype 00801 integer i 00802 type(mytpe),pointer:: next 00803 end type mytype 00804 type(mytype) pv1,pv2 00805 pv1%next=pv2 00806 00807 */ 00808 ASSERT_WARN(offset==0, (DIAG_W2F_UNEXPEXTED_OFFSET, 00809 offset, "WN2F_Offset_Memref")); 00810 00811 (void)WN2F_translate(tokens, addr, context); 00812 } 00813 else /* Accessing a field in a record or an element of an array */ 00814 { 00815 if (TY_Is_Array(base_ty)) 00816 { 00817 ASSERT_DBG_WARN(WN2F_Can_Assign_Types(TY_AR_etype(base_ty), 00818 object_ty), 00819 (DIAG_W2F_INCOMPATIBLE_TYS, "WN2F_Offset_Memref")); 00820 00821 if (TY_Is_Character_String(base_ty)) 00822 { 00823 # if 0 00824 Append_Token_String(tokens, "ichar"); 00825 Append_Token_Special(tokens, '('); 00826 # endif 00827 (void)WN2F_translate(tokens, addr, context); /* String lvalue */ 00828 # if 0 00829 Append_Token_Special(tokens, ')'); 00830 # endif 00831 00832 } 00833 else 00834 { 00835 (void)WN2F_translate(tokens, addr, context); /* Array lvalue */ 00836 } 00837 } 00838 00839 else if ((WN_opc_operator(addr) == OPR_LDA || 00840 WN_opc_operator(addr) == OPR_LDID) && 00841 (TY_kind(base_ty) != KIND_STRUCT) && 00842 (Stab_Is_Common_Block(WN_st(addr)) || 00843 Stab_Is_Equivalence_Block(WN_st(addr)))) 00844 { 00845 /* A common-block or equivalence-block, both of which we handle 00846 * only in WN2F_Offset_Symref(). 00847 */ 00848 00849 ASSERT_WARN(WN2F_Can_Assign_Types(ST_type(WN_st(addr)), base_ty) , 00850 (DIAG_W2F_INCOMPATIBLE_TYS, "WN2F_Offset_Symref")); 00851 00852 if (WN_opc_operator(addr) == OPR_LDA) 00853 reset_WN2F_CONTEXT_deref_addr(context); 00854 (void)WN2F_Offset_Symref(tokens, 00855 WN_st(addr), 00856 addr_ty, /* base */ 00857 object_ty, /* object */ 00858 offset + WN_lda_offset(addr), /* offset */ 00859 context); 00860 } 00861 00862 else /* Neither common-block nor equivalence field-access */ 00863 { 00864 /* Find the path to the field we wish to access and append 00865 * this path to the base-object reference. 00866 */ 00867 00868 FLD_PATH_INFO *fld_path; 00869 00870 /* Get any offset given by an address ADDition node. The type 00871 * of the addition, as given by WN_Tree_Type(), is the type 00872 * of base-object within which we are accessing, so the addr_ty 00873 * is already set up correctly to handle the combined offsets. 00874 */ 00875 00876 WN_OFFSET tmp = WN2F_Sum_Offsets(addr); 00877 00878 if (tmp < TY_size(TY_pointed(addr_ty))) 00879 offset += tmp; 00880 else 00881 offset = tmp; 00882 00883 if (WN_operator(addr)==OPR_ARRAYEXP) 00884 addr = WN_kid0(addr); 00885 00886 fld_path = TY2F_Get_Fld_Path(base_ty, object_ty, offset); 00887 00888 #ifdef FMZDBG 00889 { 00890 FLD_PATH_INFO *fld_path_test; 00891 fld_path_test = fld_path; 00892 while (fld_path_test) 00893 { 00894 printf("\t***Field name in the path is :: %s\n", 00895 FLD_name(fld_path_test->fld)); 00896 if (fld_path_test->arr_wn) 00897 printf("\t***WN opr is %d \n", 00898 WN_operator(fld_path_test->arr_wn)); 00899 else 00900 printf("\t***no WN found in the path\n"); 00901 00902 fld_path_test = fld_path_test->next; 00903 00904 } 00905 } 00906 #endif 00907 00908 ASSERT_DBG_WARN(fld_path != NULL, 00909 (DIAG_W2F_NONEXISTENT_FLD_PATH, 00910 "WN2F_Offset_Memref")); 00911 00912 00913 /* May have ARRAY(ADD(ARRAY(LDA),CONST)) or some such. */ 00914 /* The deepest ARRAY (with the address) is handled */ 00915 /* by the WN2F_array processing, but the others */ 00916 /* are field references with array components. */ 00917 00918 LOC_INFO det(fld_path); 00919 #ifdef FMZDBG 00920 det.debugpathinfo(); 00921 #endif 00922 det.WN2F_Find_And_Mark_Nested_Address(addr); 00923 #ifdef FMZDBG 00924 det.debugpathinfo(); 00925 #endif 00926 addr = det._nested_addr; 00927 /* Get the base expression to precede the path */ 00928 00929 (void)WN2F_translate(tokens, addr, context); 00930 00931 /* Append the path-name, perhaps w/o array subscripts. */ 00932 #if 0 00933 if (fld_type_z && offset_add) { 00934 fld_path = TY2F_Get_Fld_Path(fld_type_z, fld_type_z, offset_add); 00935 } 00936 #endif 00937 00938 #ifdef FMZDBG 00939 { 00940 FLD_PATH_INFO *fld_path_test; 00941 fld_path_test = fld_path; 00942 while (fld_path_test) 00943 { 00944 printf("\t***Field name in the path is :: %s\n", 00945 FLD_name(fld_path_test->fld)); 00946 if (fld_path_test->arr_wn) 00947 printf("\t***WN opr is %d \n", 00948 WN_operator(fld_path_test->arr_wn)); 00949 else 00950 printf("\t***no WN find in the path\n"); 00951 00952 fld_path_test = fld_path_test->next; 00953 } 00954 } 00955 #endif 00956 00957 if (fld_path != NULL) 00958 { 00959 TY2F_Fld_Separator(tokens); 00960 TY2F_Translate_Fld_Path(tokens, 00961 fld_path, 00962 deref_fld, 00963 FALSE/*common*/, 00964 FALSE/*as_is*/, 00965 context); 00966 #if 0 00967 } 00968 } 00969 fld_type_z = FLD_type(fld_path->fld); 00970 #endif 00971 TY2F_Free_Fld_Path(fld_path); 00972 } 00973 else 00974 { 00975 Append_Token_String(tokens, 00976 Number_as_String(offset, 00977 "<field-at-offset=%lld>")); 00978 } 00979 00980 } /* if (neither common-block nor equivalence field-access */ 00981 00982 } /* if (object_ty is incompatible with base_ty) */ 00983 } /* else */ 00984 00985 return EMPTY_WN2F_STATUS; 00986 } /* WN2F_Offset_Memref */ 00987 00988 /*---------------- Translation of function entry points ----------------*/ 00989 /*----------------------------------------------------------------------*/ 00990 00991 void 00992 WN2F_Entry_Point(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context) 00993 { 00994 /* This will translate an alternate or function entry point with 00995 * parameter declarations into Fortran. Note that the 00996 * PUinfo_current_func will not change as a result of this call. 00997 * 00998 */ 00999 ST **param_st; 01000 INT param, num_formals; 01001 01002 ASSERT_DBG_FATAL(WN_opcode(wn) == OPC_ALTENTRY || 01003 WN_opcode(wn) == OPC_FUNC_ENTRY, 01004 (DIAG_W2F_UNEXPECTED_OPC, "WN2F_Entry_Point")); 01005 01006 if (WN_opcode(wn) == OPC_ALTENTRY) 01007 num_formals = WN_kid_count(wn); 01008 else 01009 num_formals = WN_num_formals(wn); 01010 01011 /* Accumulate the parameter ST entries */ 01012 param_st = (ST **)alloca((num_formals + 1) * sizeof(ST *)); 01013 for (param = 0; param < num_formals; param++) 01014 { 01015 param_st[param] = WN_st(WN_formal(wn, param)); 01016 } 01017 /* Terminate the list of parameter STs */ 01018 param_st[num_formals] = NULL; 01019 01020 /* Write out the entry point with parameter declarations 01021 * on a new line. 01022 */ 01023 // WN2F_Stmt_Newline(tokens, NULL/*label*/, WN_Get_Linenum(wn), context); 01024 ST2F_func_header(tokens, 01025 &St_Table[WN_entry_name(wn)], 01026 param_st, 01027 num_formals, 01028 WN_opcode(wn) == OPC_ALTENTRY); 01029 01030 } /* WN2F_Entry_Point */ 01031 01032 01033 /*--------- The operator handlers implemented in this module ----------*/ 01034 /*---------------------------------------------------------------------*/ 01035 01036 01037 static WN2F_STATUS 01038 WN2F_ignore(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context) 01039 { 01040 return EMPTY_WN2F_STATUS; 01041 } /* WN2F_ignore */ 01042 01043 01044 static WN2F_STATUS 01045 WN2F_unsupported(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context) 01046 { 01047 /* Warn about opcodes we cannot translate, but keep translating. 01048 */ 01049 ASSERT_WARN(FALSE, 01050 (DIAG_W2F_CANNOT_HANDLE_OPC, WN_opc_name(wn), WN_opcode(wn))); 01051 01052 WN2F_Stmt_Newline(tokens, NULL/*label*/, WN_Get_Linenum(wn), context); 01053 Append_Token_String(tokens, Concat3_Strings("<", WN_opc_name(wn), ">")); 01054 01055 return EMPTY_WN2F_STATUS; 01056 } /* WN2F_unsupported */ 01057 01058 01059 static WN2F_STATUS 01060 WN2F_func_entry(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context) 01061 { 01062 /* Add tokens for the function header and body to "tokens". Note 01063 * that the whole function definition will appended to the buffer, 01064 * while the task of writing the tokens to file and freeing up 01065 * the buffer is left to the caller. 01066 * 01067 * Assume that Current_Symtab has been updated (see bedriver.c). 01068 * Note that Current_PU is not maintained, but we instead get to 01069 * it through PUinfo_current_func. 01070 * 01071 */ 01072 INT32 func_id = 0; 01073 01074 ASSERT_DBG_FATAL(WN_opcode(wn) == OPC_FUNC_ENTRY, 01075 (DIAG_W2F_UNEXPECTED_OPC, "WN2F_func_entry")); 01076 01077 /* Write prompf information */ 01078 01079 if (W2F_Prompf_Emission) { 01080 func_id = WN_MAP32_Get(*W2F_Construct_Map, wn); 01081 WN2F_Begin_Prompf_Transformed_Func(tokens, func_id); 01082 } 01083 01084 /* For local declarations, set the indentation to the current 01085 * indentation */ 01086 01087 PUinfo_local_decls_indent = Current_Indentation(); 01088 01089 PU_Body=WN_func_body(wn); 01090 01091 /* Translate the function header */ 01092 WN2F_Entry_Point(tokens, wn, context); 01093 01094 /* Emit the function pragmas before local variables */ 01095 if (!W2F_No_Pragmas) 01096 WN2F_pragma_list_begin(PUinfo_pragmas, 01097 WN_first(WN_func_pragmas(wn)), 01098 context); 01099 01100 set_WN2F_CONTEXT_new_pu(context); 01101 (void)WN2F_translate(tokens, WN_func_body(wn), context); 01102 01103 /* While necessary for regions, we probably need not end any pragmas 01104 * in a func_entry, but we make the call anyway; for consistency. 01105 */ 01106 if (!W2F_No_Pragmas) 01107 WN2F_pragma_list_end(tokens, 01108 WN_first(WN_func_pragmas(wn)), 01109 context); 01110 01111 WN2F_Stmt_Newline(tokens,NULL, WN_Get_Linenum(wn), context); 01112 01113 WN2F_End_Routine_Strings(tokens,func_id); 01114 01115 return EMPTY_WN2F_STATUS; 01116 } 01117 01118 WN2F_STATUS 01119 WN2F_altentry(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context) 01120 { 01121 /* This is very similar to a func_entry, but without the function 01122 * body. 01123 */ 01124 ASSERT_DBG_FATAL(WN_opcode(wn) == OPC_ALTENTRY, 01125 (DIAG_W2F_UNEXPECTED_OPC, "WN2F_altentry")); 01126 01127 /* Translate the function entry point */ 01128 WN2F_Entry_Point(tokens, wn, context); 01129 01130 return EMPTY_WN2F_STATUS; 01131 } /* WN2F_altentry */ 01132 01133 01134 WN2F_STATUS 01135 WN2F_comment(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context) 01136 { 01137 ASSERT_DBG_FATAL(WN_opcode(wn) == OPC_COMMENT, 01138 (DIAG_W2F_UNEXPECTED_OPC, "WN2F_comment")); 01139 01140 /* Used to avoid comments with special interpretation. Note that 01141 this is basically a prefix test. 01142 */ 01143 static char* avoid[] = { 01144 "ENDLOOP", 01145 /* original text of I/O stmt is saved in comment nodes */ 01146 /* open, close, rewind, backspace, format? */ 01147 "read", "write", "print" 01148 }; 01149 static int avoidSZ = sizeof(avoid) / sizeof(char*); 01150 01151 const char* com = Index_To_Str(WN_GetComment(wn)); 01152 01153 for (int i = 0; i < avoidSZ; ++i) { 01154 const char* str = avoid[i]; 01155 if (ux_strncasecmp(com, str, strlen(str)) == 0) { 01156 return EMPTY_WN2F_STATUS; 01157 } 01158 } 01159 01160 WHIRL2F_Append_Comment(tokens, com, 0, 0); 01161 01162 return EMPTY_WN2F_STATUS; 01163 } /* WN2F_comment */ 01164 01165 01166 /*------------------------ exported routines --------------------------*/ 01167 /*---------------------------------------------------------------------*/ 01168 01169 01170 void 01171 WN2F_initialize(void) 01172 { 01173 INT opr; 01174 INT map; 01175 01176 /* Reset the WN2F_Handler array */ 01177 for (opr = 0; opr < NUMBER_OF_OPERATORS; opr++) 01178 WN2F_Handler[opr] = &WN2F_unsupported; 01179 01180 /* Initialize the WN2F_Handler array */ 01181 for (map = 0; map < NUMBER_OF_OPR_HANDLERS; map++) 01182 WN2F_Handler[WN2F_Opr_Handler_List[map].opr] = 01183 WN2F_Opr_Handler_List[map].handler; 01184 01185 WN2F_Stmt_initialize(); 01186 WN2F_Expr_initialize(); 01187 WN2F_Load_Store_initialize(); 01188 WN2F_Io_initialize(); 01189 01190 } /* WN2F_initialize */ 01191 01192 01193 void 01194 WN2F_finalize(void) 01195 { 01196 /* Reset the auxiliary WN translator modules, and the stab_attr 01197 * facility. 01198 */ 01199 WN2F_Stmt_finalize(); 01200 WN2F_Expr_finalize(); 01201 WN2F_Load_Store_finalize(); 01202 WN2F_Io_finalize(); 01203 Stab_Free_Tmpvars(); 01204 } /* WN2F_finalize */ 01205 01206 // utility to interpret context information 01207 01208 void 01209 WN2F_dump_context( WN2F_CONTEXT c) 01210 { 01211 printf ("("); 01212 01213 if (WN2F_CONTEXT_new_pu(c)) printf (" new_pu") ; 01214 if (WN2F_CONTEXT_insert_induction(c)) printf (" induct_tmp_reqd") ; 01215 if (WN2F_CONTEXT_deref_addr(c)) printf (" deref") ; 01216 if (WN2F_CONTEXT_no_newline(c)) printf (" no_newline") ; 01217 if (WN2F_CONTEXT_has_logical_arg(c)) printf (" logical_arg") ; 01218 if (WN2F_CONTEXT_no_parenthesis(c)) printf (" no_paren") ; 01219 if (WN2F_CONTEXT_keyword_ioctrl(c)) printf (" ioctrl") ; 01220 if (WN2F_CONTEXT_io_stmt(c)) printf (" in_io") ; 01221 if (WN2F_CONTEXT_deref_io_item(c)) printf (" deref_io") ; 01222 if (WN2F_CONTEXT_origfmt_ioctrl(c)) printf (" varfmt") ; 01223 if (WN2F_CONTEXT_emit_stid(c)) printf (" emit_stid") ; 01224 if (WN2F_CONTEXT_explicit_region(c)) printf (" region_pragma") ; 01225 if (WN2F_CONTEXT_fmt_io(c)) printf (" formatted io") ; 01226 if (WN2F_CONTEXT_cray_io(c)) printf (" craylib") ; 01227 printf (")\n"); 01228 } 01229 01230 01231 WN2F_STATUS 01232 WN2F_translate(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context) 01233 { 01234 const BOOL parenthesize = !WN2F_CONTEXT_no_parenthesis(context); 01235 01236 /* Determine whether we are in a context where we expect this 01237 * expression to have logically valued arguments, or whether 01238 * we are entering a context where we expect this expression 01239 * to be a logically valued argument. 01240 */ 01241 if (OPCODE_is_boolean(WN_opcode(wn)) && 01242 WN2F_expr_has_boolean_arg(WN_opcode(wn))) /* expect logical args */ 01243 { 01244 /* Note that this may also be a logical argument, so 01245 * WN2F_CONTEXT_is_logical_arg(context) may also hold TRUE. 01246 */ 01247 set_WN2F_CONTEXT_has_logical_arg(context); 01248 } 01249 else if (WN2F_CONTEXT_has_logical_arg(context)) /* is a logical arg */ 01250 { 01251 /* This is the only place where we should need to check whether 01252 * this is expected to be a logical valued expression. I.e. the 01253 * only place where we apply WN2F_CONTEXT_has_logical_arg(context). 01254 * However, it may be set at other places (e.g. in wn2f_stmt.c). 01255 */ 01256 reset_WN2F_CONTEXT_has_logical_arg(context); 01257 set_WN2F_CONTEXT_is_logical_arg(context); 01258 } 01259 else 01260 { 01261 reset_WN2F_CONTEXT_has_logical_arg(context); 01262 reset_WN2F_CONTEXT_is_logical_arg(context); 01263 } 01264 01265 /* Dispatch to the appropriate handler for this construct. 01266 */ 01267 OPERATOR op = WN_opc_operator(wn); 01268 WN2F_STATUS ret = WN2F_Handler[WN_opc_operator(wn)](tokens, wn, context); 01269 01270 /* reset: this flag should only affect children of 'wn', not any siblings */ 01271 reset_WN2F_CONTEXT_has_logical_arg(context); 01272 01273 return ret; 01274 } /* WN2F_translate */ 01275 01276 WN2F_STATUS 01277 WN2F_translate_purple_main(TOKEN_BUFFER tokens, 01278 WN *pu, 01279 const char *region_name, 01280 WN2F_CONTEXT context) 01281 { 01282 static const char prp_return_var_name[] = "prp___return"; 01283 extern BOOL Use_Purple_Array_Bnds_Placeholder; /* Defined in ty2f.c */ 01284 01285 TY_IDX return_ty; 01286 ST *param_st; 01287 INT first_param, param, implicit_parms = 0; 01288 01289 ASSERT_DBG_FATAL(WN_opcode(pu) == OPC_FUNC_ENTRY, 01290 (DIAG_W2F_UNEXPECTED_OPC, "WN2F_translate_purple_main")); 01291 01292 /* Write program header 01293 */ 01294 WN2F_Stmt_Newline(tokens, NULL/*label*/, WN_Get_Linenum(pu), context); 01295 Append_Token_String(tokens, "PROGRAM MAIN"); 01296 01297 # if 0 01298 WN2F_Stmt_Newline(tokens, NULL/*label*/, WN_Get_Linenum(pu), context); 01299 Append_Token_String(tokens, "IMPLICIT NONE"); 01300 # endif 01301 01302 /* Write program local variables (region parameters) 01303 */ 01304 Use_Purple_Array_Bnds_Placeholder = TRUE; 01305 first_param = ST2F_FIRST_PARAM_IDX(ST_type(WN_entry_name(pu))); 01306 for (param = first_param; 01307 (param+implicit_parms) < WN_num_formals(pu); 01308 param++) 01309 { 01310 param_st = WN_st(WN_formal(pu, param)); 01311 if (STAB_PARAM_HAS_IMPLICIT_LENGTH(param_st)) 01312 implicit_parms++; 01313 01314 Append_F77_Indented_Newline(tokens, 1, NULL/*label*/); 01315 01316 ST2F_decl_translate(tokens, param_st); 01317 Append_F77_Indented_Newline(tokens, 1, NULL/*label*/); 01318 Append_Token_String(tokens, "SAVE"); 01319 Append_Token_String(tokens, W2CF_Symtab_Nameof_St(param_st)); 01320 01321 } /* while more params */ 01322 Use_Purple_Array_Bnds_Placeholder = FALSE; 01323 01324 /* We do not really care what is returned from the purplized region, 01325 * but for correctness we insert a declaration for any return variable 01326 * here, with a default name. We also insert a declaration of the 01327 * purple_region. 01328 */ 01329 return_ty = W2X_Unparse_Target->Func_Return_Type(ST_type(WN_entry_name(pu))); 01330 if (return_ty != (TY_IDX) 0 && TY_kind(return_ty) != KIND_VOID) 01331 { 01332 TOKEN_BUFFER return_tokens = New_Token_Buffer(); 01333 01334 /* Append the function declaration 01335 */ 01336 Append_Token_String(return_tokens, region_name); 01337 if (TY_Is_Pointer(return_ty)) /* Cannot return ptr in ftn */ 01338 TY2F_translate(return_tokens, 01339 Stab_Mtype_To_Ty(TY_mtype(return_ty))); 01340 else 01341 TY2F_translate(return_tokens, return_ty); 01342 01343 Append_F77_Indented_Newline(tokens, 1, NULL/*label*/); 01344 Append_Token_String(tokens, "EXTERNAL"); 01345 Append_Token_String(tokens, region_name); 01346 Append_F77_Indented_Newline(tokens, 1, NULL/*label*/); 01347 Append_And_Reclaim_Token_List(tokens, &return_tokens); 01348 01349 /* Append the return variable 01350 */ 01351 return_tokens = New_Token_Buffer(); 01352 Append_Token_String(return_tokens, prp_return_var_name); 01353 if (TY_Is_Pointer(return_ty)) /* Cannot return ptr in ftn */ 01354 TY2F_translate(return_tokens, 01355 Stab_Mtype_To_Ty(TY_mtype(return_ty))); 01356 else 01357 TY2F_translate(return_tokens, return_ty); 01358 01359 Append_F77_Indented_Newline(tokens, 1, NULL/*label*/); 01360 Append_And_Reclaim_Token_List(tokens, &return_tokens); 01361 } 01362 01363 /* Insert a placeholder for initialization of parameters 01364 */ 01365 WN2F_Stmt_Newline(tokens, NULL/*label*/, WN_Get_Linenum(pu), context); 01366 Append_Token_String(tokens, "<#PRP_XSYM:INIT_PARAM"); 01367 WN2F_Append_Purple_Funcinfo(tokens); 01368 Append_Token_String(tokens, "#>"); 01369 01370 /* Insert call to purple region routine 01371 */ 01372 WHIRL2F_Append_Comment(tokens, 01373 "**** Call to extracted purple region ****", 01374 1, 1); 01375 WN2F_Stmt_Newline(tokens, NULL/*label*/, WN_Get_Linenum(pu), context); 01376 if (return_ty != (TY_IDX) 0 && TY_kind(return_ty) != KIND_VOID) 01377 { 01378 Append_Token_String(tokens, prp_return_var_name); 01379 Append_Token_Special(tokens, '='); 01380 } 01381 else 01382 Append_Token_String(tokens, "CALL"); 01383 Append_Token_String(tokens, region_name); 01384 Append_Token_Special(tokens, '('); 01385 for (param = first_param; 01386 (param+implicit_parms) < WN_num_formals(pu); 01387 param++) 01388 { 01389 if (param > first_param) 01390 Append_Token_Special(tokens, ','); 01391 01392 param_st = WN_st(WN_formal(pu, param)); 01393 Append_Token_String(tokens, W2CF_Symtab_Nameof_St(param_st)); 01394 } 01395 Append_Token_Special(tokens, ')'); 01396 01397 /* Insert a placeholder for final testing of parameters 01398 */ 01399 WN2F_Stmt_Newline(tokens, NULL/*label*/, WN_Get_Linenum(pu), context); 01400 Append_Token_String(tokens, "<#PRP_XSYM:TEST_PARAM"); 01401 WN2F_Append_Purple_Funcinfo(tokens); 01402 Append_Token_String(tokens, "#>"); 01403 01404 WN2F_Stmt_Newline(tokens, NULL/*label*/, WN_Get_Linenum(pu), context); 01405 Append_Token_String(tokens, "END"); 01406 Append_Token_String(tokens, "!"); 01407 Append_Token_String(tokens, "MAIN"); 01408 WN2F_Stmt_Newline(tokens, NULL/*label*/, WN_Get_Linenum(pu), context); 01409 WN2F_Stmt_Newline(tokens, NULL/*label*/, WN_Get_Linenum(pu), context); 01410 01411 return EMPTY_WN2F_STATUS; 01412 } /* WN2F_translate_purple_main */ 01413 01414 01415 /*------------------------ sundry utilities --------------------------*/ 01416 /*---------------------------------------------------------------------*/ 01417 01418 extern void 01419 WN2F_Emit_End_Stmt(TOKEN_BUFFER tokens, BOOL start) 01420 { 01421 /* For F90 host routine don't know about first/last internal procedures until 01422 * they're processed, so the host didn't get an END. Emit the enclosing 01423 * CONTAINS/END if required. 01424 */ 01425 01426 if (PU_Need_End_Contains) 01427 { 01428 if (start) 01429 { 01430 if(PU_Dangling_Contains) 01431 { 01432 PU_Dangling_Contains = FALSE; 01433 Append_Token_String(tokens,"CONTAINS"); 01434 if (W2F_Prompf_Emission) 01435 WN2F_End_Prompf_Transformed_Func(tokens, PU_Host_Func_Id); 01436 Append_Token_Special(tokens, '\n'); 01437 } 01438 } 01439 else 01440 { 01441 PU_Need_End_Contains = FALSE; 01442 if (Is_Empty_Token_Buffer(tokens)) 01443 Append_F77_Indented_Newline(tokens,0,NULL); 01444 Append_Token_String(tokens,"END"); 01445 01446 /* if wasn't really a host, but just had nested parallel routines */ 01447 /* emit id now, because it wasn't emitted on the CONTAINS */ 01448 01449 if (W2F_Prompf_Emission && PU_Dangling_Contains) 01450 WN2F_End_Prompf_Transformed_Func(tokens, PU_Host_Func_Id); 01451 Append_Token_Special(tokens,'\n'); 01452 } 01453 } 01454 } 01455 01456 static void 01457 WN2F_End_Routine_Strings(TOKEN_BUFFER tokens, INT32 func_id) 01458 { 01459 // figures out how to END the current function. 01460 // An f77 routine, or f90 non-host just needs an END. 01461 // An f90 host requires a CONTAINs plus an END when the 01462 // last internal routine was seen. Distinguish functions 01463 // and subroutines for f90. 01464 01465 PU & pu = Pu_Table[ST_pu(PUINFO_FUNC_ST)]; 01466 01467 if (WN2F_F90_pu) { 01468 if (PU_has_nested(pu) ) 01469 { 01470 PU_Need_End_Contains = TRUE; 01471 PU_Dangling_Contains = TRUE; 01472 PU_Host_Func_Id = func_id; 01473 } 01474 else { 01475 01476 char * p ; 01477 01478 if (PU_is_mainpu(pu)) 01479 p = "END PROGRAM"; 01480 01481 else { 01482 TY_IDX rt = PUINFO_RETURN_TY; 01483 01484 if (TY_kind(rt) == KIND_VOID) { 01485 if (ST_is_in_module(PUINFO_FUNC_ST) && !PU_is_nested_func(pu)) 01486 p = "END MODULE"; 01487 else 01488 if (ST_is_block_data(PUINFO_FUNC_ST)) 01489 p = "END BLOCK DATA"; 01490 else 01491 p = "END SUBROUTINE"; 01492 } 01493 else 01494 p = "END FUNCTION"; 01495 } 01496 Append_Token_String(tokens,p); 01497 01498 if (W2F_Prompf_Emission) 01499 WN2F_End_Prompf_Transformed_Func(tokens,func_id); 01500 01501 Append_Token_Special(tokens, '\n'); 01502 } 01503 01504 } else { /* F77 routine */ 01505 01506 Append_Token_String(tokens, "END"); 01507 Append_Token_String(tokens, "!"); 01508 Append_Token_String(tokens, PUINFO_FUNC_NAME) ; 01509 01510 if (W2F_Prompf_Emission) 01511 WN2F_End_Prompf_Transformed_Func(tokens,func_id); 01512 01513 Append_Token_Special(tokens, '\n'); 01514 Append_Token_Special(tokens, '\n'); 01515 } 01516 } 01517