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 /* TARGET_IS_DS390)) */
1649 (options.model == MODEL_FLAT24) ))
1651 op = operandFromOperand (op);
1656 ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1657 if (IS_PTR (type) && op->isaddr && force)
1660 type = copyLinkChain (type);
1662 IC_RESULT (ic) = newiTempOperand (type, 1);
1663 IC_RESULT (ic)->isaddr = 0;
1665 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1669 return IC_RESULT (ic);
1672 /*-----------------------------------------------------------------*/
1673 /* geniCodeCast - changes the value from one type to another */
1674 /*-----------------------------------------------------------------*/
1676 geniCodeCast (sym_link * type, operand * op, bool implicit)
1680 sym_link *opetype = getSpec (optype = operandType (op));
1684 /* one of them has size zero then error */
1685 if (IS_VOID (optype))
1687 werror (E_CAST_ZERO);
1691 /* if the operand is already the desired type then do nothing */
1692 if (compareType (type, optype) == 1)
1695 /* if this is a literal then just change the type & return */
1696 if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1697 return operandFromValue (valCastLiteral (type,
1698 operandLitValue (op)));
1700 /* if casting to/from pointers, do some checking */
1701 if (IS_PTR(type)) { // to a pointer
1702 if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer
1703 if (IS_INTEGRAL(optype)) {
1704 // maybe this is NULL, than it's ok.
1705 if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
1706 if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80 && IS_GENPTR(type)) {
1707 // no way to set the storage
1708 if (IS_LITERAL(optype)) {
1709 werror(E_LITERAL_GENERIC);
1712 werror(E_NONPTR2_GENPTR);
1715 } else if (implicit) {
1716 werror(W_INTEGRAL2PTR_NOCAST);
1721 // shouldn't do that with float, array or structure unless to void
1722 if (!IS_VOID(getSpec(type)) &&
1723 !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1724 werror(E_INCOMPAT_TYPES);
1728 } else { // from a pointer to a pointer
1729 if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80) {
1730 // if not a pointer to a function
1731 if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1732 if (implicit) { // if not to generic, they have to match
1733 if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
1734 werror(E_INCOMPAT_PTYPES);
1741 } else { // to a non pointer
1742 if (IS_PTR(optype)) { // from a pointer
1743 if (implicit) { // sneaky
1744 if (IS_INTEGRAL(type)) {
1745 werror(W_PTR2INTEGRAL_NOCAST);
1747 } else { // shouldn't do that with float, array or structure
1748 werror(E_INCOMPAT_TYPES);
1755 printFromToType (optype, type);
1758 /* if they are the same size create an assignment */
1759 if (getSize (type) == getSize (optype) &&
1760 !IS_BITFIELD (type) &&
1762 !IS_FLOAT (optype) &&
1763 ((IS_SPEC (type) && IS_SPEC (optype)) ||
1764 (!IS_SPEC (type) && !IS_SPEC (optype))))
1767 ic = newiCode ('=', NULL, op);
1768 IC_RESULT (ic) = newiTempOperand (type, 0);
1769 SPIL_LOC (IC_RESULT (ic)) =
1770 (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
1771 IC_RESULT (ic)->isaddr = 0;
1775 ic = newiCode (CAST, operandFromLink (type),
1776 geniCodeRValue (op, FALSE));
1778 IC_RESULT (ic) = newiTempOperand (type, 0);
1781 /* preserve the storage class & output class */
1782 /* of the original variable */
1783 restype = getSpec (operandType (IC_RESULT (ic)));
1784 if (!IS_LITERAL(opetype))
1785 SPEC_SCLS (restype) = SPEC_SCLS (opetype);
1786 SPEC_OCLS (restype) = SPEC_OCLS (opetype);
1789 return IC_RESULT (ic);
1792 /*-----------------------------------------------------------------*/
1793 /* geniCodeLabel - will create a Label */
1794 /*-----------------------------------------------------------------*/
1796 geniCodeLabel (symbol * label)
1800 ic = newiCodeLabelGoto (LABEL, label);
1804 /*-----------------------------------------------------------------*/
1805 /* geniCodeGoto - will create a Goto */
1806 /*-----------------------------------------------------------------*/
1808 geniCodeGoto (symbol * label)
1812 ic = newiCodeLabelGoto (GOTO, label);
1816 /*-----------------------------------------------------------------*/
1817 /* geniCodeMultiply - gen intermediate code for multiplication */
1818 /*-----------------------------------------------------------------*/
1820 geniCodeMultiply (operand * left, operand * right,int resultIsInt)
1827 /* if they are both literal then we know the result */
1828 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1829 return operandFromValue (valMult (left->operand.valOperand,
1830 right->operand.valOperand));
1832 if (IS_LITERAL(retype)) {
1833 p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
1836 resType = usualBinaryConversions (&left, &right);
1838 rtype = operandType (right);
1839 retype = getSpec (rtype);
1840 ltype = operandType (left);
1841 letype = getSpec (ltype);
1845 SPEC_NOUN(getSpec(resType))=V_INT;
1848 /* if the right is a literal & power of 2 */
1849 /* then make it a left shift */
1850 /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
1851 efficient in most cases than 2 bytes result = 2 bytes << literal
1852 if port has 1 byte muldiv */
1853 if (p2 && !IS_FLOAT (letype) &&
1854 !((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
1855 (port->support.muldiv == 1)))
1857 if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
1859 /* LEFT_OP need same size for left and result, */
1860 left = geniCodeCast (resType, left, TRUE);
1861 ltype = operandType (left);
1863 ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
1867 ic = newiCode ('*', left, right); /* normal multiplication */
1868 /* if the size left or right > 1 then support routine */
1869 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1873 IC_RESULT (ic) = newiTempOperand (resType, 1);
1876 return IC_RESULT (ic);
1879 /*-----------------------------------------------------------------*/
1880 /* geniCodeDivision - gen intermediate code for division */
1881 /*-----------------------------------------------------------------*/
1883 geniCodeDivision (operand * left, operand * right)
1888 sym_link *rtype = operandType (right);
1889 sym_link *retype = getSpec (rtype);
1890 sym_link *ltype = operandType (left);
1891 sym_link *letype = getSpec (ltype);
1893 resType = usualBinaryConversions (&left, &right);
1895 /* if the right is a literal & power of 2 */
1896 /* then make it a right shift */
1897 if (IS_LITERAL (retype) &&
1898 !IS_FLOAT (letype) &&
1899 (p2 = powof2 ((unsigned long)
1900 floatFromVal (right->operand.valOperand)))) {
1901 ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
1905 ic = newiCode ('/', left, right); /* normal division */
1906 /* if the size left or right > 1 then support routine */
1907 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1910 IC_RESULT (ic) = newiTempOperand (resType, 0);
1913 return IC_RESULT (ic);
1915 /*-----------------------------------------------------------------*/
1916 /* geniCodeModulus - gen intermediate code for modulus */
1917 /*-----------------------------------------------------------------*/
1919 geniCodeModulus (operand * left, operand * right)
1925 /* if they are both literal then we know the result */
1926 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1927 return operandFromValue (valMod (left->operand.valOperand,
1928 right->operand.valOperand));
1930 resType = usualBinaryConversions (&left, &right);
1932 /* now they are the same size */
1933 ic = newiCode ('%', left, right);
1935 /* if the size left or right > 1 then support routine */
1936 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1938 IC_RESULT (ic) = newiTempOperand (resType, 0);
1941 return IC_RESULT (ic);
1944 /*-----------------------------------------------------------------*/
1945 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
1946 /*-----------------------------------------------------------------*/
1948 geniCodePtrPtrSubtract (operand * left, operand * right)
1954 /* if they are both literals then */
1955 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1957 result = operandFromValue (valMinus (left->operand.valOperand,
1958 right->operand.valOperand));
1962 ic = newiCode ('-', left, right);
1964 IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
1968 return geniCodeDivision (result,
1969 operandFromLit (getSize (ltype->next)));
1972 /*-----------------------------------------------------------------*/
1973 /* geniCodeSubtract - generates code for subtraction */
1974 /*-----------------------------------------------------------------*/
1976 geniCodeSubtract (operand * left, operand * right)
1983 /* if they both pointers then */
1984 if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
1985 (IS_PTR (rtype) || IS_ARRAY (rtype)))
1986 return geniCodePtrPtrSubtract (left, right);
1988 /* if they are both literal then we know the result */
1989 if (IS_LITERAL (letype) && IS_LITERAL (retype)
1990 && left->isLiteral && right->isLiteral)
1991 return operandFromValue (valMinus (left->operand.valOperand,
1992 right->operand.valOperand));
1994 /* if left is an array or pointer */
1995 if (IS_PTR (ltype) || IS_ARRAY (ltype))
1997 isarray = left->isaddr;
1998 right = geniCodeMultiply (right,
1999 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2000 resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
2003 { /* make them the same size */
2004 resType = usualBinaryConversions (&left, &right);
2007 ic = newiCode ('-', left, right);
2009 IC_RESULT (ic) = newiTempOperand (resType, 1);
2010 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2012 /* if left or right is a float */
2013 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2017 return IC_RESULT (ic);
2020 /*-----------------------------------------------------------------*/
2021 /* geniCodeAdd - generates iCode for addition */
2022 /*-----------------------------------------------------------------*/
2024 geniCodeAdd (operand * left, operand * right, int lvl)
2032 /* if left is an array then array access */
2033 if (IS_ARRAY (ltype))
2034 return geniCodeArray (left, right,lvl);
2036 /* if the right side is LITERAL zero */
2037 /* return the left side */
2038 if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
2041 /* if left is literal zero return right */
2042 if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
2045 /* if left is a pointer then size */
2048 isarray = left->isaddr;
2049 // there is no need to multiply with 1
2050 if (getSize(ltype->next)!=1) {
2051 size = operandFromLit (getSize (ltype->next));
2052 right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
2054 resType = copyLinkChain (ltype);
2057 { // make them the same size
2058 resType = usualBinaryConversions (&left, &right);
2061 /* if they are both literals then we know */
2062 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2063 && left->isLiteral && right->isLiteral)
2064 return operandFromValue (valPlus (valFromType (letype),
2065 valFromType (retype)));
2067 ic = newiCode ('+', left, right);
2069 IC_RESULT (ic) = newiTempOperand (resType, 1);
2070 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2072 /* if left or right is a float then support
2074 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2079 return IC_RESULT (ic);
2083 /*-----------------------------------------------------------------*/
2084 /* aggrToPtr - changes an aggregate to pointer to an aggregate */
2085 /*-----------------------------------------------------------------*/
2087 aggrToPtr (sym_link * type, bool force)
2093 if (IS_PTR (type) && !force)
2096 etype = getSpec (type);
2100 /* if the output class is generic */
2101 if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER)
2102 DCL_PTR_CONST (ptype) = port->mem.code_ro;
2104 /* if the variable was declared a constant */
2105 /* then the pointer points to a constant */
2106 if (IS_CONSTANT (etype))
2107 DCL_PTR_CONST (ptype) = 1;
2109 /* the variable was volatile then pointer to volatile */
2110 if (IS_VOLATILE (etype))
2111 DCL_PTR_VOLATILE (ptype) = 1;
2115 /*-----------------------------------------------------------------*/
2116 /* geniCodeArray2Ptr - array to pointer */
2117 /*-----------------------------------------------------------------*/
2119 geniCodeArray2Ptr (operand * op)
2121 sym_link *optype = operandType (op);
2122 sym_link *opetype = getSpec (optype);
2124 /* set the pointer depending on the storage class */
2125 if ((DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2126 DCL_PTR_CONST (optype) = port->mem.code_ro;
2129 /* if the variable was declared a constant */
2130 /* then the pointer points to a constant */
2131 if (IS_CONSTANT (opetype))
2132 DCL_PTR_CONST (optype) = 1;
2134 /* the variable was volatile then pointer to volatile */
2135 if (IS_VOLATILE (opetype))
2136 DCL_PTR_VOLATILE (optype) = 1;
2142 /*-----------------------------------------------------------------*/
2143 /* geniCodeArray - array access */
2144 /*-----------------------------------------------------------------*/
2146 geniCodeArray (operand * left, operand * right,int lvl)
2149 sym_link *ltype = operandType (left);
2153 if (IS_PTR (ltype->next) && left->isaddr)
2155 left = geniCodeRValue (left, FALSE);
2157 return geniCodeDerefPtr (geniCodeAdd (left, right, lvl), lvl);
2160 right = geniCodeMultiply (right,
2161 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2163 /* we can check for limits here */
2164 if (isOperandLiteral (right) &&
2167 (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2169 werror (E_ARRAY_BOUND);
2170 right = operandFromLit (0);
2173 ic = newiCode ('+', left, right);
2175 IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2176 !IS_AGGREGATE (ltype->next) &&
2177 !IS_PTR (ltype->next))
2178 ? ltype : ltype->next), 0);
2180 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
2182 return IC_RESULT (ic);
2185 /*-----------------------------------------------------------------*/
2186 /* geniCodeStruct - generates intermediate code for structres */
2187 /*-----------------------------------------------------------------*/
2189 geniCodeStruct (operand * left, operand * right, bool islval)
2192 sym_link *type = operandType (left);
2193 sym_link *etype = getSpec (type);
2195 symbol *element = getStructElement (SPEC_STRUCT (etype),
2196 right->operand.symOperand);
2198 /* add the offset */
2199 ic = newiCode ('+', left, operandFromLit (element->offset));
2201 IC_RESULT (ic) = newiTempOperand (element->type, 0);
2203 /* preserve the storage & output class of the struct */
2204 /* as well as the volatile attribute */
2205 retype = getSpec (operandType (IC_RESULT (ic)));
2206 SPEC_SCLS (retype) = SPEC_SCLS (etype);
2207 SPEC_OCLS (retype) = SPEC_OCLS (etype);
2208 SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2210 if (IS_PTR (element->type))
2211 setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2213 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2217 return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2220 /*-----------------------------------------------------------------*/
2221 /* geniCodePostInc - generate int code for Post increment */
2222 /*-----------------------------------------------------------------*/
2224 geniCodePostInc (operand * op)
2228 sym_link *optype = operandType (op);
2230 operand *rv = (IS_ITEMP (op) ?
2231 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2233 sym_link *rvtype = operandType (rv);
2236 /* if this is not an address we have trouble */
2239 werror (E_LVALUE_REQUIRED, "++");
2243 rOp = newiTempOperand (rvtype, 0);
2244 OP_SYMBOL(rOp)->noSpilLoc = 1;
2247 OP_SYMBOL(rv)->noSpilLoc = 1;
2249 geniCodeAssign (rOp, rv, 0);
2251 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2252 if (IS_FLOAT (rvtype))
2253 ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2255 ic = newiCode ('+', rv, operandFromLit (size));
2257 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2260 geniCodeAssign (op, result, 0);
2266 /*-----------------------------------------------------------------*/
2267 /* geniCodePreInc - generate code for preIncrement */
2268 /*-----------------------------------------------------------------*/
2270 geniCodePreInc (operand * op)
2273 sym_link *optype = operandType (op);
2274 operand *rop = (IS_ITEMP (op) ?
2275 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2277 sym_link *roptype = operandType (rop);
2283 werror (E_LVALUE_REQUIRED, "++");
2288 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2289 if (IS_FLOAT (roptype))
2290 ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2292 ic = newiCode ('+', rop, operandFromLit (size));
2293 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2297 return geniCodeAssign (op, result, 0);
2300 /*-----------------------------------------------------------------*/
2301 /* geniCodePostDec - generates code for Post decrement */
2302 /*-----------------------------------------------------------------*/
2304 geniCodePostDec (operand * op)
2308 sym_link *optype = operandType (op);
2310 operand *rv = (IS_ITEMP (op) ?
2311 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2313 sym_link *rvtype = operandType (rv);
2316 /* if this is not an address we have trouble */
2319 werror (E_LVALUE_REQUIRED, "--");
2323 rOp = newiTempOperand (rvtype, 0);
2324 OP_SYMBOL(rOp)->noSpilLoc = 1;
2327 OP_SYMBOL(rv)->noSpilLoc = 1;
2329 geniCodeAssign (rOp, rv, 0);
2331 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2332 if (IS_FLOAT (rvtype))
2333 ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2335 ic = newiCode ('-', rv, operandFromLit (size));
2337 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2340 geniCodeAssign (op, result, 0);
2346 /*-----------------------------------------------------------------*/
2347 /* geniCodePreDec - generate code for pre decrement */
2348 /*-----------------------------------------------------------------*/
2350 geniCodePreDec (operand * op)
2353 sym_link *optype = operandType (op);
2354 operand *rop = (IS_ITEMP (op) ?
2355 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2357 sym_link *roptype = operandType (rop);
2363 werror (E_LVALUE_REQUIRED, "--");
2368 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2369 if (IS_FLOAT (roptype))
2370 ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2372 ic = newiCode ('-', rop, operandFromLit (size));
2373 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2377 return geniCodeAssign (op, result, 0);
2381 /*-----------------------------------------------------------------*/
2382 /* geniCodeBitwise - gen int code for bitWise operators */
2383 /*-----------------------------------------------------------------*/
2385 geniCodeBitwise (operand * left, operand * right,
2386 int oper, sym_link * resType)
2390 left = geniCodeCast (resType, left, TRUE);
2391 right = geniCodeCast (resType, right, TRUE);
2393 ic = newiCode (oper, left, right);
2394 IC_RESULT (ic) = newiTempOperand (resType, 0);
2397 return IC_RESULT (ic);
2400 /*-----------------------------------------------------------------*/
2401 /* geniCodeAddressOf - gens icode for '&' address of operator */
2402 /*-----------------------------------------------------------------*/
2404 geniCodeAddressOf (operand * op)
2408 sym_link *optype = operandType (op);
2409 sym_link *opetype = getSpec (optype);
2411 /* lvalue check already done in decorateType */
2412 /* this must be a lvalue */
2413 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2414 /* werror (E_LVALUE_REQUIRED,"&"); */
2419 p->class = DECLARATOR;
2421 /* set the pointer depending on the storage class */
2422 if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2423 DCL_PTR_CONST (p) = port->mem.code_ro;
2425 /* make sure we preserve the const & volatile */
2426 if (IS_CONSTANT (opetype))
2427 DCL_PTR_CONST (p) = 1;
2429 if (IS_VOLATILE (opetype))
2430 DCL_PTR_VOLATILE (p) = 1;
2432 p->next = copyLinkChain (optype);
2434 /* if already a temp */
2437 setOperandType (op, p);
2442 /* other wise make this of the type coming in */
2443 ic = newiCode (ADDRESS_OF, op, NULL);
2444 IC_RESULT (ic) = newiTempOperand (p, 1);
2445 IC_RESULT (ic)->isaddr = 0;
2447 return IC_RESULT (ic);
2449 /*-----------------------------------------------------------------*/
2450 /* setOClass - sets the output class depending on the pointer type */
2451 /*-----------------------------------------------------------------*/
2453 setOClass (sym_link * ptr, sym_link * spec)
2455 switch (DCL_TYPE (ptr))
2458 SPEC_OCLS (spec) = data;
2462 SPEC_OCLS (spec) = generic;
2466 SPEC_OCLS (spec) = xdata;
2470 SPEC_OCLS (spec) = code;
2474 SPEC_OCLS (spec) = idata;
2478 SPEC_OCLS (spec) = xstack;
2482 SPEC_OCLS (spec) = eeprom;
2491 /*-----------------------------------------------------------------*/
2492 /* geniCodeDerefPtr - dereference pointer with '*' */
2493 /*-----------------------------------------------------------------*/
2495 geniCodeDerefPtr (operand * op,int lvl)
2497 sym_link *rtype, *retype;
2498 sym_link *optype = operandType (op);
2500 /* if this is a pointer then generate the rvalue */
2501 if (IS_PTR (optype))
2503 if (IS_TRUE_SYMOP (op))
2506 op = geniCodeRValue (op, TRUE);
2509 op = geniCodeRValue (op, TRUE);
2512 /* now get rid of the pointer part */
2513 if (isLvaluereq(lvl) && IS_ITEMP (op))
2515 retype = getSpec (rtype = copyLinkChain (optype));
2519 retype = getSpec (rtype = copyLinkChain (optype->next));
2522 /* if this is a pointer then outputclass needs 2b updated */
2523 if (IS_PTR (optype))
2524 setOClass (optype, retype);
2526 op->isGptr = IS_GENPTR (optype);
2528 /* if the pointer was declared as a constant */
2529 /* then we cannot allow assignment to the derefed */
2530 if (IS_PTR_CONST (optype))
2531 SPEC_CONST (retype) = 1;
2533 op->isaddr = (IS_PTR (rtype) ||
2534 IS_STRUCT (rtype) ||
2539 if (!isLvaluereq(lvl))
2540 op = geniCodeRValue (op, TRUE);
2542 setOperandType (op, rtype);
2547 /*-----------------------------------------------------------------*/
2548 /* geniCodeUnaryMinus - does a unary minus of the operand */
2549 /*-----------------------------------------------------------------*/
2551 geniCodeUnaryMinus (operand * op)
2554 sym_link *optype = operandType (op);
2556 if (IS_LITERAL (optype))
2557 return operandFromLit (-floatFromVal (op->operand.valOperand));
2559 ic = newiCode (UNARYMINUS, op, NULL);
2560 IC_RESULT (ic) = newiTempOperand (optype, 0);
2562 return IC_RESULT (ic);
2565 /*-----------------------------------------------------------------*/
2566 /* geniCodeLeftShift - gen i code for left shift */
2567 /*-----------------------------------------------------------------*/
2569 geniCodeLeftShift (operand * left, operand * right)
2573 ic = newiCode (LEFT_OP, left, right);
2574 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2576 return IC_RESULT (ic);
2579 /*-----------------------------------------------------------------*/
2580 /* geniCodeRightShift - gen i code for right shift */
2581 /*-----------------------------------------------------------------*/
2583 geniCodeRightShift (operand * left, operand * right)
2587 ic = newiCode (RIGHT_OP, left, right);
2588 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2590 return IC_RESULT (ic);
2593 /*-----------------------------------------------------------------*/
2594 /* geniCodeLogic- logic code */
2595 /*-----------------------------------------------------------------*/
2597 geniCodeLogic (operand * left, operand * right, int op)
2601 sym_link *rtype = operandType (right);
2602 sym_link *ltype = operandType (left);
2604 /* left is integral type and right is literal then
2605 check if the literal value is within bounds */
2606 if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2608 checkConstantRange(ltype,
2609 OP_VALUE(right), "compare operation", 1);
2612 ctype = usualBinaryConversions (&left, &right);
2614 ic = newiCode (op, left, right);
2615 IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2617 /* if comparing float
2618 and not a '==' || '!=' || '&&' || '||' (these
2620 if (IS_FLOAT(ctype) &&
2628 return IC_RESULT (ic);
2631 /*-----------------------------------------------------------------*/
2632 /* geniCodeUnary - for a a generic unary operation */
2633 /*-----------------------------------------------------------------*/
2635 geniCodeUnary (operand * op, int oper)
2637 iCode *ic = newiCode (oper, op, NULL);
2639 IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2641 return IC_RESULT (ic);
2644 /*-----------------------------------------------------------------*/
2645 /* geniCodeConditional - geniCode for '?' ':' operation */
2646 /*-----------------------------------------------------------------*/
2648 geniCodeConditional (ast * tree,int lvl)
2651 symbol *falseLabel = newiTempLabel (NULL);
2652 symbol *exitLabel = newiTempLabel (NULL);
2653 operand *cond = ast2iCode (tree->left,lvl+1);
2654 operand *true, *false, *result;
2656 ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
2660 true = ast2iCode (tree->right->left,lvl+1);
2662 /* move the value to a new Operand */
2663 result = newiTempOperand (tree->right->ftype, 0);
2664 geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
2666 /* generate an unconditional goto */
2667 geniCodeGoto (exitLabel);
2669 /* now for the right side */
2670 geniCodeLabel (falseLabel);
2672 false = ast2iCode (tree->right->right,lvl+1);
2673 geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
2675 /* create the exit label */
2676 geniCodeLabel (exitLabel);
2681 /*-----------------------------------------------------------------*/
2682 /* geniCodeAssign - generate code for assignment */
2683 /*-----------------------------------------------------------------*/
2685 geniCodeAssign (operand * left, operand * right, int nosupdate)
2688 sym_link *ltype = operandType (left);
2689 sym_link *rtype = operandType (right);
2691 if (!left->isaddr && !IS_ITEMP (left))
2693 werror (E_LVALUE_REQUIRED, "assignment");
2697 /* left is integral type and right is literal then
2698 check if the literal value is within bounds */
2699 if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
2701 checkConstantRange(ltype,
2702 OP_VALUE(right), "= operation", 0);
2705 /* if the left & right type don't exactly match */
2706 /* if pointer set then make sure the check is
2707 done with the type & not the pointer */
2708 /* then cast rights type to left */
2710 /* first check the type for pointer assignement */
2711 if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
2712 compareType (ltype, rtype) <= 0)
2714 if (compareType (ltype->next, rtype) < 0)
2715 right = geniCodeCast (ltype->next, right, TRUE);
2717 else if (compareType (ltype, rtype) < 0)
2718 right = geniCodeCast (ltype, right, TRUE);
2720 /* if left is a true symbol & ! volatile
2721 create an assignment to temporary for
2722 the right & then assign this temporary
2723 to the symbol this is SSA . isn't it simple
2724 and folks have published mountains of paper on it */
2725 if (IS_TRUE_SYMOP (left) &&
2726 !isOperandVolatile (left, FALSE) &&
2727 isOperandGlobal (left))
2731 if (IS_TRUE_SYMOP (right))
2732 sym = OP_SYMBOL (right);
2733 ic = newiCode ('=', NULL, right);
2734 IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
2735 SPIL_LOC (right) = sym;
2739 ic = newiCode ('=', NULL, right);
2740 IC_RESULT (ic) = left;
2743 /* if left isgptr flag is set then support
2744 routine will be required */
2748 ic->nosupdate = nosupdate;
2752 /*-----------------------------------------------------------------*/
2753 /* geniCodeSEParms - generate code for side effecting fcalls */
2754 /*-----------------------------------------------------------------*/
2756 geniCodeSEParms (ast * parms,int lvl)
2761 if (parms->type == EX_OP && parms->opval.op == PARAM)
2763 geniCodeSEParms (parms->left,lvl);
2764 geniCodeSEParms (parms->right,lvl);
2768 /* hack don't like this but too lazy to think of
2770 if (IS_ADDRESS_OF_OP (parms))
2771 parms->left->lvalue = 1;
2773 if (IS_CAST_OP (parms) &&
2774 IS_PTR (parms->ftype) &&
2775 IS_ADDRESS_OF_OP (parms->right))
2776 parms->right->left->lvalue = 1;
2778 parms->opval.oprnd =
2779 geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2781 parms->type = EX_OPERAND;
2782 AST_ARGREG(parms) = SPEC_ARGREG(parms->etype);
2785 /*-----------------------------------------------------------------*/
2786 /* geniCodeParms - generates parameters */
2787 /*-----------------------------------------------------------------*/
2789 geniCodeParms (ast * parms, value *argVals, int *stack,
2790 sym_link * fetype, symbol * func,int lvl)
2798 if (argVals==NULL) {
2800 argVals=FUNC_ARGS(func->type);
2803 /* if this is a param node then do the left & right */
2804 if (parms->type == EX_OP && parms->opval.op == PARAM)
2806 argVals=geniCodeParms (parms->left, argVals, stack, fetype, func,lvl);
2807 argVals=geniCodeParms (parms->right, argVals, stack, fetype, func,lvl);
2811 /* get the parameter value */
2812 if (parms->type == EX_OPERAND)
2813 pval = parms->opval.oprnd;
2816 /* maybe this else should go away ?? */
2817 /* hack don't like this but too lazy to think of
2819 if (IS_ADDRESS_OF_OP (parms))
2820 parms->left->lvalue = 1;
2822 if (IS_CAST_OP (parms) &&
2823 IS_PTR (parms->ftype) &&
2824 IS_ADDRESS_OF_OP (parms->right))
2825 parms->right->left->lvalue = 1;
2827 pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2830 /* if register parm then make it a send */
2831 if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(func->type)) ||
2832 IFFUNC_ISBUILTIN(func->type))
2834 ic = newiCode (SEND, pval, NULL);
2835 ic->argreg = SPEC_ARGREG(parms->etype);
2836 ic->builtinSEND = FUNC_ISBUILTIN(func->type);
2841 /* now decide whether to push or assign */
2842 if (!(options.stackAuto || IFFUNC_ISREENT (func->type)))
2846 operand *top = operandFromSymbol (argVals->sym);
2847 /* clear useDef and other bitVectors */
2848 OP_USES (top) = OP_DEFS (top) = OP_SYMBOL(top)->clashes = NULL;
2849 geniCodeAssign (top, pval, 1);
2853 sym_link *p = operandType (pval);
2855 ic = newiCode (IPUSH, pval, NULL);
2857 /* update the stack adjustment */
2858 *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2863 argVals=argVals->next;
2867 /*-----------------------------------------------------------------*/
2868 /* geniCodeCall - generates temp code for calling */
2869 /*-----------------------------------------------------------------*/
2871 geniCodeCall (operand * left, ast * parms,int lvl)
2875 sym_link *type, *etype;
2878 if (!IS_FUNC(OP_SYMBOL(left)->type) &&
2879 !IS_CODEPTR(OP_SYMBOL(left)->type)) {
2880 werror (E_FUNCTION_EXPECTED);
2884 /* take care of parameters with side-effecting
2885 function calls in them, this is required to take care
2886 of overlaying function parameters */
2887 geniCodeSEParms (parms,lvl);
2889 /* first the parameters */
2890 geniCodeParms (parms, NULL, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
2892 /* now call : if symbol then pcall */
2893 if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
2894 ic = newiCode (PCALL, left, NULL);
2896 ic = newiCode (CALL, left, NULL);
2899 type = copyLinkChain (operandType (left)->next);
2900 etype = getSpec (type);
2901 SPEC_EXTR (etype) = 0;
2902 IC_RESULT (ic) = result = newiTempOperand (type, 1);
2906 /* stack adjustment after call */
2907 ic->parmBytes = stack;
2912 /*-----------------------------------------------------------------*/
2913 /* geniCodeReceive - generate intermediate code for "receive" */
2914 /*-----------------------------------------------------------------*/
2916 geniCodeReceive (value * args)
2918 /* for all arguments that are passed in registers */
2922 if (IS_REGPARM (args->etype))
2924 operand *opr = operandFromValue (args);
2926 symbol *sym = OP_SYMBOL (opr);
2929 /* we will use it after all optimizations
2930 and before liveRange calculation */
2931 if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
2934 if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
2935 options.stackAuto == 0 &&
2936 /* !TARGET_IS_DS390) */
2937 (!(options.model == MODEL_FLAT24)) )
2942 opl = newiTempOperand (args->type, 0);
2944 sym->reqv->key = sym->key;
2945 OP_SYMBOL (sym->reqv)->key = sym->key;
2946 OP_SYMBOL (sym->reqv)->isreqv = 1;
2947 OP_SYMBOL (sym->reqv)->islocal = 0;
2948 SPIL_LOC (sym->reqv) = sym;
2952 ic = newiCode (RECEIVE, NULL, NULL);
2953 ic->argreg = SPEC_ARGREG(args->etype);
2955 currFunc->recvSize = getSize (sym->type);
2958 IC_RESULT (ic) = opr;
2966 /*-----------------------------------------------------------------*/
2967 /* geniCodeFunctionBody - create the function body */
2968 /*-----------------------------------------------------------------*/
2970 geniCodeFunctionBody (ast * tree,int lvl)
2977 /* reset the auto generation */
2983 func = ast2iCode (tree->left,lvl+1);
2984 fetype = getSpec (operandType (func));
2986 savelineno = lineno;
2987 lineno = OP_SYMBOL (func)->lineDef;
2988 /* create an entry label */
2989 geniCodeLabel (entryLabel);
2990 lineno = savelineno;
2992 /* create a proc icode */
2993 ic = newiCode (FUNCTION, func, NULL);
2994 ic->lineno = OP_SYMBOL (func)->lineDef;
2998 /* for all parameters that are passed
2999 on registers add a "receive" */
3000 geniCodeReceive (tree->values.args);
3002 /* generate code for the body */
3003 ast2iCode (tree->right,lvl+1);
3005 /* create a label for return */
3006 geniCodeLabel (returnLabel);
3008 /* now generate the end proc */
3009 ic = newiCode (ENDFUNCTION, func, NULL);
3014 /*-----------------------------------------------------------------*/
3015 /* geniCodeReturn - gen icode for 'return' statement */
3016 /*-----------------------------------------------------------------*/
3018 geniCodeReturn (operand * op)
3022 /* if the operand is present force an rvalue */
3024 op = geniCodeRValue (op, FALSE);
3026 ic = newiCode (RETURN, op, NULL);
3030 /*-----------------------------------------------------------------*/
3031 /* geniCodeIfx - generates code for extended if statement */
3032 /*-----------------------------------------------------------------*/
3034 geniCodeIfx (ast * tree,int lvl)
3037 operand *condition = ast2iCode (tree->left,lvl+1);
3040 /* if condition is null then exit */
3044 condition = geniCodeRValue (condition, FALSE);
3046 cetype = getSpec (operandType (condition));
3047 /* if the condition is a literal */
3048 if (IS_LITERAL (cetype))
3050 if (floatFromVal (condition->operand.valOperand))
3052 if (tree->trueLabel)
3053 geniCodeGoto (tree->trueLabel);
3059 if (tree->falseLabel)
3060 geniCodeGoto (tree->falseLabel);
3067 if (tree->trueLabel)
3069 ic = newiCodeCondition (condition,
3074 if (tree->falseLabel)
3075 geniCodeGoto (tree->falseLabel);
3079 ic = newiCodeCondition (condition,
3086 ast2iCode (tree->right,lvl+1);
3089 /*-----------------------------------------------------------------*/
3090 /* geniCodeJumpTable - tries to create a jump table for switch */
3091 /*-----------------------------------------------------------------*/
3093 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
3095 int min = 0, max = 0, t, cnt = 0;
3102 if (!tree || !caseVals)
3105 /* the criteria for creating a jump table is */
3106 /* all integer numbers between the maximum & minimum must */
3107 /* be present , the maximum value should not exceed 255 */
3108 min = max = (int) floatFromVal (vch = caseVals);
3109 sprintf (buffer, "_case_%d_%d",
3110 tree->values.switchVals.swNum,
3112 addSet (&labels, newiTempLabel (buffer));
3114 /* if there is only one case value then no need */
3115 if (!(vch = vch->next))
3120 if (((t = (int) floatFromVal (vch)) - max) != 1)
3122 sprintf (buffer, "_case_%d_%d",
3123 tree->values.switchVals.swNum,
3125 addSet (&labels, newiTempLabel (buffer));
3131 /* if the number of case statements <= 2 then */
3132 /* it is not economical to create the jump table */
3133 /* since two compares are needed for boundary conditions */
3134 if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
3137 if (tree->values.switchVals.swDefault)
3138 sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3140 sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3142 falseLabel = newiTempLabel (buffer);
3144 /* so we can create a jumptable */
3145 /* first we rule out the boundary conditions */
3146 /* if only optimization says so */
3147 if (!optimize.noJTabBoundary)
3149 sym_link *cetype = getSpec (operandType (cond));
3150 /* no need to check the lower bound if
3151 the condition is unsigned & minimum value is zero */
3152 if (!(min == 0 && SPEC_USIGN (cetype)))
3154 boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3155 ic = newiCodeCondition (boundary, falseLabel, NULL);
3159 /* now for upper bounds */
3160 boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3161 ic = newiCodeCondition (boundary, falseLabel, NULL);
3165 /* if the min is not zero then we no make it zero */
3168 cond = geniCodeSubtract (cond, operandFromLit (min));
3169 setOperandType (cond, UCHARTYPE);
3172 /* now create the jumptable */
3173 ic = newiCode (JUMPTABLE, NULL, NULL);
3174 IC_JTCOND (ic) = cond;
3175 IC_JTLABELS (ic) = labels;
3180 /*-----------------------------------------------------------------*/
3181 /* geniCodeSwitch - changes a switch to a if statement */
3182 /*-----------------------------------------------------------------*/
3184 geniCodeSwitch (ast * tree,int lvl)
3187 operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3188 value *caseVals = tree->values.switchVals.swVals;
3189 symbol *trueLabel, *falseLabel;
3191 /* if we can make this a jump table */
3192 if (geniCodeJumpTable (cond, caseVals, tree))
3193 goto jumpTable; /* no need for the comparison */
3195 /* for the cases defined do */
3199 operand *compare = geniCodeLogic (cond,
3200 operandFromValue (caseVals),
3203 sprintf (buffer, "_case_%d_%d",
3204 tree->values.switchVals.swNum,
3205 (int) floatFromVal (caseVals));
3206 trueLabel = newiTempLabel (buffer);
3208 ic = newiCodeCondition (compare, trueLabel, NULL);
3210 caseVals = caseVals->next;
3215 /* if default is present then goto break else break */
3216 if (tree->values.switchVals.swDefault)
3217 sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3219 sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3221 falseLabel = newiTempLabel (buffer);
3222 geniCodeGoto (falseLabel);
3225 ast2iCode (tree->right,lvl+1);
3228 /*-----------------------------------------------------------------*/
3229 /* geniCodeInline - intermediate code for inline assembler */
3230 /*-----------------------------------------------------------------*/
3232 geniCodeInline (ast * tree)
3236 ic = newiCode (INLINEASM, NULL, NULL);
3237 IC_INLINE (ic) = tree->values.inlineasm;
3241 /*-----------------------------------------------------------------*/
3242 /* geniCodeArrayInit - intermediate code for array initializer */
3243 /*-----------------------------------------------------------------*/
3245 geniCodeArrayInit (ast * tree, operand *array)
3249 if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3250 ic = newiCode (ARRAYINIT, array, NULL);
3251 IC_ARRAYILIST (ic) = tree->values.constlist;
3253 operand *left=newOperand(), *right=newOperand();
3254 left->type=right->type=SYMBOL;
3255 OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3256 OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3257 ic = newiCode (ARRAYINIT, left, right);
3262 /*-----------------------------------------------------------------*/
3263 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
3264 /* particular case. Ie : assigning or dereferencing array or ptr */
3265 /*-----------------------------------------------------------------*/
3266 set * lvaluereqSet = NULL;
3267 typedef struct lvalItem
3274 /*-----------------------------------------------------------------*/
3275 /* addLvaluereq - add a flag for lvalreq for current ast level */
3276 /*-----------------------------------------------------------------*/
3277 void addLvaluereq(int lvl)
3279 lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3282 addSetHead(&lvaluereqSet,lpItem);
3285 /*-----------------------------------------------------------------*/
3286 /* delLvaluereq - del a flag for lvalreq for current ast level */
3287 /*-----------------------------------------------------------------*/
3291 lpItem = getSet(&lvaluereqSet);
3292 if(lpItem) Safe_free(lpItem);
3294 /*-----------------------------------------------------------------*/
3295 /* clearLvaluereq - clear lvalreq flag */
3296 /*-----------------------------------------------------------------*/
3297 void clearLvaluereq()
3300 lpItem = peekSet(lvaluereqSet);
3301 if(lpItem) lpItem->req = 0;
3303 /*-----------------------------------------------------------------*/
3304 /* getLvaluereq - get the last lvalreq level */
3305 /*-----------------------------------------------------------------*/
3306 int getLvaluereqLvl()
3309 lpItem = peekSet(lvaluereqSet);
3310 if(lpItem) return lpItem->lvl;
3313 /*-----------------------------------------------------------------*/
3314 /* isLvaluereq - is lvalreq valid for this level ? */
3315 /*-----------------------------------------------------------------*/
3316 int isLvaluereq(int lvl)
3319 lpItem = peekSet(lvaluereqSet);
3320 if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3324 /*-----------------------------------------------------------------*/
3325 /* ast2iCode - creates an icodeList from an ast */
3326 /*-----------------------------------------------------------------*/
3328 ast2iCode (ast * tree,int lvl)
3330 operand *left = NULL;
3331 operand *right = NULL;
3334 /* set the global variables for filename & line number */
3336 filename = tree->filename;
3338 lineno = tree->lineno;
3340 block = tree->block;
3342 scopeLevel = tree->level;
3344 if (tree->type == EX_VALUE)
3345 return operandFromValue (tree->opval.val);
3347 if (tree->type == EX_LINK)
3348 return operandFromLink (tree->opval.lnk);
3350 /* if we find a nullop */
3351 if (tree->type == EX_OP &&
3352 (tree->opval.op == NULLOP ||
3353 tree->opval.op == BLOCK))
3355 ast2iCode (tree->left,lvl+1);
3356 ast2iCode (tree->right,lvl+1);
3360 /* special cases for not evaluating */
3361 if (tree->opval.op != ':' &&
3362 tree->opval.op != '?' &&
3363 tree->opval.op != CALL &&
3364 tree->opval.op != IFX &&
3365 tree->opval.op != LABEL &&
3366 tree->opval.op != GOTO &&
3367 tree->opval.op != SWITCH &&
3368 tree->opval.op != FUNCTION &&
3369 tree->opval.op != INLINEASM)
3372 if (IS_ASSIGN_OP (tree->opval.op) ||
3373 IS_DEREF_OP (tree) ||
3374 (tree->opval.op == '&' && !tree->right) ||
3375 tree->opval.op == PTR_OP)
3378 if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3379 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3382 left = operandFromAst (tree->left,lvl);
3384 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3385 left = geniCodeRValue (left, TRUE);
3389 left = operandFromAst (tree->left,lvl);
3391 if (tree->opval.op == INC_OP ||
3392 tree->opval.op == DEC_OP)
3395 right = operandFromAst (tree->right,lvl);
3400 right = operandFromAst (tree->right,lvl);
3404 /* now depending on the type of operand */
3405 /* this will be a biggy */
3406 switch (tree->opval.op)
3409 case '[': /* array operation */
3411 //sym_link *ltype = operandType (left);
3412 //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3413 left = geniCodeRValue (left, FALSE);
3414 right = geniCodeRValue (right, TRUE);
3417 return geniCodeArray (left, right,lvl);
3419 case '.': /* structure dereference */
3420 if (IS_PTR (operandType (left)))
3421 left = geniCodeRValue (left, TRUE);
3423 left = geniCodeRValue (left, FALSE);
3425 return geniCodeStruct (left, right, tree->lvalue);
3427 case PTR_OP: /* structure pointer dereference */
3430 pType = operandType (left);
3431 left = geniCodeRValue (left, TRUE);
3433 setOClass (pType, getSpec (operandType (left)));
3436 return geniCodeStruct (left, right, tree->lvalue);
3438 case INC_OP: /* increment operator */
3440 return geniCodePostInc (left);
3442 return geniCodePreInc (right);
3444 case DEC_OP: /* decrement operator */
3446 return geniCodePostDec (left);
3448 return geniCodePreDec (right);
3450 case '&': /* bitwise and or address of operator */
3452 { /* this is a bitwise operator */
3453 left = geniCodeRValue (left, FALSE);
3454 right = geniCodeRValue (right, FALSE);
3455 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3458 return geniCodeAddressOf (left);
3460 case '|': /* bitwise or & xor */
3462 return geniCodeBitwise (geniCodeRValue (left, FALSE),
3463 geniCodeRValue (right, FALSE),
3468 return geniCodeDivision (geniCodeRValue (left, FALSE),
3469 geniCodeRValue (right, FALSE));
3472 return geniCodeModulus (geniCodeRValue (left, FALSE),
3473 geniCodeRValue (right, FALSE));
3476 return geniCodeMultiply (geniCodeRValue (left, FALSE),
3477 geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3479 return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3483 return geniCodeSubtract (geniCodeRValue (left, FALSE),
3484 geniCodeRValue (right, FALSE));
3486 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3490 return geniCodeAdd (geniCodeRValue (left, FALSE),
3491 geniCodeRValue (right, FALSE),lvl);
3493 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
3496 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3497 geniCodeRValue (right, FALSE));
3500 return geniCodeRightShift (geniCodeRValue (left, FALSE),
3501 geniCodeRValue (right, FALSE));
3503 return geniCodeCast (operandType (left),
3504 geniCodeRValue (right, FALSE), FALSE);
3510 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3514 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3515 setOperandType (op, UCHARTYPE);
3526 return geniCodeLogic (geniCodeRValue (left, FALSE),
3527 geniCodeRValue (right, FALSE),
3530 return geniCodeConditional (tree,lvl);
3533 return operandFromLit (getSize (tree->right->ftype));
3537 sym_link *rtype = operandType (right);
3538 sym_link *ltype = operandType (left);
3539 if (IS_PTR (rtype) && IS_ITEMP (right)
3540 && right->isaddr && compareType (rtype->next, ltype) == 1)
3541 right = geniCodeRValue (right, TRUE);
3543 right = geniCodeRValue (right, FALSE);
3545 geniCodeAssign (left, right, 0);
3550 geniCodeAssign (left,
3551 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3553 geniCodeRValue (right, FALSE),FALSE), 0);
3557 geniCodeAssign (left,
3558 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3560 geniCodeRValue (right, FALSE)), 0);
3563 geniCodeAssign (left,
3564 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3566 geniCodeRValue (right, FALSE)), 0);
3569 sym_link *rtype = operandType (right);
3570 sym_link *ltype = operandType (left);
3571 if (IS_PTR (rtype) && IS_ITEMP (right)
3572 && right->isaddr && compareType (rtype->next, ltype) == 1)
3573 right = geniCodeRValue (right, TRUE);
3575 right = geniCodeRValue (right, FALSE);
3578 return geniCodeAssign (left,
3579 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3585 sym_link *rtype = operandType (right);
3586 sym_link *ltype = operandType (left);
3587 if (IS_PTR (rtype) && IS_ITEMP (right)
3588 && right->isaddr && compareType (rtype->next, ltype) == 1)
3590 right = geniCodeRValue (right, TRUE);
3594 right = geniCodeRValue (right, FALSE);
3597 geniCodeAssign (left,
3598 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3604 geniCodeAssign (left,
3605 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3607 geniCodeRValue (right, FALSE)), 0);
3610 geniCodeAssign (left,
3611 geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3613 geniCodeRValue (right, FALSE)), 0);
3616 geniCodeAssign (left,
3617 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3619 geniCodeRValue (right, FALSE),
3621 operandType (left)), 0);
3624 geniCodeAssign (left,
3625 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3627 geniCodeRValue (right, FALSE),
3629 operandType (left)), 0);
3632 geniCodeAssign (left,
3633 geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3635 geniCodeRValue (right, FALSE),
3637 operandType (left)), 0);
3639 return geniCodeRValue (right, FALSE);
3642 return geniCodeCall (ast2iCode (tree->left,lvl+1),
3645 geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3646 return ast2iCode (tree->right,lvl+1);
3649 geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3650 return ast2iCode (tree->right,lvl+1);
3653 geniCodeFunctionBody (tree,lvl);
3657 geniCodeReturn (right);
3661 geniCodeIfx (tree,lvl);
3665 geniCodeSwitch (tree,lvl);
3669 geniCodeInline (tree);
3673 geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
3680 /*-----------------------------------------------------------------*/
3681 /* reverseICChain - gets from the list and creates a linkedlist */
3682 /*-----------------------------------------------------------------*/
3689 while ((loop = getSet (&iCodeChain)))
3701 /*-----------------------------------------------------------------*/
3702 /* iCodeFromAst - given an ast will convert it to iCode */
3703 /*-----------------------------------------------------------------*/
3705 iCodeFromAst (ast * tree)
3707 returnLabel = newiTempLabel ("_return");
3708 entryLabel = newiTempLabel ("_entry");
3710 return reverseiCChain ();