1 /* $Id: code.c,v 1.8 1994/06/24 12:26:43 ceriel Exp $ */
3 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
4 * See the copyright notice in the ACK home directory, in the file "Copyright".
15 static void subscript();
16 enum addr_val { address, value };
18 void code_val(e) register struct expr *e;
19 /* Compile e for its value, which is put on the stack. */
21 register struct expr *left, *right;
28 right=e->u.node.right;
30 switch (e->u.node.op) {
78 code_bool(e, positive, &T, &F);
112 register struct symbol *var=e->u.var;
114 if (var->s_type&T_BUILTIN)
115 Loe(var->s_info.vc.st.builtin, var->s_info.vc.offset);
117 if (var->s_info.vc.st.level==curr_level)
118 if (var->s_type&T_PARAM && (var->s_type&T_TYPE)!=T_VALUE)
119 Lil(var->s_info.vc.offset);
121 Lol(var->s_info.vc.offset);
123 if (var->s_info.vc.offset<0)
124 lxl(curr_level-var->s_info.vc.st.level);
126 lxa(curr_level-var->s_info.vc.st.level);
127 if (var->s_type&T_PARAM && (var->s_type&T_TYPE)!=T_VALUE)
128 Lif(var->s_info.vc.offset);
130 Lof(var->s_info.vc.offset);
143 static void subscript(e, av) register struct expr *e; enum addr_val av;
144 /* Produce code to compute the address or value of e->left[e->right] or
145 * the address of e->left[e->right->left FOR e->right->right].
149 register struct expr *left;
150 register struct expr *index;
152 code_addr(left=e->u.node.left);
154 if ((index=e->u.node.right)->kind==E_NODE && index->u.node.op==FOR)
155 index=index->u.node.left;
157 if (left->arr_siz==0) {
158 if ((left->type&T_TYPE)==T_CHAN)
161 des= e->type&T_BYTE ? "maxbdes" : "maxwdes";
163 register lsiz=left->arr_siz;
165 if (left->type&T_BYTE && !(e->type&T_BYTE))
168 if (!(left->type&T_BYTE) && e->type&T_BYTE)
172 lsiz-=(e->arr_siz -1);
174 if (constant(index)) {
175 if (index->u.cst<0 || index->u.cst>=lsiz) {
176 warning("constant index outside vector");
184 if ((left->type&T_TYPE)==T_CHAN)
187 des= e->type&T_BYTE ? "bytedes" : "worddes";
191 if (constant(index)) {
192 register offset=index->u.cst;
194 if ((left->type&T_TYPE)==T_CHAN)
197 if ( !(e->type&T_BYTE) )
203 if (e->type&T_BYTE) {
219 if (e->type&T_BYTE) cwv();
224 void code_addr(e) register struct expr *e;
225 /* The address of e is wat we want. */
231 subscript(e, address);
233 case E_VAR: { /* variable or channel */
234 register struct symbol *var=e->u.var;
236 if (var->s_type&T_BUILTIN)
237 lae(var->s_info.vc.st.builtin, var->s_info.vc.offset);
239 if (var->s_info.vc.st.level==curr_level)
240 if (var->s_type&T_PARAM
241 && (var->s_type&(T_TYPE|T_ARR))!=T_VALUE)
242 Lolp(var->s_info.vc.offset);
244 lal(var->s_info.vc.offset);
246 if (var->s_info.vc.offset<0)
247 lxl(curr_level-var->s_info.vc.st.level);
249 lxa(curr_level-var->s_info.vc.st.level);
250 if (var->s_type&T_PARAM
251 && (var->s_type&(T_TYPE|T_ARR))!=T_VALUE)
252 Lofp(var->s_info.vc.offset);
254 adp(var->s_info.vc.offset);
264 void code_bool(e, pos, T, F)
265 register struct expr *e;
269 fall through or jump to T;
279 if (e->kind==E_NODE) {
280 register struct expr *left=e->u.node.left;
281 register struct expr *right=e->u.node.right;
283 switch(e->u.node.op) {
293 bxx(pos, e->u.node.op, new_label(F));
297 if ((e->u.node.op==AND && pos)
298 || (e->u.node.op==OR && !pos)
301 code_bool(left, pos, &L, F);
303 code_bool(right, pos, T, F);
306 code_bool(left, !pos, &L, T);
308 code_bool(right, pos, T, F);
312 code_bool(left, !pos, T, F);
327 if (pos) zeq(new_label(F)); else zne(new_label(F));
331 void code_assignment(e) register struct expr *e;
332 /* e->left := e->right */
334 register struct expr *left=e->u.node.left;
335 register struct expr *right=e->u.node.right;
337 if (left->type&T_ARR) {
338 register siz=left->arr_siz;
342 blm(left->type&T_BYTE ? siz : siz*vz);
346 sti(left->type&T_BYTE ? 1 : vz);
350 void code_input(e) register struct expr *e;
351 /* Input one v from c ? v0; v1; ... */
361 cal(e->type&T_BYTE ? "c_ba_in" : "c_wa_in");
365 cal(e->type&T_BYTE ? "cbyte_in" : "chan_in");
370 void code_output(e) register struct expr *e;
371 /* Output one e from c ? e0; e1; ... */
381 cal(e->type&T_BYTE ? "c_ba_out" : "c_wa_out");
390 void code_any(e, NO) register struct expr *e; int *NO;
391 /* Test if the channel (push address on stack) has input. If not so remove the
392 * channel pointer and jump to NO. Otherwise input values.
396 register struct expr_list *elp;
400 code_addr(e->u.io.chan);
404 zne(new_label(&YES));
410 code_input(elp->arg);
416 void code_void(e) register struct expr *e;
417 /* Assignment, I/O, or procedure call. */
422 case E_NODE: /* Must be assignment */
426 register struct expr_list *elp;
428 code_addr(e->u.io.chan);
433 code_output(elp->arg);
435 code_input(elp->arg);
443 register struct expr_list *elp=e->u.call.c_args;
444 register struct symbol *proc=e->u.call.c_proc->u.var;
445 register struct par_list *pars=proc->s_info.proc.pars;
448 if (pars->pr_type==T_VALUE) {
458 if (proc->s_type&T_BUILTIN) {
459 cal(proc->s_info.proc.st.builtin);
462 if (proc->s_info.proc.st.level>curr_level) {
466 if (proc->s_info.proc.st.level==curr_level) {
467 /* Call at same level */
471 lxa(curr_level-proc->s_info.proc.st.level);
474 cal(proc_label(proc->s_info.proc.label, proc->s_name));
476 if (proc->s_info.proc.file!=curr_file) fil();
482 void prologue(proc) register struct symbol *proc;
483 /* Open up the scope for a new proc definition. */
489 proc->s_info.proc.st.level= ++curr_level;
490 proc->s_info.proc.file= curr_file;
491 proc->s_info.proc.label= ++P;
492 curr_offset=min_offset=0;
493 pro(proc_label(proc->s_info.proc.label, proc->s_name));
494 if (curr_level==1) fil();
497 void epilogue(proc) register struct symbol *proc;
498 /* Close the scope of a proc def. */
507 void rep_init(v, e1, e2, r_info)
509 register struct expr *e1, *e2;
510 register struct replicator *r_info;
511 /* Compile v=[e1 FOR e2]. Info tells rep_test what decisions rep_init makes. */
515 r_info->BEGIN=r_info->END=0;
518 Stl(v->s_info.vc.offset);
520 if (!constant(e1) || !constant(e2)) {
521 if (constant(e2) && word_constant(e2->u.cst)) {
522 r_info->counter=memory(wz);
523 loc((int) e2->u.cst);
524 stl(r_info->counter);
526 r_info->counter=memory(vz);
528 Stl(r_info->counter);
531 if (!constant(e2) || e2->u.cst<=0L)
532 branch(&r_info->END);
533 Label(new_label(&r_info->BEGIN));
536 void rep_test(v, e1, e2, r_info)
537 register struct symbol *v;
538 register struct expr *e1, *e2;
539 register struct replicator *r_info;
543 Inl(v->s_info.vc.offset);
545 if (constant(e1) && constant(e2)) {
546 Lol(v->s_info.vc.offset);
547 Loc(e1->u.cst+e2->u.cst);
555 if (constant(e2) && word_constant(e2->u.cst)) {
556 del(r_info->counter);
558 lol(r_info->counter);
561 Del(r_info->counter);
563 Lol(r_info->counter);
574 void chan_init(info, arr_siz) union type_info *info; int arr_siz;
575 /* Garbage disposal unit for fresh channels. */
580 lal(info->vc.offset);
588 openfile((char *) nil);