00001 # define OBSOLETE
00002 # undef OBSOLETE
00003 # define DEBUG
00004
00005 # include "parm.h"
00006 # include <stdio.h>
00007 # include "stree/ststructs.mh"
00008 # include "codegen.h"
00009 # include "op_codes.h"
00010 # include "pass4/sigs.h"
00011 # include "pass3/is_local.h"
00012
00013 extern int yydebug;
00014 extern int yynerrs;
00015
00016 extern FILE * unparse_file;
00017
00018 extern char str_code_buf[];
00019
00020 extern int avail_loc;
00021
00022 extern int Glevel;
00023
00024 extern NODE * Gcurrent;
00025
00026 extern boolean Vflag;
00027
00028 extern boolean Nflag;
00029
00030 extern boolean Oflag;
00031
00032 extern boolean fflag;
00033
00034 extern boolean Fflag;
00035
00036
00037
00038
00039
00040 extern boolean hflag;
00041
00042 extern FILE * Goutfile;
00043
00044 extern boolean sl_available;
00045
00046
00047 boolean Gpush_size();
00048
00049 boolean is_id();
00050
00051 extern boolean is_int_const();
00052
00053 extern NODE * equiv_expr();
00054
00055 static int arg_loc;
00056
00057
00058
00059
00060 boolean vacuous_arg(p)
00061 NODE *p;
00062 {
00063 extern NODE * var_Void;
00064
00065 switch (p -> kind) {
00066 case VALSIGNATURE:
00067 return(FALSE);
00068 case VARSIGNATURE:
00069 return(comp_st(p, var_Void, NIL, NIL) == 0);
00070 case FUNCSIGNATURE:
00071 return(FALSE);
00072 case TYPESIGNATURE:
00073 return(tsig_length(p) == 0);
00074 case SIGNATURESIG:
00075 return(TRUE);
00076 case LETTERID:
00077 case OPRID:
00078 if (p -> id_last_definition -> kind == DECLARATION
00079 && p -> id_last_definition -> decl_sig_transp) {
00080 return(vacuous_arg(p -> id_last_definition -> decl_denotation));
00081
00082 } else {
00083 ASSERT(p -> id_last_definition -> kind == PARAMETER,
00084 "vacuous_arg: strange signature identifier\n");
00085 return(FALSE);
00086 }
00087 default:
00088 dbgmsg("vacuous_arg: bad argument kind\n");
00089 abort(p);
00090 }
00091 }
00092
00093
00094
00095
00096
00097
00098 static boolean maprl1_non_vacuous(l,fn)
00099 ConsNode * l;
00100 void (*fn)();
00101 {
00102 register boolean tail_non_vacuous = FALSE;
00103
00104 if (l != NIL) {
00105 tail_non_vacuous = maprl1_non_vacuous(cn_tail(l),fn)
00106 || !vacuous_arg(((NODE *)cn_head(l)) -> signature);
00107 (*fn) (cn_head(l), tail_non_vacuous);
00108 }
00109 return(tail_non_vacuous);
00110 }
00111
00112 void maprlist_non_vacuous(l, fn)
00113 LIST l;
00114 void (*fn)();
00115 {
00116 (void) maprl1_non_vacuous(l -> lh_first, fn);
00117 }
00118
00119 boolean reg_ok = FALSE;
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 Garg_expression(p, needed)
00130 NODE *p;
00131 boolean needed;
00132 {
00133 int SAVarg_loc = arg_loc - 1;
00134 int SAVreg_ok = reg_ok;
00135
00136 if (needed) {
00137 if (reg_ok && (p -> kind == LETTERID || p -> kind == OPRID)
00138 && p -> sel_type == NIL
00139 && p -> id_last_definition -> kind == DECLARATION
00140 && (p -> id_last_definition -> decl_special & VAR_IN_REG)) {
00141
00142
00143 } else {
00144 reg_ok = FALSE;
00145 Gexpression(p, SAVarg_loc, FALSE);
00146
00147 }
00148 } else {
00149 SAVarg_loc ++;
00150 if (!is_id(p) &&
00151 (p -> signature -> kind != TYPESIGNATURE
00152 || calls_put(p))) {
00153 if (Vflag) {
00154 printf("Evaluating vacuous argument ");
00155 unparse_file = stdout;
00156 unparse(p);
00157 printf(" for effect\n");
00158 }
00159 }
00160 reg_ok = FALSE;
00161 Gexpression(p, SK, FALSE);
00162 }
00163 arg_loc = SAVarg_loc;
00164 reg_ok = SAVreg_ok;
00165 }
00166
00167 # ifdef UNDEFINED
00168 int arg_no;
00169
00170
00171
00172
00173
00174
00175 Gdir_arg_expression(p, needed)
00176 NODE *p;
00177 boolean needed;
00178 {
00179 if (needed) {
00180 int SAVarg_no = arg_no;
00181 int tmp_loc = avail_loc++;
00182
00183 gen2(DCL, tmp_loc, DCL_INT);
00184 Gexpression(p, tmp_loc, FALSE);
00185 gen2(ARG, SAVarg_no, tmp_loc);
00186 gen1(UDC, tmp_loc);
00187 arg_no = SAVarg_no - 1;
00188 } else if (!is_id(p) &&
00189 (p -> signature -> kind != TYPESIGNATURE
00190 || calls_put(p))) {
00191 if (Vflag) {
00192 printf("Evaluating vacuous argument ");
00193 unparse_file = stdout;
00194 unparse(p);
00195 printf(" for effect\n");
00196 }
00197 Gexpression(p, SK, FALSE);
00198 }
00199 }
00200
00201 #endif
00202
00203
00204
00205
00206
00207
00208 static int heap_loc;
00209 static int heap_offset;
00210
00211 Gheap_expression(p, needed)
00212 NODE *p;
00213 boolean needed;
00214 {
00215 if (needed) {
00216 int tmp_loc = avail_loc++;
00217 int SAVheap_loc = heap_loc;
00218 int SAVheap_offset = heap_offset;
00219
00220 gen2(DCL, tmp_loc, DCL_INT);
00221 Gexpression(p, tmp_loc, FALSE);
00222
00223 gen3(STI, SAVheap_loc, SAVheap_offset, tmp_loc);
00224 gen1(UDC, tmp_loc);
00225 heap_offset = SAVheap_offset - 1;
00226 heap_loc = SAVheap_loc;
00227 } else if (!is_id(p) &&
00228 (p -> signature -> kind != TYPESIGNATURE
00229 || calls_put(p))) {
00230 if (Vflag) {
00231 printf("Evaluating vacuous argument ");
00232 unparse_file = stdout;
00233 unparse(p);
00234 printf(" for effect\n");
00235 }
00236 Gexpression(p, SK, FALSE);
00237 }
00238 }
00239
00240
00241 gen_abs(loc)
00242 int loc;
00243 {
00244 # ifdef OBSOLETE
00245 gen3(GEI, loc, C0, TL);
00246 genl(BRT, "1f");
00247 gen2(NGI, loc, loc);
00248 genl(LBL, "1");
00249 # else
00250 gen2(ABI, loc, loc);
00251 # endif
00252 }
00253
00254
00255 boolean is_id(p)
00256 NODE *p;
00257 {
00258 if (p -> kind != LETTERID && p -> kind != OPRID) {
00259 return(FALSE);
00260 } else {
00261 return(TRUE);
00262 }
00263 }
00264
00265
00266
00267
00268
00269
00270 Gappl(p, rloc, last_expr)
00271 NODE *p;
00272 int rloc;
00273 boolean last_expr;
00274 {
00275 register NODE *v;
00276 register int argcount;
00277 struct RIC_instr * in_line;
00278 boolean stack_call;
00279 boolean test_closure = TRUE;
00280
00281
00282
00283 int size_loc;
00284
00285 int ar_loc;
00286 int fn_loc;
00287 int old_sp_loc;
00288 int first_arg_loc;
00289 NODE * op = (Oflag ? equiv_expr(p -> ap_operator) : p -> ap_operator);
00290 NODE * construction = op -> signature
00291 -> fsig_construction;
00292 boolean slink_known;
00293
00294
00295
00296 NODE * result_sig = p -> signature;
00297 NODE * op_sig = p -> ap_operator -> signature;
00298 long op_special = op -> signature -> fsig_special;
00299 boolean op_is_id = is_id(p -> ap_operator);
00300 boolean appl_impure = impure(op_sig);
00301 boolean op_impure = (appl_impure && !op_is_id)
00302 || calls_put(p -> ap_operator);
00303 boolean reuse_ar;
00304
00305 boolean slink_needed;
00306 boolean bogus_slink_ok;
00307
00308 boolean direct_rec_call;
00309
00310 int Rlevel = Glevel;
00311
00312
00313 int i;
00314
00315
00316 ASSERT( !last_expr || rloc == RL, "Gappl: bad last_expr value\n");
00317
00318 if (is_int_const(p)) {
00319 extern long int_const_val;
00320
00321 gen2(LDN, int_const_val, rloc);
00322 return;
00323 }
00324
00325 argcount = 0;
00326 i = 0;
00327 maplist(s, p -> ap_args, {
00328 i++;
00329 if (!vacuous_arg(s -> signature)) {
00330 argcount = i;
00331 }
00332 });
00333
00334 switch (special_tp(op_special)) {
00335 case ARRAY_VALUEOF:
00336 if (Vflag) {
00337 printf("Using fast array ValueOf inside %s\n",
00338 Gcurrent -> fc_code_label);
00339 }
00340
00341 {
00342 int i = avail_loc++;
00343
00344 gen2(DCL, i, DCL_INT);
00345 Gexpression(first(p -> ap_args), i, FALSE);
00346 gen2(ARG, 1, i);
00347 gen1(UDC, i);
00348 }
00349 genl(EXT, "_fast_Array_ValueOf");
00350 genl(LBA, "_fast_Array_ValueOf");
00351 gen1(CLC, 1);
00352 gen2(MOV, RL, rloc);
00353 return;
00354 case ARRAY_STD_NEW:
00355 case ARRAY_PTR_NEW:
00356 {
00357 long size_val = special_val(op_special);
00358
00359 if (!Gpush_size(size_val, p -> ap_operator)) {
00360
00361
00362
00363
00364 break;
00365 }
00366 switch(special_tp(op_special)) {
00367 case ARRAY_STD_NEW:
00368 if (Vflag) {
00369 printf("Using fast standard array allocation inside %s\n",
00370 Gcurrent -> fc_code_label);
00371 }
00372 genl(EXT, "_fast_Array_New");
00373 gen3(HINT, AL, 0, 0);
00374 genl(LBA, "_fast_Array_New");
00375 gen1(CLC, 1);
00376 break;
00377 case ARRAY_PTR_NEW:
00378 if (Vflag) {
00379 printf("Using fast pointer array allocation inside %s\n",
00380 Gcurrent -> fc_code_label);
00381 }
00382 genl(EXT, "_fast_pArray_New");
00383 gen3(HINT, AL, 0, 0);
00384 genl(LBA, "_fast_pArray_New");
00385 gen1(CLC, 1);
00386 break;
00387 }
00388 gen2(MOV, RL, rloc);
00389 return;
00390 }
00391 case RECORD_VALUEOF:
00392 case PROD_VALUEOF:
00393 case ENUM_VALUEOF:
00394 case STD_VALUEOF:
00395 {
00396 NODE * arg1 = first(p -> ap_args);
00397 NODE * def;
00398
00399 if (arg1 -> kind != LETTERID && arg1 -> kind != OPRID
00400 || arg1 -> sel_type != NIL) {
00401 break;
00402 }
00403 def = arg1 -> id_last_definition;
00404 if (def -> kind != DECLARATION) {
00405
00406 break;
00407 }
00408 if (def -> decl_special & VAR_IN_REG) {
00409
00410 gen2(MOV, def -> displacement , rloc);
00411 } else if (def -> decl_special & VAR_ON_STACK) {
00412
00413 if (def -> level == 0) {
00414 gen3(LDI, GF, def -> displacement, rloc);
00415 } else if (def -> level == Glevel) {
00416 gen3(LDI, AR, def -> displacement, rloc);
00417 } else {
00418 break;
00419 }
00420 } else {
00421 break;
00422 }
00423 return;
00424 }
00425 case ARRAY_VAR_SUB:
00426 {
00427 int size = special_val(op_special);
00428 int i, j, k, m;
00429 NODE * arg1 = first(p -> ap_args);
00430 NODE * def;
00431
00432 if (size == 0) {
00433
00434 break;
00435 }
00436 if (arg1 -> kind != LETTERID && arg1 -> kind != OPRID
00437 || arg1 -> sel_type != NIL) {
00438 break;
00439 }
00440 def = arg1 -> id_last_definition;
00441 if (def -> kind != DECLARATION) {
00442
00443 break;
00444 }
00445 if (!(def -> decl_special & ARRAY_CONTIG)) {
00446 break;
00447 }
00448
00449
00450
00451 i = avail_loc++;
00452 j = avail_loc++;
00453 k = avail_loc++;
00454 m = avail_loc++;
00455 gen2(DCL, i, DCL_ADDR);
00456 gen2(DCL, j, DCL_INT);
00457 gen2(DCL, k, DCL_INT);
00458 Gexpression(second(p -> ap_args), j, FALSE);
00459
00460 gen2(HINT, OPT, 12);
00461 gen3(GEI, j, C0, TL);
00462 genl(BRF, "1f");
00463 gen2(DCL, m, DCL_INT);
00464 gen2(LDN, size, m);
00465 gen3(LTI, j, m, TL);
00466 gen1(UDC, m);
00467 genl(BRT, "2f");
00468 genl(LBL, "1");
00469 gen2(ARG, 1, j);
00470 genl(EXT, "_Array_error");
00471 genl(ERR, "_Array_error");
00472 genl(LBL, "2");
00473 gen2(LDN, size + 1, k);
00474 Gident(first(p -> ap_args), i);
00475 gen3(ADP, i, k, i);
00476 gen3(ADP, i, j, rloc);
00477 gen1(UDC, i);
00478 gen1(UDC, j);
00479 gen1(UDC, k);
00480 return;
00481 }
00482
00483 case RECORD_ASSIGN:
00484 case PROD_ASSIGN:
00485 case ENUM_ASSIGN:
00486 case STD_ASSIGN:
00487 {
00488 NODE * arg1 = first(p -> ap_args);
00489 NODE * def;
00490
00491 if (arg1 -> kind != LETTERID && arg1 -> kind != OPRID
00492 || arg1 -> sel_type != NIL) {
00493 break;
00494 }
00495 def = arg1 -> id_last_definition;
00496 if (def -> kind != DECLARATION
00497 || !(def -> decl_special & VAR_IN_REG)) {
00498
00499 break;
00500 }
00501
00502 Gexpression(second(p -> ap_args),
00503 def -> displacement, FALSE);
00504
00505
00506
00507
00508 if (rloc != SK) {
00509 gen2(MOV, def -> displacement, rloc);
00510 }
00511 return;
00512 }
00513 case STD_PASSIGN:
00514 case STD_MASSIGN:
00515 case STD_TASSIGN:
00516 {
00517 NODE * arg1 = first(p -> ap_args);
00518 NODE * def;
00519
00520 if (arg1 -> kind != LETTERID && arg1 -> kind != OPRID
00521 || arg1 -> sel_type != NIL) {
00522 break;
00523 }
00524 def = arg1 -> id_last_definition;
00525 if (def -> kind != DECLARATION
00526 || !(def -> decl_special & VAR_IN_REG)) {
00527
00528 break;
00529 }
00530 {
00531 int i = avail_loc++;
00532
00533 gen2(DCL, i, DCL_INT);
00534 Gexpression(second(p -> ap_args), i, FALSE);
00535 switch (special_tp(op_special)) {
00536 case STD_PASSIGN:
00537 gen3(ADI, def -> displacement, i, def -> displacement);
00538 break;
00539 case STD_MASSIGN:
00540 gen3(SBI, def -> displacement, i, def -> displacement);
00541 break;
00542 case STD_TASSIGN:
00543 gen3(MLI, def -> displacement, i, def -> displacement);
00544 break;
00545 }
00546 if (rloc != SK) {
00547 gen2(MOV, def -> displacement, rloc);
00548 }
00549 gen1(UDC, i);
00550 }
00551 return;
00552 }
00553 }
00554
00555
00556 in_line = (struct RIC_instr *)(op -> signature -> fsig_inline_code);
00557 if (in_line == NIL) {
00558 switch(result_sig -> kind) {
00559 case TYPESIGNATURE:
00560 stack_call = FALSE;
00561 break;
00562 case FUNCSIGNATURE:
00563 stack_call = FALSE;
00564 break;
00565 case VALSIGNATURE:
00566 # ifdef DEBUG
00567 if (!has_sig(result_sig -> val_denotation)) {
00568 dbgmsg("codegen: Missing res. type signature\n");
00569 prtree(p);
00570 abort();
00571 }
00572 # endif
00573 stack_call = result_sig -> val_denotation
00574 -> signature -> ts_simple_type;
00575 break;
00576 case VARSIGNATURE:
00577 # ifdef DEBUG
00578 if (!has_sig(result_sig -> val_denotation)) {
00579 dbgmsg("codegen: Missing res. type signature\n");
00580 prtree(p);
00581 abort();
00582 }
00583 # endif
00584 stack_call = result_sig -> var_denotation
00585 -> signature -> ts_simple_type;
00586 break;
00587 }
00588
00589 if (appl_impure) {
00590 stack_call = FALSE;
00591 }
00592
00593 maplist(q, p -> ap_args, {
00594 NODE * sig = q -> signature;
00595 if (sig -> kind == VARSIGNATURE) {
00596 ASSERT (has_sig(sig -> var_denotation),
00597 "Missing argument type signature");
00598 if (!sig -> var_denotation -> signature
00599 -> ts_simple_type) {
00600 stack_call = FALSE;
00601 }
00602 }
00603
00604 });
00605 }
00606 if (construction != NIL) {
00607 stack_call = stack_call
00608 || (construction -> fc_complexity & NO_SL)
00609 || (construction -> fc_complexity & NO_AR_REFS);
00610 test_closure = FALSE;
00611 }
00612 if (hflag) {
00613 stack_call = FALSE;
00614 }
00615 if (fflag && construction == NIL
00616 || Fflag && !(construction -> fc_complexity & NO_CALLCC)) {
00617 stack_call = FALSE;
00618
00619
00620 }
00621 if (in_line != NIL) {
00622
00623 if (op_impure) {
00624 if (Vflag) {
00625 printf("Evaluating impure operator for effect: ");
00626 unparse_file = stdout;
00627 unparse(p -> ap_operator);
00628 printf("\n\t(using in-line code for call)\n");
00629 }
00630 Gexpression (p -> ap_operator, SK, FALSE);
00631 }
00632 first_arg_loc = avail_loc;
00633 arg_loc = avail_loc = avail_loc + argcount;
00634 for (i = first_arg_loc; i < arg_loc; i++) {
00635 gen2(DCL, i, DCL_INT);
00636 }
00637 reg_ok = TRUE;
00638 maprlist_non_vacuous(p -> ap_args, Garg_expression);
00639 reg_ok = FALSE;
00640
00641 {
00642 struct RIC_instr * revised_in_line = in_line;
00643 struct RIC_instr * RIC_tmp;
00644 int argcnt = 1;
00645 NODE * argsig;
00646
00647 if (Oflag) {
00648 maplist(s, p -> ap_args, {
00649 if ((s -> kind == LETTERID
00650 || s -> kind == OPRID)
00651 && s -> sel_type == NIL
00652 && s -> id_last_definition -> kind == DECLARATION
00653 && (s -> id_last_definition -> decl_special & VAR_IN_REG)) {
00654 RIC_tmp = revised_in_line;
00655 revised_in_line = unindirect(revised_in_line, argcnt,
00656 s -> id_last_definition
00657 -> displacement);
00658 if (RIC_tmp != in_line) {
00659 free_RIC(RIC_tmp);
00660 }
00661 }
00662 argcnt ++;
00663 });
00664 }
00665 write_RIC_seq(Goutfile, revised_in_line, first_arg_loc, rloc);
00666 if (revised_in_line != in_line) {
00667 free_RIC(revised_in_line);
00668 }
00669 }
00670 for (i = first_arg_loc; i < first_arg_loc + argcount; i++) {
00671 gen1(UDC, i);
00672 }
00673 } else {
00674 boolean no_ar_ref_passed =
00675 (Gcurrent -> fc_complexity & NO_AR_REFS)
00676 || argcount == 0;
00677
00678
00679
00680
00681 slink_needed = ((construction == NIL)
00682 || ((construction -> fc_complexity & NO_SL) == 0));
00683 bogus_slink_ok = (construction != NIL &&
00684 !(construction -> fc_complexity & SL_ACC));
00685
00686
00687 direct_rec_call = (last_expr && (construction != NIL)
00688 && (construction -> pre_num == Gcurrent -> pre_num)
00689 && stack_call && no_ar_ref_passed
00690 && (construction -> pre_num != 0)
00691 && (sl_available == slink_needed));
00692 ASSERT(!direct_rec_call || (Gcurrent -> fc_complexity & DIR_REC),
00693 "Gappl: unexpected tail recursion\n");
00694 reuse_ar = direct_rec_call ||
00695 last_expr && stack_call && no_ar_ref_passed
00696 && (Gcurrent -> fc_complexity & NO_AR_REFS)
00697 && construction != NIL
00698 && (construction -> ar_size <= Gcurrent -> ar_size)
00699 && sl_available && slink_needed
00700 && (construction -> ar_static_level <=
00701 Gcurrent -> ar_static_level
00702 || bogus_slink_ok);
00703
00704
00705
00706
00707
00708 if (Vflag) {
00709 printf("Function %s calls ", Gcurrent -> fc_code_label);
00710 if (construction == NIL) {
00711 unparse_file = stdout;
00712 unparse(p -> ap_operator);
00713 } else {
00714 printf("%s", construction -> fc_code_label);
00715 }
00716 if (direct_rec_call) {
00717 printf(" tail recursively\n");
00718 } else if (reuse_ar) {
00719 printf(" with recycled stack a.r.\n");
00720 } else if (stack_call) {
00721 if (slink_needed) {
00722 printf(" with stack a.r.\n");
00723 } else {
00724 printf(" with partial a.r.\n");
00725 }
00726 } else if (test_closure) {
00727 printf(" with stack or heap a.r.\n");
00728 } else {
00729 printf(" with heap a.r.\n");
00730 }
00731 }
00732 if (slink_needed && !reuse_ar) {
00733 size_loc = avail_loc++;
00734 gen2(DCL, size_loc, DCL_INT);
00735 }
00736 if (construction != NIL) {
00737 slink_known = p -> ap_operator -> signature
00738 -> fsig_slink_known;
00739 if ((construction -> fc_complexity & CP_GLOBALS)
00740
00741
00742 || (Gcurrent -> fc_complexity & CP_GLOBALS)
00743 && construction -> ar_static_level > 1) {
00744
00745 ASSERT((construction -> fc_complexity & NEED_CL)
00746 || (!slink_needed) || bogus_slink_ok,
00747 "Gappl: reference to nonexistent closure\n");
00748 slink_known = FALSE;
00749 }
00750 }
00751
00752 if (construction == NIL
00753 || (!slink_known && slink_needed && !bogus_slink_ok)) {
00754 fn_loc = avail_loc++;
00755 gen2(DCL, fn_loc, DCL_ADDR);
00756 Gexpression (p -> ap_operator, fn_loc, FALSE);
00757 } else if (op_impure) {
00758
00759 if (Vflag) {
00760 printf("\t- Operator evaluated for effect\n");
00761 }
00762 Gexpression (p -> ap_operator, SK, FALSE);
00763 } else {
00764
00765 Gtraverse (p -> ap_operator);
00766 }
00767
00768 if (!reuse_ar) {
00769 if (construction != NIL) {
00770 if (slink_needed) {
00771 ASSERT2(construction -> ar_size > 0,
00772 "function %X has bad ar size field\n",
00773 construction);
00774 gen2(LDN, construction -> ar_size, size_loc);
00775 }
00776 } else {
00777 gen3(LDI, fn_loc, FO_SIZE, size_loc);
00778 }
00779 }
00780
00781 if (reuse_ar) {
00782 if (sl_available) {
00783 int i = Glevel - Gcurrent -> ar_static_level;
00784
00785 if (i > 0) {
00786
00787 ar_loc = avail_loc++;
00788 gen2(DCL, ar_loc, DCL_ADDR);
00789 gen3(LDI, AR, 0, ar_loc);
00790 while (--i > 0) {
00791 gen3(LDI, ar_loc, 0, ar_loc);
00792 }
00793 } else {
00794 ar_loc = AR;
00795 }
00796 } else {
00797 ar_loc = -1;
00798 }
00799 } else if (slink_needed) {
00800 ar_loc = avail_loc++;
00801 gen2(DCL, ar_loc, DCL_ADDR);
00802 if (stack_call) {
00803 if (construction == NIL) {
00804 gen_abs(size_loc);
00805 }
00806 if (fflag) {
00807 gen1(HINT, ONS);
00808 gen2(ALH, size_loc, ar_loc);
00809 } else {
00810 gen1(ALS, size_loc);
00811 gen2(MOV, SP, ar_loc);
00812 }
00813 } else if (test_closure && !fflag) {
00814 old_sp_loc = avail_loc++;
00815 gen2(DCL, old_sp_loc, DCL_INT);
00816 gen2(MOV, SP, old_sp_loc);
00817 gen3(GEI, size_loc, C0, TL);
00818 genl(BRT, "1f");
00819 gen2(NGI, size_loc, size_loc);
00820 gen2(ALH, size_loc, ar_loc);
00821 genl(BR, "2f");
00822 genl(LBL, "1");
00823 gen1(ALS, size_loc);
00824 gen2(MOV, SP, ar_loc);
00825 genl(LBL, "2");
00826 } else {
00827 if (construction == NIL) {
00828 gen_abs(size_loc);
00829 }
00830 gen2(ALH, size_loc, ar_loc);
00831 }
00832 }
00833
00834
00835 if (! slink_needed || reuse_ar) {
00836
00837
00838
00839
00840 int next_loc;
00841 int ar_offset = 1;
00842 int cur_arg_no;
00843
00844
00845 first_arg_loc = avail_loc;
00846 next_loc = arg_loc = avail_loc = avail_loc + argcount;
00847 for (i = first_arg_loc; i < next_loc; i++) {
00848 gen2(DCL, i, DCL_INT);
00849 }
00850 maprlist_non_vacuous(p -> ap_args, Garg_expression);
00851
00852 if (slink_needed) {
00853 for (i = first_arg_loc; i < next_loc; i++) {
00854 gen3(STI, ar_loc, ar_offset, i);
00855 ar_offset++;
00856 }
00857 } else if (!reuse_ar) {
00858
00859 cur_arg_no = argcount;
00860 for (i = next_loc - 1; i >= first_arg_loc; i--) {
00861 gen2(ARG, cur_arg_no--, i);
00862 }
00863 ASSERT(cur_arg_no == 0, "Appl: incorrect arg count");
00864 } else {
00865 extern int first_param_loc;
00866
00867
00868 ASSERT(first_param_loc != 0,
00869 "Appl: bad tail recursion\n");
00870 for (i = 0; i < argcount; i++) {
00871 gen2(MOV, first_arg_loc + i, first_param_loc + i);
00872 }
00873 ASSERT(argcount == Gcurrent -> ar_size - 1,
00874 "Appl: bad arg count for tail recursion\n");
00875 }
00876
00877 for (i = first_arg_loc; i < next_loc; i++) {
00878 gen1(UDC, i);
00879 }
00880 } else {
00881 heap_loc = ar_loc;
00882 heap_offset = argcount;
00883 maprlist_non_vacuous (p-> ap_args, Gheap_expression);
00884 }
00885
00886 if (slink_needed) {
00887 if (bogus_slink_ok) {
00888 if (!stack_call) {
00889
00890 gen3(STI, ar_loc, 0, UN);
00891 } else {
00892 # ifdef DEBUG
00893 gen3(STI, ar_loc, 0, UN);
00894 # endif
00895 }
00896 } else if (construction == NIL || !slink_known) {
00897 i = avail_loc++;
00898 gen2(DCL, i, DCL_INT);
00899 gen3(LDI, fn_loc, FO_EP, i);
00900 gen3(STI, ar_loc, 0, i);
00901 gen1(UDC, i);
00902 } else {
00903 if (direct_rec_call) {
00904
00905 } else {
00906 int ep_loc;
00907
00908
00909 # ifdef DEBUG
00910 if (Glevel < ((construction -> ar_static_level) - 1)) {
00911 dbgmsg ("Negative level difference for function call\n");
00912 fprintf (stderr, "Current: %d; Construction: %d; Application:\n",
00913 Glevel, (construction -> ar_static_level));
00914 unparse_file = stderr;
00915 unparse(p);
00916 fprintf(stderr, "\n");
00917 abort(p);
00918 }
00919 # endif
00920 DISPLAY ( ep_loc, ((construction -> ar_static_level) - 1));
00921 gen3(STI, ar_loc, 0, ep_loc);
00922 UNDISPLAY(ep_loc);
00923 }
00924 }
00925 }
00926
00927
00928 if (slink_needed && !direct_rec_call) {
00929 gen2(ARG, 1, ar_loc);
00930 }
00931
00932 if (direct_rec_call) {
00933
00934 if (Glevel != Gcurrent -> ar_static_level) {
00935 gen2(MOV, ar_loc, AR);
00936 }
00937 if (slink_needed) {
00938 strcpy(str_code_buf, "R");
00939 } else {
00940 strcpy(str_code_buf, "RF");
00941 }
00942 strcat(str_code_buf, construction -> fc_code_label);
00943 genl(BR, str_code_buf);
00944 } else {
00945 if (construction != NIL) {
00946 if (!slink_needed) {
00947 strcpy(str_code_buf, "F");
00948 strcat(str_code_buf, construction -> fc_code_label);
00949 genl(EXT, str_code_buf);
00950 # ifdef UNDEFINED
00951
00952 if (Nflag || construction -> fc_complexity & NO_CALLCC) {
00953 gen1(HINT, NSC);
00954 }
00955 # endif
00956 genl(LBA, str_code_buf);
00957 gen1(CLC, argcount);
00958 } else {
00959 genl(EXT, construction -> fc_code_label);
00960 if (Nflag || construction -> fc_complexity & NO_CALLCC) {
00961 gen1(HINT, NSC);
00962 }
00963 genl(CLL, construction -> fc_code_label);
00964 }
00965 } else {
00966 if (Nflag) {
00967 gen1(HINT, NSC);
00968 }
00969 gen2(CLI, fn_loc, FO_IP);
00970 }
00971 }
00972
00973 if (reuse_ar) {
00974 if (sl_available && ar_loc != AR) {
00975 gen1(UDC, ar_loc);
00976 }
00977 } else {
00978 if (stack_call) {
00979 if (slink_needed) {
00980 if (fflag) {
00981
00982 gen1(HINT, ONS);
00983 if (construction != NIL) {
00984 int sz = construction -> ar_size;
00985
00986 if (sz < 0) { sz = -sz; }
00987 gen3(HINT, DEA, ar_loc, construction -> ar_size);
00988 } else {
00989 gen3(HINT, DEA, ar_loc, 0);
00990 }
00991 } else {
00992 gen3(ADP, SP, size_loc, SP);
00993 }
00994 }
00995 } else if (test_closure && !fflag) {
00996 gen2(MOV, old_sp_loc, SP);
00997 gen1(UDC, old_sp_loc);
00998 }
00999
01000 if (slink_needed) {
01001 gen1(UDC, ar_loc);
01002 }
01003 }
01004
01005 if (slink_needed && ! reuse_ar) {
01006 gen1(UDC, size_loc);
01007 }
01008 if (construction == NIL
01009 || (slink_needed && !slink_known && !bogus_slink_ok)) {
01010 gen1(UDC, fn_loc);
01011 }
01012
01013 if (rloc != RL) {
01014 gen2(MOV, RL, rloc);
01015 }
01016 }
01017 }
01018
01019
01020
01021
01022
01023
01024
01025 boolean Gpush_size(size, op)
01026 int size;
01027 NODE * op;
01028 {
01029 NODE * sel_type_sig;
01030 NODE * size_sig;
01031 NODE * size_appl;
01032 NODE * size_id;
01033 extern NODE * id_size;
01034
01035 if (size == 0) {
01036
01037
01038 if (op -> kind != LETTERID || op -> sel_type == NIL) {
01039 return(FALSE);
01040 }
01041 sel_type_sig = op -> sel_type -> signature;
01042 size_sig = getcomp(sel_type_sig, id_size, NIL, NIL,
01043 NIL, NIL, NIL, FALSE);
01044 if (size_sig == NIL || special_tp(size_sig -> fsig_special)
01045 != ARRAY_SIZE) {
01046
01047 return(FALSE);
01048 }
01049
01050 size_id = copynode(id_size);
01051 initfld(&(size_id -> sel_type), op -> sel_type);
01052 size_id -> id_def_found = TRUE;
01053 size_appl = mknode(APPLICATION, size_id, emptylist());
01054 checksigs(size_appl, FALSE);
01055 {
01056 int i = avail_loc++;
01057
01058 gen2(DCL, i, DCL_INT);
01059 Gappl(size_appl, i, FALSE);
01060 gen2(ARG, 1, i);
01061 gen1(UDC, i);
01062 }
01063 } else {
01064
01065 int i = avail_loc++;
01066
01067 gen2(DCL, i, DCL_INT);
01068 gen2(LDN, size, i);
01069 gen2(ARG, 1, i);
01070 gen1(UDC, i);
01071 }
01072 return(TRUE);
01073 }