|
OpenADFortTk (basic)
|
00001 // -*-Mode: C++;-*- 00002 // $Header: /Volumes/cvsrep/developer/OpenADFortTk/src/whirl2xaif/wn2xaif_stmt.cxx,v 1.44 2006/05/12 16:12:23 utke Exp $ 00003 00004 #include <alloca.h> 00005 #include <sstream> 00006 00007 00008 #include "Open64IRInterface/Open64BasicTypes.h" 00009 #include "Open64IRInterface/IntrinsicInfo.h" 00010 #include "IntrinsicXlationTable.h" 00011 00012 #include "Args.h" 00013 #include "wn2xaif.h" 00014 #include "wn2xaif_stmt.h" 00015 #include "wn2xaif_mem.h" 00016 #include "wn2xaif_io.h" 00017 #include "st2xaif.h" 00018 #include "ty2xaif.h" 00019 00020 00021 using namespace whirl2xaif; 00022 using namespace xml; // for xml::ostream, etc 00023 00024 00025 static BOOL WN2F_Skip_Stmt(WN *wn) { return FALSE; /* FIXME */ } 00026 00027 00028 //*************************************************************************** 00029 // Passive Statements 00030 //*************************************************************************** 00031 void 00032 whirl2xaif::xlate_PassiveStmt(xml::ostream& xos, WN *wn_p, PUXlationContext& ctxt) { 00033 OPERATOR opr = WN_operator(wn_p); 00034 00035 // Short-circuit handling of the following: 00036 // NOTE: we could incorporate these two routines into this one 00037 switch (opr) { 00038 case OPR_GOTO: 00039 return xlate_GOTO(xos, wn_p, ctxt); 00040 case OPR_LABEL: 00041 return xlate_LABEL(xos, wn_p, ctxt); 00042 case OPR_IO: 00043 return xlate_IO(xos, wn_p, ctxt); 00044 default: 00045 break; 00046 } 00047 00048 // FIXME: cleanup AGOTO, RETURN, RETURN_VAL, PRAGMA, COMMENT, USE 00049 // INTRN_CASSIGNSTMT, INTRN_STOP, INTRN_STOP_F90, IO 00050 00051 if (opr==OPR_RETURN && WN_kid_count(wn_p) == 0) { // no kids 00052 // get the Parent 00053 WN* func_p=ctxt.findParentWN(ctxt.findParentBlockWN(wn_p)); 00054 // and see if it is the FUNC: 00055 if (WN_operator(func_p)==OPR_FUNC_ENTRY) { 00056 WN* last_p=WN_last(WN_kid(func_p,WN_kid_count(func_p)-1)); 00057 // if it is the last one: 00058 if (last_p==wn_p) 00059 return; 00060 // if it is not the last one, check if there is anything 00061 // else significant: 00062 WN* next_p=WN_next(wn_p); 00063 while (next_p!=0) { 00064 opr=WN_operator(next_p); 00065 if (opr != OPR_RETURN && opr != OPR_COMMENT) 00066 break; 00067 if (next_p==last_p) 00068 return; 00069 next_p=WN_next(next_p); 00070 } 00071 } 00072 USRCPOS srcpos; 00073 int aLineNumber; 00074 USRCPOS_srcpos(srcpos) = WN_Get_Linenum(wn_p); 00075 aLineNumber=USRCPOS_linenum(srcpos); 00076 if (!aLineNumber) { 00077 USRCPOS_srcpos(srcpos) = WN_Get_Linenum(func_p); 00078 aLineNumber=USRCPOS_linenum(srcpos); 00079 } 00080 FORTTK_MSG(1,"whirl2xaif::xlate_PassiveStmt: unstructured control flow (early return) related to line " << aLineNumber); 00081 } 00082 00083 if (opr==OPR_RETURN) { 00084 fortTkSupport::WNId stmtid = ctxt.findWNId(wn_p); 00085 xos << BegElem(XAIFStrings.elem_Marker()) 00086 << Attr("statement_id", stmtid) 00087 << BegAttr("annotation") << WhirlIdAnnotVal(stmtid) 00088 << StmtReturnAnnotVal(WN_label_number(wn_p)) << EndAttr 00089 << EndElem; 00090 } 00091 else { 00092 fortTkSupport::WNId stmtid = ctxt.findWNId(wn_p); 00093 xos << BegElem(XAIFStrings.elem_Marker()) 00094 << Attr("statement_id", stmtid) 00095 << BegAttr("annotation") << WhirlIdAnnotVal(stmtid) 00096 << " [passive: " << OPERATOR_name(opr) << "]" << EndAttr 00097 << EndElem; 00098 } 00099 } 00100 00101 00102 //*************************************************************************** 00103 // Structured Control Flow Statements: translation of these is 00104 // superceded by construction of the control flow graph. 00105 //*************************************************************************** 00106 00107 void 00108 whirl2xaif::xlate_BLOCK(xml::ostream& xos, WN *wn, PUXlationContext& ctxt) 00109 { 00110 FORTTK_ASSERT(WN_operator(wn) == OPR_BLOCK, fortTkSupport::Diagnostics::UnexpectedInput); 00111 00112 FORTTK_DIE(fortTkSupport::Diagnostics::Unimplemented); 00113 00114 } 00115 00116 00117 void 00118 whirl2xaif::WN2F_region(xml::ostream& xos, WN *wn, PUXlationContext& ctxt) 00119 { 00120 FORTTK_ASSERT(WN_operator(wn) == OPR_REGION, fortTkSupport::Diagnostics::UnexpectedInput); 00121 00122 FORTTK_DIE(fortTkSupport::Diagnostics::Unimplemented); 00123 00124 } 00125 00126 00127 void 00128 whirl2xaif::xlate_DO_LOOP(xml::ostream& xos, WN *wn, PUXlationContext& ctxt) 00129 { 00130 FORTTK_ASSERT(WN_operator(wn) == OPR_DO_LOOP, fortTkSupport::Diagnostics::UnexpectedInput); 00131 00132 FORTTK_DIE(fortTkSupport::Diagnostics::Unimplemented); 00133 00134 } 00135 00136 00137 void 00138 whirl2xaif::xlate_DO_WHILE(xml::ostream& xos, WN *wn, PUXlationContext& ctxt) 00139 { 00140 FORTTK_ASSERT(WN_operator(wn) == OPR_DO_WHILE, fortTkSupport::Diagnostics::UnexpectedInput); 00141 00142 FORTTK_DIE(fortTkSupport::Diagnostics::Unimplemented); 00143 00144 } 00145 00146 00147 void 00148 whirl2xaif::xlate_WHILE_DO(xml::ostream& xos, WN *wn, PUXlationContext& ctxt) 00149 { 00150 FORTTK_ASSERT(WN_operator(wn) == OPR_WHILE_DO, fortTkSupport::Diagnostics::UnexpectedInput); 00151 00152 FORTTK_DIE(fortTkSupport::Diagnostics::Unimplemented); 00153 00154 } 00155 00156 00157 void 00158 whirl2xaif::xlate_IF(xml::ostream& xos, WN *wn, PUXlationContext& ctxt) 00159 { 00160 FORTTK_ASSERT(WN_operator(wn) == OPR_IF, fortTkSupport::Diagnostics::UnexpectedInput); 00161 00162 FORTTK_DIE(fortTkSupport::Diagnostics::Unimplemented); 00163 00164 } 00165 00166 00167 //*************************************************************************** 00168 // Unstructured Control Flow Statements 00169 //*************************************************************************** 00170 00171 void 00172 whirl2xaif::WN2F_implied_do(xml::ostream& xos, WN *wn, PUXlationContext& ctxt) 00173 { 00174 // REMOVE 00175 FORTTK_ASSERT(ctxt.currentXlationContext().isFlag(XlationContext::IO_STMT), 00176 fortTkSupport::Diagnostics::UnexpectedInput); 00177 00178 /* This is a fortran implied do_loop, which can only occur as an 00179 * an OPR_IO_ITEM. We should always be able to regenerate 00180 * an implied do-loop from this WHIRL tree, and we should safely 00181 * be able to assert that IO_STMT is TRUE. Strictly 00182 * speaking this can be viewed as an expression, rather than as a 00183 * statement, but due to the commonality with regular do-loops 00184 * we handle it in this module. 00185 */ 00186 00187 /* Start an implied do-loop expression */ 00188 xos << '('; 00189 00190 /* Generate all the expression trees, separated by commas */ 00191 for (INT kid = 4; kid < WN_kid_count(wn); kid++) { 00192 BOOL emitted = xlate_IO_ITEM(xos, WN_kid(wn, kid), ctxt); 00193 if (emitted) 00194 xos << ","; 00195 } 00196 00197 /* Generate the loop expression */ 00198 ST* idx_name = WN_st(WN_index(wn)); 00199 xlate_SymRef(xos, idx_name, /* base-symbol */ 00200 Stab_Pointer_To(ST_type(idx_name)), /* base-type */ 00201 ST_type(idx_name), /* object-type */ 00202 0, /* object-ofst */ 00203 ctxt); 00204 xos << '='; 00205 TranslateWN(xos, WN_start(wn), ctxt); 00206 xos << ','; 00207 TranslateWN(xos, WN_end(wn), ctxt); 00208 xos << ','; 00209 TranslateWN(xos, WN_step(wn), ctxt); 00210 00211 /* Terminate the implied do-loop expression */ 00212 xos << ')'; 00213 00214 00215 } /* WN2F_implied_do */ 00216 00217 00218 void 00219 whirl2xaif::WN2F_noio_implied_do(xml::ostream& xos, WN *wn, PUXlationContext& ctxt) 00220 { 00221 xos << "("; 00222 TranslateWN(xos,WN_kid0(wn),ctxt); 00223 xos << ","; 00224 TranslateWN(xos,WN_kid1(wn),ctxt); 00225 xos << "="; 00226 00227 INT numkids = 5; 00228 for (INT kid = 2;kid<numkids; kid++) { 00229 TranslateWN(xos,WN_kid(wn,kid),ctxt); 00230 if (kid < numkids-1) 00231 xos << ","; 00232 } 00233 00234 xos << ")"; 00235 00236 } 00237 00238 00239 void 00240 whirl2xaif::xlate_GOTO(xml::ostream& xos, WN *wn, PUXlationContext& ctxt) 00241 { 00242 FORTTK_ASSERT(WN_operator(wn) == OPR_GOTO || 00243 WN_operator(wn) == OPR_REGION_EXIT, fortTkSupport::Diagnostics::UnexpectedInput); 00244 00245 fortTkSupport::WNId stmtid = ctxt.findWNId(wn); 00246 xos << BegElem(XAIFStrings.elem_Marker()) 00247 << Attr("statement_id", stmtid) 00248 << BegAttr("annotation") << WhirlIdAnnotVal(stmtid) 00249 << StmtGotoAnnotVal(WN_label_number(wn)) << EndAttr 00250 << EndElem; 00251 } 00252 00253 00254 void 00255 whirl2xaif::xlate_SWITCH(xml::ostream& xos, WN *wn, PUXlationContext& ctxt) 00256 { 00257 FORTTK_ASSERT(WN_operator(wn) == OPR_SWITCH, fortTkSupport::Diagnostics::UnexpectedInput); 00258 00259 FORTTK_DIE(fortTkSupport::Diagnostics::Unimplemented); 00260 00261 } 00262 00263 00264 void 00265 whirl2xaif::WN2F_casegoto(xml::ostream& xos, WN *wn, PUXlationContext& ctxt) 00266 { 00267 // REMOVE 00268 ST *st; 00269 st = WN_st(wn); 00270 00271 xos << std::endl; 00272 // xos << "CASE"; 00273 xos << "IF ("; 00274 TranslateSTUse(xos, st, ctxt); 00275 std::string val = TCON2F_translate(Host_To_Targ(MTYPE_I4,WN_const_val(wn)), 00276 FALSE); 00277 xos << " .EQ. " << val << ')' << " GO TO " << WN_label_number(wn); 00278 00279 } 00280 00281 void 00282 whirl2xaif::WN2F_agoto(xml::ostream& xos, WN *wn, PUXlationContext& ctxt) 00283 { 00284 // REMOVE 00285 FORTTK_ASSERT(WN_operator(wn) == OPR_AGOTO, fortTkSupport::Diagnostics::UnexpectedInput); 00286 00287 fortTkSupport::WNId stmtid = ctxt.findWNId(wn); 00288 xos << BegElem(XAIFStrings.elem_Marker()) 00289 << Attr("statement_id", stmtid) 00290 << BegAttr("annotation") << WhirlIdAnnotVal(stmtid) 00291 << " [***FIXME: agoto]" << EndAttr 00292 << EndElem; 00293 00294 xos << std::endl << "GO TO"; 00295 TranslateWN(xos, WN_kid0(wn), ctxt); // FIXME 00296 00297 00298 } /* WN2F_agoto */ 00299 00300 00301 void 00302 whirl2xaif::xlate_condBR(xml::ostream& xos, WN *wn, PUXlationContext& ctxt) 00303 { 00304 OPERATOR opr = WN_operator(wn); 00305 FORTTK_ASSERT(opr == OPR_TRUEBR || opr == OPR_FALSEBR, 00306 fortTkSupport::Diagnostics::UnexpectedInput); 00307 00308 FORTTK_DIE(fortTkSupport::Diagnostics::Unimplemented); 00309 00310 } 00311 00312 00313 void 00314 whirl2xaif::xlate_RETURN(xml::ostream& xos, WN *wn, PUXlationContext& ctxt) 00315 { 00316 FORTTK_ASSERT(WN_operator(wn) == OPR_RETURN, fortTkSupport::Diagnostics::UnexpectedInput); 00317 // for now: 00318 FORTTK_DIE(fortTkSupport::Diagnostics::Unimplemented); 00319 } 00320 00321 00322 void 00323 whirl2xaif::xlate_RETURN_VAL(xml::ostream& xos, WN *wn, PUXlationContext& ctxt) 00324 { 00325 FORTTK_ASSERT(WN_operator(wn) == OPR_RETURN_VAL, fortTkSupport::Diagnostics::UnexpectedInput); 00326 00327 fortTkSupport::WNId stmtid = ctxt.findWNId(wn); 00328 xos << BegElem(XAIFStrings.elem_Marker()) 00329 << Attr("statement_id", stmtid) 00330 << BegAttr("annotation") << WhirlIdAnnotVal(stmtid) 00331 << " [return_val]" << EndAttr 00332 << EndElem; 00333 00334 00335 } 00336 00337 00338 void 00339 whirl2xaif::xlate_LABEL(xml::ostream& xos, WN *wn, PUXlationContext& ctxt) 00340 { 00341 FORTTK_ASSERT(WN_operator(wn) == OPR_LABEL, fortTkSupport::Diagnostics::UnexpectedInput); 00342 00343 fortTkSupport::WNId stmtid = ctxt.findWNId(wn); 00344 xos << BegElem(XAIFStrings.elem_Marker()) 00345 << Attr("statement_id", stmtid) 00346 << BegAttr("annotation") << WhirlIdAnnotVal(stmtid) 00347 << StmtLabelAnnotVal(WN_label_number(wn)) << EndAttr 00348 << EndElem; 00349 00350 00351 } 00352 00353 00354 //*************************************************************************** 00355 // Calls 00356 //*************************************************************************** 00357 00358 void 00359 whirl2xaif::xlate_CALL(xml::ostream& xos, WN *wn, PUXlationContext& ctxt) { 00360 // XAIF distinguishes between a subroutine call (statement) and 00361 // function call (expression). 00362 // FIXME: this is a nearly incomprehensible function. I've cleaned 00363 // it up a little, but it needs a lot more work. 00364 /* Generates a function-call and ensures that the return value 00365 * is returned into the appropriate context, be it a variable 00366 * or a register. Note that intrinsic calls are dispatched to 00367 * this function from xlate_INTRINSIC_CALL() when appropriate. 00368 * Make sure the handling of instrinsic ops in wn2f_expr.c is 00369 * kept up to date with changes that occur here. 00370 */ 00371 // We can't handle ICALLs yet 00372 OPERATOR opr = WN_operator(wn); 00373 FORTTK_ASSERT(opr != OPR_ICALL, fortTkSupport::Diagnostics::UnexpectedInput); 00374 // ------------------------------------------------------- 00375 // Gather info... 00376 // ------------------------------------------------------- 00377 TY_IDX return_ty = WN_Call_Return_Type(wn); 00378 INT first_arg_idx = WN_Call_First_Arg_Idx(wn); 00379 INT last_arg_idx = WN_Call_Last_Arg_Idx(wn); 00380 BOOL is_user_call = FALSE; 00381 BOOL is_allocate_stmt = FALSE; 00382 if (opr == OPR_CALL) { 00383 is_user_call = TRUE; 00384 const char* nm = ST_name(WN_st(wn)); 00385 if (strcmp(nm, "_ALLOCATE") == 0) { 00386 xlate_PassiveStmt(xos,wn,ctxt); 00387 // cut short here 00388 return; 00389 is_allocate_stmt = TRUE; 00390 } else if (strcmp(nm, "_DEALLOCATE") == 0) { 00391 xlate_PassiveStmt(xos,wn,ctxt); 00392 // cut short here 00393 return; 00394 ctxt.currentXlationContext().setFlag(XlationContext::HAS_NO_ARR_ELMT); 00395 is_allocate_stmt = TRUE; 00396 } else if (strcmp(nm, "PRESENT") == 0) { 00397 ctxt.currentXlationContext().setFlag(XlationContext::HAS_NO_ARR_ELMT); 00398 } 00399 } else if (opr == OPR_PICCALL) { 00400 is_user_call = TRUE; 00401 } 00402 enum CallKind_E{SUBROUTINE_CALL, 00403 FUNCTION_CALL, 00404 INTRINSIC_CALL}; 00405 CallKind_E xlate_as=SUBROUTINE_CALL; // default 00406 UINT targid = 0; // (FIXME) 00407 // ------------------------------------------------------- 00408 // Determine the number of implicit arguments appended to the end 00409 // of the argument list (i.e. string lengths). 00410 INT total_implicit_args = 0; 00411 TY_IDX arg_ty, kid_ty, parm_ty; 00412 TYPE_ID fmtry; 00413 for (INT arg_idx = first_arg_idx; 00414 arg_idx <= last_arg_idx - total_implicit_args; 00415 arg_idx++) { 00416 if (WN_kid(wn, arg_idx) != NULL) { 00417 OPCODE tempopc = WN_opcode(WN_kid(wn, arg_idx)); 00418 WN* kidofparm = WN_kid0(WN_kid(wn, arg_idx)); 00419 if (WN_operator(kidofparm) != OPR_CALL && 00420 WN_operator(kidofparm) != OPR_INTRINSIC_CALL) { 00421 arg_ty = WN_Tree_Type(WN_kid(wn, arg_idx)); 00422 parm_ty = WN_ty(WN_kid(wn,arg_idx)); 00423 if (TY_Is_Pointer(arg_ty)) { 00424 fmtry = TY_mtype(TY_pointed(arg_ty)); 00425 } 00426 else { 00427 fmtry = TY_mtype(arg_ty); 00428 } 00429 if (fmtry == MTYPE_M) { 00430 if (TY_Is_Pointer(parm_ty)) { // FIXME: hack to handle KIND_STRUCT 00431 fmtry = TY_pointed(parm_ty); 00432 fmtry = TY_mtype(fmtry); 00433 } 00434 } 00435 if ( 00436 (TY_Is_Character_Reference(arg_ty) 00437 || 00438 TY_Is_Chararray_Reference(arg_ty) 00439 || 00440 ( 00441 (TY_Is_Pointer(arg_ty) 00442 && 00443 TY_mtype(TY_pointed(arg_ty))==MTYPE_M) 00444 && 00445 (TY_Is_Character_Reference(parm_ty) 00446 || 00447 TY_Is_Chararray_Reference(parm_ty))) 00448 ) 00449 && !is_allocate_stmt) { 00450 total_implicit_args++; 00451 } 00452 } 00453 else { /* the argument is function call 00454 * if the return value is Chararray or Character Reference: 00455 */ 00456 if (WN_operator(kidofparm) == OPR_CALL) { 00457 kid_ty = PU_prototype (Pu_Table[ST_pu(WN_st(kidofparm))]); 00458 if (Func_Return_Character (kid_ty)) 00459 total_implicit_args++; 00460 } 00461 else { 00462 if (WN_operator(kidofparm) == OPR_INTRINSIC_CALL && 00463 WN_intrinsic(kidofparm) == INTRN_CONCATEXPR) 00464 total_implicit_args++; 00465 } 00466 } 00467 } 00468 } 00469 if (opr == OPR_INTRINSIC_CALL) { 00470 // xlate_INTRINSIC_CALL() has already handled certain intrinsics (FIXME) 00471 // ... only consider returns through a first non-string parameter here 00472 const char* inm = IntrinsicInfo::intrinsicBaseName(WN_intrinsic(wn)); 00473 fortTkSupport::IntrinsicXlationTable::XAIFInfoPair infoPair(Whirl2Xaif::getIntrinsicXlationTable().findXAIFInfo(opr, inm)); 00474 xlate_as = INTRINSIC_CALL; 00475 targid = ctxt.currentXlationContext().getNewVertexId(); 00476 xos << BegElem("xaif:Intrinsic") 00477 << Attr("vertex_id", targid) << Attr("name", infoPair.second.name) 00478 << Attr("type", "***"); 00479 TY_IDX result_ty=WN_GetExprType(wn); 00480 bool isPointer = TY_Is_Pointer(result_ty) || TY_is_f90_pointer(result_ty); 00481 bool isFnPointer = isPointer && (TY_kind(TY_pointed(result_ty)) == KIND_FUNCTION); 00482 const char* ty_str = 00483 (isPointer && (!isFnPointer)) ? TranslateTYToSymType(TY_pointed(result_ty)) 00484 : TranslateTYToSymType(result_ty); 00485 if (!ty_str) { ty_str = "***"; } 00486 const char* shape_str = 00487 (isPointer && (!isFnPointer)) ? TranslateTYToSymShape(TY_pointed(result_ty)) 00488 : TranslateTYToSymShape(result_ty); 00489 if (strcmp(ty_str,"real")) 00490 xos << xml::Attr("rType", ty_str); 00491 if (strcmp(shape_str,"scalar")) 00492 xos << xml::Attr("rShape", shape_str); 00493 xos << EndElem; 00494 } 00495 else { 00496 // Could translate as an XAIF SubroutineCall, FunctionCall or Intrinsic 00497 // OPR_ICALL: TranslateWN(xos, WN_kid(wn, WN_kid_count(wn) - 1), ctxt); 00498 ST* st = WN_st(wn); 00499 ST_TAB* sttab = Scope_tab[ST_level(st)].st_tab; 00500 fortTkSupport::SymTabId scopeid = ctxt.findSymTabId(sttab); 00501 const char* funcNm = ST_name(st); 00502 fortTkSupport::IntrinsicXlationTable::XAIFInfoPair infoPair(Whirl2Xaif::getIntrinsicXlationTable(). 00503 findXAIFInfo(opr, 00504 funcNm, 00505 false)); // don't complain if it is not there 00506 if (infoPair.first) { 00507 // Intrinsic 00508 xlate_as = INTRINSIC_CALL; 00509 targid = ctxt.currentXlationContext().getNewVertexId(); 00510 xos << BegElem("xaif:Intrinsic") 00511 << Attr("vertex_id", targid) << Attr("name", infoPair.second.name) 00512 << Attr("type", "***"); 00513 if (infoPair.second.key) { xos << IntrinsicKeyAnnot(infoPair.second.key); } 00514 TY_IDX result_ty=WN_GetExprType(wn); 00515 bool isPointer = TY_Is_Pointer(result_ty) || TY_is_f90_pointer(result_ty); 00516 bool isFnPointer = isPointer && (TY_kind(TY_pointed(result_ty)) == KIND_FUNCTION); 00517 const char* ty_str = 00518 (isPointer && (!isFnPointer)) ? TranslateTYToSymType(TY_pointed(result_ty)) 00519 : TranslateTYToSymType(result_ty); 00520 if (!ty_str) { ty_str = "***"; } 00521 const char* shape_str = 00522 (isPointer && (!isFnPointer)) ? TranslateTYToSymShape(TY_pointed(result_ty)) 00523 : TranslateTYToSymShape(result_ty); 00524 if (strcmp(ty_str,"real")) 00525 xos << xml::Attr("rType", ty_str); 00526 if (strcmp(shape_str,"scalar")) 00527 xos << xml::Attr("rShape", shape_str); 00528 xos << EndElem; 00529 } else if (return_ty != (TY_IDX)0 && TY_kind(return_ty) != KIND_VOID) { 00530 // FunctionCall 00531 xlate_as = FUNCTION_CALL; 00532 // JU: for now: 00533 USRCPOS srcpos; 00534 USRCPOS_srcpos(srcpos) = WN_Get_Linenum(wn); 00535 if(!USRCPOS_linenum(srcpos)) { 00536 WN* parWN=ctxt.findParentWN(wn); 00537 if (parWN) { 00538 USRCPOS_srcpos(srcpos) = WN_Get_Linenum(parWN); 00539 while (!USRCPOS_linenum(srcpos) && parWN) { 00540 parWN=ctxt.findParentWN(parWN); 00541 USRCPOS_srcpos(srcpos) = WN_Get_Linenum(parWN); 00542 } 00543 } 00544 } 00545 FORTTK_DIE("whirl2xaif::xlate_CALL: call to function: " 00546 << funcNm 00547 << " near line " 00548 << USRCPOS_linenum(srcpos) 00549 << " is not supported! This should either be recognized as an intrinsic or should have been canonicalized into a subroutine call"); 00550 // we leave the rest of the code as is... 00551 xos << BegElem("xaif:FunctionCall") 00552 << Attr("vertex_id", ctxt.currentXlationContext().getNewVertexId()) 00553 << Attr("scope_id", scopeid) << AttrSymId(st); 00554 } else { 00555 // std::cout << "last " << last_arg_idx << " first " << first_arg_idx << " impl " << total_implicit_args << std::endl; 00556 // SubroutineCall 00557 USRCPOS srcpos; 00558 USRCPOS_srcpos(srcpos) = WN_Get_Linenum(wn); 00559 xlate_as = SUBROUTINE_CALL; 00560 xos << BegElem("xaif:SubroutineCall") 00561 << Attr("statement_id", ctxt.findWNId(wn)) 00562 << Attr("scope_id", scopeid) 00563 << Attr("lineNumber",USRCPOS_linenum(srcpos)) 00564 << Attr("formalArgCount",last_arg_idx-first_arg_idx-total_implicit_args+1) 00565 << AttrSymId(st); 00566 } 00567 } 00568 // Append the argument list to the function reference, skipping 00569 // implicit character-string-length arguments assumed to be the 00570 // last ones in the list (see also ST2F_func_header()). Note 00571 // that we should not need to use any special-casing for 00572 // ADRTMP or VALTMP OPR_INTRINSIC_OP nodes, as these should be 00573 // handled appropriately by TranslateWN(). 00574 BOOL has_stat = FALSE; 00575 BOOL first_nonemptyarg = FALSE; 00576 INT implicit_args; 00577 UINT position = 0; // invalid position id 00578 UINT srcid = 0; // used for intrinsics (FIXME) 00579 for (INT arg_idx = first_arg_idx, implicit_args = 0; 00580 arg_idx <= last_arg_idx - implicit_args; 00581 arg_idx++) { 00582 position++; // need to account for optional parameters (when not present they are represented a NULL nodes) 00583 if (WN_kid(wn, arg_idx) != NULL) { 00584 WN* kidofparm = WN_kid0(WN_kid(wn, arg_idx)); 00585 if (WN_operator(kidofparm) != OPR_CALL) 00586 arg_ty = WN_Tree_Type(WN_kid(wn, arg_idx)); 00587 else 00588 arg_ty = PU_prototype (Pu_Table[ST_pu(WN_st(kidofparm))]); 00589 if (xlate_as == SUBROUTINE_CALL || xlate_as == FUNCTION_CALL) { 00590 xos << BegElem("xaif:Argument"); 00591 if (xlate_as == SUBROUTINE_CALL) { 00592 xos << Attr("position", position); 00593 } 00594 if ((WN_kid(wn, arg_idx))->u3.ty_fields.ty) { // hack for keyword call 00595 xos << BegAttr("annotation") 00596 << SymIdAnnotVal((WN_kid(wn, arg_idx))->u3.ty_fields.ty) 00597 << EndAttr; 00598 } 00599 ctxt.createXlationContext(XlationContext::NOFLAG, kidofparm);// implicit for Argument 00600 } 00601 // FIXME 00602 if (opr == OPR_INTRINSIC_CALL && 00603 INTRN_by_value(WN_intrinsic(wn))) { 00604 /* Call-by value, but argument should be emitted without the 00605 * %val() qualifier. */ 00606 first_nonemptyarg = TRUE; 00607 srcid = ctxt.currentXlationContext().peekVertexId(); // used for intrinsics 00608 TranslateWN(xos, WN_kid(wn, arg_idx), ctxt); 00609 } 00610 else if ((WN_operator(kidofparm) != OPR_CALL 00611 && (TY_Is_Character_Reference(arg_ty) 00612 || ((TY_Is_Pointer(arg_ty) 00613 && TY_mtype(TY_pointed(arg_ty))==MTYPE_M) 00614 && (TY_Is_Character_Reference(parm_ty) 00615 || TY_Is_Chararray_Reference(parm_ty)))) 00616 || WN_operator(kidofparm)==OPR_CALL 00617 && Func_Return_Character(arg_ty) ) 00618 && !is_allocate_stmt) { 00619 /* Handle substring arguments here. These are always assumed 00620 * to be passed by reference. For a function result, the length 00621 * follows the address - does this look like char fn result? 00622 * can't tell, but make good guess.. 00623 */ 00624 INT len_idx; 00625 INT cur_idx = arg_idx; 00626 implicit_args++; 00627 if ((is_user_call) && (cur_idx == first_arg_idx) 00628 && (cur_idx == first_arg_idx) 00629 && (WN_kid_count(wn) >= cur_idx + 2) 00630 && (WN_kid(wn,cur_idx+1) != NULL) 00631 && (WN_Parm_By_Value(WN_kid(wn,cur_idx + 1))) 00632 && ((return_ty != 0) && (TY_kind(return_ty) == KIND_VOID))) { 00633 len_idx = cur_idx + 1; 00634 } else { 00635 len_idx = last_arg_idx - (total_implicit_args - implicit_args); 00636 } 00637 if ( !(first_nonemptyarg && !has_stat) ) 00638 has_stat = FALSE; 00639 first_nonemptyarg = TRUE; 00640 srcid=ctxt.currentXlationContext().peekVertexId(); 00641 WN2F_String_Argument(xos, WN_kid(wn, cur_idx), /* string base */ 00642 WN_kid(wn, len_idx), /* string length */ 00643 ctxt); 00644 } 00645 else if (!TY_Is_Pointer(arg_ty) 00646 || 00647 ((WN_operator(kidofparm) == OPR_INTRINSIC_OP 00648 || 00649 WN_operator(kidofparm) == OPR_INTRINSIC_CALL) 00650 && 00651 INTR_is_valtmp(WN_intrinsic(kidofparm))) 00652 || 00653 WN_operator(kidofparm) == OPR_ARRAYEXP) { 00654 // Need to explicitly note this as a value parameter. 00655 if (WN_operator(kidofparm) == OPR_INTRINSIC_CALL && 00656 WN_intrinsic(kidofparm) == INTRN_CONCATEXPR) 00657 implicit_args++; 00658 /*parser always generate an extra arg for concat operator*/ 00659 if ( !(first_nonemptyarg && !has_stat) ) 00660 has_stat = FALSE; 00661 first_nonemptyarg = TRUE; 00662 srcid = ctxt.currentXlationContext().peekVertexId(); 00663 TranslateWN(xos, WN_kid(wn, arg_idx), ctxt); 00664 } 00665 else { /* TY_Is_Pointer(arg_ty) */ 00666 /* There is also an implicit string length when the argument 00667 * is an array of character strings. */ 00668 if (TY_Is_Chararray_Reference(arg_ty) && !is_allocate_stmt) 00669 implicit_args++; 00670 /* Assume call-by-reference parameter passing */ 00671 if ( !(first_nonemptyarg && !has_stat) ) 00672 has_stat = FALSE; 00673 first_nonemptyarg = TRUE; 00674 srcid = ctxt.currentXlationContext().peekVertexId(); 00675 WN* ctxtRefWN=0; 00676 if (ctxt.currentXlationContext().hasWN()) 00677 ctxtRefWN=ctxt.currentXlationContext().getWN(); 00678 ctxt.currentXlationContext().setWN(WN_kid(wn, arg_idx)); 00679 xlate_MemRef(xos, 00680 WN_kid(wn, arg_idx), /* address expression */ 00681 arg_ty, /* address type */ 00682 TY_pointed(arg_ty), /* object type */ 00683 0, /* offset from address */ 00684 ctxt); 00685 if (ctxtRefWN) 00686 ctxt.currentXlationContext().setWN(ctxtRefWN); 00687 } 00688 if ((arg_idx+implicit_args) == (last_arg_idx-1)) { 00689 if (opr == OPR_CALL && is_allocate_stmt) { 00690 if (WN_operator(WN_kid0(WN_kid(wn, last_arg_idx))) == OPR_LDA) { 00691 // xos << ","; 00692 xos << "STAT="; 00693 has_stat=TRUE; 00694 } else { 00695 arg_idx++; 00696 } 00697 } 00698 } 00699 if (xlate_as == SUBROUTINE_CALL || xlate_as == FUNCTION_CALL) { 00700 ctxt.deleteXlationContext(); // end Argument context 00701 xos << EndElem; // End Argument 00702 } else { 00703 // Intrinsic: create an edge 00704 DumpExprGraphEdge(xos, ctxt.currentXlationContext().getNewEdgeId(), srcid, targid, position); 00705 } 00706 } // non-null argument 00707 } // loop over arguments 00708 ctxt.currentXlationContext().unsetFlag(XlationContext::HAS_NO_ARR_ELMT); 00709 if (xlate_as == SUBROUTINE_CALL || xlate_as == FUNCTION_CALL) 00710 xos << EndElem; 00711 } /* xlate_CALL */ 00712 00713 00714 void 00715 whirl2xaif::xlate_INTRINSIC_CALL(xml::ostream& xos, WN *wn, 00716 PUXlationContext& ctxt) 00717 { 00718 // Handles all intrinsics that are translated into XAIF statements 00719 00720 FORTTK_ASSERT(WN_operator(wn) == OPR_INTRINSIC_CALL, 00721 fortTkSupport::Diagnostics::UnexpectedInput); 00722 00723 WN *arg_expr; 00724 TY_IDX arg_ty; 00725 INT str_kid, length_kid, first_length_kid; 00726 BOOL regular_call = FALSE; /* Specially treated intrinsic call? */ 00727 00728 fortTkSupport::WNId wnid = ctxt.findWNId(wn); 00729 00730 switch (WN_intrinsic(wn)) { 00731 case INTRN_CONCATEXPR: 00732 /* In the context of an IO statement, emit the concatenation 00733 * but disregard the temporary result buffer. */ 00734 00735 /* Determine the range of kids denoting the base of the string- 00736 * arguments and the the length of these strings respectively. */ 00737 str_kid = 1; 00738 length_kid = first_length_kid = (WN_kid_count(wn) + 2)/2; 00739 00740 /* Emit the concatenation operations */ 00741 WN2F_String_Argument(xos, 00742 WN_kid(wn, str_kid), /* base of string1 */ 00743 WN_kid(wn, length_kid), /* length of string1 */ 00744 ctxt); 00745 while ((++str_kid) < first_length_kid) { 00746 length_kid++; 00747 xos << "//"; 00748 WN2F_String_Argument(xos, 00749 WN_kid(wn, str_kid), /* base of stringN */ 00750 WN_kid(wn, length_kid), /* length of stringN */ 00751 ctxt); 00752 } 00753 break; 00754 00755 case INTRN_CASSIGNSTMT: 00756 // string assignment 00757 // kid 0, 2: base of and length of destination; kid 1, 3: same, for source 00758 //WN2F_String_Argument(xos, WN_kid(wn,0), WN_kid(wn,2), ctxt); 00759 //WN2F_String_Argument(xos, WN_kid(wn,1), WN_kid(wn,3), ctxt); 00760 xos << BegElem(XAIFStrings.elem_Marker()) 00761 << Attr("statement_id", wnid) 00762 << BegAttr("annotation") << WhirlIdAnnotVal(wnid) 00763 << " [cassignstmt]" << EndAttr << EndElem; 00764 break; 00765 00766 case INTRN_STOP: 00767 case INTRN_STOP_F90: 00768 // Either the F90 or F77 stop 00769 xos << BegElem(XAIFStrings.elem_Marker()) 00770 << Attr("statement_id", wnid) 00771 << BegAttr("annotation") << WhirlIdAnnotVal(wnid) 00772 << " [stop]" << EndAttr << EndElem; 00773 break; 00774 00775 default: 00776 regular_call = TRUE; 00777 xlate_CALL(xos, wn, ctxt); 00778 break; 00779 } 00780 00781 00782 } /* xlate_INTRINSIC_CALL */ 00783 00784 00785 //*************************************************************************** 00786 // Other Statements 00787 //*************************************************************************** 00788 00789 void 00790 whirl2xaif::WN2F_eval(xml::ostream& xos, WN *wn, PUXlationContext& ctxt) 00791 { 00792 /* This generates code that will not recompile. Short of 00793 * some kind of surrounding statement there is no way to do 00794 * this in Fortran-77. 00795 */ 00796 FORTTK_ASSERT(WN_operator(wn) == OPR_EVAL, fortTkSupport::Diagnostics::UnexpectedInput); 00797 00798 xos << "CALL _EVAL("; 00799 TranslateWN(xos, WN_kid0(wn), ctxt); 00800 xos << ')'; 00801 00802 00803 } /* WN2F_eval */ 00804 00805 00806 void 00807 whirl2xaif::xlate_PRAGMA(xml::ostream& xos, WN *wn, PUXlationContext& ctxt) 00808 { 00809 FORTTK_ASSERT(WN_operator(wn) == OPR_PRAGMA || 00810 WN_operator(wn) == OPR_XPRAGMA, fortTkSupport::Diagnostics::UnexpectedInput); 00811 00812 // switch (WN_pragma(apragma)) 00813 fortTkSupport::WNId stmtid = ctxt.findWNId(wn); 00814 xos << BegElem(XAIFStrings.elem_Marker()) 00815 << Attr("statement_id", stmtid) 00816 << BegAttr("annotation") << WhirlIdAnnotVal(stmtid) 00817 << " [pragma]" << EndAttr << EndElem; 00818 00819 00820 } 00821 00822 00823 void 00824 whirl2xaif::xlate_PREFETCH(xml::ostream& xos, WN *wn, PUXlationContext& ctxt) 00825 { 00826 FORTTK_ASSERT(WN_operator(wn) == OPR_PREFETCH || 00827 WN_operator(wn) == OPR_PREFETCHX, fortTkSupport::Diagnostics::UnexpectedInput); 00828 00829 00830 } 00831 00832 00833 void 00834 whirl2xaif::xlate_COMMENT(xml::ostream& xos, WN *wn, PUXlationContext& ctxt) 00835 { 00836 FORTTK_ASSERT(WN_operator(wn) == OPR_COMMENT, fortTkSupport::Diagnostics::UnexpectedInput); 00837 00838 // Note: Index_To_Str(WN_GetComment(wn)) returns comment text 00839 fortTkSupport::WNId stmtid = ctxt.findWNId(wn); 00840 xos << BegElem(XAIFStrings.elem_Marker()) 00841 << Attr("statement_id", stmtid) 00842 << BegAttr("annotation") << WhirlIdAnnotVal(stmtid) 00843 << " [comment]" << EndAttr << EndElem; 00844 00845 00846 } 00847 00848 void 00849 whirl2xaif::WN2F_dealloca(xml::ostream& xos, WN *wn, PUXlationContext& ctxt) 00850 { 00851 FORTTK_ASSERT(WN_operator(wn) == OPR_DEALLOCA, fortTkSupport::Diagnostics::UnexpectedInput); 00852 00853 INT16 n,i; 00854 n = WN_kid_count(wn); 00855 00856 xos << std::endl << "CALL OPR_DEALLOCA("; 00857 i = 0 ; 00858 while (i < n) { 00859 TranslateWN(xos,WN_kid(wn,i),ctxt); 00860 if (++i < n) 00861 xos << ","; 00862 } 00863 xos << ")"; 00864 00865 00866 } /* WN2F_dealloca */ 00867 00868 00869 void 00870 whirl2xaif::xlate_USE(xml::ostream& xos, WN *wn, PUXlationContext& ctxt) 00871 { 00872 FORTTK_ASSERT(WN_operator(wn) == OPR_USE, fortTkSupport::Diagnostics::UnexpectedInput); 00873 00874 fortTkSupport::WNId stmtid = ctxt.findWNId(wn); 00875 const char* nm = ST_name(WN_st(wn)); 00876 xos << BegElem(XAIFStrings.elem_Marker()) 00877 << Attr("statement_id", stmtid) 00878 << BegAttr("annotation") << WhirlIdAnnotVal(stmtid) 00879 << " [use " << nm << "]" << EndAttr << EndElem; 00880 00881 00882 } 00883 00884 00885 void 00886 whirl2xaif::WN2F_namelist_stmt(xml::ostream& xos, WN *wn, PUXlationContext& ctxt) 00887 { 00888 FORTTK_ASSERT(WN_operator(wn) == OPR_NAMELIST, fortTkSupport::Diagnostics::UnexpectedInput); 00889 00890 const char *st_name = ST_name(WN_st(wn)); 00891 if (ST_is_external(WN_st(wn))) { 00892 ; 00893 } else { 00894 xos << "NAMELIST /" << st_name << " /"; 00895 int k ; 00896 for(k=0;k< WN_kid_count(wn);k++ ) { 00897 st_name = ST_name(WN_st(WN_kid(wn,k))); 00898 Set_BE_ST_w2fc_referenced(WN_st(WN_kid(wn,k))); 00899 if (k==0) 00900 ; 00901 else 00902 xos << ","; 00903 xos << st_name; 00904 } 00905 } 00906 00907 00908 } //WN2F_namelist_stmt 00909 00910 00911 void 00912 whirl2xaif::WN2F_implicit_bnd(xml::ostream& xos, WN *wn, PUXlationContext& ctxt) 00913 { 00914 xos << "[+-+]"; 00915 00916 } 00917 00918 00919 void 00920 whirl2xaif::WN2F_nullify_stmt(xml::ostream& xos, WN *wn, PUXlationContext& ctxt) 00921 { 00922 FORTTK_ASSERT(WN_operator(wn) == OPR_NULLIFY, fortTkSupport::Diagnostics::UnexpectedInput); 00923 00924 int k ; 00925 const char *st_name; 00926 00927 xos << "NULLIFY ("; 00928 for(k=0;k< WN_kid_count(wn);k++ ) { 00929 st_name = ST_name(WN_st(WN_kid(wn,k))); 00930 Set_BE_ST_w2fc_referenced(WN_st(WN_kid(wn,k))); 00931 if (k!=0) 00932 xos << ","; 00933 xos << st_name; 00934 00935 } 00936 xos << ")"; 00937 00938 00939 } //WN2F_namelist_stmt 00940 00941 00942 void 00943 whirl2xaif::WN2F_interface_blk(xml::ostream& xos, WN *wn, PUXlationContext& ctxt) 00944 { 00945 FORTTK_ASSERT(WN_operator(wn) == OPR_INTERFACE, fortTkSupport::Diagnostics::UnexpectedInput); 00946 00947 int k ; 00948 ST **param_st; 00949 ST *st = WN_st(wn); 00950 ST *rslt = NULL; 00951 INT param,num_params; 00952 INT first_param; 00953 TY_IDX return_ty; 00954 INT implicit = 0 ; 00955 00956 const char *intface_name = ST_name(st); 00957 if (ST_is_external(WN_st(wn))) { 00958 ; 00959 } else { 00960 xos << std::endl; 00961 xos << "interface "; 00962 00963 if (ST_is_assign_interface(st)) { 00964 xos << "assignment ("; 00965 } 00966 00967 if (ST_is_operator_interface(st) || ST_is_u_operator_interface(st)){ 00968 xos << "operator ("; 00969 } 00970 00971 if (ST_is_u_operator_interface(st)) 00972 xos << "."; 00973 00974 #if 0 00975 static const char unnamed_interface[] = "unnamed interface"; 00976 if (strcmp(intface_name,unnamed_interface)) 00977 Append_Token_String(xos, intface_name); 00978 #endif 00979 00980 if (ST_is_u_operator_interface(st)) 00981 xos << "."; 00982 00983 if (ST_is_assign_interface(st) || 00984 ST_is_operator_interface(st) || 00985 ST_is_u_operator_interface(st)) 00986 xos << ")"; 00987 00988 xos << '\n'; 00989 00990 for(k=0;k< WN_kid_count(wn);k++ ) { // each kid is OPR_FUNC_ENTRY wn 00991 num_params = WN_kid_count(WN_kid(wn,k)); 00992 param_st = (ST **)alloca((num_params + 1) * sizeof(ST *)); 00993 for (param = 0; param < num_params; param++) { 00994 param_st[param] = WN_st(WN_formal(WN_kid(wn,k), param)); 00995 } 00996 00997 st = &St_Table[WN_entry_name(WN_kid(wn,k))]; 00998 TY_IDX funtype = ST_pu_type(st); 00999 01000 return_ty = Func_Return_Type(funtype); 01001 01002 if (ST_is_in_module(st) ) { 01003 xos << "module procedure "; 01004 Append_Token_String(xos, ST_name(st)); 01005 } else { 01006 if (return_ty != (TY_IDX) 0 && TY_kind(return_ty) != KIND_VOID) { 01007 xos << "FUNCTION"; 01008 01009 if (PU_recursive(Get_Current_PU())) { 01010 //Prepend_Token_String(xos, "RECURSIVE"); 01011 xos << "RECURSIVE"; 01012 } 01013 01014 /* Note that we cannot have functions returning pointer types 01015 * in Fortran, so we use the corresponding integral type 01016 * instead. 01017 */ 01018 if (TY_Is_Pointer(return_ty)) 01019 TY2F_translate(xos, Stab_Mtype_To_Ty(TY_mtype(return_ty)), ctxt); 01020 else { 01021 if (TY_kind(return_ty)==KIND_ARRAY && !TY_is_character(return_ty)) 01022 TY2F_translate(xos,TY_AR_etype(return_ty), ctxt); 01023 else 01024 TY2F_translate(xos, return_ty, ctxt); 01025 } 01026 01027 } else { /* subroutine */ 01028 xos << "SUBROUTINE"; 01029 } 01030 01031 Append_Token_String(xos, ST_name(st)); 01032 01033 /* Emit the parameter name-list, if one is present, and skip any 01034 * implicit "length" parameters associated with character strings. 01035 * Such implicit parameters should be at the end of the parameter list. 01036 */ 01037 01038 first_param = ST2F_FIRST_PARAM_IDX(funtype); 01039 BOOL isFirstArg = TRUE; /* become FALSE after first argument has been emitted */ 01040 /* (radu@par.univie.ac.at) */ 01041 if (param_st[first_param] != NULL) { 01042 xos << "("; 01043 for (param = first_param; 01044 param < num_params; 01045 param++) 01046 { 01047 if (implicit){ 01048 param_st[param] = NULL; 01049 implicit = 0; 01050 } else { 01051 if (STAB_PARAM_HAS_IMPLICIT_LENGTH(param_st[param])) 01052 implicit = 1; 01053 if (!ST_is_return_var(param_st[param])) { 01054 /* separate argument with a comma, if not the first one */ 01055 /* (radu@par.univie.ac.at) */ 01056 if (isFirstArg == FALSE) 01057 xos << ","; 01058 else 01059 isFirstArg = FALSE; 01060 Append_Token_String(xos, 01061 ST_name(param_st[param])); 01062 01063 /* Bug: next and last param may be implicit */ 01064 /* this causes the argument list to end with a comma (radu@par.univie.ac.at) */ 01065 /* if (param+1 < num_params) */ 01066 /* xos << ","; */ 01067 } else 01068 rslt = param_st[param]; 01069 01070 } 01071 } 01072 xos << ")"; 01073 } else { 01074 /* Use the "()" notation for "no parameters" */ 01075 xos << "()"; 01076 } 01077 01078 if (rslt !=NULL && strcasecmp(ST_name(st), 01079 ST_name(rslt)) != 0) { 01080 /* append the RESULT option only if it is different from the function name */ 01081 /* (radu@par.univie.ac.at) */ 01082 xos << "result("; 01083 Append_Token_String(xos, ST_name(rslt)); 01084 xos << ")"; 01085 } 01086 /* Emit parameter declarations, indented and on a new line */ 01087 01088 for (param = first_param; param < num_params ; param++) 01089 01090 if (param_st[param] != NULL) { 01091 xos << std::endl; 01092 TranslateSTDecl(xos, param_st[param], ctxt); 01093 if (ST_is_optional_argument(param_st[param])) { 01094 xos << std::endl; 01095 xos << "OPTIONAL "; 01096 Append_Token_String(xos, ST_name(param_st[param])); 01097 } 01098 if (ST_is_intent_in_argument(param_st[param])) { 01099 xos << std::endl; 01100 xos << "INTENT(in) "; 01101 Append_Token_String(xos, ST_name(param_st[param])); 01102 } 01103 if (ST_is_intent_out_argument(param_st[param])) { 01104 xos << std::endl; 01105 xos << "INTENT(out) "; 01106 Append_Token_String(xos, ST_name(param_st[param])); 01107 } 01108 } 01109 01110 xos << "\n"; 01111 xos << std::endl; 01112 01113 if (return_ty != (TY_IDX) 0 && TY_kind(return_ty) != KIND_VOID) 01114 xos << "END FUNCTION"; 01115 else /* subroutine */ 01116 xos << "END SUBROUTINE"; 01117 } 01118 01119 xos << "\n"; 01120 } 01121 01122 xos << std::endl; 01123 xos << "end interface "; 01124 xos << std::endl; 01125 } 01126 01127 01128 } //WN2F_interface_blk 01129 01130 void 01131 whirl2xaif::WN2F_ar_construct(xml::ostream& xos, WN *wn, PUXlationContext& ctxt) 01132 { 01133 xos << "(/"; 01134 for (INT kid = 0; kid < WN_kid_count(wn); kid++) { 01135 TranslateWN(xos,WN_kid(wn,kid), ctxt); 01136 if (kid < WN_kid_count(wn)-1) 01137 xos << ","; 01138 } 01139 xos << "/)"; 01140 01141 01142 } 01143