OpenADFortTk (basic)
src/whirl2xaif/wn2xaif_stmt.cxx
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines