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 # include "../runtime/runtime.h"
00022
00023 # define UNDEF (HEAPLIM+1)
00024
00025 extern int yydebug;
00026 extern int yynerrs;
00027
00028 extern boolean Pflag;
00029 extern boolean Tflag;
00030 extern boolean Vflag;
00031 extern boolean hflag;
00032
00033 extern char * entry_name;
00034
00035 boolean mentions_r11();
00036
00037 void type_expr();
00038
00039 char str_code_buf[MAXSTRCODELEN];
00040
00041
00042
00043 extern int Ventry_mask,Vgc_mask;
00044 extern int Vlevel;
00045
00046 extern NODE * Vcurrent;
00047 extern FILE * Voutfile;
00048
00049 void Vexpression();
00050
00051
00052 Vappl(p)
00053 NODE *p;
00054 {
00055 register NODE *v;
00056 register int argcount;
00057 char * in_line;
00058 boolean stack_call;
00059 char * size_reg;
00060
00061 char * ar_reg;
00062
00063 boolean in_memory;
00064 NODE * construction = p -> ap_operator -> signature
00065 -> fsig_construction;
00066 boolean slink_known;
00067
00068
00069
00070 NODE * result_sig = p -> signature;
00071 NODE * op_sig = p -> ap_operator -> signature;
00072 int op_kind = p -> ap_operator -> kind;
00073 long op_special = op_sig -> fsig_special;
00074 extern boolean is_id();
00075 boolean op_is_id = is_id(p -> ap_operator);
00076 boolean appl_impure = impure(op_sig);
00077 boolean op_impure = (appl_impure && !op_is_id)
00078 || calls_put(p -> ap_operator);
00079 int i;
00080
00081
00082
00083 switch (special_tp(op_special)) {
00084 case STD_VALUEOF:
00085 {
00086 NODE * arg = first(p -> ap_args);
00087
00088 if (arg -> kind == LETTERID
00089 && arg -> id_last_definition -> kind == DECLARATION
00090 && (arg -> id_last_definition -> decl_special & VAR_ON_STACK)) {
00091 register NODE * v;
00092 char * r10 = "r10";
00093 char * display_reg;
00094
00095 v = arg -> id_last_definition;
00096 putcomment1("\t\t\t# Value of Identifier %s",
00097 getname(arg -> id_str_table_index));
00098 DISPLAY ( display_reg, v -> level, r10,
00099 "# display entry in place");
00100 if (display_reg == r10) Ventry_mask |= R10;
00101 PUSH_DISP (display_reg, v->displacement,
00102 "# referenced object");
00103 return;
00104 } else {
00105 break;
00106 }
00107 }
00108 case ARRAY_VALUEOF:
00109 if (Vflag) {
00110 printf("Using fast array ValueOf inside %s\n",
00111 Vcurrent -> fc_code_label);
00112 }
00113 Vexpression(first(p -> ap_args));
00114 SET_GC_INFO;
00115 CODE("\t.globl\t_fast_Array_ValueOf");
00116 CODE("\tcalls\t$1,_fast_Array_ValueOf");
00117 CODE("\tpushl\tr0\n");
00118 return;
00119 case ARRAY_STD_NEW:
00120 case ARRAY_PTR_NEW:
00121 {
00122 long size_val = special_val(op_special);
00123 NODE * sel_type_sig;
00124 NODE * size_sig;
00125 NODE * size_appl;
00126 NODE * size_id;
00127 extern NODE * id_size;
00128 NODE * op = p -> ap_operator;
00129
00130 if (size_val == 0) {
00131
00132
00133 if (op_kind != LETTERID || op -> sel_type == NIL) {
00134 break;
00135 }
00136 sel_type_sig = op -> sel_type -> signature;
00137 size_sig = getcomp(sel_type_sig, id_size, NIL, NIL,
00138 NIL, NIL, NIL, FALSE);
00139 if (size_sig == NIL || special_tp(size_sig -> fsig_special)
00140 != ARRAY_SIZE) {
00141
00142 break;
00143 }
00144
00145 size_id = copynode(id_size);
00146 initfld(&(size_id -> sel_type), op -> sel_type);
00147 size_id -> id_def_found = TRUE;
00148 size_appl = mknode(APPLICATION, size_id, emptylist());
00149 tl_findsig(size_appl, FALSE);
00150 Vappl(size_appl);
00151 } else {
00152
00153 fprintf(Voutfile, "\tpushl\t$%d\n", size_val);
00154 }
00155 SET_GC_INFO;
00156 switch(special_tp(op_special)) {
00157 case ARRAY_STD_NEW:
00158 if (Vflag) {
00159 printf("Using fast standard array allocation inside %s\n",
00160 Vcurrent -> fc_code_label);
00161 }
00162 CODE("\t.globl\t_fast_Array_New");
00163 CODE("\tcalls\t$1,_fast_Array_New");
00164 break;
00165 case ARRAY_PTR_NEW:
00166 if (Vflag) {
00167 printf("Using fast pointer array allocation inside %s\n",
00168 Vcurrent -> fc_code_label);
00169 }
00170 CODE("\t.globl\t_fast_ptr_Array_New");
00171 CODE("\tcalls\t$1,_fast_ptr_Array_New");
00172 break;
00173 }
00174 CODE("\tpushl\tr0");
00175 return;
00176 }
00177 }
00178
00179 in_line = op_sig -> fsig_inline_code;
00180
00181 if (op_impure) {
00182 # ifdef VERBOSE
00183 printf("Clearing inline code\n");
00184 # endif
00185 in_line = NIL;
00186 }
00187 if (in_line == NIL) {
00188 switch(result_sig -> kind) {
00189 case TYPESIGNATURE:
00190 stack_call = FALSE;
00191 break;
00192 case FUNCSIGNATURE:
00193 stack_call = FALSE;
00194 break;
00195 case VALSIGNATURE:
00196 # ifdef DEBUG
00197 if (!has_sig(result_sig -> val_denotation)) {
00198 dbgmsg("codegen: Missing res. type signature\n");
00199 prtree(p);
00200 abort();
00201 }
00202 # endif
00203 stack_call = result_sig -> val_denotation
00204 -> signature -> ts_simple_type;
00205 break;
00206 case VARSIGNATURE:
00207 # ifdef DEBUG
00208 if (!has_sig(result_sig -> val_denotation)) {
00209 dbgmsg("codegen: Missing res. type signature\n");
00210 prtree(p);
00211 abort();
00212 }
00213 # endif
00214 stack_call = result_sig -> var_denotation
00215 -> signature -> ts_simple_type;
00216 break;
00217 }
00218
00219 if (appl_impure) {
00220 stack_call = FALSE;
00221 }
00222
00223 maplist(q, p -> ap_args, {
00224 NODE * sig = q -> signature;
00225 if (sig -> kind == VARSIGNATURE) {
00226 ASSERT (has_sig(sig -> var_denotation),
00227 "Missing argument type signature");
00228 if (!sig -> var_denotation -> signature
00229 -> ts_simple_type) {
00230 stack_call = FALSE;
00231 }
00232 }
00233 });
00234 }
00235 if (construction != NIL) {
00236 stack_call = stack_call
00237 || (construction -> fc_complexity & NO_SL)
00238 || (construction -> fc_complexity & NO_CONSTR);
00239 }
00240 if (hflag) {
00241 stack_call = FALSE;
00242 }
00243 if (in_line != NIL) {
00244 maprlist(p -> ap_args, Vexpression);
00245
00246 if(mentions_r11(in_line)) {
00247 Ventry_mask |= R11;
00248 }
00249 fprintf(Voutfile,
00250 in_line,
00251 Vgc_mask << 16, Vgc_mask << 16);
00252 fprintf(Voutfile, "\n");
00253 } else {
00254 if (stack_call & Vflag) {
00255 printf("Function %s calls ", Vcurrent -> fc_code_label);
00256 if (construction == NIL) {
00257 extern FILE * unparse_file;
00258
00259 unparse_file = stdout;
00260 unparse(p -> ap_operator);
00261 } else {
00262 printf("%s", construction -> fc_code_label);
00263 }
00264 printf(" with stack a.r.\n");
00265 }
00266 if (construction != NIL) {
00267 slink_known = p -> ap_operator -> signature
00268 -> fsig_slink_known;
00269 }
00270 if (construction == NIL
00271 || (!slink_known && !(construction -> fc_complexity & NO_SL))) {
00272 Vexpression (p -> ap_operator);
00273 } else if (op_impure) {
00274
00275 Vexpression (p -> ap_operator);
00276 POP ("r0", "# clobber unneeded function value");
00277 } else {
00278
00279 Vtraverse (p -> ap_operator);
00280 }
00281 argcount = length(p -> ap_args);
00282 if (!stack_call) {
00283
00284 if (construction != NIL && slink_known) {
00285 FXD_NEWOBJ(construction -> ar_size);
00286 } else {
00287 fprintf(Voutfile,"\tmovl\t*(sp),r1");
00288 putcomment ("# Get Size of Activation Record");
00289 NEWOBJ;
00290 }
00291 ar_reg = Vnewreg();
00292 Vgc_mask |= Vreg_bit;
00293 in_memory = (Vreg_bit == 0);
00294 if (construction == NIL || !slink_known) {
00295 fprintf(Voutfile, "\tmovl\t(sp),r1");
00296 putcomment("# Function Value");
00297 fprintf (Voutfile,"\tmovl\t%d(r1),(r0)",
00298 FO_EP);
00299 } else {
00300 char * display_reg;
00301
00302 char * r10 = "r10";
00303
00304 DISPLAY ( display_reg,
00305 ((construction -> ar_static_level) - 1),
00306 r10, "# display entry in place" );
00307 if (display_reg == r10) Ventry_mask |= R10;
00308 fprintf(Voutfile, "\tmovl\t%s,(r0)",
00309 display_reg);
00310 }
00311 putcomment ("# initialize static link to ep");
00312 fprintf(Voutfile,"\tmovl\tr0,%s",ar_reg);
00313 putcomment("# Save Activation Record object");
00314 if (in_memory) {
00315 PUSH("r0", "# make sure it's accessible");
00316 }
00317 } else {
00318
00319 if (construction == NIL) {
00320 size_reg = Vnewreg();
00321 in_memory = (Vreg_bit == 0);
00322 fprintf(Voutfile,"\tmovl\t*(sp),%s\n",size_reg);
00323 if (in_memory) {
00324 fprintf(Voutfile, "\tmovl\t%s,r10\n", size_reg);
00325 Ventry_mask |= R10;
00326 }
00327 Ventry_mask |= movc_regs;
00328 fprintf(Voutfile,"\tmoval\t%d[%s],r2",
00329 -4*(argcount+1),
00330 in_memory? "r10" : size_reg);
00331 putcomment("# size of local variable area");
00332 fprintf(Voutfile,"\tsubl2\tr2,sp");
00333 putcomment("# reserve space for local variables");
00334 fprintf(Voutfile,"\tmovc5\t$0,(sp),$0,r2,(sp)\n");
00335 } else {
00336 ASSERT(construction -> kind == FUNCCONSTR,
00337 "codegen.c: fn construction expected");
00338 switch(i = (construction -> ar_size
00339 - argcount - 1)) {
00340 case 0:
00341 break;
00342 case 1:
00343 fprintf(Voutfile,"\tclrl\t-(sp)");
00344 putcomment("# 1 local variable");
00345 break;
00346 case 2:
00347 fprintf(Voutfile,"\tclrq\t-(sp)");
00348 putcomment("# 2 local variables");
00349 break;
00350 case 3:
00351 fprintf(Voutfile,"\tclrq\t-(sp)");
00352 putcomment("# 3 local variables");
00353 fprintf(Voutfile,"\tclrl\t-(sp)\n");
00354 break;
00355 case 4:
00356 # ifdef EXTENDED_RANGE
00357 fprintf(Voutfile,"\tclro\t-(sp)");
00358 # else
00359 fprintf(Voutfile,"\tclrq\t-(sp)\n");
00360 fprintf(Voutfile,"\tclrq\t-(sp)");
00361 # endif
00362 putcomment("# 4 local variables");
00363 break;
00364 default: fprintf(Voutfile,
00365 "\tsubl2\t$%d,sp", 4*i);
00366 putcomment(
00367 "# reserve space for locals");
00368 fprintf(Voutfile,
00369 "\tmovc5\t$0,(sp),$0,$%d,(sp)\n",
00370 4*i);
00371 Ventry_mask |= movc_regs;
00372 }
00373 }
00374 }
00375 maprlist (p-> ap_args, Vexpression);
00376 if (!stack_call) {
00377 char * treg = in_memory? "r10" : ar_reg;
00378
00379 if (in_memory) {
00380 Vgc_mask |= R10;
00381 fprintf(Voutfile,"\tmovl\t%s,r10\n", ar_reg);
00382 }
00383
00384 switch(argcount) {
00385 case 0:
00386 break;
00387 case 1:
00388 POP_DISP(treg, 1, "# copy argument");
00389 break;
00390 case 2:
00391 fprintf(Voutfile,"\tmovq\t(sp)+,4(%s)\n", treg);
00392 putcomment("# copy 2 arguments");
00393 break;
00394 case 3:
00395 POP_DISP(treg, 1, "# copy 3 args");
00396 fprintf(Voutfile,"\tmovq\t(sp)+,8(%s)\n", treg);
00397 break;
00398 # ifdef EXTENDED_RANGE
00399 case 4:
00400 fprintf(Voutfile,"\tmovo\t(sp)+,4(%s)\n", treg);
00401 putcomment("# copy 4 arguments");
00402 break;
00403 # endif
00404 default:
00405 Ventry_mask |= movc_regs;
00406 fprintf(Voutfile,"\tmovc3\t$%d,(sp),4(%s)\n",
00407 4*argcount, treg);
00408 CODE("\tmovl\tr1,sp");
00409 }
00410 if (in_memory) {
00411 POP ("r0", "# clobber a.r. pointer");
00412 }
00413 if (construction == NIL || !slink_known) {
00414 POP ("r0","# Function Value");
00415 }
00416 SET_GC_INFO;
00417 if (construction != NIL) {
00418 fprintf(Voutfile,"\tcallg\t(%s),%s\n",
00419 treg, construction -> fc_code_label);
00420 } else {
00421 fprintf(Voutfile,"\tcallg\t(%s),*%d(r0)\n",
00422 treg, FO_IP);
00423 }
00424 Vretreg(ar_reg);
00425 } else if (construction == NIL) {
00426
00427 if (in_memory) {
00428 Vgc_mask |= R10;
00429 fprintf(Voutfile, "\tmovl\t%s,r10\n", size_reg);
00430 }
00431 fprintf(Voutfile,"\tmovl\t-4(sp)[%s],r0",
00432 in_memory? "r10" : size_reg);
00433 putcomment("# function value");
00434 PUSH_DISP("r0",(FO_EP/ObjSize),"# static link");
00435 SET_GC_INFO;
00436 fprintf(Voutfile,"\tcallg\t(sp),*%d(r0)\n",
00437 FO_IP);
00438 fprintf(Voutfile,"\tmoval\t4(sp)[%s],sp",
00439 in_memory? "r10" : size_reg);
00440 putcomment("# pop a.r. and function value");
00441 Vretreg(size_reg);
00442 } else {
00443 if (construction -> fc_complexity & NO_SL) {
00444 fprintf(Voutfile,"\tjsb\tF%s\n",
00445 construction -> fc_code_label);
00446 if(argcount > 0) {
00447
00448 fprintf(Voutfile,"\taddl2\t$%d,sp\n",4*argcount);
00449 }
00450 } else {
00451 if (slink_known) {
00452 char * display_reg;
00453 char * r10 = "r10";
00454
00455 DISPLAY ( display_reg,
00456 ((construction -> ar_static_level) - 1),
00457 r10, "# display entry in place" );
00458 if (display_reg == r10) Ventry_mask |= R10;
00459 PUSH(display_reg, "# static link");
00460 } else {
00461 fprintf(Voutfile, "\tmovl\t%d(sp),r0\n",
00462 4 * ((construction -> ar_size) - 1));
00463 PUSH_DISP("r0",(FO_EP/ObjSize),"# static link");
00464 }
00465 SET_GC_INFO;
00466 fprintf(Voutfile,"\tcallg\t(sp),%s\n",
00467 construction -> fc_code_label);
00468 if (!slink_known) {
00469 fprintf(Voutfile,"\taddl2\t$%d,sp",
00470 4 * ((construction -> ar_size) + 1));
00471 putcomment("# pop a.r. and function value");
00472 } else {
00473 fprintf(Voutfile,"\taddl2\t$%d,sp",
00474 4 * (construction -> ar_size));
00475 putcomment("# pop a.r.");
00476 }
00477 }
00478 }
00479 PUSH ("r0","# push value returned by function");
00480 }
00481 }