00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 static char *source_file = __FILE__;
00046
00047 #ifdef _KEEP_RCS_ID
00048 #endif
00049
00050
00051
00052 #include "defs.h"
00053 #include "glob.h"
00054 #include "stab.h"
00055 #include "strtab.h"
00056 #include "erfe90.h"
00057 #include "errors.h"
00058 #include "targ_const.h"
00059 #include "config_targ.h"
00060 #include "const.h"
00061 #include "wn.h"
00062 #include "wn_util.h"
00063 #include "irbdata.h"
00064 #include "cxx_memory.h"
00065
00066
00067
00068 #include "i_cvrt.h"
00069
00070
00071
00072 #include "cwh_defines.h"
00073 #include "cwh_types.h"
00074 #include "cwh_addr.h"
00075 #include "cwh_stmt.h"
00076 #include "cwh_preg.h"
00077 #include "cwh_stab.h"
00078 #include "cwh_auxst.h"
00079 #include "cwh_stk.h"
00080 #include "cwh_expr.h"
00081 #include "cwh_data.h"
00082
00083 #include "cwh_data.i"
00084
00085
00086
00087
00088
00089
00090
00091
00092 extern void
00093 fei_static_base(INTPTR sym_idx)
00094 {
00095 STB_pkt *p ;
00096 ST *base;
00097 INT64 offset;
00098 BOOL init_common_or_module;
00099
00100 p = cast_to_STB(sym_idx);
00101 DevAssert((p->form == is_ST),("Odd object ref"));
00102
00103 current_st = (ST *) p->item;
00104 orig_st = current_st;
00105 current_ty = ST_type(current_st);
00106 current_pos = 0;
00107 array_pos = 0;
00108 init_common_or_module = FALSE;
00109 offset = 0;
00110 base = current_st;
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 if (ST_base(base) != base && (ST_sclass(ST_base(base))!=SCLASS_TEXT)) {
00123
00124
00125
00126
00127
00128
00129 base = ST_base(base);
00130 }
00131
00132
00133
00134
00135 if ((ST_sclass(base) == SCLASS_DGLOBAL) ||
00136 (ST_sclass(base) == SCLASS_COMMON)) {
00137
00138
00139
00140
00141
00142
00143
00144 Set_ST_sclass(base, SCLASS_DGLOBAL);
00145
00146 cwh_data_set_init_flag(base,l_COMLIST);
00147
00148 current_pos = offset;
00149 init_common_or_module = TRUE;
00150
00151 } else if (base != current_st) {
00152
00153
00154
00155 cwh_data_set_init_flag(base,l_EQVLIST);
00156 current_pos = offset;
00157 Set_ST_is_initialized(base);
00158 init_common_or_module = TRUE;
00159 }
00160
00161
00162 Set_ST_is_initialized(current_st);
00163
00164 # if 0
00165 if (ST_sclass(current_st)!=SCLASS_MODULE)
00166 Set_ST_sclass(current_st,SCLASS_PSTATIC);
00167 # endif
00168
00169
00170 if (TY_kind(current_ty) == KIND_ARRAY) {
00171 is_struct_or_array = TRUE;
00172
00173 current_bytesize = TY_size(TY_etype(current_ty));
00174 } else {
00175 if (TY_kind(current_ty) == KIND_STRUCT) {
00176 is_struct_or_array = TRUE;
00177 } else {
00178 is_struct_or_array = FALSE;
00179 }
00180 current_bytesize = TY_size(current_ty);
00181 }
00182 if (init_common_or_module) {
00183 is_struct_or_array = TRUE;
00184 }
00185
00186 current_data_info = ST_auxst_data_info(current_st);
00187 if (!current_data_info) {
00188 current_data_info = CXX_NEW(data_info_s(current_st),FE_Mempool);
00189 Set_ST_auxst_data_info(current_st,current_data_info);
00190 }
00191 current_inito = current_data_info->Get_Inito();
00192 return;
00193 }
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205 extern void
00206 fei_static_subscripts( INT64 static_subscripts[STATIC_SUBSCRIPT_SIZE] )
00207 {
00208 INT i;
00209 INT rank;
00210 INT64 offset;
00211
00212
00213 ARB_HANDLE arb;
00214
00215
00216 DevAssert((TY_kind(current_ty)==KIND_ARRAY),("Not an array ty"));
00217 rank = TY_AR_ndims(Ty_Table[current_ty]);
00218 offset = 0;
00219
00220 arb = TY_arb(Ty_Table[current_ty])[rank - 1];
00221
00222 for (i=rank-1; i >= 0; i--) {
00223 offset += (static_subscripts[i] -
00224 ARB_lbnd_val(arb))*
00225 ARB_stride_val(arb);
00226 arb = arb[-1];
00227 }
00228
00229 array_pos += offset;
00230 return;
00231 }
00232
00233
00234
00235
00236
00237
00238 extern void
00239 fei_static_substr( INT32 start)
00240 {
00241
00242
00243
00244 array_pos += start - 1;
00245 return;
00246 }
00247
00248
00249
00250
00251
00252
00253 extern
00254 void fei_static_member (INT32 st_idx )
00255 {
00256 FLD_IDX fld;
00257
00258 fld = (FLD_IDX)st_idx;
00259
00260 FLD_HANDLE f (fld);
00261 DevAssert((FLD_bofst(f) == 0),("Can't handle non 0 bofst"));
00262 current_pos += FLD_ofst(f);
00263
00264 current_ty = FLD_type(f);
00265 if (TY_kind(current_ty) == KIND_ARRAY) {
00266 current_bytesize = TY_size(TY_etype(current_ty));
00267 } else {
00268 current_bytesize = TY_size(current_ty);
00269 }
00270 }
00271
00272
00273 static INT32 get_TCON_size(TCON_IDX tc)
00274 {
00275 TYPE_ID t;
00276 INT32 esize;
00277 if (tc == 0) {
00278
00279
00280
00281 esize = Pointer_Size;
00282 } else {
00283 TCON& tcon = Tcon_Table[tc];
00284 t = TCON_ty(tcon);
00285 if (t == MTYPE_STR) {
00286 esize = Targ_String_Length(tcon);
00287 } else {
00288 esize = MTYPE_size_min(t)/8;
00289 }
00290 }
00291 return (esize);
00292 }
00293
00294
00295 static TCON_IDX TCON_from_stack(void)
00296 {
00297 TCON_IDX tcp;
00298 ST *cst;
00299 WN *slen;
00300 WN *w;
00301 TY_IDX ty;
00302
00303 switch (cwh_stk_get_class()) {
00304 case STR_item:
00305 cwh_stk_pop_STR();
00306 slen = cwh_stk_pop_WN();
00307 WN_DELETE_Tree(slen);
00308 cst = cwh_stk_pop_ST();
00309 tcp = ST_tcon(cst);
00310 break;
00311
00312 case PCONST_item:
00313 cst = (ST *) cwh_stk_pop_PCONST();
00314 tcp = ST_tcon(cst);
00315 break;
00316
00317 case WN_item:
00318 case WN_item_whole_array:
00319 ty = cwh_stk_get_TY();
00320 w = cwh_stk_pop_WN();
00321 if (WNOPR(w) == OPR_INTCONST) {
00322 if (ty) {
00323 tcp = Enter_tcon(Host_To_Targ(TY_mtype(ty),WN_const_val(w)));
00324 } else {
00325 tcp = Enter_tcon(Host_To_Targ(WN_rtype(w),WN_const_val(w)));
00326 }
00327 } else if (WNOPR(w) == OPR_CONST) {
00328 tcp = Enter_tcon(Const_Val(w));
00329 } else {
00330 DevAssert((0),("not a const node"));
00331 }
00332 WN_Delete(w);
00333 break;
00334 }
00335 return (tcp);
00336 }
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349 static
00350 b_and_o get_base_and_offset(WN *wn)
00351 {
00352 b_and_o r,t1,t2;
00353 INT64 offset;
00354 INT ndim,i;
00355 INT64 esize;
00356 INT64 smult;
00357 WN *adim, *aindex;
00358 INT64 adim_val,aindex_val;
00359
00360 r.base = NULL;
00361 r.offset = 0;
00362
00363 switch (WN_operator(wn)) {
00364 case OPR_ADD:
00365 t1 = get_base_and_offset(WN_kid0(wn));
00366 t2 = get_base_and_offset(WN_kid1(wn));
00367 r.offset = t1.offset + t2.offset;
00368 if (t1.base) {
00369 r.base = t1.base;
00370 } else if (t2.base) {
00371 r.base = t2.base;
00372 } else {
00373 DevAssert((0),("No base found"));
00374 }
00375 break;
00376
00377 case OPR_SUB:
00378 t1 = get_base_and_offset(WN_kid0(wn));
00379 t2 = get_base_and_offset(WN_kid1(wn));
00380 r.offset = t1.offset - t2.offset;
00381 if (t1.base) {
00382 r.base = t1.base;
00383 } else {
00384 DevAssert((0),("No base or bad base"));
00385 }
00386 break;
00387
00388 case OPR_INTCONST:
00389 r.base = NULL;
00390 r.offset = WN_const_val(wn);
00391 break;
00392
00393 case OPR_LDA:
00394 r.base = WN_st(wn);
00395 r.offset = WN_offset(wn);
00396
00397 # ifdef linux
00398
00399 while (ST_base(r.base) != r.base) {
00400 r.offset += ST_ofst(r.base);
00401 r.base = ST_base(r.base);
00402 }
00403 # endif
00404 break;
00405
00406 case OPR_ARRAYEXP:
00407 r = get_base_and_offset(WN_kid0(wn));
00408 break;
00409
00410 case OPR_ARRAY:
00411 case OPR_ARRSECTION:
00412
00413 r = get_base_and_offset(WN_kid0(wn));
00414 esize = WN_element_size(wn);
00415 ndim = WN_num_dim(wn);
00416 offset = 0;
00417
00418 smult = 1;
00419 for (i = ndim-1; i >= 0; i--) {
00420 aindex = WN_array_index(wn,i);
00421 adim = WN_array_dim(wn,i);
00422 DevAssert((WN_operator(aindex)==OPR_INTCONST),("Non-constant index"));
00423 DevAssert((WN_operator(adim)==OPR_INTCONST),("Non-constant dim"));
00424 aindex_val = WN_const_val(aindex);
00425 adim_val = WN_const_val(adim);
00426 if (esize < 0) {
00427
00428 offset += aindex_val * adim_val;
00429 } else {
00430
00431 offset += aindex_val * smult;
00432 smult *= adim_val;
00433 }
00434 }
00435
00436
00437 if (esize > 0) {
00438 offset *= esize;
00439 } else {
00440 offset *= (-esize);
00441 }
00442
00443 r.offset += offset;
00444 break;
00445
00446 case OPR_COMMA:
00447 r = get_base_and_offset(WN_kid1(wn));
00448 break;
00449
00450 default:
00451
00452 DevAssert((0),("strange offset expression"));
00453 break;
00454 }
00455 return (r);
00456 }
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471 static INITV_IDX create_initv(INITO_IDX ino, INT32 repeat, TCON_IDX tc,
00472 b_and_o *bo)
00473 {
00474 if (tc) {
00475 return (Irb_Init_Val(ino, 0, repeat, tc));
00476 } else {
00477 return (Irb_Init_Symoff(ino, 0, repeat, bo->base, bo->offset));
00478 }
00479 }
00480
00481 static
00482 void static_simple_init_helper (INT64 dup_count,
00483 INT64 stride,
00484 TCON_IDX value,
00485 b_and_o *bo)
00486
00487 {
00488 INT64 byte_stride;
00489 INT32 init_size;
00490 INT64 i;
00491 INT64 element_offset;
00492
00493 if (!is_struct_or_array) {
00494 create_initv(current_inito,1,value, bo);
00495 return;
00496 }
00497
00498 if (dup_count == 0) return;
00499 element_offset = array_pos;
00500
00501 byte_stride = stride/8;
00502 if (byte_stride < 0) {
00503
00504 element_offset += byte_stride*(dup_count-1);
00505 byte_stride = -byte_stride;
00506 }
00507
00508 init_size = get_TCON_size(value);
00509 if (byte_stride == 0) byte_stride = init_size;
00510
00511
00512 current_data_info->Reserve(dup_count);
00513 for (i=0; i < dup_count; i++) {
00514 current_data_info->Add_Data_Element(current_pos+element_offset,value,bo,init_size);
00515 element_offset += byte_stride;
00516 }
00517
00518 return;
00519 }
00520
00521
00522 extern
00523 void fei_static_simple_init (INT64 dup_count,
00524 INT64 stride,
00525 INT32 ignore_types,
00526 INT32 string_literal)
00527
00528 {
00529 TCON_IDX value;
00530 value = TCON_from_stack();
00531 static_simple_init_helper(dup_count,stride,value,NULL);
00532 }
00533
00534
00535
00536
00537
00538
00539
00540 extern
00541 void fei_static_next_simple_init ( INT64 bit_increment,
00542 INT64 dup_count,
00543 INT64 init_offset,
00544 INT32 string_literal )
00545 {
00546 array_pos += (init_offset >> 3);
00547 fei_static_simple_init(dup_count,bit_increment,0,string_literal);
00548 }
00549
00550
00551
00552
00553
00554
00555
00556 extern
00557 void fei_static_simple_reloc_init ( INT64 bit_offset,
00558 INT64 dup_count,
00559 INT64 stride,
00560 INT64 bit_size,
00561 INT32 ignore_types )
00562 {
00563 WN *addr;
00564 b_and_o value;
00565
00566
00567
00568 addr = cwh_expr_operand(NULL);
00569 value = get_base_and_offset(addr);
00570 WN_DELETE_Tree(addr);
00571 DevAssert((value.base),("NULL base found"));
00572 cwh_expr_set_flags(value.base,f_T_SAVED);
00573
00574 static_simple_init_helper(dup_count,stride,0,&value);
00575 }
00576
00577
00578
00579
00580
00581
00582
00583
00584 static void emit_inits_for_symbol(ST_IDX st_idx, ST *st)
00585 {
00586 DATA_INFO d;
00587 INITO_IDX inito;
00588 DATA_ELEMENTS *v;
00589 INT vsize,i;
00590 INT64 pos;
00591
00592 INITV_IDX pad;
00593 INITV_IDX initv;
00594 INITV_IDX prev_initv;
00595 INT64 offset;
00596 INT64 init_size;
00597 INT64 pad_size;
00598
00599 if (ST_sym_class(st) != CLASS_VAR) return;
00600
00601 d = ST_auxst_data_info(st);
00602 if (d==NULL) return;
00603 if (d->Get_Data_Elements()==NULL) return;
00604
00605
00606 inito = d->Get_Inito();
00607
00608 d->sort_data(st);
00609 v = d->Get_Data_Elements();
00610
00611
00612 vsize = v->size();
00613 if (vsize == 0) return;
00614
00615 #ifdef DATA_DEBUG
00616 printf("Emitting inits for %s ====================\n",ST_name(st));
00617 #endif
00618
00619 prev_initv = 0;
00620 pos = 0;
00621 for (i = 0; i < vsize; i++) {
00622 if (!(*v)[i].is_valid) continue;
00623 offset = (*v)[i].offset;
00624 init_size = (*v)[i].initv_size;
00625 initv = (*v)[i].create_initv();
00626
00627
00628 pad_size = offset - pos;
00629 if (pad_size > 0) {
00630 pad = Irb_Init_Pad(0,prev_initv,pad_size);
00631 if (prev_initv == 0) {
00632 prev_initv = Irb_Init_Block(inito,0,1);
00633 Set_INITV_blk(prev_initv,pad);
00634 } else {
00635 Set_INITV_next(prev_initv,pad);
00636 }
00637 prev_initv = pad;
00638 }
00639
00640 #ifdef DATA_DEBUG
00641 printf("pad %lld, offset %lld, size %lld, next %lld\n",pad_size,
00642 offset,init_size, offset + init_size);
00643 #endif
00644
00645
00646 if (prev_initv == 0) {
00647 prev_initv = Irb_Init_Block(inito,0,1);
00648 Set_INITV_blk(prev_initv,initv);
00649 } else {
00650 Set_INITV_next(prev_initv,initv);
00651 }
00652 prev_initv = initv;
00653 pos = offset + init_size;
00654 }
00655
00656
00657 pad_size = TY_size(ST_type(st)) - pos;
00658 if (pad_size > 0) {
00659 pad = Irb_Init_Pad(0,prev_initv,pad_size);
00660 }
00661
00662
00663 CXX_DELETE(d,FE_Mempool);
00664 Set_ST_auxst_data_info(st,NULL);
00665
00666 return;
00667 }
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677 extern void
00678 cwh_data_emit_symbol_inits(SYMTAB_IDX level)
00679 {
00680 For_all(St_Table, level,&emit_inits_for_symbol);
00681 }
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695 static void
00696 cwh_data_set_init_flag(ST * st, enum list_name list)
00697 {
00698
00699 ITEM * el = NULL;
00700
00701 while ((el = cwh_auxst_next_element(st,el,list)) != NULL) {
00702
00703 ST * el_st = I_element(el);
00704 if (ST_sclass(el_st)!=SCLASS_AUTO)
00705 Set_ST_sclass(el_st, ST_sclass(st));
00706 else
00707 Set_ST_sclass(el_st,SCLASS_PSTATIC);
00708 Set_ST_is_initialized(el_st);
00709
00710 ST * p_st = cwh_auxst_cri_pointee(el_st,0);
00711
00712 if (p_st) {
00713
00714 if (ST_sclass(p_st)!= SCLASS_AUTO)
00715 Set_ST_sclass(p_st, ST_sclass(st));
00716 else
00717 Set_ST_sclass(p_st,SCLASS_PSTATIC);
00718
00719 Set_ST_is_initialized(p_st);
00720 }
00721
00722 if (list == l_COMLIST)
00723 cwh_data_set_init_flag(el_st, l_EQVLIST);
00724 }
00725 }
00726