00001 #define DEBUG
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 # ifdef VERBOSE
00014 # define IFVERBOSE(x) x
00015 # else
00016 # define IFVERBOSE(x)
00017 # endif
00018
00019 # include "parm.h"
00020 # include <stdio.h>
00021 # include "stree/ststructs.mh"
00022 # include "codeutil.h"
00023 # include "../pass4/sigs.h"
00024
00025 # define MAXOBJSZ 512
00026
00027 extern FILE * unparse_file;
00028
00029 NODE * Vcurrent_func;
00030 NODE * Vcurrent_ar;
00031
00032
00033 int Vstatic_level = -1;
00034 int Vnext_free;
00035
00036 int Vhigh_water;
00037
00038
00039
00040
00041 boolean Vextent_limited;
00042
00043
00044 boolean Vallocate_on_stack;
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 boolean Vcallcc;
00057
00058 extern boolean Nflag;
00059 extern boolean Vflag;
00060 extern boolean Gflag;
00061 extern boolean Rflag;
00062 extern boolean hflag;
00063
00064 extern long max_addr_regs;
00065
00066 extern long max_int_regs;
00067 long n_addr_regs = 0;
00068 long n_int_regs = 0;
00069
00070
00071
00072
00073
00074 extern int yynerrs;
00075
00076 int n_decls;
00077
00078
00079 struct blocks {
00080 struct blocks * bl_next;
00081 NODE * bl_block;
00082 } * Vcurrent_blocks = NIL;
00083
00084
00085 void Vfree_blocks()
00086 {
00087 struct blocks *p;
00088
00089 while (Vcurrent_blocks != NIL) {
00090 p = Vcurrent_blocks;
00091 Vcurrent_blocks = Vcurrent_blocks -> bl_next;
00092 free(p);
00093 }
00094 }
00095
00096
00097
00098
00099 void realloc_blocks(block)
00100 NODE * block;
00101 {
00102 struct blocks *p;
00103
00104
00105 for(p = Vcurrent_blocks; p != NIL; p = p -> bl_next) {
00106
00107
00108 if (p -> bl_block -> post_num < block -> post_num ) {
00109 switch (p -> bl_block -> kind) {
00110 case BLOCKDENOTATION:
00111 maplist(s, p -> bl_block -> bld_declaration_list, {
00112 if (s -> decl_special & VAR_NONTR_REF) {
00113 if (Vflag && (s -> decl_special & VAR_ON_STACK)) {
00114 printf("Parallel blocks: Undoing stack allocation of %s:%s\n",
00115 Vcurrent_func -> fc_code_label,
00116 getname(s -> decl_id -> id_str_table_index));
00117 }
00118 s -> decl_special &= ~VAR_ON_STACK;
00119 }
00120 });
00121 break;
00122 default:
00123 dbgmsg("realloc_blocks: bad list entry\n");
00124 }
00125 }
00126 }
00127 }
00128
00129
00130 void add_block(block)
00131 NODE * block;
00132 {
00133 struct blocks *p;
00134
00135 if (block -> kind == MODPRIMARY) {
00136 dbgmsg("add_block: MODPRIMARY in block list\n");
00137 return;
00138 }
00139 if (block -> kind == BLOCKDENOTATION
00140 && (block -> bld_declaration_list == NIL
00141 || is_empty(block -> bld_declaration_list))) {
00142
00143 return;
00144 }
00145
00146 p = (struct blocks *) malloc(sizeof (struct blocks));
00147 p -> bl_block = block;
00148 p -> bl_next = Vcurrent_blocks;
00149 Vcurrent_blocks = p;
00150 }
00151
00152 Vallocwalk(p)
00153 register NODE * p;
00154 {
00155 register NODE * v;
00156 int tp;
00157
00158 if (p == NIL) return;
00159
00160
00161 switch (p -> kind) {
00162 case DECLARATION:
00163 {
00164
00165
00166
00167 NODE * den = p -> decl_denotation;
00168 boolean no_ref = (p -> decl_signature -> kind
00169 == VARSIGNATURE
00170 && !(p -> decl_special & VAR_NONTR_REF));
00171 boolean allocate_in_ar =
00172 (Vallocate_on_stack || (no_ref && !Vcallcc))
00173 && den -> kind == APPLICATION
00174 && ((tp = special_tp(den -> ap_operator -> signature
00175 -> fsig_special))
00176 == STD_NEW
00177 || tp == PROD_NEW || tp == UNION_NEW
00178 || tp == PTR_NEW || tp == INIT_NEW );
00179 boolean allocate_in_reg =
00180 allocate_in_ar
00181 && (Rflag
00182 || ((tp == STD_NEW || tp == INIT_NEW) ?
00183 (n_int_regs < max_int_regs)
00184 : (n_addr_regs < max_addr_regs)))
00185 && !(p -> decl_special & (ID_IMPORTED
00186 | VAR_NONTR_REF))
00187 && (special_val(den -> ap_operator
00188 -> signature -> fsig_special)
00189 == 1
00190 || tp == PROD_NEW || tp == UNION_NEW);
00191
00192 if (hflag || allocate_in_reg) {
00193 allocate_in_ar = FALSE;
00194 }
00195 p -> level = Vstatic_level;
00196 if (allocate_in_reg) {
00197
00198
00199 extern int avail_loc;
00200
00201 if (Vflag) {
00202 printf("Allocating value of %s:%s to v. register\n",
00203 Vcurrent_func -> fc_code_label,
00204 getname(p -> decl_id -> id_str_table_index));
00205 }
00206 p -> displacement = avail_loc++;
00207 if (tp == STD_NEW) {
00208 p -> decl_special |= SIMPLE_VAR_IN_REG;
00209 n_int_regs++;
00210 } else if (tp == INIT_NEW) {
00211 p -> decl_special |= INIT_VAR_IN_REG;
00212 n_int_regs++;
00213 } else {
00214 p -> decl_special |= PTR_VAR_IN_REG;
00215 n_addr_regs++;
00216 }
00217 } else if (allocate_in_ar) {
00218
00219 if (Vflag) {
00220 printf("Allocating %s:%s directly in act. record\n",
00221 Vcurrent_func -> fc_code_label,
00222 getname(p -> decl_id -> id_str_table_index));
00223 }
00224 p -> displacement = Vnext_free;
00225 Vnext_free +=
00226 special_val(den -> ap_operator
00227 -> signature -> fsig_special);
00228 if (tp == STD_NEW) {
00229 p -> decl_special |= SIMPLE_VAR_ON_STACK;
00230 } else if (tp == INIT_NEW) {
00231 p -> decl_special |= INIT_VAR_ON_STACK;
00232 } else {
00233 p -> decl_special |= PTR_VAR_ON_STACK;
00234 }
00235 } else {
00236 if (Vextent_limited
00237 && den -> kind == APPLICATION
00238 && ((tp = special_tp(den -> ap_operator -> signature
00239 -> fsig_special))
00240 == ARRAY_STD_NEW
00241 || tp == ARRAY_PTR_NEW)) {
00242
00243 if (Vflag && Gflag) {
00244 printf("Allocating %s:%s contiguously\n",
00245 Vcurrent_func -> fc_code_label,
00246 getname(p -> decl_id -> id_str_table_index));
00247 }
00248 p -> decl_special |= ARRAY_CONTIG;
00249 }
00250 if (p -> decl_needed) {
00251
00252 if ((Rflag || (n_int_regs < max_int_regs)
00253 && n_decls < max_int_regs + max_addr_regs
00254 && !is_int_const(p -> decl_denotation))
00255 && !(p -> decl_special & ID_IMPORTED)) {
00256 extern int avail_loc;
00257
00258 if (Vflag) {
00259 printf("Binding of %s:%s stored in v. register\n",
00260 Vcurrent_func -> fc_code_label,
00261 getname(p -> decl_id -> id_str_table_index));
00262 }
00263 p -> decl_special |= ID_IN_REG;
00264 p -> displacement = avail_loc++;
00265 n_int_regs++;
00266 } else {
00267 p -> displacement = Vnext_free++;
00268 }
00269 }
00270 }
00271 if (p -> decl_denotation -> kind == FUNCCONSTR
00272 && !(p -> decl_needed)) {
00273 Vallocate(p -> decl_denotation, TRUE);
00274 } else {
00275 Vallocwalk(p -> decl_denotation);
00276 }
00277 return;
00278 }
00279
00280 case PARAMETER:
00281 if (Vflag && p -> par_id != NIL
00282 && is_real_def(p -> par_only_def)) {
00283 printf( "Parameter %s:%s is known to be bound to: ",
00284 Vcurrent_func -> fc_code_label,
00285 getname(p -> par_id -> id_str_table_index));
00286 unparse_file = stdout;
00287 unparse(p -> par_only_def);
00288 printf("\n");
00289 }
00290 p -> displacement = Vnext_free++;
00291 p -> level = Vstatic_level;
00292 return;
00293
00294 case GUARDEDELEMENT:
00295 Vallocwalk(p->ge_guard);
00296 Vallocwalk(p->ge_element);
00297 return;
00298
00299 case EXTERNDEF:
00300 return;
00301 }
00302
00303 if (p -> signature -> kind == SIGNATURESIG) {
00304
00305 return;
00306 }
00307
00308 switch ( p -> kind ) {
00309
00310 case BLOCKDENOTATION:
00311 {
00312 long old_int_regs = n_int_regs;
00313 long old_addr_regs = n_addr_regs;
00314 int old_n_decls = n_decls;
00315 boolean escaping_env_ptrs
00316 = (p->bld_flags & (CONTAINS_CLOSURE | CALLCC_CALL)) != 0;
00317 boolean needs_ar = (p -> bld_flags & REQUIRES_AR) != 0;
00318 boolean old_ccc = Vcallcc;
00319 boolean old_aos;
00320 boolean old_el;
00321 struct blocks * old_Vcurrent_blocks;
00322 NODE * old_ar;
00323 int old_Vnext_free = Vnext_free;
00324 int old_Vhigh_water = Vhigh_water;
00325
00326 if (p -> bld_declaration_list != NIL) {
00327 n_decls = length(p -> bld_declaration_list);
00328 } else {
00329 n_decls = 0;
00330 }
00331 Vcallcc = (p -> bld_flags & CALLCC_CALL) != 0;
00332 if (needs_ar) {
00333 old_aos = Vallocate_on_stack;
00334 old_el = Vextent_limited;
00335 old_Vcurrent_blocks = Vcurrent_blocks;
00336 old_ar = Vcurrent_ar;
00337 Vcurrent_ar = p;
00338 Vcurrent_func -> fc_complexity |= NESTED_AR_BLOCK;
00339 Vextent_limited = (p -> signature -> kind
00340 == TYPESIGNATURE);
00341
00342
00343 Vallocate_on_stack = Vextent_limited && !Vcallcc;
00344 Vcurrent_blocks = NIL;
00345 Vhigh_water = Vnext_free = AR_FIRST_PARM;
00346 Vstatic_level++;
00347 } else {
00348
00349
00350
00351
00352
00353
00354
00355
00356 realloc_blocks(p);
00357 if (!escaping_env_ptrs) {
00358
00359 add_block(p);
00360 }
00361 }
00362
00363 maplist(v,p->bld_declaration_list,Vallocwalk(v));
00364 maplist(v,p->bld_den_seq,Vallocwalk(v));
00365 if (needs_ar) {
00366 Vallocate_on_stack = old_aos;
00367 Vextent_limited = old_el;
00368 Vcurrent_blocks = old_Vcurrent_blocks;
00369 Vcallcc = old_ccc;
00370 if (Vnext_free >= Vhigh_water) {
00371 p -> ar_size = Vnext_free;
00372 } else {
00373 p -> ar_size = Vhigh_water;
00374 }
00375 if (p -> ar_size > MAXOBJSZ) {
00376 errmsg0(p, "Too many local variables");
00377 }
00378 p -> ar_static_level = Vstatic_level;
00379 p -> ar_static_link = old_ar;
00380 Vnext_free = old_Vnext_free;
00381 Vhigh_water = old_Vhigh_water;
00382 Vcurrent_ar = old_ar;
00383 Vstatic_level--;
00384 } else if (!escaping_env_ptrs) {
00385 if (Vnext_free > Vhigh_water) {
00386 Vhigh_water = Vnext_free;
00387 }
00388 Vnext_free = old_Vnext_free;
00389 }
00390 n_int_regs = old_int_regs;
00391 n_addr_regs = old_addr_regs;
00392 n_decls = old_n_decls;
00393 break;
00394 }
00395
00396 case APPLICATION:
00397 {
00398 Vallocwalk(p->ap_operator);
00399 maplist(v,p->ap_args,Vallocwalk(v));
00400 break;
00401 }
00402
00403 case LOOPDENOTATION:
00404 {
00405 boolean old_aos = Vallocate_on_stack;
00406 boolean old_el = Vextent_limited;
00407
00408 Vallocate_on_stack = FALSE;
00409 Vextent_limited = FALSE;
00410 maplist(v,p->gl_list,Vallocwalk(v));
00411 Vallocate_on_stack = old_aos;
00412 Vextent_limited = old_el;
00413 break;
00414 }
00415
00416 case QSTR:
00417 case UQSTR:
00418 {
00419
00420
00421
00422 boolean old_aos = Vallocate_on_stack;
00423 boolean old_el = Vextent_limited;
00424
00425 Vallocate_on_stack = FALSE;
00426 Vextent_limited = FALSE;
00427 Vallocwalk(p -> sel_type);
00428 Vallocate_on_stack = old_aos;
00429 Vextent_limited = old_el;
00430 break;
00431 }
00432
00433 case GUARDEDLIST:
00434 maplist(v,p->gl_list,Vallocwalk(v));
00435 break;
00436
00437 case OPRID:
00438 case LETTERID:
00439 if (p -> sel_type != NIL) {
00440 Vallocwalk(p->sel_type);
00441 }
00442 break;
00443
00444 case FUNCCONSTR:
00445 {
00446 Vallocate (p, FALSE);
00447 break;
00448 }
00449
00450 case REXTERNDEF:
00451 break;
00452
00453 case USELIST:
00454 maplist(q, p -> usl_den_seq, Vallocwalk(q));
00455 break;
00456
00457 case MODPRIMARY:
00458 if (p -> mp_type_modifier != NIL
00459 && p -> mp_type_modifier -> kind == WITHLIST) {
00460
00461
00462 realloc_blocks(p);
00463 }
00464 Vallocwalk(p -> mp_primary);
00465 if (p -> mp_type_modifier != NIL
00466 && p -> mp_type_modifier -> kind == WITHLIST) {
00467
00468 p -> displacement = Vnext_free++;
00469 p -> level = Vstatic_level;
00470 maplist (q, p -> mp_type_modifier -> wl_component_list, {
00471 Vallocwalk(q -> decl_denotation);
00472 });
00473 }
00474 break;
00475
00476 case ENUMERATION:
00477 case PRODCONSTRUCTION:
00478 case UNIONCONSTRUCTION:
00479
00480
00481 break;
00482
00483 case EXTENSION:
00484 Vallocwalk(p -> ext_denotation);
00485 break;
00486
00487 case RECORDCONSTRUCTION:
00488 maplist(s, p -> rec_component_list, {
00489 Vallocwalk(s -> re_denotation);
00490 });
00491 break;
00492
00493 case WORDELSE:
00494 break;
00495
00496 case WORDCAND:
00497 case WORDCOR:
00498 dbgmsg("Vallocate: cand or cor\n");
00499 break;
00500
00501 case RECORDELEMENT:
00502 case FUNCSIGNATURE:
00503 case LISTHEADER:
00504 case VARSIGNATURE:
00505 case VALSIGNATURE:
00506 case TYPESIGNATURE:
00507 case TSCOMPONENT:
00508 case DEFCHARSIGS:
00509 case WITHLIST:
00510 case EXPORTLIST:
00511 case EXPORTELEMENT:
00512 case ALLCONSTANTS:
00513 case HIDELIST:
00514 case PARAMETER:
00515 case DECLARATION:
00516 case GUARDEDELEMENT:
00517 default:
00518 dbgmsg("Vallocwalk: bad kind\n");
00519 break;
00520 };
00521 return;
00522 }
00523
00524
00525
00526 static boolean found_non_vacuous;
00527 static n_vacuous;
00528
00529 static void check_vacuous(p)
00530 NODE * p;
00531 {
00532 if (!found_non_vacuous) {
00533 if (vacuous_arg(p -> par_signature)) {
00534 n_vacuous++;
00535 } else {
00536 found_non_vacuous = TRUE;
00537 }
00538 }
00539 }
00540
00541 int n_vacuous_params(p)
00542 NODE *p;
00543 {
00544 if (!Gflag) return(0);
00545
00546 found_non_vacuous = FALSE;
00547 n_vacuous = 0;
00548 maprlist(p, check_vacuous);
00549 return(n_vacuous);
00550 }
00551
00552 Vallocate (p, unused_decl)
00553 register NODE * p;
00554 boolean unused_decl;
00555 {
00556 register NODE * v;
00557 boolean old_aos = Vallocate_on_stack;
00558 boolean old_el = Vextent_limited;
00559 boolean old_ccc = Vcallcc;
00560 long old_addr_regs = n_addr_regs;
00561 long old_int_regs = n_int_regs;
00562 struct blocks * old_Vcurrent_blocks = Vcurrent_blocks;
00563 NODE * old_func = Vcurrent_func;
00564 NODE * old_ar = Vcurrent_ar;
00565 int old_Vnext_free = Vnext_free;
00566 int old_Vhigh_water = Vhigh_water;
00567 NODE * op_sig = p -> signature;
00568 NODE * result_sig = p -> signature -> fsig_result_sig;
00569
00570 ASSERT (p->kind == FUNCCONSTR,"Vallocate.c: arg not FUNCCONSTR\n");
00571 if (p->kind != FUNCCONSTR) {dbgmsg ("p is %x\n",p);};
00572 Vstatic_level++;
00573 Vcurrent_func = Vcurrent_ar = p;
00574 Vcurrent_blocks = NIL;
00575 Vhigh_water = Vnext_free = AR_FIRST_PARM;
00576 n_int_regs = n_addr_regs = 0;
00577
00578 {
00579 if (impure(op_sig)) {
00580
00581 Vextent_limited = FALSE;
00582 # ifdef VERBOSE
00583 printf("Vallocate: impure operator signature\n");
00584 # endif
00585 } else if (result_sig -> kind == VARSIGNATURE) {
00586
00587 Vextent_limited = FALSE;
00588 # ifdef VERBOSE
00589 printf("Vallocate: variable result signature\n");
00590 # endif
00591 } else if (result_sig -> kind == VALSIGNATURE &&
00592 !result_sig -> val_denotation -> signature
00593 -> ts_simple_type) {
00594 ASSERT (has_sig(result_sig -> val_denotation),
00595 "Missing result type signature");
00596 Vextent_limited = FALSE;
00597 # ifdef VERBOSE
00598 printf("Vallocate: bad value result\n");
00599 # endif
00600 } else if (result_sig -> kind == FUNCSIGNATURE
00601 && impure(result_sig)) {
00602 Vextent_limited = FALSE;
00603 # ifdef VERBOSE
00604 printf("Vallocate: impure result signature\n");
00605 # endif
00606 } else {
00607
00608 Vextent_limited = TRUE;
00609 # ifdef VERBOSE
00610 printf("Vallocate: so far - so good\n");
00611 # endif
00612 if (p -> ar_static_level != 0) {
00613 maplist(q, op_sig -> fsig_param_list, {
00614 NODE * sig = q -> par_signature;
00615
00616 if (sig -> kind == VARSIGNATURE) {
00617 ASSERT (has_sig(sig -> var_denotation),
00618 "Missing parameter type signature");
00619 if (!sig -> var_denotation -> signature
00620 -> ts_simple_type) {
00621 Vextent_limited = FALSE;
00622 IFVERBOSE(
00623 printf("Vallocate: bad parameter\n");
00624 )
00625 }
00626 }
00627 });
00628 }
00629 }
00630 }
00631 Vcallcc = FALSE;
00632 Vallocate_on_stack = Vextent_limited;
00633 if (!Gflag
00634 && (result_sig -> kind == FUNCSIGNATURE || !unused_decl)) {
00635
00636
00637 Vallocate_on_stack = FALSE;
00638 # ifdef VERBOSE
00639 printf("Vallocate: possible heap a.r.\n");
00640 # endif
00641 }
00642 if (!Nflag && (p -> fc_complexity & NO_CALLCC) == 0) {
00643
00644
00645 Vallocate_on_stack = FALSE;
00646 Vcallcc = TRUE;
00647 # ifdef VERBOSE
00648 printf("Vallocate: possible saved continuation\n");
00649 # endif
00650 }
00651 # ifdef VERBOSE
00652 printf("Vallocate: Vallocate_on_stack = %d\n",
00653 Vallocate_on_stack);
00654 # endif
00655 {
00656 NODE * params = p -> signature -> fsig_param_list;
00657 int n_params = length(params) - n_vacuous_params(params);
00658 register int i = 0;
00659
00660 maplist (v,p->signature->fsig_param_list, {
00661 if (i < n_params || Vstatic_level == 0) {
00662
00663 Vallocwalk(v);
00664 } else {
00665
00666 v -> displacement = Vnext_free - 1;
00667 v -> level = Vstatic_level;
00668 }
00669 i++;
00670 });
00671 }
00672 Vallocwalk (p->fc_body);
00673 p -> ar_static_level = Vstatic_level;
00674 if (Vnext_free >= Vhigh_water) {
00675 p -> ar_size = Vnext_free;
00676 } else {
00677 p -> ar_size = Vhigh_water;
00678 }
00679 if (p -> ar_size > MAXOBJSZ) {
00680 errmsg0(p, "Too many local variables");
00681 }
00682 p -> ar_static_link = old_ar;
00683 Vcurrent_func = old_func;
00684 Vcurrent_ar = old_ar;
00685 Vstatic_level--;
00686 Vnext_free = old_Vnext_free;
00687 Vhigh_water = old_Vhigh_water;
00688 Vallocate_on_stack = old_aos;
00689 Vextent_limited = old_el;
00690 Vcallcc = old_ccc;
00691 Vfree_blocks();
00692 Vcurrent_blocks = old_Vcurrent_blocks;
00693 n_int_regs = old_int_regs;
00694 n_addr_regs = old_addr_regs;
00695 }
00696