Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
00001 /* 00002 00003 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00004 00005 This program is free software; you can redistribute it and/or modify it 00006 under the terms of version 2 of the GNU General Public License as 00007 published by the Free Software Foundation. 00008 00009 This program is distributed in the hope that it would be useful, but 00010 WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00012 00013 Further, this software is distributed without any warranty that it is 00014 free of the rightful claim of any third person regarding infringement 00015 or the like. Any license provided herein, whether implied or 00016 otherwise, applies only to this software file. Patent licenses, if 00017 any, provided herein do not apply to combinations of this program with 00018 other software, or any other product whatsoever. 00019 00020 You should have received a copy of the GNU General Public License along 00021 with this program; if not, write the Free Software Foundation, Inc., 59 00022 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00023 00024 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00025 Mountain View, CA 94043, or: 00026 00027 http://www.sgi.com 00028 00029 For further information regarding this notice, see: 00030 00031 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00032 00033 */ 00034 00035 00036 00037 #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 }