00001 #define DEBUG
00002
00003 #define VERBOSE
00004 #undef VERBOSE
00005
00006 #define MAXFREEIDS 6
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 # include "parm.h"
00020 # include <stdio.h>
00021 # include "stree/ststructs.mh"
00022 # include "pass3/is_local.h"
00023 # include "codegen.h"
00024
00025 extern FILE * unparse_file;
00026
00027 extern boolean fflag;
00028
00029 extern boolean Vflag;
00030
00031 extern boolean Oflag;
00032
00033 extern boolean cflag;
00034
00035 static int nestlevel;
00036
00037 static NODE * current_fc;
00038
00039
00040 static NODE * current_free_ids;
00041
00042
00043 static int num_free_ids;
00044
00045 static boolean ar_refs;
00046
00047
00048 static boolean fast_calls;
00049
00050
00051 static boolean forward_refs;
00052
00053
00054
00055
00056
00057
00058 boolean needs_new_nonl(p)
00059 NODE *p;
00060 {
00061 boolean result;
00062
00063 switch(p -> kind) {
00064 case LETTERID:
00065 case OPRID:
00066 if (p -> sel_type == NIL) {
00067 if (p -> id_last_definition -> kind == DECLARATION
00068 && !(p -> id_last_definition -> decl_special
00069 & ID_IMPORTED)
00070 && p -> id_last_definition -> level < nestlevel) {
00071 result = TRUE;
00072 } else {
00073 result = FALSE;
00074 }
00075 } else {
00076 result = needs_new_nonl(p -> sel_type);
00077 }
00078 break;
00079 default:
00080 result = TRUE;
00081 }
00082 # ifdef VERBOSE
00083 printf("needs_new_nonl(");
00084 unparse_file = stdout;
00085 unparse(p);
00086 printf(") returning %d level = %d, id level = %d\n",
00087 result, nestlevel,
00088 p -> id_last_definition? p -> id_last_definition -> level : 0);
00089 # endif
00090 return(result);
00091 }
00092
00093
00094
00095
00096 add_id_fv(id)
00097 NODE *id;
00098 {
00099 boolean already_there;
00100
00101 if (id -> id_last_definition -> kind == DECLARATION
00102 && !(id -> id_last_definition -> decl_special & ID_IMPORTED)) {
00103
00104
00105 # ifdef VERBOSE
00106 printf("Discarding bogus global reference.\n");
00107 # endif
00108 return;
00109 }
00110 if (((current_fc -> fc_complexity) & NO_CONSTR) != 0
00111 && num_free_ids <= MAXFREEIDS
00112 && ! forward_refs) {
00113
00114
00115 already_there = FALSE;
00116 maplist(s, current_free_ids, {
00117 if (s -> id_last_definition -> pre_num
00118 == id -> id_last_definition -> pre_num)
00119 {
00120 already_there = TRUE;
00121 break;
00122 }
00123 });
00124 if (!already_there) {
00125 # ifdef VERBOSE
00126 printf("Adding non-local %s for fn %s\n",
00127 getname(id -> id_str_table_index),
00128 current_fc -> fc_code_label);
00129 # endif
00130 addright(current_free_ids, id);
00131 num_free_ids++;
00132 }
00133 }
00134 }
00135
00136
00137
00138
00139
00140
00141 cl_analyze(p, lst)
00142 register NODE * p;
00143 boolean lst;
00144 {
00145 NODE * v;
00146 int i;
00147
00148 if (p == NIL) return;
00149
00150 if (p -> signature -> kind == SIGNATURESIG) {
00151
00152 return;
00153 }
00154
00155 switch ( p -> kind ) {
00156 case LETTERID:
00157 case OPRID:
00158 if (p -> sel_type != NIL) {
00159 cl_analyze(p -> sel_type, FALSE);
00160 } else {
00161 if (!is_local(p, current_fc) &&
00162 (p -> id_last_definition -> level != 0)) {
00163 add_id_fv(p);
00164
00165 if (current_fc -> ar_static_level
00166 > (p -> id_last_definition -> level) + 1) {
00167
00168
00169
00170
00171
00172 if (p -> id_forward_ref) {
00173 forward_refs = TRUE;
00174 }
00175 } else {
00176
00177 if (p -> id_last_definition -> post_num
00178 > current_fc -> post_num) {
00179 forward_refs = TRUE;
00180 }
00181 }
00182 }
00183 }
00184 break;
00185
00186 case BLOCKDENOTATION :
00187 maplist (v, p->bld_declaration_list, {
00188 ASSERT (v->kind == DECLARATION,
00189 "cl_analyze: decl expected");
00190 cl_analyze(v-> decl_denotation, FALSE);
00191 });
00192 maplist (v,p->bld_den_seq, {
00193 if (v == last(p -> bld_den_seq)) {
00194 cl_analyze(v, lst);
00195 } else {
00196 cl_analyze(v, FALSE);
00197 }
00198 });
00199 break;
00200
00201 case USELIST:
00202 maplist(s, p -> usl_den_seq, {
00203 if (s == last(p -> usl_den_seq)) {
00204 cl_analyze(s, lst);
00205 } else {
00206 cl_analyze(s, FALSE);
00207 }
00208 });
00209 break;
00210
00211 case APPLICATION:
00212 {
00213 NODE * constr = p -> ap_operator -> signature
00214 -> fsig_construction;
00215
00216 if (lst && constr != NIL
00217 && constr -> pre_num == current_fc -> pre_num
00218 && constr -> pre_num != 0 ) {
00219 current_fc -> fc_complexity |= DIR_REC;
00220 # ifdef VERBOSE
00221 printf("Directly recursive:\n");
00222 unparse_file = stdout;
00223 unparse(p);
00224 printf("\nSetting recursion bit in %s (%d)\n",
00225 current_fc -> fc_code_label,
00226 current_fc -> pre_num);
00227 # endif
00228 }
00229
00230
00231 {
00232 extern boolean is_id();
00233 NODE * op_sig = p -> ap_operator -> signature;
00234 boolean is_ident = is_id(p -> ap_operator);
00235 boolean no_op_val =
00236 is_ident
00237 && (op_sig -> fsig_inline_code != NIL
00238 || (constr != NIL &&
00239 (constr -> ar_static_level == 1
00240 || constr -> fc_complexity & NO_SL)));
00241 if (!no_op_val) {
00242 if (is_ident
00243 && constr != NIL
00244 && op_sig -> fsig_slink_known) {
00245 if (constr -> ar_static_level > 1
00246 && (constr -> fc_complexity & SL_ACC)
00247 && !(constr -> fc_complexity & NO_SL)) {
00248
00249 if(!(constr -> fc_complexity & NEED_CL)
00250 || needs_new_nonl(p -> ap_operator)) {
00251
00252
00253
00254
00255
00256 # ifdef VERBOSE
00257 unparse_file = stdout;
00258 printf("\nfast call: ");
00259 unparse(p);
00260 printf("\n");
00261 # endif
00262 fast_calls = TRUE;
00263 } else {
00264
00265 cl_analyze(p -> ap_operator, FALSE);
00266 }
00267 }
00268 } else {
00269 cl_analyze(p -> ap_operator, FALSE);
00270 }
00271 }
00272 }
00273 }
00274 maplist(s, p -> ap_args, {
00275 cl_analyze(s, FALSE);
00276 });
00277 break;
00278
00279 case LOOPDENOTATION:
00280 maplist(v,p->gl_list, {
00281 cl_analyze(v, FALSE);
00282 });
00283 break;
00284
00285 case GUARDEDLIST:
00286 maplist(v,p->gl_list, {
00287 cl_analyze(v, lst);
00288 });
00289 break;
00290
00291 case GUARDEDELEMENT:
00292 cl_analyze(p -> ge_guard, FALSE);
00293 cl_analyze(p -> ge_element, lst);
00294 break;
00295
00296 case FUNCCONSTR:
00297 {
00298 NODE * old_fc = current_fc;
00299 NODE * old_free_ids = current_free_ids;
00300 int old_num_free_ids = num_free_ids;
00301 boolean old_ar_refs = ar_refs;
00302 boolean old_forward_refs = forward_refs;
00303 boolean old_fast_calls = fast_calls;
00304
00305 boolean need_closure;
00306 boolean cp_globals;
00307
00308 need_closure = ((p -> fc_complexity & NEED_CL) != 0);
00309
00310 current_fc = p;
00311 nestlevel = current_fc -> ar_static_level;
00312 current_free_ids = lock(emptylist());
00313 num_free_ids = 0;
00314 ar_refs = FALSE;
00315 forward_refs = FALSE;
00316 fast_calls = FALSE;
00317
00318 cl_analyze(p -> fc_body, TRUE);
00319
00320 cp_globals = ((p -> fc_complexity & NO_CONSTR)
00321 && (num_free_ids < MAXFREEIDS)
00322 && need_closure
00323 && !(p -> fc_complexity
00324 & (DIR_CALL | NESTED_AR_BLOCK))
00325 && !forward_refs
00326 && !fast_calls
00327 && p -> ar_static_level != 0);
00328 if (Vflag && forward_refs) {
00329 printf("%s contains embedded forward references\n",
00330 p -> fc_code_label);
00331 }
00332 if (Vflag && fast_calls) {
00333 printf("%s contains calls requiring static link\n",
00334 p -> fc_code_label);
00335 }
00336 if (cp_globals) {
00337 p -> fc_complexity |= CP_GLOBALS;
00338 p -> fc_free_vars = current_free_ids;
00339
00340 if (Vflag) {
00341 printf("%s closure contains copies of %d non-locals\n",
00342 p -> fc_code_label,
00343 length(current_free_ids));
00344 }
00345
00346
00347 maplist(s, current_free_ids, {
00348 if (s -> id_last_definition -> kind == DECLARATION
00349 && (s -> id_last_definition -> decl_special
00350 & VAR_ON_STACK)) {
00351 s -> id_last_definition -> decl_special
00352 &= ~VAR_ON_STACK;
00353 if (Vflag) {
00354 printf("\tForcing heap allocation of %s\n",
00355 getname(s -> id_str_table_index));
00356 }
00357 }
00358 });
00359 } else {
00360 if (current_free_ids != NIL) {
00361 vfree(unlock(current_free_ids));
00362 }
00363 }
00364 if (!ar_refs) {
00365 p -> fc_complexity |= NO_AR_REFS;
00366 }
00367
00368 if (cflag && !Oflag) {
00369 p -> fc_complexity &= (~NO_SL);
00370
00371 }
00372
00373 if (cp_globals) {
00374 ar_refs = old_ar_refs;
00375 } else if (!need_closure) {
00376 ar_refs |= old_ar_refs;
00377 } else {
00378 if (Vflag && old_fc != NIL) {
00379 printf("%s may need a.r. pointer for %s\n",
00380 p -> fc_code_label,
00381 old_fc -> fc_code_label);
00382 }
00383 ar_refs = TRUE;
00384 }
00385
00386 if (Vflag && !(p -> fc_complexity & SL_ACC)) {
00387 printf("%s contains no indirections through slink\n",
00388 p -> fc_code_label);
00389 }
00390
00391 current_fc = old_fc;
00392 if (current_fc != NIL) {
00393 nestlevel = current_fc -> ar_static_level;
00394 }
00395 current_free_ids = old_free_ids;
00396 num_free_ids = old_num_free_ids;
00397 forward_refs = old_forward_refs;
00398 fast_calls = old_fast_calls;
00399 break;
00400 }
00401
00402 case MODPRIMARY:
00403 cl_analyze(p -> mp_primary, FALSE);
00404 if (p -> mp_type_modifier != NIL
00405 && p -> mp_type_modifier -> kind == WITHLIST) {
00406 maplist (q, p -> mp_type_modifier -> wl_component_list, {
00407 cl_analyze(q -> decl_denotation, FALSE);
00408 });
00409 }
00410 break;
00411
00412 case ENUMERATION:
00413 case PRODCONSTRUCTION:
00414 case UNIONCONSTRUCTION:
00415
00416 break;
00417
00418 case QSTR:
00419 case UQSTR:
00420 {
00421 NODE * tsig = p -> sel_type -> signature;
00422
00423 ASSERT(tsig -> kind == TYPESIGNATURE,
00424 "cl_analyze: bad string type");
00425 if (tsig -> ts_string_code != NIL
00426 && tsig -> ts_element_code != NIL
00427 && strlen(p -> str_string) <= MAXSTRLEN) {
00428 break;
00429
00430 } else {
00431 cl_analyze(p -> str_expansion, lst);
00432 }
00433 break;
00434 }
00435
00436 case WORDELSE:
00437 break;
00438
00439 case EXTERNDEF:
00440 break;
00441
00442 case REXTERNDEF:
00443 break;
00444
00445 case RECORDCONSTRUCTION:
00446 maplist(s, p -> rec_component_list, {
00447 cl_analyze(s -> re_denotation, FALSE);
00448 });
00449 break;
00450
00451 case EXTENSION:
00452 cl_analyze(p -> ext_denotation, FALSE);
00453 break;
00454
00455 case RECORDELEMENT:
00456 case DECLARATION:
00457 case PARAMETER:
00458 case FUNCSIGNATURE:
00459 case LISTHEADER:
00460 case VARSIGNATURE:
00461 case VALSIGNATURE:
00462 case TYPESIGNATURE:
00463 case TSCOMPONENT:
00464 case DEFCHARSIGS:
00465 case WITHLIST:
00466 case EXPORTLIST:
00467 case EXPORTELEMENT:
00468 case ALLCONSTANTS:
00469 case HIDELIST:
00470 case WORDCAND:
00471 case WORDCOR:
00472 default:
00473 dbgmsg("cl_analyze: bad kind, kind = %d\n", p -> kind);
00474 abort();
00475
00476 };
00477 return;
00478 }