2 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3 * See the copyright notice in the ACK home directory, in the file "Copyright".
5 * Author: Ceriel J.H. Jacobs
8 /* C O D E G E N E R A T I O N R O U T I N E S */
10 /* $Id: code.c,v 1.80 1996/11/19 09:12:36 ceriel Exp $ */
12 /* Code generation for expressions and coercions
31 #include "standards.h"
33 #include "bigresult.h"
36 extern char options[];
37 extern t_desig null_desig;
44 /* Generate code to push constant "cst" with size "size"
47 if (size <= (int) word_size) {
50 else if (size == (int) dword_size) {
61 if (nd->nd_type->tp_fund != T_STRING) {
62 /* Character constant */
63 CodeConst(nd->nd_INT, nd->nd_type->tp_size);
66 C_df_dlb(++data_label);
67 C_rom_scon(nd->nd_STR, WA((arith)(nd->nd_SLE + 1)));
68 c_lae_dlb(data_label);
71 CodeExpr(nd, ds, true_label, false_label)
74 label true_label, false_label;
76 register t_type *tp = nd->nd_type;
79 if (tp->tp_fund == T_REAL) fp_used = 1;
80 switch(nd->nd_class) {
82 if (nd->nd_def->df_kind & (D_PROCEDURE|D_PROCHEAD)) {
83 C_lpi(nd->nd_def->prc_name);
84 ds->dsg_kind = DSG_LOADED;
96 CodeOper(nd, true_label, false_label);
97 ds->dsg_kind = DSG_LOADED;
98 true_label = NO_LABEL;
103 ds->dsg_kind = DSG_LOADED;
107 switch(nd->nd_symb) {
109 C_df_dlb(++data_label);
111 static char buf[FLT_STRLEN];
113 flt_flt2str(&nd->nd_RVAL, buf, FLT_STRLEN);
114 C_rom_fcon(buf, tp->tp_size);
116 else C_rom_fcon(nd->nd_RSTR, tp->tp_size);
117 c_lae_dlb(data_label);
124 CodeConst(nd->nd_INT, (int) (tp->tp_size));
127 crash("Value error");
129 ds->dsg_kind = DSG_LOADED;
134 ds->dsg_kind = DSG_LOADED;
138 register unsigned i = (unsigned) (tp->tp_size) / (int) word_size;
139 register arith *st = nd->nd_set + i;
142 ds->dsg_kind = DSG_LOADED;
144 if (*--st != 0) null_set = 0;
147 i = (unsigned) (tp->tp_size) / (int) word_size;
154 CodeSet(nd, null_set);
159 crash("(CodeExpr) bad node type");
162 if (true_label != NO_LABEL) {
163 /* Only for boolean expressions
175 int sz1 = t1->tp_size;
181 switch(fund1 = t1->tp_fund) {
189 if (sz1 < (int) word_size) sz1 = word_size;
196 switch(fund2 = t2->tp_fund) {
212 if (sz1 < (int) word_size) {
214 c_loc((int) word_size);
231 crash("Funny integer conversion");
251 crash("Funny cardinal conversion");
268 if (! options['R']) {
269 label lb = ++text_label;
285 crash("Funny REAL conversion");
294 /* Generate code for a procedure call. Checking of parameters
295 and result is already done.
297 register t_node *left = nd->nd_LEFT;
301 if (left->nd_type == std_type) {
306 assert(IsProc(left));
308 result_tp = ResultType(left->nd_type);
309 #ifdef BIG_RESULT_ON_STACK
310 if (result_tp && TooBigForReturnArea(result_tp)) {
311 C_asp(-WA(result_tp->tp_size));
316 CodeParameters(ParamList(left->nd_type), nd->nd_RIGHT);
319 switch(left->nd_class) {
321 register t_def *df = left->nd_def;
323 if (df->df_kind == D_CONST) {
324 /* a procedure address */
325 df = df->con_const.tk_data.tk_def;
327 if (df->df_kind & (D_PROCEDURE|D_PROCHEAD)) {
328 int level = df->df_scope->sc_level;
331 C_lxl((arith) (proclevel - level));
333 needs_fn = df->df_scope->sc_defmodule;
343 C_asp(left->nd_type->prc_nbpar);
345 arith sz = WA(result_tp->tp_size);
346 if (TooBigForReturnArea(result_tp)) {
347 #ifndef BIG_RESULT_ON_STACK
354 DoFilename(needs_fn);
358 CodeParameters(param, arg)
360 register t_node *arg;
363 register t_type *arg_type;
365 assert(param != 0 && arg != 0);
367 if (param->par_next) {
368 CodeParameters(param->par_next, arg->nd_RIGHT);
371 tp = TypeOfParam(param);
373 arg_type = arg->nd_type;
374 if (IsConformantArray(tp)) {
375 register t_type *elem = tp->arr_elem;
377 C_loc(tp->arr_elsize);
378 if (IsConformantArray(arg_type)) {
380 if (elem->tp_size != arg_type->arr_elem->tp_size) {
381 /* This can only happen if the formal type is
384 C_loc(arg_type->arr_elem->tp_size);
386 if (elem == word_type) {
387 c_loc((int) word_size - 1);
389 c_loc((int) word_size - 1);
393 assert(elem == byte_type);
397 else if (arg->nd_symb == STRING) {
398 c_loc((int) arg->nd_SLE - 1);
400 else if (elem == word_type) {
401 C_loc((arg_type->tp_size+word_size-1) / word_size - 1);
403 else if (elem == byte_type) {
404 C_loc(arg_type->tp_size - 1);
407 C_loc(arg_type->arr_high - arg_type->arr_low);
411 if (IsConformantArray(tp) || IsVarParam(param)) {
412 if (arg->nd_symb == STRING) {
415 else switch(arg->nd_class) {
419 CodeDAddress(arg, IsVarParam(param));
422 arith tmp, TmpSpace();
423 arith sz = WA(arg->nd_type->tp_size);
426 tmp = TmpSpace(sz, arg->nd_type->tp_align);
434 if (arg_type->tp_fund == T_STRING) {
435 CodePString(arg, tp);
445 arith szarg = WA(nd->nd_type->tp_size);
446 register arith zersz = WA(tp->tp_size) - szarg;
449 /* null padding required */
453 CodeString(nd); /* push address of string */
461 if (! options['R']) {
462 C_cal(sz == (int) word_size ? "subuchk" : "subulchk");
471 if (! options['R']) {
472 C_cal(sz == (int) word_size ? "adduchk" : "addulchk");
481 switch(nd->nd_class) {
488 return complex_lhs(nd->nd_NEXT);
497 register t_node *arg = nd->nd_RIGHT;
498 register t_node *left = 0;
499 register t_type *tp = 0;
500 int std = nd->nd_LEFT->nd_def->df_value.df_stdname;
504 tp = BaseType(left->nd_type);
516 if (tp->tp_fund == T_INTEGER) {
517 CAL((int)(tp->tp_size) == (int)int_size ? "absi" : "absl", (int)(tp->tp_size));
519 else if (tp->tp_fund == T_REAL) {
520 CAL((int)(tp->tp_size) == (int)float_size ? "absf" : "absd", (int)(tp->tp_size));
531 assert(IsConformantArray(tp));
532 DoHIGH(left->nd_def);
537 assert(IsConformantArray(tp));
538 DoHIGH(left->nd_def);
540 C_loc(tp->arr_elem->tp_size);
546 if ((int) tp->tp_size == (int) word_size) {
551 assert(tp->tp_size == dword_size);
559 CodeDAddress(left, 1);
565 int compl = complex_lhs(left);
568 size = left->nd_type->tp_size;
569 if ((int) size < (int) word_size) size = word_size;
572 CodeDAddress(left, 1);
573 STL(tmp, pointer_size);
574 LOL(tmp, pointer_size);
575 C_loi(left->nd_type->tp_size);
577 else CodePExpr(left);
578 CodeCoercion(left->nd_type, tp);
580 CodePExpr(arg->nd_LEFT);
581 CodeCoercion(arg->nd_LEFT->nd_type, tp);
585 CodeCoercion(intorcard_type, tp);
588 if (tp->tp_fund == T_INTEGER) C_sbi(size);
589 else subu((int) size);
592 if (tp->tp_fund == T_INTEGER) C_adi(size);
593 else addu((int) size);
595 if ((int) size == (int) word_size) {
596 RangeCheck(left->nd_type, tp->tp_fund == T_INTEGER ?
597 int_type : card_type);
600 LOL(tmp, pointer_size);
601 C_sti(left->nd_type->tp_size);
604 else CodeDStore(left);
614 int compl = complex_lhs(left);
619 CodeDAddress(left, 1);
620 STL(tmp, pointer_size);
621 LOL(tmp, pointer_size);
622 C_loi(left->nd_type->tp_size);
624 else CodePExpr(left);
625 CodePExpr(arg->nd_LEFT);
637 LOL(tmp, pointer_size);
638 C_sti(left->nd_type->tp_size);
641 else CodeDStore(left);
651 needs_rangecheck(tpl, tpr)
652 register t_type *tpl, *tpr;
657 /* In this case we might need a range check.
658 If both types are restricted. check the bounds
659 to see wether we need a range check.
660 We don't need one if the range of values of the
661 right hand side is a subset of the range of values
662 of the left hand side.
665 getbounds(tpr, &rlo, &rhi);
666 if (in_range(rlo, tpl) && in_range(rhi, tpl)) {
676 register t_type *tpl, *tpr;
678 /* Generate a range check if neccessary
683 if (options['R']) return;
685 if (needs_rangecheck(tpl, tpr)) {
690 if ((tpl->tp_fund == T_INTEGER && tpr->tp_fund == T_CARDINAL) ||
691 (tpr->tp_fund == T_INTEGER && tpl->tp_fund == T_CARDINAL)) {
692 label lb = ++text_label;
708 CodePExpr(nd->nd_LEFT);
709 CodePExpr(nd->nd_RIGHT);
713 CodeOper(expr, true_label, false_label)
714 register t_node *expr; /* the expression tree itself */
716 label false_label; /* labels to jump to in logical expr's */
718 register t_node *leftop = expr->nd_LEFT;
719 register t_node *rightop = expr->nd_RIGHT;
720 int fund = expr->nd_type->tp_fund;
721 arith size = expr->nd_type->tp_size;
723 switch (expr->nd_symb) {
735 C_ads(rightop->nd_type->tp_size);
759 if (rightop->nd_type == address_type) {
763 C_ngi(rightop->nd_type->tp_size);
764 C_ads(rightop->nd_type->tp_size);
788 if (! options['R']) {
789 C_cal((int)(size) <= (int)word_size ?
822 C_cal((int)(size) == (int)word_size
835 crash("bad type DIV");
842 C_cal((int)(size) == (int)word_size
855 crash("bad type MOD");
867 tp = BaseType(leftop->nd_type);
868 if (tp->tp_fund == T_INTORCARD) tp = BaseType(rightop->nd_type);
870 switch (tp->tp_fund) {
891 if (expr->nd_symb == GREATEREQUAL) {
892 /* A >= B is the same as A equals A + B
899 else if (expr->nd_symb == LESSEQUAL) {
900 /* A <= B is the same as A - B = {}
910 crash("bad type COMPARE");
912 if (true_label != NO_LABEL) {
913 compare(expr->nd_symb, true_label);
917 truthvalue(expr->nd_symb);
922 /* In this case, evaluate right hand side first! The
923 INN instruction expects the bit number on top of the
926 label l_toolarge = NO_LABEL, l_cont = NO_LABEL;
927 t_type *ltp = leftop->nd_type;
929 if (leftop->nd_symb == COERCION) {
930 /* Could be coercion to word_type. */
931 ltp = leftop->nd_RIGHT->nd_type;
933 if (leftop->nd_class == Value) {
934 if (! in_range(leftop->nd_INT, ElementType(rightop->nd_type))) {
935 if (true_label != NO_LABEL) {
942 C_loc(leftop->nd_INT - rightop->nd_type->set_low);
947 C_loc(rightop->nd_type->set_low);
949 if (needs_rangecheck(ElementType(rightop->nd_type), ltp)) {
950 l_toolarge = ++text_label;
952 C_loc(rightop->nd_type->tp_size*8);
957 C_inn(rightop->nd_type->tp_size);
958 if (true_label != NO_LABEL) {
963 l_cont = ++text_label;
966 if (l_toolarge != NO_LABEL) {
968 C_asp(word_size+rightop->nd_type->tp_size);
969 if (true_label != NO_LABEL) {
974 if (l_cont != NO_LABEL) {
981 label l_maybe = ++text_label, l_end = NO_LABEL;
986 if (true_label == NO_LABEL) {
987 true_label = ++text_label;
988 false_label = ++text_label;
989 l_end = ++text_label;
992 if (expr->nd_symb == OR) {
993 CodeExpr(leftop, &Des, true_label, l_maybe);
995 else CodeExpr(leftop, &Des, l_maybe, false_label);
998 CodeExpr(rightop, &Des, true_label, false_label);
999 if (l_end != NO_LABEL) {
1000 def_ilb(true_label);
1003 def_ilb(false_label);
1010 crash("(CodeOper) Bad operator");
1014 /* compare() serves as an auxiliary function of CodeOper */
1043 /* truthvalue() serves as an auxiliary function of CodeOper */
1067 crash("(truthvalue)");
1072 register t_node *nd;
1074 register t_type *tp = nd->nd_type;
1076 CodePExpr(nd->nd_RIGHT);
1077 switch(nd->nd_symb) {
1082 switch(tp->tp_fund) {
1091 crash("Bad operand to unary -");
1095 CodeCoercion(nd->nd_RIGHT->nd_type, tp);
1096 RangeCheck(tp, nd->nd_RIGHT->nd_type);
1101 crash("Bad unary operator");
1105 CodeSet(nd, null_set)
1106 register t_node *nd;
1108 register t_type *tp = nd->nd_type;
1112 assert(nd->nd_class == Link && nd->nd_symb == ',');
1115 CodeEl(nd->nd_LEFT, tp, null_set);
1120 if (null_set) C_zer(tp->tp_size);
1123 CodeEl(nd, tp, null_set)
1124 register t_node *nd;
1125 register t_type *tp;
1127 register t_type *eltype = ElementType(tp);
1129 if (nd->nd_class == Link && nd->nd_symb == UPTO) {
1130 if (null_set) C_zer(tp->tp_size);
1132 C_loc(tp->tp_size); /* push size */
1133 if (eltype->tp_fund == T_SUBRANGE) {
1134 C_loc(eltype->sub_ub);
1136 else C_loc(eltype->enm_ncst - 1);
1138 CAL("LtoUset", 5 * (int) word_size);
1139 /* library routine to fill set */
1146 if (! null_set) C_ior(tp->tp_size);
1151 register t_node *nd;
1153 /* Generate code to push the value of the expression "nd"
1158 designator = null_desig;
1159 CodeExpr(nd, &designator, NO_LABEL, NO_LABEL);
1160 CodeValue(&designator, nd->nd_type);
1163 CodeDAddress(nd, chk_controlvar)
1166 /* Generate code to push the address of the designator "nd"
1173 designator = null_desig;
1174 if (chk_controlvar) ChkForFOR(nd);
1175 CodeDesig(nd, &designator);
1176 chkptr = designator.dsg_kind==DSG_PLOADED ||
1177 designator.dsg_kind==DSG_PFIXED;
1178 CodeAddress(&designator);
1180 /* Generate dummy use of pointer, to get possible error message
1183 if (chkptr && ! options['R']) {
1184 C_dup(pointer_size);
1191 register t_node *nd;
1193 /* Generate code to store the expression on the stack into the
1199 designator = null_desig;
1201 CodeDesig(nd, &designator);
1202 CodeStore(&designator, nd->nd_type);
1208 /* Get the high index of a conformant array, indicated by "nd".
1209 The high index is the second field in the descriptor of
1210 the array, so it is easily found.
1212 register arith highoff;
1214 assert(df->df_kind == D_VARIABLE);
1215 assert(IsConformantArray(df->df_type));
1217 highoff = df->var_off /* base address and descriptor */
1218 + word_size + pointer_size;
1219 /* skip base and first field of
1222 if (df->df_scope->sc_level < proclevel) {
1223 C_lxa((arith) (proclevel - df->df_scope->sc_level));
1226 else C_lol(highoff);
1244 C_lae_dlb(l, (arith) 0);