Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
mem_ctr.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 #include "mem_ctr.h"
00038 #include "wn.h"
00039 #include "stab.h"
00040 #include "strtab.h"
00041 #include "mtypes.h"
00042 #include "targ_const.h"
00043 #include "wn_util.h"
00044 #include "config_targ.h"
00045 #include "const.h"
00046 #include "cxx_template.h"
00047 #include "cxx_hash.h"
00048 
00049 /***********************************************************************
00050  *
00051  * Exported symbols.
00052  *
00053  ***********************************************************************/
00054 
00055 extern void MemCtr_Add (WN* pu);
00056 
00057 /***********************************************************************
00058  *
00059  * Local declarations.
00060  *
00061  ***********************************************************************/
00062 
00063 static INT memctr_size = 8192;  /* default at least half a page */
00064 
00065 static ST *reg_st_global;
00066 static ST *reg_st_local;
00067 static ST *unreg_st_local;
00068 static ST *reg_st_common;
00069 
00070 static ST*  Declare_Function (char* ty_name, char* st_name, 
00071                               INT nparms, TY *ty_array[]);
00072 static void Set_Call_Side_Effects (WN* call_wn);
00073 static void MemCtr_Init ();
00074 static BOOL MemCtr_Criteria_Check (ST* st);
00075 
00076 static MEM_POOL memctr_pool;
00077 static WN_MAP Parent_Map = WN_MAP_UNDEFINED;
00078 #define Set_Parent(wn, p) (WN_MAP_Set(Parent_Map, wn, (void*)  p))
00079 #define Get_Parent(wn) ((WN*) WN_MAP_Get(Parent_Map, (WN*) wn))
00080 static void Parentize (WN* wn);
00081 
00082 typedef STACK<WN *> STACK_OF_WN;
00083 typedef HASH_TABLE<ST*, BOOL> STBOOL_HASH_TABLE;
00084 
00085 static void MemCtr_Add_Global (WN* pu, ST* st,
00086                                STACK_OF_WN *altentry_stack);
00087 static void MemCtr_Add_Common (WN* pu, ST* st,
00088                                STACK_OF_WN *altentry_stack);
00089 static void MemCtr_Add_Local  (WN* pu, ST* st,
00090                                STACK_OF_WN *altentry_stack,
00091                                STACK_OF_WN *exit_stack);
00092 
00093 static void Collect_Goodies (WN* pu,
00094                              STACK_OF_WN *exit_stack,
00095                              STACK_OF_WN *altentry_stack,
00096                              STBOOL_HASH_TABLE *used_st_hash);
00097 
00098 extern void MemCtr_Add (WN* pu) {
00099   ST* st;
00100 
00101   STACK_OF_WN *altentry_stack = NULL;
00102   STACK_OF_WN *exit_stack = NULL;
00103 
00104   STBOOL_HASH_TABLE *used_st_hash = NULL;
00105 
00106   // one-time initializations
00107   {
00108     static BOOL memctr_initialized = FALSE;
00109     if (!memctr_initialized) {
00110       memctr_initialized = TRUE;
00111       MemCtr_Init ();
00112     }
00113   }
00114 
00115   MEM_POOL_Push (&memctr_pool);
00116 
00117   Parent_Map = WN_MAP_Create (&memctr_pool);
00118   Parentize (pu);
00119 
00120   // walk the tree, store all the STs that are referenced,
00121   // and collect exit points and alt-entries
00122   {
00123 
00124     // Create stack to collect the exit points in the PU
00125     exit_stack = CXX_NEW(STACK_OF_WN(&memctr_pool), &memctr_pool);
00126 
00127     // Create stack to collect the alt-entries in the PU
00128     if (PU_has_altentry(Get_Current_PU())) {
00129       altentry_stack = CXX_NEW (STACK_OF_WN(&memctr_pool), &memctr_pool);
00130     }
00131 
00132     // Create hash-table to collect referenced symbols
00133     used_st_hash = CXX_NEW(STBOOL_HASH_TABLE(200,&memctr_pool),&memctr_pool);
00134 
00135     // Walk the tree, collecting exits, altentries, and used STs
00136     Collect_Goodies (pu, exit_stack,
00137                      altentry_stack, used_st_hash);
00138   }
00139 
00140 
00141 
00142   INT i;
00143   FOREACH_SYMBOL(GLOBAL_SYMTAB, st, i) {
00144     if (ST_class(st) == CLASS_VAR &&
00145         used_st_hash->Find(st) &&
00146         !ST_is_reshaped(st)) {
00147       MemCtr_Add_Global (pu, st, altentry_stack);
00148     }
00149   }
00150 
00151   FOREACH_SYMBOL(CURRENT_SYMTAB, st, i) {
00152     if (ST_class(st) == CLASS_VAR && used_st_hash->Find(st)) {
00153       if (
00154           ST_base(st) != st &&
00155           ST_sclass(ST_base(st)) == SCLASS_COMMON) {
00156         if (!ST_is_reshaped(st)) {
00157           MemCtr_Add_Common (pu, st, altentry_stack);
00158         }
00159       }
00160       else {
00161         if (!ST_is_reshaped(st)) {
00162           MemCtr_Add_Local (pu, st, altentry_stack, exit_stack);
00163         }
00164       }
00165     }
00166   }
00167 
00168   WN_MAP_Delete (Parent_Map);
00169   Parent_Map = WN_MAP_UNDEFINED;
00170   MEM_POOL_Pop (&memctr_pool);
00171 }
00172 
00173 static void Parentize (WN* wn) {
00174   if (!OPCODE_is_leaf (WN_opcode (wn))) { 
00175     if (WN_opcode(wn) == OPC_BLOCK) {
00176       WN* kid = WN_first (wn);
00177       while (kid) {
00178         Set_Parent (kid, wn);
00179         Parentize (kid);
00180         kid = WN_next (kid);
00181       }
00182     }
00183     else {
00184       INT kidno;
00185       WN* kid;
00186       for (kidno=0; kidno<WN_kid_count(wn); kidno++) {
00187         kid = WN_kid (wn, kidno);
00188         if (kid) { 
00189           Set_Parent (kid, wn);
00190           Parentize (kid);
00191         }
00192       }
00193     }
00194   }
00195 }
00196 
00197 /***********************************************************************
00198  *
00199  * Given an array node, find the base ST.
00200  *
00201  ***********************************************************************/
00202 static ST *Find_Address_Base (WN* wn) {
00203   FmtAssert (wn && (WN_operator(wn) == OPR_ILOAD ||
00204                     WN_operator(wn) == OPR_ISTORE),
00205              ("Find_Address_Base: expected an ILOAD/ISTORE node"));
00206 
00207   if (WN_operator(wn) == OPR_ILOAD)
00208     wn = WN_kid0(wn);
00209   else wn = WN_kid1(wn);
00210 
00211   // wn is now the address expression
00212   OPERATOR opr = WN_operator(wn);
00213   if (opr == OPR_LDID || opr == OPR_LDA) 
00214     return &St_Table[WN_st_idx(wn)];
00215 
00216   return NULL;
00217 }
00218 
00219 static void Collect_Goodies (WN* wn,
00220                              STACK_OF_WN *exit_stack,
00221                              STACK_OF_WN *altentry_stack,
00222                              STBOOL_HASH_TABLE *used_st_hash) {
00223 
00224   if (!wn) return;
00225 
00226   OPCODE opc = WN_opcode(wn);
00227   OPERATOR opr = OPCODE_operator(opc);
00228 
00229   if (opr == OPR_RETURN) {
00230     exit_stack->Push(wn);
00231     return;
00232   }
00233 
00234   if (opr == OPR_INTRINSIC_CALL && (WN_intrinsic(wn) == INTRN_STOP || 
00235                                     WN_intrinsic(wn) == INTRN_STOP_F90)) {
00236     exit_stack->Push (wn);
00237     return;
00238   }
00239 
00240   if (opr == OPR_ALTENTRY) {
00241     altentry_stack->Push (wn);
00242     return;
00243   }
00244   
00245   if ((opr==OPR_ILOAD && WN_operator(WN_kid0(wn))==OPR_ARRAY) ||
00246       (opr==OPR_ISTORE && WN_operator(WN_kid1(wn))==OPR_ARRAY))
00247     {
00248       WN* address_wn = (opr == OPR_ILOAD ? WN_kid0(wn) : WN_kid1(wn));
00249       if (WN_operator(address_wn) == OPR_LDID ||
00250           WN_operator(address_wn) == OPR_LDA) {
00251         
00252         ST *st = &St_Table[WN_st_idx(address_wn)];
00253         if (!used_st_hash->Find(st)) used_st_hash->Enter (st, TRUE);
00254       }
00255     }
00256 
00257   ST *st = &St_Table[WN_st_idx(wn)];
00258 
00259   if ((opr == OPR_LDA && TY_kind(ST_type(st)) == KIND_ARRAY) ||
00260       (opr == OPR_LDID && 
00261        ST_base(st) &&
00262        ST_sclass(ST_base(st)) == SCLASS_AUTO) ||
00263       (opr == OPR_LDID && TY_kind(ST_type(st)) == KIND_POINTER &&
00264        TY_kind(TY_pointed(ST_type(st))) == KIND_ARRAY)) {
00265 
00266     if (!used_st_hash->Find(st)) used_st_hash->Enter (st, TRUE);
00267   }
00268   
00269   // now recurse
00270   if (opr == OPR_BLOCK) {
00271     for (WN* kid = WN_first(wn); kid; kid = WN_next(kid)) {
00272       Collect_Goodies (kid, exit_stack, altentry_stack, used_st_hash);
00273     }
00274     return;
00275   }
00276   
00277   for (INT i=0; i<WN_kid_count(wn); i++) {
00278     Collect_Goodies (WN_kid(wn, i), exit_stack, altentry_stack, used_st_hash);
00279   }
00280 }
00281 
00282 
00283 static ST* Declare_Function (char* ty_name, char* st_name, 
00284                              INT nparms, TY_IDX ty_array[])
00285 {
00286   ST* func_st;
00287   TY_IDX voidpty = Make_Pointer_Type (Be_Type_Tbl(MTYPE_V), TRUE); 
00288   TY_IDX func_ty;
00289   TY& ty = New_TY(func_ty);
00290   PU_IDX pu_idx;
00291   PU& pu = New_PU (pu_idx);
00292 
00293   TYLIST_IDX idx = Tylist_Table.Insert(voidpty);
00294   for (INT i = 0; i < nparms; i++) {
00295     Tylist_Table.Insert(ty_array[i]);
00296   }
00297   Tylist_Table.Insert(0);
00298   TY_Init (ty, TY_size(voidpty), KIND_FUNCTION, MTYPE_UNKNOWN, Save_Str(ty_name));
00299   Set_TY_tylist (ty, idx);
00300 
00301   Set_TY_align (func_ty, TY_align(voidpty));
00302   Set_PU_prototype (pu, func_ty);
00303 
00304   /* Make a ST: add function to global symbol table */
00305   func_st = New_ST ( GLOBAL_SYMTAB );
00306   ST_Init(func_st, Save_Str(st_name), CLASS_FUNC, SCLASS_EXTERN, EXPORT_PREEMPTIBLE, (TY_IDX) pu_idx);
00307   return func_st;
00308 }
00309 
00310 /***********************************************************************
00311  *
00312  * Given a call-node of one of the memory-counter registration routines,
00313  * update side-effect info.
00314  *
00315  ***********************************************************************/
00316 static void Set_Call_Side_Effects (WN* call_wn) {
00317   WN_Set_Call_Parm_Ref (call_wn);
00318 }
00319 
00320 static void MemCtr_Init () {
00321   TY_IDX ty_array[10];
00322 
00323   // make address pointer to I8, shouldn't matter.
00324   TY_IDX string_ptr_ty = Make_Pointer_Type (Be_Type_Tbl(MTYPE_U1), TRUE);
00325   TY_IDX i8_ty         = Be_Type_Tbl(MTYPE_I8);
00326   TY_IDX i8_ptr_ty     = Make_Pointer_Type (Be_Type_Tbl(MTYPE_I8), TRUE);
00327   
00328   // declare __memctr_register_global (address, size, name)
00329   {
00330     ty_array[0] = i8_ptr_ty;
00331     ty_array[1] = i8_ty;
00332     ty_array[2] = string_ptr_ty;
00333     reg_st_global = Declare_Function (".__memctr_register_global",
00334                                       "__memctr_register_global",
00335                                       3,
00336                                       ty_array);
00337   }
00338 
00339   // declare __memctr_register_common (address, size, common-name, name)
00340   {
00341     ty_array[0] = i8_ptr_ty;
00342     ty_array[1] = i8_ty;
00343     ty_array[2] = string_ptr_ty;
00344     ty_array[3] = string_ptr_ty;
00345     reg_st_common = Declare_Function (".__memctr_register_common",
00346                                       "__memctr_register_common",
00347                                       4,
00348                                       ty_array);
00349   }
00350 
00351   // declare __memctr_register_local (address, size, func-name, name)
00352   {
00353     ty_array[0] = i8_ptr_ty;
00354     ty_array[1] = i8_ty;
00355     ty_array[2] = string_ptr_ty;
00356     ty_array[3] = string_ptr_ty;
00357     reg_st_local = Declare_Function (".__memctr_register_local",
00358                                      "__memctr_register_local",
00359                                      4,
00360                                      ty_array);
00361   }
00362 
00363   // __memctr_unregister_local (address, size, func-name, name)
00364   {
00365     ty_array[0] = i8_ptr_ty;
00366     ty_array[1] = i8_ty;
00367     ty_array[2] = string_ptr_ty;
00368     ty_array[3] = string_ptr_ty;
00369     unreg_st_local = Declare_Function (".__memctr_unregister_local",
00370                                        "__memctr_unregister_local",
00371                                        4,
00372                                        ty_array);
00373   }
00374 
00375   MEM_POOL_Initialize (&memctr_pool, "memory_counter_pool", FALSE);
00376 }
00377 
00378 static BOOL MemCtr_Criteria_Check (ST* st) {
00379   if (TY_size(ST_type(st)) < memctr_size) return FALSE;
00380   return TRUE;
00381 }
00382 
00383 static BOOL Is_VLA (ST* st) {
00384   if (TY_kind(ST_type(st)) == KIND_POINTER &&
00385       TY_kind(TY_pointed(ST_type(st))) == KIND_ARRAY &&
00386       TY_size(TY_pointed(ST_type(st))) == 0) return TRUE;
00387 
00388   if (ST_base(st) &&
00389       ST_sclass(ST_base(st)) == SCLASS_AUTO)
00390     return TRUE;
00391 
00392   return FALSE;
00393 }
00394 
00395 /***********************************************************************
00396  *
00397  * Given a call-whirl tree, insert it right after the preamble in the PU,
00398  * and after the preamble in each alt-entry.
00399  *
00400  ***********************************************************************/
00401 static void Insert_Call (WN* call_wn, WN* pu, STACK_OF_WN *altentry_stack) {
00402 
00403   WN* insert_wn = WN_first(WN_func_body(pu));
00404   while (insert_wn) {
00405     if (WN_opcode(insert_wn) == OPC_PRAGMA &&
00406         WN_pragma(insert_wn) == WN_PRAGMA_PREAMBLE_END)
00407       break;
00408     insert_wn = WN_next(insert_wn);
00409   }
00410   FmtAssert (insert_wn, ("Missing function preamble in function %s\n",
00411                          ST_name(WN_st(pu))));
00412   WN_INSERT_BlockAfter (WN_func_body(pu), insert_wn, call_wn);
00413   Set_Parent (call_wn, WN_func_body(pu));
00414 
00415   if (altentry_stack && altentry_stack->Elements()) {
00416     for (INT i=0; i<altentry_stack->Elements(); i++) {
00417       insert_wn = altentry_stack->Bottom_nth(i);
00418       while (insert_wn) {
00419         if (WN_opcode(insert_wn) == OPC_PRAGMA &&
00420             WN_pragma(insert_wn) == WN_PRAGMA_PREAMBLE_END)
00421           break;
00422         insert_wn = WN_next(insert_wn);
00423       }
00424       FmtAssert (insert_wn, ("Missing function preamble in function %s\n",
00425                              ST_name(WN_st(pu))));
00426       call_wn = WN_COPY_Tree (call_wn);
00427       Parentize (call_wn);
00428       WN_INSERT_BlockAfter (Get_Parent(insert_wn), insert_wn, call_wn);
00429       Set_Parent (call_wn, Get_Parent(insert_wn));
00430     }
00431   }
00432 }   /* Insert_Call */
00433 
00434 /***********************************************************************
00435  *
00436  * Called with the PU-wn, a global-variable st to annotate, and
00437  * a stack of alternate-entries in the PU.
00438  *
00439  * Generate a call upon entry to the library routine describing this
00440  * global array. 
00441  *      __memctr_register_global (address, size, name)
00442  *
00443  ***********************************************************************/
00444 static void MemCtr_Add_Global (WN* pu, ST* st, STACK_OF_WN *altentry_stack) {
00445   if (MemCtr_Criteria_Check(st)) {
00446 
00447     // create the call
00448     OPCODE callop = OPCODE_make_op (OPR_CALL, MTYPE_V, MTYPE_V);
00449     WN* call_wn = WN_Create (callop, 3);
00450     WN_st_idx(call_wn) = ST_st_idx(reg_st_global);
00451 
00452     // parm 1: address of ST
00453     OPCODE lda_op = OPCODE_make_op (OPR_LDA, Pointer_type, MTYPE_V);
00454     TY_IDX ptr_ty = Make_Pointer_Type (ST_type(st), Is_Global_Symbol(st));
00455     WN* parm_wn = WN_CreateLda (lda_op, 0, ptr_ty, st);
00456     parm_wn = WN_CreateParm (Pointer_type,
00457                              parm_wn,
00458                              ptr_ty,
00459                              WN_PARM_BY_VALUE);
00460     WN_kid0(call_wn) = parm_wn;
00461     
00462     // parm 2: size of ST
00463     OPCODE const_op = OPCODE_make_op(OPR_INTCONST, MTYPE_I8, MTYPE_V);
00464     parm_wn = WN_CreateIntconst (const_op, TY_size(ST_type(st)));
00465     parm_wn = WN_CreateParm (MTYPE_I8,
00466                              parm_wn,
00467                              Be_Type_Tbl(MTYPE_I8),
00468                              WN_PARM_BY_VALUE);
00469     WN_kid1(call_wn) = parm_wn;
00470 
00471     // parm 3: name of ST
00472     char* var_name = ST_name(st);
00473     TCON tcon = Host_To_Targ_String (MTYPE_STRING,var_name,strlen(var_name)+1);
00474     TY_IDX string_ty = Make_Pointer_Type(Be_Type_Tbl(MTYPE_U1), TRUE);
00475     ST *string_st = Gen_String_Sym (&tcon, Be_Type_Tbl(MTYPE_STRING), FALSE);
00476     parm_wn = WN_CreateLda (lda_op, 0, string_ty, string_st);
00477     parm_wn = WN_CreateParm (Pointer_type,
00478                              parm_wn,
00479                              Be_Type_Tbl(Pointer_type),
00480                              WN_PARM_BY_REFERENCE);
00481     WN_kid2(call_wn) = parm_wn;
00482 
00483     Set_Call_Side_Effects (call_wn);
00484     Parentize(call_wn);
00485 
00486     Insert_Call (call_wn, pu, altentry_stack);
00487   }
00488 }
00489 
00490 /***********************************************************************
00491  *
00492  * Called with the PU-wn, a COMMON st to annotate, and
00493  * a stack of alternate-entries in the PU.
00494  *
00495  * Generate a call upon entry to the library routine describing this
00496  * COMMON array. 
00497  *      __memctr_register_common (address, size, common-name, name)
00498  *
00499  ***********************************************************************/
00500 static void MemCtr_Add_Common (WN *pu, ST *st, STACK_OF_WN *altentry_stack) {
00501 
00502   if (MemCtr_Criteria_Check(st)) {
00503 
00504     // create the call
00505     OPCODE callop = OPCODE_make_op (OPR_CALL, MTYPE_V, MTYPE_V);
00506     WN* call_wn = WN_Create (callop, 4);
00507     WN_st_idx(call_wn) = ST_st_idx(reg_st_common);
00508 
00509     // parm 1: address of ST
00510     OPCODE lda_op = OPCODE_make_op (OPR_LDA, Pointer_type, MTYPE_V);
00511     TY_IDX ptr_ty = Make_Pointer_Type (ST_type(st), Is_Global_Symbol(st));
00512 
00513     WN* parm_wn = WN_CreateLda (lda_op, 0, ptr_ty, st);
00514     parm_wn = WN_CreateParm (Pointer_type,
00515                              parm_wn,
00516                              ptr_ty,
00517                              WN_PARM_BY_VALUE);
00518     WN_kid0(call_wn) = parm_wn;
00519     
00520     // parm 2: size of ST
00521     OPCODE const_op = OPCODE_make_op(OPR_INTCONST, MTYPE_I8, MTYPE_V);
00522     parm_wn = WN_CreateIntconst (const_op, TY_size(ST_type(st)));
00523     parm_wn = WN_CreateParm (MTYPE_I8,
00524                              parm_wn,
00525                              Be_Type_Tbl(MTYPE_I8),
00526                              WN_PARM_BY_VALUE);
00527     WN_kid1(call_wn) = parm_wn;
00528 
00529     // parm 3: name of common block
00530     char* var_name = ST_name(ST_base(st));
00531     TCON tcon = Host_To_Targ_String (MTYPE_STRING,var_name,strlen(var_name)+1);
00532     TY_IDX string_ty = Make_Pointer_Type(Be_Type_Tbl(MTYPE_U1), TRUE);
00533     ST *string_st = Gen_String_Sym (&tcon, Be_Type_Tbl(MTYPE_STRING), FALSE);
00534     parm_wn = WN_CreateLda (lda_op, 0, string_ty, string_st);
00535     parm_wn = WN_CreateParm (Pointer_type,
00536                              parm_wn,
00537                              Be_Type_Tbl(Pointer_type),
00538                              WN_PARM_BY_REFERENCE);
00539     WN_kid2(call_wn) = parm_wn;
00540 
00541     // parm 4: name of ST
00542     var_name = ST_name(st);
00543     tcon = Host_To_Targ_String (MTYPE_STRING,var_name,strlen(var_name)+1);
00544     string_ty = Make_Pointer_Type(Be_Type_Tbl(MTYPE_U1), TRUE);
00545     string_st = Gen_String_Sym (&tcon, Be_Type_Tbl(MTYPE_STRING), FALSE);
00546     parm_wn = WN_CreateLda (lda_op, 0, string_ty, string_st);
00547     parm_wn = WN_CreateParm (Pointer_type,
00548                              parm_wn,
00549                              Be_Type_Tbl(Pointer_type),
00550                              WN_PARM_BY_REFERENCE);
00551     WN_kid3(call_wn) = parm_wn;
00552 
00553     Set_Call_Side_Effects (call_wn);
00554     Parentize(call_wn);
00555 
00556     Insert_Call (call_wn, pu, altentry_stack);
00557   }
00558 }
00559 
00560 /***********************************************************************
00561  *
00562  * Called with the PU-wn, a local st to annotate, and
00563  * a stack of alternate-entries in the PU.
00564  *
00565  * Generate a call upon entry to the library routine describing this
00566  * local array. 
00567  *      __memctr_register_local (address, size, func-name, name)
00568  *
00569  * and upon each return point to
00570  *      __memctr_unregister_local (address, size, func-name, name)
00571  *
00572  ***********************************************************************/
00573 static void MemCtr_Add_Local  (WN* pu, ST* st,
00574                                STACK_OF_WN *altentry_stack,
00575                                STACK_OF_WN *exit_stack) {
00576 
00577   if (MemCtr_Criteria_Check(st) || Is_VLA(st)) {
00578 
00579     // create the call
00580     OPCODE callop = OPCODE_make_op (OPR_CALL, MTYPE_V, MTYPE_V);
00581     WN* call_wn = WN_Create (callop, 4);
00582     WN_st_idx(call_wn) = ST_st_idx(reg_st_local);
00583 
00584     // parm 1: address of ST
00585     WN *parm_wn;
00586     TY_IDX ptr_ty;
00587     OPCODE lda_op = OPCODE_make_op (OPR_LDA, Pointer_type, MTYPE_V);
00588     if (Is_VLA(st)) {
00589       OPCODE ldid_op = OPCODE_make_op (OPR_LDID, Pointer_type, Pointer_type);
00590       ptr_ty = ST_type(st);
00591       parm_wn = WN_CreateLdid (ldid_op, 0, st, ptr_ty);
00592     }
00593     else {
00594       ptr_ty = Make_Pointer_Type (ST_type(st), Is_Global_Symbol(st));
00595 
00596       parm_wn = WN_CreateLda (lda_op, 0, ptr_ty, st);
00597     }
00598     parm_wn = WN_CreateParm (Pointer_type,
00599                              parm_wn,
00600                              ptr_ty,
00601                              WN_PARM_BY_VALUE);
00602     WN_kid0(call_wn) = parm_wn;
00603     
00604     // parm 2: size of ST
00605     if (Is_VLA(st)) {
00606 
00607       // find alloca
00608       WN *alloca_wn = WN_first(WN_func_body(pu));
00609       while (alloca_wn) {
00610         if (WN_operator(alloca_wn) == OPR_PRAGMA &&
00611             WN_pragma(alloca_wn) == WN_PRAGMA_PREAMBLE_END) {
00612           DevWarn ("Reached end of preamble w/o finding alloca of %s\n",
00613                    ST_name(st));
00614         }
00615         if ((WN_operator(alloca_wn) == OPR_STID) &&
00616             (WN_st_idx(alloca_wn) == ST_st_idx(st)))
00617           break;
00618         alloca_wn = WN_next(alloca_wn);
00619       }
00620       FmtAssert (alloca_wn,
00621                  ("Unable to find alloca of %s\n", ST_name(st)));
00622       alloca_wn = WN_prev(alloca_wn);
00623       Is_True (alloca_wn &&
00624                WN_operator(alloca_wn) == OPR_INTRINSIC_CALL &&
00625                (WN_intrinsic(alloca_wn) == INTRN_U4I4ALLOCA ||
00626                 WN_intrinsic(alloca_wn) == INTRN_U8I8ALLOCA),
00627                ("Expected to find an alloca for %s in preamble",
00628                 ST_name(st)));
00629       parm_wn = WN_COPY_Tree (WN_kid0(WN_kid0(alloca_wn)));
00630       Parentize(parm_wn);
00631     }
00632     else {
00633       OPCODE const_op = OPCODE_make_op(OPR_INTCONST, MTYPE_I8, MTYPE_V);
00634       parm_wn = WN_CreateIntconst (const_op, TY_size(ST_type(st)));
00635     }
00636     parm_wn = WN_CreateParm (MTYPE_I8,
00637                              parm_wn,
00638                              Be_Type_Tbl(MTYPE_I8),
00639                              WN_PARM_BY_VALUE);
00640     WN_kid1(call_wn) = parm_wn;
00641 
00642     // parm 3: name of function
00643     char* var_name = ST_name(WN_st(pu));
00644     TCON tcon = Host_To_Targ_String (MTYPE_STRING,var_name,strlen(var_name)+1);
00645     TY_IDX string_ty = Make_Pointer_Type(Be_Type_Tbl(MTYPE_U1), TRUE);
00646     ST *string_st = Gen_String_Sym (&tcon, Be_Type_Tbl(MTYPE_STRING), FALSE);
00647     parm_wn = WN_CreateLda (lda_op, 0, string_ty, string_st);
00648     parm_wn = WN_CreateParm (Pointer_type,
00649                              parm_wn,
00650                              Be_Type_Tbl(Pointer_type),
00651                              WN_PARM_BY_REFERENCE);
00652     WN_kid2(call_wn) = parm_wn;
00653 
00654     // parm 4: name of ST
00655     var_name = ST_name(st);
00656     tcon = Host_To_Targ_String (MTYPE_STRING,var_name,strlen(var_name)+1);
00657     string_ty = Make_Pointer_Type(Be_Type_Tbl(MTYPE_U1), TRUE);
00658     string_st = Gen_String_Sym (&tcon, Be_Type_Tbl(MTYPE_STRING), FALSE);
00659     parm_wn = WN_CreateLda (lda_op, 0, string_ty, string_st);
00660     parm_wn = WN_CreateParm (Pointer_type,
00661                              parm_wn,
00662                              Be_Type_Tbl(Pointer_type),
00663                              WN_PARM_BY_REFERENCE);
00664     WN_kid3(call_wn) = parm_wn;
00665 
00666     Set_Call_Side_Effects (call_wn);
00667     Parentize(call_wn);
00668 
00669     Insert_Call (call_wn, pu, altentry_stack);
00670 
00671     // now unregister at each exit point
00672     // __memctr_unregister_local (address, size, func-name, name)
00673     for (INT i=0; i<exit_stack->Elements(); i++) {
00674       WN* insert_wn = exit_stack->Bottom_nth(i);
00675       call_wn = WN_COPY_Tree (call_wn);
00676       WN_st_idx(call_wn) = ST_st_idx(unreg_st_local);
00677       WN_INSERT_BlockBefore (Get_Parent(insert_wn), insert_wn, call_wn);
00678       Set_Parent(call_wn, Get_Parent(insert_wn));
00679     }
00680   }
00681 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines