00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 # include "parm.h"
00016 # include <stdio.h>
00017 # include "stree/ststructs.mh"
00018 # include "codeutil.h"
00019 # include "pass4/sigs.h"
00020 # include "pass3/is_local.h"
00021
00022 # ifdef DEBUG
00023 # define IFDEBUG(x) x
00024 # else
00025 # define IFDEBUG(x)
00026 # endif
00027
00028 # define UNDEF (0x87654321)
00029 # define MAXOBJSZ 512
00030
00031 extern int yydebug;
00032 extern int yynerrs;
00033
00034 extern boolean Pflag;
00035 extern boolean Tflag;
00036
00037 extern char * entry_name;
00038
00039 boolean mentions_r11();
00040
00041 void type_expr();
00042
00043 extern boolean is_int_const();
00044
00045 char str_code_buf[MAXSTRCODELEN];
00046
00047
00048
00049 FILE * objfilelist = NULL;
00050
00051
00052 void add_objfile(fn)
00053 char * fn;
00054 {
00055 char *s;
00056
00057 if (objfilelist == NULL) {
00058 objfilelist = fopen(OBJFILELIST, "w");
00059 if (objfilelist == NULL) {
00060 fprintf(stderr, "Can't open %s\n", OBJFILELIST);
00061 exit(1);
00062 }
00063 }
00064 for (s = fn; *s != '\0'; s++) {
00065 putc(*s, objfilelist);
00066 }
00067 putc('\n', objfilelist);
00068 }
00069
00070
00071
00072
00073
00074 typedef struct Fc_Entry {
00075 NODE * fc_pointer;
00076 int fc_level;
00077 int fc_fast_only;
00078 struct Fc_Entry * fc_next;
00079 } fc_entry;
00080
00081 fc_entry * fc_list = NIL;
00082
00083
00084 void fc_add(ptr,lvl,fast_only)
00085 NODE * ptr;
00086 int lvl;
00087 int fast_only;
00088 {
00089 fc_entry * p = (fc_entry *)malloc(sizeof (fc_entry));
00090
00091 p -> fc_pointer = ptr;
00092 p -> fc_level = lvl;
00093 p -> fc_fast_only = fast_only;
00094 p -> fc_next = fc_list;
00095 fc_list = p;
00096 }
00097
00098
00099 void fc_delete()
00100 {
00101 fc_entry * p = fc_list;
00102
00103 fc_list = fc_list -> fc_next;
00104 free(p);
00105 }
00106
00107 int Ventry_mask,Vgc_mask;
00108 int Vlevel = -1;
00109
00110 NODE * Vcurrent;
00111 FILE * Voutfile;
00112
00113
00114
00115 Vgeneratecode ( f , p )
00116 NODE * p;
00117 FILE * f;
00118 {
00119 NODE * fc_ptr;
00120 int fc_lvl;
00121 int fc_fast_only;
00122
00123 Voutfile = f;
00124 p -> fc_code_label = "russell_top_level";
00125 analyze(p);
00126 accessible(p);
00127 bld_analyze(&p);
00128 Vallocate (p, TRUE);
00129 if (yydebug) prtree(p);
00130 ASM_HEADER;
00131 fc_add(p,0,FALSE);
00132
00133 while (fc_list != NIL) {
00134 fc_ptr = fc_list -> fc_pointer;
00135 fc_lvl = fc_list -> fc_level;
00136 fc_fast_only = fc_list -> fc_fast_only;
00137 fc_delete();
00138 if(!fc_fast_only) Vfuncbody(fc_ptr, fc_lvl);
00139 if((fc_ptr -> fc_complexity & NO_SL) && fc_lvl != 0) {
00140 Ffuncbody(fc_ptr);
00141
00142 }
00143 }
00144 }
00145
00146
00147
00148 Vgeneratepcode ( f, q, p )
00149 NODE * q;
00150 NODE * p;
00151 FILE * f;
00152 {
00153 NODE * fc_ptr;
00154 int fc_lvl;
00155 int fc_fast_only;
00156 extern char * ofname;
00157
00158 Voutfile = f;
00159 q -> fc_code_label = "russell_top_level";
00160 if (p -> kind != FUNCCONSTR) {
00161 errmsg0(p, "Outermost expression must be function construction");
00162 return;
00163 }
00164 analyze(q);
00165 accessible(q);
00166 bld_analyze(&q);
00167 Vallocate (q, TRUE);
00168 if (yydebug) prtree(p);
00169 if (p -> ar_static_level != 1) {
00170 dbgmsg("user program must be at level 1");
00171 }
00172
00173 fprintf(Voutfile, "\t.globl\tm_%s\n", entry_name);
00174 fprintf(Voutfile, "m_%s:\n", entry_name);
00175 Vlevel = 0;
00176 Vfuncconstructor(p);
00177 fprintf(Voutfile, "\tmovl\t(sp)+,r0\n");
00178 fprintf(Voutfile, "\trsb\n");
00179
00180 while (fc_list != NIL) {
00181 fc_ptr = fc_list -> fc_pointer;
00182 fc_lvl = fc_list -> fc_level;
00183 fc_fast_only = fc_list -> fc_fast_only;
00184 fc_delete();
00185 if(!fc_fast_only) Vfuncbody(fc_ptr, fc_lvl);
00186 if((fc_ptr -> fc_complexity & NO_SL) && fc_lvl != 0) {
00187 Ffuncbody(fc_ptr);
00188
00189 }
00190 }
00191 }
00192
00193
00194
00195 Vfuncconstructor(p)
00196 NODE * p;
00197
00198
00199
00200
00201
00202 {
00203 if (p -> fc_body -> kind == EXTERNDEF) {
00204 int n_args = length(p -> signature -> fsig_param_list);
00205
00206 putcomment ("# request new function object");
00207 FXD_NEWOBJ(FO_OBJ_SIZE);
00208 fprintf(Voutfile,"\tmovl\t$%d,%d(r0)", n_args, FO_EP);
00209 putcomment("# environment pointer");
00210 fprintf(Voutfile,"\t.globl\t%s\n",p -> fc_code_label);
00211 fprintf(Voutfile,"\tmovab\t%s,%d(r0)",p -> fc_code_label, FO_IP);
00212 putcomment("# instruction pointer");
00213 fprintf(Voutfile,"\tmovl\t$%d,%d(r0)", n_args+1 ,FO_SIZE);
00214 putcomment("# size of activation record");
00215 PUSH ("r0","# push function value");
00216 return;
00217 }
00218
00219
00220 putcomment ("# request new function object");
00221 FXD_NEWOBJ(FO_OBJ_SIZE);
00222 fprintf(Voutfile,"\tmovl\tap,%d(r0)",FO_EP);
00223 putcomment("# environment pointer");
00224 fprintf(Voutfile,"\tmovab\t%s,%d(r0)",p -> fc_code_label, FO_IP);
00225 putcomment("# instruction pointer");
00226
00227
00228
00229
00230 fprintf(Voutfile,"\tmovzwl\t$%d,%d(r0)",p -> ar_size,FO_SIZE);
00231 putcomment("# size of activation record");
00232 PUSH ("r0","# push function value");
00233
00234
00235 fc_add(p, Vlevel + 1, FALSE);
00236 }
00237
00238
00239
00240
00241
00242
00243 Vfuncbody(p, l)
00244 NODE * p;
00245 int l;
00246 {
00247 char * M1;
00248
00249
00250
00251
00252 Vcurrent = p;
00253 Ventry_mask = 0;
00254 Vgc_mask = 0;
00255 Vlevel = l;
00256
00257 fprintf(Voutfile,"\t.globl\t%s\n",p -> fc_code_label);
00258 M1 = Vnewlabel ("mask");
00259 CODE ("\t.align 1");
00260 fprintf(Voutfile,"%s:\t.word\t%s",p -> fc_code_label,M1);
00261 putcomment("# code body");
00262
00263 if (Vlevel == 0) {
00264
00265 fprintf(Voutfile,"\tmovl\tap,%s\n", L0fp);
00266 Ventry_mask |= L0FP;
00267 }
00268
00269 if (Pflag) {
00270
00271 Vcall_mcount();
00272 }
00273
00274 if (Tflag) {
00275
00276 Ventry_trace(p -> fc_code_label,
00277 p -> signature -> fsig_param_list, FALSE);
00278 }
00279
00280
00281 Vexpression( p -> fc_body );
00282
00283
00284 if (Tflag) {
00285
00286 Vexit_trace();
00287 }
00288 POP ("r0","# function value to r0");
00289 fprintf(Voutfile,"\tret\n");
00290 fprintf(Voutfile,"\t.set\t%s,0x%x\n",M1,Ventry_mask);
00291
00292 if (Vlevel == 0) {
00293 CODE("\t.data");
00294 fprintf(Voutfile,"_entry_ar_sz:\t.long\t%d\n",p -> ar_size);
00295 CODE("\t.text");
00296 }
00297 }
00298
00299
00300
00301
00302 Vexpression (p)
00303 register NODE * p;
00304 {
00305 int i;
00306
00307 if (p -> signature -> kind == SIGNATURESIG) {
00308
00309 fprintf(Voutfile, "\tpushl\t$0\n");
00310 return;
00311 }
00312
00313 switch ( p -> kind ) {
00314
00315 case OPRID :
00316 case LETTERID :
00317 {
00318 register NODE * v;
00319 char * display_reg;
00320 char * r10 = "r10";
00321
00322 if (is_int_const(p)) {
00323 extern long int_const_val;
00324
00325 fprintf(Voutfile, "\tpushl\t$%d\n", int_const_val);
00326 return;
00327 }
00328
00329 v = p -> id_last_definition;
00330 if (p -> sel_type == NIL) {
00331 ASSERT2 (v != NIL, "Vexpression: id %s not declared\n",
00332 getname(p -> id_str_table_index)
00333 );
00334 ASSERT2 (v -> kind == DECLARATION
00335 || v -> kind == PARAMETER
00336 || v -> kind == MODPRIMARY
00337 && v -> mp_type_modifier -> kind == WITHLIST,
00338 "Vexpression: id %x not declaration or parameter\n",v
00339 );
00340 putcomment1("\t\t\t# Identifier %s",
00341 getname(p -> id_str_table_index));
00342 DISPLAY ( display_reg, v -> level, r10,
00343 "# display entry in place");
00344 if (display_reg == r10) Ventry_mask |= R10;
00345 if (v -> kind == DECLARATION
00346 && (v -> decl_special & VAR_ON_STACK)) {
00347 fprintf(Voutfile, "\tmoval\t%d(%s),-(sp)\n",
00348 4 * v->displacement, display_reg);
00349 } else {
00350 PUSH_DISP (display_reg, v->displacement,
00351 "# referenced object");
00352 }
00353 }
00354 else {
00355 putcomment1("\t\t\t# Selection of %s",
00356 getname(p->id_str_table_index));
00357 Vexpression (p -> sel_type);
00358 POP ("r0","# type value to r0");
00359 PUSH_DISP ("r0",p -> sel_index,
00360 "# push selected function value");
00361 }
00362 if (p -> id_forward_ref) {
00363
00364 fprintf(Voutfile, "\tcmpl\t(sp),$0x%X\t #---\n",
00365 UNDEF);
00366 fprintf(Voutfile, "\tbneq\t1f\t #---\n");
00367 fprintf(Voutfile,
00368 "\tcalls\t$0,_forward_error\t #---\n");
00369 fprintf(Voutfile, "1:\n");
00370 }
00371 break;
00372 }
00373
00374 case QSTR:
00375 case UQSTR:
00376 {
00377 NODE * sig = p -> sel_type -> signature;
00378 int maxlen;
00379
00380 boolean know_inline;
00381
00382
00383 ASSERT(sig -> kind == TYPESIGNATURE,
00384 "codegen: bad string type\n");
00385 if (sig -> ts_string_max == -1) {
00386 maxlen = MAXSTRLEN;
00387 } else {
00388 maxlen = sig -> ts_string_max;
00389 }
00390 know_inline = (sig -> ts_string_code != NIL
00391 && sig -> ts_element_code != NIL
00392 && strlen(p -> str_string) <= maxlen);
00393 if (know_inline
00394 && ! calls_put(p -> sel_type)) {
00395
00396 char *r = p -> str_string;
00397 char *q = str_code_buf;
00398
00399 *q = '\0';
00400 while (*r != '\0') {
00401 sprintf(q, sig -> ts_element_code, *r);
00402
00403 q += strlen(q);
00404 r++;
00405 }
00406 fprintf(Voutfile, sig -> ts_string_code, str_code_buf);
00407 fprintf(Voutfile, "\n");
00408 } else {
00409
00410 Vexpression(p -> str_expansion);
00411 }
00412 }
00413 break;
00414
00415 case APPLICATION :
00416 Vappl(p);
00417 break;
00418
00419 case BLOCKDENOTATION :
00420 {
00421 if ( p -> bld_flags & REQUIRES_AR ) {
00422
00423
00424
00425
00426 Vlevel++;
00427 FXD_NEWOBJ(p -> ar_size);
00428 CODE("\tmovl\tap,(r0)");
00429 CODE("\tmovl\tr0,ap");
00430 }
00431
00432
00433 maplist (v, p -> bld_declaration_list, {
00434 ASSERT (v->kind == DECLARATION,
00435 "codegen.c: decl expected");
00436 if (v -> decl_needed &&
00437 v -> decl_can_be_refd <= v -> pre_num) {
00438
00439 fprintf(Voutfile,"\tmovl\t$0x%X,%d(ap)\t #---\n",
00440 UNDEF, ObjSize * (v -> displacement));
00441 putcomment("# store undefined value");
00442 }
00443 });
00444 maplist (v, p -> bld_declaration_list, {
00445 if (!v -> decl_needed) {
00446
00447
00448
00449 Vtraverse (v -> decl_denotation);
00450 } else {
00451 if (!(v -> decl_special & VAR_ON_STACK)) {
00452 Vexpression (v-> decl_denotation);
00453 POP_DISP ("ap",v->displacement,
00454 "# store declared value");
00455 } else {
00456
00457 if (v -> decl_special & SIMPLE_VAR_ON_STACK) {
00458 fprintf(Voutfile,"\tmovl\t$0,%d(ap)\n",
00459 4 * v->displacement);
00460 } else if (v -> decl_special & PTR_VAR_ON_STACK) {
00461 fprintf(Voutfile,"\tmovl\t$%d,%d(ap)\n",
00462 UNDEF, 4 * v->displacement);
00463 } else {
00464 NODE * appl = v -> decl_denotation;
00465 NODE * arg = first(appl -> ap_args);
00466
00467 ASSERT(appl -> kind == APPLICATION,
00468 "codegen.c: bad New application");
00469 Vexpression (arg);
00470 POP_DISP ("ap",v->displacement,
00471 "# store initial value");
00472 }
00473 }
00474 }
00475 });
00476 maplist (v,p->bld_den_seq, {
00477 Vexpression(v);
00478 if (v != last(p -> bld_den_seq)) {
00479 POP ("r0","# trash value");
00480 }
00481 });
00482 if ( p -> bld_flags & REQUIRES_AR ) {
00483 Vlevel--;
00484 CODE("\tmovl\t(ap),ap");
00485 }
00486 break;
00487 }
00488
00489 case GUARDEDLIST :
00490 case LOOPDENOTATION :
00491 {
00492 char * L0;
00493 register NODE * v;
00494
00495 if (p->kind == LOOPDENOTATION) {
00496 L0=Vnewlabel("loop");
00497 fprintf(Voutfile,"%s:\n",L0);
00498 }
00499 else {
00500 L0=Vnewlabel("guard_exit");
00501 }
00502 maplist (v,p->gl_list, {
00503 char * L1;
00504
00505 ASSERT (v->kind == GUARDEDELEMENT,
00506 "codegen.c: bad guard list");
00507 Vexpression(v->ge_guard);
00508 L1 = Vnewlabel ("guard");
00509 POP ("r0","# value of guard");
00510 fprintf(Voutfile,"\tjeql\t%s", L1);
00511 putcomment ("# branch on false");
00512 Vexpression(v->ge_element);
00513 if (p -> kind == LOOPDENOTATION) {
00514 POP("r0","# trash element value");
00515 } else {
00516
00517 }
00518 fprintf(Voutfile,"\tjbr\t%s",L0);
00519 putcomment ("# leave guarded list");
00520 fprintf(Voutfile,"%s:",L1);
00521 putcomment ("# next case");
00522 });
00523 if (p -> kind == LOOPDENOTATION) {
00524 PUSH ("$0","# Value of loop or default of else is void");
00525 } else {
00526 fprintf(Voutfile,"\tcalls\t$0,_cond_error\n");
00527 }
00528 if (p->kind == GUARDEDLIST) {
00529 fprintf (Voutfile,"%s:\n",L0);
00530 }
00531 break;
00532 }
00533 case WORDELSE :
00534 {
00535 PUSH ("$1","# Else = constant 1");
00536 break;
00537 }
00538
00539
00540 case FUNCCONSTR :
00541 {
00542 Vfuncconstructor (p);
00543 break;
00544 }
00545
00546 case REXTERNDEF :
00547 {
00548 int name_length = strlen(p -> r_ext_name);
00549 char *q;
00550
00551 if (name_length + 3 > MAXSTRCODELEN) {
00552 errmsg0(p, "File name too long");
00553 }
00554 strcpy(str_code_buf, p -> r_ext_name);
00555 str_code_buf[name_length] = '.';
00556 str_code_buf[name_length+1] = 'o';
00557 str_code_buf[name_length+2] = 0;
00558 add_objfile(str_code_buf);
00559
00560 strcpy(str_code_buf, p -> r_ext_name);
00561
00562 for (q = str_code_buf; *q != '\0'; q++) {
00563 if (*q == '/') {
00564 *q = '.';
00565 }
00566 }
00567 fprintf(Voutfile, "\t.globl\tm_%s\n", str_code_buf);
00568 fprintf(Voutfile, "\tjsb\tm_%s\n", str_code_buf);
00569 fprintf(Voutfile, "\tpushl\tr0\n");
00570 break;
00571 }
00572
00573 case USELIST :
00574 {
00575 maplist (v,p->usl_den_seq, {
00576 Vexpression(v);
00577 if (v != last(p -> usl_den_seq)) {
00578 POP ("r0","# trash value");
00579 }
00580 });
00581 break;
00582 }
00583
00584
00585 case MODPRIMARY :
00586 {
00587 NODE * tm = p -> mp_type_modifier;
00588 unsigned * delv = (unsigned *)p -> mp_delete_v;
00589 int orig = p -> mp_orig_length;
00590 int final = 0;
00591 int i,j;
00592 int res_pos;
00593
00594 DECLARE_ITER;
00595 NODE *s;
00596
00597
00598 int *q;
00599 int skipcnt;
00600 int copycnt;
00601 boolean is_wl = (tm == NIL? FALSE
00602 : (tm -> kind == WITHLIST));
00603 int wl_length;
00604
00605 if (is_wl) {
00606 wl_length = length(tm -> wl_component_list);
00607 } else {
00608 wl_length = 0;
00609 }
00610
00611 if (orig > 0) {
00612 q = (int *)delv; i = 0; j = *q;
00613 while (i < orig) {
00614 if (j >= 0) final++;
00615 i++; j <<= 1;
00616 if (i % WORDLENGTH == 0) {
00617 j = *(++q);
00618 }
00619 }
00620 }
00621 final += wl_length;
00622 if (final == 0) {
00623 CODE("\tclrl\t-(sp)");
00624 } else {
00625 Vexpression(p -> mp_primary);
00626 putcomment("# Get type object");
00627 FXD_NEWOBJ(final);
00628 CODE("\tclrl\t(r0)");
00629
00630
00631
00632
00633 Ventry_mask |= R10;
00634 POP("r10", "# original type");
00635 PUSH("r0", "# new type");
00636
00637
00638 if (is_wl && !is_empty(tm->wl_component_list)) {
00639 INIT_ITER(s, tm -> wl_component_list);
00640 } else {
00641 s = NIL;
00642 }
00643 q = (int *)delv; i = res_pos = 0;
00644 j = (orig > 0? *q : 0);
00645 skipcnt = 0; copycnt = 0;
00646 while (s != NIL || i < orig) {
00647
00648
00649
00650
00651
00652
00653
00654 if (s != NIL && s -> decl_sel_index == res_pos) {
00655
00656 copy_r10_to_r0(copycnt);
00657 copycnt = 0;
00658 fprintf(Voutfile,"\tclrl\t(r0)+");
00659 putcomment("# space for with list component");
00660 res_pos++;
00661 NEXT_ITER(s);
00662 continue;
00663 } else if (j >= 0) {
00664
00665 if (skipcnt != 0) {
00666 fprintf(Voutfile,"\taddl2\t$%d,r10",
00667 4*skipcnt);
00668 putcomment("# skip slots");
00669 skipcnt = 0;
00670 }
00671 copycnt++;
00672 res_pos++;
00673 i++; j <<= 1;
00674 } else {
00675
00676 copy_r10_to_r0(copycnt);
00677 copycnt = 0;
00678 skipcnt++;
00679 i++; j <<= 1;
00680 }
00681 if (i % WORDLENGTH == 0) {
00682 j = *(++q);
00683 }
00684 }
00685
00686 copy_r10_to_r0(copycnt);
00687 copycnt = 0;
00688
00689
00690 if (is_wl) {
00691 char * display_reg;
00692
00693 char * r10 = "r10";
00694 NODE * decl_l = (LIST)
00695 decl_sort(p -> mp_type_modifier
00696 -> wl_component_list);
00697
00698
00699
00700 char * nt_tmp;
00701 boolean in_memory;
00702
00703
00704
00705 nt_tmp = Vnewreg();
00706 in_memory = (Vreg_bit == 0);
00707 fprintf(Voutfile, "\tmovl\t(sp),%s", nt_tmp);
00708 putcomment("# new type to temporary");
00709
00710 DISPLAY (display_reg, p -> level, r10,
00711 "# display entry for wlc");
00712 if (display_reg == r10) Ventry_mask |= R10;
00713 fprintf(Voutfile, "\tmovl\t%s,%d(%s)",
00714 nt_tmp,
00715 4 * (p -> displacement),
00716 display_reg);
00717 putcomment("# save for local id references");
00718
00719
00720
00721 maplist (v, decl_l, {
00722 ASSERT (v -> kind == DECLARATION,
00723 "codegen.c: decl expected");
00724 if (v -> decl_can_be_refd <= v -> pre_num) {
00725
00726 if (in_memory) {
00727 fprintf(Voutfile,
00728 "\tmovl\t%s,r0\t #---\n", nt_tmp);
00729 }
00730 fprintf(Voutfile,
00731 "\tmovl\t$0x%X,%d(%s)\t #---",
00732 UNDEF,
00733 ObjSize * (v -> decl_sel_index),
00734 in_memory? "r0" : nt_tmp);
00735 putcomment("# store undefined value");
00736 }
00737 });
00738
00739 maplist(s, decl_l, {
00740 Vexpression(s -> decl_denotation);
00741 if (in_memory) {
00742 fprintf(Voutfile, "\tmovl\t%s,r0\n", nt_tmp);
00743 POP_DISP("r0", s -> decl_sel_index,
00744 "# store with list component");
00745 } else {
00746 POP_DISP(nt_tmp, s -> decl_sel_index,
00747 "# store with list component");
00748 }
00749 });
00750 Vretreg(nt_tmp);
00751 }
00752
00753 }
00754 break;
00755 }
00756
00757 case RECORDCONSTRUCTION:
00758 {
00759 int n_components = length(p -> rec_component_list);
00760 int i;
00761
00762
00763
00764
00765 if (3 * n_components > MAXOBJSZ) {
00766 errmsg0(p, "Record too big\n");
00767 }
00768 putcomment ("# request pseudo-environment object");
00769 FXD_NEWOBJ(3 * n_components);
00770 CODE("\tclrl\t(r0)");
00771
00772
00773 CODE("\tpushl\tr0");
00774
00775 maprlist(p -> rec_component_list, type_expr);
00776
00777 i = 0;
00778 maplist(s, p -> rec_component_list, {
00779 fprintf(Voutfile, "\tmovl\t(sp)+,r1");
00780 putcomment("# get component type");
00781 fprintf(Voutfile, "\tmovl\t%d(r1),(r0)+",
00782 4 * (s -> re_assign_index));
00783 putcomment("# component := operator");
00784 fprintf(Voutfile, "\tmovl\t%d(r1),(r0)+",
00785 4 * (s -> re_New_index));
00786 putcomment("# component New operator");
00787 fprintf(Voutfile, "\tmovl\t%d(r1),(r0)+",
00788 4 * (s -> re_ValueOf_index));
00789 putcomment("# component ValueOf operator");
00790 });
00791
00792
00793 }
00794
00795 case PRODCONSTRUCTION :
00796 case UNIONCONSTRUCTION :
00797 case ENUMERATION:
00798 {
00799 NODE * clist = p -> signature -> ts_clist;
00800 int len = tsig_length(p -> signature);
00801
00802 if (len > MAXOBJSZ) {
00803 errmsg0(p, "Constructed type too big");
00804 }
00805
00806 putcomment ("# request new type object");
00807 FXD_NEWOBJ(len);
00808
00809
00810 CODE("\tpushl\tr0");
00811 CODE("\tmovl\tr0,r2");
00812 Ventry_mask |= R2;
00813
00814
00815
00816 {
00817 NODE * dcs = first(clist);
00818
00819 ASSERT(dcs -> kind == DEFCHARSIGS,
00820 "codegen: type constr: bad DCS node\n");
00821 if (dcs -> dcs_exceptions != NIL) {
00822 maplist(s, dcs -> dcs_exceptions, {
00823 gen_special(s -> dcse_special);
00824 CODE("\tmovl\tr0,(r2)+");
00825 });
00826 }
00827 }
00828
00829 maplist(s, clist, {
00830 switch(s -> kind) {
00831 case TSCOMPONENT:
00832 gen_special(s -> tsc_signature -> fsig_special);
00833 CODE("\tmovl\tr0,(r2)+");
00834 break;
00835 IFDEBUG(
00836 case DEFCHARSIGS:
00837
00838 break;
00839 default:
00840 dbgmsg("codegen: bad type constr. sig\n");
00841 )
00842 }
00843 });
00844 if (p -> kind == RECORDCONSTRUCTION) {
00845
00846 fprintf(Voutfile,"\tmovl\t(sp)+,(sp)");
00847 putcomment(" # remove pseudo-environment");
00848 }
00849 break;
00850 }
00851
00852 case EXTENSION :
00853 {
00854 int len = tsig_length(p -> signature);
00855
00856 if (len > MAXOBJSZ) {
00857 errmsg0(p, "Constructed type too big");
00858 }
00859
00860 putcomment ("# request new extension type object");
00861 FXD_NEWOBJ(len);
00862 CODE("\tclrl\t(r0)");
00863
00864
00865 CODE("\tpushl\tr0");
00866
00867 Vexpression(p -> ext_denotation);
00868 fprintf(Voutfile, "\tmovl\t(sp)+,r3");
00869 putcomment("# Extension argument");
00870 Ventry_mask |= R3;
00871 Vgc_mask |= R3;
00872
00873 CODE("\tmovl\t(sp),r2");
00874 Ventry_mask |= R2;
00875
00876 gen_special(special(IDENTITY, 0));
00877
00878
00879
00880 Vgc_mask &= ~R3;
00881 ASSERT(p -> In_index < p -> Out_index,
00882 "Vexpression: bad In, Out indicees\n");
00883 copy_r3_to_r2(p -> In_index);
00884 fprintf(Voutfile, "\tmovl\tr0,(r2)+");
00885 putcomment("# In function");
00886 copy_r3_to_r2(p->Out_index - p->In_index - 1);
00887 fprintf(Voutfile, "\tmovl\tr0,(r2)+");
00888 putcomment("# Out function");
00889 copy_r3_to_r2(len - p->Out_index - 1);
00890
00891 break;
00892 }
00893
00894
00895 default :
00896 findvl( p -> vlineno );
00897
00898 dbgmsg( "Vexpression: Unimplemented construct (kind = %s) in file %s at line %d\n",
00899 kindname(p->kind), getname(getfn()), getrl() );
00900 dbgmsg( "Vexpression: p is 0x%x\n",p);
00901 fprintf( Voutfile, "?" );
00902 fflush (Voutfile);
00903 abort();
00904 }
00905 }
00906
00907
00908
00909
00910
00911
00912 gen_special(spcl)
00913 unsigned spcl;
00914 {
00915 char * routine_name;
00916 int n_args;
00917 boolean ep_on_stack = FALSE;
00918
00919
00920 switch(special_tp(spcl)) {
00921 case PROD_PROJ:
00922 case RECORD_VAL_FIELD:
00923 case RECORD_VAR_FIELD:
00924 routine_name = "_P_R_ith";
00925 n_args = 1;
00926 break;
00927
00928 case RECORD_MK:
00929 case PROD_MK:
00930 routine_name = "_P_R_Make";
00931 n_args = special_val(spcl);
00932 break;
00933
00934 case PROD_NEW:
00935 case UNION_NEW:
00936 routine_name = "_P_U_New";
00937 n_args = 0;
00938 break;
00939
00940 case RECORD_NEW:
00941 routine_name = "_Record_New";
00942 n_args = 0;
00943 ep_on_stack = TRUE;
00944 break;
00945
00946 case ENUM_NEW:
00947 routine_name = "_E_New";
00948 n_args = 0;
00949 break;
00950
00951 case PROD_ASSIGN:
00952 case UNION_ASSIGN:
00953 case ENUM_ASSIGN:
00954 routine_name = "_P_U_E_Assign";
00955 n_args = 2;
00956 break;
00957
00958 case RECORD_ASSIGN:
00959 routine_name = "_Record_Assign";
00960 n_args = 2;
00961 ep_on_stack = TRUE;
00962 break;
00963
00964 case PROD_VALUEOF:
00965 case UNION_VALUEOF:
00966 case ENUM_VALUEOF:
00967 routine_name = "_P_U_E_ValueOf";
00968 n_args = 1;
00969 break;
00970
00971 case RECORD_VALUEOF:
00972 routine_name = "_Record_ValueOf";
00973 n_args = 1;
00974 ep_on_stack = TRUE;
00975 break;
00976
00977 case UNION_PROJ:
00978 routine_name = "_Union_Proj";
00979 n_args = 1;
00980 break;
00981
00982 case UNION_INJ:
00983 routine_name = "_Union_Inj";
00984 n_args = 1;
00985 break;
00986
00987 case UNION_INQ:
00988 routine_name = "_Union_Inq";
00989 n_args = 1;
00990 break;
00991
00992 case ENUM_EQ:
00993 routine_name = "_Enum_eq";
00994 n_args = 2;
00995 break;
00996
00997 case ENUM_NE:
00998 routine_name = "_Enum_ne";
00999 n_args = 2;
01000 break;
01001
01002 case ENUM_ELEMENT:
01003 routine_name = "_Enum_Element";
01004 n_args = 0;
01005 break;
01006
01007 case ENUM_CARD:
01008 routine_name = "_Enum_Card";
01009 n_args = 0;
01010 break;
01011
01012 case ENUM_PRED:
01013 routine_name = "_Enum_Pred";
01014 n_args = 1;
01015 break;
01016
01017 case ENUM_SUCC:
01018 routine_name = "_Enum_Succ";
01019 n_args = 1;
01020 break;
01021
01022 case IDENTITY:
01023 routine_name = "_Identity";
01024 n_args = 1;
01025 break;
01026
01027 # ifdef DEBUG
01028 default:
01029 dbgmsg("gen_special: Unknown special function\n");
01030 # endif
01031 }
01032
01033 putcomment ("# request new function object");
01034 FXD_NEWOBJ(FO_OBJ_SIZE);
01035 if (!ep_on_stack) {
01036
01037 fprintf(Voutfile,"\tmovl\t$%d,%d(r0)",special_val(spcl), FO_EP);
01038 } else {
01039 fprintf(Voutfile,"\tmovl\t4(sp),%d(r0)", FO_EP);
01040 }
01041 putcomment("# dummy environment pointer");
01042
01043 fprintf(Voutfile,"\t.globl\t%s\n", routine_name);
01044 fprintf(Voutfile,"\tmovab\t%s,%d(r0)",routine_name, FO_IP);
01045 putcomment("# instruction pointer");
01046
01047 fprintf(Voutfile,"\tmovzwl\t$%d,%d(r0)", n_args + 1, FO_SIZE);
01048 putcomment("# size of activation record");
01049 }
01050
01051
01052
01053
01054
01055 copy_r10_to_r0(copycnt)
01056 int copycnt;
01057 {
01058 # ifdef EXTENDED_RANGE
01059 while (copycnt >= 4) {
01060 CODE("\tmovo\t(r10)+,(r0)+");
01061 copycnt -= 4;
01062 }
01063 # endif
01064 while (copycnt >= 2) {
01065 CODE("\tmovq\t(r10)+,(r0)+");
01066 copycnt -= 2;
01067 }
01068 while (copycnt >= 1) {
01069 CODE("\tmovl\t(r10)+,(r0)+");
01070 copycnt -= 1;
01071 }
01072 }
01073
01074
01075 copy_r3_to_r2(copycnt)
01076 int copycnt;
01077 {
01078 # ifdef EXTENDED_RANGE
01079 while (copycnt >= 4) {
01080 CODE("\tmovo\t(r3)+,(r2)+");
01081 copycnt -= 4;
01082 }
01083 # endif
01084 while (copycnt >= 2) {
01085 CODE("\tmovq\t(r3)+,(r2)+");
01086 copycnt -= 2;
01087 }
01088 while (copycnt >= 1) {
01089 CODE("\tmovl\t(r3)+,(r2)+");
01090 copycnt -= 1;
01091 }
01092 }
01093
01094
01095
01096
01097 char * Vspcl_to_inline(spcl)
01098 unsigned spcl;
01099 {
01100 # define MAX_PROD_EXP_LEN 5
01101 int tp = special_tp(spcl);
01102 int val = special_val(spcl);
01103 int i;
01104 char * result;
01105
01106 switch(tp) {
01107 case PROD_NEW:
01108 case UNION_NEW:
01109 sprintf(str_code_buf, "\tmovl\t_objfreelist+4,r0\n\tjneq\t1f\n\tmovl\t$0x%%X,r11\n\tpushl\t$1\n\tcalls\t$1,_allocobj\n1:\tmovl\t(r0),_objfreelist+4\n\tmovl\t$0x%X,(r0)\n\tpushl\tr0", UNDEF);
01110 break;
01111 case ENUM_NEW:
01112 sprintf(str_code_buf, "\tmovl\t_objfreelist+4,r0\n\tjneq\t1f\n\tmovl\t$0x%%X,r11\n\tpushl\t$1\n\tcalls\t$1,_allocobj\n1:\tmovl\t(r0),_objfreelist+4\n\tmovl\t$0,(r0)\n\tpushl\tr0", 0);
01113 break;
01114 case PROD_ASSIGN:
01115 case UNION_ASSIGN:
01116 case ENUM_ASSIGN:
01117 return("\tmovl\t4(sp),*(sp)+");
01118 case PROD_VALUEOF:
01119 case UNION_VALUEOF:
01120 case ENUM_VALUEOF:
01121 return("\tmovl\t*(sp),(sp)");
01122 case PROD_MK:
01123 if (val > MAX_PROD_EXP_LEN) return(NIL);
01124 sprintf(str_code_buf, "\tmovl\t_objfreelist+%d,r0\n\tjneq\t1f\n\tpushl\t$%d\n\tmovl\t$0x%%X,r11\n\tcalls\t$1,_allocobj\n1:\tmovl\t(r0),_objfreelist+%d\n\tmovl\tr0,r1", 4*val, val, 4*val);
01125 for(i = 0; i < val; i++) {
01126 strcat(str_code_buf, "\n\tmovl\t(sp)+,(r1)+");
01127 }
01128 strcat(str_code_buf, "\n\tpushl\tr0");
01129 break;
01130 case PROD_PROJ:
01131 case RECORD_VAL_FIELD:
01132 case RECORD_VAR_FIELD:
01133 if (val == 0) {
01134 return("\tmovl\t*(sp),(sp)");
01135 } else {
01136 sprintf(str_code_buf, "\tmovl\t(sp),r0\n\tmovl\t%d(r0),(sp)",
01137 4*val);
01138 }
01139 break;
01140 case UNION_INJ:
01141 sprintf(str_code_buf, "\tmovl\t_objfreelist+8,r0\n\tjneq\t1f\n\tpushl\t$2\n\tmovl\t$0x%%X,r11\n\tcalls\t$1,_allocobj\n1:\tmovl\t(r0),_objfreelist+8\n\tmovl\t$%d,4(r0)\n\tmovl\t(sp),(r0)\n\tmovl\tr0,(sp)", val);
01142 break;
01143 case UNION_INQ:
01144 sprintf(str_code_buf, "\tmovl\t(sp)+,r0;\tcmpl\t4(r0),$%d #COMP jneq 4\n\tmovpsl\tr0\n\trotl\t$-2,r0,r0\n\tbicl3\t$0xfffffffe,r0,-(sp)", val);
01145 break;
01146 case UNION_PROJ:
01147 sprintf(str_code_buf, "\tmovl\t(sp),r0 #---\n\tcmpl\t$%d,4(r0) #---\n\tbeql\t1f #---\n\t.globl\t_union_err #---\n\tcalls\t$0,_union_err #---\n1:\tmovl\t*(sp),(sp)",val);
01148 break;
01149 case ENUM_EQ:
01150 sprintf(str_code_buf, "\tcmpl\t(sp)+,(sp)+ #COMP jneq 4\n\tmovpsl\tr0\n\trotl\t$-2,r0,r0\n\tbicl3\t$0xfffffffe,r0,-(sp)", val);
01151 break;
01152 case ENUM_NE:
01153 sprintf(str_code_buf, "\tcmpl\t(sp)+,(sp)+ #COMP jeql 4\n\tmovpsl\tr0\n\trotl\t$-2,r0,r0\n\tbicl3\tr0,$0x1,-(sp)", val);
01154 break;
01155 case ENUM_CARD:
01156 case ENUM_ELEMENT:
01157 sprintf(str_code_buf, "\tpushl\t$%d", val);
01158 break;
01159 case IDENTITY:
01160 return("# application of In, Out, Ord or OrdInv");
01161 case ENUM_PRED:
01162 return("\tdecl\t(sp)\n\tbgeq\t1f #---\n\t.globl\t_pred_error #---\n\tcalls\t$0,_pred_error #---\n1:\t\t #---");
01163 case ENUM_SUCC:
01164 sprintf(str_code_buf, "\tincl\t(sp)\n\tcmpl\t(sp),$%d #---\n\tbleq\t1f #---\n\t.globl\t_succ_error #---\n\tcalls\t$0,_succ_error #---\n1:\t\t #---",val);
01165 break;
01166 default:
01167 return(NIL);
01168 }
01169
01170 result = (char *) malloc(strlen(str_code_buf) + 1);
01171 strcpy(result, str_code_buf);
01172 return(result);
01173 }
01174
01175
01176 boolean mentions_r11(string)
01177 char *string;
01178 {
01179 register char * s;
01180
01181 s = string;
01182 while (*s != '\0') {
01183 if (*s++ == 'r') {
01184 if (*s == '1') {
01185 s++;
01186 if (*s == '1') {
01187 return(TRUE);
01188 }
01189 }
01190 }
01191 }
01192 return(FALSE);
01193 }
01194
01195
01196
01197 void type_expr(re)
01198 NODE * re;
01199 {
01200 Vexpression(re -> re_denotation);
01201 }