Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
wn2c_pragma.cxx
Go to the documentation of this file.
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  * Revision history:
00041  *  12-Aug-96 - Original Version
00042  *
00043  * Description:
00044  *
00045  *   Translate a pragma WN node to Fortran!  The corresponding header
00046  *   declaration for for WN2C_pragma() can be found in wn2c_pragma.h.
00047  *
00048  * ====================================================================
00049  * ====================================================================
00050  */
00051 
00052 #ifdef _KEEP_RCS_ID
00053 /*REFERENCED*/
00054 #endif /* _KEEP_RCS_ID */
00055 
00056 #include "alloca.h"
00057 #include "whirl2c_common.h"
00058 #include "w2cf_parentize.h"  /* For W2CF_Get_Parent */
00059 #include "pf_cg.h"
00060 #include "region_util.h"     /* For RID and RID_map */
00061 #include "PUinfo.h"          /* In be/whirl2c directory */
00062 #include "wn2c.h"
00063 #include "st2c.h"
00064 #include "ty2c.h"
00065 #include "tcon2c.h"
00066 #include "wn2c_pragma.h"
00067 
00068 
00069 extern BOOL Run_w2fc_early;     /* Defined in be.so */
00070 extern BOOL W2C_Emit_Omp;      /* Defined in w2c_driver.cxx */
00071 
00072 
00073 #define WN_pragma_nest(wn) WN_pragma_arg1(wn)
00074 #define WN_max_nest_level(wn) WN_pragma_arg2(wn)
00075 #define WN_mp_schedtype(wn) (WN_PRAGMA_SCHEDTYPE_KIND)WN_pragma_arg1(wn)
00076 
00077 #define EMIT_ARG_NUMBERS1(tokens, val1) \
00078    Append_Arg_Numbers((tokens), (val1), -1)
00079 
00080 #define EMIT_ARG_NUMBERS2(tokens, val1, val2) \
00081    Append_Arg_Numbers((tokens), (val1), (val2))
00082 
00083 #define PARENTHESIZE_ARG_NUMBERS1(tokens, val1) \
00084    Append_Token_Special((tokens), '('); \
00085    EMIT_ARG_NUMBERS1((tokens), (val1)); \
00086    Append_Token_Special((tokens), ')')
00087 
00088 #define PARENTHESIZE_ARG_NUMBERS2(tokens, val1, val2) \
00089    Append_Token_Special((tokens), '('); \
00090    EMIT_ARG_NUMBERS2((tokens), (val1), (val2)); \
00091    Append_Token_Special((tokens), ')')
00092 
00093 
00094 typedef struct Array_Distribution
00095 {
00096    INT       current_dimension;  /* Enumerated dimension number in C order */
00097    const WN *base;               /* PRAGMA starting description of this dim */
00098    const WN *cyclic_expr;        /* XPRAGMA holding a cyclic expr (or NULL) */
00099    const WN *dimension_bound;    /* XPRAGMA holding the bounds expr */
00100 } ARRAY_DISTRIBUTION;
00101 
00102 
00103 #define MAX_PRAGMAS_TO_SKIP 50
00104 static struct Set_Of_Pragmas_To_Skip
00105 {
00106    INT start, end;
00107    const WN *array[MAX_PRAGMAS_TO_SKIP];
00108 } Pragmas_To_Skip = {0, 0, 
00109                      {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
00110                       NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
00111                       NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
00112                       NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
00113                       NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}};
00114 
00115 
00116 typedef struct Local_Preg
00117 {
00118    const ST *st;
00119    PREG_IDX  preg_idx;
00120 } LOCAL_PREG;
00121 
00122 
00123 static const WN *WN2C_Prompf_Subsection = NULL;
00124 
00125 
00126 /* ======================= Prompf utilities ======================= */
00127 /* ================================================================ */
00128 
00129 static void WN2C_Stmt_Newline(TOKEN_BUFFER tokens, SRCPOS srcpos);
00130 
00131 inline BOOL
00132 WN2C_is_omp(const WN *pragma)
00133 {
00134    return (WN_pragma_omp(pragma) ||
00135            (W2C_Emit_Omp && WN_pragma_compiler_generated(pragma)));
00136 }
00137 
00138 
00139 static void
00140 WN2C_Append_Prompf_Flag_Newline(TOKEN_BUFFER tokens)
00141 {
00142    UINT current_indent = Current_Indentation();
00143 
00144    Set_Current_Indentation(0);
00145    Append_Indented_Newline(tokens, 1);
00146    Set_Current_Indentation(current_indent);
00147 } /* WN2C_Append_Prompf_Flag_Newline */
00148 
00149 
00150 static void 
00151 WN2C_Start_Prompf_Construct(TOKEN_BUFFER tokens, const WN *pragma)
00152 {
00153    INT32 construct_id = WN_MAP32_Get(*W2C_Construct_Map, pragma);
00154 
00155    WN2C_Append_Prompf_Flag_Newline(tokens);
00156    Append_Token_String(tokens, "/*$SGI");
00157    Append_Token_String(tokens, "start");
00158    Append_Token_String(tokens, Number_as_String(construct_id, "%llu"));
00159    Append_Token_String(tokens, "*/");
00160 } /* WN2C_Start_Prompf_Construct */
00161 
00162 
00163 static void 
00164 WN2C_End_Prompf_Construct(TOKEN_BUFFER tokens, const WN *pragma)
00165 {
00166    INT32 construct_id = WN_MAP32_Get(*W2C_Construct_Map, pragma);
00167 
00168    WN2C_Append_Prompf_Flag_Newline(tokens);
00169    Append_Token_String(tokens, "/*$SGI");
00170    Append_Token_String(tokens, "end");
00171    Append_Token_String(tokens, Number_as_String(construct_id, "%llu"));
00172    Append_Token_String(tokens, "*/");
00173 } /* WN2C_End_Prompf_Construct */
00174 
00175 
00176 /* ======================= Static Functions ======================= */
00177 /* ================================================================ */
00178 
00179 
00180 static void 
00181 WN2C_Stmt_Newline(TOKEN_BUFFER tokens,
00182                   SRCPOS       srcpos)
00183 {
00184    if (W2C_Emit_Linedirs)
00185       Append_Srcpos_Directive(tokens, srcpos);
00186    Append_Indented_Newline(tokens, 1);
00187    if (W2C_File[W2C_LOC_FILE] != NULL)
00188       Append_Srcpos_Map(tokens, srcpos);
00189 } /* WN2C_Stmt_Newline */
00190 
00191 
00192 static void
00193 WN2C_Append_Pragma_Newline(TOKEN_BUFFER tokens, SRCPOS srcpos)
00194 {
00195    UINT current_indent = Current_Indentation();
00196 
00197    Set_Current_Indentation(0);
00198    WN2C_Stmt_Newline(tokens, srcpos);
00199    Append_Token_String(tokens, "#pragma");
00200    Set_Current_Indentation(current_indent);
00201 } /* WN2C_Append_Pragma_Newline */
00202 
00203 
00204 inline void
00205 Append_Clause_Newline(TOKEN_BUFFER tokens, CONTEXT context)
00206 {
00207    if (!CONTEXT_omp(context))
00208       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
00209 } // Append_Clause_Newline
00210 
00211 
00212 static void 
00213 Append_Reduction_Operator(TOKEN_BUFFER tokens, OPERATOR op)
00214 {
00215   /* 
00216    * appends a symbol representing an OMP reduction operator.
00217    */
00218 
00219   char * p;
00220 
00221   switch(op) 
00222     {
00223     case OPR_ADD:
00224       p = "+";
00225       break;
00226 
00227     case OPR_SUB:
00228       p = "-";
00229       break;
00230 
00231     case OPR_MPY:
00232       p = "*";
00233       break;
00234 
00235     case OPR_BAND:
00236       p = "&";
00237       break;
00238 
00239     case OPR_BIOR:
00240       p = "|";
00241       break;
00242 
00243     case OPR_BXOR:
00244        p = "^";
00245       break;
00246 
00247     case OPR_LAND:
00248       p = "&&";
00249       break;
00250 
00251     case OPR_LIOR:
00252       p = "||";
00253       break;
00254 
00255     default:
00256       p = "?" ;
00257   }   
00258   Append_Token_String(tokens, p);
00259   Append_Token_Special(tokens,':');
00260 } // Append_Reduction_Operator
00261 
00262 
00263 static BOOL
00264 Preg_Is_In_Clause_List(const WN *clause_list, const ST *preg_st, PREG_IDX preg_idx)
00265 {
00266    /* Returns TRUE when the given preg is already referenced in a LOCAL,
00267     * LASTLOCAL or SHARED clause in the given clause list; otherwise we
00268     * return FALSE.
00269     */
00270    BOOL found = FALSE;
00271 
00272    while (!found && clause_list != NULL)
00273    {
00274       switch (WN_pragma(clause_list))
00275       {
00276       case WN_PRAGMA_LOCAL:
00277       case WN_PRAGMA_LASTLOCAL:
00278       case WN_PRAGMA_SHARED:
00279       case WN_PRAGMA_FIRSTPRIVATE:
00280       case WN_PRAGMA_REDUCTION:
00281          if (WN_operator(clause_list) != OPR_XPRAGMA &&
00282              WN_st(clause_list) == preg_st && 
00283              WN_pragma_arg1(clause_list) == preg_idx)
00284          {
00285             found = TRUE;
00286          }
00287          break;
00288       default:
00289          break;
00290       }
00291       clause_list = WN_next(clause_list);
00292    }
00293    return found;
00294 } /* Preg_Is_In_Clause_List */
00295 
00296 
00297 static void
00298 Get_Implicit_Locals(WN_PRAGMA_ID  kind,              /* in */
00299                     const WN     *wn,                /* in */
00300                     const WN     *clauses,           /* in */
00301                     LOCAL_PREG  **ptr_to_local_list, /* out */
00302                     UINT         *next_local,        /* in/out */
00303                     UINT         *max_locals)        /* in/out */
00304 {
00305    /* Puts the implicit locals into the local_list.  Every element of the
00306     * local list must represent a unique preg.
00307     */
00308    OPERATOR  opr = WN_operator(wn);
00309    const ST *st;
00310    PREG_IDX  preg_idx;
00311 
00312    /* Get the preg attributes (st, offset) if this is a preg reference
00313     */
00314    switch (opr)
00315    {
00316    case OPR_LDA:
00317       st = WN_st(wn);
00318       preg_idx = WN_lda_offset(wn);
00319       break;
00320    case OPR_LDID:
00321       st = WN_st(wn);
00322       preg_idx = WN_load_offset(wn);
00323       break;
00324    case OPR_STID:
00325       st = WN_st(wn);
00326       preg_idx = WN_store_offset(wn);
00327       break;
00328    default:
00329       st = NULL;
00330       preg_idx = 0;
00331    }
00332 
00333    /* Add a preg reference to the local_list.
00334     */
00335    if (st != NULL &&
00336        ST_sym_class(st) == CLASS_PREG &&
00337        !Preg_Is_In_Clause_List(clauses, st, preg_idx))
00338    {
00339       /* Unless the preg is already in the local list, add it.
00340        */
00341       INT  i;
00342       BOOL found = FALSE;
00343       LOCAL_PREG *local_list = *ptr_to_local_list;
00344 
00345       for (i = 0; !found && i < *next_local; i++)
00346          if (local_list[i].st == st && local_list[i].preg_idx == preg_idx)
00347             found = TRUE;
00348 
00349       if (!found)
00350       {
00351          if (*next_local >= *max_locals)
00352          {
00353             /* Need to reallocate the local_list buffer.  Use increments
00354              * of 200 elements for each reallocation.
00355              */
00356             *max_locals += 200;
00357             local_list = TYPE_ALLOC_N(LOCAL_PREG, *max_locals);
00358 
00359             /* Copy old values into new list, and free up the old list.
00360              */
00361             if (*ptr_to_local_list != NULL)
00362             {
00363                for (i = 0; i < *next_local; i++)
00364                   local_list[i] = (*ptr_to_local_list)[i];
00365                FREE(*ptr_to_local_list);
00366             }
00367             *ptr_to_local_list = local_list;
00368          }
00369 
00370          local_list[*next_local].st = st;
00371          local_list[*next_local].preg_idx = preg_idx;
00372          (*next_local)++;
00373       }
00374    }
00375 
00376    /* Look for preg references in kids
00377     */
00378    if (!OPCODE_is_leaf(WN_opcode(wn)))
00379    {
00380       if (opr == OPR_REGION)
00381       {
00382          /* Skip a pdo or a parallel_do inside a parallel region, since
00383           * such nested regions will be handled independently.
00384           *
00385           * NO LONGER DO THIS, SINCE WE NO LONGER DO IMPLICIT SEARCHES
00386           * ON SUCH NESTED CONSTRUCTS.
00387           *
00388           * WN *pragma = WN_first(WN_region_pragmas(wn));
00389           * if (kind != WN_PRAGMA_PARALLEL_BEGIN         ||
00390           *   pragma == NULL                           ||
00391           *   (WN_pragma(pragma) != WN_PRAGMA_PDO_BEGIN      && /may occur /
00392           *    WN_pragma(pragma) != WN_PRAGMA_PARALLEL_BEGIN && /impossible?/
00393           *    WN_pragma(pragma) != WN_PRAGMA_PARALLEL_DO    && /impossible?/
00394           *    WN_pragma(pragma) != WN_PRAGMA_DOACROSS))        /impossible?/
00395           *{
00396           */
00397          Get_Implicit_Locals(kind, WN_region_body(wn), clauses, 
00398                              ptr_to_local_list, next_local, max_locals);
00399       }
00400       else if (opr == OPR_BLOCK)
00401       {
00402          const WN *kid = WN_first(wn);
00403          while (kid)
00404          {
00405             Get_Implicit_Locals(kind, kid, clauses, 
00406                                 ptr_to_local_list, next_local, max_locals);
00407             kid = WN_next(kid);
00408          }
00409       }
00410       else
00411       {
00412          INT       kidno;
00413          const WN *kid;
00414          for (kidno=0; kidno < WN_kid_count(wn); kidno++)
00415          {
00416             kid = WN_kid (wn, kidno);
00417             if (kid) 
00418             { 
00419                Get_Implicit_Locals(kind, kid, clauses, 
00420                                    ptr_to_local_list, next_local, max_locals);
00421             }
00422          }
00423       }
00424    }
00425 } /* Get_Implicit_Locals */
00426 
00427 
00428 static void
00429 Append_Implicit_Locals(TOKEN_BUFFER tokens,
00430                        WN_PRAGMA_ID region_kind,
00431                        const WN    *region_body,
00432                        const WN    *region_clauses,
00433                        CONTEXT      context)
00434 {
00435    /* This will append implicit LOCAL clauses to the tokens, assuming
00436     * the regular clauses already have been appended to the tokens.
00437     */
00438    LOCAL_PREG *local_list = NULL;
00439    UINT        i, number_of_locals = 0, max_number_of_locals = 0;
00440 
00441    /* Get the list of implicit locals.
00442     */
00443    Get_Implicit_Locals(region_kind, region_body, region_clauses,
00444                        &local_list, &number_of_locals, &max_number_of_locals);
00445 
00446    /* Add make the implicit LOCAL clauses explicit in the token buffer
00447     */
00448    if (number_of_locals > 0)
00449    {
00450       Append_Clause_Newline(tokens, context);
00451       if (CONTEXT_omp(context))
00452          Append_Token_String(tokens, "private");
00453       else
00454          Append_Token_String(tokens, "local");
00455       Append_Token_Special(tokens, '(');
00456       for (i = 0; i < number_of_locals; i++)
00457       {
00458          if (i > 0)
00459             Append_Token_Special(tokens, ',');
00460 
00461          ST2C_Use_Preg(tokens,
00462                        ST_type(local_list[i].st),
00463                        local_list[i].preg_idx,
00464                        context);
00465       }
00466       Append_Token_Special(tokens, ')');
00467    }
00468 
00469    if (local_list != NULL)
00470       FREE(local_list);
00471 } /* Append_Implicit_Locals */
00472 
00473 
00474 static void
00475 WN2C_Value_Reference(TOKEN_BUFFER tokens, 
00476                      const WN *   expression, 
00477                      BOOL         prepend)
00478 {
00479    CONTEXT      context = INIT_CONTEXT;
00480    TOKEN_BUFFER expr_tokens = New_Token_Buffer();
00481    TY_IDX       ty = WN_Tree_Type(expression);
00482 
00483    /* Emit memory reference
00484     */
00485    if (TY_Is_Pointer(ty))
00486    {
00487       TY_IDX object_ty;
00488 
00489       WN2C_memref_lhs(expr_tokens, 
00490                       &object_ty,               /* Type referenced (out) */
00491                       expression,               /* address */
00492                       0,                        /* offset in object */
00493                       ty,                       /* ref type of object */
00494                       TY_pointed(ty),           /* type of stored object */
00495                       TY_mtype(TY_pointed(ty)), /* base-type of object */
00496                       context);
00497    }
00498    else
00499       (void)WN2C_translate(expr_tokens, expression, context);
00500 
00501    if (prepend)
00502       Prepend_And_Reclaim_Token_List(tokens, &expr_tokens);
00503    else
00504       Append_And_Reclaim_Token_List(tokens, &expr_tokens);
00505 } /* WN2C_Value_Reference */
00506 
00507 static void
00508 WN2C_Append_Value_Reference(TOKEN_BUFFER tokens, 
00509                             const WN *   expression, 
00510                             BOOL         prepend = FALSE)
00511 {
00512    WN2C_Value_Reference(tokens, expression, FALSE/*prepend*/);
00513 }
00514 
00515 static void
00516 WN2C_Prepend_Value_Reference(TOKEN_BUFFER tokens, 
00517                              const WN *   expression, 
00518                              BOOL         prepend = FALSE)
00519 {
00520    WN2C_Value_Reference(tokens, expression, TRUE/*prepend*/);
00521 }
00522 
00523 
00524 static void
00525 Append_MP_Schedtype(TOKEN_BUFFER tokens, WN_PRAGMA_SCHEDTYPE_KIND kind)
00526 {
00527    switch (kind)
00528    {
00529    case WN_PRAGMA_SCHEDTYPE_RUNTIME:
00530       Append_Token_String(tokens, "runtime");
00531       break;
00532    case WN_PRAGMA_SCHEDTYPE_SIMPLE:
00533       Append_Token_String(tokens, "simple");
00534       break;
00535    case WN_PRAGMA_SCHEDTYPE_INTERLEAVE:
00536       Append_Token_String(tokens, "interleave");
00537       break;
00538    case WN_PRAGMA_SCHEDTYPE_DYNAMIC:
00539       Append_Token_String(tokens, "dynamic");
00540       break;
00541    case WN_PRAGMA_SCHEDTYPE_GSS:
00542       Append_Token_String(tokens, "gss");
00543       break;
00544    case WN_PRAGMA_SCHEDTYPE_PSEUDOLOWERED:
00545       Append_Token_String(tokens, "pseudolowered");
00546       break;
00547    default:
00548       Is_True(FALSE, 
00549               ("Unexpected MP scheduling type (%d) in Append_MP_Schedtype()",
00550                kind));
00551       break;
00552    }
00553 } /* Append_MP_Schedtype */
00554 
00555 
00556 static void
00557 Append_Arg_Numbers(TOKEN_BUFFER tokens,
00558                    INT32        val1,
00559                    INT32        val2)
00560 {
00561    if (val1 != -1)
00562       Append_Token_String(tokens, Number_as_String(val1, "%lld"));
00563 
00564    if (val2 != -1)
00565    {
00566       Append_Token_Special(tokens, ',');
00567       Append_Token_String(tokens, Number_as_String(val2, "%lld"));
00568    }
00569 } /* Append_Arg_Numbers */
00570 
00571          
00572 static void
00573 Append_Prefetch_Attributes(TOKEN_BUFFER tokens, 
00574                            const WN    *prefetch,
00575                            INT32        size)
00576 {
00577    INT pflag = WN_prefetch_flag(prefetch);
00578 
00579    /* Emit memory reference
00580     */
00581    Append_Token_Special(tokens, '=');
00582    WN2C_Append_Value_Reference(tokens, WN_kid0(prefetch));
00583 
00584    /* Emit stride and level clauses
00585     */
00586    Append_Token_Special(tokens, ',');
00587    if (PF_GET_STRIDE_1L(pflag) > 0)
00588    {
00589       if (PF_GET_STRIDE_2L(pflag) > 0)
00590       {
00591          Append_Token_String(tokens, 
00592             Concat2_Strings("stride=",
00593             Concat2_Strings(Number_as_String(PF_GET_STRIDE_1L(pflag), "%lld"),
00594             Concat2_Strings(",",
00595                         Number_as_String(PF_GET_STRIDE_2L(pflag), "%lld")))));
00596          Append_Token_Special(tokens, ',');
00597          Append_Token_String(tokens, "level=1,2");
00598       }
00599       else
00600       {
00601          Append_Token_String(tokens, 
00602             Concat2_Strings("stride=",
00603                Number_as_String(PF_GET_STRIDE_1L(pflag), "%lld")));
00604          Append_Token_Special(tokens, ',');
00605          Append_Token_String(tokens, "level=1");
00606       }
00607    }
00608    else if (PF_GET_STRIDE_2L(pflag) > 0)
00609    {
00610       Append_Token_String(tokens, 
00611             Concat2_Strings("stride=,",
00612                Number_as_String(PF_GET_STRIDE_2L(pflag), "%lld")));
00613          Append_Token_Special(tokens, ',');
00614          Append_Token_String(tokens, "level=,2");
00615    }
00616    else
00617    {
00618       Append_Token_String(tokens, "stride=");
00619       Append_Token_Special(tokens, ',');
00620       Append_Token_String(tokens, "level=");
00621    }
00622 
00623    /* Emit a kind clause
00624     */
00625    Append_Token_Special(tokens, ',');
00626    if (PF_GET_READ(pflag))
00627       Append_Token_String(tokens, "kind=rd");
00628    else
00629       Append_Token_String(tokens, "kind=wr");
00630 
00631    /* Emit a size clause
00632     */
00633    if (size > 0)
00634    {
00635       Append_Token_Special(tokens, ',');
00636       Append_Token_String(tokens, 
00637          Concat2_Strings("size=", Number_as_String(size, "%lld")));
00638    }
00639 } /* Append_Prefetch_Attributes */
00640 
00641 
00642 static void
00643 Append_Distribution(TOKEN_BUFFER tokens, const WN **apragma, WN_PRAGMA_ID id)
00644 {
00645    INT32               dim, num_dims;
00646    ARRAY_DISTRIBUTION  distr[MAX_PRAGMAS_TO_SKIP];
00647    const WN           *wn = *apragma;
00648    CONTEXT             context = INIT_CONTEXT;
00649 
00650    Is_True(WN_operator(wn) == OPR_PRAGMA, 
00651            ("Unexpected operator (%d) in Append_Distribution()",
00652             WN_operator(wn)));
00653 
00654    /* Accumulate the distribution kind for each dimension.
00655     */
00656    for (num_dims = 0; 
00657         (WN_operator(wn) == OPR_PRAGMA &&
00658          WN_pragma(wn) == id           &&
00659          num_dims == WN_pragma_index(wn));
00660         num_dims++)
00661    {
00662       /* In reverese order of pragma sequence */
00663       distr[num_dims].current_dimension = WN_pragma_index(wn);
00664       distr[num_dims].base = wn;
00665       if (WN_pragma_distr_type(wn) == DISTRIBUTE_CYCLIC_EXPR)
00666          distr[num_dims].cyclic_expr = wn = WN_next(wn);
00667       distr[num_dims].dimension_bound = wn = WN_next(wn);
00668       wn = WN_next(wn);
00669    }
00670 
00671    /* Skip two stores, which are generated purely for dependency analysis
00672     * purposes.
00673     */
00674    if (WN_operator(wn)==OPR_STID && ST_sym_class(WN_st(wn))==CLASS_PREG)
00675    {
00676       wn = WN_next(wn);
00677       if (WN_operator(wn)==OPR_STID && ST_sym_class(WN_st(wn))==CLASS_PREG)
00678          wn = WN_next(wn);
00679    }
00680    *apragma = wn;
00681 
00682    /* Translate the sequence of distribution kinds, in C order, i.e.
00683     * in the order of the WHIRL representation.
00684     */
00685    for (dim = 0; dim < num_dims; dim++)
00686    {
00687       Append_Token_Special(tokens, '[');
00688       switch (WN_pragma_distr_type(distr[dim].base))
00689       {
00690       case DISTRIBUTE_STAR:
00691          Append_Token_Special(tokens, '*');
00692          break;
00693 
00694       case DISTRIBUTE_BLOCK:
00695          Append_Token_String(tokens, "block");
00696          break;
00697 
00698       case DISTRIBUTE_CYCLIC_EXPR:
00699          Append_Token_String(tokens, "cyclic");
00700          Append_Token_Special(tokens, '(');
00701          WN2C_translate(tokens, WN_kid0(distr[dim].cyclic_expr), context);
00702          Append_Token_Special(tokens, ')');
00703          break;
00704 
00705       case DISTRIBUTE_CYCLIC_CONST:
00706          Append_Token_String(tokens, "cyclic");
00707          PARENTHESIZE_ARG_NUMBERS1(tokens, 
00708                                    WN_pragma_preg(distr[dim].base));
00709          break;
00710 
00711       default:
00712          Append_Token_String(tokens, "unknown_distribution");
00713          break;
00714       }
00715       Append_Token_Special(tokens, ']');
00716 
00717    } /* For each dimension */
00718 } /* Append_Distribution */
00719 
00720 
00721 static void
00722 Append_A_Clause_Symbol(TOKEN_BUFFER tokens, const WN *clause, WN_OFFSET ofst)
00723 {
00724    CONTEXT         context = INIT_CONTEXT;
00725    const ST *const st = WN_st(clause);
00726 
00727    if (ST_sym_class(st) == CLASS_PREG)
00728    {
00729       INT32 preg_num = WN_pragma_arg1(clause);
00730 
00731       ST2C_Use_Preg(tokens, ST_type(st), preg_num, context);
00732    }
00733    else
00734    {
00735       TY_IDX       object_ty;
00736       const TY_IDX base_ty = ST_type(st);
00737       TOKEN_BUFFER sym_tokens = New_Token_Buffer();
00738 
00739       WN2C_stid_lhs(sym_tokens,
00740                     &object_ty,
00741                     st,        /* base variable */
00742                     ofst,      /* base offset */
00743                     base_ty,   /* type of reference */
00744                     TY_mtype(base_ty),
00745                     context);
00746       Append_And_Reclaim_Token_List(tokens, &sym_tokens);
00747    }
00748 } /* Append_A_Clause_Symbol */
00749 
00750 
00751 static void
00752 Append_Clause_Symbols(TOKEN_BUFFER tokens,
00753                       WN_PRAGMA_ID id,
00754                       const WN   **next)
00755 {
00756    /* Loop through the pragmas, and emit a ',' separated list
00757     * of the ST attributes for all contiguous pragmas with the 
00758     * given "id".  Terminate upon reaching a pragma with a
00759     * different "id" or the end of the pragma list. Set *next to
00760     * point to the next node after the last one processed here.
00761     */
00762    const WN *clause;
00763 
00764    Is_True(WN_operator(*next) == OPR_PRAGMA, 
00765            ("Unexpected operator (%d) in Append_Clause_Symbols()", 
00766             WN_operator(*next)));
00767 
00768    Append_Token_Special(tokens, '(');
00769    for (clause = *next;
00770         (clause != NULL                    && 
00771          WN_operator(clause) == OPR_PRAGMA && 
00772          WN_pragma(clause) == id);
00773         clause = WN_next(clause))
00774    {
00775       if (clause != *next)
00776          Append_Token_Special(tokens, ',');
00777 
00778       Append_A_Clause_Symbol(tokens,  clause, 0);
00779    }
00780    Append_Token_Special(tokens, ')');
00781    *next = clause;
00782 } /* Append_Clause_Symbols */
00783 
00784 
00785 static void
00786 Append_Reduction_Clause(TOKEN_BUFFER tokens,
00787                         WN_PRAGMA_ID id,
00788                         const WN   **next)
00789 {
00790    /* Loop through the pragmas, and emit a ',' separated list
00791     * of the reduction operator and ST attributes for all 
00792     * contiguous pragmas with the given "id".  
00793     */
00794    const WN *       clause;
00795    const WN * const first_clause = *next;
00796 
00797    Is_True(WN_operator(first_clause) == OPR_PRAGMA, 
00798            ("Unexpected operator (%d) in Append_Reduction_Clause()", 
00799             WN_operator(first_clause)));
00800 
00801    Append_Token_String(tokens, "reduction (");
00802    for (clause = first_clause;
00803         (clause != NULL                    && 
00804          WN_operator(clause) == OPR_PRAGMA && 
00805          WN_pragma(clause) == id);
00806         clause = WN_next(clause))
00807    {
00808       if (WN2C_is_omp(clause) &&  
00809           WN_pragma(clause) == WN_PRAGMA_REDUCTION &&
00810           WN_pragma_arg2(clause) != OPERATOR_UNKNOWN) 
00811       {
00812          if (first_clause != clause) 
00813             Append_Token_String(tokens, "), reduction (");
00814          Append_Reduction_Operator(tokens, (OPERATOR) WN_pragma_arg2(clause));
00815          
00816       } 
00817       else if (clause != first_clause) 
00818          Append_Token_Special(tokens, ',');
00819 
00820       Append_A_Clause_Symbol(tokens, clause, 0);
00821    }
00822 
00823    Append_Token_Special(tokens, ')');
00824    *next = clause;
00825 
00826 } /* Append_Reduction_Clause */
00827 
00828 
00829 static void
00830 Append_Clause_Expressions(TOKEN_BUFFER tokens,
00831                           WN_PRAGMA_ID id,
00832                           const WN   **next,
00833                           BOOL         reverse_order = FALSE)
00834 {
00835    /* Loop through the pragmas, and emit a ',' separated list
00836     * of the ST attributes for all contiguous pragmas with the 
00837     * given "id".  Terminate upon reaching a pragma with a
00838     * different "id" or the end of the pragma list. Set *next to
00839     * point to the next node after the last one processed here.
00840     */
00841    TOKEN_BUFFER     clause_tokens = New_Token_Buffer();
00842    const WN *       clause;
00843    const WN * const first_clause = *next;
00844 
00845    Is_True(WN_operator(first_clause) == OPR_XPRAGMA,
00846            ("Unexpected operator %d in Append_Clause_Expressions()", 
00847             WN_operator(first_clause)));
00848 
00849    Append_Token_Special(tokens, '(');
00850    for (clause = first_clause;
00851         (clause != NULL && 
00852          WN_operator(clause) == OPR_XPRAGMA && 
00853          WN_pragma(clause) == id);
00854         clause = WN_next(clause))
00855    {
00856       if (clause != first_clause)
00857       {
00858          if (reverse_order)
00859             Prepend_Token_Special(clause_tokens,  ',');
00860          else
00861             Append_Token_Special(clause_tokens, ',');
00862       }
00863 
00864       if (id == WN_PRAGMA_ONTO && 
00865           WN_operator(WN_kid0(clause)) == OPR_INTCONST &&
00866           WN_const_val(WN_kid0(clause)) == 0)
00867       {
00868          /* Special case!
00869           */
00870          if (reverse_order)
00871             Prepend_Token_Special(clause_tokens,  '*');
00872          else
00873             Append_Token_Special(clause_tokens, '*');
00874       }
00875       else
00876       {
00877          if (reverse_order)
00878             WN2C_Prepend_Value_Reference(tokens, WN_kid0(clause));
00879          else
00880             WN2C_Append_Value_Reference(tokens, WN_kid0(clause));
00881       }
00882    }
00883    Append_And_Reclaim_Token_List(tokens, &clause_tokens);
00884    Append_Token_Special(tokens, ')');
00885    *next = clause;
00886 } /* Append_Clause_Expressions */
00887 
00888         
00889 static void
00890 Append_Array_Segment(TOKEN_BUFFER tokens,
00891                      WN_PRAGMA_ID id,
00892                      const WN   **next)
00893 {
00894    /* Loop through the pragmas, and emit a ',' separated list
00895     * of the ST attributes for all contiguous pragmas with the 
00896     * given "id".  Terminate upon reaching a pragma with a
00897     * different "id" or the end of the pragma list. Set *next to
00898     * point to the next node after the last one processed here.
00899     */
00900    const WN *clause;
00901 
00902    Is_True(WN_operator(*next) == OPR_XPRAGMA,
00903            ("Unexpected operator %d in Append_Array_Segment()", 
00904             WN_operator(*next)));
00905 
00906    Append_Token_Special(tokens, '(');
00907    for (clause = *next;
00908         (clause != NULL && 
00909          WN_operator(clause) == OPR_XPRAGMA && 
00910          WN_pragma(clause) == id);
00911         clause = WN_next(clause))
00912    {
00913       if (clause != *next)
00914          Append_Token_Special(tokens, ',');
00915 
00916       Append_A_Clause_Symbol(tokens,  clause, 0);
00917       Append_Token_Special(tokens, '(');
00918       EMIT_ARG_NUMBERS1(tokens, 0);
00919       Append_Token_Special(tokens, ':');
00920       WN2C_Append_Value_Reference(tokens, WN_kid0(clause));
00921       Append_Token_Special(tokens, '-'); // Subtract 1, since expr is at base 1
00922       EMIT_ARG_NUMBERS1(tokens, 1);
00923       Append_Token_Special(tokens, ')');
00924    }
00925    Append_Token_Special(tokens, ')');
00926 
00927    *next = clause;
00928 } /* Append_Array_Segment */
00929 
00930             
00931 static void
00932 Append_Nest_Clauses(TOKEN_BUFFER tokens, 
00933                     const WN    *nest_region, 
00934                     INT          nest_levels,
00935                     CONTEXT      context)
00936 {
00937    BOOL         pattern_error = FALSE;
00938    INT          nest;
00939    const ST    *idx_var;
00940    TY_IDX       idx_ty;
00941    const WN    *next_stmt = nest_region;
00942    WN_PRAGMA_ID nest_kind = WN_PRAGMA_UNDEFINED;
00943    TOKEN_BUFFER nest_tokens = New_Token_Buffer();
00944 
00945    Is_True(next_stmt != NULL &&
00946            WN_operator(next_stmt) == OPR_REGION &&
00947            WN_first(WN_region_pragmas(next_stmt)) != NULL,
00948            ("Unexpected top-level structure for Append_Nest_Clauses()"));
00949 
00950    nest_kind = 
00951       (WN_PRAGMA_ID)WN_pragma(WN_first(WN_region_pragmas(next_stmt)));
00952 
00953    Append_Clause_Newline(tokens, context);
00954    Append_Token_String(nest_tokens, "nest");
00955    Append_Token_Special(nest_tokens, '(');
00956    CONTEXT_reset(context);
00957    for (nest = 1; !pattern_error && nest <= nest_levels; nest++)
00958    {
00959       /* Get the next nested loop, assuming next_stmt at this point
00960        * refers to a region.
00961        */
00962       next_stmt = WN_first(WN_region_body(next_stmt));
00963       while (next_stmt != NULL && WN_operator(next_stmt) != OPR_DO_LOOP)
00964          next_stmt = WN_next(next_stmt);
00965 
00966       if (next_stmt == NULL)
00967          pattern_error = TRUE;
00968       else
00969       {
00970          /* Write out the index variable (or preg).
00971           */
00972          idx_var = WN_st(WN_index(next_stmt));
00973          idx_ty = ST_type(idx_var);
00974          if (ST_sym_class(idx_var) == CLASS_PREG)
00975          {
00976             ST2C_Use_Preg(nest_tokens,
00977                           idx_ty,
00978                           WN_idname_offset(WN_index(next_stmt)),
00979                           context);
00980          }
00981          else
00982          {
00983             TY_IDX       object_ty;
00984             TOKEN_BUFFER sym_tokens = New_Token_Buffer();
00985 
00986             WN2C_stid_lhs(sym_tokens,
00987                           &object_ty,
00988                           idx_var,          /* base variable */
00989                           WN_idname_offset(WN_index(next_stmt)),
00990                           idx_ty,           /* type of reference */
00991                           TY_mtype(idx_ty),
00992                           context);
00993             Append_And_Reclaim_Token_List(nest_tokens, &sym_tokens);
00994          }
00995          
00996          /* Emit separator, and search for the next nested region, if 
00997           * any is expected.
00998           */
00999          if (nest < nest_levels)
01000          {
01001             Append_Token_Special(nest_tokens, ',');
01002 
01003             next_stmt = WN_first(WN_do_body(next_stmt));
01004             while (next_stmt != NULL && 
01005                    WN_operator(next_stmt) != OPR_REGION)
01006                next_stmt = WN_next(next_stmt);
01007 
01008             if (next_stmt == NULL                              ||
01009                 WN_first(WN_region_pragmas(next_stmt)) == NULL ||
01010                 WN_pragma(WN_first(WN_region_pragmas(next_stmt))) != 
01011                 nest_kind)
01012                pattern_error = TRUE;
01013          }
01014       }
01015    }
01016    Append_Token_Special(nest_tokens, ')');
01017 
01018    if (!pattern_error)
01019       Append_And_Reclaim_Token_List(tokens, &nest_tokens);
01020 } /* Append_Nest_Clauses */
01021 
01022 
01023 static void
01024 Skip_Pragma_Clauses(const WN **clause_list,  
01025                     CONTEXT    context)
01026 {
01027    /* Also change Append_Pragma_Clauses() when changing this.
01028     */
01029    const WN *clause = *clause_list;
01030    BOOL      more;
01031 
01032    more = (clause != NULL && 
01033            (WN_operator(clause) == OPR_PRAGMA ||
01034             WN_operator(clause) == OPR_XPRAGMA));
01035 
01036    while (more)
01037    {
01038       switch (WN_pragma(clause))
01039       {
01040       case WN_PRAGMA_AFFINITY:
01041       case WN_PRAGMA_DATA_AFFINITY:
01042       case WN_PRAGMA_THREAD_AFFINITY:
01043       case WN_PRAGMA_CHUNKSIZE:
01044       case WN_PRAGMA_IF:
01045       case WN_PRAGMA_LASTLOCAL:
01046       case WN_PRAGMA_LOCAL:
01047       case WN_PRAGMA_MPSCHEDTYPE:
01048       case WN_PRAGMA_ORDERED:
01049       case WN_PRAGMA_REDUCTION:
01050       case WN_PRAGMA_SHARED:
01051       case WN_PRAGMA_ONTO:
01052       case WN_PRAGMA_LASTTHREAD:
01053       case WN_PRAGMA_MPNUM:
01054       case WN_PRAGMA_SYNC_DOACROSS:
01055       case WN_PRAGMA_FIRSTPRIVATE:
01056       case WN_PRAGMA_NOWAIT: // We put "nowait" on the pragma itself for C
01057          clause = WN_next(clause);
01058          break;
01059 
01060       default:
01061          more = FALSE;
01062          break;
01063       } /* switch */
01064 
01065       more = (more &&
01066               clause != NULL && 
01067               (WN_operator(clause) == OPR_PRAGMA ||
01068                WN_operator(clause) == OPR_XPRAGMA));
01069    } /* for each attribute pragma */
01070 
01071    *clause_list = clause;
01072 } /* Skip_Pragma_Clauses */
01073 
01074  
01075 static void 
01076 Skip_Ignored_Clauses(const WN *following_clauses, const WN **next_clause)
01077 {
01078    BOOL skipped = TRUE;
01079 
01080    while (skipped && *next_clause != following_clauses)
01081    {
01082       switch (WN_pragma(*next_clause))
01083       {
01084       case WN_PRAGMA_DATA_AFFINITY:
01085       case WN_PRAGMA_THREAD_AFFINITY:
01086       case WN_PRAGMA_MPNUM:
01087       case WN_PRAGMA_SYNC_DOACROSS:
01088          *next_clause = WN_next(*next_clause);
01089          break;
01090       default:
01091          skipped = FALSE;
01092          break;
01093       }
01094    }
01095 } /* Skip_Ignored_Clauses */
01096 
01097 
01098 static void
01099 Append_Pragma_Clauses(TOKEN_BUFFER tokens, 
01100                       const WN   **clause_list,  
01101                       CONTEXT      context)
01102 {
01103    /* Loop through the sequence of pragmas, emitting those representing
01104     * attributes to another (already emitted) pragma.  Terminate upon
01105     * reaching a non-attribute pragma or the end of the pragma list.
01106     * Also change Skip_Pragma_Clauses() when changing this.  Update the
01107     * clause_list, such that it denotes the item following the last one
01108     * processed here.  In C we can always emit clauses on a separate line,
01109     * as a subsequent pragma, so we take that approach here, with exception
01110     * of "omp" pragmas.
01111     */
01112    const WN   *next;
01113    const WN   *clause = *clause_list;
01114    const WN   *wn_after_clauses = *clause_list;
01115 
01116    Skip_Pragma_Clauses(&wn_after_clauses, context);
01117    while (clause != wn_after_clauses)
01118    {
01119       /* Note: In C we do not separate clauses by commas.
01120        */
01121       BOOL omp = CONTEXT_omp(context) || WN2C_is_omp(clause);
01122       
01123       next = clause;
01124       switch (WN_pragma(clause))
01125       {
01126       case WN_PRAGMA_DATA_AFFINITY:
01127       case WN_PRAGMA_THREAD_AFFINITY:
01128       case WN_PRAGMA_MPNUM:
01129       case WN_PRAGMA_SYNC_DOACROSS:
01130          break; /* Ignore these */
01131 
01132       case WN_PRAGMA_NOWAIT:
01133          Append_Clause_Newline(tokens, context);
01134          Append_Token_String(tokens, "nowait");
01135          clause = WN_next(clause);
01136          break;
01137 
01138       case WN_PRAGMA_AFFINITY:
01139          Append_Clause_Newline(tokens, context);
01140          Append_Token_String(tokens, "affinity");
01141          Append_Clause_Expressions(tokens, WN_PRAGMA_AFFINITY, &clause);
01142 
01143          Append_Token_Special(tokens, '=');
01144          if (WN_pragma(clause) == WN_PRAGMA_DATA_AFFINITY)
01145             Append_Token_String(tokens, "data");
01146          else if (WN_pragma(clause) == WN_PRAGMA_THREAD_AFFINITY)
01147             Append_Token_String(tokens, "thread");
01148          else
01149             Is_True(FALSE, 
01150                     ("Unexpected clause kind (%d) in Append_Pragma_Clauses()",
01151                      WN_pragma(clause)));
01152 
01153          /* Process the expression associated with the thread/data affinity
01154           * pragma.
01155           */
01156          Append_Token_Special(tokens, '(');
01157          WN2C_Append_Value_Reference(tokens, WN_kid0(clause));
01158          Append_Token_Special(tokens, ')');
01159          clause = WN_next(clause);
01160          break;
01161 
01162       case WN_PRAGMA_CHUNKSIZE:
01163          Append_Clause_Newline(tokens, context);
01164          Append_Token_String(tokens, "chunksize");
01165          Append_Clause_Expressions(tokens, WN_PRAGMA_CHUNKSIZE, &clause);
01166          break;
01167 
01168       case WN_PRAGMA_IF:
01169          Append_Clause_Newline(tokens, context);
01170          Append_Token_String(tokens, "if");
01171          Append_Clause_Expressions(tokens, WN_PRAGMA_IF, &clause);
01172          break;
01173 
01174       case WN_PRAGMA_LASTLOCAL:
01175          Append_Clause_Newline(tokens, context);
01176          if (omp)
01177             Append_Token_String(tokens, "lastprivate");
01178          else
01179             Append_Token_String(tokens, "lastlocal");
01180          Append_Clause_Symbols(tokens, WN_PRAGMA_LASTLOCAL, &clause);
01181          break;
01182 
01183       case WN_PRAGMA_LOCAL:
01184          Append_Clause_Newline(tokens, context);
01185          if (omp)
01186             Append_Token_String(tokens, "private");
01187          else
01188             Append_Token_String(tokens, "local");
01189          if (WN_operator(clause) == OPR_XPRAGMA)
01190          {
01191             Append_Array_Segment(tokens, WN_PRAGMA_LOCAL, &clause);
01192          }
01193          else
01194          {
01195             Append_Clause_Symbols(tokens, WN_PRAGMA_LOCAL, &clause);
01196          }
01197          break;
01198 
01199       case WN_PRAGMA_MPSCHEDTYPE:
01200          /* Can be both a clause and a pragma */
01201          if (omp)
01202          {
01203             Append_Clause_Newline(tokens, context);
01204             Append_Token_String(tokens, "schedule");
01205             Append_Token_Special(tokens, '(');
01206             Append_MP_Schedtype(tokens, WN_mp_schedtype(clause));
01207             if (WN_next(clause) != NULL &&
01208                 WN_pragma(WN_next(clause)) == WN_PRAGMA_CHUNKSIZE)
01209             {
01210                clause = WN_next(clause);
01211                Append_Token_Special(tokens, ',');
01212                WN2C_Append_Value_Reference(tokens, WN_kid0(clause));
01213             }
01214             Append_Token_Special(tokens, ')');
01215             clause = WN_next(clause);
01216          }
01217          else
01218          {
01219             Append_Token_String(tokens, "schedtype");
01220             Append_Token_Special(tokens, '(');
01221             Append_MP_Schedtype(tokens, WN_mp_schedtype(clause));
01222             Append_Token_Special(tokens, ')');
01223          }
01224          break;
01225 
01226       case WN_PRAGMA_ORDERED:
01227          Append_Clause_Newline(tokens, context);
01228          if (omp)
01229             Append_Token_String(tokens, "(ordered)");
01230          else
01231             Append_Token_String(tokens, "ordered");
01232          break;
01233 
01234       case WN_PRAGMA_REDUCTION:
01235          Append_Clause_Newline(tokens, context);
01236          if (WN_operator(clause) == OPR_XPRAGMA)
01237          {
01238             Append_Token_String(tokens, "reduction");
01239             Append_Clause_Expressions(tokens, WN_PRAGMA_REDUCTION, &clause);
01240          }
01241          else
01242          {
01243             Append_Reduction_Clause(tokens, WN_PRAGMA_REDUCTION, &clause);
01244          }
01245          break;
01246 
01247       case WN_PRAGMA_SHARED:
01248          Append_Clause_Newline(tokens, context);
01249          Append_Token_String(tokens, "shared");
01250          Append_Clause_Symbols(tokens, WN_PRAGMA_SHARED, &clause);
01251          break;
01252 
01253       case WN_PRAGMA_ONTO:
01254          Append_Clause_Newline(tokens, context);
01255          Append_Token_String(tokens, "onto");
01256          Append_Clause_Expressions(tokens, WN_PRAGMA_ONTO, &clause);
01257          break;
01258 
01259       case WN_PRAGMA_LASTTHREAD:
01260          Append_Clause_Newline(tokens, context);
01261          Append_Token_String(tokens, "lastthread");
01262          Append_Clause_Symbols(tokens, WN_PRAGMA_LASTTHREAD, &clause);
01263          break;
01264 
01265       case WN_PRAGMA_FIRSTPRIVATE:
01266          Append_Token_String(tokens, "firstprivate");
01267          Append_Clause_Symbols(tokens, WN_PRAGMA_FIRSTPRIVATE, &clause);
01268          break;
01269 
01270       default:
01271          Is_True(FALSE,
01272                  ("Unexpected pragma id in Append_Pragma_Clauses()"));
01273          break;
01274       } /* switch */
01275 
01276       /* See if we have already advanced to the next pragma, e.g. as a result
01277        * of calling Append_Clause_Expressions() or Append_Clause_Symbols(),
01278        * and if not so, then advance to the next pragma.
01279        */
01280       if (next == clause)
01281          clause = WN_next(clause);
01282 
01283       Skip_Ignored_Clauses(wn_after_clauses, &clause);
01284    } /* for each attribute pragma */
01285 
01286    *clause_list = clause;
01287 } /* Append_Pragma_Clauses */
01288 
01289 
01290 static void
01291 Emit_To_PUinfo_Pragmas(const WN **next, CONTEXT context)
01292 {
01293    /* This is a special handler for pragmas that must be taken out of
01294     * a statement list context and instead must be appended to the 
01295     * PUinfo_pragmas list.
01296     */
01297    TOKEN_BUFFER tokens = New_Token_Buffer();
01298 
01299    Is_True(WN_operator(*next) == OPR_PRAGMA ||
01300            WN_operator(*next) == OPR_XPRAGMA, 
01301            ("Unexpected operator (%d) in WN2C_pragma()", WN_operator(*next)));
01302 
01303    switch (WN_pragma(*next))
01304    {
01305    case WN_PRAGMA_DISTRIBUTE:
01306       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01307       Append_Token_String(tokens, "distribute");
01308       Append_A_Clause_Symbol(tokens, *next, 0/*ofst*/);
01309       Append_Distribution(tokens, next, WN_PRAGMA_DISTRIBUTE);
01310       Append_Pragma_Clauses(tokens, next, context);
01311       break;
01312 
01313    case WN_PRAGMA_DISTRIBUTE_RESHAPE:
01314       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01315       Append_Token_String(tokens, "distribute reshape");
01316       Append_A_Clause_Symbol(tokens, *next, 0/*ofst*/);
01317       Append_Distribution(tokens, next, WN_PRAGMA_DISTRIBUTE_RESHAPE);
01318       Append_Pragma_Clauses(tokens, next, context);
01319       break;
01320 
01321    default:
01322       Is_True(FALSE,
01323               ("Unexpected pragma id in Emit_To_PUinfo_Pragmas()"));
01324       break;
01325    }
01326    Prepend_And_Reclaim_Token_List(PUinfo_pragmas, &tokens);
01327 } /* Emit_To_PUinfo_Pragmas */
01328 
01329 
01330 static const WN *
01331 Get_Enclosing_Parallel_Region(const WN *construct)
01332 {
01333    WN *found_parallel = NULL;
01334 
01335    construct = W2CF_Get_Parent(construct);
01336    while (found_parallel == NULL && construct != NULL)
01337    {
01338       if (WN_operator(construct) == OPR_REGION)
01339       {
01340          WN *pragma = WN_first(WN_region_pragmas(construct));
01341          if (WN_pragma(pragma) == WN_PRAGMA_PARALLEL_BEGIN)
01342             found_parallel = pragma;
01343       }
01344       construct = W2CF_Get_Parent(construct);
01345    }
01346    return found_parallel;
01347 } /* Get_Enclosing_Parallel_Region */
01348 
01349 
01350 static void
01351 WN2C_process_pragma(TOKEN_BUFFER tokens, const WN **next, CONTEXT context)
01352 {
01353    /* This procedure will translate the "next" pragma and and any associated
01354     * clauses, such that "next" end up pointing to the WN* after the pragma
01355     * and clauses.
01356     */
01357    const WN *apragma = *next;
01358    const WN *this_pragma = apragma;
01359    const WN *first_clause;
01360    const WN *surrounding_region;
01361 
01362    Is_True(WN_operator(apragma) == OPR_PRAGMA ||
01363            WN_operator(apragma) == OPR_XPRAGMA,
01364            ("Invalid operator for WN2C_process_pragma()"));
01365 
01366    // Set the context to correctly handle nested clauses for this
01367    // pragma.
01368    //
01369    if (WN2C_is_omp(apragma))
01370       CONTEXT_set_omp(context);
01371    
01372    switch (WN_pragma(apragma))
01373    {
01374    case WN_PRAGMA_INLINE_DEPTH:
01375       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01376       Append_Token_String(tokens,"inline_depth");
01377       Append_Token_Special(tokens,'(');
01378       EMIT_ARG_NUMBERS1(tokens, WN_pragma_arg1(apragma));
01379       Append_Token_Special(tokens,')');
01380       break;
01381 
01382    case WN_PRAGMA_AGGRESSIVE_INNER_LOOP_FISSION:
01383       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01384       Append_Token_String(tokens,"aggressive inner loop fission");
01385       break;
01386 
01387    case WN_PRAGMA_FISSION:
01388       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01389       Append_Token_String(tokens,"fission");
01390       PARENTHESIZE_ARG_NUMBERS1(tokens, WN_pragma_arg1(apragma));
01391       break;
01392 
01393    case WN_PRAGMA_FISSIONABLE:
01394       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01395       Append_Token_String(tokens,"fissionable");
01396       break;
01397 
01398    case WN_PRAGMA_FUSE:
01399       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01400       Append_Token_String(tokens,"fuse");
01401       PARENTHESIZE_ARG_NUMBERS2(tokens, 
01402                                 WN_pragma_arg1(apragma),
01403                                 WN_pragma_arg2(apragma));
01404       break;
01405 
01406    case WN_PRAGMA_FUSEABLE:
01407       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01408       Append_Token_String(tokens,"fusable");
01409       break;
01410 
01411    case WN_PRAGMA_NO_FISSION:
01412       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01413       Append_Token_String(tokens,"no fission");
01414       break;
01415 
01416    case WN_PRAGMA_NO_FUSION:
01417       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01418       Append_Token_String(tokens,"no fusion");
01419       break; 
01420 
01421    case WN_PRAGMA_INTERCHANGE:
01422       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01423       Append_Token_String(tokens, "interchange");
01424       Append_Clause_Symbols(tokens, (WN_PRAGMA_ID)WN_pragma(apragma),
01425                             &apragma);
01426       break;
01427 
01428    case WN_PRAGMA_NO_INTERCHANGE:
01429       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01430       Append_Token_String(tokens, "no interchange");
01431       break;
01432 
01433    case WN_PRAGMA_BLOCKING_SIZE:
01434       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01435       Append_Token_String(tokens, "blocking size");
01436       PARENTHESIZE_ARG_NUMBERS2(tokens, 
01437                                 WN_pragma_arg1(apragma),
01438                                 WN_pragma_arg2(apragma));
01439       break;
01440 
01441    case WN_PRAGMA_NO_BLOCKING:
01442       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01443       Append_Token_String(tokens, "no blocking");
01444       break;
01445 
01446    case WN_PRAGMA_UNROLL:
01447       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01448       Append_Token_String(tokens, "unroll");
01449       PARENTHESIZE_ARG_NUMBERS2(tokens, 
01450                                 WN_pragma_arg1(apragma), 
01451                                 WN_pragma_arg2(apragma));
01452       break;
01453 
01454    case WN_PRAGMA_BLOCKABLE:
01455       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01456       Append_Token_String(tokens, "blockable");
01457       Append_Clause_Symbols(tokens, (WN_PRAGMA_ID)WN_pragma(apragma),
01458                             &apragma);
01459       break;
01460 
01461    case WN_PRAGMA_PREFETCH:
01462       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01463       Append_Token_String(tokens, "prefetch");
01464       PARENTHESIZE_ARG_NUMBERS2(tokens, 
01465                                 WN_pragma_arg1(apragma),
01466                                 WN_pragma_arg2(apragma));
01467       break;
01468 
01469    case WN_PRAGMA_PREFETCH_MANUAL:
01470       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01471       Append_Token_String(tokens, "prefetch_manual");
01472       PARENTHESIZE_ARG_NUMBERS1(tokens, WN_pragma_arg1(apragma));
01473       break;
01474 
01475    case WN_PRAGMA_PREFETCH_REF:
01476       if (WN_next(apragma) != NULL && 
01477           WN_operator(WN_next(apragma)) == OPR_PREFETCH)
01478       {
01479          WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01480          Append_Token_String(tokens, "prefetch_ref");
01481          Append_Prefetch_Attributes(tokens, 
01482                                     WN_next(apragma),
01483                                     WN_pragma_arg2(apragma));
01484       }
01485       break;
01486 
01487    case WN_PRAGMA_PREFETCH_REF_DISABLE:
01488       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01489       Append_Token_String(tokens, "prefetch_ref_disable");
01490       Append_Token_Special(tokens, '=');
01491       Append_A_Clause_Symbol(tokens, apragma, 0/*ofst*/);
01492       if (WN_pragma_arg2(apragma) > 0)
01493       {
01494          Append_Token_Special(tokens, ',');
01495          Append_Token_String(tokens, "size");
01496          Append_Token_Special(tokens, '=');
01497          EMIT_ARG_NUMBERS1(tokens, WN_pragma_arg2(apragma));
01498       }         
01499       break;
01500       
01501    case WN_PRAGMA_DISTRIBUTE:
01502       Emit_To_PUinfo_Pragmas(&apragma, context);
01503       break;
01504       
01505    case WN_PRAGMA_REDISTRIBUTE:
01506       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01507       Append_Token_String(tokens, "redistribute");
01508       Append_A_Clause_Symbol(tokens, apragma, 0/*ofst*/);
01509       Append_Distribution(tokens, &apragma, WN_PRAGMA_REDISTRIBUTE);
01510       Append_Pragma_Clauses(tokens, &apragma, context);
01511       break;
01512       
01513    case WN_PRAGMA_DISTRIBUTE_RESHAPE:
01514       Emit_To_PUinfo_Pragmas(&apragma, context);
01515       break;
01516       
01517    case WN_PRAGMA_DYNAMIC:
01518       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01519       Append_Token_String(tokens, "dynamic");
01520       Append_A_Clause_Symbol(tokens, apragma, 0/*ofst*/);
01521       break;
01522 
01523    case WN_PRAGMA_IVDEP:
01524       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01525       Append_Token_String(tokens, "ivdep");
01526       break;
01527 
01528    case WN_PRAGMA_DOACROSS:
01529       /* Ignore deeper nests.
01530        */
01531       if (WN_pragma_nest(apragma) <= 0 && 
01532           !Ignore_Synchronized_Construct(apragma, context))
01533       {
01534          surrounding_region = W2CF_Get_Parent(W2CF_Get_Parent(apragma));
01535          first_clause = WN_next(apragma);
01536 
01537          WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01538          Append_Token_String(tokens, "parallel");
01539          WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
01540          Append_Token_Special(tokens, '{');
01541          WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01542          Append_Token_String(tokens, "pfor");
01543          if (WN_max_nest_level(apragma) > 1)
01544             Append_Nest_Clauses(tokens, 
01545                                 surrounding_region, 
01546                                 WN_max_nest_level(apragma),
01547                                 context);
01548          apragma = first_clause;
01549          Append_Pragma_Clauses(tokens, &apragma, context);
01550          Append_Implicit_Locals(tokens, 
01551                                 WN_PRAGMA_DOACROSS, 
01552                                 WN_region_body(surrounding_region),
01553                                 first_clause,
01554                                 context);
01555          Increment_Indentation();
01556       }
01557       else
01558       {
01559          apragma = WN_next(apragma);
01560          Skip_Pragma_Clauses(&apragma, context);
01561       }
01562       break;
01563 
01564    case WN_PRAGMA_MPSCHEDTYPE:
01565       /* Can be both a clause and a pragma.
01566        */
01567       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01568       if (CONTEXT_omp(context))
01569       {
01570          Append_Clause_Newline(tokens, context);
01571          Append_Token_String(tokens, "schedule");
01572          Append_Token_Special(tokens, '(');
01573          Append_MP_Schedtype(tokens, WN_mp_schedtype(apragma));
01574          if (WN_next(apragma) != NULL &&
01575              WN_pragma(WN_next(apragma)) == WN_PRAGMA_CHUNKSIZE)
01576          {
01577             apragma = WN_next(apragma);
01578             Append_Token_Special(tokens, ',');
01579             WN2C_Append_Value_Reference(tokens, WN_kid0(apragma));
01580          }
01581          Append_Token_Special(tokens, ')');
01582          apragma = WN_next(apragma);
01583       }
01584       else
01585       {
01586          Append_Token_String(tokens, "mp_schedtype");
01587          Append_Token_Special(tokens, '(');
01588          Append_MP_Schedtype(tokens, WN_mp_schedtype(apragma));
01589          Append_Token_Special(tokens, ')');
01590       }
01591       break;
01592 
01593    case WN_PRAGMA_BARRIER:
01594       if (W2C_Prompf_Emission)
01595          WN2C_Start_Prompf_Construct(tokens, apragma);
01596       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01597       if (CONTEXT_omp(context))
01598          Append_Token_String(tokens, "omp barrier");
01599       else
01600          Append_Token_String(tokens, "synchronize");
01601       if (W2C_Prompf_Emission)
01602          WN2C_End_Prompf_Construct(tokens, apragma);
01603       break;
01604 
01605    case WN_PRAGMA_COPYIN:
01606       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01607       if (CONTEXT_omp(context))
01608          Append_Token_String(tokens, "omp copyin");
01609       else
01610          Append_Token_String(tokens, "copyin");
01611       if (WN_operator(apragma) == OPR_XPRAGMA)
01612          Append_Clause_Expressions(tokens, 
01613                                    (WN_PRAGMA_ID)WN_pragma(apragma),
01614                                    &apragma);
01615       else
01616       {
01617          ST2C_use_translate(tokens, WN_st(apragma), context);
01618       }
01619       break;
01620 
01621    case WN_PRAGMA_CRITICAL_SECTION_BEGIN:
01622       if (W2C_Prompf_Emission)
01623          WN2C_Start_Prompf_Construct(tokens, apragma);
01624       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01625       if (CONTEXT_omp(context))
01626          Append_Token_String(tokens, "omp critical");
01627       else
01628          Append_Token_String(tokens, "critical");
01629       if (WN_operator(apragma) == OPR_XPRAGMA)
01630          Append_Clause_Expressions(tokens,
01631                                    (WN_PRAGMA_ID)WN_pragma(apragma),
01632                                    &apragma);
01633       WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
01634       Append_Token_Special(tokens, '{');
01635       Increment_Indentation();
01636       break;
01637 
01638    case WN_PRAGMA_CRITICAL_SECTION_END:
01639       Decrement_Indentation();
01640       WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
01641       Append_Token_Special(tokens, '}');
01642       if (W2C_Prompf_Emission)
01643          WN2C_End_Prompf_Construct(tokens, apragma);
01644       break;
01645 
01646    case WN_PRAGMA_ORDERED_BEGIN:
01647       if (W2C_Prompf_Emission)
01648          WN2C_Start_Prompf_Construct(tokens, apragma);
01649       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01650       Append_Token_String(tokens, "omp ordered");
01651       if (WN_operator(apragma) == OPR_XPRAGMA)
01652          Append_Clause_Expressions(tokens,
01653                                    (WN_PRAGMA_ID)WN_pragma(apragma),
01654                                    &apragma);
01655       WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
01656       Append_Token_Special(tokens, '{');
01657       Increment_Indentation();
01658       break;
01659 
01660    case WN_PRAGMA_ORDERED_END:
01661       Decrement_Indentation();
01662       WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
01663       Append_Token_Special(tokens, '}');
01664       if (W2C_Prompf_Emission)
01665          WN2C_End_Prompf_Construct(tokens, apragma);
01666       break;
01667 
01668    case WN_PRAGMA_ATOMIC:
01669       if (W2C_Prompf_Emission)
01670          WN2C_Start_Prompf_Construct(tokens, apragma);
01671       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01672       Append_Token_String(tokens, "omp atomic");
01673       if (WN_operator(apragma) == OPR_XPRAGMA)
01674          Append_Clause_Expressions(tokens,
01675                                    (WN_PRAGMA_ID)WN_pragma(apragma),
01676                                    &apragma);
01677       if (W2C_Prompf_Emission)
01678          WN2C_End_Prompf_Construct(tokens, this_pragma);
01679       break;
01680 
01681    case WN_PRAGMA_PARALLEL_BEGIN:
01682       if (!Ignore_Synchronized_Construct(apragma, context))
01683       {
01684          surrounding_region = W2CF_Get_Parent(W2CF_Get_Parent(apragma));
01685          first_clause = WN_next(apragma);
01686 
01687          WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01688          if (CONTEXT_omp(context))
01689             Append_Token_String(tokens, "omp parallel");
01690          else
01691             Append_Token_String(tokens, "parallel");
01692          apragma = first_clause;
01693          Append_Pragma_Clauses(tokens, &apragma, context);
01694          Append_Implicit_Locals(tokens, 
01695                                 WN_PRAGMA_PARALLEL_BEGIN, 
01696                                 WN_region_body(surrounding_region),
01697                                 first_clause,
01698                                 context);
01699          WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
01700          Append_Token_Special(tokens, '{');
01701          Increment_Indentation();
01702       }
01703       break;
01704 
01705    case WN_PRAGMA_PARALLEL_DO:
01706       /* Ignore deeper nests.
01707        */
01708       if (WN_pragma_nest(apragma) <= 0 &&
01709           !Ignore_Synchronized_Construct(apragma, context))
01710       {
01711          surrounding_region = W2CF_Get_Parent(W2CF_Get_Parent(apragma));
01712          first_clause = WN_next(apragma);
01713 
01714          WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01715          if (CONTEXT_omp(context))
01716          {
01717             Append_Token_String(tokens, "omp parallel for");
01718          }
01719          else
01720          {
01721             Append_Token_String(tokens, "parallel");
01722             WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
01723             Append_Token_Special(tokens, '{');
01724             WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01725             Append_Token_String(tokens, "pfor");
01726          }
01727          if (WN_max_nest_level(apragma) > 1)
01728             Append_Nest_Clauses(tokens, 
01729                                 surrounding_region, 
01730                                 WN_max_nest_level(apragma),
01731                                 context);
01732          apragma = first_clause;
01733          Append_Pragma_Clauses(tokens, &apragma, context);
01734          Append_Implicit_Locals(tokens, 
01735                                 WN_PRAGMA_PARALLEL_DO, 
01736                                 WN_region_body(surrounding_region),
01737                                 first_clause,
01738                                 context);
01739           
01740          if (CONTEXT_omp(context))
01741          {
01742             WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
01743             Append_Token_Special(tokens, '{');
01744          }
01745          Increment_Indentation();
01746       }
01747       else
01748       {
01749          apragma = WN_next(apragma);
01750          Skip_Pragma_Clauses(&apragma, context);
01751       }
01752       break;
01753 
01754    case WN_PRAGMA_PDO_BEGIN:
01755       /* Ignore deeper nests.
01756        */
01757       if (WN_pragma_nest(apragma) == 0 &&
01758           !Ignore_Synchronized_Construct(apragma, context))
01759       {
01760          surrounding_region = W2CF_Get_Parent(W2CF_Get_Parent(apragma));
01761          first_clause = WN_next(apragma);
01762 
01763          WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01764          if (CONTEXT_omp(context)) 
01765             Append_Token_String(tokens, "omp for");
01766          else
01767             Append_Token_String(tokens, "pfor");
01768          if (WN_max_nest_level(apragma) > 1)
01769             Append_Nest_Clauses(tokens, 
01770                                 surrounding_region, 
01771                                 WN_max_nest_level(apragma),
01772                                 context);
01773          apragma = first_clause;
01774          Append_Pragma_Clauses(tokens, &apragma, context);
01775 
01776          /* Turn this off for now, since we also need to avoid declaring
01777           * as local variables declared as shared in the enclosing
01778           * parallel region.
01779           *
01780           * Append_Implicit_Locals(tokens, 
01781           *             WN_PRAGMA_PARALLEL_DO 
01782           *             WN_region_body(surrounding_region),
01783           *             first_clause,
01784           *             context);
01785           */
01786       }
01787       else
01788       {
01789          apragma = WN_next(apragma);
01790          Skip_Pragma_Clauses(&apragma, context);
01791       }
01792       break;
01793 
01794    case WN_PRAGMA_PARALLEL_SECTIONS:
01795    case WN_PRAGMA_PSECTION_BEGIN:
01796       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01797       if (CONTEXT_omp(context)) 
01798          Append_Token_String(tokens, "omp parallel sections");
01799       else
01800          Append_Token_String(tokens, "psections");
01801       apragma = WN_next(apragma);
01802       Append_Pragma_Clauses(tokens, &apragma, context);
01803       WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
01804       Append_Token_Special(tokens, '{');
01805       Increment_Indentation();
01806       break;
01807 
01808    case WN_PRAGMA_ENTER_GATE:
01809       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01810       Append_Token_String(tokens, "enter gate");
01811       break;
01812 
01813    case WN_PRAGMA_EXIT_GATE:
01814       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01815       Append_Token_String(tokens, "exit gate");
01816       break;
01817       
01818    case WN_PRAGMA_INDEPENDENT_BEGIN:
01819       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01820       Append_Token_String(tokens, "independent");
01821       apragma = WN_next(apragma);
01822       Append_Pragma_Clauses(tokens, &apragma, context);
01823       WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
01824       Append_Token_Special(tokens, '{');
01825       Increment_Indentation();
01826       break;
01827 
01828    case WN_PRAGMA_INDEPENDENT_END:
01829       Decrement_Indentation();
01830       WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
01831       Append_Token_Special(tokens, '}');
01832       break;
01833 
01834    case WN_PRAGMA_SECTION:
01835       if (W2C_Prompf_Emission)
01836       {
01837          if (WN2C_Prompf_Subsection != NULL)
01838          {
01839             // End a the previous SECTION directive seen!
01840             //
01841             WN2C_End_Prompf_Construct(tokens, WN2C_Prompf_Subsection);
01842          }
01843          WN2C_Prompf_Subsection = apragma;
01844          WN2C_Start_Prompf_Construct(tokens, apragma);
01845       }
01846       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01847       if (CONTEXT_omp(context)) 
01848          Append_Token_String(tokens, "omp section");
01849       else
01850          Append_Token_String(tokens, "section");
01851       break;
01852 
01853    case WN_PRAGMA_SINGLE_PROCESS_BEGIN:
01854       if (!Ignore_Synchronized_Construct(apragma, context))
01855       {
01856          WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01857          if (CONTEXT_omp(context))
01858             Append_Token_String(tokens, "omp single");
01859          else
01860             Append_Token_String(tokens, "one processor");
01861          apragma = WN_next(apragma);
01862          Append_Pragma_Clauses(tokens, &apragma, context);
01863          WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
01864          Append_Token_Special(tokens, '{');
01865          Increment_Indentation();
01866       }
01867       break;
01868 
01869     case WN_PRAGMA_MASTER_BEGIN:
01870       if (!Ignore_Synchronized_Construct(apragma, context))
01871       {
01872          WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01873          if (CONTEXT_omp(context))
01874            Append_Token_String(tokens, "omp master");
01875          else
01876            Append_Token_String(tokens, "master process");
01877       }
01878       break;
01879 
01880    case WN_PRAGMA_NUMTHREADS:
01881       /* Should only appear for C, but if we ever see it, we also emit
01882        * it for Fortran.
01883        */
01884       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01885       Append_Token_String(tokens, "numthreads");
01886       Append_Clause_Expressions(tokens,
01887                                 (WN_PRAGMA_ID)WN_pragma(apragma),
01888                                 &apragma);
01889       break;
01890 
01891    case WN_PRAGMA_PAGE_PLACE:
01892       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01893       Append_Token_String(tokens, "page_place");
01894       Append_Clause_Expressions(tokens,
01895                                 (WN_PRAGMA_ID)WN_pragma(apragma),
01896                                 &apragma);
01897       break;
01898 
01899    case WN_PRAGMA_NORECURRENCE:
01900       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01901       Append_Token_String(tokens, "no recurrence");
01902       break;
01903 
01904    case WN_PRAGMA_NEXT_SCALAR:
01905       WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
01906       Append_Token_String(tokens, "next scalar");
01907       break;
01908       
01909    default:
01910       /* The others are always clauses that are processed as part of other
01911        * pragmas, or they are not to be emitted.
01912        */
01913       break;
01914 
01915    } /* switch on pragma cases */
01916 
01917    /* See if we have already advanced to the next pragma, e.g. as a result
01918     * of calling Append_Pragma_Clauses() or Append_Clause_Symbols(),
01919     * and if not so, then advance to the next pragma.
01920     */
01921    if (apragma == *next)
01922       *next = WN_next(apragma);
01923    else
01924       *next = apragma;
01925 
01926 } /* WN2C_process_pragma */
01927 
01928 
01929 /* ====================== Exported Functions ====================== */
01930 /* ================================================================ */
01931 
01932 
01933 BOOL
01934 WN2C_Skip_Pragma_Stmt(const WN *wn)
01935 {
01936    /* This assumes that any pragma related nodes to be skipped will be
01937     * accessed in sequence, and that this routine will be called at most
01938     * once per such node.
01939     */
01940    BOOL found = (Pragmas_To_Skip.array[Pragmas_To_Skip.start] == wn);
01941 
01942    if (found)
01943    {
01944       if (Pragmas_To_Skip.end - Pragmas_To_Skip.start == 1)
01945       {
01946          Pragmas_To_Skip.start = Pragmas_To_Skip.end = 0;
01947          Pragmas_To_Skip.array[0] = NULL;
01948       }
01949       else
01950       {
01951          Pragmas_To_Skip.start++;
01952       }
01953    }
01954    return found;
01955 } /* WN2C_Skip_Pragma_Stmt */
01956 
01957 
01958 STATUS
01959 WN2C_pragma(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
01960 {
01961    const WN *skip;
01962    const WN *next = wn;
01963 
01964    Is_True(WN_operator(wn) == OPR_PRAGMA || WN_operator(wn) == OPR_XPRAGMA,
01965            ("Invalid operator for WN2C_pragma()"));
01966 
01967    /* If this is a purple code-extraction, insert a placeholder
01968     * for purple-specific initialization.
01969     */
01970    if (W2C_Purple_Emission && WN_pragma(wn) == WN_PRAGMA_PREAMBLE_END)
01971    {
01972       /* <#PRP_XSYM:INIT name, id, sclass, export#>
01973        */
01974       Append_Indented_Newline(tokens, 1);
01975       Append_Token_String(tokens, "<#PRP_XSYM:INIT_STMT");
01976       WN2C_Append_Purple_Funcinfo(tokens);
01977       Append_Token_String(tokens, "#>");
01978       next = WN_next(wn);
01979    }
01980    else
01981    {
01982       WN2C_process_pragma(tokens, &next, context);
01983    }
01984 
01985    Is_True(Pragmas_To_Skip.end == 0,
01986            ("Unexpected index for Pragmas_To_Skip in WN2C_pragma()"));
01987 
01988    /* For pragmas inlined in code, we need to keep track of the pragmas
01989     * that have already been processed.
01990     */
01991    for (skip = WN_next(wn); skip != next; skip = WN_next(skip))
01992    {
01993       Is_True(Pragmas_To_Skip.end < MAX_PRAGMAS_TO_SKIP,
01994               ("Too many pragmas in sequence in WN2C_pragma()"));
01995 
01996       Pragmas_To_Skip.array[Pragmas_To_Skip.end++] = skip;
01997    }
01998 
01999    return EMPTY_STATUS;
02000 } /* WN2C_pragma */
02001 
02002 
02003 STATUS 
02004 WN2C_pragma_list_begin(TOKEN_BUFFER tokens,
02005                        const WN    *first_pragma,
02006                        CONTEXT      context)
02007 {
02008    const WN *next_pragma = first_pragma;
02009 
02010    while (next_pragma != NULL)
02011    {
02012       if (WN_operator(next_pragma) == OPR_PRAGMA ||
02013           WN_operator(next_pragma) == OPR_XPRAGMA)
02014          WN2C_process_pragma(tokens, &next_pragma, context);
02015       else
02016          next_pragma = WN_next(next_pragma);
02017    }
02018    return EMPTY_STATUS;
02019 } /* WN2C_pragma_list_begin */
02020 
02021 
02022 STATUS 
02023 WN2C_pragma_list_end(TOKEN_BUFFER tokens, 
02024                      const WN    *first_pragma,
02025                      CONTEXT context)
02026 {
02027    /* Skip code inserted into the pragma region (may occur for C++).
02028     */
02029    while (first_pragma != NULL                  &&
02030           WN_operator(first_pragma) != OPR_PRAGMA &&
02031           WN_operator(first_pragma) != OPR_XPRAGMA)
02032    {
02033       first_pragma = WN_next(first_pragma);
02034    }
02035 
02036    if (first_pragma != NULL)
02037    {
02038       Is_True(WN_operator(first_pragma) == OPR_PRAGMA ||
02039               WN_operator(first_pragma) == OPR_XPRAGMA, 
02040               ("Unexpected operator (%d) in WN2C_pragma_list_end()",
02041                WN_operator(first_pragma)));
02042       
02043       switch (WN_pragma(first_pragma))
02044       {
02045 
02046       case WN_PRAGMA_PARALLEL_BEGIN:
02047          if (!Ignore_Synchronized_Construct(first_pragma, context))
02048          {
02049             Decrement_Indentation();
02050             WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
02051             Append_Token_Special(tokens, '}');
02052          }
02053          break;
02054 
02055       case WN_PRAGMA_DOACROSS:
02056       case WN_PRAGMA_PARALLEL_DO:
02057          if (WN_pragma_nest(first_pragma) <= 0 &&
02058              !Ignore_Synchronized_Construct(first_pragma, context))
02059          {
02060             Decrement_Indentation();
02061             WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
02062             Append_Token_Special(tokens, '}');
02063          }
02064          break;
02065 
02066       case WN_PRAGMA_PARALLEL_SECTIONS:
02067       case WN_PRAGMA_PSECTION_BEGIN:
02068          Decrement_Indentation();
02069          WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
02070          Append_Token_Special(tokens, '}');
02071          if (WN2C_is_omp(first_pragma))
02072          {
02073             if (WN2C_Prompf_Subsection != NULL)
02074             {
02075                // End a the last SECTION pragma seen!
02076                //
02077                WN2C_End_Prompf_Construct(tokens, WN2C_Prompf_Subsection);
02078                WN2C_Prompf_Subsection = NULL;
02079             }
02080          }
02081          break;
02082 
02083       case WN_PRAGMA_SINGLE_PROCESS_BEGIN:
02084          if (!Ignore_Synchronized_Construct(first_pragma, context))
02085          {
02086             Decrement_Indentation();
02087             WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
02088             Append_Token_Special(tokens, '}');
02089       }
02090       break;
02091 
02092       default:
02093          break; /* Not a region that needs an END pragma (in C, a '}'). */
02094       }
02095    }
02096    return EMPTY_STATUS;
02097 } /* WN2C_pragma_list_end */
02098 
02099 
02100 BOOL
02101 Ignore_Synchronized_Construct(const WN *construct_pragma,  
02102                               CONTEXT   context)
02103 {
02104    /* This can be TRUE for DOACROSS, PARALLEL, and any paralellization
02105     * related construct that may occur within a parallel region.
02106     * It only applies for prompf/mplist (i.e. when Run_w2fc_early).
02107     */
02108    BOOL ignore_construct;
02109 
02110    Is_True(WN_operator(construct_pragma) == OPR_PRAGMA,
02111            ("Unexpected WHIRL tree in Ignore_Synchronized_Construct"));
02112 
02113    if (!Run_w2fc_early)
02114       ignore_construct = FALSE;
02115    else
02116    {
02117       if (WN_pragma(construct_pragma) != WN_PRAGMA_DOACROSS)
02118          construct_pragma = Get_Enclosing_Parallel_Region(construct_pragma);
02119 
02120       if (construct_pragma == NULL)
02121          ignore_construct = FALSE;
02122       else
02123       {
02124          const WN *clause = WN_next(construct_pragma);
02125          const WN *beyond_last_clause = clause;
02126 
02127          Skip_Pragma_Clauses(&beyond_last_clause, context);
02128          while (clause != beyond_last_clause && 
02129                 WN_pragma(clause) != WN_PRAGMA_SYNC_DOACROSS)
02130             clause = WN_next(clause);
02131          ignore_construct = (clause != beyond_last_clause);
02132       }
02133    }
02134    return ignore_construct;
02135 } /* Ignore_Synchronized_Construct */
02136 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines