00001 #define DEBUG
00002
00003 #define VERBOSE
00004 #undef VERBOSE
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 # include "parm.h"
00019 # include <stdio.h>
00020 # include "stree/ststructs.mh"
00021 # include "codeutil.h"
00022 # include "../runtime/runtime.h"
00023 # include "pass3/is_local.h"
00024 # include "pass4/sigs.h"
00025
00026 # ifdef VERBOSE
00027 # define IFVERBOSE(x) x
00028 # else
00029 # define IFVERBOSE(x)
00030 # endif
00031
00032 extern FILE * Voutfile;
00033
00034 extern FILE * unparse_file;
00035
00036 extern NODE * insrtptr;
00037
00038 extern boolean has_externs;
00039
00040 extern boolean Tflag;
00041
00042 extern boolean Gflag;
00043
00044 extern boolean Vflag;
00045
00046 extern boolean Oflag;
00047
00048 extern unsigned indx_put;
00049
00050 static int Clevel = -1;
00051
00052 extern void add_objfile();
00053
00054 extern boolean is_int_const();
00055
00056 extern char * rindex();
00057
00058
00059
00060
00061 boolean eval_decl(p)
00062 NODE *p;
00063 {
00064 int decl_den_kind, decl_sig_kind;
00065 NODE * decl_sig;
00066 extern NODE * declerr;
00067 extern NODE * declsig();
00068
00069 if (has_externs && !is_descendant(p, insrtptr)) {
00070
00071 return(TRUE);
00072 }
00073 decl_sig = p -> decl_signature;
00074 if (decl_sig == NIL) {
00075 decl_sig = declsig(p);
00076 if (declerr != SUCCESS) return(TRUE);
00077 } else if (decl_sig == ERR_SIG) {
00078 return(TRUE);
00079 }
00080 decl_sig_kind = decl_sig -> kind;
00081 decl_den_kind = p -> decl_denotation -> kind;
00082 if (decl_sig_kind == VARSIGNATURE
00083 || decl_sig_kind == VALSIGNATURE
00084 || decl_sig_kind == FUNCSIGNATURE
00085 && decl_den_kind != FUNCCONSTR
00086 && (impure(p -> decl_signature)
00087 || calls_put(p -> decl_denotation))
00088 || decl_sig_kind == TYPESIGNATURE
00089 && calls_put(p -> decl_denotation)) {
00090 return(TRUE);
00091 } else {
00092 return(FALSE);
00093 }
00094 }
00095
00096
00097 void add_extracted_objfile(entry_name)
00098 char * entry_name;
00099 {
00100 char * filename = (char *) malloc(strlen(entry_name));
00101 char * p, *q;
00102
00103
00104 for(p = entry_name; *p != '_'; p++);
00105 p++;
00106 q = filename;
00107 while(*q++ = *p++);
00108
00109 p = rindex(filename, '.');
00110
00111 for (q = filename; q < p; q++) {
00112 if (*q == '.') {
00113 *q = '/';
00114 }
00115 }
00116 *(p+1) = 'o';
00117 *(p+2) = '\0';
00118
00119 if (filename[0] != '\0') {
00120 add_objfile(filename);
00121 }
00122 free(filename);
00123 }
00124
00125
00126 body_accessible(p)
00127 register NODE * p;
00128 {
00129 int Olevel = Clevel;
00130
00131 if (p -> fc_body_needed) return;
00132 Clevel = p -> ar_static_level;
00133 p -> fc_body_needed = TRUE;
00134 accessible(p -> fc_body);
00135 Clevel = Olevel;
00136 }
00137
00138
00139
00140 id_accessible(p)
00141 NODE *p;
00142 {
00143 if (!is_int_const(p)) {
00144 if (p -> sel_type != NIL) {
00145 accessible(p->sel_type);
00146 } else {
00147 # ifdef DEBUG
00148 int Olevel = Clevel;
00149 # endif
00150 NODE * def = p -> id_last_definition;
00151
00152
00153
00154 accessible(def);
00155 # ifdef DEBUG
00156 if (Clevel != Olevel) {
00157 dbgmsg("id_accessible: Clevel clobbered\n");
00158 abort(Clevel,Olevel);
00159 }
00160 # endif
00161 if (def -> kind == DECLARATION && def -> level != Clevel) {
00162 # ifdef VERBOSE
00163 unparse_file = stdout;
00164 printf("Non-local reference from level %d to ", Clevel);
00165 unparse(p);
00166 printf("\n");
00167 # endif
00168 def -> decl_special |= ID_IMPORTED;
00169 }
00170 }
00171 }
00172 }
00173
00174
00175 accessible(p)
00176 register NODE * p;
00177 {
00178 register NODE * v;
00179
00180 if (p == NIL) return;
00181 if (p -> kind == PARAMETER) return;
00182 if (p -> kind != DECLARATION
00183 && p -> signature -> kind == SIGNATURESIG) {
00184
00185 return;
00186 }
00187
00188 switch ( p -> kind ) {
00189
00190 case DECLARATION:
00191 if (p -> decl_needed) break;
00192 {
00193 int Olevel = Clevel;
00194 p -> decl_needed = TRUE;
00195 Clevel = p -> level;
00196 accessible(p -> decl_denotation);
00197 Clevel = Olevel;
00198 }
00199 break;
00200
00201 case BLOCKDENOTATION:
00202
00203 label_decls(p -> bld_declaration_list);
00204 maplist(v,p->bld_den_seq,accessible(v));
00205
00206
00207 maplist (v, p -> bld_declaration_list, {
00208 NODE * sig;
00209
00210 if (v -> decl_needed) {
00211 continue;
00212 }
00213 sig = v -> decl_denotation -> signature;
00214 if ((eval_decl(v) && !is_int_const(v -> decl_denotation))
00215 || Tflag
00216 && sig -> kind == TYPESIGNATURE
00217 && hascomp(sig, indx_put)) {
00218
00219
00220 accessible(v);
00221 }
00222 });
00223 break;
00224
00225 case APPLICATION:
00226 v = p -> ap_operator -> signature;
00227
00228 if (v -> fsig_inline_code == NIL
00229 && v -> fsig_construction != NIL) {
00230 v -> fsig_inline_code = v -> fsig_construction
00231 -> signature
00232 -> fsig_inline_code;
00233 }
00234 if (impure(v)
00235 && !is_id(p -> ap_operator)
00236 || calls_put(p -> ap_operator)) {
00237 # ifdef VERBOSE
00238 unparse_file = stdout;
00239 printf("Accessible operator (impure or put): ");
00240 unparse(p -> ap_operator);
00241 printf("\n");
00242 # endif
00243 accessible(p -> ap_operator);
00244 } else if (v -> fsig_inline_code == NIL) {
00245 if (Oflag && v -> fsig_construction != NIL) {
00246 map2lists(a, p -> ap_args,
00247 f, v -> fsig_construction -> signature -> fsig_param_list, {
00248 if (f -> par_only_def == NIL
00249 || is_real_def(f -> par_only_def)
00250 && comp_st(a, f -> par_only_def,
00251 NIL, NIL) == 0) {
00252 f -> par_only_def = a;
00253 } else {
00254 f -> par_only_def = MULTIPLE_DEFS;
00255
00256 }
00257 });
00258 }
00259 if (v -> fsig_construction != NIL &&
00260 (v -> fsig_slink_known ||
00261 (v -> fsig_construction -> fc_complexity & NO_SL))) {
00262 if (v -> fsig_construction -> fc_body -> kind
00263 == EXTERNDEF
00264 && v -> fsig_construction -> fc_body -> ext_name
00265 == NIL) {
00266
00267 add_extracted_objfile(v -> fsig_construction
00268 -> fc_code_label);
00269 } else {
00270 # ifdef VERBOSE
00271 printf("Accessible construction: %s,",
00272 v -> fsig_construction
00273 -> fc_code_label);
00274 if (v -> fsig_slink_known) {
00275 printf("Static link known\n");
00276 } else {
00277 printf("Simple construction\n");
00278 }
00279 # endif
00280
00281 v -> fsig_construction -> fc_complexity
00282 |= DIR_CALL;
00283
00284
00285 body_accessible(v -> fsig_construction);
00286 }
00287 } else {
00288 # ifdef VERBOSE
00289 unparse_file = stdout;
00290 if (v -> fsig_construction == NIL) {
00291 printf("Accessible operator (unknown constr): ");
00292 } else {
00293 printf("Accessible operator (unknown sl): ");
00294 }
00295 unparse(p -> ap_operator);
00296 printf("\n");
00297 # endif
00298 if (v -> fsig_construction != NIL
00299 && v -> fsig_construction -> fc_body -> kind
00300 == EXTERNDEF
00301 && v -> fsig_construction -> fc_body -> ext_name
00302 == NIL) {
00303
00304
00305
00306 add_extracted_objfile(v -> fsig_construction
00307 -> fc_code_label);
00308 }
00309 accessible(p -> ap_operator);
00310 }
00311 }
00312
00313
00314 {
00315 int s = special_tp(v -> fsig_special);
00316
00317 switch(s) {
00318 case RECORD_VALUEOF:
00319 case PROD_VALUEOF:
00320 case ENUM_VALUEOF:
00321 s = STD_VALUEOF;
00322 break;
00323 case RECORD_ASSIGN:
00324 case PROD_ASSIGN:
00325 case ENUM_ASSIGN:
00326 case STD_PASSIGN:
00327 case STD_MASSIGN:
00328 case STD_TASSIGN:
00329 s = STD_ASSIGN;
00330 break;
00331 }
00332 if (s == STD_VALUEOF || s == STD_ASSIGN) {
00333
00334 NODE * arg1 = first(p -> ap_args);
00335
00336 if (arg1 -> kind == LETTERID
00337 || arg1 -> kind == OPRID) {
00338 id_accessible(arg1);
00339 } else {
00340 accessible(arg1);
00341 }
00342 if (s == STD_ASSIGN) {
00343 accessible(second(p -> ap_args));
00344 }
00345 } else if (Oflag && Gflag
00346 && v -> fsig_inline_code != NIL) {
00347
00348
00349
00350 int argcount = 1;
00351
00352 maplist(s, p -> ap_args, {
00353 if ((s -> kind == LETTERID
00354 || s -> kind == OPRID)
00355 && s -> sel_type == NIL
00356 && s -> id_last_definition -> kind
00357 == DECLARATION) {
00358 NODE * sig = sig_structure(s -> signature);
00359
00360 if (sig -> kind == VARSIGNATURE
00361 && !(s -> id_last_definition -> decl_special
00362 & VAR_NONTR_REF)) {
00363 if (only_indirect_ref(v -> fsig_inline_code,
00364 argcount)) {
00365 id_accessible(s);
00366 } else {
00367 accessible(s);
00368 }
00369 } else {
00370 accessible(s);
00371 }
00372 } else {
00373 accessible(s);
00374 }
00375 argcount++;
00376 });
00377 } else {
00378 maplist(s,p->ap_args,accessible(s));
00379 }
00380 }
00381 break;
00382
00383 case LOOPDENOTATION:
00384 case GUARDEDLIST:
00385 maplist(v,p->gl_list,accessible(v));
00386 break;
00387
00388 case GUARDEDELEMENT:
00389 accessible(p->ge_guard);
00390 accessible(p->ge_element);
00391 break;
00392
00393 case OPRID:
00394 case LETTERID:
00395 if (p -> signature -> kind == VARSIGNATURE
00396
00397 && p -> id_last_definition -> kind == DECLARATION) {
00398
00399 if (Vflag) {
00400 printf("Direct reference to variable cell ");
00401 unparse_file = stdout;
00402 unparse(p);
00403 findvl(p -> vlineno);
00404 printf(" from line %d\n", getrl());
00405 }
00406 p -> id_last_definition -> decl_special |= VAR_NONTR_REF;
00407 }
00408 id_accessible(p);
00409 break;
00410
00411 case FUNCCONSTR:
00412 (p -> fc_complexity) |= NEED_CL;
00413
00414
00415 maplist(q, p -> signature -> fsig_param_list, {
00416 q -> par_only_def = MULTIPLE_DEFS;
00417 });
00418 if (p -> fc_body_needed) break;
00419 p -> fc_body_needed = TRUE;
00420 Clevel++;
00421 accessible(p -> fc_body);
00422 Clevel--;
00423 break;
00424
00425 case USELIST:
00426 maplist(q, p -> usl_den_seq, accessible(q));
00427 break;
00428
00429 case MODPRIMARY:
00430 {
00431 int Olevel = Clevel;
00432 # ifdef VERBOSE
00433 printf("Accessible type modification:\n");
00434 unparse_file = stdout;
00435 unparse(p);
00436 printf("\n");
00437 # endif
00438 if (p -> mp_needed) break;
00439 p -> mp_needed = TRUE;
00440 Clevel = p -> level;
00441 accessible(p -> mp_primary);
00442 if (p -> mp_type_modifier != NIL
00443 && p -> mp_type_modifier -> kind == WITHLIST) {
00444
00445 (void) label_wl(p);
00446 maplist (q, p -> mp_type_modifier -> wl_component_list, {
00447 IFVERBOSE(
00448 printf("Accessible wlc:\n");
00449 unparse_file = stdout;
00450 unparse(q -> decl_id);
00451 printf("\n");
00452 )
00453 accessible(q -> decl_denotation);
00454 });
00455 }
00456 Clevel = Olevel;
00457 }
00458 break;
00459
00460 case QSTR:
00461 case UQSTR:
00462 {
00463 NODE * sig = p -> sel_type -> signature;
00464 int maxlen;
00465
00466 ASSERT(sig -> kind == TYPESIGNATURE,
00467 "accessible: bad string type\n");
00468 if (sig -> ts_string_max == -1) {
00469 maxlen = MAXSTRLEN;
00470 } else {
00471 maxlen = sig -> ts_string_max;
00472 }
00473 if (sig -> ts_string_code != NIL
00474 && sig -> ts_element_code != NIL
00475 && strlen(p -> str_string) <= maxlen
00476 && ! calls_put(p -> sel_type)) {
00477
00478 } else {
00479 accessible(p -> str_expansion);
00480 }
00481 }
00482 break;
00483
00484 case ENUMERATION:
00485 case PRODCONSTRUCTION:
00486 case UNIONCONSTRUCTION:
00487
00488 break;
00489
00490 case WORDELSE:
00491 case EXTERNDEF:
00492 case REXTERNDEF:
00493 break;
00494
00495 case RECORDCONSTRUCTION:
00496 maplist(s, p -> rec_component_list, {
00497 accessible(s -> re_denotation);
00498 });
00499 break;
00500
00501 case EXTENSION:
00502 accessible(p -> ext_denotation);
00503 break;
00504
00505 case PARAMETER:
00506 case RECORDELEMENT:
00507 case FUNCSIGNATURE:
00508 case LISTHEADER:
00509 case VARSIGNATURE:
00510 case VALSIGNATURE:
00511 case TYPESIGNATURE:
00512 case TSCOMPONENT:
00513 case DEFCHARSIGS:
00514 case WITHLIST:
00515 case EXPORTLIST:
00516 case EXPORTELEMENT:
00517 case ALLCONSTANTS:
00518 case HIDELIST:
00519 case WORDCAND:
00520 case WORDCOR:
00521 default:
00522 dbgmsg("accessible: bad kind, kind = %d\n", p -> kind);
00523 abort();
00524
00525 };
00526 return;
00527 }
00528
00529 extern void Vexpression();
00530 extern void fc_add();
00531 extern int Vlevel;
00532
00533
00534
00535
00536
00537 Vtraverse(p)
00538 register NODE * p;
00539 {
00540 register NODE * v;
00541
00542 if (p == NIL) return;
00543
00544 switch ( p -> kind ) {
00545
00546 case BLOCKDENOTATION :
00547 {
00548 if ( p -> bld_flags & REQUIRES_AR ) {
00549 Vlevel++;
00550 }
00551 maplist (v, (LIST)decl_sort(p->bld_declaration_list), {
00552 ASSERT (v->kind == DECLARATION,
00553 "Vtraverse: decl expected");
00554 if (v -> decl_needed) {
00555 Vexpression (v-> decl_denotation);
00556 POP_DISP ("ap",v->displacement,
00557 "# store declared value");
00558 } else {
00559
00560
00561
00562 Vtraverse (v -> decl_denotation);
00563 }
00564 }
00565 );
00566 maplist (v,p->bld_den_seq, {
00567 Vtraverse(v);
00568 });
00569 if ( p -> bld_flags & REQUIRES_AR ) {
00570 Vlevel--;
00571 }
00572 break;
00573 }
00574
00575 case APPLICATION:
00576 Vtraverse(p -> ap_operator);
00577 maplist(v,p->ap_args,Vtraverse(v));
00578 break;
00579
00580 case LOOPDENOTATION:
00581 case GUARDEDLIST:
00582 maplist(v,p->gl_list,Vtraverse(v));
00583 break;
00584
00585 case GUARDEDELEMENT:
00586 Vtraverse(p->ge_guard);
00587 Vtraverse(p->ge_element);
00588 break;
00589
00590 case OPRID:
00591 case LETTERID:
00592 if (p -> sel_type != NIL) {
00593 Vtraverse(p->sel_type);
00594 }
00595 break;
00596
00597 case FUNCCONSTR:
00598 if (p -> fc_body_needed) {
00599 if (p -> fc_complexity & NO_SL) {
00600 fc_add(p, Vlevel+1, TRUE );
00601 } else {
00602 fc_add(p, Vlevel+1, FALSE);
00603 }
00604 } else {
00605 Vlevel++;
00606 Vtraverse(p -> fc_body);
00607 Vlevel--;
00608 }
00609 break;
00610
00611 case USELIST:
00612 maplist(q, p -> usl_den_seq, Vtraverse(q));
00613 break;
00614
00615 case MODPRIMARY:
00616 if (p -> mp_needed) {
00617 Vexpression(p);
00618 POP("r0", "# type modification value not used");
00619 } else {
00620 Vtraverse(p -> mp_primary);
00621 if (p -> mp_type_modifier != NIL
00622 && p -> mp_type_modifier -> kind == WITHLIST) {
00623 maplist (q, p -> mp_type_modifier -> wl_component_list, {
00624 Vtraverse(q -> decl_denotation);
00625 });
00626 }
00627 }
00628 break;
00629
00630 case ENUMERATION:
00631 case PRODCONSTRUCTION:
00632 case UNIONCONSTRUCTION:
00633
00634 break;
00635
00636 case QSTR:
00637 case UQSTR:
00638 Vtraverse(p -> sel_type);
00639
00640 break;
00641
00642 case WORDELSE:
00643 case EXTERNDEF:
00644 case REXTERNDEF:
00645 break;
00646
00647 case RECORDCONSTRUCTION:
00648 maplist(s, p -> rec_component_list, {
00649 Vtraverse(s -> re_denotation);
00650 });
00651 break;
00652
00653 case EXTENSION:
00654 Vtraverse(p -> ext_denotation);
00655 break;
00656
00657 case VALSIGNATURE:
00658 case VARSIGNATURE:
00659 case FUNCSIGNATURE:
00660 case TYPESIGNATURE:
00661 case SIGNATURESIG:
00662 break;
00663
00664 case RECORDELEMENT:
00665 case DECLARATION:
00666 case PARAMETER:
00667 case LISTHEADER:
00668 case TSCOMPONENT:
00669 case DEFCHARSIGS:
00670 case WITHLIST:
00671 case EXPORTLIST:
00672 case EXPORTELEMENT:
00673 case ALLCONSTANTS:
00674 case HIDELIST:
00675 case WORDCAND:
00676 case WORDCOR:
00677 default:
00678 dbgmsg("Vtraverse: bad kind, kind = %d\n", p -> kind);
00679 abort();
00680
00681 };
00682 return;
00683 }