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
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 #ifdef USE_PCH
00059 #include "be_com_pch.h"
00060 #endif
00061 #pragma hdrstop
00062 #include <cmplrs/rcodes.h>
00063 #ifndef __MINGW32__
00064 #include <sys/resource.h>
00065 #endif
00066 #if (__GNUC__==2)
00067 #include <slist>
00068 #else
00069 #include <ext/slist>
00070 #endif
00071 #include "defs.h"
00072 #include "erglob.h"
00073 #include "erbe.h"
00074 #include "config.h"
00075 #include "tracing.h"
00076 #include "strtab.h"
00077 #include "stab.h"
00078 #include "const.h"
00079 #include "glob.h"
00080 #include "mtypes.h"
00081 #include "targ_const.h"
00082 #include "targ_sim.h"
00083 #include "ttype.h"
00084 #include "irbdata.h"
00085 #include "util.h"
00086 #include "stblock.h"
00087 #include "data_layout.h"
00088 #include "wintrinsic.h"
00089 #include "sections.h"
00090 #include "betarget.h"
00091 #include "intrn_info.h"
00092 #ifdef TARG_X8664
00093 #include "config_opt.h"
00094
00095 extern void (*CG_Set_Is_Stack_Used_p)();
00096 extern INT (*Push_Pop_Int_Saved_Regs_p)(void);
00097 #endif
00098 #if defined(TARG_SL)
00099 #include <map>
00100 #include <vector>
00101 #include "fb_whirl.h"
00102 #endif
00103 extern void Early_Terminate (INT status);
00104
00105 #ifdef TARG_MIPS
00106 #if defined(TARG_SL)
00107 static BOOL inline Is_Target_32bit (void) { return TRUE; }
00108 #else
00109
00110 static BOOL inline Is_Target_32bit (void) { return FALSE; }
00111 #endif
00112 #endif // TARG_MIPS
00113
00114 #define ST_force_gprel(s) ST_gprel(s)
00115
00116 ST *SP_Sym;
00117 ST *FP_Sym;
00118 ST *Local_Spill_Sym;
00119 extern INT32 mp_io;
00120 INT32 Current_PU_Actual_Size;
00121 STACK_MODEL Current_PU_Stack_Model = SMODEL_UNDEF;
00122
00123 #define ST_NAME(st) (ST_class(st) == CLASS_CONST ? \
00124 Targ_Print(NULL,STC_val(st)) : ST_name(st) )
00125
00126 #define ST_NO_LINKAGE(st) \
00127 (ST_export(st) == EXPORT_LOCAL || \
00128 ST_export(st) == EXPORT_LOCAL_INTERNAL)
00129 static BOOL Frame_Has_Calls;
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139 typedef enum {
00140 SFSEG_UNKNOWN,
00141 SFSEG_ACTUAL,
00142 SFSEG_FTEMP,
00143 SFSEG_FORMAL,
00144 SFSEG_UPFORMAL
00145
00146
00147
00148
00149
00150 } SF_SEGMENT;
00151
00152 #define SFSEG_FIRST SFSEG_ACTUAL
00153 #define SFSEG_LAST SFSEG_UPFORMAL
00154
00155 typedef struct {
00156 SF_SEGMENT seg;
00157 ST *block;
00158 mINT64 maxsize;
00159 const char *name;
00160 } SF_SEG_DESC;
00161
00162 #define SFSEG_seg(s) ((s)->seg)
00163 #define SFSEG_block(s) ((s)->block)
00164 #define SFSEG_maxsize(s) ((s)->maxsize)
00165 #define SFSEG_name(s) ((s)->name)
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 #define DEFAULT_LARGE_OBJECT_BYTES 64
00176
00177 #define DEFAULT_TEMP_SPACE_BYTES 4096
00178 #define MAX_SFSEG_BYTES 0x7FFFFFFFFFFFFFFFLL
00179
00180 #define MAX_LARGE_FRAME_OFFSET 0x7FFFFFFFFFFFFFFFLL // 64bits on all targs
00181 #define MAX_FRAME_OFFSET \
00182 (Current_PU_Stack_Model == SMODEL_SMALL ? \
00183 Max_Small_Frame_Offset : MAX_LARGE_FRAME_OFFSET)
00184
00185 typedef enum _align {
00186 _BYTE_ALIGN = 1,
00187 _CARD_ALIGN = 2,
00188 _WORD_ALIGN = 4,
00189 _DWORD_ALIGN = 8,
00190 _QUAD_ALIGN = 16
00191 } ALIGN;
00192
00193 static STACK_DIR stack_direction;
00194
00195 #ifndef DEFAULT_STACK_ALIGNMENT
00196 #define DEFAULT_STACK_ALIGNMENT _QUAD_ALIGN
00197 #endif // DEFAULT_STACK_ALIGNMENT
00198
00199 #ifdef TARG_X8664
00200 #define stack_align ( Stack_Alignment() )
00201 #else
00202 static INT16 stack_align = DEFAULT_STACK_ALIGNMENT;
00203 #endif
00204
00205
00206
00207 static SF_SEG_DESC SF_Seg_Descriptors [SFSEG_LAST+1] = {
00208 { SFSEG_UNKNOWN, NULL, MAX_SFSEG_BYTES, "Unknown" },
00209 { SFSEG_ACTUAL, NULL, MAX_SFSEG_BYTES, "Actual_Arg" },
00210 { SFSEG_FTEMP, NULL, MAX_SFSEG_BYTES, "Fixed_Temp" },
00211 { SFSEG_FORMAL, NULL, MAX_SFSEG_BYTES, "Formal_Arg" },
00212 { SFSEG_UPFORMAL, NULL, MAX_SFSEG_BYTES, "UpFormal_Arg" }
00213 };
00214 #define SF_Seg_Desc(n) (&SF_Seg_Descriptors[n])
00215
00216 #define SF_Block(n) (SFSEG_block(SF_Seg_Desc(n)))
00217 #define SF_Maxsize(n) (SFSEG_maxsize(SF_Seg_Desc(n)))
00218 #define SF_Name(n) (SFSEG_name(SF_Seg_Desc(n)))
00219
00220
00221
00222
00223
00224 static INT32 Large_Object_Bytes;
00225
00226 static BOOL Trace_Frame = FALSE;
00227
00228
00229
00230
00231
00232
00233
00234
00235 #define Is_root_base(st) (ST_class(st) == CLASS_BLOCK && STB_root_base(st))
00236 #define Has_No_Base_Block(st) (ST_base(st) == st)
00237 #define Is_Allocatable(st) (!Has_Base_Block(st) && !Is_root_base(st))
00238 #define Is_Allocatable_Root_Block(st) \
00239 (ST_class(st) == CLASS_BLOCK && !Is_root_base(st) && Has_No_Base_Block(st))
00240
00241
00242
00243
00244
00245
00246 static SECTION_IDX Shorten_Section (ST *, SECTION_IDX);
00247 static void Allocate_Object_To_Section (ST *, SECTION_IDX, UINT);
00248 static void Allocate_Label (ST *lab);
00249
00250
00251 BOOL ST_has_Predefined_Named_Section (ST *, SECTION_IDX &);
00252 static void Allocate_Object_To_Predefined_Named_Section (ST *, SECTION_IDX);
00253
00254 extern BOOL
00255 Is_Allocated (ST *st)
00256 {
00257 ST *base;
00258 INT64 ofst;
00259 Base_Symbol_And_Offset(st, &base, &ofst);
00260
00261 if (ST_sclass(st) == SCLASS_FORMAL && ST_class(base) == CLASS_BLOCK)
00262 return TRUE;
00263 return ((base != st && Is_root_base(base)) || Is_root_base(st));
00264 }
00265
00266
00267
00268
00269
00270 #define ROUNDUP(val,align) ( (-(INT64)align) & (INT64)(val+align-1) )
00271 #define ROUNDDOWN(val,align) ( (-(INT64)align) & (INT64)(val) )
00272 #define IS_POW2(num) ( (~((num)-1) & (num) ) == (num) )
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284 BOOL ST_on_stack(ST *sym)
00285 {
00286 if (ST_sclass(sym) == SCLASS_AUTO)
00287 return TRUE;
00288 else if (ST_sclass(sym) == SCLASS_FORMAL)
00289 return TRUE;
00290 else if (sym == SP_Sym || sym == FP_Sym)
00291 return TRUE;
00292 else {
00293 ST *base = Base_Symbol(sym);
00294 if (base == SP_Sym || base == FP_Sym)
00295 return TRUE;
00296 else
00297 return FALSE;
00298 }
00299 }
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313 BOOL ST_pu_defined(ST *sym)
00314 {
00315 if ((ST_class(sym) == CLASS_VAR) ||
00316 (ST_class(sym) == CLASS_CONST))
00317 {
00318 switch(ST_sclass(sym))
00319 {
00320 case SCLASS_AUTO:
00321 case SCLASS_PSTATIC:
00322 case SCLASS_FSTATIC:
00323 case SCLASS_DGLOBAL:
00324 case SCLASS_FORMAL:
00325 return TRUE;
00326 default:
00327 return FALSE;
00328 }
00329 }
00330 return FALSE;
00331
00332 }
00333
00334
00335
00336
00337
00338 typedef struct {
00339 const ST *sym;
00340 ST *base;
00341 PREG_NUM preg;
00342
00343
00344
00345
00346 SYMTAB_IDX level;
00347 } formal_info;
00348 static formal_info *formal_info_array;
00349 static INT max_formal_info_index = 0;
00350
00351 static void
00352 Realloc_ST_formal_info (INT min_needed)
00353 {
00354 if (min_needed >= max_formal_info_index) {
00355
00356 formal_info_array = TYPE_MEM_POOL_REALLOC_N (
00357 formal_info, &MEM_src_pool,
00358 formal_info_array,
00359 max_formal_info_index,
00360 min_needed + 8);
00361 max_formal_info_index = min_needed + 8;
00362 }
00363 }
00364
00365
00366
00367 static void
00368 Init_ST_formal_info_for_PU (INT num_formals)
00369 {
00370 if (formal_info_array == NULL) {
00371 max_formal_info_index = MAX(8,num_formals);
00372 formal_info_array = (formal_info*) Src_Alloc (
00373 sizeof(formal_info) * max_formal_info_index);
00374 }
00375 else {
00376
00377
00378
00379 INT num_uplevel_entries = 0;
00380 for (INT i = 0; i < max_formal_info_index; i++) {
00381 if (formal_info_array[i].sym != NULL) {
00382 if (formal_info_array[i].level >=
00383 CURRENT_SYMTAB) {
00384 formal_info_array[i].sym = NULL;
00385 formal_info_array[i].base = NULL;
00386 formal_info_array[i].preg = 0;
00387 formal_info_array[i].level =
00388 SYMTAB_IDX_ZERO;
00389 } else {
00390 num_uplevel_entries++;
00391 }
00392 }
00393 }
00394 Realloc_ST_formal_info (num_formals + num_uplevel_entries);
00395 }
00396
00397 #ifdef Is_True_On
00398
00399
00400 Is_True(max_formal_info_index > 0, ("no elements allocated"));
00401 const ST *last = formal_info_array[0].sym;
00402 for (INT i = 0; i < max_formal_info_index; i++) {
00403 Is_True(last != NULL || last == formal_info_array[i].sym,
00404 ("NULL sym precedes non-NULL sym"));
00405 last = formal_info_array[i].sym;
00406 }
00407 #endif
00408 }
00409
00410
00411 ST *
00412 Get_ST_formal_ref_base (const ST *sym)
00413 {
00414 if (ST_sclass(sym) != SCLASS_FORMAL_REF)
00415 return NULL;
00416 INT i;
00417 for (i = 0; i < max_formal_info_index; i++) {
00418 if (formal_info_array[i].sym == sym)
00419 return formal_info_array[i].base;
00420 else if (formal_info_array[i].sym == NULL)
00421 break;
00422 }
00423 return NULL;
00424 }
00425
00426 void
00427 Set_ST_formal_ref_base (const ST *sym, ST *base)
00428 {
00429 INT i;
00430 for (i = 0; i < max_formal_info_index; i++) {
00431 if (formal_info_array[i].sym == NULL) {
00432 formal_info_array[i].sym = sym;
00433 formal_info_array[i].base = base;
00434 formal_info_array[i].level = ST_level(sym);
00435 return;
00436 }
00437 }
00438 Realloc_ST_formal_info (max_formal_info_index);
00439 formal_info_array[i].sym = sym;
00440 formal_info_array[i].base = base;
00441 formal_info_array[i].level = ST_level(sym);
00442 }
00443
00444
00445 PREG_NUM
00446 Get_ST_formal_preg_num (const ST *base)
00447 {
00448 INT i;
00449 for (i = 0; i < max_formal_info_index; i++) {
00450 if (formal_info_array[i].base == base)
00451 return formal_info_array[i].preg;
00452 else if (formal_info_array[i].sym == NULL)
00453 break;
00454 }
00455 return (PREG_NUM) 0;
00456 }
00457
00458 void
00459 Set_ST_formal_preg_num (const ST *base, PREG_NUM p)
00460 {
00461 INT i;
00462 for (i = 0; i < max_formal_info_index; i++) {
00463 if (formal_info_array[i].base == base) {
00464 formal_info_array[i].preg = p;
00465 return;
00466 }
00467 }
00468 Is_True(FALSE, ("Set_ST_formal_preg_num didn't find base"));
00469 }
00470
00471 static ST *Formal_Sym(ST *sym, BOOL onstack)
00472 {
00473 ST *base;
00474
00475 if (ST_sclass(sym) != SCLASS_FORMAL_REF)
00476 return sym;
00477
00478 if (Is_Allocated(sym))
00479 {
00480 return sym;
00481 }
00482 if (base = Get_ST_formal_ref_base(sym))
00483 {
00484 return base;
00485 }
00486
00487 base = Copy_ST(sym);
00488 Set_ST_name(base, Save_Str2(ST_name(base), ".base"));
00489 Set_ST_type(base, Make_Pointer_Type(ST_type(sym)) );
00490 Set_ST_sclass (base, SCLASS_FORMAL);
00491 Set_ST_formal_ref_base(sym, base);
00492
00493
00494
00495 Clear_ST_promote_parm(base);
00496
00497
00498
00499
00500
00501
00502 onstack |= (Debug_Level > 0 && Debug_Level != 3) ||
00503 #ifdef KEY
00504
00505
00506 Opt_Level < 2 ||
00507 #endif
00508 ST_has_nested_ref(sym) ||
00509 ST_declared_static(sym) ||
00510 PU_has_mp(Get_Current_PU());
00511
00512 if (onstack == FALSE)
00513 {
00514 Set_ST_formal_preg_num(base, Create_Preg(TY_mtype(ST_type(base)), ST_name(base)));
00515 }
00516
00517 if ( Trace_Frame )
00518 {
00519 fprintf(TFile, "SCLASS_FORMAL (%s, base %s, onstack= %d, preg= %d) allocated\n",
00520 ST_name(sym), ST_name(base), onstack, Get_ST_formal_preg_num(base));
00521 }
00522
00523 return base;
00524 }
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537 INT32
00538 Stack_Alignment ( void )
00539 {
00540 #ifdef TARG_X8664
00541 if( Is_Target_64bit() )
00542 return _QUAD_ALIGN;
00543
00544
00545
00546
00547 if( Align_Double )
00548 return _DWORD_ALIGN;
00549
00550 return _WORD_ALIGN;
00551 #else
00552 return stack_align;
00553 #endif
00554 }
00555
00556
00557 STACK_DIR Stack_Direction(void)
00558 {
00559 return stack_direction;
00560 }
00561
00562 static STACK_DIR
00563 Get_Direction (ST *blk)
00564 {
00565 if (STB_decrement(blk)) return DECREMENT;
00566 else return INCREMENT;
00567 }
00568
00569 static void
00570 Set_Direction (STACK_DIR dir, ST *blk)
00571 {
00572 if (dir == DECREMENT) Set_STB_decrement(blk);
00573 else Reset_STB_decrement(blk);
00574 }
00575
00576 static ST*
00577 Create_Local_Block( STACK_DIR dir, STR_IDX name )
00578 {
00579 ST *new_blk = New_ST_Block(name, FALSE, SCLASS_UNKNOWN, stack_align, 0);
00580 Set_Direction(dir, new_blk);
00581 Enter_ST(new_blk);
00582 return new_blk;
00583 }
00584
00585 static ST *
00586 Create_Base_Reg (const char *name, STACK_DIR dir)
00587 {
00588 ST *new_blk = Create_Local_Block(dir, Save_Str(name));
00589 Set_STB_root_base(new_blk);
00590 Set_STB_is_basereg(new_blk);
00591 return new_blk;
00592 }
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604 static void
00605 Assign_Offset (ST *blk, ST *base, INT32 lpad, INT32 rpad)
00606 {
00607 UINT align = Adjusted_Alignment(blk);
00608 Set_ST_ofst(blk, ROUNDUP(STB_size(base) + lpad, align));
00609 if (STB_decrement(base)) {
00610 INT32 size = ST_size(blk);
00611 #ifdef KEY
00612
00613 if (ST_class(blk) == CLASS_VAR && (!Current_pu ||
00614 (PU_src_lang (Get_Current_PU()) & PU_CXX_LANG)) && size == 0)
00615 size = 1;
00616 #endif
00617
00618 Set_ST_ofst(blk,
00619 -(INT64) ROUNDUP(ST_ofst(blk) + size + rpad, align));
00620 }
00621 }
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633 static void
00634 Allocate_Space(ST *base, ST *blk, INT32 lpad, INT32 rpad, INT64 maxsize)
00635 {
00636 UINT align = Adjusted_Alignment(blk);
00637 INT64 old_offset;
00638 INT64 size = ST_size(blk);
00639
00640 #ifdef KEY
00641
00642 if (ST_class(blk) == CLASS_VAR && (!Current_pu ||
00643 (PU_src_lang (Get_Current_PU()) & PU_CXX_LANG)) && size == 0)
00644 size = 1;
00645 #endif
00646
00647 Set_STB_align(base, MAX(STB_align(base), align));
00648 if (!STB_decrement(base)) {
00649 old_offset = STB_size(base);
00650 Set_ST_ofst(blk, ROUNDUP(old_offset + lpad, align));
00651 Set_STB_size(base, ROUNDUP(ST_ofst(blk) + size + rpad, align));
00652 }
00653 else {
00654 old_offset = STB_size(base);
00655
00656 Set_ST_ofst(blk, ROUNDUP(old_offset + lpad, align));
00657 Set_ST_ofst(blk,
00658 -(INT64) ROUNDUP(ST_ofst(blk) + size + rpad, align));
00659 Set_STB_size(base, -ST_ofst(blk));
00660 }
00661 if ((base == SP_Sym && Frame_Has_Calls) || base == FP_Sym) {
00662
00663
00664
00665
00666
00667 Set_ST_ofst(blk, ST_ofst(blk) + Stack_Offset_Adjustment);
00668 }
00669 if ( Trace_Frame ) {
00670 if (ST_class(blk) == CLASS_CONST)
00671 fprintf ( TFile, "Allocate <constant: %s>", Targ_Print(NULL,STC_val(blk)));
00672 else
00673 fprintf ( TFile, "Allocate %s", ST_name(blk));
00674 if (ST_class(blk) == CLASS_BLOCK || ST_class(blk) == CLASS_FUNC)
00675 fprintf (TFile, " to %s: offset = %lld, size = %lld\n",
00676 ST_name(base), ST_ofst(blk), size);
00677 else fprintf (TFile, " to %s: offset = %lld, size = %lld, align = %d\n",
00678 ST_name(base), ST_ofst(blk), size,
00679 #ifdef KEY
00680 align
00681 #else
00682 TY_align(ST_type(blk)
00683 #endif
00684 );
00685 }
00686 if (STB_size(base) > maxsize
00687 && Is_Local_Symbol(base)
00688 && maxsize == Max_Small_Frame_Offset
00689 && Current_PU_Stack_Model == SMODEL_SMALL)
00690 {
00691 DevWarn("overflowed small stack frame; will try recompiling with -TENV:large_stack");
00692 Early_Terminate(RC_OVERFLOW_ERROR);
00693 }
00694 Is_True( old_offset <= STB_size(base) && STB_size(base) <= maxsize,
00695 ("Block size overflowed"));
00696 }
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714 static ST*
00715 ST_Block_Merge (ST *block, ST *sym, INT32 lpad, INT32 rpad, INT64 maxsize)
00716 {
00717 ST *base;
00718
00719 Is_True(ST_class(block) == CLASS_BLOCK, ("block-merge not given a block"));
00720 Set_ST_base(sym, block);
00721 base = ST_base(sym);
00722 Allocate_Space(base, sym, lpad, rpad, maxsize);
00723
00724
00725 if (ST_is_initialized(sym) && !STB_section(block))
00726 Set_ST_is_initialized(block);
00727
00728 return base;
00729 }
00730
00731
00732 static void
00733 Initialize_Frame_Segment (SF_SEGMENT seg, ST_SCLASS sclass, STACK_DIR dir)
00734 {
00735 if (SF_Block(seg) == NULL)
00736 {
00737 SF_Block(seg) = Create_Local_Block(dir,
00738 Save_Str2 (SF_Name(seg),"_StkSeg"));
00739 Set_ST_sclass (SF_Block(seg), sclass);
00740 }
00741 }
00742
00743 static void
00744 Assign_Object_To_Frame_Segment ( ST *sym, SF_SEGMENT seg, INT64 offset)
00745 {
00746 if (Trace_Frame) {
00747 fprintf ( TFile,
00748 "Assigning symbol %s to segment %s at offset %lld\n",
00749 ST_name(sym), SF_Name(seg), offset);
00750 }
00751 Initialize_Frame_Segment (seg, ST_sclass(sym), INCREMENT);
00752 Set_ST_base(sym, SF_Block(seg));
00753 Set_ST_ofst(sym, offset);
00754 }
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765 static void
00766 Add_Object_To_Frame_Segment ( ST *sym, SF_SEGMENT seg, BOOL allocate )
00767 {
00768 if ( Trace_Frame && !allocate )
00769 {
00770 fprintf ( TFile, "Adding symbol to %s segment -- %s \n",
00771 SF_Name(seg), ST_name(sym)? ST_name(sym) : "<null>");
00772 }
00773
00774 Initialize_Frame_Segment (seg, ST_sclass(sym), INCREMENT);
00775
00776 if (SF_Block(seg) == sym)
00777 {
00778
00779
00780
00781 return;
00782 }
00783
00784 if (allocate)
00785 {
00786 INT64 size;
00787 INT32 lpad, rpad;
00788 lpad = rpad = 0;
00789
00790 switch (seg)
00791 {
00792 case SFSEG_ACTUAL:
00793 case SFSEG_UPFORMAL:
00794 case SFSEG_FORMAL:
00795 size = ST_size(sym);
00796 #ifdef KEY
00797
00798
00799
00800 if( size == 0 &&
00801 ( Current_pu == NULL ||
00802 PU_cxx_lang( Get_Current_PU() ) ) ){
00803 size = 1;
00804 }
00805 #endif
00806
00807 if (TY_kind(ST_type(sym)) == KIND_STRUCT)
00808 {
00809 rpad = ROUNDUP(size, MTYPE_RegisterSize(Spill_Int_Mtype)) - size;
00810 }
00811 else
00812 {
00813
00814
00815
00816
00817
00818
00819 if (size < MTYPE_RegisterSize(Spill_Int_Mtype)) {
00820 if (Target_Byte_Sex == LITTLE_ENDIAN ||
00821 MTYPE_is_float(TY_mtype(ST_type(sym)))) {
00822 rpad = MTYPE_RegisterSize(Spill_Int_Mtype) - size;
00823 }
00824 else
00825 lpad = MTYPE_RegisterSize(Spill_Int_Mtype) - size;
00826 }
00827 }
00828 break;
00829 }
00830 ST_Block_Merge (SF_Block(seg), sym, lpad, rpad, SF_Maxsize(seg));
00831
00832 #ifndef TARG_X8664
00833 if (seg == SFSEG_FORMAL)
00834 {
00835 ST *formal = SF_Block(seg);
00836
00837
00838
00839
00840 if (STB_size(formal) > Formal_Save_Area_Size)
00841 {
00842 ST *upformal = SF_Block(SFSEG_UPFORMAL);
00843
00844 if (Trace_Frame)
00845 fprintf(TFile, "<lay> split formal between segs\n");
00846
00847 Initialize_Frame_Segment (SFSEG_UPFORMAL, ST_sclass(sym), INCREMENT);
00848 Set_STB_size(upformal,
00849 STB_size(upformal) + STB_size(formal) - Formal_Save_Area_Size);
00850 Set_STB_size(formal, Formal_Save_Area_Size);
00851 }
00852 }
00853 #endif
00854 }
00855 else
00856 {
00857 Set_ST_base(sym, SF_Block(seg));
00858 }
00859 }
00860
00861
00862
00863
00864
00865 static UINT32 *arg_area_size_array;
00866 static INT max_arg_area_size_index = 0;
00867
00868
00869 static void
00870 Init_PU_arg_area_size_array (void)
00871 {
00872 INT num_pus = TY_Table_Size();
00873 if (arg_area_size_array == NULL) {
00874 max_arg_area_size_index = num_pus;
00875 arg_area_size_array = (UINT32*) Src_Alloc (
00876 sizeof(UINT32) * (max_arg_area_size_index+1));
00877 }
00878 else if (num_pus >= max_arg_area_size_index) {
00879
00880 num_pus = MAX(num_pus, 2 * max_arg_area_size_index);
00881 arg_area_size_array = TYPE_MEM_POOL_REALLOC_N (
00882 UINT32, &MEM_src_pool,
00883 arg_area_size_array,
00884 max_arg_area_size_index,
00885 num_pus);
00886 max_arg_area_size_index = num_pus;
00887 }
00888 }
00889
00890
00891 UINT32
00892 Get_PU_arg_area_size (TY_IDX pu)
00893 {
00894 Is_True(TY_kind(pu) == KIND_FUNCTION, ("Get_PU_arg_area_size of non-pu"));
00895 INT index = TY_id(pu);
00896 if (index >= max_arg_area_size_index) {
00897
00898 Init_PU_arg_area_size_array ();
00899 }
00900 Is_True(index < max_arg_area_size_index, ("Get_PU_arg_area_size still overflows?"));
00901 return arg_area_size_array[index];
00902 }
00903
00904 void
00905 Set_PU_arg_area_size (TY_IDX pu, UINT32 size)
00906 {
00907 Is_True(TY_kind(pu) == KIND_FUNCTION, ("Set_PU_arg_area_size of non-pu"));
00908 INT index = TY_id(pu);
00909 if (index >= max_arg_area_size_index) {
00910
00911 Init_PU_arg_area_size_array ();
00912 }
00913 Is_True(index < max_arg_area_size_index, ("Set_PU_arg_area_size still overflows?"));
00914 arg_area_size_array[index] = size;
00915 }
00916
00917
00918
00919 struct is_return_address
00920 {
00921 BOOL operator () (UINT32, const ST *st) const {
00922 return (strcmp (ST_name (st), "__return_address") == 0);
00923 }
00924 };
00925
00926 ST *
00927 Find_Special_Return_Address_Symbol (void)
00928 {
00929 ST_IDX st_idx = For_all_until (St_Table, CURRENT_SYMTAB,
00930 is_return_address ());
00931
00932 if (st_idx == 0)
00933 return NULL;
00934 else
00935 return ST_ptr(st_idx);
00936
00937 }
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949 static ST*
00950 Get_Section_ST(SECTION_IDX sec, UINT align, ST_SCLASS sclass)
00951 {
00952 if (SEC_block(sec) == NULL) {
00953 #if defined(TARG_X8664) || defined(TARG_SL) // bug 9795
00954 if (sec == _SEC_DATA && align != 0)
00955 align = MAX(align, 16);
00956 #if defined(TARG_SL)
00957 if (((sec == _SEC_SDATA) || (sec == _SEC_DATA)) && (align < 4))
00958 align = 4;
00959 #endif
00960 #endif
00961 ST *new_blk = New_ST_Block (Save_Str(SEC_name(sec)),
00962 TRUE, sclass, align, 0);
00963 Set_STB_section_idx(new_blk, sec);
00964 SEC_block(sec) = new_blk;
00965 Set_STB_section(new_blk);
00966 Set_STB_root_base(new_blk);
00967 if (SEC_is_gprel(sec)) {
00968 Set_STB_is_basereg(new_blk);
00969 Set_ST_gprel(new_blk);
00970 }
00971 if (SEC_is_merge(sec))
00972 Set_STB_merge(new_blk);
00973 if (SEC_is_exec(sec))
00974 Set_STB_exec(new_blk);
00975 if (SEC_is_nobits(sec))
00976 Set_STB_nobits(new_blk);
00977 Enter_ST(new_blk);
00978 }
00979 return SEC_block(sec);
00980 }
00981
00982
00983
00984
00985 static ST *
00986 Get_Section_ST_With_Given_Name (SECTION_IDX sec, ST_SCLASS sclass, STR_IDX name)
00987 {
00988 ST *newblk = NULL;
00989 ST *st;
00990 INT i;
00991 FOREACH_SYMBOL (GLOBAL_SYMTAB,st,i) {
00992 if (ST_class(st) != CLASS_BLOCK) continue;
00993 if (STB_section(st) && ST_name_idx(st) == name)
00994 {
00995 if (STB_section_idx(st) != sec) {
00996 ErrMsg (EC_LAY_section_name, ST_name(st), SEC_name(STB_section_idx(st)), SEC_name(sec));
00997 }
00998 newblk = st;
00999 break;
01000 }
01001 }
01002
01003 if (newblk == NULL) {
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013 if ( strncmp(Index_To_Str(name), ".gnu.linkonce.b.", 16) == 0 ||
01014 strncmp(Index_To_Str(name), ".bss.", 5) == 0 ) {
01015
01016 sec = _SEC_BSS;
01017 }
01018 else if ( sec == _SEC_BSS ) {
01019
01020 sec = _SEC_DATA;
01021 }
01022 ST *blk = Get_Section_ST(sec, 0, sclass);
01023 if (strcmp(SEC_name(sec), Index_To_Str(name)) == 0) {
01024
01025 newblk = blk;
01026 }
01027 else {
01028 newblk = Copy_ST_Block(blk);
01029 Set_ST_name_idx(newblk, name);
01030 }
01031 }
01032 return newblk;
01033 }
01034
01035 #ifndef KEY
01036 static
01037 #endif
01038 void
01039 Assign_ST_To_Named_Section (ST *st, STR_IDX name)
01040 {
01041 ST *newblk;
01042 if (ST_is_not_used(st))
01043 return;
01044
01045
01046 SECTION_IDX sec_idx;
01047
01048
01049 if (ST_has_Predefined_Named_Section(st, sec_idx))
01050 return;
01051 if (ST_class(st) == CLASS_FUNC) {
01052 if (ST_sclass(st) == SCLASS_EXTERN) {
01053
01054 return;
01055 }
01056
01057
01058 newblk = Get_Section_ST_With_Given_Name (_SEC_TEXT,
01059 ST_sclass(st), name);
01060 Set_ST_base(st, newblk);
01061 }
01062 else if (ST_class(st) == CLASS_VAR) {
01063
01064
01065
01066 SECTION_IDX sec;
01067 switch (ST_sclass(st)) {
01068 case SCLASS_DGLOBAL:
01069 case SCLASS_FSTATIC:
01070 case SCLASS_PSTATIC:
01071
01072 if (ST_is_constant(st)) sec = _SEC_RDATA;
01073
01074 else if ( ST_is_initialized(st) )
01075 sec = _SEC_DATA;
01076 else
01077 sec = _SEC_BSS;
01078 break;
01079 case SCLASS_UGLOBAL:
01080 #ifdef KEY
01081 if (ST_is_constant(st) &&
01082 !ST_is_weak_symbol(st)) {
01083 sec = _SEC_RDATA;
01084 } else
01085 #endif
01086 #if defined(TARG_SL)
01087 if (name != _SEC_BSS) {
01088 DevWarn("change user specified section symbol to be initialized");
01089 Set_ST_is_initialized(st);
01090 Set_ST_sclass(st, SCLASS_DGLOBAL);
01091 INITO_IDX ino = New_INITO(st);
01092 INITV_IDX inv = New_INITV();
01093 INITV_Init_Pad (inv, ST_size(st));
01094 Set_INITO_val(ino, inv);
01095 sec = _SEC_DATA;
01096 }
01097 else
01098 #endif
01099 sec = _SEC_BSS;
01100 break;
01101 #ifdef KEY
01102 case SCLASS_COMMON:
01103 case SCLASS_EXTERN:
01104 return;
01105 #endif
01106 default:
01107 FmtAssert(FALSE,
01108 ("unexpected sclass %d for section attribute on %s",
01109 ST_sclass(st), ST_name(st)));
01110 }
01111 newblk = Get_Section_ST_With_Given_Name (sec,
01112 SCLASS_UNKNOWN, name);
01113 Set_ST_base(st, newblk);
01114
01115
01116
01117 if (sec == _SEC_BSS && STB_section_idx(newblk) != _SEC_BSS) {
01118 DevWarn("change bss symbol to be initialized to 0");
01119 Set_ST_sclass(st, SCLASS_DGLOBAL);
01120 Set_ST_is_initialized(st);
01121 INITO_IDX ino = New_INITO(st);
01122 INITV_IDX inv = New_INITV();
01123 INITV_Init_Pad (inv, ST_size(st));
01124 Set_INITO_val(ino, inv);
01125 Clear_ST_init_value_zero(st);
01126 }
01127 ST_Block_Merge (newblk, st, 0, 0, SEC_max_sec_size(sec));
01128 }
01129 else
01130 FmtAssert(FALSE, ("unexpected section attribute"));
01131 }
01132
01133 struct Assign_Section_Names
01134 {
01135 inline void operator() (UINT32, ST_ATTR *st_attr) const {
01136 ST *st;
01137 STR_IDX name;
01138 if (ST_ATTR_kind (*st_attr) != ST_ATTR_SECTION_NAME)
01139 return;
01140 st = ST_ptr(ST_ATTR_st_idx(*st_attr));
01141 name = ST_ATTR_section_name(*st_attr);
01142 Assign_ST_To_Named_Section (st, name);
01143 }
01144 };
01145
01146
01147 struct find_st_attr_secname {
01148 ST_IDX st;
01149 find_st_attr_secname (const ST *s) : st (ST_st_idx (s)) {}
01150
01151 BOOL operator () (UINT, const ST_ATTR *st_attr) const {
01152 return (ST_ATTR_kind (*st_attr) == ST_ATTR_SECTION_NAME &&
01153 ST_ATTR_st_idx (*st_attr) == st);
01154 }
01155 };
01156
01157 STR_IDX
01158 Find_Section_Name_For_ST (const ST *st)
01159 {
01160 ST_IDX idx = ST_st_idx (st);
01161 ST_ATTR_IDX d;
01162
01163 d = For_all_until (St_Attr_Table, ST_IDX_level (idx),
01164 find_st_attr_secname(st));
01165 FmtAssert(d != 0, ("didn't find section name for ST %s", ST_name(st)));
01166 return ST_ATTR_section_name(St_Attr_Table(ST_IDX_level (idx), d));
01167 }
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186 static INT32
01187 Calc_Actual_Area ( TY_IDX pu_type, WN *pu_tree )
01188 {
01189 INT size;
01190 PLOC ploc;
01191
01192 size = 0;
01193 if (size == 0) {
01194 INT i;
01195 INT num_parms;
01196 INT regsize = MTYPE_RegisterSize(Spill_Int_Mtype);
01197 INTRINSIC id;
01198
01199 switch (WN_operator(pu_tree)) {
01200 case OPR_PICCALL:
01201 case OPR_ICALL:
01202 case OPR_CALL:
01203 #ifdef KEY
01204 case OPR_PURE_CALL_OP:
01205 #endif
01206 num_parms = WN_num_actuals(pu_tree);
01207 ploc = Setup_Output_Parameter_Locations(pu_type);
01208 for (i = 0; i < num_parms; i++) {
01209 ploc = Get_Output_Parameter_Location (TY_Of_Parameter(WN_actual(pu_tree,i)));
01210 #ifdef TARG_X8664
01211 if (ploc.reg == 0)
01212 size = PLOC_total_size(ploc);
01213 #endif
01214 }
01215 #ifndef TARG_X8664
01216 size = PLOC_total_size(ploc);
01217 #endif
01218 break;
01219 case OPR_INTRINSIC_OP:
01220 case OPR_INTRINSIC_CALL:
01221 id = (INTRINSIC) WN_intrinsic(pu_tree);
01222
01223 switch(id) {
01224 case INTRN_CONCATEXPR:
01225 size = 5 * regsize;
01226 break;
01227 #ifdef TARG_X8664
01228 case INTRN_F4COS:
01229 case INTRN_F8COS:
01230 case INTRN_FQCOS:
01231 case INTRN_F4SIN:
01232 case INTRN_F8SIN:
01233 case INTRN_FQSIN:
01234 if( Is_Target_32bit() &&
01235 CIS_Allowed ){
01236
01237
01238
01239 size += 2 * MTYPE_byte_size( Pointer_Mtype );
01240 }
01241
01242 #endif
01243 default:
01244 num_parms = WN_num_actuals(pu_tree);
01245
01246
01247
01248
01249
01250 if (MTYPE_id(WN_rtype(pu_tree)) == MTYPE_CQ)
01251 size = ROUNDUP(regsize, MTYPE_align_best(MTYPE_CQ));
01252 if (INTRN_by_value(id) == TRUE)
01253 {
01254 for(i= 0; i<num_parms; i++) {
01255 size += ROUNDUP(TY_size(TY_Of_Parameter(WN_actual(pu_tree,i))), regsize);
01256 }
01257 }
01258 else
01259 {
01260 size += num_parms * regsize;
01261 }
01262 break;
01263 }
01264 break;
01265 default:
01266 FmtAssert(FALSE, ("Calc_Actual_Area: unexpected opcode"));
01267 }
01268
01269
01270
01271 if (pu_type != (TY_IDX) NULL && TY_has_prototype (pu_type) &&
01272 !TY_is_varargs (pu_type)) {
01273 Set_PU_arg_area_size(pu_type, size);
01274 }
01275 }
01276 size -= Formal_Save_Area_Size;
01277 if (size < 0)
01278 size = 0;
01279 else if (Trace_Frame)
01280 fprintf(TFile, "<lay> actual_arg_area = %d\n", size);
01281
01282 return size;
01283 }
01284
01285
01286
01287
01288
01289 extern void
01290 Check_Actual_Stack_Size (WN *call_tree)
01291 {
01292 INT32 actual_size;
01293 switch (WN_operator(call_tree)) {
01294 case OPR_CALL:
01295 case OPR_PICCALL:
01296 actual_size = Calc_Actual_Area ( ST_pu_type(WN_st(call_tree)), call_tree);
01297 break;
01298 case OPR_ICALL:
01299 actual_size = Calc_Actual_Area ( WN_ty(call_tree), call_tree);
01300 break;
01301 default:
01302 FmtAssert(FALSE, ("unexpected opcode in Check_Actual_Stack_Size"));
01303 }
01304 #ifndef TARG_X8664
01305 FmtAssert(actual_size <= Current_PU_Actual_Size,
01306 ("size of actual area increased from %d to %d",
01307 Current_PU_Actual_Size, actual_size));
01308 #else
01309 FmtAssert(actual_size <= Current_PU_Actual_Size || Is_Target_32bit(),
01310
01311
01312 ("size of actual area increased from %d to %d",
01313 Current_PU_Actual_Size, actual_size));
01314 #endif
01315 }
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329 static INT32
01330 Max_Arg_Area_Bytes(WN *node)
01331 {
01332 OPCODE opcode;
01333 INT32 maxsize = 0;
01334
01335 opcode = WN_opcode (node);
01336
01337 switch (OPCODE_operator(opcode)) {
01338 case OPR_CALL:
01339 case OPR_PICCALL:
01340 #ifdef KEY
01341 case OPR_PURE_CALL_OP:
01342 #endif
01343 maxsize = Calc_Actual_Area ( ST_pu_type (WN_st (node)), node);
01344 Frame_Has_Calls = TRUE;
01345 break;
01346 case OPR_ICALL:
01347 maxsize = Calc_Actual_Area ( WN_ty(node), node );
01348 Frame_Has_Calls = TRUE;
01349 break;
01350 case OPR_INTRINSIC_OP:
01351 case OPR_INTRINSIC_CALL:
01352 maxsize = Calc_Actual_Area ( (TY_IDX) NULL, node );
01353 Frame_Has_Calls = TRUE;
01354 break;
01355 #if defined(TARG_IA32) || defined(TARG_X8664)
01356 case OPR_IO:
01357 if( Is_Target_32bit() ){
01358 maxsize = 16;
01359 }
01360 break;
01361 #endif
01362 }
01363
01364 if (opcode == OPC_BLOCK) {
01365 WN *wn;
01366 for ( wn = WN_first(node); wn != NULL; wn = WN_next(wn) ) {
01367 INT32 wn_size;
01368 if (((WN_opcode(wn) == OPC_PRAGMA) || (WN_opcode(wn) == OPC_XPRAGMA)) &&
01369 (WN_pragma(wn) == WN_PRAGMA_COPYIN)) {
01370 INT32 copyincount = 3;
01371 WN *next;
01372 while ((next = WN_next(wn)) &&
01373 ((WN_opcode(next) == OPC_PRAGMA) ||
01374 (WN_opcode(next) == OPC_XPRAGMA)) &&
01375 (WN_pragma(next) == WN_PRAGMA_COPYIN)) {
01376 copyincount += 2;
01377 wn = next;
01378 }
01379 wn_size = copyincount * MTYPE_RegisterSize(Spill_Int_Mtype);
01380 maxsize = MAX(maxsize, wn_size);
01381 Frame_Has_Calls = TRUE;
01382 } else {
01383 wn_size = Max_Arg_Area_Bytes (wn);
01384 maxsize = MAX(maxsize, wn_size);
01385 }
01386 }
01387 }
01388 else if (!OPCODE_is_leaf(opcode)) {
01389 INT i;
01390
01391 for (i = 0; i < WN_kid_count(node); i++) {
01392 if (WN_kid(node, i) != NULL) {
01393 INT32 wn_size = Max_Arg_Area_Bytes (WN_kid(node, i));
01394 maxsize = MAX(maxsize, wn_size);
01395 }
01396 }
01397 }
01398
01399 return maxsize;
01400 }
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412 void
01413 Reset_UPFORMAL_Segment(void)
01414 {
01415 ST *block;
01416
01417 if (block = SF_Block(SFSEG_UPFORMAL))
01418 {
01419 Set_ST_ofst(block, 0);
01420 Set_STB_size(block, 0);
01421 }
01422 else
01423 {
01424 Initialize_Frame_Segment (SFSEG_UPFORMAL, SCLASS_AUTO, INCREMENT);
01425 }
01426 }
01427
01428
01429
01430
01431
01432 static void
01433 Allocate_Entry_Formal(ST *formal, BOOL on_stack, BOOL in_formal_reg)
01434 {
01435 if (Has_No_Base_Block(formal))
01436 {
01437
01438
01439
01440
01441 if (PU_has_altentry(Get_Current_PU()) && ST_declared_static(formal))
01442 {
01443 SECTION_IDX sec;
01444
01445 Set_ST_sclass(formal, SCLASS_PSTATIC);
01446 Clear_ST_is_value_parm(formal);
01447 sec = Shorten_Section(formal, _SEC_BSS);
01448 Allocate_Object_To_Section(formal, sec, Adjusted_Alignment(formal));
01449 }
01450 #ifdef TARG_NVISA
01451
01452
01453 else if (ST_in_shared_mem(formal)) {
01454 Clear_ST_is_value_parm(formal);
01455 Allocate_Object_To_Section(formal, _SEC_BSS, Adjusted_Alignment(formal));
01456 }
01457 #endif
01458 #ifndef TARG_MIPS // bug 12772
01459 else if (in_formal_reg)
01460 {
01461
01462 Add_Object_To_Frame_Segment ( formal, SFSEG_FORMAL, TRUE );
01463 }
01464 #endif
01465 else if (on_stack)
01466 {
01467
01468 if (PU_has_altentry(Get_Current_PU())) {
01469 Add_Object_To_Frame_Segment ( formal, SFSEG_FTEMP, TRUE );
01470 }
01471 else {
01472 Add_Object_To_Frame_Segment ( formal, SFSEG_UPFORMAL, TRUE );
01473 }
01474 }
01475 #ifdef TARG_MIPS // bug 12772
01476 else if (in_formal_reg)
01477 {
01478
01479 Add_Object_To_Frame_Segment ( formal, SFSEG_FORMAL, TRUE );
01480 }
01481 #endif
01482 else
01483 {
01484
01485
01486 Add_Object_To_Frame_Segment ( formal, SFSEG_FTEMP, TRUE );
01487 }
01488 }
01489 }
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503 static TY_IDX Formal_ST_type(ST *sym)
01504 {
01505 TY_IDX type= ST_type(sym);
01506
01507 if (ST_sclass(sym) == SCLASS_FORMAL_REF)
01508 {
01509 return Make_Pointer_Type(type);
01510 }
01511 return type;
01512 }
01513
01514
01515 # if MAX_NUMBER_OF_REGISTER_PARAMETERS > 0
01516 ST *vararg_symbols[MAX_NUMBER_OF_REGISTER_PARAMETERS];
01517 # else
01518
01519 # define vararg_symbols ((ST * *)0) // Not accessed
01520 # endif
01521
01522
01523 static void
01524 Clear_Vararg_Symbols (void)
01525 {
01526 INT i;
01527 for (i = 0; i < MAX_NUMBER_OF_REGISTER_PARAMETERS; i++) {
01528 vararg_symbols[i] = NULL;
01529 }
01530 }
01531
01532
01533 extern ST*
01534 Get_Vararg_Symbol (PLOC ploc)
01535 {
01536 #ifndef TARG_X8664
01537 Is_True(PLOC_reg(ploc) <
01538 First_Int_Preg_Param_Offset+MAX_NUMBER_OF_REGISTER_PARAMETERS,
01539 ("Get_Vararg_Symbol: ploc %d out of range", PLOC_reg(ploc)));
01540 return vararg_symbols[PLOC_reg(ploc)-First_Int_Preg_Param_Offset];
01541 #else
01542 if (Preg_Offset_Is_Int(PLOC_reg(ploc)))
01543 return vararg_symbols[PLOC_reg(ploc)-First_Int_Preg_Param_Offset];
01544 else
01545 return vararg_symbols[PLOC_reg(ploc)-First_Float_Preg_Param_Offset+MAX_NUMBER_OF_INT_REGISTER_PARAMETERS];
01546 #endif
01547 }
01548
01549 #ifdef TARG_X8664
01550
01551
01552
01553
01554
01555
01556 ST *Get_Vararg_Save_Area_Info(int &fixed_int_parms,
01557 int &fixed_float_parms,
01558 ST* &upformal) {
01559 INT i;
01560 for (i = MAX_NUMBER_OF_INT_REGISTER_PARAMETERS;
01561 i > 0 && vararg_symbols[i-1] != NULL;
01562 i--)
01563 ;
01564 fixed_int_parms = i;
01565 for (i = MAX_NUMBER_OF_REGISTER_PARAMETERS;
01566 i > MAX_NUMBER_OF_INT_REGISTER_PARAMETERS && vararg_symbols[i-1] != NULL;
01567 i--)
01568 ;
01569 fixed_float_parms = i - MAX_NUMBER_OF_INT_REGISTER_PARAMETERS;
01570 upformal = SF_Block(SFSEG_UPFORMAL);
01571 if (fixed_int_parms < MAX_NUMBER_OF_INT_REGISTER_PARAMETERS)
01572 return vararg_symbols[fixed_int_parms];
01573 else if (fixed_float_parms < MAX_NUMBER_OF_FLOAT_REGISTER_PARAMETERS)
01574 return vararg_symbols[fixed_float_parms+MAX_NUMBER_OF_INT_REGISTER_PARAMETERS];
01575 else return NULL;
01576 }
01577 #endif
01578
01579
01580
01581
01582
01583 static void
01584 Allocate_All_Formals (WN *pu)
01585 {
01586 INT i;
01587 PLOC ploc;
01588 ST *sym;
01589 BOOL varargs;
01590 TY_IDX pu_type = ST_pu_type (WN_st (pu));
01591
01592 Init_ST_formal_info_for_PU (WN_num_formals(pu));
01593 varargs = TY_is_varargs (pu_type);
01594 ploc = Setup_Input_Parameter_Locations(pu_type);
01595
01596
01597
01598
01599 for (i = 0; i < WN_num_formals(pu); i++)
01600 {
01601 sym = WN_st(WN_formal(pu, i));
01602
01603 ploc = Get_Input_Parameter_Location( Formal_ST_type(sym));
01604
01605 sym = Formal_Sym(sym, PLOC_on_stack(ploc) || varargs);
01606
01607 Allocate_Entry_Formal (sym, PLOC_on_stack(ploc), Is_Formal_Preg(PLOC_reg(ploc)));
01608 }
01609
01610 if ( PU_has_altentry(Get_Current_PU()))
01611 {
01612 WN *tree;
01613
01614 for ( tree = WN_first(WN_func_body(pu)); tree != NULL; tree = WN_next(tree))
01615 {
01616 if (WN_opcode(tree) == OPC_ALTENTRY)
01617 {
01618 Reset_UPFORMAL_Segment();
01619 ploc = Setup_Input_Parameter_Locations(ST_pu_type(WN_st(tree)));
01620 for (i = 0; i < WN_kid_count(tree); i++)
01621 {
01622 sym = WN_st(WN_formal(tree, i));
01623
01624 ploc = Get_Input_Parameter_Location ( Formal_ST_type(sym));
01625
01626 sym = Formal_Sym(sym, PLOC_on_stack(ploc) || varargs);
01627
01628 Allocate_Entry_Formal (sym, TRUE, Is_Formal_Preg(PLOC_reg(ploc)));
01629 }
01630 }
01631 }
01632 }
01633
01634 if (varargs) {
01635
01636
01637
01638
01639
01640
01641
01642 ST *last_fixed_symbol = sym;
01643 PLOC last_fixed_ploc = ploc;
01644
01645 TY_IDX vararg_type = Copy_TY(ST_type(Int_Preg));
01646
01647 Set_TY_no_ansi_alias (vararg_type);
01648 #ifdef TARG_X8664
01649 TY_IDX vararg_type2 = Copy_TY(MTYPE_To_TY(MTYPE_F16));
01650
01651 Set_TY_no_ansi_alias (vararg_type);
01652 #endif
01653
01654 #ifndef TARG_X8664 // x86-64 always needs to call Get_Vararg_Parameter_Location
01655 if (PLOC_is_nonempty(ploc) && !PLOC_on_stack(ploc)) {
01656
01657 #endif
01658 ploc = Get_Vararg_Input_Parameter_Location (ploc);
01659 #ifndef TARG_X8664
01660 }
01661 #endif
01662
01663 #ifdef TARG_X8664
01664 if (!PLOC_on_stack(ploc) && PLOC_size(ploc) == 8 &&
01665 (PLOC_reg(ploc) & 1) == 0) {
01666
01667
01668 sym = Gen_Temp_Symbol (vararg_type, "vararg");
01669 Set_ST_addr_saved(sym);
01670 Add_Object_To_Frame_Segment ( sym, SFSEG_FTEMP, TRUE );
01671 }
01672 BOOL float_seen = FALSE;
01673 #endif
01674 while (!PLOC_on_stack(ploc)) {
01675
01676
01677
01678 #ifdef TARG_X8664
01679 if (! float_seen && PLOC_size(ploc) == 16) {
01680
01681 float_seen = TRUE;
01682
01683 for (INT k = 0;
01684 k < (PLOC_reg(ploc)-First_Float_Preg_Param_Offset);
01685 k++) {
01686 sym = Gen_Temp_Symbol (vararg_type2, "vararg");
01687 Set_ST_addr_saved(sym);
01688 Add_Object_To_Frame_Segment ( sym, SFSEG_FTEMP, TRUE );
01689 }
01690 }
01691 if (PLOC_size(ploc) == 16)
01692 sym = Gen_Temp_Symbol (vararg_type2, "vararg");
01693 else
01694 #endif
01695 sym = Gen_Temp_Symbol (vararg_type, "vararg");
01696 Set_ST_sclass (sym, SCLASS_FORMAL);
01697 Set_ST_is_value_parm( sym);
01698 Set_ST_addr_saved(sym);
01699 #ifdef TARG_X8664
01700 if (Preg_Offset_Is_Int(PLOC_reg(ploc)))
01701 #endif
01702 vararg_symbols[PLOC_reg(ploc)-First_Int_Preg_Param_Offset] = sym;
01703 #ifdef TARG_X8664
01704 else if( Preg_Offset_Is_Float(PLOC_reg(ploc)) )
01705 vararg_symbols[PLOC_reg(ploc)-First_Float_Preg_Param_Offset+MAX_NUMBER_OF_INT_REGISTER_PARAMETERS] = sym;
01706 else
01707 FmtAssert( false, ("Unknown vararg symbol type.") );
01708 #endif
01709 #ifndef TARG_X8664
01710 Allocate_Entry_Formal(sym, PLOC_on_stack(ploc), Is_Formal_Preg(PLOC_reg(ploc)));
01711
01712
01713
01714
01715
01716
01717 Set_ST_base(sym, last_fixed_symbol);
01718 Set_ST_ofst(sym, PLOC_offset(ploc) - PLOC_offset(last_fixed_ploc));
01719 #else
01720 Add_Object_To_Frame_Segment ( sym, SFSEG_FTEMP, TRUE );
01721 #endif
01722
01723 ploc = Get_Vararg_Input_Parameter_Location (ploc);
01724 }
01725 }
01726 }
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737 extern ST*
01738 Get_Altentry_UpFormal_Symbol (ST *formal, PLOC ploc)
01739 {
01740 ST* upformal = Copy_ST(formal);
01741 Set_ST_name(upformal, Save_Str2(ST_name(upformal), ".upformal."));
01742 Set_ST_sclass(upformal, SCLASS_FORMAL);
01743 Clear_ST_gprel(upformal);
01744
01745 INT offset = PLOC_offset(ploc) - Formal_Save_Area_Size;
01746 if (PUSH_FRAME_POINTER_ON_STACK && PU_has_alloca(Get_Current_PU())) {
01747 offset += MTYPE_byte_size(Pointer_Mtype);
01748 }
01749 #ifdef TARG_X8664 // always reserve FP save location to maintain quad align
01750 else offset += MTYPE_byte_size(Pointer_Mtype);
01751 #endif
01752 if (PUSH_RETURN_ADDRESS_ON_STACK) {
01753 offset += MTYPE_byte_size(Pointer_Mtype);
01754 }
01755
01756 Assign_Object_To_Frame_Segment (upformal, SFSEG_UPFORMAL, offset);
01757 return upformal;
01758 }
01759
01760
01761
01762 static void
01763 Calc_Formal_Area (WN *pu_tree, INT32 *formal_size, INT32 *upformal_size)
01764 {
01765 INT maxsize;
01766 ST *st = WN_st (pu_tree);
01767 TY_IDX pu_ty = ST_pu_type (st);
01768 FmtAssert(WN_opcode(pu_tree) == OPC_FUNC_ENTRY, ("not a func-entry"));
01769
01770 if (TY_is_varargs (pu_ty)) {
01771 *formal_size = Formal_Save_Area_Size;
01772 *upformal_size = 0;
01773
01774 return;
01775 }
01776 else if (Get_PU_arg_area_size(pu_ty) > 0) {
01777 ;
01778 }
01779 else {
01780 PLOC ploc;
01781 INT i;
01782 #ifdef TARG_X8664
01783 Set_PU_arg_area_size(pu_ty, 0);
01784 #endif
01785 ploc = Setup_Input_Parameter_Locations(pu_ty);
01786 for (i = 0; i < WN_num_formals(pu_tree); i++) {
01787 ploc = Get_Input_Parameter_Location (TY_Of_Parameter(WN_formal(pu_tree,i)));
01788 #ifdef TARG_X8664
01789 if (ploc.reg == 0)
01790 Set_PU_arg_area_size(pu_ty, PLOC_total_size(ploc));
01791 #endif
01792 }
01793 #ifndef TARG_X8664
01794 Set_PU_arg_area_size(pu_ty, PLOC_total_size(ploc));
01795 #endif
01796 }
01797 maxsize = Get_PU_arg_area_size(pu_ty);
01798 if ( PU_has_altentry(Get_Current_PU())) {
01799
01800
01801
01802
01803 WN *tree = WN_first(WN_func_body(pu_tree));
01804 for (; tree != NULL; tree = WN_next(tree)) {
01805 if (WN_opcode(tree) == OPC_ALTENTRY) {
01806 PLOC ploc;
01807 INT i;
01808 ploc = Setup_Input_Parameter_Locations(ST_pu_type(WN_st(tree)));
01809 for (i = 0; i < WN_kid_count(tree); i++) {
01810 ploc = Get_Input_Parameter_Location (TY_Of_Parameter(WN_formal(tree,i)));
01811 }
01812 maxsize = MAX(maxsize, PLOC_total_size(ploc));
01813 }
01814 }
01815 }
01816
01817 *formal_size = MIN (Get_PU_arg_area_size(pu_ty), Formal_Save_Area_Size);
01818
01819 *upformal_size = MAX (maxsize - Formal_Save_Area_Size, 0);
01820 }
01821
01822
01823
01824 static inline INT64
01825 Calc_Local_Area (void)
01826 {
01827 INT64 local_size = 0;
01828 ST_ITER first = Scope_tab[CURRENT_SYMTAB].st_tab->begin ();
01829 const ST_ITER last = Scope_tab[CURRENT_SYMTAB].st_tab->end ();
01830
01831 while (++first != last) {
01832 ST &st = *first;
01833 switch (ST_sclass (st)) {
01834
01835 case SCLASS_AUTO:
01836
01837
01838 if (ST_base_idx (st) != ST_st_idx (st))
01839 break;
01840 if (Trace_Frame)
01841 fprintf (TFile, "local %s has size %lld\n", ST_name(&st),
01842 #ifdef KEY
01843
01844 (ST_size(&st) == 0 ? 1 : 0) +
01845 #endif
01846 ST_size(&st));
01847 local_size += ST_size(&st);
01848 #ifdef KEY
01849 if (ST_class(&st) == CLASS_VAR && (!Current_pu ||
01850 (PU_src_lang (Get_Current_PU()) & PU_CXX_LANG)) && ST_size(&st) == 0)
01851 local_size++;
01852 #endif
01853 break;
01854
01855 case SCLASS_DGLOBAL:
01856 case SCLASS_COMMON:
01857
01858
01859 if (ST_type (st) != 0) {
01860 Set_ST_type (st, Make_Align_Type (ST_type (st),
01861 Adjusted_Alignment (&st)));
01862 }
01863 break;
01864 }
01865 }
01866
01867 return local_size;
01868 }
01869
01870
01871
01872
01873
01874
01875 static void
01876 Init_Segment_Descriptors(void)
01877 {
01878 SF_SEGMENT s;
01879
01880 for (s = (SF_SEGMENT) (SFSEG_UNKNOWN+1); s <= SFSEG_LAST; s = (SF_SEGMENT) (s + 1) )
01881 {
01882
01883
01884
01885 SF_Block(s) = Create_Local_Block(INCREMENT,
01886 Save_Str2 (SF_Name(s),"_StkSeg"));
01887 SF_Maxsize(s) = MAX_SFSEG_BYTES;
01888 }
01889
01890 Set_ST_is_not_used(SF_Block(SFSEG_FORMAL));
01891 }
01892
01893
01894 #define SEG_SIZE(s) \
01895 (SF_Block(s) ? \
01896 STB_size(SF_Block(s)) : \
01897 ((SF_Maxsize(s) == MAX_SFSEG_BYTES) ? 0 : SF_Maxsize(s) ) )
01898
01899
01900 static void
01901 Init_Formal_Segments (INT32 formal_size, INT32 upformal_size)
01902 {
01903 #ifndef TARG_X8664
01904 SF_Maxsize ( SFSEG_UPFORMAL ) = ROUNDUP(upformal_size, stack_align);
01905 SF_Maxsize ( SFSEG_FORMAL ) = ROUNDUP(formal_size, stack_align);
01906 #endif
01907 }
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918 static void
01919 Init_Frame_For_PU (INT32 actual_size)
01920 {
01921
01922
01923
01924
01925
01926 SF_Maxsize ( SFSEG_ACTUAL ) = ROUNDUP(actual_size, stack_align);
01927
01928
01929
01930 SF_Maxsize ( SFSEG_FTEMP ) =
01931 MAX_FRAME_OFFSET - SEG_SIZE(SFSEG_FORMAL) - SEG_SIZE(SFSEG_ACTUAL);
01932
01933
01934
01935
01936
01937 Large_Object_Bytes = DEFAULT_LARGE_OBJECT_BYTES;
01938 }
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949 static void
01950 Bind_Stack_Frame ( ST *SP_baseST, ST *FP_baseST )
01951 {
01952 Set_Direction (Get_Direction(SP_baseST), SF_Block(SFSEG_ACTUAL));
01953 Set_Direction (Get_Direction(SP_baseST), SF_Block(SFSEG_UPFORMAL));
01954
01955 Set_Direction (Get_Direction(SP_baseST), SF_Block(SFSEG_FORMAL));
01956
01957 switch (Current_PU_Stack_Model) {
01958 case SMODEL_SMALL:
01959 case SMODEL_LARGE:
01960 Set_Direction (Get_Direction(SP_baseST), SF_Block(SFSEG_FTEMP));
01961 break;
01962 case SMODEL_DYNAMIC:
01963 Set_Direction (Get_Direction(FP_baseST), SF_Block(SFSEG_FTEMP));
01964 break;
01965 default:
01966 FmtAssert ( TRUE,
01967 ("UNDEFINED Stack Model in Bind_Stack_Frame" ));
01968 }
01969 }
01970
01971 #define MERGE_SEGMENT(base, seg, mxfrm) \
01972 ST_Block_Merge (base, SF_Block(seg), 0, 0, mxfrm)
01973
01974
01975
01976
01977
01978
01979
01980
01981
01982
01983 static void
01984 Merge_Fixed_Stack_Frame(ST *SP_baseST, ST *FP_baseST)
01985 {
01986 INT32 orig_formal_size;
01987 FmtAssert(SP_baseST != NULL && FP_baseST != NULL,
01988 ("Initialize_Stack_Frame: Invalid parameters"));
01989
01990 Set_STB_size(SP_baseST,0);
01991 Set_STB_size(FP_baseST,0);
01992
01993
01994 Set_STB_size(SF_Block(SFSEG_ACTUAL), SF_Maxsize(SFSEG_ACTUAL));
01995
01996
01997 BOOL pu_is_varargs = TY_is_varargs (ST_pu_type (Get_Current_PU_ST()));
01998 if (pu_is_varargs) {
01999 orig_formal_size = STB_size(SF_Block(SFSEG_FORMAL));
02000 #ifndef TARG_X8664
02001 Set_STB_size(SF_Block(SFSEG_FORMAL), SF_Maxsize(SFSEG_FORMAL));
02002 #endif
02003 }
02004
02005 switch ( Current_PU_Stack_Model) {
02006 case SMODEL_SMALL:
02007 MERGE_SEGMENT(SP_baseST, SFSEG_ACTUAL, Max_Small_Frame_Offset);
02008
02009 MERGE_SEGMENT(SP_baseST, SFSEG_FTEMP, Max_Small_Frame_Offset);
02010
02011 #ifndef KEY
02012
02013
02014 #else
02015
02016 Set_ST_base(SF_Block(SFSEG_FORMAL), SP_baseST);
02017 Set_ST_base(SF_Block(SFSEG_UPFORMAL), SP_baseST);
02018 #endif
02019 break;
02020
02021 case SMODEL_LARGE:
02022 MERGE_SEGMENT(SP_baseST, SFSEG_ACTUAL, MAX_LARGE_FRAME_OFFSET);
02023 MERGE_SEGMENT(SP_baseST, SFSEG_FTEMP, MAX_LARGE_FRAME_OFFSET);
02024 Set_ST_base(SF_Block(SFSEG_UPFORMAL), FP_baseST);
02025 Set_ST_ofst (SF_Block(SFSEG_UPFORMAL), Stack_Offset_Adjustment);
02026 MERGE_SEGMENT(FP_baseST, SFSEG_FORMAL, MAX_LARGE_FRAME_OFFSET);
02027 break;
02028
02029 case SMODEL_DYNAMIC:
02030 MERGE_SEGMENT(SP_baseST, SFSEG_ACTUAL, MAX_LARGE_FRAME_OFFSET);
02031 Set_ST_base(SF_Block(SFSEG_UPFORMAL), FP_baseST);
02032 Set_ST_ofst (SF_Block(SFSEG_UPFORMAL), Stack_Offset_Adjustment);
02033
02034 MERGE_SEGMENT(FP_baseST, SFSEG_FORMAL, MAX_LARGE_FRAME_OFFSET);
02035 MERGE_SEGMENT(FP_baseST, SFSEG_FTEMP, MAX_LARGE_FRAME_OFFSET);
02036 break;
02037
02038 default:
02039 FmtAssert ( TRUE,
02040 ("UNDEFINED Stack Model in Initialize_Stack_Frame" ));
02041 }
02042 if (pu_is_varargs) {
02043
02044 Set_STB_size(SF_Block(SFSEG_FORMAL), orig_formal_size);
02045 }
02046 }
02047
02048 static STACK_MODEL
02049 Choose_Stack_Model (INT64 frame_size)
02050 {
02051 if (PU_has_alloca(Get_Current_PU())) {
02052 return SMODEL_DYNAMIC;
02053 }
02054 #ifdef TARG_X8664
02055 if (Opt_Level == 0 || Force_Frame_Pointer || Call_Mcount ||
02056 Debug_Level > 0) {
02057 return SMODEL_DYNAMIC;
02058 }
02059 #endif
02060 else if (PU_has_nested(Get_Current_PU())) {
02061 return SMODEL_DYNAMIC;
02062 }
02063 else if (Force_Large_Stack_Model) {
02064 return SMODEL_LARGE;
02065 }
02066 else if (frame_size < Max_Small_Frame_Offset) {
02067 return SMODEL_SMALL;
02068 }
02069 else if (frame_size < MAX_LARGE_FRAME_OFFSET) {
02070 return SMODEL_LARGE;
02071 }
02072 else {
02073 FmtAssert ( FALSE, ("64-bit stack frame NYI"));
02074 return SMODEL_UNDEF;
02075 }
02076 }
02077
02078
02079
02080 static void
02081 Allocate_Local_Spill_Sym (void)
02082 {
02083 if (Current_PU_Stack_Model == SMODEL_SMALL) {
02084
02085 Local_Spill_Sym = NULL;
02086 }
02087 else {
02088 Local_Spill_Sym = Gen_Temp_Symbol (Spill_Int_Type, "reserved_spill");
02089 Allocate_Temp_To_Memory (Local_Spill_Sym);
02090 }
02091 }
02092
02093 extern void
02094 Initialize_Stack_Frame (WN *PU_tree)
02095 {
02096 INT32 actual_size;
02097 INT32 formal_size;
02098 INT32 upformal_size;
02099 INT64 frame_size = 0;
02100
02101 Set_Error_Phase("Data Layout");
02102 Trace_Frame = Get_Trace(TP_DATALAYOUT, 1);
02103 FmtAssert(WN_opcode(PU_tree) == OPC_FUNC_ENTRY,
02104 ("Determine_Stack_Model: The PU_tree node does not point to a OPC_FUNC_ENTRY"));
02105
02106 if (ST_asm_function_st(*WN_st(PU_tree))) {
02107
02108
02109 return;
02110 }
02111
02112 if (Trace_Frame)
02113 fprintf(TFile, "<lay> Determine_Stack_Model for %s\n",
02114 ST_name(WN_st(PU_tree)));
02115
02116 #ifndef TARG_X8664
02117 if (PU_has_return_address(Get_Current_PU())
02118 && MTYPE_byte_size(Pointer_Mtype) < MTYPE_byte_size(Spill_Int_Mtype) )
02119 {
02120
02121
02122
02123
02124
02125
02126 ST *ra_sym = Find_Special_Return_Address_Symbol();
02127 ST *st_base = New_ST ();
02128 ST_Init (st_base, Save_Str("return_address_base"),
02129 ST_class(ra_sym), ST_sclass(ra_sym), ST_export(ra_sym),
02130 MTYPE_To_TY(Spill_Int_Mtype) );
02131 Set_ST_base (ra_sym, st_base);
02132 Set_ST_ofst (ra_sym, Target_Byte_Sex == BIG_ENDIAN ?
02133 MTYPE_byte_size(Spill_Int_Mtype) - MTYPE_byte_size(Pointer_Mtype) :
02134 0);
02135 }
02136 #endif
02137
02138 Init_Segment_Descriptors();
02139 Init_PU_arg_area_size_array();
02140
02141 Calc_Formal_Area (PU_tree, &formal_size, &upformal_size);
02142
02143
02144 Frame_Has_Calls = FALSE;
02145 actual_size = Max_Arg_Area_Bytes(PU_tree);
02146
02147 actual_size = ROUNDUP(actual_size, MTYPE_byte_size(Spill_Int_Mtype));
02148 if (mp_io && actual_size < MTYPE_byte_size(Spill_Int_Mtype)) {
02149 actual_size = MTYPE_byte_size(Spill_Int_Mtype);
02150 Frame_Has_Calls = TRUE;
02151 }
02152 Current_PU_Actual_Size = actual_size;
02153
02154 frame_size = Calc_Local_Area ();
02155
02156 if (PUSH_FRAME_POINTER_ON_STACK) {
02157
02158
02159 ST* old_fp = New_ST ();
02160 ST_Init (old_fp,
02161 Save_Str("old_frame_pointer"),
02162 CLASS_VAR,
02163 SCLASS_FORMAL,
02164 EXPORT_LOCAL,
02165 MTYPE_To_TY(Pointer_Mtype));
02166 Add_Object_To_Frame_Segment (old_fp, SFSEG_UPFORMAL, TRUE);
02167 upformal_size += MTYPE_byte_size(Pointer_Mtype);
02168 }
02169
02170 if (PUSH_RETURN_ADDRESS_ON_STACK) {
02171
02172 ST* ra_st;
02173 #ifdef KEY // bug 12261: check before creating another return address symbol
02174 if ((ra_st = Find_Special_Return_Address_Symbol()) == NULL) {
02175 #endif
02176 ra_st = New_ST ();
02177 ST_Init (ra_st,
02178 Save_Str("return_address"),
02179 CLASS_VAR,
02180 SCLASS_FORMAL,
02181 EXPORT_LOCAL,
02182 MTYPE_To_TY(Pointer_Mtype));
02183 #ifdef KEY
02184 }
02185 #endif
02186 Add_Object_To_Frame_Segment (ra_st, SFSEG_UPFORMAL, TRUE);
02187 upformal_size += MTYPE_byte_size(Pointer_Mtype);
02188 }
02189
02190 if (Trace_Frame) {
02191 fprintf(TFile, "<lay> locals size = %lld\n", frame_size);
02192 fprintf(TFile, "<lay> upformal size = %d, formal size = %d\n",
02193 upformal_size, formal_size);
02194 fprintf(TFile, "<lay> actual size = %d\n", actual_size);
02195 }
02196 frame_size += formal_size + actual_size;
02197
02198
02199 frame_size += DEFAULT_TEMP_SPACE_BYTES;
02200
02201
02202
02203 frame_size += upformal_size;
02204
02205 Current_PU_Stack_Model = Choose_Stack_Model(frame_size);
02206 if (Trace_Frame) {
02207 fprintf(TFile, "<lay> guess frame_size = %lld\n", frame_size);
02208 fprintf(TFile, "<lay> stack model = %d\n", Current_PU_Stack_Model);
02209 }
02210
02211
02212 stack_direction = DECREMENT;
02213 SP_Sym = Create_Base_Reg (".SP", INCREMENT);
02214 FP_Sym = Create_Base_Reg (".FP", DECREMENT);
02215
02216
02217 Allocate_All_Formals (PU_tree);
02218 Init_Formal_Segments (formal_size, upformal_size);
02219
02220 #ifdef TARG_NVISA
02221
02222 if ((formal_size + upformal_size) > 256)
02223 ErrMsg (EC_Too_Many_Args, ST_name(WN_st(PU_tree)));
02224 #endif
02225 }
02226
02227
02228 extern void
02229 Calculate_Stack_Frame_Sizes (WN *PU_tree)
02230 {
02231 if (ST_asm_function_st(*Get_Current_PU_ST())) {
02232
02233
02234 return;
02235 }
02236
02237 INT32 actual_size;
02238
02239 actual_size = Max_Arg_Area_Bytes(PU_tree);
02240
02241 actual_size = ROUNDUP(actual_size, MTYPE_byte_size(Spill_Int_Mtype));
02242 if (Trace_Frame && actual_size != Current_PU_Actual_Size) {
02243 fprintf(TFile, "actual_size was %d, now is %d\n",
02244 Current_PU_Actual_Size, actual_size);
02245 }
02246
02247
02248 Current_PU_Actual_Size = MAX(Current_PU_Actual_Size, actual_size);
02249
02250 Init_Frame_For_PU (Current_PU_Actual_Size);
02251 Bind_Stack_Frame (SP_Sym, FP_Sym);
02252
02253 Merge_Fixed_Stack_Frame (SP_Sym, FP_Sym);
02254
02255 Allocate_Local_Spill_Sym ();
02256 }
02257
02258
02259
02260
02261
02262
02263
02264
02265
02266
02267
02268
02269
02270 static void
02271 Process_Stack_Variable ( ST *st )
02272 {
02273 ST_SCLASS sc;
02274 UINT64 size;
02275 BOOL is_root_block = Is_Allocatable_Root_Block(st);
02276 ST *base;
02277
02278 if (! is_root_block && ST_class(st) == CLASS_BLOCK) return;
02279
02280 if((PU_src_lang(Get_Current_PU()) & (PU_CXX_LANG|PU_C_LANG)) &&
02281 ST_is_return_var(st)) {
02282 Set_ST_base(st, FP_Sym);
02283 Set_ST_ofst(st, Is_Target_32bit()? 4 : 8);
02284 return;
02285 }
02286
02287 sc = ST_sclass(st);
02288 Is_True ( (sc == SCLASS_AUTO),
02289 ("Process_Stack_Variable: Invalid SCLASS %d\n",ST_sclass(st)) );
02290
02291 size = (is_root_block) ? STB_size(st) : TY_size(ST_type(st));
02292
02293
02294 if (Current_PU_Stack_Model == SMODEL_SMALL ||
02295 (Current_PU_Stack_Model == SMODEL_LARGE && size < Large_Object_Bytes))
02296 base = SP_Sym;
02297 else
02298 base = FP_Sym;
02299 ST_Block_Merge (base, st, 0, 0, MAX_FRAME_OFFSET);
02300 }
02301
02302 static void
02303 Trace_Stack_Segments(const char *msg, ST *SP_baseST, ST *FP_baseST )
02304 {
02305 SF_SEGMENT s;
02306
02307 fprintf(TFile, "Stack Segment after \"%s\"\n", msg);
02308 fprintf(TFile, "SegName \toffset\tbase\tblksize\talign\tmaxsize\n");
02309
02310
02311 for ( s = SFSEG_FIRST; s <= SFSEG_LAST; s = (SF_SEGMENT) (s + 1) ) {
02312 ST *block;
02313 INT64 size, offset;
02314 INT align;
02315 const char *basename;
02316
02317 block = SF_Block(s);
02318 basename = block ? ST_name(ST_base(block)) : "<none>";
02319 size = block? STB_size(block): 0;
02320 align = block? STB_align(block): 0;
02321 offset = block? ST_ofst(block): 0;
02322 fprintf(TFile, "%s \t%lld\t%s\t%lld\t%d\t%lld\n",
02323 SF_Name(s), offset, basename, size, align, SF_Maxsize(s));
02324 }
02325 if (SP_baseST != NULL)
02326 fprintf(TFile, "%s \t\t%lld\t\t%lld\t%d\n",
02327 ST_name(SP_baseST), ST_ofst(SP_baseST),
02328 STB_size(SP_baseST), STB_align(SP_baseST));
02329 if (FP_baseST != NULL)
02330 fprintf(TFile, "%s \t\t%lld\t\t%lld\t%d\n",
02331 ST_name(FP_baseST), ST_ofst(FP_baseST),
02332 STB_size(FP_baseST), STB_align(FP_baseST));
02333 }
02334
02335 #ifdef PV394813
02336
02337 static void
02338 Allocate_All_INITV (INITV *inv1)
02339 {
02340 INITV *inv;
02341 if (inv1 == NULL) return;
02342 FOREACH_INITV(inv1, inv) {
02343 if ( INITV_kind(inv) == INITVKIND_SYMOFF) {
02344
02345 Allocate_Object(INITV_st(inv));
02346 }
02347 else if (INITV_kind(inv) == INITVKIND_BLOCK) {
02348
02349 Allocate_All_INITV (INITV_blk(inv));
02350 }
02351 }
02352 }
02353 #endif
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363
02364
02365 struct finalize_inito
02366 {
02367 void operator() (UINT32, const INITO* inito) const {
02368 ST* st = INITO_st (*inito);
02369 if (Has_No_Base_Block(st))
02370 Allocate_Object(st);
02371 #ifdef PV394813
02372 Allocate_All_INITV (INITO_val(*inito));
02373 #endif
02374 }
02375 };
02376
02377 INT64 Finalize_Stack_Frame (void)
02378 {
02379 INT64 Frame_Size;
02380 ST *st;
02381 INT i;
02382
02383 Set_Error_Phase("Data Layout");
02384 Clear_Vararg_Symbols();
02385
02386 For_all (Inito_Table, CURRENT_SYMTAB, finalize_inito());
02387
02388
02389
02390 if (PU_has_nested(Get_Current_PU())) {
02391 FOREACH_SYMBOL (CURRENT_SYMTAB, st, i) {
02392 if (ST_class(st) == CLASS_VAR && ST_has_nested_ref(st)) {
02393 Allocate_Object(st);
02394 }
02395 }
02396 }
02397
02398 switch ( Current_PU_Stack_Model ) {
02399 case SMODEL_SMALL:
02400
02401
02402 if (SEG_SIZE(SFSEG_UPFORMAL) == 0
02403 && ST_is_not_used(SF_Block(SFSEG_FORMAL)) )
02404 {
02405 if (Trace_Frame) fprintf(TFile, "<lay> formals not used\n");
02406 }
02407 else {
02408 MERGE_SEGMENT(SP_Sym, SFSEG_FORMAL, Max_Small_Frame_Offset);
02409 }
02410 Frame_Size = STB_size(SP_Sym);
02411 Set_ST_base(SF_Block(SFSEG_UPFORMAL), SP_Sym);
02412 Assign_Offset(SF_Block(SFSEG_UPFORMAL), SP_Sym,
02413 (Frame_Has_Calls ? Stack_Offset_Adjustment : 0), 0);
02414 #ifdef TARG_X8664
02415 {
02416 int push_pop_int_saved_regs = (*Push_Pop_Int_Saved_Regs_p)();
02417 if (push_pop_int_saved_regs & 1)
02418 push_pop_int_saved_regs++;
02419 Set_ST_ofst(SF_Block(SFSEG_UPFORMAL), ST_ofst(SF_Block(SFSEG_UPFORMAL)) +
02420 push_pop_int_saved_regs * MTYPE_byte_size(Pointer_Mtype));
02421 }
02422 #endif
02423 break;
02424
02425 case SMODEL_LARGE:
02426 Frame_Size = STB_size(SP_Sym) + STB_size(FP_Sym);
02427 break;
02428
02429 case SMODEL_DYNAMIC:
02430 Frame_Size = STB_size(SP_Sym) + STB_size(FP_Sym);
02431 break;
02432
02433 default:
02434 FmtAssert ( TRUE,
02435 ("UNDEFINED Stack Model in Finalize_Stack_Frame" ));
02436 }
02437
02438 Frame_Size = ROUNDUP(Frame_Size, stack_align);
02439 #ifdef TARG_X8664 // this is needed to maintain 16 bytes gap that contains
02440
02441 if (Current_PU_Stack_Model == SMODEL_SMALL && PUSH_FRAME_POINTER_ON_STACK) {
02442 Frame_Size += MTYPE_byte_size(Pointer_Mtype);
02443 if ((*Push_Pop_Int_Saved_Regs_p)() & 1)
02444 Frame_Size += MTYPE_byte_size(Pointer_Mtype);
02445 }
02446 #endif
02447
02448
02449
02450
02451
02452 if (!Frame_Has_Calls) {
02453 Frame_Size = MAX(0, Frame_Size - Stack_Offset_Adjustment);
02454 }
02455
02456 #if defined(BUILD_OS_DARWIN)
02457
02458
02459
02460
02461
02462
02463
02464 if(! Is_Target_64bit() ) {
02465 int excess = MTYPE_byte_size(Pointer_Mtype) *
02466 ((Current_PU_Stack_Model == SMODEL_DYNAMIC) ?
02467 2 :
02468 1);
02469 int mod = (Frame_Size + excess) % 16;
02470 if (mod) {
02471 excess = 16 - mod;
02472 Frame_Size += excess;
02473 ST *upformal = SF_Block(SFSEG_UPFORMAL);
02474 if (Current_PU_Stack_Model == SMODEL_SMALL) {
02475 Set_ST_ofst(upformal, ST_ofst(upformal) + excess);
02476 }
02477 }
02478 }
02479 #endif
02480
02481 if ( Trace_Frame ) {
02482 Trace_Stack_Segments ( "Finalize_Stack_Frame", SP_Sym, FP_Sym);
02483 fprintf(TFile, "<lay> final frame_size = %lld\n", Frame_Size);
02484 }
02485 if (Current_PU_Stack_Model == SMODEL_SMALL
02486 && ((Frame_Size + STB_size(SF_Block(SFSEG_UPFORMAL)))
02487 > Max_Small_Frame_Offset))
02488 {
02489 DevWarn("upformals overflowed small stack frame; will try recompiling with -TENV:large_stack");
02490 Early_Terminate(RC_OVERFLOW_ERROR);
02491 }
02492 if (Current_PU_Stack_Model == SMODEL_LARGE && Frame_Size < Max_Small_Frame_Offset)
02493 if (Trace_Frame) fprintf(TFile, "<lay> stack-model underflowed\n");
02494
02495 {
02496
02497 #ifndef __MINGW32__
02498 #if defined(linux) || defined(__CYGWIN__) || defined(__APPLE__) || defined(BUILD_OS_DARWIN)
02499 struct rlimit rlp;
02500 getrlimit(RLIMIT_STACK, &rlp);
02501 #else
02502 struct rlimit64 rlp;
02503 getrlimit64 (RLIMIT_STACK, &rlp);
02504 #endif
02505 #endif
02506
02507 #ifndef KEY // Redhat 8.0 will have unlimited stack size
02508 if (Frame_Size > rlp.rlim_cur)
02509 ErrMsg (EC_LAY_stack_limit, Frame_Size, (INT64) rlp.rlim_cur);
02510 #endif
02511 }
02512 return Frame_Size;
02513 }
02514
02515
02516
02517
02518
02519
02520
02521
02522
02523
02524 void
02525 Allocate_Temp_To_Memory ( ST *st )
02526 {
02527 Is_True(ST_sclass(st) == SCLASS_AUTO, ("Allocate_Temp_To_Memory expect stack var"));
02528 Set_ST_is_temp_var(st);
02529 Process_Stack_Variable ( st );
02530 #ifdef TARG_X8664
02531 (*CG_Set_Is_Stack_Used_p)();
02532 #endif
02533 }
02534
02535
02536
02537
02538
02539
02540
02541
02542
02543 static BOOL
02544 Is_String_Literal (ST *st)
02545 {
02546 if (ST_class(st) == CLASS_CONST && TCON_ty(STC_val(st)) == MTYPE_STR) {
02547 return TRUE;
02548 }
02549
02550 else if (ST_class(st) == CLASS_VAR && ST_is_const_var(st)
02551 && ST_is_initialized(st)
02552 && TY_kind(ST_type(st)) == KIND_ARRAY
02553 && TY_mtype(TY_AR_etype(ST_type(st))) == MTYPE_U1 )
02554 {
02555 return TRUE;
02556 }
02557 return FALSE;
02558 }
02559
02560
02561
02562
02563
02564
02565
02566
02567
02568
02569
02570
02571 static SECTION_IDX
02572 Shorten_Section ( ST *st, SECTION_IDX sec )
02573 {
02574 INT64 size;
02575 SECTION_IDX newsec;
02576 BOOL is_root_block = Is_Allocatable_Root_Block(st);
02577
02578 if (! is_root_block && ST_class(st) == CLASS_BLOCK) return sec;
02579
02580
02581
02582
02583 if ((Gen_PIC_Shared || Gen_PIC_Call_Shared) && ST_is_preemptible(st)
02584 && ! (ST_class(st) == CLASS_VAR && ST_force_gprel(st)) )
02585 {
02586 return sec;
02587 }
02588
02589 newsec = Corresponding_Short_Section (sec);
02590 if (newsec == sec) return sec;
02591
02592 #ifdef TARG_X8664
02593
02594
02595
02596 if( !SEC_is_gprel( newsec ) ){
02597 return sec;
02598 }
02599 #endif
02600
02601 size = ST_size(st);
02602
02603 if (size == 0) return sec;
02604
02605 if (ST_class(st) == CLASS_VAR && ST_not_gprel(st))
02606 return sec;
02607
02608 if (size > Max_Sdata_Elt_Size) {
02609
02610
02611
02612 if (ST_class(st) != CLASS_VAR)
02613 return sec;
02614
02615 else if (!ST_gprel(st) && !ST_force_gprel(st))
02616 return sec;
02617 }
02618
02619 if (Strings_Not_Gprelative && Is_String_Literal(st)) {
02620
02621 return sec;
02622 }
02623
02624 if ((ST_class(st) == CLASS_VAR || ST_class(st) == CLASS_CONST) && !ST_gprel(st))
02625 {
02626
02627
02628
02629 size = MAX(size, Adjusted_Alignment(st));
02630 if (size <= Gspace_Available) {
02631 Gspace_Available -= size;
02632 #if 0
02633 if (Trace_Frame) fprintf(TFile, "<lay> use Gspace for %s (size %d, align %d)\n", ST_NAME(st), TY_size(ST_type(st)), Adjusted_Alignment(st));
02634 #endif
02635 }
02636 else {
02637 if (Trace_Frame) fprintf(TFile, "<lay> not enough Gspace, so didn't assign %s to gprel section\n", ST_NAME(st));
02638 return sec;
02639 }
02640 }
02641 #if 0
02642 else {
02643 if (Trace_Frame) fprintf(TFile, "<lay> didn't check Gspace for %s\n", ST_NAME(st));
02644 }
02645 #endif
02646
02647 if (sec == _SEC_RDATA && ST_class(st) == CLASS_CONST) {
02648
02649
02650
02651 TCON tcon = STC_val(st);
02652 switch (TCON_ty (tcon)) {
02653 case MTYPE_F4:
02654 case MTYPE_I4:
02655 case MTYPE_U4:
02656 newsec = _SEC_LIT4;
02657 break;
02658 case MTYPE_F8:
02659 case MTYPE_I8:
02660 case MTYPE_U8:
02661 newsec = _SEC_LIT8;
02662 break;
02663 #if defined(TARG_IA64)
02664 case MTYPE_F10:
02665 case MTYPE_C10:
02666 #endif
02667 case MTYPE_FQ:
02668 newsec = _SEC_LIT16;
02669 break;
02670 }
02671 }
02672 Set_ST_gprel(st);
02673 return newsec;
02674 }
02675
02676
02677
02678
02679
02680
02681
02682
02683
02684
02685
02686
02687
02688
02689
02690
02691
02692 static void
02693 Allocate_Object_To_Section (ST *st, SECTION_IDX sec, UINT align)
02694 {
02695 ST *block;
02696 INT64 max_size;
02697
02698
02699 Is_True( IS_POW2(align), ("Alignment %d must be power of 2",align));
02700
02701 block = Get_Section_ST (sec, align, SCLASS_UNKNOWN );
02702 max_size = SEC_max_sec_size(sec);
02703 if ( Trace_Frame ) {
02704 fprintf(TFile, "Allocating %s to %s", ST_name(st), ST_name(block));
02705 }
02706 ST_Block_Merge (block, st, 0, 0, max_size);
02707 }
02708
02709
02710
02711
02712
02713
02714
02715
02716
02717
02718
02719
02720
02721
02722 static void
02723 Assign_Object_To_Section( ST *st, SECTION_IDX sec, UINT align)
02724 {
02725 ST *block;
02726
02727
02728 Is_True( IS_POW2(align), ("Alignment %d must be power of 2",align));
02729
02730 block = Get_Section_ST(sec, align, ST_sclass (st));
02731 if ( Trace_Frame ) {
02732 fprintf ( TFile, "Assigning symbol %s to %s section \n",
02733 ST_name(st) ? ST_name(st) : "<null>", ST_name(block) );
02734 }
02735 Set_ST_base(st, block);
02736 }
02737
02738 static void
02739 Allocate_Label (ST *lab)
02740 {
02741 FmtAssert(ST_sclass(lab) == SCLASS_TEXT, ("non-text label?"));
02742
02743 Assign_Object_To_Section ( lab, _SEC_TEXT, 0 );
02744 }
02745
02746
02747 #ifdef TARG_SL
02748 inline SECTION_IDX
02749 Get_Vbuf_Section(const ST *st)
02750 {
02751 if( ST_in_v1buf(st))
02752 {
02753 return _SEC_VS1DATA;
02754 }
02755 else if(ST_in_v2buf(st)){
02756 return _SEC_VS2DATA;
02757 }
02758 else {
02759 return _SEC_VS4DATA;
02760 }
02761 }
02762
02763 typedef std::map<ST*, float> ST_FREQ_MAP;
02764 typedef ST_FREQ_MAP::iterator ST_FREQ_ITER;
02765
02766
02767 static void
02768 Walk_And_Collect_Heur_Based_Refs(WN *wn, ST_FREQ_MAP *st2f_map)
02769 {
02770 OPERATOR opr=WN_operator(wn);
02771 ST *st=NULL;
02772 switch (opr) {
02773 case OPR_LDID:
02774 case OPR_LDA:
02775 st=WN_st(wn);
02776 break;
02777 case OPR_STID:
02778 Walk_And_Collect_Heur_Based_Refs(WN_kid0(wn), st2f_map);
02779 st=WN_st(wn);
02780 break;
02781 case OPR_BLOCK:
02782 for(WN *kid=WN_first(wn); kid; kid=WN_next(kid))
02783 Walk_And_Collect_Heur_Based_Refs(kid, st2f_map);
02784 break;
02785 case OPR_FUNC_ENTRY:
02786 Walk_And_Collect_Heur_Based_Refs(WN_func_body(wn), st2f_map);
02787 break;
02788 default:
02789 for(INT i=0;i<WN_kid_count(wn); i++)
02790 Walk_And_Collect_Heur_Based_Refs(WN_kid(wn, i), st2f_map);
02791 break;
02792 }
02793
02794 if(st!=NULL && ST_sclass(st)==SCLASS_AUTO) {
02795 if((*st2f_map).find(st)==st2f_map->end())
02796 (*st2f_map)[st]=1;
02797 else
02798 (*st2f_map)[st]=(*st2f_map)[st]+1;
02799 }
02800 return;
02801 }
02802
02803
02804
02805 static void
02806 Walk_And_Collect_Fb_Based_Refs(WN *wn, float& cur_freq, ST_FREQ_MAP *st2f_map)
02807 {
02808 ST *st=NULL;
02809 OPERATOR opr=WN_operator(wn);
02810 switch (opr) {
02811 case OPR_FUNC_ENTRY:
02812 {
02813 FB_FREQ freq_default = Cur_PU_Feedback->Query( wn, FB_EDGE_ENTRY_OUTGOING );
02814 cur_freq=freq_default.Value();
02815 Walk_And_Collect_Fb_Based_Refs(WN_func_body(wn), cur_freq, st2f_map);
02816 }
02817 break;
02818 case OPR_BLOCK:
02819 {
02820 for(WN* kid=WN_first(wn);kid;kid=WN_next(kid))
02821 Walk_And_Collect_Fb_Based_Refs(kid, cur_freq, st2f_map);
02822 }
02823 break;
02824 case OPR_DO_LOOP:
02825 {
02826 FB_FREQ freq_exit, freq_iterate;
02827 freq_exit = Cur_PU_Feedback->Query(wn, FB_EDGE_LOOP_EXIT);
02828 freq_iterate = Cur_PU_Feedback->Query( wn, FB_EDGE_LOOP_ITERATE );
02829 cur_freq=freq_iterate.Value();
02830 Walk_And_Collect_Fb_Based_Refs(WN_start(wn), cur_freq, st2f_map);
02831 cur_freq=freq_iterate.Value();
02832 Walk_And_Collect_Fb_Based_Refs(WN_do_body(wn), cur_freq, st2f_map);
02833 cur_freq=freq_iterate.Value();
02834 Walk_And_Collect_Fb_Based_Refs(WN_step(wn), cur_freq, st2f_map);
02835 cur_freq=freq_iterate.Value()+1;
02836 Walk_And_Collect_Fb_Based_Refs(WN_end(wn), cur_freq, st2f_map);
02837 cur_freq=freq_exit.Value();
02838 }
02839 break;
02840 case OPR_DO_WHILE:
02841 {
02842 FB_FREQ freq_positive, freq_out, freq_back;
02843 freq_positive = Cur_PU_Feedback->Query( wn, FB_EDGE_LOOP_POSITIVE );
02844 freq_out = Cur_PU_Feedback->Query( wn, FB_EDGE_LOOP_OUT );
02845 freq_back = Cur_PU_Feedback->Query( wn, FB_EDGE_LOOP_BACK );
02846 float iterate = freq_positive.Value()+freq_back.Value();
02847 cur_freq=freq_positive.Value()+freq_back.Value();
02848 Walk_And_Collect_Fb_Based_Refs(WN_while_body(wn), cur_freq, st2f_map);
02849 cur_freq=freq_positive.Value()+freq_back.Value();
02850 Walk_And_Collect_Fb_Based_Refs(WN_while_test(wn), cur_freq, st2f_map);
02851 cur_freq=freq_out.Value();
02852 }
02853 break;
02854 case OPR_WHILE_DO:
02855 {
02856 FB_FREQ freq_exit, freq_iterate;
02857 freq_exit = Cur_PU_Feedback->Query( wn, FB_EDGE_LOOP_EXIT );
02858 freq_iterate = Cur_PU_Feedback->Query( wn, FB_EDGE_LOOP_ITERATE );
02859 cur_freq=freq_iterate.Value();
02860 Walk_And_Collect_Fb_Based_Refs(WN_while_body(wn), cur_freq, st2f_map);
02861 cur_freq=freq_iterate.Value();
02862 Walk_And_Collect_Fb_Based_Refs(WN_while_test(wn), cur_freq, st2f_map);
02863 cur_freq=freq_exit.Value();
02864 }
02865 break;
02866 case OPR_IF:
02867 {
02868 FB_FREQ freq_then, freq_else;
02869 freq_then = Cur_PU_Feedback->Query( wn, FB_EDGE_BRANCH_TAKEN );
02870 freq_else = Cur_PU_Feedback->Query( wn, FB_EDGE_BRANCH_NOT_TAKEN );
02871 cur_freq=freq_then.Value()+freq_else.Value();
02872 Walk_And_Collect_Fb_Based_Refs(WN_if_test(wn), cur_freq, st2f_map);
02873 float out_freq_then=freq_then.Value();
02874 Walk_And_Collect_Fb_Based_Refs(WN_then(wn), out_freq_then, st2f_map);
02875 float out_freq_else=freq_else.Value();
02876 Walk_And_Collect_Fb_Based_Refs(WN_else(wn), out_freq_else, st2f_map);
02877 cur_freq=out_freq_then + out_freq_else;
02878 }
02879 break;
02880 case OPR_GOTO:
02881 {
02882 cur_freq=0;
02883 }
02884 break;
02885 case OPR_SWITCH:
02886 case OPR_COMPGOTO:
02887 case OPR_XGOTO:
02888 {
02889 Walk_And_Collect_Fb_Based_Refs(WN_kid0(wn), cur_freq, st2f_map);
02890 cur_freq=0;
02891 }
02892 break;
02893 case OPR_TRUEBR:
02894 case OPR_FALSEBR:
02895 {
02896 FB_FREQ freq_branch, freq_default;
02897 freq_branch = Cur_PU_Feedback->Query( wn, FB_EDGE_BRANCH_TAKEN );
02898 freq_default = Cur_PU_Feedback->Query( wn, FB_EDGE_BRANCH_NOT_TAKEN );
02899 cur_freq=freq_branch.Value()+freq_default.Value();
02900 Walk_And_Collect_Fb_Based_Refs(WN_kid0(wn), cur_freq, st2f_map);
02901 cur_freq=freq_default.Value();
02902 }
02903 break;
02904 case OPR_RETURN:
02905 {
02906 cur_freq=0;
02907 }
02908 break;
02909 case OPR_RETURN_VAL:
02910 {
02911 Walk_And_Collect_Fb_Based_Refs(WN_kid0(wn), cur_freq, st2f_map);
02912 cur_freq=0;
02913 }
02914 break;
02915 case OPR_LABEL:
02916 {
02917 FB_FREQ freq_l = Cur_PU_Feedback->Query( wn, FB_EDGE_INCOMING );
02918 cur_freq=freq_l.Value();
02919 }
02920 break;
02921 case OPR_CALL:
02922 case OPR_ICALL:
02923 case OPR_VFCALL:
02924 case OPR_PICCALL:
02925 case OPR_INTRINSIC_CALL:
02926 case OPR_IO:
02927 {
02928 if(Cur_PU_Feedback->Same_in_out(wn)) {
02929 FB_FREQ freq_in = Cur_PU_Feedback->Query( wn, FB_EDGE_CALL_INOUTSAME );
02930 cur_freq=freq_in.Value();
02931 for ( INT t = 0; t < WN_kid_count(wn); ++t ) {
02932 Walk_And_Collect_Fb_Based_Refs(WN_kid(wn, t), cur_freq, st2f_map);
02933 }
02934 cur_freq=freq_in.Value();
02935 } else {
02936 FB_FREQ freq_entry = Cur_PU_Feedback->Query( wn, FB_EDGE_CALL_INCOMING );
02937 FB_FREQ freq_exit = Cur_PU_Feedback->Query( wn, FB_EDGE_CALL_OUTGOING );
02938 cur_freq=freq_entry.Value();
02939 for ( INT t = 0; t < WN_kid_count(wn); ++t )
02940 Walk_And_Collect_Fb_Based_Refs(WN_kid(wn, t), cur_freq, st2f_map);
02941 cur_freq=freq_exit.Value();
02942 }
02943 }
02944 break;
02945 case OPR_REGION:
02946 {
02947 FB_FREQ freq_entry = Cur_PU_Feedback->Query( wn, FB_EDGE_CALL_INCOMING );
02948 FB_FREQ freq_exit = Cur_PU_Feedback->Query( wn, FB_EDGE_CALL_OUTGOING );
02949 cur_freq=freq_entry.Value();
02950 Walk_And_Collect_Fb_Based_Refs(WN_region_body(wn), cur_freq, st2f_map);
02951 cur_freq=freq_exit.Value();
02952 }
02953 break;
02954 case OPR_LDA:
02955 case OPR_LDID:
02956 st=WN_st(wn);
02957 break;
02958 case OPR_STID:
02959 {
02960 Walk_And_Collect_Fb_Based_Refs(WN_kid0(wn), cur_freq, st2f_map);
02961 st=WN_st(wn);
02962 }
02963 break;
02964 default:
02965 for(int i=0;i<WN_kid_count(wn);i++)
02966 Walk_And_Collect_Fb_Based_Refs(WN_kid(wn, i), cur_freq, st2f_map);
02967 break;
02968 }
02969
02970 if(st!=NULL && ST_sclass(st)==SCLASS_AUTO) {
02971 if((*st2f_map).find(st)==st2f_map->end())
02972 (*st2f_map)[st]=cur_freq;
02973 else
02974 (*st2f_map)[st]=(*st2f_map)[st]+cur_freq;
02975 }
02976
02977 return;
02978 }
02979
02980
02981
02982 class Sort_Vst_By_Freq_Size{
02983 private:
02984 ST_FREQ_MAP& st2f;
02985 public:
02986 Sort_Vst_By_Freq_Size(ST_FREQ_MAP& st2f_map) :
02987 st2f(st2f_map)
02988 {}
02989 bool operator()(ST *st1, ST *st2) {
02990 return st2f[st1]/float(ST_size(st1))>st2f[st2]/float(ST_size(st2));
02991 }
02992 };
02993
02994 extern void
02995 Pre_Allocate_Objects(WN* wn)
02996 {
02997 ST_FREQ_MAP st2f_map;
02998
02999 if(Cur_PU_Feedback) {
03000 float freq=0;
03001 Walk_And_Collect_Fb_Based_Refs(wn, freq, &st2f_map);
03002 }
03003 else
03004 Walk_And_Collect_Heur_Based_Refs(wn, &st2f_map);
03005
03006
03007 vector<ST *> sorted_vst;
03008 for(ST_FREQ_ITER itr=st2f_map.begin(); itr!=st2f_map.end();itr++)
03009 sorted_vst.push_back(itr->first);
03010
03011 sort(sorted_vst.begin(), sorted_vst.end(), Sort_Vst_By_Freq_Size(st2f_map));
03012
03013 if(Trace_Frame) {
03014 fprintf(TFile, "Ordered objects:\n");
03015 for(vector<ST*>::iterator itr=sorted_vst.begin(); itr!=sorted_vst.end();itr++) {
03016 ST *st=*itr;
03017 fprintf(TFile, "%s: size=%lld, freq=%f\n", ST_name(st), ST_size(st), st2f_map[st]);
03018 }
03019 }
03020
03021
03022 for(vector<ST*>::iterator itr=sorted_vst.begin(); itr!=sorted_vst.end();itr++) {
03023 ST *st=*itr;
03024 Allocate_Object(st);
03025 }
03026 return;
03027 }
03028
03029 #endif
03030
03031
03032
03033
03034
03035
03036
03037
03038
03039
03040
03041
03042
03043
03044 BOOL
03045 ST_has_Predefined_Named_Section(ST *st, SECTION_IDX &sec_idx) {
03046
03047 for (sec_idx = _SEC_UNKNOWN; sec_idx <= _SEC_DISTR_ARRAY; sec_idx ++) {
03048 if (SEC_name(sec_idx) &&
03049 !strcmp(Index_To_Str(Find_Section_Name_For_ST(st)), SEC_name(sec_idx)))
03050 return TRUE;
03051 }
03052
03053 return FALSE;
03054 }
03055
03056
03057
03058
03059
03060
03061
03062
03063
03064
03065
03066
03067 static void
03068 Allocate_Object_To_Predefined_Named_Section(ST *st, SECTION_IDX sec_idx) {
03069 Clear_ST_has_named_section(st);
03070 Set_ST_base_idx(st,ST_st_idx(st));
03071 Set_ST_ofst(st,0);
03072
03073
03074
03075
03076
03077
03078 if (ST_storage_class (*st) == SCLASS_UGLOBAL) {
03079 DevWarn("change bss symbol to be initialized to 0");
03080 Set_ST_sclass(st, SCLASS_DGLOBAL);
03081 Set_ST_is_initialized(st);
03082 INITO_IDX ino = New_INITO(st);
03083 INITV_IDX inv = New_INITV();
03084 INITV_Init_Pad (inv, ST_size(st));
03085 Set_INITO_val(ino, inv);
03086 Clear_ST_init_value_zero(st);
03087 }
03088
03089
03090 Allocate_Object_To_Section ( st, sec_idx, Adjusted_Alignment(st));
03091 return;
03092 }
03093
03094
03095
03096
03097
03098
03099
03100
03101
03102
03103
03104
03105
03106
03107
03108
03109
03110 extern void
03111 Allocate_Object ( ST *st )
03112 {
03113 SECTION_IDX sec;
03114 ST *base_st = st;
03115
03116 if ( ST_sclass(st) == SCLASS_FORMAL ) {
03117
03118 Clear_ST_is_not_used(SF_Block(SFSEG_FORMAL));
03119 }
03120
03121 if (Is_Allocated(st)) {
03122
03123
03124
03125 if (!ST_has_named_section(st))
03126 return;
03127 else if (!ST_has_Predefined_Named_Section(st, sec))
03128 return;
03129 }
03130
03131 if (ST_is_not_used(st)) return;
03132
03133 if (ST_has_named_section(st)) {
03134
03135 if (ST_has_Predefined_Named_Section(st, sec))
03136
03137 Allocate_Object_To_Predefined_Named_Section(st, sec);
03138 else {
03139 STR_IDX name = Find_Section_Name_For_ST (st);
03140 Assign_ST_To_Named_Section (st, name);
03141 }
03142 return;
03143 }
03144 if (Has_Base_Block(st)) {
03145 base_st = Base_Symbol(st);
03146 }
03147
03148 if (ST_sclass(st) != ST_sclass(base_st))
03149 DevWarn("st sclass %d different from base sclass %d",
03150 ST_sclass(st), ST_sclass(base_st));
03151
03152 switch ( ST_sclass(base_st) ) {
03153 case SCLASS_UNKNOWN :
03154 break;
03155 case SCLASS_AUTO:
03156 Process_Stack_Variable(base_st);
03157 break;
03158 case SCLASS_FORMAL:
03159 case SCLASS_FORMAL_REF:
03160
03161
03162
03163 break;
03164 case SCLASS_PSTATIC :
03165 case SCLASS_FSTATIC :
03166 if (ST_is_thread_private(st)) {
03167 if (ST_is_initialized(st) && !ST_init_value_zero (st))
03168 #if defined(KEY) && !defined(TARG_SL)
03169 sec = _SEC_LDATA_MIPS_LOCAL;
03170 #else
03171 sec = _SEC_LDATA;
03172 #endif
03173 #ifdef TARG_SL
03174 else if(ST_in_v1buf(st))
03175 sec = _SEC_VS1DATA;
03176 else if(ST_in_v2buf(st))
03177 sec = _SEC_VS2DATA;
03178 else if(ST_in_v4buf(st))
03179 sec = _SEC_VS4DATA;
03180 #endif
03181
03182 else
03183 #ifdef KEY
03184 sec = _SEC_BSS;
03185 #else
03186 sec = _SEC_LBSS;
03187 #endif // KEY
03188 }
03189 #ifdef KEY
03190 else if (ST_is_thread_local(st)) {
03191 if (ST_is_initialized(st) && !ST_init_value_zero(st))
03192 sec = _SEC_LDATA;
03193 else
03194 sec = _SEC_LBSS;
03195 }
03196 #endif
03197 else if (ST_is_initialized(st) && !ST_init_value_zero (st))
03198 #ifdef TARG_X8664
03199 {
03200 if (ST_is_constant(st))
03201
03202 if (Gen_PIC_Shared &&
03203 !ST_NO_LINKAGE(st) &&
03204 ST_sym_class(st) != CLASS_CONST)
03205 sec = _SEC_DATA_REL_RO;
03206 else
03207 sec = _SEC_RDATA;
03208 else
03209 sec = _SEC_DATA;
03210 }
03211 #elif defined(TARG_SL)
03212 sec = _SEC_DATA;
03213 #else
03214 sec = (ST_is_constant(st) ? _SEC_RDATA : _SEC_DATA);
03215 #endif
03216
03217 else
03218 #ifdef TARG_SL
03219 if (ST_in_vbuf(st)) {
03220
03221
03222
03223 sec = Get_Vbuf_Section(st);
03224 }
03225 else if(ST_in_sbuf(st)){
03226 sec = _SEC_SSDATA;
03227 }
03228 else
03229 #endif
03230 sec = _SEC_BSS;
03231 sec = Shorten_Section ( st, sec );
03232 Allocate_Object_To_Section ( base_st, sec, Adjusted_Alignment (base_st) );
03233 break;
03234 case SCLASS_REG:
03235 break;
03236 case SCLASS_CPLINIT:
03237 sec = _SEC_CPLINIT;
03238 Allocate_Object_To_Section ( base_st, sec, Adjusted_Alignment(base_st));
03239 break;
03240 case SCLASS_EH_REGION:
03241 sec = _SEC_EH_REGION;
03242 Allocate_Object_To_Section ( base_st, sec, Adjusted_Alignment(base_st));
03243 break;
03244 case SCLASS_EH_REGION_SUPP:
03245 sec = _SEC_EH_REGION_SUPP;
03246 Allocate_Object_To_Section ( base_st, sec, Adjusted_Alignment(base_st));
03247 break;
03248 case SCLASS_DISTR_ARRAY:
03249 sec = _SEC_DISTR_ARRAY;
03250 Allocate_Object_To_Section ( base_st, sec, Adjusted_Alignment(base_st));
03251 break;
03252 case SCLASS_THREAD_PRIVATE_FUNCS:
03253 sec = _SEC_THREAD_PRIVATE_FUNCS;
03254 Allocate_Object_To_Section ( base_st, sec, Adjusted_Alignment(base_st));
03255 break;
03256 case SCLASS_COMMON:
03257
03258
03259
03260
03261
03262
03263 if (ST_type(st) != (TY_IDX) NULL)
03264 {
03265 TY_IDX type = ST_type(st);
03266
03267 Set_ST_type(st,
03268 Make_Align_Type(type, Adjusted_Alignment(st)) );
03269 }
03270 case SCLASS_EXTERN:
03271
03272
03273
03274
03275 if ( ! FILE_INFO_ipa (File_info) && !ST_is_weak_symbol(st)) {
03276 sec = Shorten_Section ( st, _SEC_DATA );
03277 if (sec != _SEC_DATA) Set_ST_gprel (st);
03278 }
03279 break;
03280 case SCLASS_UGLOBAL :
03281 if (ST_is_thread_private(st)) {
03282 #ifdef KEY
03283 sec = _SEC_BSS;
03284 #else
03285 sec = _SEC_LBSS;
03286 #endif // KEY
03287 }
03288 #ifdef KEY
03289 else if (ST_is_thread_local(st)) {
03290 sec = _SEC_LBSS;
03291 }
03292 #endif
03293 else sec = _SEC_BSS;
03294 sec = Shorten_Section ( st, sec );
03295 Allocate_Object_To_Section ( base_st, sec, Adjusted_Alignment(base_st));
03296 break;
03297 case SCLASS_DGLOBAL :
03298 if (ST_is_thread_private(st))
03299 #if defined(KEY) && !defined(TARG_SL)
03300 sec = _SEC_LDATA_MIPS_LOCAL;
03301 #else
03302 sec = _SEC_LDATA;
03303 #endif
03304 #ifdef KEY
03305 else if (ST_is_thread_local(st)) sec = _SEC_LDATA;
03306 #endif
03307 else if (ST_is_constant(st)) {
03308 #ifdef TARG_X8664
03309 if (Gen_PIC_Shared)
03310 sec = _SEC_DATA_REL_RO;
03311 else
03312 #endif
03313 sec = _SEC_RDATA;
03314 }
03315
03316 #ifdef TARG_SL
03317 else if (ST_in_vbuf(st)) {
03318 sec = Get_Vbuf_Section(st);
03319 }
03320 else if(ST_in_sbuf(st)){
03321 sec = _SEC_SSDATA;
03322 }
03323 #endif
03324 else sec = _SEC_DATA;
03325 sec = Shorten_Section ( st, sec );
03326 Allocate_Object_To_Section ( base_st, sec, Adjusted_Alignment(base_st));
03327 break;
03328 case SCLASS_TEXT :
03329
03330
03331 sec = _SEC_TEXT;
03332 Assign_Object_To_Section ( base_st, sec, 0 );
03333 break;
03334 default:
03335 Is_True ( (FALSE)
03336 , ("Allocate_Object: Invalid SCLASS %d",ST_sclass(st)) );
03337 break;
03338 }
03339
03340 }
03341
03342
03343
03344
03345
03346
03347
03348
03349
03350
03351
03352
03353 extern void
03354 Allocate_File_Statics (void)
03355 {
03356 ST *st;
03357 INT i;
03358 Trace_Frame = Get_Trace(TP_DATALAYOUT, 1);
03359
03360
03361 if ( ST_ATTR_Table_Size (GLOBAL_SYMTAB)) {
03362 For_all (St_Attr_Table, GLOBAL_SYMTAB,
03363 Assign_Section_Names());
03364 }
03365
03366
03367
03368 slist<ST*> common_list;
03369 slist<ST*>::iterator cit;
03370 FOREACH_SYMBOL (GLOBAL_SYMTAB,st,i) {
03371 if (ST_sclass(st) != SCLASS_COMMON) continue;
03372 if (Has_Base_Block(st)) continue;
03373
03374 for (cit = common_list.begin(); cit != common_list.end(); ++cit)
03375 {
03376 if (ST_name_idx(*cit) == ST_name_idx(st)
03377 && ST_export(*cit) == ST_export(st))
03378 {
03379
03380
03381
03382 if (TY_size(ST_type(st)) > TY_size(ST_type(*cit))) {
03383 Set_ST_base(*cit, st);
03384 DevWarn("found commons with same name %s; merge together %d->%d", ST_name(st), ST_index(*cit), ST_index(st));
03385
03386
03387 *cit = st;
03388 }
03389 else {
03390 Set_ST_base(st, *cit);
03391 DevWarn("found commons with same name %s; merge together %d->%d", ST_name(st), ST_index(st), ST_index(*cit));
03392 }
03393 break;
03394 }
03395 }
03396 if (cit == common_list.end()) {
03397 common_list.push_front(st);
03398 }
03399 }
03400
03401 FOREACH_SYMBOL (GLOBAL_SYMTAB,st,i) {
03402 if (ST_sclass(st) == SCLASS_REG) continue;
03403
03404
03405 if (ST_class(st) == CLASS_CONST && !Emit_Global_Data) continue;
03406
03407
03408
03409
03410 if (ST_class(st) == CLASS_VAR &&
03411 (ST_is_reshaped(st) || ST_is_fill_align(st)))
03412 continue;
03413 Allocate_Object(st);
03414 }
03415 }
03416
03417
03418
03419 BOOL
03420 Uses_Small_Offset (ST *st, WN_OFFSET wn_ofst)
03421 {
03422 switch(ST_sclass(st)) {
03423
03424 case SCLASS_AUTO:
03425 switch (Current_PU_Stack_Model) {
03426 case SMODEL_SMALL:
03427 return TRUE;
03428 case SMODEL_LARGE:
03429
03430
03431
03432 return (ST_size(st) < Large_Object_Bytes);
03433 case SMODEL_DYNAMIC:
03434
03435
03436 return FALSE;
03437 }
03438
03439 case SCLASS_FORMAL:
03440 return (Current_PU_Stack_Model != SMODEL_DYNAMIC);
03441 default:
03442 switch (ST_class(st)) {
03443 case CLASS_VAR:
03444 case CLASS_BLOCK:
03445 return ST_gprel(st);
03446 case CLASS_CONST:
03447
03448
03449 return TRUE;
03450 }
03451 return FALSE;
03452 }
03453 }
03454
03455
03456
03457
03458 static ST*
03459 Create_Global_Array_ST (TYPE_ID emtype, INT num, char *name)
03460 {
03461
03462 TY_IDX arr_ty = Make_Array_Type (emtype, 1, num);
03463 ST* st = New_ST ();
03464 ST_Init (st, Save_Str(name), CLASS_VAR, SCLASS_UGLOBAL, EXPORT_LOCAL, arr_ty);
03465 Set_ST_pt_to_unique_mem (st);
03466 return st;
03467 }
03468
03469
03470
03471
03472
03473 struct pad_global_arrays
03474 {
03475 inline void operator() (UINT32, ST* st) const {
03476 if ((ST_sclass(st) == SCLASS_UGLOBAL) && (ST_class(st) == CLASS_VAR)) {
03477 const TY_IDX ty = ST_type(st);
03478
03479 if (!ST_is_not_used(st) &&
03480 (TY_size (ty) > 0) &&
03481 !ST_is_fill_align(st) &&
03482 !ST_has_nested_ref(st) &&
03483 (TY_kind(ty) == KIND_ARRAY) &&
03484 (!ST_is_reshaped(st))) {
03485
03486 INT size = TY_size (ty);
03487 INT set_size = 256*1024;
03488 INT mod = size % set_size;
03489 INT pad_size=0;
03490 if ((size > 0.9*set_size) && (mod < set_size/20)) {
03491 pad_size = set_size/20 - mod;
03492 } else if ((size > 0.9*set_size) &&
03493 ((set_size - mod) < set_size/20)) {
03494 pad_size = set_size/20 + (set_size - mod);
03495 }
03496 size += pad_size;
03497 set_size = 16*1024;
03498 mod = size % set_size;
03499 if ((size > 0.9*set_size) && (mod < set_size/20)) {
03500 pad_size += set_size/20 - mod;
03501 } else if ((size > 0.9*set_size) &&
03502 ((set_size - mod) < set_size/20)) {
03503 pad_size += set_size/20 + (set_size - mod);
03504 }
03505 size += pad_size;
03506 if (pad_size) {
03507 static INT count;
03508 char name[64];
03509 sprintf (name, "global_pad_%d", count);
03510 count++;
03511 ST *pad_symbol = Create_Global_Array_ST (MTYPE_I1,size,name);
03512 St_Block_Union(st,pad_symbol);
03513 }
03514 }
03515 }
03516 }
03517 };
03518
03519 extern void
03520 Pad_Global_Arrays()
03521 {
03522 For_all (St_Table, GLOBAL_SYMTAB, pad_global_arrays ());
03523 }
03524
03525
03526 extern INT
03527 Stack_Offset_Adjustment_For_PU (void)
03528 {
03529 if (Frame_Has_Calls)
03530 return Stack_Offset_Adjustment;
03531 else
03532 return 0;
03533 }
03534
03535 extern void
03536 Set_Frame_Has_Calls(BOOL b)
03537 {
03538 Frame_Has_Calls = b;
03539 }
03540
03541 #ifdef TARG_X8664
03542 BOOL
03543 Stack_Frame_Has_Calls (void)
03544 {
03545 return Frame_Has_Calls;
03546 }
03547 #endif