1 /*-------------------------------------------------------------------------
3 SDCCicode.c - intermediate code generation etc.
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
29 /*-----------------------------------------------------------------*/
30 /* global variables */
32 set *iCodeChain = NULL;
42 symbol *returnLabel; /* function return label */
43 symbol *entryLabel; /* function entry label */
45 /*-----------------------------------------------------------------*/
46 /* forward definition of some functions */
47 operand *geniCodeDivision (operand *, operand *);
48 operand *geniCodeAssign (operand *, operand *, int);
49 operand *geniCodeArray (operand *, operand *,int);
50 operand *geniCodeArray2Ptr (operand *);
51 operand *geniCodeRValue (operand *, bool);
52 operand *geniCodeDerefPtr (operand *,int);
53 int isLvaluereq(int lvl);
55 #define PRINTFUNC(x) void x (FILE *of, iCode *ic, char *s)
56 /* forward definition of ic print functions */
57 PRINTFUNC (picGetValueAtAddr);
58 PRINTFUNC (picSetValueAtAddr);
59 PRINTFUNC (picAddrOf);
60 PRINTFUNC (picGeneric);
61 PRINTFUNC (picGenericOne);
63 PRINTFUNC (picAssign);
67 PRINTFUNC (picJumpTable);
68 PRINTFUNC (picInline);
69 PRINTFUNC (picReceive);
71 iCodeTable codeTable[] =
73 {'!', "not", picGenericOne, NULL},
74 {'~', "~", picGenericOne, NULL},
75 {RRC, "rrc", picGenericOne, NULL},
76 {RLC, "rlc", picGenericOne, NULL},
77 {GETHBIT, "ghbit", picGenericOne, NULL},
78 {UNARYMINUS, "-", picGenericOne, NULL},
79 {IPUSH, "push", picGenericOne, NULL},
80 {IPOP, "pop", picGenericOne, NULL},
81 {CALL, "call", picGenericOne, NULL},
82 {PCALL, "pcall", picGenericOne, NULL},
83 {FUNCTION, "proc", picGenericOne, NULL},
84 {ENDFUNCTION, "eproc", picGenericOne, NULL},
85 {RETURN, "ret", picGenericOne, NULL},
86 {'+', "+", picGeneric, NULL},
87 {'-', "-", picGeneric, NULL},
88 {'*', "*", picGeneric, NULL},
89 {'/', "/", picGeneric, NULL},
90 {'%', "%", picGeneric, NULL},
91 {'>', ">", picGeneric, NULL},
92 {'<', "<", picGeneric, NULL},
93 {LE_OP, "<=", picGeneric, NULL},
94 {GE_OP, ">=", picGeneric, NULL},
95 {EQ_OP, "==", picGeneric, NULL},
96 {NE_OP, "!=", picGeneric, NULL},
97 {AND_OP, "&&", picGeneric, NULL},
98 {OR_OP, "||", picGeneric, NULL},
99 {'^', "^", picGeneric, NULL},
100 {'|', "|", picGeneric, NULL},
101 {BITWISEAND, "&", picGeneric, NULL},
102 {LEFT_OP, "<<", picGeneric, NULL},
103 {RIGHT_OP, ">>", picGeneric, NULL},
104 {GET_VALUE_AT_ADDRESS, "@", picGetValueAtAddr, NULL},
105 {ADDRESS_OF, "&", picAddrOf, NULL},
106 {CAST, "<>", picCast, NULL},
107 {'=', ":=", picAssign, NULL},
108 {LABEL, "", picLabel, NULL},
109 {GOTO, "", picGoto, NULL},
110 {JUMPTABLE, "jtab", picJumpTable, NULL},
111 {IFX, "if", picIfx, NULL},
112 {INLINEASM, "", picInline, NULL},
113 {RECEIVE, "recv", picReceive, NULL},
114 {SEND, "send", picGenericOne, NULL},
115 {ARRAYINIT, "arrayInit", picGenericOne, NULL},
118 /*-----------------------------------------------------------------*/
119 /* checkConstantRange: check a constant against the type */
120 /*-----------------------------------------------------------------*/
122 /* pedantic=0: allmost anything is allowed as long as the absolute
123 value is within the bit range of the type, and -1 is treated as
124 0xf..f for unsigned types (e.g. in assign)
125 pedantic=1: -1==-1, not allowed for unsigned types (e.g. in compare)
126 pedantic>1: "char c=200" is not allowed (evaluates to -56)
129 void checkConstantRange(sym_link *ltype, value *val, char *msg, int pedantic) {
131 char message[132]="";
136 max = pow ((double)2.0, (double)bitsForType(ltype));
138 if (SPEC_LONG(val->type)) {
139 if (SPEC_USIGN(val->type)) {
140 v=SPEC_CVAL(val->type).v_ulong;
142 v=SPEC_CVAL(val->type).v_long;
145 if (SPEC_USIGN(val->type)) {
146 v=SPEC_CVAL(val->type).v_uint;
148 v=SPEC_CVAL(val->type).v_int;
154 // this could be a good idea
155 if (options.pedantic)
159 if (SPEC_NOUN(ltype)==FLOAT) {
164 if (!SPEC_USIGN(val->type) && v<0) {
166 if (SPEC_USIGN(ltype) && (pedantic>1)) {
172 // if very pedantic: "char c=200" is not allowed
173 if (pedantic>1 && !SPEC_USIGN(ltype)) {
174 max = max/2 + negative;
182 sprintf (message, "for %s %s in %s",
183 SPEC_USIGN(ltype) ? "unsigned" : "signed",
184 nounName(ltype), msg);
185 werror (W_CONST_RANGE, message);
192 /*-----------------------------------------------------------------*/
193 /* operandName - returns the name of the operand */
194 /*-----------------------------------------------------------------*/
196 printOperand (operand * op, FILE * file)
213 opetype = getSpec (operandType (op));
214 if (SPEC_NOUN (opetype) == V_FLOAT)
215 fprintf (file, "%g {", SPEC_CVAL (opetype).v_float);
217 fprintf (file, "0x%x {", (int) floatFromVal (op->operand.valOperand));
218 printTypeChain (operandType (op), file);
225 fprintf (file, "%s [k%d lr%d:%d so:%d]{ ia%d re%d rm%d nos%d}", /*{ar%d rm%d ru%d p%d a%d u%d i%d au%d k%d ks%d}" , */
226 (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name),
228 OP_LIVEFROM (op), OP_LIVETO (op),
229 OP_SYMBOL (op)->stack,
230 op->isaddr, OP_SYMBOL (op)->isreqv, OP_SYMBOL (op)->remat,OP_SYMBOL(op)->noSpilLoc
234 printTypeChain (operandType (op), file);
235 if (SPIL_LOC (op) && IS_ITEMP (op))
236 fprintf (file, "}{ sir@ %s", SPIL_LOC (op)->rname);
241 /* if assigned to registers */
242 if (OP_SYMBOL (op)->nRegs)
244 if (OP_SYMBOL (op)->isspilt)
246 if (!OP_SYMBOL (op)->remat)
247 if (OP_SYMBOL (op)->usl.spillLoc)
248 fprintf (file, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
249 OP_SYMBOL (op)->usl.spillLoc->rname :
250 OP_SYMBOL (op)->usl.spillLoc->name));
252 fprintf (file, "[err]");
254 fprintf (file, "[remat]");
260 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
261 fprintf (file, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i]));
266 fprintf (file, "%s", (OP_SYMBOL (op)->rname[0] ?
267 OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name));
268 /* if assigned to registers */
269 if (OP_SYMBOL (op)->nRegs && !OP_SYMBOL (op)->isspilt)
273 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
274 fprintf (file, "%s ", (OP_SYMBOL (op)->regs[i] ?
275 OP_SYMBOL (op)->regs[i]->name :
284 printTypeChain (op->operand.typeOperand, file);
290 fprintf (file, "\n");
295 /*-----------------------------------------------------------------*/
296 /* print functions */
297 /*-----------------------------------------------------------------*/
298 PRINTFUNC (picGetValueAtAddr)
301 printOperand (IC_RESULT (ic), of);
304 printOperand (IC_LEFT (ic), of);
310 PRINTFUNC (picSetValueAtAddr)
314 printOperand (IC_LEFT (ic), of);
315 fprintf (of, "] = ");
316 printOperand (IC_RIGHT (ic), of);
320 PRINTFUNC (picAddrOf)
323 printOperand (IC_RESULT (ic), of);
324 if (IS_ITEMP (IC_LEFT (ic)))
327 fprintf (of, " = &[");
328 printOperand (IC_LEFT (ic), of);
331 if (IS_ITEMP (IC_LEFT (ic)))
332 fprintf (of, " offsetAdd ");
335 printOperand (IC_RIGHT (ic), of);
337 if (IS_ITEMP (IC_LEFT (ic)))
343 PRINTFUNC (picJumpTable)
348 fprintf (of, "%s\t", s);
349 printOperand (IC_JTCOND (ic), of);
351 for (sym = setFirstItem (IC_JTLABELS (ic)); sym;
352 sym = setNextItem (IC_JTLABELS (ic)))
353 fprintf (of, "\t\t\t%s\n", sym->name);
356 PRINTFUNC (picGeneric)
359 printOperand (IC_RESULT (ic), of);
361 printOperand (IC_LEFT (ic), of);
362 fprintf (of, " %s ", s);
363 printOperand (IC_RIGHT (ic), of);
367 PRINTFUNC (picGenericOne)
372 printOperand (IC_RESULT (ic), of);
378 fprintf (of, "%s ", s);
379 printOperand (IC_LEFT (ic), of);
382 if (!IC_RESULT (ic) && !IC_LEFT (ic))
391 printOperand (IC_RESULT (ic), of);
393 printOperand (IC_LEFT (ic), of);
394 printOperand (IC_RIGHT (ic), of);
399 PRINTFUNC (picAssign)
403 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
406 printOperand (IC_RESULT (ic), of);
408 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
411 fprintf (of, " %s ", s);
412 printOperand (IC_RIGHT (ic), of);
419 fprintf (of, " %s($%d) :\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
425 fprintf (of, " goto %s($%d)\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
432 printOperand (IC_COND (ic), of);
435 fprintf (of, " == 0 goto %s($%d)\n", IC_FALSE (ic)->name, IC_FALSE (ic)->key);
438 fprintf (of, " != 0 goto %s($%d)\n", IC_TRUE (ic)->name, IC_TRUE (ic)->key);
440 fprintf (of, "\tzzgoto %s\n", IC_FALSE (ic)->name);
444 PRINTFUNC (picInline)
446 fprintf (of, "%s", IC_INLINE (ic));
449 PRINTFUNC (picReceive)
451 printOperand (IC_RESULT (ic), of);
452 fprintf (of, " = %s ", s);
453 printOperand (IC_LEFT (ic), of);
457 /*-----------------------------------------------------------------*/
458 /* piCode - prints one iCode */
459 /*-----------------------------------------------------------------*/
461 piCode (void *item, FILE * of)
469 icTab = getTableEntry (ic->op);
470 fprintf (stdout, "%s(%d:%d:%d:%d:%d)\t",
471 ic->filename, ic->lineno,
472 ic->seq, ic->key, ic->depth, ic->supportRtn);
473 icTab->iCodePrint (of, ic, icTab->printName);
479 printiCChain(ic,stdout);
481 /*-----------------------------------------------------------------*/
482 /* printiCChain - prints intermediate code for humans */
483 /*-----------------------------------------------------------------*/
485 printiCChain (iCode * icChain, FILE * of)
492 for (loop = icChain; loop; loop = loop->next)
494 if ((icTab = getTableEntry (loop->op)))
496 fprintf (of, "%s(%d:%d:%d:%d:%d)\t",
497 loop->filename, loop->lineno,
498 loop->seq, loop->key, loop->depth, loop->supportRtn);
500 icTab->iCodePrint (of, loop, icTab->printName);
506 /*-----------------------------------------------------------------*/
507 /* newOperand - allocate, init & return a new iCode */
508 /*-----------------------------------------------------------------*/
514 op = Safe_alloc ( sizeof (operand));
520 /*-----------------------------------------------------------------*/
521 /* newiCode - create and return a new iCode entry initialised */
522 /*-----------------------------------------------------------------*/
524 newiCode (int op, operand * left, operand * right)
528 ic = Safe_alloc ( sizeof (iCode));
531 ic->filename = filename;
533 ic->level = scopeLevel;
535 ic->key = iCodeKey++;
537 IC_RIGHT (ic) = right;
542 /*-----------------------------------------------------------------*/
543 /* newiCode for conditional statements */
544 /*-----------------------------------------------------------------*/
546 newiCodeCondition (operand * condition,
552 if (IS_VOID(operandType(condition))) {
553 werror(E_VOID_VALUE_USED);
556 ic = newiCode (IFX, NULL, NULL);
557 IC_COND (ic) = condition;
558 IC_TRUE (ic) = trueLabel;
559 IC_FALSE (ic) = falseLabel;
563 /*-----------------------------------------------------------------*/
564 /* newiCodeLabelGoto - unconditional goto statement| label stmnt */
565 /*-----------------------------------------------------------------*/
567 newiCodeLabelGoto (int op, symbol * label)
571 ic = newiCode (op, NULL, NULL);
573 ic->argLabel.label = label;
575 IC_RIGHT (ic) = NULL;
576 IC_RESULT (ic) = NULL;
580 /*-----------------------------------------------------------------*/
581 /* newiTemp - allocate & return a newItemp Variable */
582 /*-----------------------------------------------------------------*/
589 sprintf (buffer, "%s", s);
591 sprintf (buffer, "iTemp%d", iTempNum++);
592 itmp = newSymbol (buffer, 1);
593 strcpy (itmp->rname, itmp->name);
599 /*-----------------------------------------------------------------*/
600 /* newiTempLabel - creates a temp variable label */
601 /*-----------------------------------------------------------------*/
603 newiTempLabel (char *s)
607 /* check if this alredy exists */
608 if (s && (itmplbl = findSym (LabelTab, NULL, s)))
612 itmplbl = newSymbol (s, 1);
615 sprintf (buffer, "iTempLbl%d", iTempLblNum++);
616 itmplbl = newSymbol (buffer, 1);
621 itmplbl->key = labelKey++;
622 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
626 /*-----------------------------------------------------------------*/
627 /* newiTempPreheaderLabel - creates a new preheader label */
628 /*-----------------------------------------------------------------*/
630 newiTempPreheaderLabel ()
634 sprintf (buffer, "preHeaderLbl%d", iTempLblNum++);
635 itmplbl = newSymbol (buffer, 1);
639 itmplbl->key = labelKey++;
640 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
645 /*-----------------------------------------------------------------*/
646 /* initiCode - initialises some iCode related stuff */
647 /*-----------------------------------------------------------------*/
654 /*-----------------------------------------------------------------*/
655 /* copyiCode - make a copy of the iCode given */
656 /*-----------------------------------------------------------------*/
658 copyiCode (iCode * ic)
660 iCode *nic = newiCode (ic->op, NULL, NULL);
662 nic->lineno = ic->lineno;
663 nic->filename = ic->filename;
664 nic->block = ic->block;
665 nic->level = ic->level;
666 nic->parmBytes = ic->parmBytes;
668 /* deal with the special cases first */
672 IC_COND (nic) = operandFromOperand (IC_COND (ic));
673 IC_TRUE (nic) = IC_TRUE (ic);
674 IC_FALSE (nic) = IC_FALSE (ic);
678 IC_JTCOND (nic) = operandFromOperand (IC_JTCOND (ic));
679 IC_JTLABELS (nic) = IC_JTLABELS (ic);
684 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
685 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
689 IC_INLINE (nic) = IC_INLINE (ic);
693 IC_ARRAYILIST(nic) = IC_ARRAYILIST(ic);
697 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
698 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
699 IC_RIGHT (nic) = operandFromOperand (IC_RIGHT (ic));
705 /*-----------------------------------------------------------------*/
706 /* getTableEntry - gets the table entry for the given operator */
707 /*-----------------------------------------------------------------*/
709 getTableEntry (int oper)
713 for (i = 0; i < (sizeof (codeTable) / sizeof (iCodeTable)); i++)
714 if (oper == codeTable[i].icode)
715 return &codeTable[i];
720 /*-----------------------------------------------------------------*/
721 /* newiTempOperand - new intermediate temp operand */
722 /*-----------------------------------------------------------------*/
724 newiTempOperand (sym_link * type, char throwType)
727 operand *op = newOperand ();
731 itmp = newiTemp (NULL);
733 etype = getSpec (type);
735 if (IS_LITERAL (etype))
738 /* copy the type information */
740 itmp->etype = getSpec (itmp->type = (throwType ? type :
741 copyLinkChain (type)));
742 if (IS_LITERAL (itmp->etype))
744 SPEC_SCLS (itmp->etype) = S_REGISTER;
745 SPEC_OCLS (itmp->etype) = reg;
748 op->operand.symOperand = itmp;
749 op->key = itmp->key = ++operandKey;
753 /*-----------------------------------------------------------------*/
754 /* operandType - returns the type chain for an operand */
755 /*-----------------------------------------------------------------*/
757 operandType (operand * op)
759 /* depending on type of operand */
764 return op->operand.valOperand->type;
767 return op->operand.symOperand->type;
770 return op->operand.typeOperand;
772 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
773 " operand type not known ");
774 assert (0); /* should never come here */
775 /* Just to keep the compiler happy */
776 return (sym_link *) 0;
780 /*-----------------------------------------------------------------*/
781 /* isParamterToCall - will return 1 if op is a parameter to args */
782 /*-----------------------------------------------------------------*/
784 isParameterToCall (value * args, operand * op)
791 isSymbolEqual (op->operand.symOperand, tval->sym))
798 /*-----------------------------------------------------------------*/
799 /* isOperandGlobal - return 1 if operand is a global variable */
800 /*-----------------------------------------------------------------*/
802 isOperandGlobal (operand * op)
810 if (op->type == SYMBOL &&
811 (op->operand.symOperand->level == 0 ||
812 IS_STATIC (op->operand.symOperand->etype) ||
813 IS_EXTERN (op->operand.symOperand->etype))
820 /*-----------------------------------------------------------------*/
821 /* isOperandVolatile - return 1 if the operand is volatile */
822 /*-----------------------------------------------------------------*/
824 isOperandVolatile (operand * op, bool chkTemp)
829 if (IS_ITEMP (op) && !chkTemp)
832 opetype = getSpec (optype = operandType (op));
834 if (IS_PTR (optype) && DCL_PTR_VOLATILE (optype))
837 if (IS_VOLATILE (opetype))
842 /*-----------------------------------------------------------------*/
843 /* isOperandLiteral - returns 1 if an operand contains a literal */
844 /*-----------------------------------------------------------------*/
846 isOperandLiteral (operand * op)
853 opetype = getSpec (operandType (op));
855 if (IS_LITERAL (opetype))
860 /*-----------------------------------------------------------------*/
861 /* isOperandInFarSpace - will return true if operand is in farSpace */
862 /*-----------------------------------------------------------------*/
864 isOperandInFarSpace (operand * op)
874 if (!IS_TRUE_SYMOP (op))
877 etype = SPIL_LOC (op)->etype;
883 etype = getSpec (operandType (op));
885 return (IN_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
888 /*-----------------------------------------------------------------*/
889 /* isOperandOnStack - will return true if operand is on stack */
890 /*-----------------------------------------------------------------*/
892 isOperandOnStack (operand * op)
902 etype = getSpec (operandType (op));
904 return ((IN_STACK (etype)) ? TRUE : FALSE);
907 /*-----------------------------------------------------------------*/
908 /* operandLitValue - literal value of an operand */
909 /*-----------------------------------------------------------------*/
911 operandLitValue (operand * op)
913 assert (isOperandLiteral (op));
915 return floatFromVal (op->operand.valOperand);
918 /*-----------------------------------------------------------------*/
919 /* operandOperation - perforoms operations on operands */
920 /*-----------------------------------------------------------------*/
922 operandOperation (operand * left, operand * right,
923 int op, sym_link * type)
925 sym_link *let , *ret=NULL;
926 operand *retval = (operand *) 0;
928 assert (isOperandLiteral (left));
929 let = getSpec(operandType(left));
931 assert (isOperandLiteral (right));
932 ret = getSpec(operandType(left));
938 retval = operandFromValue (valCastLiteral (type,
939 operandLitValue (left) +
940 operandLitValue (right)));
943 retval = operandFromValue (valCastLiteral (type,
944 operandLitValue (left) -
945 operandLitValue (right)));
948 retval = operandFromValue (valCastLiteral (type,
949 operandLitValue (left) *
950 operandLitValue (right)));
953 if ((unsigned long) operandLitValue (right) == 0)
955 werror (E_DIVIDE_BY_ZERO);
960 retval = operandFromValue (valCastLiteral (type,
961 operandLitValue (left) /
962 operandLitValue (right)));
965 if ((unsigned long) operandLitValue (right) == 0) {
966 werror (E_DIVIDE_BY_ZERO);
970 retval = operandFromLit ((SPEC_USIGN(let) ?
971 (unsigned long) operandLitValue (left) :
972 (long) operandLitValue (left)) %
974 (unsigned long) operandLitValue (right) :
975 (long) operandLitValue (right)));
979 retval = operandFromLit ((SPEC_USIGN(let) ?
980 (unsigned long) operandLitValue (left) :
981 (long) operandLitValue (left)) <<
983 (unsigned long) operandLitValue (right) :
984 (long) operandLitValue (right)));
987 retval = operandFromLit ((SPEC_USIGN(let) ?
988 (unsigned long) operandLitValue (left) :
989 (long) operandLitValue (left)) >>
991 (unsigned long) operandLitValue (right) :
992 (long) operandLitValue (right)));
995 retval = operandFromLit (operandLitValue (left) ==
996 operandLitValue (right));
999 retval = operandFromLit (operandLitValue (left) <
1000 operandLitValue (right));
1003 retval = operandFromLit (operandLitValue (left) <=
1004 operandLitValue (right));
1007 retval = operandFromLit (operandLitValue (left) !=
1008 operandLitValue (right));
1011 retval = operandFromLit (operandLitValue (left) >
1012 operandLitValue (right));
1015 retval = operandFromLit (operandLitValue (left) >=
1016 operandLitValue (right));
1019 retval = operandFromLit ((long)operandLitValue(left) &
1020 (long)operandLitValue(right));
1023 retval = operandFromLit ((long)operandLitValue (left) |
1024 (long)operandLitValue (right));
1027 retval = operandFromLit ((long)operandLitValue (left) ^
1028 (long)operandLitValue (right));
1031 retval = operandFromLit (operandLitValue (left) &&
1032 operandLitValue (right));
1035 retval = operandFromLit (operandLitValue (left) ||
1036 operandLitValue (right));
1040 long i = (long) operandLitValue (left);
1042 retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
1048 long i = (long) operandLitValue (left);
1050 retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
1056 retval = operandFromLit (-1 * operandLitValue (left));
1060 retval = operandFromLit (~((long) operandLitValue (left)));
1064 retval = operandFromLit (!operandLitValue (left));
1068 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1069 " operandOperation invalid operator ");
1077 /*-----------------------------------------------------------------*/
1078 /* isOperandEqual - compares two operand & return 1 if they r = */
1079 /*-----------------------------------------------------------------*/
1081 isOperandEqual (operand * left, operand * right)
1083 /* if the pointers are equal then they are equal */
1087 /* if either of them null then false */
1088 if (!left || !right)
1091 if (left->type != right->type)
1094 if (IS_SYMOP (left) && IS_SYMOP (right))
1095 return left->key == right->key;
1097 /* if types are the same */
1101 return isSymbolEqual (left->operand.symOperand,
1102 right->operand.symOperand);
1104 return (floatFromVal (left->operand.valOperand) ==
1105 floatFromVal (right->operand.valOperand));
1107 if (compareType (left->operand.typeOperand,
1108 right->operand.typeOperand) == 1)
1115 /*-------------------------------------------------------------------*/
1116 /* isiCodeEqual - compares two iCodes are equal, returns true if yes */
1117 /*-------------------------------------------------------------------*/
1119 isiCodeEqual (iCode * left, iCode * right)
1121 /* if the same pointer */
1125 /* if either of them null */
1126 if (!left || !right)
1129 /* if operand are the same */
1130 if (left->op == right->op)
1133 /* compare all the elements depending on type */
1134 if (left->op != IFX)
1136 if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
1138 if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
1144 if (!isOperandEqual (IC_COND (left), IC_COND (right)))
1146 if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
1148 if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
1157 /*-----------------------------------------------------------------*/
1158 /* newiTempFromOp - create a temp Operand with same attributes */
1159 /*-----------------------------------------------------------------*/
1161 newiTempFromOp (operand * op)
1171 nop = newiTempOperand (operandType (op), TRUE);
1172 nop->isaddr = op->isaddr;
1173 nop->isvolatile = op->isvolatile;
1174 nop->isGlobal = op->isGlobal;
1175 nop->isLiteral = op->isLiteral;
1176 nop->usesDefs = op->usesDefs;
1177 nop->isParm = op->isParm;
1181 /*-----------------------------------------------------------------*/
1182 /* operand from operand - creates an operand holder for the type */
1183 /*-----------------------------------------------------------------*/
1185 operandFromOperand (operand * op)
1191 nop = newOperand ();
1192 nop->type = op->type;
1193 nop->isaddr = op->isaddr;
1195 nop->isvolatile = op->isvolatile;
1196 nop->isGlobal = op->isGlobal;
1197 nop->isLiteral = op->isLiteral;
1198 nop->usesDefs = op->usesDefs;
1199 nop->isParm = op->isParm;
1204 nop->operand.symOperand = op->operand.symOperand;
1207 nop->operand.valOperand = op->operand.valOperand;
1210 nop->operand.typeOperand = op->operand.typeOperand;
1217 /*-----------------------------------------------------------------*/
1218 /* opFromOpWithDU - makes a copy of the operand and DU chains */
1219 /*-----------------------------------------------------------------*/
1221 opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
1223 operand *nop = operandFromOperand (op);
1225 if (nop->type == SYMBOL)
1227 OP_SYMBOL (nop)->defs = bitVectCopy (defs);
1228 OP_SYMBOL (nop)->uses = bitVectCopy (uses);
1234 /*-----------------------------------------------------------------*/
1235 /* operandFromSymbol - creates an operand from a symbol */
1236 /*-----------------------------------------------------------------*/
1238 operandFromSymbol (symbol * sym)
1243 /* if the symbol's type is a literal */
1244 /* then it is an enumerator type */
1245 if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
1246 return operandFromValue (valFromType (sym->etype));
1249 sym->key = ++operandKey;
1251 /* if this an implicit variable, means struct/union */
1252 /* member so just return it */
1253 if (sym->implicit || IS_FUNC (sym->type))
1257 op->operand.symOperand = sym;
1259 op->isvolatile = isOperandVolatile (op, TRUE);
1260 op->isGlobal = isOperandGlobal (op);
1264 /* under the following conditions create a
1265 register equivalent for a local symbol */
1266 if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
1267 (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
1268 (!(options.model == MODEL_FLAT24)) ) &&
1269 options.stackAuto == 0)
1272 if (!IS_AGGREGATE (sym->type) && /* not an aggregate */
1273 !IS_FUNC (sym->type) && /* not a function */
1274 !sym->_isparm && /* not a parameter */
1275 sym->level && /* is a local variable */
1276 !sym->addrtaken && /* whose address has not been taken */
1277 !sym->reqv && /* does not already have a reg equivalence */
1278 !IS_VOLATILE (sym->etype) && /* not declared as volatile */
1279 !IS_STATIC (sym->etype) && /* and not declared static */
1280 !sym->islbl && /* not a label */
1281 ok && /* farspace check */
1282 !IS_BITVAR (sym->etype) /* not a bit variable */
1286 /* we will use it after all optimizations
1287 and before liveRange calculation */
1288 sym->reqv = newiTempOperand (sym->type, 0);
1289 sym->reqv->key = sym->key;
1290 OP_SYMBOL (sym->reqv)->key = sym->key;
1291 OP_SYMBOL (sym->reqv)->isreqv = 1;
1292 OP_SYMBOL (sym->reqv)->islocal = 1;
1293 OP_SYMBOL (sym->reqv)->onStack = sym->onStack;
1294 SPIL_LOC (sym->reqv) = sym;
1297 if (!IS_AGGREGATE (sym->type))
1301 op->operand.symOperand = sym;
1304 op->isvolatile = isOperandVolatile (op, TRUE);
1305 op->isGlobal = isOperandGlobal (op);
1306 op->isPtr = IS_PTR (operandType (op));
1307 op->isParm = sym->_isparm;
1312 /* itemp = &[_symbol] */
1314 ic = newiCode (ADDRESS_OF, newOperand (), NULL);
1315 IC_LEFT (ic)->type = SYMBOL;
1316 IC_LEFT (ic)->operand.symOperand = sym;
1317 IC_LEFT (ic)->key = sym->key;
1318 (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
1319 (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
1320 IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
1323 IC_RESULT (ic) = newiTempOperand (sym->type, 0);
1324 if (IS_ARRAY (sym->type))
1326 IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
1327 IC_RESULT (ic)->isaddr = 0;
1330 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
1334 return IC_RESULT (ic);
1337 /*-----------------------------------------------------------------*/
1338 /* operandFromValue - creates an operand from value */
1339 /*-----------------------------------------------------------------*/
1341 operandFromValue (value * val)
1345 /* if this is a symbol then do the symbol thing */
1347 return operandFromSymbol (val->sym);
1349 /* this is not a symbol */
1352 op->operand.valOperand = val;
1353 op->isLiteral = isOperandLiteral (op);
1357 /*-----------------------------------------------------------------*/
1358 /* operandFromLink - operand from typeChain */
1359 /*-----------------------------------------------------------------*/
1361 operandFromLink (sym_link * type)
1365 /* operand from sym_link */
1371 op->operand.typeOperand = copyLinkChain (type);
1375 /*-----------------------------------------------------------------*/
1376 /* operandFromLit - makes an operand from a literal value */
1377 /*-----------------------------------------------------------------*/
1379 operandFromLit (double i)
1381 return operandFromValue (valueFromLit (i));
1384 /*-----------------------------------------------------------------*/
1385 /* operandFromAst - creates an operand from an ast */
1386 /*-----------------------------------------------------------------*/
1388 operandFromAst (ast * tree,int lvl)
1394 /* depending on type do */
1398 return ast2iCode (tree,lvl+1);
1402 return operandFromValue (tree->opval.val);
1406 return operandFromLink (tree->opval.lnk);
1410 /* Just to keep the comiler happy */
1411 return (operand *) 0;
1414 /*-----------------------------------------------------------------*/
1415 /* setOperandType - sets the operand's type to the given type */
1416 /*-----------------------------------------------------------------*/
1418 setOperandType (operand * op, sym_link * type)
1420 /* depending on the type of operand */
1425 op->operand.valOperand->etype =
1426 getSpec (op->operand.valOperand->type =
1427 copyLinkChain (type));
1431 if (op->operand.symOperand->isitmp)
1432 op->operand.symOperand->etype =
1433 getSpec (op->operand.symOperand->type =
1434 copyLinkChain (type));
1436 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1437 "attempt to modify type of source");
1441 op->operand.typeOperand = copyLinkChain (type);
1446 /*-----------------------------------------------------------------*/
1447 /* Get size in byte of ptr need to access an array */
1448 /*-----------------------------------------------------------------*/
1450 getArraySizePtr (operand * op)
1452 sym_link *ltype = operandType(op);
1456 int size = getSize(ltype);
1457 return(IS_GENPTR(ltype)?(size-1):size);
1462 sym_link *letype = getSpec(ltype);
1463 switch (PTR_TYPE (SPEC_OCLS (letype)))
1475 return (GPTRSIZE-1);
1484 /*-----------------------------------------------------------------*/
1485 /* perform "usual unary conversions" */
1486 /*-----------------------------------------------------------------*/
1488 usualUnaryConversions (operand * op)
1490 if (IS_INTEGRAL (operandType (op)))
1492 if (getSize (operandType (op)) < (unsigned int) INTSIZE)
1495 return geniCodeCast (INTTYPE, op, TRUE);
1501 /*-----------------------------------------------------------------*/
1502 /* perform "usual binary conversions" */
1503 /*-----------------------------------------------------------------*/
1505 usualBinaryConversions (operand ** op1, operand ** op2)
1508 sym_link *rtype = operandType (*op2);
1509 sym_link *ltype = operandType (*op1);
1511 ctype = computeType (ltype, rtype);
1512 *op1 = geniCodeCast (ctype, *op1, TRUE);
1513 *op2 = geniCodeCast (ctype, *op2, TRUE);
1518 /*-----------------------------------------------------------------*/
1519 /* geniCodeValueAtAddress - generate intermeditate code for value */
1521 /*-----------------------------------------------------------------*/
1523 geniCodeRValue (operand * op, bool force)
1526 sym_link *type = operandType (op);
1527 sym_link *etype = getSpec (type);
1529 /* if this is an array & already */
1530 /* an address then return this */
1531 if (IS_AGGREGATE (type) ||
1532 (IS_PTR (type) && !force && !op->isaddr))
1533 return operandFromOperand (op);
1535 /* if this is not an address then must be */
1536 /* rvalue already so return this one */
1540 /* if this is not a temp symbol then */
1541 if (!IS_ITEMP (op) &&
1543 !IN_FARSPACE (SPEC_OCLS (etype)))
1545 op = operandFromOperand (op);
1550 if (IS_SPEC (type) &&
1551 IS_TRUE_SYMOP (op) &&
1552 (!IN_FARSPACE (SPEC_OCLS (etype)) ||
1553 /* TARGET_IS_DS390)) */
1554 (options.model == MODEL_FLAT24) ))
1556 op = operandFromOperand (op);
1561 ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1562 if (IS_PTR (type) && op->isaddr && force)
1565 type = copyLinkChain (type);
1567 IC_RESULT (ic) = newiTempOperand (type, 1);
1568 IC_RESULT (ic)->isaddr = 0;
1570 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1574 return IC_RESULT (ic);
1577 /*-----------------------------------------------------------------*/
1578 /* geniCodeCast - changes the value from one type to another */
1579 /*-----------------------------------------------------------------*/
1581 geniCodeCast (sym_link * type, operand * op, bool implicit)
1585 sym_link *opetype = getSpec (optype = operandType (op));
1589 /* one of them has size zero then error */
1590 if (IS_VOID (optype))
1592 werror (E_CAST_ZERO);
1596 /* if the operand is already the desired type then do nothing */
1597 if (compareType (type, optype) == 1)
1600 /* if this is a literal then just change the type & return */
1601 if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1602 return operandFromValue (valCastLiteral (type,
1603 operandLitValue (op)));
1605 /* if casting to/from pointers, do some checking */
1606 if (IS_PTR(type)) { // to a pointer
1607 if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer
1608 if (IS_INTEGRAL(optype)) {
1609 // maybe this is NULL, than it's ok.
1610 if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
1611 if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80 && IS_GENPTR(type)) {
1612 // no way to set the storage
1613 if (IS_LITERAL(optype)) {
1614 werror(E_LITERAL_GENERIC);
1617 werror(E_NONPTR2_GENPTR);
1620 } else if (implicit) {
1621 werror(W_INTEGRAL2PTR_NOCAST);
1626 // shouldn't do that with float, array or structure unless to void
1627 if (!IS_VOID(getSpec(type)) &&
1628 !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1629 werror(E_INCOMPAT_TYPES);
1633 } else { // from a pointer to a pointer
1634 if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80) {
1635 // if not a pointer to a function
1636 if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1637 if (implicit) { // if not to generic, they have to match
1638 if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
1639 werror(E_INCOMPAT_PTYPES);
1646 } else { // to a non pointer
1647 if (IS_PTR(optype)) { // from a pointer
1648 if (implicit) { // sneaky
1649 if (IS_INTEGRAL(type)) {
1650 werror(W_PTR2INTEGRAL_NOCAST);
1652 } else { // shouldn't do that with float, array or structure
1653 werror(E_INCOMPAT_TYPES);
1660 printFromToType (optype, type);
1663 /* if they are the same size create an assignment */
1664 if (getSize (type) == getSize (optype) &&
1665 !IS_BITFIELD (type) &&
1667 !IS_FLOAT (optype) &&
1668 ((IS_SPEC (type) && IS_SPEC (optype)) ||
1669 (!IS_SPEC (type) && !IS_SPEC (optype))))
1672 ic = newiCode ('=', NULL, op);
1673 IC_RESULT (ic) = newiTempOperand (type, 0);
1674 SPIL_LOC (IC_RESULT (ic)) =
1675 (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
1676 IC_RESULT (ic)->isaddr = 0;
1680 ic = newiCode (CAST, operandFromLink (type),
1681 geniCodeRValue (op, FALSE));
1683 IC_RESULT (ic) = newiTempOperand (type, 0);
1686 /* preserve the storage class & output class */
1687 /* of the original variable */
1688 restype = getSpec (operandType (IC_RESULT (ic)));
1689 SPEC_SCLS (restype) = SPEC_SCLS (opetype);
1690 SPEC_OCLS (restype) = SPEC_OCLS (opetype);
1693 return IC_RESULT (ic);
1696 /*-----------------------------------------------------------------*/
1697 /* geniCodeLabel - will create a Label */
1698 /*-----------------------------------------------------------------*/
1700 geniCodeLabel (symbol * label)
1704 ic = newiCodeLabelGoto (LABEL, label);
1708 /*-----------------------------------------------------------------*/
1709 /* geniCodeGoto - will create a Goto */
1710 /*-----------------------------------------------------------------*/
1712 geniCodeGoto (symbol * label)
1716 ic = newiCodeLabelGoto (GOTO, label);
1720 /*-----------------------------------------------------------------*/
1721 /* geniCodeMultiply - gen intermediate code for multiplication */
1722 /*-----------------------------------------------------------------*/
1724 geniCodeMultiply (operand * left, operand * right,int resultIsInt)
1731 /* if they are both literal then we know the result */
1732 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1733 return operandFromValue (valMult (left->operand.valOperand,
1734 right->operand.valOperand));
1736 if (IS_LITERAL(retype)) {
1737 p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
1740 resType = usualBinaryConversions (&left, &right);
1742 rtype = operandType (right);
1743 retype = getSpec (rtype);
1744 ltype = operandType (left);
1745 letype = getSpec (ltype);
1749 SPEC_NOUN(getSpec(resType))=V_INT;
1752 /* if the right is a literal & power of 2 */
1753 /* then make it a left shift */
1754 /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
1755 efficient in most cases than 2 bytes result = 2 bytes << literal
1756 if port has 1 byte muldiv */
1757 if (p2 && !IS_FLOAT (letype) &&
1758 !((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
1759 (port->support.muldiv == 1)))
1761 if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
1763 /* LEFT_OP need same size for left and result, */
1764 left = geniCodeCast (resType, left, TRUE);
1765 ltype = operandType (left);
1767 ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
1771 ic = newiCode ('*', left, right); /* normal multiplication */
1772 /* if the size left or right > 1 then support routine */
1773 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1777 IC_RESULT (ic) = newiTempOperand (resType, 1);
1780 return IC_RESULT (ic);
1783 /*-----------------------------------------------------------------*/
1784 /* geniCodeDivision - gen intermediate code for division */
1785 /*-----------------------------------------------------------------*/
1787 geniCodeDivision (operand * left, operand * right)
1792 sym_link *rtype = operandType (right);
1793 sym_link *retype = getSpec (rtype);
1794 sym_link *ltype = operandType (left);
1795 sym_link *letype = getSpec (ltype);
1797 resType = usualBinaryConversions (&left, &right);
1799 /* if the right is a literal & power of 2 */
1800 /* then make it a right shift */
1801 if (IS_LITERAL (retype) &&
1802 !IS_FLOAT (letype) &&
1803 (p2 = powof2 ((unsigned long)
1804 floatFromVal (right->operand.valOperand)))) {
1805 ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
1809 ic = newiCode ('/', left, right); /* normal division */
1810 /* if the size left or right > 1 then support routine */
1811 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1814 IC_RESULT (ic) = newiTempOperand (resType, 0);
1817 return IC_RESULT (ic);
1819 /*-----------------------------------------------------------------*/
1820 /* geniCodeModulus - gen intermediate code for modulus */
1821 /*-----------------------------------------------------------------*/
1823 geniCodeModulus (operand * left, operand * right)
1829 /* if they are both literal then we know the result */
1830 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1831 return operandFromValue (valMod (left->operand.valOperand,
1832 right->operand.valOperand));
1834 resType = usualBinaryConversions (&left, &right);
1836 /* now they are the same size */
1837 ic = newiCode ('%', left, right);
1839 /* if the size left or right > 1 then support routine */
1840 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1842 IC_RESULT (ic) = newiTempOperand (resType, 0);
1845 return IC_RESULT (ic);
1848 /*-----------------------------------------------------------------*/
1849 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
1850 /*-----------------------------------------------------------------*/
1852 geniCodePtrPtrSubtract (operand * left, operand * right)
1858 /* if they are both literals then */
1859 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1861 result = operandFromValue (valMinus (left->operand.valOperand,
1862 right->operand.valOperand));
1866 ic = newiCode ('-', left, right);
1868 IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
1872 return geniCodeDivision (result,
1873 operandFromLit (getSize (ltype->next)));
1876 /*-----------------------------------------------------------------*/
1877 /* geniCodeSubtract - generates code for subtraction */
1878 /*-----------------------------------------------------------------*/
1880 geniCodeSubtract (operand * left, operand * right)
1887 /* if they both pointers then */
1888 if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
1889 (IS_PTR (rtype) || IS_ARRAY (rtype)))
1890 return geniCodePtrPtrSubtract (left, right);
1892 /* if they are both literal then we know the result */
1893 if (IS_LITERAL (letype) && IS_LITERAL (retype)
1894 && left->isLiteral && right->isLiteral)
1895 return operandFromValue (valMinus (left->operand.valOperand,
1896 right->operand.valOperand));
1898 /* if left is an array or pointer */
1899 if (IS_PTR (ltype) || IS_ARRAY (ltype))
1901 isarray = left->isaddr;
1902 right = geniCodeMultiply (right,
1903 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
1904 resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
1907 { /* make them the same size */
1908 resType = usualBinaryConversions (&left, &right);
1911 ic = newiCode ('-', left, right);
1913 IC_RESULT (ic) = newiTempOperand (resType, 1);
1914 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
1916 /* if left or right is a float */
1917 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
1921 return IC_RESULT (ic);
1924 /*-----------------------------------------------------------------*/
1925 /* geniCodeAdd - generates iCode for addition */
1926 /*-----------------------------------------------------------------*/
1928 geniCodeAdd (operand * left, operand * right,int lvl)
1936 /* if left is an array then array access */
1937 if (IS_ARRAY (ltype))
1938 return geniCodeArray (left, right,lvl);
1940 /* if the right side is LITERAL zero */
1941 /* return the left side */
1942 if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
1945 /* if left is literal zero return right */
1946 if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
1949 /* if left is an array or pointer then size */
1952 isarray = left->isaddr;
1953 // there is no need to multiply with 1
1954 if (getSize(ltype->next)!=1) {
1955 size = operandFromLit (getSize (ltype->next));
1956 right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
1958 resType = copyLinkChain (ltype);
1961 { /* make them the same size */
1962 resType = usualBinaryConversions (&left, &right);
1965 /* if they are both literals then we know */
1966 if (IS_LITERAL (letype) && IS_LITERAL (retype)
1967 && left->isLiteral && right->isLiteral)
1968 return operandFromValue (valPlus (valFromType (letype),
1969 valFromType (retype)));
1971 ic = newiCode ('+', left, right);
1973 IC_RESULT (ic) = newiTempOperand (resType, 1);
1974 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
1976 /* if left or right is a float then support
1978 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
1983 return IC_RESULT (ic);
1987 /*-----------------------------------------------------------------*/
1988 /* aggrToPtr - changes an aggregate to pointer to an aggregate */
1989 /*-----------------------------------------------------------------*/
1991 aggrToPtr (sym_link * type, bool force)
1997 if (IS_PTR (type) && !force)
2000 etype = getSpec (type);
2004 /* if the output class is generic */
2005 if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER)
2006 DCL_PTR_CONST (ptype) = port->mem.code_ro;
2008 /* if the variable was declared a constant */
2009 /* then the pointer points to a constant */
2010 if (IS_CONSTANT (etype))
2011 DCL_PTR_CONST (ptype) = 1;
2013 /* the variable was volatile then pointer to volatile */
2014 if (IS_VOLATILE (etype))
2015 DCL_PTR_VOLATILE (ptype) = 1;
2019 /*-----------------------------------------------------------------*/
2020 /* geniCodeArray2Ptr - array to pointer */
2021 /*-----------------------------------------------------------------*/
2023 geniCodeArray2Ptr (operand * op)
2025 sym_link *optype = operandType (op);
2026 sym_link *opetype = getSpec (optype);
2028 /* set the pointer depending on the storage class */
2029 if ((DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2030 DCL_PTR_CONST (optype) = port->mem.code_ro;
2033 /* if the variable was declared a constant */
2034 /* then the pointer points to a constant */
2035 if (IS_CONSTANT (opetype))
2036 DCL_PTR_CONST (optype) = 1;
2038 /* the variable was volatile then pointer to volatile */
2039 if (IS_VOLATILE (opetype))
2040 DCL_PTR_VOLATILE (optype) = 1;
2046 /*-----------------------------------------------------------------*/
2047 /* geniCodeArray - array access */
2048 /*-----------------------------------------------------------------*/
2050 geniCodeArray (operand * left, operand * right,int lvl)
2053 sym_link *ltype = operandType (left);
2057 if (IS_PTR (ltype->next) && left->isaddr)
2059 left = geniCodeRValue (left, FALSE);
2061 return geniCodeDerefPtr (geniCodeAdd (left, right,lvl),lvl);
2064 right = geniCodeMultiply (right,
2065 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2067 /* we can check for limits here */
2068 if (isOperandLiteral (right) &&
2071 (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2073 werror (E_ARRAY_BOUND);
2074 right = operandFromLit (0);
2077 ic = newiCode ('+', left, right);
2079 IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2080 !IS_AGGREGATE (ltype->next) &&
2081 !IS_PTR (ltype->next))
2082 ? ltype : ltype->next), 0);
2084 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
2086 return IC_RESULT (ic);
2089 /*-----------------------------------------------------------------*/
2090 /* geniCodeStruct - generates intermediate code for structres */
2091 /*-----------------------------------------------------------------*/
2093 geniCodeStruct (operand * left, operand * right, bool islval)
2096 sym_link *type = operandType (left);
2097 sym_link *etype = getSpec (type);
2099 symbol *element = getStructElement (SPEC_STRUCT (etype),
2100 right->operand.symOperand);
2102 /* add the offset */
2103 ic = newiCode ('+', left, operandFromLit (element->offset));
2105 IC_RESULT (ic) = newiTempOperand (element->type, 0);
2107 /* preserve the storage & output class of the struct */
2108 /* as well as the volatile attribute */
2109 retype = getSpec (operandType (IC_RESULT (ic)));
2110 SPEC_SCLS (retype) = SPEC_SCLS (etype);
2111 SPEC_OCLS (retype) = SPEC_OCLS (etype);
2112 SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2114 if (IS_PTR (element->type))
2115 setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2117 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2121 return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2124 /*-----------------------------------------------------------------*/
2125 /* geniCodePostInc - generate int code for Post increment */
2126 /*-----------------------------------------------------------------*/
2128 geniCodePostInc (operand * op)
2132 sym_link *optype = operandType (op);
2134 operand *rv = (IS_ITEMP (op) ?
2135 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2137 sym_link *rvtype = operandType (rv);
2140 /* if this is not an address we have trouble */
2143 werror (E_LVALUE_REQUIRED, "++");
2147 rOp = newiTempOperand (rvtype, 0);
2148 OP_SYMBOL(rOp)->noSpilLoc = 1;
2151 OP_SYMBOL(rv)->noSpilLoc = 1;
2153 geniCodeAssign (rOp, rv, 0);
2155 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2156 if (IS_FLOAT (rvtype))
2157 ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2159 ic = newiCode ('+', rv, operandFromLit (size));
2161 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2164 geniCodeAssign (op, result, 0);
2170 /*-----------------------------------------------------------------*/
2171 /* geniCodePreInc - generate code for preIncrement */
2172 /*-----------------------------------------------------------------*/
2174 geniCodePreInc (operand * op)
2177 sym_link *optype = operandType (op);
2178 operand *rop = (IS_ITEMP (op) ?
2179 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2181 sym_link *roptype = operandType (rop);
2187 werror (E_LVALUE_REQUIRED, "++");
2192 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2193 if (IS_FLOAT (roptype))
2194 ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2196 ic = newiCode ('+', rop, operandFromLit (size));
2197 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2201 return geniCodeAssign (op, result, 0);
2204 /*-----------------------------------------------------------------*/
2205 /* geniCodePostDec - generates code for Post decrement */
2206 /*-----------------------------------------------------------------*/
2208 geniCodePostDec (operand * op)
2212 sym_link *optype = operandType (op);
2214 operand *rv = (IS_ITEMP (op) ?
2215 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2217 sym_link *rvtype = operandType (rv);
2220 /* if this is not an address we have trouble */
2223 werror (E_LVALUE_REQUIRED, "--");
2227 rOp = newiTempOperand (rvtype, 0);
2228 OP_SYMBOL(rOp)->noSpilLoc = 1;
2231 OP_SYMBOL(rv)->noSpilLoc = 1;
2233 geniCodeAssign (rOp, rv, 0);
2235 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2236 if (IS_FLOAT (rvtype))
2237 ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2239 ic = newiCode ('-', rv, operandFromLit (size));
2241 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2244 geniCodeAssign (op, result, 0);
2250 /*-----------------------------------------------------------------*/
2251 /* geniCodePreDec - generate code for pre decrement */
2252 /*-----------------------------------------------------------------*/
2254 geniCodePreDec (operand * op)
2257 sym_link *optype = operandType (op);
2258 operand *rop = (IS_ITEMP (op) ?
2259 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2261 sym_link *roptype = operandType (rop);
2267 werror (E_LVALUE_REQUIRED, "--");
2272 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2273 if (IS_FLOAT (roptype))
2274 ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2276 ic = newiCode ('-', rop, operandFromLit (size));
2277 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2281 return geniCodeAssign (op, result, 0);
2285 /*-----------------------------------------------------------------*/
2286 /* geniCodeBitwise - gen int code for bitWise operators */
2287 /*-----------------------------------------------------------------*/
2289 geniCodeBitwise (operand * left, operand * right,
2290 int oper, sym_link * resType)
2294 left = geniCodeCast (resType, left, TRUE);
2295 right = geniCodeCast (resType, right, TRUE);
2297 ic = newiCode (oper, left, right);
2298 IC_RESULT (ic) = newiTempOperand (resType, 0);
2301 return IC_RESULT (ic);
2304 /*-----------------------------------------------------------------*/
2305 /* geniCodeAddressOf - gens icode for '&' address of operator */
2306 /*-----------------------------------------------------------------*/
2308 geniCodeAddressOf (operand * op)
2312 sym_link *optype = operandType (op);
2313 sym_link *opetype = getSpec (optype);
2315 /* lvalue check already done in decorateType */
2316 /* this must be a lvalue */
2317 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2318 /* werror (E_LVALUE_REQUIRED,"&"); */
2323 p->class = DECLARATOR;
2325 /* set the pointer depending on the storage class */
2326 if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2327 DCL_PTR_CONST (p) = port->mem.code_ro;
2329 /* make sure we preserve the const & volatile */
2330 if (IS_CONSTANT (opetype))
2331 DCL_PTR_CONST (p) = 1;
2333 if (IS_VOLATILE (opetype))
2334 DCL_PTR_VOLATILE (p) = 1;
2336 p->next = copyLinkChain (optype);
2338 /* if already a temp */
2341 setOperandType (op, p);
2346 /* other wise make this of the type coming in */
2347 ic = newiCode (ADDRESS_OF, op, NULL);
2348 IC_RESULT (ic) = newiTempOperand (p, 1);
2349 IC_RESULT (ic)->isaddr = 0;
2351 return IC_RESULT (ic);
2353 /*-----------------------------------------------------------------*/
2354 /* setOClass - sets the output class depending on the pointer type */
2355 /*-----------------------------------------------------------------*/
2357 setOClass (sym_link * ptr, sym_link * spec)
2359 switch (DCL_TYPE (ptr))
2362 SPEC_OCLS (spec) = data;
2366 SPEC_OCLS (spec) = generic;
2370 SPEC_OCLS (spec) = xdata;
2374 SPEC_OCLS (spec) = code;
2378 SPEC_OCLS (spec) = idata;
2382 SPEC_OCLS (spec) = xstack;
2386 SPEC_OCLS (spec) = eeprom;
2395 /*-----------------------------------------------------------------*/
2396 /* geniCodeDerefPtr - dereference pointer with '*' */
2397 /*-----------------------------------------------------------------*/
2399 geniCodeDerefPtr (operand * op,int lvl)
2401 sym_link *rtype, *retype;
2402 sym_link *optype = operandType (op);
2404 /* if this is a pointer then generate the rvalue */
2405 if (IS_PTR (optype))
2407 if (IS_TRUE_SYMOP (op))
2410 op = geniCodeRValue (op, TRUE);
2413 op = geniCodeRValue (op, TRUE);
2416 /* now get rid of the pointer part */
2417 if (isLvaluereq(lvl) && IS_ITEMP (op))
2419 retype = getSpec (rtype = copyLinkChain (optype));
2423 retype = getSpec (rtype = copyLinkChain (optype->next));
2426 /* if this is a pointer then outputclass needs 2b updated */
2427 if (IS_PTR (optype))
2428 setOClass (optype, retype);
2430 op->isGptr = IS_GENPTR (optype);
2432 /* if the pointer was declared as a constant */
2433 /* then we cannot allow assignment to the derefed */
2434 if (IS_PTR_CONST (optype))
2435 SPEC_CONST (retype) = 1;
2437 op->isaddr = (IS_PTR (rtype) ||
2438 IS_STRUCT (rtype) ||
2443 if (!isLvaluereq(lvl))
2444 op = geniCodeRValue (op, TRUE);
2446 setOperandType (op, rtype);
2451 /*-----------------------------------------------------------------*/
2452 /* geniCodeUnaryMinus - does a unary minus of the operand */
2453 /*-----------------------------------------------------------------*/
2455 geniCodeUnaryMinus (operand * op)
2458 sym_link *optype = operandType (op);
2460 if (IS_LITERAL (optype))
2461 return operandFromLit (-floatFromVal (op->operand.valOperand));
2463 ic = newiCode (UNARYMINUS, op, NULL);
2464 IC_RESULT (ic) = newiTempOperand (optype, 0);
2466 return IC_RESULT (ic);
2469 /*-----------------------------------------------------------------*/
2470 /* geniCodeLeftShift - gen i code for left shift */
2471 /*-----------------------------------------------------------------*/
2473 geniCodeLeftShift (operand * left, operand * right)
2477 ic = newiCode (LEFT_OP, left, right);
2478 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2480 return IC_RESULT (ic);
2483 /*-----------------------------------------------------------------*/
2484 /* geniCodeRightShift - gen i code for right shift */
2485 /*-----------------------------------------------------------------*/
2487 geniCodeRightShift (operand * left, operand * right)
2491 ic = newiCode (RIGHT_OP, left, right);
2492 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2494 return IC_RESULT (ic);
2497 /*-----------------------------------------------------------------*/
2498 /* geniCodeLogic- logic code */
2499 /*-----------------------------------------------------------------*/
2501 geniCodeLogic (operand * left, operand * right, int op)
2505 sym_link *rtype = operandType (right);
2506 sym_link *ltype = operandType (left);
2508 /* left is integral type and right is literal then
2509 check if the literal value is within bounds */
2510 if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2512 checkConstantRange(ltype,
2513 OP_VALUE(right), "compare operation", 1);
2516 ctype = usualBinaryConversions (&left, &right);
2518 ic = newiCode (op, left, right);
2519 IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2521 /* if comparing float
2522 and not a '==' || '!=' || '&&' || '||' (these
2524 if (IS_FLOAT(ctype) &&
2532 return IC_RESULT (ic);
2535 /*-----------------------------------------------------------------*/
2536 /* geniCodeUnary - for a a generic unary operation */
2537 /*-----------------------------------------------------------------*/
2539 geniCodeUnary (operand * op, int oper)
2541 iCode *ic = newiCode (oper, op, NULL);
2543 IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2545 return IC_RESULT (ic);
2548 /*-----------------------------------------------------------------*/
2549 /* geniCodeConditional - geniCode for '?' ':' operation */
2550 /*-----------------------------------------------------------------*/
2552 geniCodeConditional (ast * tree,int lvl)
2555 symbol *falseLabel = newiTempLabel (NULL);
2556 symbol *exitLabel = newiTempLabel (NULL);
2557 operand *cond = ast2iCode (tree->left,lvl+1);
2558 operand *true, *false, *result;
2560 ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
2564 true = ast2iCode (tree->right->left,lvl+1);
2566 /* move the value to a new Operand */
2567 result = newiTempOperand (operandType (true), 0);
2568 geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
2570 /* generate an unconditional goto */
2571 geniCodeGoto (exitLabel);
2573 /* now for the right side */
2574 geniCodeLabel (falseLabel);
2576 false = ast2iCode (tree->right->right,lvl+1);
2577 geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
2579 /* create the exit label */
2580 geniCodeLabel (exitLabel);
2585 /*-----------------------------------------------------------------*/
2586 /* geniCodeAssign - generate code for assignment */
2587 /*-----------------------------------------------------------------*/
2589 geniCodeAssign (operand * left, operand * right, int nosupdate)
2592 sym_link *ltype = operandType (left);
2593 sym_link *rtype = operandType (right);
2595 if (!left->isaddr && !IS_ITEMP (left))
2597 werror (E_LVALUE_REQUIRED, "assignment");
2601 /* left is integral type and right is literal then
2602 check if the literal value is within bounds */
2603 if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
2605 checkConstantRange(ltype,
2606 OP_VALUE(right), "= operation", 0);
2609 /* if the left & right type don't exactly match */
2610 /* if pointer set then make sure the check is
2611 done with the type & not the pointer */
2612 /* then cast rights type to left */
2614 /* first check the type for pointer assignement */
2615 if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
2616 compareType (ltype, rtype) <= 0)
2618 if (compareType (ltype->next, rtype) < 0)
2619 right = geniCodeCast (ltype->next, right, TRUE);
2621 else if (compareType (ltype, rtype) < 0)
2622 right = geniCodeCast (ltype, right, TRUE);
2624 /* if left is a true symbol & ! volatile
2625 create an assignment to temporary for
2626 the right & then assign this temporary
2627 to the symbol this is SSA . isn't it simple
2628 and folks have published mountains of paper on it */
2629 if (IS_TRUE_SYMOP (left) &&
2630 !isOperandVolatile (left, FALSE) &&
2631 isOperandGlobal (left))
2635 if (IS_TRUE_SYMOP (right))
2636 sym = OP_SYMBOL (right);
2637 ic = newiCode ('=', NULL, right);
2638 IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
2639 SPIL_LOC (right) = sym;
2643 ic = newiCode ('=', NULL, right);
2644 IC_RESULT (ic) = left;
2647 /* if left isgptr flag is set then support
2648 routine will be required */
2652 ic->nosupdate = nosupdate;
2656 /*-----------------------------------------------------------------*/
2657 /* geniCodeSEParms - generate code for side effecting fcalls */
2658 /*-----------------------------------------------------------------*/
2660 geniCodeSEParms (ast * parms,int lvl)
2665 if (parms->type == EX_OP && parms->opval.op == PARAM)
2667 geniCodeSEParms (parms->left,lvl);
2668 geniCodeSEParms (parms->right,lvl);
2672 /* hack don't like this but too lazy to think of
2674 if (IS_ADDRESS_OF_OP (parms))
2675 parms->left->lvalue = 1;
2677 if (IS_CAST_OP (parms) &&
2678 IS_PTR (parms->ftype) &&
2679 IS_ADDRESS_OF_OP (parms->right))
2680 parms->right->left->lvalue = 1;
2682 parms->opval.oprnd =
2683 geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2685 parms->type = EX_OPERAND;
2688 /*-----------------------------------------------------------------*/
2689 /* geniCodeParms - generates parameters */
2690 /*-----------------------------------------------------------------*/
2692 geniCodeParms (ast * parms, value *argVals, int *stack,
2693 sym_link * fetype, symbol * func,int lvl)
2701 if (argVals==NULL) {
2703 argVals=FUNC_ARGS(func->type);
2706 /* if this is a param node then do the left & right */
2707 if (parms->type == EX_OP && parms->opval.op == PARAM)
2709 argVals=geniCodeParms (parms->left, argVals, stack, fetype, func,lvl);
2710 argVals=geniCodeParms (parms->right, argVals, stack, fetype, func,lvl);
2714 /* get the parameter value */
2715 if (parms->type == EX_OPERAND)
2716 pval = parms->opval.oprnd;
2719 /* maybe this else should go away ?? */
2720 /* hack don't like this but too lazy to think of
2722 if (IS_ADDRESS_OF_OP (parms))
2723 parms->left->lvalue = 1;
2725 if (IS_CAST_OP (parms) &&
2726 IS_PTR (parms->ftype) &&
2727 IS_ADDRESS_OF_OP (parms->right))
2728 parms->right->left->lvalue = 1;
2730 pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2733 /* if register parm then make it a send */
2734 if (IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(func->type))
2736 ic = newiCode (SEND, pval, NULL);
2741 /* now decide whether to push or assign */
2742 if (!(options.stackAuto || IFFUNC_ISREENT (func->type)))
2746 operand *top = operandFromSymbol (argVals->sym);
2747 geniCodeAssign (top, pval, 1);
2751 sym_link *p = operandType (pval);
2753 ic = newiCode (IPUSH, pval, NULL);
2755 /* update the stack adjustment */
2756 *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2761 argVals=argVals->next;
2765 /*-----------------------------------------------------------------*/
2766 /* geniCodeCall - generates temp code for calling */
2767 /*-----------------------------------------------------------------*/
2769 geniCodeCall (operand * left, ast * parms,int lvl)
2773 sym_link *type, *etype;
2776 if (!IS_FUNC(OP_SYMBOL(left)->type) &&
2777 !IS_CODEPTR(OP_SYMBOL(left)->type)) {
2778 werror (E_FUNCTION_EXPECTED);
2782 /* take care of parameters with side-effecting
2783 function calls in them, this is required to take care
2784 of overlaying function parameters */
2785 geniCodeSEParms (parms,lvl);
2787 /* first the parameters */
2788 geniCodeParms (parms, NULL, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
2790 /* now call : if symbol then pcall */
2791 if (IS_OP_POINTER (left) || IS_ITEMP(left))
2792 ic = newiCode (PCALL, left, NULL);
2794 ic = newiCode (CALL, left, NULL);
2796 type = copyLinkChain (operandType (left)->next);
2797 etype = getSpec (type);
2798 SPEC_EXTR (etype) = 0;
2799 IC_RESULT (ic) = result = newiTempOperand (type, 1);
2803 /* stack adjustment after call */
2804 ic->parmBytes = stack;
2809 /*-----------------------------------------------------------------*/
2810 /* geniCodeReceive - generate intermediate code for "receive" */
2811 /*-----------------------------------------------------------------*/
2813 geniCodeReceive (value * args)
2815 /* for all arguments that are passed in registers */
2819 if (IS_REGPARM (args->etype))
2821 operand *opr = operandFromValue (args);
2823 symbol *sym = OP_SYMBOL (opr);
2826 /* we will use it after all optimizations
2827 and before liveRange calculation */
2828 if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
2831 if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
2832 options.stackAuto == 0 &&
2833 /* !TARGET_IS_DS390) */
2834 (!(options.model == MODEL_FLAT24)) )
2839 opl = newiTempOperand (args->type, 0);
2841 sym->reqv->key = sym->key;
2842 OP_SYMBOL (sym->reqv)->key = sym->key;
2843 OP_SYMBOL (sym->reqv)->isreqv = 1;
2844 OP_SYMBOL (sym->reqv)->islocal = 0;
2845 SPIL_LOC (sym->reqv) = sym;
2849 ic = newiCode (RECEIVE, NULL, NULL);
2850 currFunc->recvSize = getSize (sym->etype);
2851 IC_RESULT (ic) = opr;
2859 /*-----------------------------------------------------------------*/
2860 /* geniCodeFunctionBody - create the function body */
2861 /*-----------------------------------------------------------------*/
2863 geniCodeFunctionBody (ast * tree,int lvl)
2870 /* reset the auto generation */
2876 func = ast2iCode (tree->left,lvl+1);
2877 fetype = getSpec (operandType (func));
2879 savelineno = lineno;
2880 lineno = OP_SYMBOL (func)->lineDef;
2881 /* create an entry label */
2882 geniCodeLabel (entryLabel);
2883 lineno = savelineno;
2885 /* create a proc icode */
2886 ic = newiCode (FUNCTION, func, NULL);
2887 ic->lineno = OP_SYMBOL (func)->lineDef;
2891 /* for all parameters that are passed
2892 on registers add a "receive" */
2893 geniCodeReceive (tree->values.args);
2895 /* generate code for the body */
2896 ast2iCode (tree->right,lvl+1);
2898 /* create a label for return */
2899 geniCodeLabel (returnLabel);
2901 /* now generate the end proc */
2902 ic = newiCode (ENDFUNCTION, func, NULL);
2907 /*-----------------------------------------------------------------*/
2908 /* geniCodeReturn - gen icode for 'return' statement */
2909 /*-----------------------------------------------------------------*/
2911 geniCodeReturn (operand * op)
2915 /* if the operand is present force an rvalue */
2917 op = geniCodeRValue (op, FALSE);
2919 ic = newiCode (RETURN, op, NULL);
2923 /*-----------------------------------------------------------------*/
2924 /* geniCodeIfx - generates code for extended if statement */
2925 /*-----------------------------------------------------------------*/
2927 geniCodeIfx (ast * tree,int lvl)
2930 operand *condition = ast2iCode (tree->left,lvl+1);
2933 /* if condition is null then exit */
2937 condition = geniCodeRValue (condition, FALSE);
2939 cetype = getSpec (operandType (condition));
2940 /* if the condition is a literal */
2941 if (IS_LITERAL (cetype))
2943 if (floatFromVal (condition->operand.valOperand))
2945 if (tree->trueLabel)
2946 geniCodeGoto (tree->trueLabel);
2952 if (tree->falseLabel)
2953 geniCodeGoto (tree->falseLabel);
2960 if (tree->trueLabel)
2962 ic = newiCodeCondition (condition,
2967 if (tree->falseLabel)
2968 geniCodeGoto (tree->falseLabel);
2972 ic = newiCodeCondition (condition,
2979 ast2iCode (tree->right,lvl+1);
2982 /*-----------------------------------------------------------------*/
2983 /* geniCodeJumpTable - tries to create a jump table for switch */
2984 /*-----------------------------------------------------------------*/
2986 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
2988 int min = 0, max = 0, t, cnt = 0;
2995 if (!tree || !caseVals)
2998 /* the criteria for creating a jump table is */
2999 /* all integer numbers between the maximum & minimum must */
3000 /* be present , the maximum value should not exceed 255 */
3001 min = max = (int) floatFromVal (vch = caseVals);
3002 sprintf (buffer, "_case_%d_%d",
3003 tree->values.switchVals.swNum,
3005 addSet (&labels, newiTempLabel (buffer));
3007 /* if there is only one case value then no need */
3008 if (!(vch = vch->next))
3013 if (((t = (int) floatFromVal (vch)) - max) != 1)
3015 sprintf (buffer, "_case_%d_%d",
3016 tree->values.switchVals.swNum,
3018 addSet (&labels, newiTempLabel (buffer));
3024 /* if the number of case statements <= 2 then */
3025 /* it is not economical to create the jump table */
3026 /* since two compares are needed for boundary conditions */
3027 if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
3030 if (tree->values.switchVals.swDefault)
3031 sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3033 sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3035 falseLabel = newiTempLabel (buffer);
3037 /* so we can create a jumptable */
3038 /* first we rule out the boundary conditions */
3039 /* if only optimization says so */
3040 if (!optimize.noJTabBoundary)
3042 sym_link *cetype = getSpec (operandType (cond));
3043 /* no need to check the lower bound if
3044 the condition is unsigned & minimum value is zero */
3045 if (!(min == 0 && SPEC_USIGN (cetype)))
3047 boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3048 ic = newiCodeCondition (boundary, falseLabel, NULL);
3052 /* now for upper bounds */
3053 boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3054 ic = newiCodeCondition (boundary, falseLabel, NULL);
3058 /* if the min is not zero then we no make it zero */
3061 cond = geniCodeSubtract (cond, operandFromLit (min));
3062 setOperandType (cond, UCHARTYPE);
3065 /* now create the jumptable */
3066 ic = newiCode (JUMPTABLE, NULL, NULL);
3067 IC_JTCOND (ic) = cond;
3068 IC_JTLABELS (ic) = labels;
3073 /*-----------------------------------------------------------------*/
3074 /* geniCodeSwitch - changes a switch to a if statement */
3075 /*-----------------------------------------------------------------*/
3077 geniCodeSwitch (ast * tree,int lvl)
3080 operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3081 value *caseVals = tree->values.switchVals.swVals;
3082 symbol *trueLabel, *falseLabel;
3084 /* if we can make this a jump table */
3085 if (geniCodeJumpTable (cond, caseVals, tree))
3086 goto jumpTable; /* no need for the comparison */
3088 /* for the cases defined do */
3092 operand *compare = geniCodeLogic (cond,
3093 operandFromValue (caseVals),
3096 sprintf (buffer, "_case_%d_%d",
3097 tree->values.switchVals.swNum,
3098 (int) floatFromVal (caseVals));
3099 trueLabel = newiTempLabel (buffer);
3101 ic = newiCodeCondition (compare, trueLabel, NULL);
3103 caseVals = caseVals->next;
3108 /* if default is present then goto break else break */
3109 if (tree->values.switchVals.swDefault)
3110 sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3112 sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3114 falseLabel = newiTempLabel (buffer);
3115 geniCodeGoto (falseLabel);
3118 ast2iCode (tree->right,lvl+1);
3121 /*-----------------------------------------------------------------*/
3122 /* geniCodeInline - intermediate code for inline assembler */
3123 /*-----------------------------------------------------------------*/
3125 geniCodeInline (ast * tree)
3129 ic = newiCode (INLINEASM, NULL, NULL);
3130 IC_INLINE (ic) = tree->values.inlineasm;
3134 /*-----------------------------------------------------------------*/
3135 /* geniCodeArrayInit - intermediate code for array initializer */
3136 /*-----------------------------------------------------------------*/
3138 geniCodeArrayInit (ast * tree, operand *array)
3142 if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3143 ic = newiCode (ARRAYINIT, array, NULL);
3144 IC_ARRAYILIST (ic) = tree->values.constlist;
3146 operand *left=newOperand(), *right=newOperand();
3147 left->type=right->type=SYMBOL;
3148 OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3149 OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3150 ic = newiCode (ARRAYINIT, left, right);
3155 /*-----------------------------------------------------------------*/
3156 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
3157 /* particular case. Ie : assigning or dereferencing array or ptr */
3158 /*-----------------------------------------------------------------*/
3159 set * lvaluereqSet = NULL;
3160 typedef struct lvalItem
3167 /*-----------------------------------------------------------------*/
3168 /* addLvaluereq - add a flag for lvalreq for current ast level */
3169 /*-----------------------------------------------------------------*/
3170 void addLvaluereq(int lvl)
3172 lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3175 addSetHead(&lvaluereqSet,lpItem);
3178 /*-----------------------------------------------------------------*/
3179 /* delLvaluereq - del a flag for lvalreq for current ast level */
3180 /*-----------------------------------------------------------------*/
3184 lpItem = getSet(&lvaluereqSet);
3185 if(lpItem) Safe_free(lpItem);
3187 /*-----------------------------------------------------------------*/
3188 /* clearLvaluereq - clear lvalreq flag */
3189 /*-----------------------------------------------------------------*/
3190 void clearLvaluereq()
3193 lpItem = peekSet(lvaluereqSet);
3194 if(lpItem) lpItem->req = 0;
3196 /*-----------------------------------------------------------------*/
3197 /* getLvaluereq - get the last lvalreq level */
3198 /*-----------------------------------------------------------------*/
3199 int getLvaluereqLvl()
3202 lpItem = peekSet(lvaluereqSet);
3203 if(lpItem) return lpItem->lvl;
3206 /*-----------------------------------------------------------------*/
3207 /* isLvaluereq - is lvalreq valid for this level ? */
3208 /*-----------------------------------------------------------------*/
3209 int isLvaluereq(int lvl)
3212 lpItem = peekSet(lvaluereqSet);
3213 if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3217 /*-----------------------------------------------------------------*/
3218 /* ast2iCode - creates an icodeList from an ast */
3219 /*-----------------------------------------------------------------*/
3221 ast2iCode (ast * tree,int lvl)
3223 operand *left = NULL;
3224 operand *right = NULL;
3227 /* set the global variables for filename & line number */
3229 filename = tree->filename;
3231 lineno = tree->lineno;
3233 block = tree->block;
3235 scopeLevel = tree->level;
3237 if (tree->type == EX_VALUE)
3238 return operandFromValue (tree->opval.val);
3240 if (tree->type == EX_LINK)
3241 return operandFromLink (tree->opval.lnk);
3243 /* if we find a nullop */
3244 if (tree->type == EX_OP &&
3245 (tree->opval.op == NULLOP ||
3246 tree->opval.op == BLOCK))
3248 ast2iCode (tree->left,lvl+1);
3249 ast2iCode (tree->right,lvl+1);
3253 /* special cases for not evaluating */
3254 if (tree->opval.op != ':' &&
3255 tree->opval.op != '?' &&
3256 tree->opval.op != CALL &&
3257 tree->opval.op != IFX &&
3258 tree->opval.op != LABEL &&
3259 tree->opval.op != GOTO &&
3260 tree->opval.op != SWITCH &&
3261 tree->opval.op != FUNCTION &&
3262 tree->opval.op != INLINEASM)
3265 if (IS_ASSIGN_OP (tree->opval.op) ||
3266 IS_DEREF_OP (tree) ||
3267 (tree->opval.op == '&' && !tree->right) ||
3268 tree->opval.op == PTR_OP)
3271 if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3272 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3275 left = operandFromAst (tree->left,lvl);
3277 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3278 left = geniCodeRValue (left, TRUE);
3282 left = operandFromAst (tree->left,lvl);
3284 if (tree->opval.op == INC_OP ||
3285 tree->opval.op == DEC_OP)
3288 right = operandFromAst (tree->right,lvl);
3293 right = operandFromAst (tree->right,lvl);
3297 /* now depending on the type of operand */
3298 /* this will be a biggy */
3299 switch (tree->opval.op)
3302 case '[': /* array operation */
3304 //sym_link *ltype = operandType (left);
3305 //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3306 left = geniCodeRValue (left, FALSE);
3307 right = geniCodeRValue (right, TRUE);
3310 return geniCodeArray (left, right,lvl);
3312 case '.': /* structure dereference */
3313 if (IS_PTR (operandType (left)))
3314 left = geniCodeRValue (left, TRUE);
3316 left = geniCodeRValue (left, FALSE);
3318 return geniCodeStruct (left, right, tree->lvalue);
3320 case PTR_OP: /* structure pointer dereference */
3323 pType = operandType (left);
3324 left = geniCodeRValue (left, TRUE);
3326 setOClass (pType, getSpec (operandType (left)));
3329 return geniCodeStruct (left, right, tree->lvalue);
3331 case INC_OP: /* increment operator */
3333 return geniCodePostInc (left);
3335 return geniCodePreInc (right);
3337 case DEC_OP: /* decrement operator */
3339 return geniCodePostDec (left);
3341 return geniCodePreDec (right);
3343 case '&': /* bitwise and or address of operator */
3345 { /* this is a bitwise operator */
3346 left = geniCodeRValue (left, FALSE);
3347 right = geniCodeRValue (right, FALSE);
3348 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3351 return geniCodeAddressOf (left);
3353 case '|': /* bitwise or & xor */
3355 return geniCodeBitwise (geniCodeRValue (left, FALSE),
3356 geniCodeRValue (right, FALSE),
3361 return geniCodeDivision (geniCodeRValue (left, FALSE),
3362 geniCodeRValue (right, FALSE));
3365 return geniCodeModulus (geniCodeRValue (left, FALSE),
3366 geniCodeRValue (right, FALSE));
3369 return geniCodeMultiply (geniCodeRValue (left, FALSE),
3370 geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3372 return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3376 return geniCodeSubtract (geniCodeRValue (left, FALSE),
3377 geniCodeRValue (right, FALSE));
3379 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3383 return geniCodeAdd (geniCodeRValue (left, FALSE),
3384 geniCodeRValue (right, FALSE),lvl);
3386 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
3389 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3390 geniCodeRValue (right, FALSE));
3393 return geniCodeRightShift (geniCodeRValue (left, FALSE),
3394 geniCodeRValue (right, FALSE));
3396 return geniCodeCast (operandType (left),
3397 geniCodeRValue (right, FALSE), FALSE);
3403 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3407 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3408 setOperandType (op, UCHARTYPE);
3419 return geniCodeLogic (geniCodeRValue (left, FALSE),
3420 geniCodeRValue (right, FALSE),
3423 return geniCodeConditional (tree,lvl);
3426 return operandFromLit (getSize (tree->right->ftype));
3430 sym_link *rtype = operandType (right);
3431 sym_link *ltype = operandType (left);
3432 if (IS_PTR (rtype) && IS_ITEMP (right)
3433 && right->isaddr && compareType (rtype->next, ltype) == 1)
3434 right = geniCodeRValue (right, TRUE);
3436 right = geniCodeRValue (right, FALSE);
3438 geniCodeAssign (left, right, 0);
3443 geniCodeAssign (left,
3444 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3446 geniCodeRValue (right, FALSE),FALSE), 0);
3450 geniCodeAssign (left,
3451 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3453 geniCodeRValue (right, FALSE)), 0);
3456 geniCodeAssign (left,
3457 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3459 geniCodeRValue (right, FALSE)), 0);
3462 sym_link *rtype = operandType (right);
3463 sym_link *ltype = operandType (left);
3464 if (IS_PTR (rtype) && IS_ITEMP (right)
3465 && right->isaddr && compareType (rtype->next, ltype) == 1)
3466 right = geniCodeRValue (right, TRUE);
3468 right = geniCodeRValue (right, FALSE);
3471 return geniCodeAssign (left,
3472 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3478 sym_link *rtype = operandType (right);
3479 sym_link *ltype = operandType (left);
3480 if (IS_PTR (rtype) && IS_ITEMP (right)
3481 && right->isaddr && compareType (rtype->next, ltype) == 1)
3483 right = geniCodeRValue (right, TRUE);
3487 right = geniCodeRValue (right, FALSE);
3490 geniCodeAssign (left,
3491 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3497 geniCodeAssign (left,
3498 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3500 geniCodeRValue (right, FALSE)), 0);
3503 geniCodeAssign (left,
3504 geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3506 geniCodeRValue (right, FALSE)), 0);
3509 geniCodeAssign (left,
3510 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3512 geniCodeRValue (right, FALSE),
3514 operandType (left)), 0);
3517 geniCodeAssign (left,
3518 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3520 geniCodeRValue (right, FALSE),
3522 operandType (left)), 0);
3525 geniCodeAssign (left,
3526 geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3528 geniCodeRValue (right, FALSE),
3530 operandType (left)), 0);
3532 return geniCodeRValue (right, FALSE);
3535 return geniCodeCall (ast2iCode (tree->left,lvl+1),
3538 geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3539 return ast2iCode (tree->right,lvl+1);
3542 geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3543 return ast2iCode (tree->right,lvl+1);
3546 geniCodeFunctionBody (tree,lvl);
3550 geniCodeReturn (right);
3554 geniCodeIfx (tree,lvl);
3558 geniCodeSwitch (tree,lvl);
3562 geniCodeInline (tree);
3566 geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
3573 /*-----------------------------------------------------------------*/
3574 /* reverseICChain - gets from the list and creates a linkedlist */
3575 /*-----------------------------------------------------------------*/
3582 while ((loop = getSet (&iCodeChain)))
3594 /*-----------------------------------------------------------------*/
3595 /* iCodeFromAst - given an ast will convert it to iCode */
3596 /*-----------------------------------------------------------------*/
3598 iCodeFromAst (ast * tree)
3600 returnLabel = newiTempLabel ("_return");
3601 entryLabel = newiTempLabel ("_entry");
3603 return reverseiCChain ();