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,
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;
181 #if 0 // temporary disabled, leaving the warning as a reminder
183 sprintf (message, "for %s %s in %s",
184 SPEC_USIGN(ltype) ? "unsigned" : "signed",
185 nounName(ltype), msg);
186 werror (W_CONST_RANGE, message);
194 /*-----------------------------------------------------------------*/
195 /* operandName - returns the name of the operand */
196 /*-----------------------------------------------------------------*/
198 printOperand (operand * op, FILE * file)
215 opetype = getSpec (operandType (op));
216 if (SPEC_NOUN (opetype) == V_FLOAT)
217 fprintf (file, "%g {", SPEC_CVAL (opetype).v_float);
219 fprintf (file, "0x%x {", (int) floatFromVal (op->operand.valOperand));
220 printTypeChain (operandType (op), file);
227 fprintf (file, "%s [k%d lr%d:%d so:%d]{ ia%d re%d rm%d nos%d ru%d dp%d}", /*{ar%d rm%d ru%d p%d a%d u%d i%d au%d k%d ks%d}" , */
228 (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name),
230 OP_LIVEFROM (op), OP_LIVETO (op),
231 OP_SYMBOL (op)->stack,
232 op->isaddr, OP_SYMBOL (op)->isreqv,
233 OP_SYMBOL (op)->remat,OP_SYMBOL(op)->noSpilLoc,
234 OP_SYMBOL(op)->ruonly,OP_SYMBOL(op)->dptr
238 printTypeChain (operandType (op), file);
239 if (SPIL_LOC (op) && IS_ITEMP (op))
240 fprintf (file, "}{ sir@ %s", SPIL_LOC (op)->rname);
245 /* if assigned to registers */
246 if (OP_SYMBOL (op)->nRegs)
248 if (OP_SYMBOL (op)->isspilt)
250 if (!OP_SYMBOL (op)->remat)
251 if (OP_SYMBOL (op)->usl.spillLoc)
252 fprintf (file, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
253 OP_SYMBOL (op)->usl.spillLoc->rname :
254 OP_SYMBOL (op)->usl.spillLoc->name));
256 fprintf (file, "[err]");
258 fprintf (file, "[remat]");
264 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
265 fprintf (file, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i]));
270 fprintf (file, "%s", (OP_SYMBOL (op)->rname[0] ?
271 OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name));
272 /* if assigned to registers */
273 if (OP_SYMBOL (op)->nRegs && !OP_SYMBOL (op)->isspilt)
277 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
278 fprintf (file, "%s ", (OP_SYMBOL (op)->regs[i] ?
279 OP_SYMBOL (op)->regs[i]->name :
288 printTypeChain (op->operand.typeOperand, file);
294 fprintf (file, "\n");
299 /*-----------------------------------------------------------------*/
300 /* print functions */
301 /*-----------------------------------------------------------------*/
302 PRINTFUNC (picGetValueAtAddr)
305 printOperand (IC_RESULT (ic), of);
308 printOperand (IC_LEFT (ic), of);
314 PRINTFUNC (picSetValueAtAddr)
318 printOperand (IC_LEFT (ic), of);
319 fprintf (of, "] = ");
320 printOperand (IC_RIGHT (ic), of);
324 PRINTFUNC (picAddrOf)
327 printOperand (IC_RESULT (ic), of);
328 if (IS_ITEMP (IC_LEFT (ic)))
331 fprintf (of, " = &[");
332 printOperand (IC_LEFT (ic), of);
335 if (IS_ITEMP (IC_LEFT (ic)))
336 fprintf (of, " offsetAdd ");
339 printOperand (IC_RIGHT (ic), of);
341 if (IS_ITEMP (IC_LEFT (ic)))
347 PRINTFUNC (picJumpTable)
352 fprintf (of, "%s\t", s);
353 printOperand (IC_JTCOND (ic), of);
355 for (sym = setFirstItem (IC_JTLABELS (ic)); sym;
356 sym = setNextItem (IC_JTLABELS (ic)))
357 fprintf (of, "\t\t\t%s\n", sym->name);
360 PRINTFUNC (picGeneric)
363 printOperand (IC_RESULT (ic), of);
365 printOperand (IC_LEFT (ic), of);
366 fprintf (of, " %s ", s);
367 printOperand (IC_RIGHT (ic), of);
371 PRINTFUNC (picGenericOne)
376 printOperand (IC_RESULT (ic), of);
382 fprintf (of, "%s ", s);
383 printOperand (IC_LEFT (ic), of);
386 if (!IC_RESULT (ic) && !IC_LEFT (ic))
389 if (ic->op == SEND || ic->op == RECEIVE) {
390 fprintf(of,"{argreg = %d}",ic->argreg);
398 printOperand (IC_RESULT (ic), of);
400 printOperand (IC_LEFT (ic), of);
401 printOperand (IC_RIGHT (ic), of);
406 PRINTFUNC (picAssign)
410 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
413 printOperand (IC_RESULT (ic), of);
415 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
418 fprintf (of, " %s ", s);
419 printOperand (IC_RIGHT (ic), of);
426 fprintf (of, " %s($%d) :\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
432 fprintf (of, " goto %s($%d)\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
439 printOperand (IC_COND (ic), of);
442 fprintf (of, " == 0 goto %s($%d)\n", IC_FALSE (ic)->name, IC_FALSE (ic)->key);
445 fprintf (of, " != 0 goto %s($%d)\n", IC_TRUE (ic)->name, IC_TRUE (ic)->key);
447 fprintf (of, "\tzzgoto %s\n", IC_FALSE (ic)->name);
451 PRINTFUNC (picInline)
453 fprintf (of, "%s", IC_INLINE (ic));
456 PRINTFUNC (picReceive)
458 printOperand (IC_RESULT (ic), of);
459 fprintf (of, " = %s ", s);
460 printOperand (IC_LEFT (ic), of);
464 /*-----------------------------------------------------------------*/
465 /* piCode - prints one iCode */
466 /*-----------------------------------------------------------------*/
468 piCode (void *item, FILE * of)
476 icTab = getTableEntry (ic->op);
477 fprintf (stdout, "%s(%d:%d:%d:%d:%d)\t",
478 ic->filename, ic->lineno,
479 ic->seq, ic->key, ic->depth, ic->supportRtn);
480 icTab->iCodePrint (of, ic, icTab->printName);
486 printiCChain(ic,stdout);
488 /*-----------------------------------------------------------------*/
489 /* printiCChain - prints intermediate code for humans */
490 /*-----------------------------------------------------------------*/
492 printiCChain (iCode * icChain, FILE * of)
499 for (loop = icChain; loop; loop = loop->next)
501 if ((icTab = getTableEntry (loop->op)))
503 fprintf (of, "%s(%d:%d:%d:%d:%d)\t",
504 loop->filename, loop->lineno,
505 loop->seq, loop->key, loop->depth, loop->supportRtn);
507 icTab->iCodePrint (of, loop, icTab->printName);
513 /*-----------------------------------------------------------------*/
514 /* newOperand - allocate, init & return a new iCode */
515 /*-----------------------------------------------------------------*/
521 op = Safe_alloc ( sizeof (operand));
527 /*-----------------------------------------------------------------*/
528 /* newiCode - create and return a new iCode entry initialised */
529 /*-----------------------------------------------------------------*/
531 newiCode (int op, operand * left, operand * right)
535 ic = Safe_alloc ( sizeof (iCode));
538 ic->filename = filename;
540 ic->level = scopeLevel;
542 ic->key = iCodeKey++;
544 IC_RIGHT (ic) = right;
549 /*-----------------------------------------------------------------*/
550 /* newiCode for conditional statements */
551 /*-----------------------------------------------------------------*/
553 newiCodeCondition (operand * condition,
559 if (IS_VOID(operandType(condition))) {
560 werror(E_VOID_VALUE_USED);
563 ic = newiCode (IFX, NULL, NULL);
564 IC_COND (ic) = condition;
565 IC_TRUE (ic) = trueLabel;
566 IC_FALSE (ic) = falseLabel;
570 /*-----------------------------------------------------------------*/
571 /* newiCodeLabelGoto - unconditional goto statement| label stmnt */
572 /*-----------------------------------------------------------------*/
574 newiCodeLabelGoto (int op, symbol * label)
578 ic = newiCode (op, NULL, NULL);
580 ic->argLabel.label = label;
582 IC_RIGHT (ic) = NULL;
583 IC_RESULT (ic) = NULL;
587 /*-----------------------------------------------------------------*/
588 /* newiTemp - allocate & return a newItemp Variable */
589 /*-----------------------------------------------------------------*/
596 sprintf (buffer, "%s", s);
598 sprintf (buffer, "iTemp%d", iTempNum++);
599 itmp = newSymbol (buffer, 1);
600 strcpy (itmp->rname, itmp->name);
606 /*-----------------------------------------------------------------*/
607 /* newiTempLabel - creates a temp variable label */
608 /*-----------------------------------------------------------------*/
610 newiTempLabel (char *s)
614 /* check if this alredy exists */
615 if (s && (itmplbl = findSym (LabelTab, NULL, s)))
619 itmplbl = newSymbol (s, 1);
622 sprintf (buffer, "iTempLbl%d", iTempLblNum++);
623 itmplbl = newSymbol (buffer, 1);
628 itmplbl->key = labelKey++;
629 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
633 /*-----------------------------------------------------------------*/
634 /* newiTempPreheaderLabel - creates a new preheader label */
635 /*-----------------------------------------------------------------*/
637 newiTempPreheaderLabel ()
641 sprintf (buffer, "preHeaderLbl%d", iTempLblNum++);
642 itmplbl = newSymbol (buffer, 1);
646 itmplbl->key = labelKey++;
647 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
652 /*-----------------------------------------------------------------*/
653 /* initiCode - initialises some iCode related stuff */
654 /*-----------------------------------------------------------------*/
661 /*-----------------------------------------------------------------*/
662 /* copyiCode - make a copy of the iCode given */
663 /*-----------------------------------------------------------------*/
665 copyiCode (iCode * ic)
667 iCode *nic = newiCode (ic->op, NULL, NULL);
669 nic->lineno = ic->lineno;
670 nic->filename = ic->filename;
671 nic->block = ic->block;
672 nic->level = ic->level;
673 nic->parmBytes = ic->parmBytes;
675 /* deal with the special cases first */
679 IC_COND (nic) = operandFromOperand (IC_COND (ic));
680 IC_TRUE (nic) = IC_TRUE (ic);
681 IC_FALSE (nic) = IC_FALSE (ic);
685 IC_JTCOND (nic) = operandFromOperand (IC_JTCOND (ic));
686 IC_JTLABELS (nic) = IC_JTLABELS (ic);
691 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
692 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
696 IC_INLINE (nic) = IC_INLINE (ic);
700 IC_ARRAYILIST(nic) = IC_ARRAYILIST(ic);
704 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
705 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
706 IC_RIGHT (nic) = operandFromOperand (IC_RIGHT (ic));
712 /*-----------------------------------------------------------------*/
713 /* getTableEntry - gets the table entry for the given operator */
714 /*-----------------------------------------------------------------*/
716 getTableEntry (int oper)
720 for (i = 0; i < (sizeof (codeTable) / sizeof (iCodeTable)); i++)
721 if (oper == codeTable[i].icode)
722 return &codeTable[i];
727 /*-----------------------------------------------------------------*/
728 /* newiTempOperand - new intermediate temp operand */
729 /*-----------------------------------------------------------------*/
731 newiTempOperand (sym_link * type, char throwType)
734 operand *op = newOperand ();
738 itmp = newiTemp (NULL);
740 etype = getSpec (type);
742 if (IS_LITERAL (etype))
745 /* copy the type information */
747 itmp->etype = getSpec (itmp->type = (throwType ? type :
748 copyLinkChain (type)));
749 if (IS_LITERAL (itmp->etype))
751 SPEC_SCLS (itmp->etype) = S_REGISTER;
752 SPEC_OCLS (itmp->etype) = reg;
755 op->operand.symOperand = itmp;
756 op->key = itmp->key = ++operandKey;
760 /*-----------------------------------------------------------------*/
761 /* operandType - returns the type chain for an operand */
762 /*-----------------------------------------------------------------*/
764 operandType (operand * op)
766 /* depending on type of operand */
771 return op->operand.valOperand->type;
774 return op->operand.symOperand->type;
777 return op->operand.typeOperand;
779 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
780 " operand type not known ");
781 assert (0); /* should never come here */
782 /* Just to keep the compiler happy */
783 return (sym_link *) 0;
787 /*-----------------------------------------------------------------*/
788 /* isParamterToCall - will return 1 if op is a parameter to args */
789 /*-----------------------------------------------------------------*/
791 isParameterToCall (value * args, operand * op)
798 isSymbolEqual (op->operand.symOperand, tval->sym))
805 /*-----------------------------------------------------------------*/
806 /* isOperandGlobal - return 1 if operand is a global variable */
807 /*-----------------------------------------------------------------*/
809 isOperandGlobal (operand * op)
817 if (op->type == SYMBOL &&
818 (op->operand.symOperand->level == 0 ||
819 IS_STATIC (op->operand.symOperand->etype) ||
820 IS_EXTERN (op->operand.symOperand->etype))
827 /*-----------------------------------------------------------------*/
828 /* isOperandVolatile - return 1 if the operand is volatile */
829 /*-----------------------------------------------------------------*/
831 isOperandVolatile (operand * op, bool chkTemp)
836 if (IS_ITEMP (op) && !chkTemp)
839 opetype = getSpec (optype = operandType (op));
841 if (IS_PTR (optype) && DCL_PTR_VOLATILE (optype))
844 if (IS_VOLATILE (opetype))
849 /*-----------------------------------------------------------------*/
850 /* isOperandLiteral - returns 1 if an operand contains a literal */
851 /*-----------------------------------------------------------------*/
853 isOperandLiteral (operand * op)
860 opetype = getSpec (operandType (op));
862 if (IS_LITERAL (opetype))
868 /*-----------------------------------------------------------------*/
869 /* isOperandInFarSpace - will return true if operand is in farSpace */
870 /*-----------------------------------------------------------------*/
872 isOperandInFarSpace (operand * op)
882 if (!IS_TRUE_SYMOP (op))
885 etype = SPIL_LOC (op)->etype;
891 etype = getSpec (operandType (op));
893 return (IN_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
896 /*------------------------------------------------------------------*/
897 /* isOperandInDirSpace - will return true if operand is in dirSpace */
898 /*------------------------------------------------------------------*/
900 isOperandInDirSpace (operand * op)
910 if (!IS_TRUE_SYMOP (op))
913 etype = SPIL_LOC (op)->etype;
919 etype = getSpec (operandType (op));
921 return (IN_DIRSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
924 /*--------------------------------------------------------------------*/
925 /* isOperandInCodeSpace - will return true if operand is in codeSpace */
926 /*--------------------------------------------------------------------*/
928 isOperandInCodeSpace (operand * op)
938 etype = getSpec (operandType (op));
940 if (!IS_TRUE_SYMOP (op))
943 etype = SPIL_LOC (op)->etype;
949 etype = getSpec (operandType (op));
951 return (IN_CODESPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
954 /*-----------------------------------------------------------------*/
955 /* isOperandOnStack - will return true if operand is on stack */
956 /*-----------------------------------------------------------------*/
958 isOperandOnStack (operand * op)
968 etype = getSpec (operandType (op));
969 if (IN_STACK (etype) ||
970 OP_SYMBOL(op)->onStack ||
971 (SPIL_LOC(op) && SPIL_LOC(op)->onStack))
977 /*-----------------------------------------------------------------*/
978 /* operandLitValue - literal value of an operand */
979 /*-----------------------------------------------------------------*/
981 operandLitValue (operand * op)
983 assert (isOperandLiteral (op));
985 return floatFromVal (op->operand.valOperand);
988 /*-----------------------------------------------------------------*/
989 /* getBuiltInParms - returns parameters to a builtin functions */
990 /*-----------------------------------------------------------------*/
991 iCode *getBuiltinParms (iCode *ic, int *pcount, operand **parms)
996 /* builtin functions uses only SEND for parameters */
997 while (ic->op != CALL) {
998 assert(ic->op == SEND && ic->builtinSEND);
999 ic->generated = 1; /* mark the icode as generated */
1000 parms[*pcount] = IC_LEFT(ic);
1006 /* make sure this is a builtin function call */
1007 assert(IS_SYMOP(IC_LEFT(ic)));
1008 ftype = operandType(IC_LEFT(ic));
1009 assert(IFFUNC_ISBUILTIN(ftype));
1013 /*-----------------------------------------------------------------*/
1014 /* operandOperation - perforoms operations on operands */
1015 /*-----------------------------------------------------------------*/
1017 operandOperation (operand * left, operand * right,
1018 int op, sym_link * type)
1020 sym_link *let , *ret=NULL;
1021 operand *retval = (operand *) 0;
1023 assert (isOperandLiteral (left));
1024 let = getSpec(operandType(left));
1026 assert (isOperandLiteral (right));
1027 ret = getSpec(operandType(left));
1033 retval = operandFromValue (valCastLiteral (type,
1034 operandLitValue (left) +
1035 operandLitValue (right)));
1038 retval = operandFromValue (valCastLiteral (type,
1039 operandLitValue (left) -
1040 operandLitValue (right)));
1043 retval = operandFromValue (valCastLiteral (type,
1044 operandLitValue (left) *
1045 operandLitValue (right)));
1048 if ((unsigned long) operandLitValue (right) == 0)
1050 werror (E_DIVIDE_BY_ZERO);
1055 retval = operandFromValue (valCastLiteral (type,
1056 operandLitValue (left) /
1057 operandLitValue (right)));
1060 if ((unsigned long) operandLitValue (right) == 0) {
1061 werror (E_DIVIDE_BY_ZERO);
1065 retval = operandFromLit ((SPEC_USIGN(let) ?
1066 (unsigned long) operandLitValue (left) :
1067 (long) operandLitValue (left)) %
1069 (unsigned long) operandLitValue (right) :
1070 (long) operandLitValue (right)));
1074 retval = operandFromLit ((SPEC_USIGN(let) ?
1075 (unsigned long) operandLitValue (left) :
1076 (long) operandLitValue (left)) <<
1078 (unsigned long) operandLitValue (right) :
1079 (long) operandLitValue (right)));
1082 retval = operandFromLit ((SPEC_USIGN(let) ?
1083 (unsigned long) operandLitValue (left) :
1084 (long) operandLitValue (left)) >>
1086 (unsigned long) operandLitValue (right) :
1087 (long) operandLitValue (right)));
1090 retval = operandFromLit (operandLitValue (left) ==
1091 operandLitValue (right));
1094 retval = operandFromLit (operandLitValue (left) <
1095 operandLitValue (right));
1098 retval = operandFromLit (operandLitValue (left) <=
1099 operandLitValue (right));
1102 retval = operandFromLit (operandLitValue (left) !=
1103 operandLitValue (right));
1106 retval = operandFromLit (operandLitValue (left) >
1107 operandLitValue (right));
1110 retval = operandFromLit (operandLitValue (left) >=
1111 operandLitValue (right));
1114 retval = operandFromLit ((long)operandLitValue(left) &
1115 (long)operandLitValue(right));
1118 retval = operandFromLit ((long)operandLitValue (left) |
1119 (long)operandLitValue (right));
1122 retval = operandFromLit ((long)operandLitValue (left) ^
1123 (long)operandLitValue (right));
1126 retval = operandFromLit (operandLitValue (left) &&
1127 operandLitValue (right));
1130 retval = operandFromLit (operandLitValue (left) ||
1131 operandLitValue (right));
1135 long i = (long) operandLitValue (left);
1137 retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
1143 long i = (long) operandLitValue (left);
1145 retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
1151 retval = operandFromLit (-1 * operandLitValue (left));
1155 retval = operandFromLit (~((long) operandLitValue (left)));
1159 retval = operandFromLit (!operandLitValue (left));
1163 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1164 " operandOperation invalid operator ");
1172 /*-----------------------------------------------------------------*/
1173 /* isOperandEqual - compares two operand & return 1 if they r = */
1174 /*-----------------------------------------------------------------*/
1176 isOperandEqual (operand * left, operand * right)
1178 /* if the pointers are equal then they are equal */
1182 /* if either of them null then false */
1183 if (!left || !right)
1186 if (left->type != right->type)
1189 if (IS_SYMOP (left) && IS_SYMOP (right))
1190 return left->key == right->key;
1192 /* if types are the same */
1196 return isSymbolEqual (left->operand.symOperand,
1197 right->operand.symOperand);
1199 return (floatFromVal (left->operand.valOperand) ==
1200 floatFromVal (right->operand.valOperand));
1202 if (compareType (left->operand.typeOperand,
1203 right->operand.typeOperand) == 1)
1210 /*-------------------------------------------------------------------*/
1211 /* isiCodeEqual - compares two iCodes are equal, returns true if yes */
1212 /*-------------------------------------------------------------------*/
1214 isiCodeEqual (iCode * left, iCode * right)
1216 /* if the same pointer */
1220 /* if either of them null */
1221 if (!left || !right)
1224 /* if operand are the same */
1225 if (left->op == right->op)
1228 /* compare all the elements depending on type */
1229 if (left->op != IFX)
1231 if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
1233 if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
1239 if (!isOperandEqual (IC_COND (left), IC_COND (right)))
1241 if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
1243 if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
1252 /*-----------------------------------------------------------------*/
1253 /* newiTempFromOp - create a temp Operand with same attributes */
1254 /*-----------------------------------------------------------------*/
1256 newiTempFromOp (operand * op)
1266 nop = newiTempOperand (operandType (op), TRUE);
1267 nop->isaddr = op->isaddr;
1268 nop->isvolatile = op->isvolatile;
1269 nop->isGlobal = op->isGlobal;
1270 nop->isLiteral = op->isLiteral;
1271 nop->usesDefs = op->usesDefs;
1272 nop->isParm = op->isParm;
1276 /*-----------------------------------------------------------------*/
1277 /* operand from operand - creates an operand holder for the type */
1278 /*-----------------------------------------------------------------*/
1280 operandFromOperand (operand * op)
1286 nop = newOperand ();
1287 nop->type = op->type;
1288 nop->isaddr = op->isaddr;
1290 nop->isvolatile = op->isvolatile;
1291 nop->isGlobal = op->isGlobal;
1292 nop->isLiteral = op->isLiteral;
1293 nop->usesDefs = op->usesDefs;
1294 nop->isParm = op->isParm;
1299 nop->operand.symOperand = op->operand.symOperand;
1302 nop->operand.valOperand = op->operand.valOperand;
1305 nop->operand.typeOperand = op->operand.typeOperand;
1312 /*-----------------------------------------------------------------*/
1313 /* opFromOpWithDU - makes a copy of the operand and DU chains */
1314 /*-----------------------------------------------------------------*/
1316 opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
1318 operand *nop = operandFromOperand (op);
1320 if (nop->type == SYMBOL)
1322 OP_SYMBOL (nop)->defs = bitVectCopy (defs);
1323 OP_SYMBOL (nop)->uses = bitVectCopy (uses);
1329 /*-----------------------------------------------------------------*/
1330 /* operandFromSymbol - creates an operand from a symbol */
1331 /*-----------------------------------------------------------------*/
1333 operandFromSymbol (symbol * sym)
1338 /* if the symbol's type is a literal */
1339 /* then it is an enumerator type */
1340 if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
1341 return operandFromValue (valFromType (sym->etype));
1344 sym->key = ++operandKey;
1346 /* if this an implicit variable, means struct/union */
1347 /* member so just return it */
1348 if (sym->implicit || IS_FUNC (sym->type))
1352 op->operand.symOperand = sym;
1354 op->isvolatile = isOperandVolatile (op, TRUE);
1355 op->isGlobal = isOperandGlobal (op);
1359 /* under the following conditions create a
1360 register equivalent for a local symbol */
1361 if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
1362 (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
1363 (!(options.model == MODEL_FLAT24)) ) &&
1364 options.stackAuto == 0)
1367 if (!IS_AGGREGATE (sym->type) && /* not an aggregate */
1368 !IS_FUNC (sym->type) && /* not a function */
1369 !sym->_isparm && /* not a parameter */
1370 sym->level && /* is a local variable */
1371 !sym->addrtaken && /* whose address has not been taken */
1372 !sym->reqv && /* does not already have a reg equivalence */
1373 !IS_VOLATILE (sym->etype) && /* not declared as volatile */
1374 !IS_STATIC (sym->etype) && /* and not declared static */
1375 !sym->islbl && /* not a label */
1376 ok && /* farspace check */
1377 !IS_BITVAR (sym->etype) /* not a bit variable */
1381 /* we will use it after all optimizations
1382 and before liveRange calculation */
1383 sym->reqv = newiTempOperand (sym->type, 0);
1384 sym->reqv->key = sym->key;
1385 OP_SYMBOL (sym->reqv)->key = sym->key;
1386 OP_SYMBOL (sym->reqv)->isreqv = 1;
1387 OP_SYMBOL (sym->reqv)->islocal = 1;
1388 OP_SYMBOL (sym->reqv)->onStack = sym->onStack;
1389 SPIL_LOC (sym->reqv) = sym;
1392 if (!IS_AGGREGATE (sym->type))
1396 op->operand.symOperand = sym;
1399 op->isvolatile = isOperandVolatile (op, TRUE);
1400 op->isGlobal = isOperandGlobal (op);
1401 op->isPtr = IS_PTR (operandType (op));
1402 op->isParm = sym->_isparm;
1407 /* itemp = &[_symbol] */
1409 ic = newiCode (ADDRESS_OF, newOperand (), NULL);
1410 IC_LEFT (ic)->type = SYMBOL;
1411 IC_LEFT (ic)->operand.symOperand = sym;
1412 IC_LEFT (ic)->key = sym->key;
1413 (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
1414 (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
1415 IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
1418 IC_RESULT (ic) = newiTempOperand (sym->type, 0);
1419 if (IS_ARRAY (sym->type))
1421 IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
1422 IC_RESULT (ic)->isaddr = 0;
1425 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
1429 return IC_RESULT (ic);
1432 /*-----------------------------------------------------------------*/
1433 /* operandFromValue - creates an operand from value */
1434 /*-----------------------------------------------------------------*/
1436 operandFromValue (value * val)
1440 /* if this is a symbol then do the symbol thing */
1442 return operandFromSymbol (val->sym);
1444 /* this is not a symbol */
1447 op->operand.valOperand = val;
1448 op->isLiteral = isOperandLiteral (op);
1452 /*-----------------------------------------------------------------*/
1453 /* operandFromLink - operand from typeChain */
1454 /*-----------------------------------------------------------------*/
1456 operandFromLink (sym_link * type)
1460 /* operand from sym_link */
1466 op->operand.typeOperand = copyLinkChain (type);
1470 /*-----------------------------------------------------------------*/
1471 /* operandFromLit - makes an operand from a literal value */
1472 /*-----------------------------------------------------------------*/
1474 operandFromLit (double i)
1476 return operandFromValue (valueFromLit (i));
1479 /*-----------------------------------------------------------------*/
1480 /* operandFromAst - creates an operand from an ast */
1481 /*-----------------------------------------------------------------*/
1483 operandFromAst (ast * tree,int lvl)
1489 /* depending on type do */
1493 return ast2iCode (tree,lvl+1);
1497 return operandFromValue (tree->opval.val);
1501 return operandFromLink (tree->opval.lnk);
1505 /* Just to keep the comiler happy */
1506 return (operand *) 0;
1509 /*-----------------------------------------------------------------*/
1510 /* setOperandType - sets the operand's type to the given type */
1511 /*-----------------------------------------------------------------*/
1513 setOperandType (operand * op, sym_link * type)
1515 /* depending on the type of operand */
1520 op->operand.valOperand->etype =
1521 getSpec (op->operand.valOperand->type =
1522 copyLinkChain (type));
1526 if (op->operand.symOperand->isitmp)
1527 op->operand.symOperand->etype =
1528 getSpec (op->operand.symOperand->type =
1529 copyLinkChain (type));
1531 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1532 "attempt to modify type of source");
1536 op->operand.typeOperand = copyLinkChain (type);
1541 /*-----------------------------------------------------------------*/
1542 /* Get size in byte of ptr need to access an array */
1543 /*-----------------------------------------------------------------*/
1545 getArraySizePtr (operand * op)
1547 sym_link *ltype = operandType(op);
1551 int size = getSize(ltype);
1552 return(IS_GENPTR(ltype)?(size-1):size);
1557 sym_link *letype = getSpec(ltype);
1558 switch (PTR_TYPE (SPEC_OCLS (letype)))
1570 return (GPTRSIZE-1);
1579 /*-----------------------------------------------------------------*/
1580 /* perform "usual unary conversions" */
1581 /*-----------------------------------------------------------------*/
1583 usualUnaryConversions (operand * op)
1585 if (IS_INTEGRAL (operandType (op)))
1587 if (getSize (operandType (op)) < (unsigned int) INTSIZE)
1590 return geniCodeCast (INTTYPE, op, TRUE);
1596 /*-----------------------------------------------------------------*/
1597 /* perform "usual binary conversions" */
1598 /*-----------------------------------------------------------------*/
1600 usualBinaryConversions (operand ** op1, operand ** op2)
1603 sym_link *rtype = operandType (*op2);
1604 sym_link *ltype = operandType (*op1);
1606 ctype = computeType (ltype, rtype);
1607 *op1 = geniCodeCast (ctype, *op1, TRUE);
1608 *op2 = geniCodeCast (ctype, *op2, TRUE);
1613 /*-----------------------------------------------------------------*/
1614 /* geniCodeValueAtAddress - generate intermeditate code for value */
1616 /*-----------------------------------------------------------------*/
1618 geniCodeRValue (operand * op, bool force)
1621 sym_link *type = operandType (op);
1622 sym_link *etype = getSpec (type);
1624 /* if this is an array & already */
1625 /* an address then return this */
1626 if (IS_AGGREGATE (type) ||
1627 (IS_PTR (type) && !force && !op->isaddr))
1628 return operandFromOperand (op);
1630 /* if this is not an address then must be */
1631 /* rvalue already so return this one */
1635 /* if this is not a temp symbol then */
1636 if (!IS_ITEMP (op) &&
1638 !IN_FARSPACE (SPEC_OCLS (etype)))
1640 op = operandFromOperand (op);
1645 if (IS_SPEC (type) &&
1646 IS_TRUE_SYMOP (op) &&
1647 (!IN_FARSPACE (SPEC_OCLS (etype)) ||
1648 (options.model == MODEL_FLAT24) ))
1650 op = operandFromOperand (op);
1655 ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1656 if (IS_PTR (type) && op->isaddr && force)
1659 type = copyLinkChain (type);
1661 IC_RESULT (ic) = newiTempOperand (type, 1);
1662 IC_RESULT (ic)->isaddr = 0;
1664 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1668 return IC_RESULT (ic);
1671 /*-----------------------------------------------------------------*/
1672 /* geniCodeCast - changes the value from one type to another */
1673 /*-----------------------------------------------------------------*/
1675 geniCodeCast (sym_link * type, operand * op, bool implicit)
1679 sym_link *opetype = getSpec (optype = operandType (op));
1683 /* one of them has size zero then error */
1684 if (IS_VOID (optype))
1686 werror (E_CAST_ZERO);
1690 /* if the operand is already the desired type then do nothing */
1691 if (compareType (type, optype) == 1)
1694 /* if this is a literal then just change the type & return */
1695 if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1696 return operandFromValue (valCastLiteral (type,
1697 operandLitValue (op)));
1699 /* if casting to/from pointers, do some checking */
1700 if (IS_PTR(type)) { // to a pointer
1701 if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer
1702 if (IS_INTEGRAL(optype)) {
1703 // maybe this is NULL, than it's ok.
1704 if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
1705 if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80 && IS_GENPTR(type)) {
1706 // no way to set the storage
1707 if (IS_LITERAL(optype)) {
1708 werror(E_LITERAL_GENERIC);
1711 werror(E_NONPTR2_GENPTR);
1714 } else if (implicit) {
1715 werror(W_INTEGRAL2PTR_NOCAST);
1720 // shouldn't do that with float, array or structure unless to void
1721 if (!IS_VOID(getSpec(type)) &&
1722 !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1723 werror(E_INCOMPAT_TYPES);
1727 } else { // from a pointer to a pointer
1728 if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80) {
1729 // if not a pointer to a function
1730 if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1731 if (implicit) { // if not to generic, they have to match
1732 if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
1733 werror(E_INCOMPAT_PTYPES);
1740 } else { // to a non pointer
1741 if (IS_PTR(optype)) { // from a pointer
1742 if (implicit) { // sneaky
1743 if (IS_INTEGRAL(type)) {
1744 werror(W_PTR2INTEGRAL_NOCAST);
1746 } else { // shouldn't do that with float, array or structure
1747 werror(E_INCOMPAT_TYPES);
1754 printFromToType (optype, type);
1757 /* if they are the same size create an assignment */
1758 if (getSize (type) == getSize (optype) &&
1759 !IS_BITFIELD (type) &&
1761 !IS_FLOAT (optype) &&
1762 ((IS_SPEC (type) && IS_SPEC (optype)) ||
1763 (!IS_SPEC (type) && !IS_SPEC (optype))))
1766 ic = newiCode ('=', NULL, op);
1767 IC_RESULT (ic) = newiTempOperand (type, 0);
1768 SPIL_LOC (IC_RESULT (ic)) =
1769 (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
1770 IC_RESULT (ic)->isaddr = 0;
1774 ic = newiCode (CAST, operandFromLink (type),
1775 geniCodeRValue (op, FALSE));
1777 IC_RESULT (ic) = newiTempOperand (type, 0);
1780 /* preserve the storage class & output class */
1781 /* of the original variable */
1782 restype = getSpec (operandType (IC_RESULT (ic)));
1783 if (!IS_LITERAL(opetype))
1784 SPEC_SCLS (restype) = SPEC_SCLS (opetype);
1785 SPEC_OCLS (restype) = SPEC_OCLS (opetype);
1788 return IC_RESULT (ic);
1791 /*-----------------------------------------------------------------*/
1792 /* geniCodeLabel - will create a Label */
1793 /*-----------------------------------------------------------------*/
1795 geniCodeLabel (symbol * label)
1799 ic = newiCodeLabelGoto (LABEL, label);
1803 /*-----------------------------------------------------------------*/
1804 /* geniCodeGoto - will create a Goto */
1805 /*-----------------------------------------------------------------*/
1807 geniCodeGoto (symbol * label)
1811 ic = newiCodeLabelGoto (GOTO, label);
1815 /*-----------------------------------------------------------------*/
1816 /* geniCodeMultiply - gen intermediate code for multiplication */
1817 /*-----------------------------------------------------------------*/
1819 geniCodeMultiply (operand * left, operand * right,int resultIsInt)
1826 /* if they are both literal then we know the result */
1827 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1828 return operandFromValue (valMult (left->operand.valOperand,
1829 right->operand.valOperand));
1831 if (IS_LITERAL(retype)) {
1832 p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
1835 resType = usualBinaryConversions (&left, &right);
1837 rtype = operandType (right);
1838 retype = getSpec (rtype);
1839 ltype = operandType (left);
1840 letype = getSpec (ltype);
1844 SPEC_NOUN(getSpec(resType))=V_INT;
1847 /* if the right is a literal & power of 2 */
1848 /* then make it a left shift */
1849 /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
1850 efficient in most cases than 2 bytes result = 2 bytes << literal
1851 if port has 1 byte muldiv */
1852 if (p2 && !IS_FLOAT (letype) &&
1853 !((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
1854 (port->support.muldiv == 1)))
1856 if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
1858 /* LEFT_OP need same size for left and result, */
1859 left = geniCodeCast (resType, left, TRUE);
1860 ltype = operandType (left);
1862 ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
1866 ic = newiCode ('*', left, right); /* normal multiplication */
1867 /* if the size left or right > 1 then support routine */
1868 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1872 IC_RESULT (ic) = newiTempOperand (resType, 1);
1875 return IC_RESULT (ic);
1878 /*-----------------------------------------------------------------*/
1879 /* geniCodeDivision - gen intermediate code for division */
1880 /*-----------------------------------------------------------------*/
1882 geniCodeDivision (operand * left, operand * right)
1887 sym_link *rtype = operandType (right);
1888 sym_link *retype = getSpec (rtype);
1889 sym_link *ltype = operandType (left);
1890 sym_link *letype = getSpec (ltype);
1892 resType = usualBinaryConversions (&left, &right);
1894 /* if the right is a literal & power of 2 */
1895 /* then make it a right shift */
1896 if (IS_LITERAL (retype) &&
1897 !IS_FLOAT (letype) &&
1898 (p2 = powof2 ((unsigned long)
1899 floatFromVal (right->operand.valOperand)))) {
1900 ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
1904 ic = newiCode ('/', left, right); /* normal division */
1905 /* if the size left or right > 1 then support routine */
1906 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1909 IC_RESULT (ic) = newiTempOperand (resType, 0);
1912 return IC_RESULT (ic);
1914 /*-----------------------------------------------------------------*/
1915 /* geniCodeModulus - gen intermediate code for modulus */
1916 /*-----------------------------------------------------------------*/
1918 geniCodeModulus (operand * left, operand * right)
1924 /* if they are both literal then we know the result */
1925 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1926 return operandFromValue (valMod (left->operand.valOperand,
1927 right->operand.valOperand));
1929 resType = usualBinaryConversions (&left, &right);
1931 /* now they are the same size */
1932 ic = newiCode ('%', left, right);
1934 /* if the size left or right > 1 then support routine */
1935 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1937 IC_RESULT (ic) = newiTempOperand (resType, 0);
1940 return IC_RESULT (ic);
1943 /*-----------------------------------------------------------------*/
1944 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
1945 /*-----------------------------------------------------------------*/
1947 geniCodePtrPtrSubtract (operand * left, operand * right)
1953 /* if they are both literals then */
1954 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1956 result = operandFromValue (valMinus (left->operand.valOperand,
1957 right->operand.valOperand));
1961 ic = newiCode ('-', left, right);
1963 IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
1967 return geniCodeDivision (result,
1968 operandFromLit (getSize (ltype->next)));
1971 /*-----------------------------------------------------------------*/
1972 /* geniCodeSubtract - generates code for subtraction */
1973 /*-----------------------------------------------------------------*/
1975 geniCodeSubtract (operand * left, operand * right)
1982 /* if they both pointers then */
1983 if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
1984 (IS_PTR (rtype) || IS_ARRAY (rtype)))
1985 return geniCodePtrPtrSubtract (left, right);
1987 /* if they are both literal then we know the result */
1988 if (IS_LITERAL (letype) && IS_LITERAL (retype)
1989 && left->isLiteral && right->isLiteral)
1990 return operandFromValue (valMinus (left->operand.valOperand,
1991 right->operand.valOperand));
1993 /* if left is an array or pointer */
1994 if (IS_PTR (ltype) || IS_ARRAY (ltype))
1996 isarray = left->isaddr;
1997 right = geniCodeMultiply (right,
1998 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
1999 resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
2002 { /* make them the same size */
2003 resType = usualBinaryConversions (&left, &right);
2006 ic = newiCode ('-', left, right);
2008 IC_RESULT (ic) = newiTempOperand (resType, 1);
2009 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2011 /* if left or right is a float */
2012 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2016 return IC_RESULT (ic);
2019 /*-----------------------------------------------------------------*/
2020 /* geniCodeAdd - generates iCode for addition */
2021 /*-----------------------------------------------------------------*/
2023 geniCodeAdd (operand * left, operand * right, int lvl)
2031 /* if left is an array then array access */
2032 if (IS_ARRAY (ltype))
2033 return geniCodeArray (left, right,lvl);
2035 /* if the right side is LITERAL zero */
2036 /* return the left side */
2037 if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
2040 /* if left is literal zero return right */
2041 if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
2044 /* if left is a pointer then size */
2047 isarray = left->isaddr;
2048 // there is no need to multiply with 1
2049 if (getSize(ltype->next)!=1) {
2050 size = operandFromLit (getSize (ltype->next));
2051 right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
2053 resType = copyLinkChain (ltype);
2056 { // make them the same size
2057 resType = usualBinaryConversions (&left, &right);
2060 /* if they are both literals then we know */
2061 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2062 && left->isLiteral && right->isLiteral)
2063 return operandFromValue (valPlus (valFromType (letype),
2064 valFromType (retype)));
2066 ic = newiCode ('+', left, right);
2068 IC_RESULT (ic) = newiTempOperand (resType, 1);
2069 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2071 /* if left or right is a float then support
2073 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2078 return IC_RESULT (ic);
2082 /*-----------------------------------------------------------------*/
2083 /* aggrToPtr - changes an aggregate to pointer to an aggregate */
2084 /*-----------------------------------------------------------------*/
2086 aggrToPtr (sym_link * type, bool force)
2092 if (IS_PTR (type) && !force)
2095 etype = getSpec (type);
2099 /* if the output class is generic */
2100 if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER)
2101 DCL_PTR_CONST (ptype) = port->mem.code_ro;
2103 /* if the variable was declared a constant */
2104 /* then the pointer points to a constant */
2105 if (IS_CONSTANT (etype))
2106 DCL_PTR_CONST (ptype) = 1;
2108 /* the variable was volatile then pointer to volatile */
2109 if (IS_VOLATILE (etype))
2110 DCL_PTR_VOLATILE (ptype) = 1;
2114 /*-----------------------------------------------------------------*/
2115 /* geniCodeArray2Ptr - array to pointer */
2116 /*-----------------------------------------------------------------*/
2118 geniCodeArray2Ptr (operand * op)
2120 sym_link *optype = operandType (op);
2121 sym_link *opetype = getSpec (optype);
2123 /* set the pointer depending on the storage class */
2124 if ((DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2125 DCL_PTR_CONST (optype) = port->mem.code_ro;
2128 /* if the variable was declared a constant */
2129 /* then the pointer points to a constant */
2130 if (IS_CONSTANT (opetype))
2131 DCL_PTR_CONST (optype) = 1;
2133 /* the variable was volatile then pointer to volatile */
2134 if (IS_VOLATILE (opetype))
2135 DCL_PTR_VOLATILE (optype) = 1;
2141 /*-----------------------------------------------------------------*/
2142 /* geniCodeArray - array access */
2143 /*-----------------------------------------------------------------*/
2145 geniCodeArray (operand * left, operand * right,int lvl)
2148 sym_link *ltype = operandType (left);
2152 if (IS_PTR (ltype->next) && left->isaddr)
2154 left = geniCodeRValue (left, FALSE);
2156 return geniCodeDerefPtr (geniCodeAdd (left, right, lvl), lvl);
2159 right = geniCodeMultiply (right,
2160 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2162 /* we can check for limits here */
2163 if (isOperandLiteral (right) &&
2166 (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2168 werror (E_ARRAY_BOUND);
2169 right = operandFromLit (0);
2172 ic = newiCode ('+', left, right);
2174 IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2175 !IS_AGGREGATE (ltype->next) &&
2176 !IS_PTR (ltype->next))
2177 ? ltype : ltype->next), 0);
2179 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
2181 return IC_RESULT (ic);
2184 /*-----------------------------------------------------------------*/
2185 /* geniCodeStruct - generates intermediate code for structres */
2186 /*-----------------------------------------------------------------*/
2188 geniCodeStruct (operand * left, operand * right, bool islval)
2191 sym_link *type = operandType (left);
2192 sym_link *etype = getSpec (type);
2194 symbol *element = getStructElement (SPEC_STRUCT (etype),
2195 right->operand.symOperand);
2197 /* add the offset */
2198 ic = newiCode ('+', left, operandFromLit (element->offset));
2200 IC_RESULT (ic) = newiTempOperand (element->type, 0);
2202 /* preserve the storage & output class of the struct */
2203 /* as well as the volatile attribute */
2204 retype = getSpec (operandType (IC_RESULT (ic)));
2205 SPEC_SCLS (retype) = SPEC_SCLS (etype);
2206 SPEC_OCLS (retype) = SPEC_OCLS (etype);
2207 SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2209 if (IS_PTR (element->type))
2210 setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2212 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2216 return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2219 /*-----------------------------------------------------------------*/
2220 /* geniCodePostInc - generate int code for Post increment */
2221 /*-----------------------------------------------------------------*/
2223 geniCodePostInc (operand * op)
2227 sym_link *optype = operandType (op);
2229 operand *rv = (IS_ITEMP (op) ?
2230 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2232 sym_link *rvtype = operandType (rv);
2235 /* if this is not an address we have trouble */
2238 werror (E_LVALUE_REQUIRED, "++");
2242 rOp = newiTempOperand (rvtype, 0);
2243 OP_SYMBOL(rOp)->noSpilLoc = 1;
2246 OP_SYMBOL(rv)->noSpilLoc = 1;
2248 geniCodeAssign (rOp, rv, 0);
2250 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2251 if (IS_FLOAT (rvtype))
2252 ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2254 ic = newiCode ('+', rv, operandFromLit (size));
2256 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2259 geniCodeAssign (op, result, 0);
2265 /*-----------------------------------------------------------------*/
2266 /* geniCodePreInc - generate code for preIncrement */
2267 /*-----------------------------------------------------------------*/
2269 geniCodePreInc (operand * op)
2272 sym_link *optype = operandType (op);
2273 operand *rop = (IS_ITEMP (op) ?
2274 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2276 sym_link *roptype = operandType (rop);
2282 werror (E_LVALUE_REQUIRED, "++");
2287 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2288 if (IS_FLOAT (roptype))
2289 ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2291 ic = newiCode ('+', rop, operandFromLit (size));
2292 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2296 return geniCodeAssign (op, result, 0);
2299 /*-----------------------------------------------------------------*/
2300 /* geniCodePostDec - generates code for Post decrement */
2301 /*-----------------------------------------------------------------*/
2303 geniCodePostDec (operand * op)
2307 sym_link *optype = operandType (op);
2309 operand *rv = (IS_ITEMP (op) ?
2310 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2312 sym_link *rvtype = operandType (rv);
2315 /* if this is not an address we have trouble */
2318 werror (E_LVALUE_REQUIRED, "--");
2322 rOp = newiTempOperand (rvtype, 0);
2323 OP_SYMBOL(rOp)->noSpilLoc = 1;
2326 OP_SYMBOL(rv)->noSpilLoc = 1;
2328 geniCodeAssign (rOp, rv, 0);
2330 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2331 if (IS_FLOAT (rvtype))
2332 ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2334 ic = newiCode ('-', rv, operandFromLit (size));
2336 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2339 geniCodeAssign (op, result, 0);
2345 /*-----------------------------------------------------------------*/
2346 /* geniCodePreDec - generate code for pre decrement */
2347 /*-----------------------------------------------------------------*/
2349 geniCodePreDec (operand * op)
2352 sym_link *optype = operandType (op);
2353 operand *rop = (IS_ITEMP (op) ?
2354 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2356 sym_link *roptype = operandType (rop);
2362 werror (E_LVALUE_REQUIRED, "--");
2367 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2368 if (IS_FLOAT (roptype))
2369 ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2371 ic = newiCode ('-', rop, operandFromLit (size));
2372 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2376 return geniCodeAssign (op, result, 0);
2380 /*-----------------------------------------------------------------*/
2381 /* geniCodeBitwise - gen int code for bitWise operators */
2382 /*-----------------------------------------------------------------*/
2384 geniCodeBitwise (operand * left, operand * right,
2385 int oper, sym_link * resType)
2389 left = geniCodeCast (resType, left, TRUE);
2390 right = geniCodeCast (resType, right, TRUE);
2392 ic = newiCode (oper, left, right);
2393 IC_RESULT (ic) = newiTempOperand (resType, 0);
2396 return IC_RESULT (ic);
2399 /*-----------------------------------------------------------------*/
2400 /* geniCodeAddressOf - gens icode for '&' address of operator */
2401 /*-----------------------------------------------------------------*/
2403 geniCodeAddressOf (operand * op)
2407 sym_link *optype = operandType (op);
2408 sym_link *opetype = getSpec (optype);
2410 /* lvalue check already done in decorateType */
2411 /* this must be a lvalue */
2412 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2413 /* werror (E_LVALUE_REQUIRED,"&"); */
2418 p->class = DECLARATOR;
2420 /* set the pointer depending on the storage class */
2421 if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2422 DCL_PTR_CONST (p) = port->mem.code_ro;
2424 /* make sure we preserve the const & volatile */
2425 if (IS_CONSTANT (opetype))
2426 DCL_PTR_CONST (p) = 1;
2428 if (IS_VOLATILE (opetype))
2429 DCL_PTR_VOLATILE (p) = 1;
2431 p->next = copyLinkChain (optype);
2433 /* if already a temp */
2436 setOperandType (op, p);
2441 /* other wise make this of the type coming in */
2442 ic = newiCode (ADDRESS_OF, op, NULL);
2443 IC_RESULT (ic) = newiTempOperand (p, 1);
2444 IC_RESULT (ic)->isaddr = 0;
2446 return IC_RESULT (ic);
2448 /*-----------------------------------------------------------------*/
2449 /* setOClass - sets the output class depending on the pointer type */
2450 /*-----------------------------------------------------------------*/
2452 setOClass (sym_link * ptr, sym_link * spec)
2454 switch (DCL_TYPE (ptr))
2457 SPEC_OCLS (spec) = data;
2461 SPEC_OCLS (spec) = generic;
2465 SPEC_OCLS (spec) = xdata;
2469 SPEC_OCLS (spec) = code;
2473 SPEC_OCLS (spec) = idata;
2477 SPEC_OCLS (spec) = xstack;
2481 SPEC_OCLS (spec) = eeprom;
2490 /*-----------------------------------------------------------------*/
2491 /* geniCodeDerefPtr - dereference pointer with '*' */
2492 /*-----------------------------------------------------------------*/
2494 geniCodeDerefPtr (operand * op,int lvl)
2496 sym_link *rtype, *retype;
2497 sym_link *optype = operandType (op);
2499 /* if this is a pointer then generate the rvalue */
2500 if (IS_PTR (optype))
2502 if (IS_TRUE_SYMOP (op))
2505 op = geniCodeRValue (op, TRUE);
2508 op = geniCodeRValue (op, TRUE);
2511 /* now get rid of the pointer part */
2512 if (isLvaluereq(lvl) && IS_ITEMP (op))
2514 retype = getSpec (rtype = copyLinkChain (optype));
2518 retype = getSpec (rtype = copyLinkChain (optype->next));
2521 /* if this is a pointer then outputclass needs 2b updated */
2522 if (IS_PTR (optype))
2523 setOClass (optype, retype);
2525 op->isGptr = IS_GENPTR (optype);
2527 /* if the pointer was declared as a constant */
2528 /* then we cannot allow assignment to the derefed */
2529 if (IS_PTR_CONST (optype))
2530 SPEC_CONST (retype) = 1;
2532 op->isaddr = (IS_PTR (rtype) ||
2533 IS_STRUCT (rtype) ||
2538 if (!isLvaluereq(lvl))
2539 op = geniCodeRValue (op, TRUE);
2541 setOperandType (op, rtype);
2546 /*-----------------------------------------------------------------*/
2547 /* geniCodeUnaryMinus - does a unary minus of the operand */
2548 /*-----------------------------------------------------------------*/
2550 geniCodeUnaryMinus (operand * op)
2553 sym_link *optype = operandType (op);
2555 if (IS_LITERAL (optype))
2556 return operandFromLit (-floatFromVal (op->operand.valOperand));
2558 ic = newiCode (UNARYMINUS, op, NULL);
2559 IC_RESULT (ic) = newiTempOperand (optype, 0);
2561 return IC_RESULT (ic);
2564 /*-----------------------------------------------------------------*/
2565 /* geniCodeLeftShift - gen i code for left shift */
2566 /*-----------------------------------------------------------------*/
2568 geniCodeLeftShift (operand * left, operand * right)
2572 ic = newiCode (LEFT_OP, left, right);
2573 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2575 return IC_RESULT (ic);
2578 /*-----------------------------------------------------------------*/
2579 /* geniCodeRightShift - gen i code for right shift */
2580 /*-----------------------------------------------------------------*/
2582 geniCodeRightShift (operand * left, operand * right)
2586 ic = newiCode (RIGHT_OP, left, right);
2587 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2589 return IC_RESULT (ic);
2592 /*-----------------------------------------------------------------*/
2593 /* geniCodeLogic- logic code */
2594 /*-----------------------------------------------------------------*/
2596 geniCodeLogic (operand * left, operand * right, int op)
2600 sym_link *rtype = operandType (right);
2601 sym_link *ltype = operandType (left);
2603 /* left is integral type and right is literal then
2604 check if the literal value is within bounds */
2605 if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2607 checkConstantRange(ltype,
2608 OP_VALUE(right), "compare operation", 1);
2611 ctype = usualBinaryConversions (&left, &right);
2613 ic = newiCode (op, left, right);
2614 IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2616 /* if comparing float
2617 and not a '==' || '!=' || '&&' || '||' (these
2619 if (IS_FLOAT(ctype) &&
2627 return IC_RESULT (ic);
2630 /*-----------------------------------------------------------------*/
2631 /* geniCodeUnary - for a a generic unary operation */
2632 /*-----------------------------------------------------------------*/
2634 geniCodeUnary (operand * op, int oper)
2636 iCode *ic = newiCode (oper, op, NULL);
2638 IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2640 return IC_RESULT (ic);
2643 /*-----------------------------------------------------------------*/
2644 /* geniCodeConditional - geniCode for '?' ':' operation */
2645 /*-----------------------------------------------------------------*/
2647 geniCodeConditional (ast * tree,int lvl)
2650 symbol *falseLabel = newiTempLabel (NULL);
2651 symbol *exitLabel = newiTempLabel (NULL);
2652 operand *cond = ast2iCode (tree->left,lvl+1);
2653 operand *true, *false, *result;
2655 ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
2659 true = ast2iCode (tree->right->left,lvl+1);
2661 /* move the value to a new Operand */
2662 result = newiTempOperand (tree->right->ftype, 0);
2663 geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
2665 /* generate an unconditional goto */
2666 geniCodeGoto (exitLabel);
2668 /* now for the right side */
2669 geniCodeLabel (falseLabel);
2671 false = ast2iCode (tree->right->right,lvl+1);
2672 geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
2674 /* create the exit label */
2675 geniCodeLabel (exitLabel);
2680 /*-----------------------------------------------------------------*/
2681 /* geniCodeAssign - generate code for assignment */
2682 /*-----------------------------------------------------------------*/
2684 geniCodeAssign (operand * left, operand * right, int nosupdate)
2687 sym_link *ltype = operandType (left);
2688 sym_link *rtype = operandType (right);
2690 if (!left->isaddr && !IS_ITEMP (left))
2692 werror (E_LVALUE_REQUIRED, "assignment");
2696 /* left is integral type and right is literal then
2697 check if the literal value is within bounds */
2698 if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
2700 checkConstantRange(ltype,
2701 OP_VALUE(right), "= operation", 0);
2704 /* if the left & right type don't exactly match */
2705 /* if pointer set then make sure the check is
2706 done with the type & not the pointer */
2707 /* then cast rights type to left */
2709 /* first check the type for pointer assignement */
2710 if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
2711 compareType (ltype, rtype) <= 0)
2713 if (compareType (ltype->next, rtype) < 0)
2714 right = geniCodeCast (ltype->next, right, TRUE);
2716 else if (compareType (ltype, rtype) < 0)
2717 right = geniCodeCast (ltype, right, TRUE);
2719 /* if left is a true symbol & ! volatile
2720 create an assignment to temporary for
2721 the right & then assign this temporary
2722 to the symbol this is SSA . isn't it simple
2723 and folks have published mountains of paper on it */
2724 if (IS_TRUE_SYMOP (left) &&
2725 !isOperandVolatile (left, FALSE) &&
2726 isOperandGlobal (left))
2730 if (IS_TRUE_SYMOP (right))
2731 sym = OP_SYMBOL (right);
2732 ic = newiCode ('=', NULL, right);
2733 IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
2734 SPIL_LOC (right) = sym;
2738 ic = newiCode ('=', NULL, right);
2739 IC_RESULT (ic) = left;
2742 /* if left isgptr flag is set then support
2743 routine will be required */
2747 ic->nosupdate = nosupdate;
2751 /*-----------------------------------------------------------------*/
2752 /* geniCodeSEParms - generate code for side effecting fcalls */
2753 /*-----------------------------------------------------------------*/
2755 geniCodeSEParms (ast * parms,int lvl)
2760 if (parms->type == EX_OP && parms->opval.op == PARAM)
2762 geniCodeSEParms (parms->left,lvl);
2763 geniCodeSEParms (parms->right,lvl);
2767 /* hack don't like this but too lazy to think of
2769 if (IS_ADDRESS_OF_OP (parms))
2770 parms->left->lvalue = 1;
2772 if (IS_CAST_OP (parms) &&
2773 IS_PTR (parms->ftype) &&
2774 IS_ADDRESS_OF_OP (parms->right))
2775 parms->right->left->lvalue = 1;
2777 parms->opval.oprnd =
2778 geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2780 parms->type = EX_OPERAND;
2781 AST_ARGREG(parms) = SPEC_ARGREG(parms->etype);
2784 /*-----------------------------------------------------------------*/
2785 /* geniCodeParms - generates parameters */
2786 /*-----------------------------------------------------------------*/
2788 geniCodeParms (ast * parms, value *argVals, int *stack,
2789 sym_link * fetype, symbol * func,int lvl)
2797 if (argVals==NULL) {
2799 argVals=FUNC_ARGS(func->type);
2802 /* if this is a param node then do the left & right */
2803 if (parms->type == EX_OP && parms->opval.op == PARAM)
2805 argVals=geniCodeParms (parms->left, argVals, stack, fetype, func,lvl);
2806 argVals=geniCodeParms (parms->right, argVals, stack, fetype, func,lvl);
2810 /* get the parameter value */
2811 if (parms->type == EX_OPERAND)
2812 pval = parms->opval.oprnd;
2815 /* maybe this else should go away ?? */
2816 /* hack don't like this but too lazy to think of
2818 if (IS_ADDRESS_OF_OP (parms))
2819 parms->left->lvalue = 1;
2821 if (IS_CAST_OP (parms) &&
2822 IS_PTR (parms->ftype) &&
2823 IS_ADDRESS_OF_OP (parms->right))
2824 parms->right->left->lvalue = 1;
2826 pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2829 /* if register parm then make it a send */
2830 if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(func->type)) ||
2831 IFFUNC_ISBUILTIN(func->type))
2833 ic = newiCode (SEND, pval, NULL);
2834 ic->argreg = SPEC_ARGREG(parms->etype);
2835 ic->builtinSEND = FUNC_ISBUILTIN(func->type);
2840 /* now decide whether to push or assign */
2841 if (!(options.stackAuto || IFFUNC_ISREENT (func->type)))
2845 operand *top = operandFromSymbol (argVals->sym);
2846 /* clear useDef and other bitVectors */
2847 OP_USES (top) = OP_DEFS (top) = OP_SYMBOL(top)->clashes = NULL;
2848 geniCodeAssign (top, pval, 1);
2852 sym_link *p = operandType (pval);
2854 ic = newiCode (IPUSH, pval, NULL);
2856 /* update the stack adjustment */
2857 *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2862 argVals=argVals->next;
2866 /*-----------------------------------------------------------------*/
2867 /* geniCodeCall - generates temp code for calling */
2868 /*-----------------------------------------------------------------*/
2870 geniCodeCall (operand * left, ast * parms,int lvl)
2874 sym_link *type, *etype;
2877 if (!IS_FUNC(OP_SYMBOL(left)->type) &&
2878 !IS_CODEPTR(OP_SYMBOL(left)->type)) {
2879 werror (E_FUNCTION_EXPECTED);
2883 /* take care of parameters with side-effecting
2884 function calls in them, this is required to take care
2885 of overlaying function parameters */
2886 geniCodeSEParms (parms,lvl);
2888 /* first the parameters */
2889 geniCodeParms (parms, NULL, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
2891 /* now call : if symbol then pcall */
2892 if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
2893 ic = newiCode (PCALL, left, NULL);
2895 ic = newiCode (CALL, left, NULL);
2898 type = copyLinkChain (operandType (left)->next);
2899 etype = getSpec (type);
2900 SPEC_EXTR (etype) = 0;
2901 IC_RESULT (ic) = result = newiTempOperand (type, 1);
2905 /* stack adjustment after call */
2906 ic->parmBytes = stack;
2911 /*-----------------------------------------------------------------*/
2912 /* geniCodeReceive - generate intermediate code for "receive" */
2913 /*-----------------------------------------------------------------*/
2915 geniCodeReceive (value * args)
2917 /* for all arguments that are passed in registers */
2921 if (IS_REGPARM (args->etype))
2923 operand *opr = operandFromValue (args);
2925 symbol *sym = OP_SYMBOL (opr);
2928 /* we will use it after all optimizations
2929 and before liveRange calculation */
2930 if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
2933 if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
2934 options.stackAuto == 0 &&
2935 (!(options.model == MODEL_FLAT24)) )
2940 opl = newiTempOperand (args->type, 0);
2942 sym->reqv->key = sym->key;
2943 OP_SYMBOL (sym->reqv)->key = sym->key;
2944 OP_SYMBOL (sym->reqv)->isreqv = 1;
2945 OP_SYMBOL (sym->reqv)->islocal = 0;
2946 SPIL_LOC (sym->reqv) = sym;
2950 ic = newiCode (RECEIVE, NULL, NULL);
2951 ic->argreg = SPEC_ARGREG(args->etype);
2953 currFunc->recvSize = getSize (sym->type);
2956 IC_RESULT (ic) = opr;
2964 /*-----------------------------------------------------------------*/
2965 /* geniCodeFunctionBody - create the function body */
2966 /*-----------------------------------------------------------------*/
2968 geniCodeFunctionBody (ast * tree,int lvl)
2975 /* reset the auto generation */
2981 func = ast2iCode (tree->left,lvl+1);
2982 fetype = getSpec (operandType (func));
2984 savelineno = lineno;
2985 lineno = OP_SYMBOL (func)->lineDef;
2986 /* create an entry label */
2987 geniCodeLabel (entryLabel);
2988 lineno = savelineno;
2990 /* create a proc icode */
2991 ic = newiCode (FUNCTION, func, NULL);
2992 lineno=ic->lineno = OP_SYMBOL (func)->lineDef;
2996 /* for all parameters that are passed
2997 on registers add a "receive" */
2998 geniCodeReceive (tree->values.args);
3000 /* generate code for the body */
3001 ast2iCode (tree->right,lvl+1);
3003 /* create a label for return */
3004 geniCodeLabel (returnLabel);
3006 /* now generate the end proc */
3007 ic = newiCode (ENDFUNCTION, func, NULL);
3012 /*-----------------------------------------------------------------*/
3013 /* geniCodeReturn - gen icode for 'return' statement */
3014 /*-----------------------------------------------------------------*/
3016 geniCodeReturn (operand * op)
3020 /* if the operand is present force an rvalue */
3022 op = geniCodeRValue (op, FALSE);
3024 ic = newiCode (RETURN, op, NULL);
3028 /*-----------------------------------------------------------------*/
3029 /* geniCodeIfx - generates code for extended if statement */
3030 /*-----------------------------------------------------------------*/
3032 geniCodeIfx (ast * tree,int lvl)
3035 operand *condition = ast2iCode (tree->left,lvl+1);
3038 /* if condition is null then exit */
3042 condition = geniCodeRValue (condition, FALSE);
3044 cetype = getSpec (operandType (condition));
3045 /* if the condition is a literal */
3046 if (IS_LITERAL (cetype))
3048 if (floatFromVal (condition->operand.valOperand))
3050 if (tree->trueLabel)
3051 geniCodeGoto (tree->trueLabel);
3057 if (tree->falseLabel)
3058 geniCodeGoto (tree->falseLabel);
3065 if (tree->trueLabel)
3067 ic = newiCodeCondition (condition,
3072 if (tree->falseLabel)
3073 geniCodeGoto (tree->falseLabel);
3077 ic = newiCodeCondition (condition,
3084 ast2iCode (tree->right,lvl+1);
3087 /*-----------------------------------------------------------------*/
3088 /* geniCodeJumpTable - tries to create a jump table for switch */
3089 /*-----------------------------------------------------------------*/
3091 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
3093 int min = 0, max = 0, t, cnt = 0;
3100 if (!tree || !caseVals)
3103 /* the criteria for creating a jump table is */
3104 /* all integer numbers between the maximum & minimum must */
3105 /* be present , the maximum value should not exceed 255 */
3106 min = max = (int) floatFromVal (vch = caseVals);
3107 sprintf (buffer, "_case_%d_%d",
3108 tree->values.switchVals.swNum,
3110 addSet (&labels, newiTempLabel (buffer));
3112 /* if there is only one case value then no need */
3113 if (!(vch = vch->next))
3118 if (((t = (int) floatFromVal (vch)) - max) != 1)
3120 sprintf (buffer, "_case_%d_%d",
3121 tree->values.switchVals.swNum,
3123 addSet (&labels, newiTempLabel (buffer));
3129 /* if the number of case statements <= 2 then */
3130 /* it is not economical to create the jump table */
3131 /* since two compares are needed for boundary conditions */
3132 if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
3135 if (tree->values.switchVals.swDefault)
3136 sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3138 sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3140 falseLabel = newiTempLabel (buffer);
3142 /* so we can create a jumptable */
3143 /* first we rule out the boundary conditions */
3144 /* if only optimization says so */
3145 if (!optimize.noJTabBoundary)
3147 sym_link *cetype = getSpec (operandType (cond));
3148 /* no need to check the lower bound if
3149 the condition is unsigned & minimum value is zero */
3150 if (!(min == 0 && SPEC_USIGN (cetype)))
3152 boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3153 ic = newiCodeCondition (boundary, falseLabel, NULL);
3157 /* now for upper bounds */
3158 boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3159 ic = newiCodeCondition (boundary, falseLabel, NULL);
3163 /* if the min is not zero then we no make it zero */
3166 cond = geniCodeSubtract (cond, operandFromLit (min));
3167 setOperandType (cond, UCHARTYPE);
3170 /* now create the jumptable */
3171 ic = newiCode (JUMPTABLE, NULL, NULL);
3172 IC_JTCOND (ic) = cond;
3173 IC_JTLABELS (ic) = labels;
3178 /*-----------------------------------------------------------------*/
3179 /* geniCodeSwitch - changes a switch to a if statement */
3180 /*-----------------------------------------------------------------*/
3182 geniCodeSwitch (ast * tree,int lvl)
3185 operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3186 value *caseVals = tree->values.switchVals.swVals;
3187 symbol *trueLabel, *falseLabel;
3189 /* if we can make this a jump table */
3190 if (geniCodeJumpTable (cond, caseVals, tree))
3191 goto jumpTable; /* no need for the comparison */
3193 /* for the cases defined do */
3197 operand *compare = geniCodeLogic (cond,
3198 operandFromValue (caseVals),
3201 sprintf (buffer, "_case_%d_%d",
3202 tree->values.switchVals.swNum,
3203 (int) floatFromVal (caseVals));
3204 trueLabel = newiTempLabel (buffer);
3206 ic = newiCodeCondition (compare, trueLabel, NULL);
3208 caseVals = caseVals->next;
3213 /* if default is present then goto break else break */
3214 if (tree->values.switchVals.swDefault)
3215 sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3217 sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3219 falseLabel = newiTempLabel (buffer);
3220 geniCodeGoto (falseLabel);
3223 ast2iCode (tree->right,lvl+1);
3226 /*-----------------------------------------------------------------*/
3227 /* geniCodeInline - intermediate code for inline assembler */
3228 /*-----------------------------------------------------------------*/
3230 geniCodeInline (ast * tree)
3234 ic = newiCode (INLINEASM, NULL, NULL);
3235 IC_INLINE (ic) = tree->values.inlineasm;
3239 /*-----------------------------------------------------------------*/
3240 /* geniCodeArrayInit - intermediate code for array initializer */
3241 /*-----------------------------------------------------------------*/
3243 geniCodeArrayInit (ast * tree, operand *array)
3247 if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3248 ic = newiCode (ARRAYINIT, array, NULL);
3249 IC_ARRAYILIST (ic) = tree->values.constlist;
3251 operand *left=newOperand(), *right=newOperand();
3252 left->type=right->type=SYMBOL;
3253 OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3254 OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3255 ic = newiCode (ARRAYINIT, left, right);
3260 /*-----------------------------------------------------------------*/
3261 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
3262 /* particular case. Ie : assigning or dereferencing array or ptr */
3263 /*-----------------------------------------------------------------*/
3264 set * lvaluereqSet = NULL;
3265 typedef struct lvalItem
3272 /*-----------------------------------------------------------------*/
3273 /* addLvaluereq - add a flag for lvalreq for current ast level */
3274 /*-----------------------------------------------------------------*/
3275 void addLvaluereq(int lvl)
3277 lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3280 addSetHead(&lvaluereqSet,lpItem);
3283 /*-----------------------------------------------------------------*/
3284 /* delLvaluereq - del a flag for lvalreq for current ast level */
3285 /*-----------------------------------------------------------------*/
3289 lpItem = getSet(&lvaluereqSet);
3290 if(lpItem) Safe_free(lpItem);
3292 /*-----------------------------------------------------------------*/
3293 /* clearLvaluereq - clear lvalreq flag */
3294 /*-----------------------------------------------------------------*/
3295 void clearLvaluereq()
3298 lpItem = peekSet(lvaluereqSet);
3299 if(lpItem) lpItem->req = 0;
3301 /*-----------------------------------------------------------------*/
3302 /* getLvaluereq - get the last lvalreq level */
3303 /*-----------------------------------------------------------------*/
3304 int getLvaluereqLvl()
3307 lpItem = peekSet(lvaluereqSet);
3308 if(lpItem) return lpItem->lvl;
3311 /*-----------------------------------------------------------------*/
3312 /* isLvaluereq - is lvalreq valid for this level ? */
3313 /*-----------------------------------------------------------------*/
3314 int isLvaluereq(int lvl)
3317 lpItem = peekSet(lvaluereqSet);
3318 if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3322 /*-----------------------------------------------------------------*/
3323 /* ast2iCode - creates an icodeList from an ast */
3324 /*-----------------------------------------------------------------*/
3326 ast2iCode (ast * tree,int lvl)
3328 operand *left = NULL;
3329 operand *right = NULL;
3333 /* set the global variables for filename & line number */
3335 filename = tree->filename;
3337 lineno = tree->lineno;
3339 block = tree->block;
3341 scopeLevel = tree->level;
3343 if (tree->type == EX_VALUE)
3344 return operandFromValue (tree->opval.val);
3346 if (tree->type == EX_LINK)
3347 return operandFromLink (tree->opval.lnk);
3349 /* if we find a nullop */
3350 if (tree->type == EX_OP &&
3351 (tree->opval.op == NULLOP ||
3352 tree->opval.op == BLOCK))
3354 ast2iCode (tree->left,lvl+1);
3355 ast2iCode (tree->right,lvl+1);
3359 /* special cases for not evaluating */
3360 if (tree->opval.op != ':' &&
3361 tree->opval.op != '?' &&
3362 tree->opval.op != CALL &&
3363 tree->opval.op != IFX &&
3364 tree->opval.op != LABEL &&
3365 tree->opval.op != GOTO &&
3366 tree->opval.op != SWITCH &&
3367 tree->opval.op != FUNCTION &&
3368 tree->opval.op != INLINEASM)
3371 if (IS_ASSIGN_OP (tree->opval.op) ||
3372 IS_DEREF_OP (tree) ||
3373 (tree->opval.op == '&' && !tree->right) ||
3374 tree->opval.op == PTR_OP)
3377 if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3378 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3381 left = operandFromAst (tree->left,lvl);
3383 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3384 left = geniCodeRValue (left, TRUE);
3388 left = operandFromAst (tree->left,lvl);
3390 if (tree->opval.op == INC_OP ||
3391 tree->opval.op == DEC_OP)
3394 right = operandFromAst (tree->right,lvl);
3399 right = operandFromAst (tree->right,lvl);
3403 /* now depending on the type of operand */
3404 /* this will be a biggy */
3405 switch (tree->opval.op)
3408 case '[': /* array operation */
3410 //sym_link *ltype = operandType (left);
3411 //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3412 left = geniCodeRValue (left, FALSE);
3413 right = geniCodeRValue (right, TRUE);
3416 return geniCodeArray (left, right,lvl);
3418 case '.': /* structure dereference */
3419 if (IS_PTR (operandType (left)))
3420 left = geniCodeRValue (left, TRUE);
3422 left = geniCodeRValue (left, FALSE);
3424 return geniCodeStruct (left, right, tree->lvalue);
3426 case PTR_OP: /* structure pointer dereference */
3429 pType = operandType (left);
3430 left = geniCodeRValue (left, TRUE);
3432 setOClass (pType, getSpec (operandType (left)));
3435 return geniCodeStruct (left, right, tree->lvalue);
3437 case INC_OP: /* increment operator */
3439 return geniCodePostInc (left);
3441 return geniCodePreInc (right);
3443 case DEC_OP: /* decrement operator */
3445 return geniCodePostDec (left);
3447 return geniCodePreDec (right);
3449 case '&': /* bitwise and or address of operator */
3451 { /* this is a bitwise operator */
3452 left = geniCodeRValue (left, FALSE);
3453 right = geniCodeRValue (right, FALSE);
3454 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3457 return geniCodeAddressOf (left);
3459 case '|': /* bitwise or & xor */
3461 return geniCodeBitwise (geniCodeRValue (left, FALSE),
3462 geniCodeRValue (right, FALSE),
3467 return geniCodeDivision (geniCodeRValue (left, FALSE),
3468 geniCodeRValue (right, FALSE));
3471 return geniCodeModulus (geniCodeRValue (left, FALSE),
3472 geniCodeRValue (right, FALSE));
3475 return geniCodeMultiply (geniCodeRValue (left, FALSE),
3476 geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3478 return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3482 return geniCodeSubtract (geniCodeRValue (left, FALSE),
3483 geniCodeRValue (right, FALSE));
3485 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3489 return geniCodeAdd (geniCodeRValue (left, FALSE),
3490 geniCodeRValue (right, FALSE),lvl);
3492 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
3495 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3496 geniCodeRValue (right, FALSE));
3499 return geniCodeRightShift (geniCodeRValue (left, FALSE),
3500 geniCodeRValue (right, FALSE));
3502 return geniCodeCast (operandType (left),
3503 geniCodeRValue (right, FALSE), FALSE);
3509 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3513 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3514 setOperandType (op, UCHARTYPE);
3525 return geniCodeLogic (geniCodeRValue (left, FALSE),
3526 geniCodeRValue (right, FALSE),
3529 return geniCodeConditional (tree,lvl);
3532 return operandFromLit (getSize (tree->right->ftype));
3536 sym_link *rtype = operandType (right);
3537 sym_link *ltype = operandType (left);
3538 if (IS_PTR (rtype) && IS_ITEMP (right)
3539 && right->isaddr && compareType (rtype->next, ltype) == 1)
3540 right = geniCodeRValue (right, TRUE);
3542 right = geniCodeRValue (right, FALSE);
3544 geniCodeAssign (left, right, 0);
3549 geniCodeAssign (left,
3550 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3552 geniCodeRValue (right, FALSE),FALSE), 0);
3556 geniCodeAssign (left,
3557 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3559 geniCodeRValue (right, FALSE)), 0);
3562 geniCodeAssign (left,
3563 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3565 geniCodeRValue (right, FALSE)), 0);
3568 sym_link *rtype = operandType (right);
3569 sym_link *ltype = operandType (left);
3570 if (IS_PTR (rtype) && IS_ITEMP (right)
3571 && right->isaddr && compareType (rtype->next, ltype) == 1)
3572 right = geniCodeRValue (right, TRUE);
3574 right = geniCodeRValue (right, FALSE);
3577 return geniCodeAssign (left,
3578 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3584 sym_link *rtype = operandType (right);
3585 sym_link *ltype = operandType (left);
3586 if (IS_PTR (rtype) && IS_ITEMP (right)
3587 && right->isaddr && compareType (rtype->next, ltype) == 1)
3589 right = geniCodeRValue (right, TRUE);
3593 right = geniCodeRValue (right, FALSE);
3596 geniCodeAssign (left,
3597 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3603 geniCodeAssign (left,
3604 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3606 geniCodeRValue (right, FALSE)), 0);
3609 geniCodeAssign (left,
3610 geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3612 geniCodeRValue (right, FALSE)), 0);
3615 geniCodeAssign (left,
3616 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3618 geniCodeRValue (right, FALSE),
3620 operandType (left)), 0);
3623 geniCodeAssign (left,
3624 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3626 geniCodeRValue (right, FALSE),
3628 operandType (left)), 0);
3631 geniCodeAssign (left,
3632 geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3634 geniCodeRValue (right, FALSE),
3636 operandType (left)), 0);
3638 return geniCodeRValue (right, FALSE);
3641 return geniCodeCall (ast2iCode (tree->left,lvl+1),
3644 geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3645 return ast2iCode (tree->right,lvl+1);
3648 geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3649 return ast2iCode (tree->right,lvl+1);
3652 geniCodeFunctionBody (tree,lvl);
3656 geniCodeReturn (right);
3660 geniCodeIfx (tree,lvl);
3664 geniCodeSwitch (tree,lvl);
3668 geniCodeInline (tree);
3672 geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
3679 /*-----------------------------------------------------------------*/
3680 /* reverseICChain - gets from the list and creates a linkedlist */
3681 /*-----------------------------------------------------------------*/
3688 while ((loop = getSet (&iCodeChain)))
3700 /*-----------------------------------------------------------------*/
3701 /* iCodeFromAst - given an ast will convert it to iCode */
3702 /*-----------------------------------------------------------------*/
3704 iCodeFromAst (ast * tree)
3706 returnLabel = newiTempLabel ("_return");
3707 entryLabel = newiTempLabel ("_entry");
3709 return reverseiCChain ();