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 -------------------------------------------------------------------------*/
28 /*-----------------------------------------------------------------*/
29 /* global variables */
31 set *iCodeChain = NULL;
41 symbol *returnLabel; /* function return label */
42 symbol *entryLabel; /* function entry label */
43 /*-----------------------------------------------------------------*/
44 /* forward definition of some functions */
45 operand *geniCodeDivision (operand *, operand *);
46 operand *geniCodeAssign (operand *, operand *, int);
47 operand *geniCodeArray (operand *, operand *,int);
48 operand *geniCodeArray2Ptr (operand *);
49 operand *geniCodeRValue (operand *, bool);
50 operand *geniCodeDerefPtr (operand *,int);
51 int isLvaluereq(int lvl);
53 #define PRINTFUNC(x) void x (FILE *of, iCode *ic, char *s)
54 /* forward definition of ic print functions */
55 PRINTFUNC (picGetValueAtAddr);
56 PRINTFUNC (picSetValueAtAddr);
57 PRINTFUNC (picAddrOf);
58 PRINTFUNC (picGeneric);
59 PRINTFUNC (picGenericOne);
61 PRINTFUNC (picAssign);
65 PRINTFUNC (picJumpTable);
66 PRINTFUNC (picInline);
67 PRINTFUNC (picReceive);
69 iCodeTable codeTable[] =
71 {'!', "not", picGenericOne, NULL},
72 {'~', "~", picGenericOne, NULL},
73 {RRC, "rrc", picGenericOne, NULL},
74 {RLC, "rlc", picGenericOne, NULL},
75 {GETHBIT, "ghbit", picGenericOne, NULL},
76 {UNARYMINUS, "-", picGenericOne, NULL},
77 {IPUSH, "push", picGenericOne, NULL},
78 {IPOP, "pop", picGenericOne, NULL},
79 {CALL, "call", picGenericOne, NULL},
80 {PCALL, "pcall", picGenericOne, NULL},
81 {FUNCTION, "proc", picGenericOne, NULL},
82 {ENDFUNCTION, "eproc", picGenericOne, NULL},
83 {RETURN, "ret", picGenericOne, NULL},
84 {'+', "+", picGeneric, NULL},
85 {'-', "-", picGeneric, NULL},
86 {'*', "*", picGeneric, NULL},
87 {'/', "/", picGeneric, NULL},
88 {'%', "%", picGeneric, NULL},
89 {'>', ">", picGeneric, NULL},
90 {'<', "<", picGeneric, NULL},
91 {LE_OP, "<=", picGeneric, NULL},
92 {GE_OP, ">=", picGeneric, NULL},
93 {EQ_OP, "==", picGeneric, NULL},
94 {NE_OP, "!=", picGeneric, NULL},
95 {AND_OP, "&&", picGeneric, NULL},
96 {OR_OP, "||", picGeneric, NULL},
97 {'^', "^", picGeneric, NULL},
98 {'|', "|", picGeneric, NULL},
99 {BITWISEAND, "&", picGeneric, NULL},
100 {LEFT_OP, "<<", picGeneric, NULL},
101 {RIGHT_OP, ">>", picGeneric, NULL},
102 {GET_VALUE_AT_ADDRESS, "@", picGetValueAtAddr, NULL},
103 {ADDRESS_OF, "&", picAddrOf, NULL},
104 {CAST, "<>", picCast, NULL},
105 {'=', ":=", picAssign, NULL},
106 {LABEL, "", picLabel, NULL},
107 {GOTO, "", picGoto, NULL},
108 {JUMPTABLE, "jtab", picJumpTable, NULL},
109 {IFX, "if", picIfx, NULL},
110 {INLINEASM, "", picInline, NULL},
111 {RECEIVE, "recv", picReceive, NULL},
112 {SEND, "send", picGenericOne, NULL},
113 {ARRAYINIT, "arrayInit", picGenericOne, NULL},
117 /*-----------------------------------------------------------------*/
118 /* operandName - returns the name of the operand */
119 /*-----------------------------------------------------------------*/
121 printOperand (operand * op, FILE * file)
138 opetype = getSpec (operandType (op));
139 if (SPEC_NOUN (opetype) == V_FLOAT)
140 fprintf (file, "%g {", SPEC_CVAL (opetype).v_float);
142 fprintf (file, "0x%x {", (int) floatFromVal (op->operand.valOperand));
143 printTypeChain (operandType (op), file);
150 fprintf (file, "%s [k%d lr%d:%d so:%d]{ ia%d re%d rm%d nos%d}", /*{ar%d rm%d ru%d p%d a%d u%d i%d au%d k%d ks%d}" , */
151 (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name),
153 OP_LIVEFROM (op), OP_LIVETO (op),
154 OP_SYMBOL (op)->stack,
155 op->isaddr, OP_SYMBOL (op)->isreqv, OP_SYMBOL (op)->remat,OP_SYMBOL(op)->noSpilLoc
159 printTypeChain (operandType (op), file);
160 if (SPIL_LOC (op) && IS_ITEMP (op))
161 fprintf (file, "}{ sir@ %s", SPIL_LOC (op)->rname);
166 /* if assigned to registers */
167 if (OP_SYMBOL (op)->nRegs)
169 if (OP_SYMBOL (op)->isspilt)
171 if (!OP_SYMBOL (op)->remat)
172 if (OP_SYMBOL (op)->usl.spillLoc)
173 fprintf (file, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
174 OP_SYMBOL (op)->usl.spillLoc->rname :
175 OP_SYMBOL (op)->usl.spillLoc->name));
177 fprintf (file, "[err]");
179 fprintf (file, "[remat]");
185 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
186 fprintf (file, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i]));
191 fprintf (file, "%s", (OP_SYMBOL (op)->rname[0] ?
192 OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name));
193 /* if assigned to registers */
194 if (OP_SYMBOL (op)->nRegs && !OP_SYMBOL (op)->isspilt)
198 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
199 fprintf (file, "%s ", (OP_SYMBOL (op)->regs[i] ?
200 OP_SYMBOL (op)->regs[i]->name :
209 printTypeChain (op->operand.typeOperand, file);
215 fprintf (file, "\n");
220 /*-----------------------------------------------------------------*/
221 /* print functions */
222 /*-----------------------------------------------------------------*/
223 PRINTFUNC (picGetValueAtAddr)
226 printOperand (IC_RESULT (ic), of);
229 printOperand (IC_LEFT (ic), of);
235 PRINTFUNC (picSetValueAtAddr)
239 printOperand (IC_LEFT (ic), of);
240 fprintf (of, "] = ");
241 printOperand (IC_RIGHT (ic), of);
245 PRINTFUNC (picAddrOf)
248 printOperand (IC_RESULT (ic), of);
249 if (IS_ITEMP (IC_LEFT (ic)))
252 fprintf (of, " = &[");
253 printOperand (IC_LEFT (ic), of);
256 if (IS_ITEMP (IC_LEFT (ic)))
257 fprintf (of, " offsetAdd ");
260 printOperand (IC_RIGHT (ic), of);
262 if (IS_ITEMP (IC_LEFT (ic)))
268 PRINTFUNC (picJumpTable)
273 fprintf (of, "%s\t", s);
274 printOperand (IC_JTCOND (ic), of);
276 for (sym = setFirstItem (IC_JTLABELS (ic)); sym;
277 sym = setNextItem (IC_JTLABELS (ic)))
278 fprintf (of, "\t\t\t%s\n", sym->name);
281 PRINTFUNC (picGeneric)
284 printOperand (IC_RESULT (ic), of);
286 printOperand (IC_LEFT (ic), of);
287 fprintf (of, " %s ", s);
288 printOperand (IC_RIGHT (ic), of);
292 PRINTFUNC (picGenericOne)
297 printOperand (IC_RESULT (ic), of);
303 fprintf (of, "%s ", s);
304 printOperand (IC_LEFT (ic), of);
307 if (!IC_RESULT (ic) && !IC_LEFT (ic))
316 printOperand (IC_RESULT (ic), of);
318 printOperand (IC_LEFT (ic), of);
319 printOperand (IC_RIGHT (ic), of);
324 PRINTFUNC (picAssign)
328 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
331 printOperand (IC_RESULT (ic), of);
333 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
336 fprintf (of, " %s ", s);
337 printOperand (IC_RIGHT (ic), of);
344 fprintf (of, " %s($%d) :\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
350 fprintf (of, " goto %s($%d)\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
357 printOperand (IC_COND (ic), of);
360 fprintf (of, " == 0 goto %s($%d)\n", IC_FALSE (ic)->name, IC_FALSE (ic)->key);
363 fprintf (of, " != 0 goto %s($%d)\n", IC_TRUE (ic)->name, IC_TRUE (ic)->key);
365 fprintf (of, "\tzzgoto %s\n", IC_FALSE (ic)->name);
369 PRINTFUNC (picInline)
371 fprintf (of, "%s", IC_INLINE (ic));
374 PRINTFUNC (picReceive)
376 printOperand (IC_RESULT (ic), of);
377 fprintf (of, " = %s ", s);
378 printOperand (IC_LEFT (ic), of);
382 /*-----------------------------------------------------------------*/
383 /* piCode - prints one iCode */
384 /*-----------------------------------------------------------------*/
386 piCode (void *item, FILE * of)
394 icTab = getTableEntry (ic->op);
395 fprintf (stdout, "%s(%d:%d:%d:%d:%d)\t",
396 ic->filename, ic->lineno,
397 ic->seq, ic->key, ic->depth, ic->supportRtn);
398 icTab->iCodePrint (of, ic, icTab->printName);
404 printiCChain(ic,stdout);
406 /*-----------------------------------------------------------------*/
407 /* printiCChain - prints intermediate code for humans */
408 /*-----------------------------------------------------------------*/
410 printiCChain (iCode * icChain, FILE * of)
417 for (loop = icChain; loop; loop = loop->next)
419 if ((icTab = getTableEntry (loop->op)))
421 fprintf (of, "%s(%d:%d:%d:%d:%d)\t",
422 loop->filename, loop->lineno,
423 loop->seq, loop->key, loop->depth, loop->supportRtn);
425 icTab->iCodePrint (of, loop, icTab->printName);
431 /*-----------------------------------------------------------------*/
432 /* newOperand - allocate, init & return a new iCode */
433 /*-----------------------------------------------------------------*/
439 op = Safe_calloc (1, sizeof (operand));
445 /*-----------------------------------------------------------------*/
446 /* newiCode - create and return a new iCode entry initialised */
447 /*-----------------------------------------------------------------*/
449 newiCode (int op, operand * left, operand * right)
453 ic = Safe_calloc (1, sizeof (iCode));
456 ic->filename = filename;
458 ic->level = scopeLevel;
460 ic->key = iCodeKey++;
462 IC_RIGHT (ic) = right;
467 /*-----------------------------------------------------------------*/
468 /* newiCode for conditional statements */
469 /*-----------------------------------------------------------------*/
471 newiCodeCondition (operand * condition,
477 ic = newiCode (IFX, NULL, NULL);
478 IC_COND (ic) = condition;
479 IC_TRUE (ic) = trueLabel;
480 IC_FALSE (ic) = falseLabel;
484 /*-----------------------------------------------------------------*/
485 /* newiCodeLabelGoto - unconditional goto statement| label stmnt */
486 /*-----------------------------------------------------------------*/
488 newiCodeLabelGoto (int op, symbol * label)
492 ic = newiCode (op, NULL, NULL);
494 ic->argLabel.label = label;
496 IC_RIGHT (ic) = NULL;
497 IC_RESULT (ic) = NULL;
501 /*-----------------------------------------------------------------*/
502 /* newiTemp - allocate & return a newItemp Variable */
503 /*-----------------------------------------------------------------*/
510 sprintf (buffer, "%s", s);
512 sprintf (buffer, "iTemp%d", iTempNum++);
513 itmp = newSymbol (buffer, 1);
514 strcpy (itmp->rname, itmp->name);
520 /*-----------------------------------------------------------------*/
521 /* newiTempLabel - creates a temp variable label */
522 /*-----------------------------------------------------------------*/
524 newiTempLabel (char *s)
528 /* check if this alredy exists */
529 if (s && (itmplbl = findSym (LabelTab, NULL, s)))
533 itmplbl = newSymbol (s, 1);
536 sprintf (buffer, "iTempLbl%d", iTempLblNum++);
537 itmplbl = newSymbol (buffer, 1);
542 itmplbl->key = labelKey++;
543 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
547 /*-----------------------------------------------------------------*/
548 /* newiTempPreheaderLabel - creates a new preheader label */
549 /*-----------------------------------------------------------------*/
551 newiTempPreheaderLabel ()
555 sprintf (buffer, "preHeaderLbl%d", iTempLblNum++);
556 itmplbl = newSymbol (buffer, 1);
560 itmplbl->key = labelKey++;
561 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
566 /*-----------------------------------------------------------------*/
567 /* initiCode - initialises some iCode related stuff */
568 /*-----------------------------------------------------------------*/
575 /*-----------------------------------------------------------------*/
576 /* copyiCode - make a copy of the iCode given */
577 /*-----------------------------------------------------------------*/
579 copyiCode (iCode * ic)
581 iCode *nic = newiCode (ic->op, NULL, NULL);
583 nic->lineno = ic->lineno;
584 nic->filename = ic->filename;
585 nic->block = ic->block;
586 nic->level = ic->level;
587 nic->parmBytes = ic->parmBytes;
589 /* deal with the special cases first */
593 IC_COND (nic) = operandFromOperand (IC_COND (ic));
594 IC_TRUE (nic) = IC_TRUE (ic);
595 IC_FALSE (nic) = IC_FALSE (ic);
599 IC_JTCOND (nic) = operandFromOperand (IC_JTCOND (ic));
600 IC_JTLABELS (nic) = IC_JTLABELS (ic);
605 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
606 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
607 IC_ARGS (nic) = IC_ARGS (ic);
611 IC_INLINE (nic) = IC_INLINE (ic);
615 IC_ARRAYILIST(nic) = IC_ARRAYILIST(ic);
619 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
620 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
621 IC_RIGHT (nic) = operandFromOperand (IC_RIGHT (ic));
627 /*-----------------------------------------------------------------*/
628 /* getTableEntry - gets the table entry for the given operator */
629 /*-----------------------------------------------------------------*/
631 getTableEntry (int oper)
635 for (i = 0; i < (sizeof (codeTable) / sizeof (iCodeTable)); i++)
636 if (oper == codeTable[i].icode)
637 return &codeTable[i];
642 /*-----------------------------------------------------------------*/
643 /* newiTempOperand - new intermediate temp operand */
644 /*-----------------------------------------------------------------*/
646 newiTempOperand (sym_link * type, char throwType)
649 operand *op = newOperand ();
653 itmp = newiTemp (NULL);
655 etype = getSpec (type);
657 if (IS_LITERAL (etype))
660 /* copy the type information */
662 itmp->etype = getSpec (itmp->type = (throwType ? type :
663 copyLinkChain (type)));
664 if (IS_LITERAL (itmp->etype))
666 SPEC_SCLS (itmp->etype) = S_REGISTER;
667 SPEC_OCLS (itmp->etype) = reg;
670 op->operand.symOperand = itmp;
671 op->key = itmp->key = ++operandKey;
675 /*-----------------------------------------------------------------*/
676 /* operandType - returns the type chain for an operand */
677 /*-----------------------------------------------------------------*/
679 operandType (operand * op)
681 /* depending on type of operand */
686 return op->operand.valOperand->type;
689 return op->operand.symOperand->type;
692 return op->operand.typeOperand;
694 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
695 " operand type not known ");
696 assert (0); /* should never come here */
697 /* Just to keep the compiler happy */
698 return (sym_link *) 0;
702 /*-----------------------------------------------------------------*/
703 /* isParamterToCall - will return 1 if op is a parameter to args */
704 /*-----------------------------------------------------------------*/
706 isParameterToCall (value * args, operand * op)
713 isSymbolEqual (op->operand.symOperand, tval->sym))
720 /*-----------------------------------------------------------------*/
721 /* isOperandGlobal - return 1 if operand is a global variable */
722 /*-----------------------------------------------------------------*/
724 isOperandGlobal (operand * op)
732 if (op->type == SYMBOL &&
733 (op->operand.symOperand->level == 0 ||
734 IS_STATIC (op->operand.symOperand->etype) ||
735 IS_EXTERN (op->operand.symOperand->etype))
742 /*-----------------------------------------------------------------*/
743 /* isOperandVolatile - return 1 if the operand is volatile */
744 /*-----------------------------------------------------------------*/
746 isOperandVolatile (operand * op, bool chkTemp)
751 if (IS_ITEMP (op) && !chkTemp)
754 opetype = getSpec (optype = operandType (op));
756 if (IS_PTR (optype) && DCL_PTR_VOLATILE (optype))
759 if (IS_VOLATILE (opetype))
764 /*-----------------------------------------------------------------*/
765 /* isOperandLiteral - returns 1 if an operand contains a literal */
766 /*-----------------------------------------------------------------*/
768 isOperandLiteral (operand * op)
775 opetype = getSpec (operandType (op));
777 if (IS_LITERAL (opetype))
782 /*-----------------------------------------------------------------*/
783 /* isOperandInFarSpace - will return true if operand is in farSpace */
784 /*-----------------------------------------------------------------*/
786 isOperandInFarSpace (operand * op)
796 if (!IS_TRUE_SYMOP (op))
799 etype = SPIL_LOC (op)->etype;
805 etype = getSpec (operandType (op));
807 return (IN_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
810 /*-----------------------------------------------------------------*/
811 /* isOperandOnStack - will return true if operand is on stack */
812 /*-----------------------------------------------------------------*/
814 isOperandOnStack (operand * op)
824 etype = getSpec (operandType (op));
826 return ((IN_STACK (etype)) ? TRUE : FALSE);
829 /*-----------------------------------------------------------------*/
830 /* operandLitValue - literal value of an operand */
831 /*-----------------------------------------------------------------*/
833 operandLitValue (operand * op)
835 assert (isOperandLiteral (op));
837 return floatFromVal (op->operand.valOperand);
840 /*-----------------------------------------------------------------*/
841 /* operandOperation - perforoms operations on operands */
842 /*-----------------------------------------------------------------*/
844 operandOperation (operand * left, operand * right,
845 int op, sym_link * type)
847 sym_link *let , *ret=NULL;
848 operand *retval = (operand *) 0;
850 assert (isOperandLiteral (left));
851 let = getSpec(operandType(left));
853 assert (isOperandLiteral (right));
854 ret = getSpec(operandType(left));
860 retval = operandFromValue (valCastLiteral (type,
861 operandLitValue (left) +
862 operandLitValue (right)));
865 retval = operandFromValue (valCastLiteral (type,
866 operandLitValue (left) -
867 operandLitValue (right)));
870 retval = operandFromValue (valCastLiteral (type,
871 operandLitValue (left) *
872 operandLitValue (right)));
875 if ((unsigned long) operandLitValue (right) == 0)
877 werror (E_DIVIDE_BY_ZERO);
882 retval = operandFromValue (valCastLiteral (type,
883 operandLitValue (left) /
884 operandLitValue (right)));
887 if ((unsigned long) operandLitValue (right) == 0) {
888 werror (E_DIVIDE_BY_ZERO);
892 retval = operandFromLit ((SPEC_USIGN(let) ?
893 (unsigned long) operandLitValue (left) :
894 (long) operandLitValue (left)) %
896 (unsigned long) operandLitValue (right) :
897 (long) operandLitValue (right)));
901 retval = operandFromLit (((SPEC_USIGN(let) ?
902 (unsigned long) operandLitValue (left) :
903 (long) operandLitValue (left)) <<
905 (unsigned long) operandLitValue (right) :
906 (long) operandLitValue (right))));
909 retval = operandFromLit (((SPEC_USIGN(let) ?
910 (unsigned long) operandLitValue (left) :
911 (long) operandLitValue (left)) >>
913 (unsigned long) operandLitValue (right) :
914 (long) operandLitValue (right))));
917 retval = operandFromLit (operandLitValue (left) ==
918 operandLitValue (right));
921 retval = operandFromLit (operandLitValue (left) <
922 operandLitValue (right));
925 retval = operandFromLit (operandLitValue (left) <=
926 operandLitValue (right));
929 retval = operandFromLit (operandLitValue (left) !=
930 operandLitValue (right));
933 retval = operandFromLit (operandLitValue (left) >
934 operandLitValue (right));
937 retval = operandFromLit (operandLitValue (left) >=
938 operandLitValue (right));
941 retval = operandFromLit ((unsigned long) operandLitValue (left) &
942 (unsigned long) operandLitValue (right));
945 retval = operandFromLit ((unsigned long) operandLitValue (left) |
946 (unsigned long) operandLitValue (right));
949 retval = operandFromLit ((unsigned long) operandLitValue (left) ^
950 (unsigned long) operandLitValue (right));
953 retval = operandFromLit (operandLitValue (left) &&
954 operandLitValue (right));
957 retval = operandFromLit (operandLitValue (left) ||
958 operandLitValue (right));
962 long i = (long) operandLitValue (left);
964 retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
970 long i = (long) operandLitValue (left);
972 retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
978 retval = operandFromLit (-1 * operandLitValue (left));
982 retval = operandFromLit (~((long) operandLitValue (left)));
986 retval = operandFromLit (!operandLitValue (left));
990 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
991 " operandOperation invalid operator ");
999 /*-----------------------------------------------------------------*/
1000 /* isOperandEqual - compares two operand & return 1 if they r = */
1001 /*-----------------------------------------------------------------*/
1003 isOperandEqual (operand * left, operand * right)
1005 /* if the pointers are equal then they are equal */
1009 /* if either of them null then false */
1010 if (!left || !right)
1013 if (left->type != right->type)
1016 if (IS_SYMOP (left) && IS_SYMOP (right))
1017 return left->key == right->key;
1019 /* if types are the same */
1023 return isSymbolEqual (left->operand.symOperand,
1024 right->operand.symOperand);
1026 return (floatFromVal (left->operand.valOperand) ==
1027 floatFromVal (right->operand.valOperand));
1029 if (compareType (left->operand.typeOperand,
1030 right->operand.typeOperand) == 1)
1037 /*-----------------------------------------------------------------*/
1038 /* isiCodeEqual - comapres two iCodes are returns true if yes */
1039 /*-----------------------------------------------------------------*/
1041 isiCodeEqual (iCode * left, iCode * right)
1043 /* if the same pointer */
1047 /* if either of them null */
1048 if (!left || !right)
1051 /* if operand are the same */
1052 if (left->op == right->op)
1055 /* compare all the elements depending on type */
1056 if (left->op != IFX)
1058 if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
1060 if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
1066 if (!isOperandEqual (IC_COND (left), IC_COND (right)))
1068 if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
1070 if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
1078 /*-----------------------------------------------------------------*/
1079 /* newiTempFromOp - create a temp Operand with same attributes */
1080 /*-----------------------------------------------------------------*/
1082 newiTempFromOp (operand * op)
1092 nop = newiTempOperand (operandType (op), TRUE);
1093 nop->isaddr = op->isaddr;
1094 nop->isvolatile = op->isvolatile;
1095 nop->isGlobal = op->isGlobal;
1096 nop->isLiteral = op->isLiteral;
1097 nop->usesDefs = op->usesDefs;
1098 nop->isParm = op->isParm;
1102 /*-----------------------------------------------------------------*/
1103 /* operand from operand - creates an operand holder for the type */
1104 /*-----------------------------------------------------------------*/
1106 operandFromOperand (operand * op)
1112 nop = newOperand ();
1113 nop->type = op->type;
1114 nop->isaddr = op->isaddr;
1116 nop->isvolatile = op->isvolatile;
1117 nop->isGlobal = op->isGlobal;
1118 nop->isLiteral = op->isLiteral;
1119 nop->usesDefs = op->usesDefs;
1120 nop->isParm = op->isParm;
1125 nop->operand.symOperand = op->operand.symOperand;
1128 nop->operand.valOperand = op->operand.valOperand;
1131 nop->operand.typeOperand = op->operand.typeOperand;
1138 /*-----------------------------------------------------------------*/
1139 /* opFromOpWithDU - makes a copy of the operand and DU chains */
1140 /*-----------------------------------------------------------------*/
1142 opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
1144 operand *nop = operandFromOperand (op);
1146 if (nop->type == SYMBOL)
1148 OP_SYMBOL (nop)->defs = bitVectCopy (defs);
1149 OP_SYMBOL (nop)->uses = bitVectCopy (uses);
1155 /*-----------------------------------------------------------------*/
1156 /* operandFromSymbol - creates an operand from a symbol */
1157 /*-----------------------------------------------------------------*/
1159 operandFromSymbol (symbol * sym)
1164 /* if the symbol's type is a literal */
1165 /* then it is an enumerator type */
1166 if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
1167 return operandFromValue (valFromType (sym->etype));
1170 sym->key = ++operandKey;
1172 /* if this an implicit variable, means struct/union */
1173 /* member so just return it */
1174 if (sym->implicit || IS_FUNC (sym->type))
1178 op->operand.symOperand = sym;
1180 op->isvolatile = isOperandVolatile (op, TRUE);
1181 op->isGlobal = isOperandGlobal (op);
1185 /* under the following conditions create a
1186 register equivalent for a local symbol */
1187 if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
1188 (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
1189 /* (!TARGET_IS_DS390)) && */
1190 (!(options.model == MODEL_FLAT24)) ) &&
1191 options.stackAuto == 0)
1194 if (!IS_AGGREGATE (sym->type) && /* not an aggregate */
1195 !IS_FUNC (sym->type) && /* not a function */
1196 !sym->_isparm && /* not a parameter */
1197 sym->level && /* is a local variable */
1198 !sym->addrtaken && /* whose address has not been taken */
1199 !sym->reqv && /* does not already have a register euivalence */
1200 !IS_VOLATILE (sym->etype) && /* not declared as volatile */
1201 !IS_STATIC (sym->etype) && /* and not declared static */
1202 !sym->islbl && /* not a label */
1203 ok && /* farspace check */
1204 !IS_BITVAR (sym->etype) /* not a bit variable */
1208 /* we will use it after all optimizations
1209 and before liveRange calculation */
1210 sym->reqv = newiTempOperand (sym->type, 0);
1211 sym->reqv->key = sym->key;
1212 OP_SYMBOL (sym->reqv)->key = sym->key;
1213 OP_SYMBOL (sym->reqv)->isreqv = 1;
1214 OP_SYMBOL (sym->reqv)->islocal = 1;
1215 SPIL_LOC (sym->reqv) = sym;
1218 if (!IS_AGGREGATE (sym->type))
1222 op->operand.symOperand = sym;
1225 op->isvolatile = isOperandVolatile (op, TRUE);
1226 op->isGlobal = isOperandGlobal (op);
1227 op->isPtr = IS_PTR (operandType (op));
1228 op->isParm = sym->_isparm;
1233 /* itemp = &[_symbol] */
1235 ic = newiCode (ADDRESS_OF, newOperand (), NULL);
1236 IC_LEFT (ic)->type = SYMBOL;
1237 IC_LEFT (ic)->operand.symOperand = sym;
1238 IC_LEFT (ic)->key = sym->key;
1239 (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
1240 (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
1241 IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
1244 IC_RESULT (ic) = newiTempOperand (sym->type, 0);
1245 if (IS_ARRAY (sym->type))
1247 IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
1248 IC_RESULT (ic)->isaddr = 0;
1251 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
1253 IC_RESULT (ic)->operand.symOperand->args = sym->args;
1257 return IC_RESULT (ic);
1260 /*-----------------------------------------------------------------*/
1261 /* operandFromValue - creates an operand from value */
1262 /*-----------------------------------------------------------------*/
1264 operandFromValue (value * val)
1268 /* if this is a symbol then do the symbol thing */
1270 return operandFromSymbol (val->sym);
1272 /* this is not a symbol */
1275 op->operand.valOperand = val;
1276 op->isLiteral = isOperandLiteral (op);
1280 /*-----------------------------------------------------------------*/
1281 /* operandFromLink - operand from typeChain */
1282 /*-----------------------------------------------------------------*/
1284 operandFromLink (sym_link * type)
1288 /* operand from sym_link */
1294 op->operand.typeOperand = copyLinkChain (type);
1298 /*-----------------------------------------------------------------*/
1299 /* operandFromLit - makes an operand from a literal value */
1300 /*-----------------------------------------------------------------*/
1302 operandFromLit (double i)
1304 return operandFromValue (valueFromLit (i));
1307 /*-----------------------------------------------------------------*/
1308 /* operandFromAst - creates an operand from an ast */
1309 /*-----------------------------------------------------------------*/
1311 operandFromAst (ast * tree,int lvl)
1317 /* depending on type do */
1321 return ast2iCode (tree,lvl+1);
1325 return operandFromValue (tree->opval.val);
1329 return operandFromLink (tree->opval.lnk);
1333 /* Just to keep the comiler happy */
1334 return (operand *) 0;
1337 /*-----------------------------------------------------------------*/
1338 /* setOperandType - sets the operand's type to the given type */
1339 /*-----------------------------------------------------------------*/
1341 setOperandType (operand * op, sym_link * type)
1343 /* depending on the type of operand */
1348 op->operand.valOperand->etype =
1349 getSpec (op->operand.valOperand->type =
1350 copyLinkChain (type));
1354 if (op->operand.symOperand->isitmp)
1355 op->operand.symOperand->etype =
1356 getSpec (op->operand.symOperand->type =
1357 copyLinkChain (type));
1359 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1360 "attempt to modify type of source");
1364 op->operand.typeOperand = copyLinkChain (type);
1369 /*-----------------------------------------------------------------*/
1370 /* Get size in byte of ptr need to access an array */
1371 /*-----------------------------------------------------------------*/
1373 getArraySizePtr (operand * op)
1375 sym_link *ltype = operandType(op);
1379 int size = getSize(ltype);
1380 return(IS_GENPTR(ltype)?(size-1):size);
1385 sym_link *letype = getSpec(ltype);
1386 switch (PTR_TYPE (SPEC_OCLS (letype)))
1398 return (GPTRSIZE-1);
1407 /*-----------------------------------------------------------------*/
1408 /* perform "usual unary conversions" */
1409 /*-----------------------------------------------------------------*/
1411 usualUnaryConversions (operand * op)
1413 if (IS_INTEGRAL (operandType (op)))
1415 if (getSize (operandType (op)) < (unsigned int) INTSIZE)
1418 return geniCodeCast (INTTYPE, op, TRUE);
1424 /*-----------------------------------------------------------------*/
1425 /* perform "usual binary conversions" */
1426 /*-----------------------------------------------------------------*/
1428 usualBinaryConversions (operand ** op1, operand ** op2)
1431 sym_link *rtype = operandType (*op2);
1432 sym_link *ltype = operandType (*op1);
1434 ctype = computeType (ltype, rtype);
1435 *op1 = geniCodeCast (ctype, *op1, TRUE);
1436 *op2 = geniCodeCast (ctype, *op2, TRUE);
1441 /*-----------------------------------------------------------------*/
1442 /* geniCodeValueAtAddress - generate intermeditate code for value */
1444 /*-----------------------------------------------------------------*/
1446 geniCodeRValue (operand * op, bool force)
1449 sym_link *type = operandType (op);
1450 sym_link *etype = getSpec (type);
1452 /* if this is an array & already */
1453 /* an address then return this */
1454 if (IS_AGGREGATE (type) ||
1455 (IS_PTR (type) && !force && !op->isaddr))
1456 return operandFromOperand (op);
1458 /* if this is not an address then must be */
1459 /* rvalue already so return this one */
1463 /* if this is not a temp symbol then */
1464 if (!IS_ITEMP (op) &&
1466 !IN_FARSPACE (SPEC_OCLS (etype)))
1468 op = operandFromOperand (op);
1473 if (IS_SPEC (type) &&
1474 IS_TRUE_SYMOP (op) &&
1475 (!IN_FARSPACE (SPEC_OCLS (etype)) ||
1476 /* TARGET_IS_DS390)) */
1477 (options.model == MODEL_FLAT24) ))
1479 op = operandFromOperand (op);
1484 ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1485 if (IS_PTR (type) && op->isaddr && force)
1488 type = copyLinkChain (type);
1490 IC_RESULT (ic) = newiTempOperand (type, 1);
1491 IC_RESULT (ic)->isaddr = 0;
1493 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1495 /* if the right is a symbol */
1496 if (op->type == SYMBOL)
1497 IC_RESULT (ic)->operand.symOperand->args =
1498 op->operand.symOperand->args;
1501 return IC_RESULT (ic);
1504 /*-----------------------------------------------------------------*/
1505 /* geniCodeCast - changes the value from one type to another */
1506 /*-----------------------------------------------------------------*/
1508 geniCodeCast (sym_link * type, operand * op, bool implicit)
1512 sym_link *opetype = getSpec (optype = operandType (op));
1515 /* one of them has size zero then error */
1516 if (IS_VOID (optype))
1518 werror (E_CAST_ZERO);
1522 /* if the operand is already the desired type then do nothing */
1523 if (compareType (type, optype) == 1)
1526 /* if this is a literal then just change the type & return */
1527 if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1528 return operandFromValue (valCastLiteral (type,
1529 operandLitValue (op)));
1531 /* if casting to some pointer type &&
1532 the destination is not a generic pointer
1533 then give a warning : (only for implicit casts) */
1534 if (IS_PTR (optype) && implicit &&
1535 (DCL_TYPE (optype) != DCL_TYPE (type)) &&
1538 werror (E_INCOMPAT_CAST);
1539 fprintf (stderr, "from type '");
1540 printTypeChain (optype, stderr);
1541 fprintf (stderr, "' to type '");
1542 printTypeChain (type, stderr);
1543 fprintf (stderr, "'\n");
1546 /* if they are the same size create an assignment */
1547 if (getSize (type) == getSize (optype) &&
1548 !IS_BITFIELD (type) &&
1550 !IS_FLOAT (optype) &&
1551 ((IS_SPEC (type) && IS_SPEC (optype)) ||
1552 (!IS_SPEC (type) && !IS_SPEC (optype))))
1555 ic = newiCode ('=', NULL, op);
1556 IC_RESULT (ic) = newiTempOperand (type, 0);
1557 SPIL_LOC (IC_RESULT (ic)) =
1558 (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
1559 IC_RESULT (ic)->isaddr = 0;
1563 ic = newiCode (CAST, operandFromLink (type),
1564 geniCodeRValue (op, FALSE));
1566 IC_RESULT (ic) = newiTempOperand (type, 0);
1569 /* preserve the storage class & output class */
1570 /* of the original variable */
1571 restype = getSpec (operandType (IC_RESULT (ic)));
1572 SPEC_SCLS (restype) = SPEC_SCLS (opetype);
1573 SPEC_OCLS (restype) = SPEC_OCLS (opetype);
1576 return IC_RESULT (ic);
1579 /*-----------------------------------------------------------------*/
1580 /* geniCodeLabel - will create a Label */
1581 /*-----------------------------------------------------------------*/
1583 geniCodeLabel (symbol * label)
1587 ic = newiCodeLabelGoto (LABEL, label);
1591 /*-----------------------------------------------------------------*/
1592 /* geniCodeGoto - will create a Goto */
1593 /*-----------------------------------------------------------------*/
1595 geniCodeGoto (symbol * label)
1599 ic = newiCodeLabelGoto (GOTO, label);
1603 /*-----------------------------------------------------------------*/
1604 /* geniCodeMultiply - gen intermediate code for multiplication */
1605 /*-----------------------------------------------------------------*/
1607 geniCodeMultiply (operand * left, operand * right,int resultIsInt)
1614 /* if they are both literal then we know the result */
1615 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1616 return operandFromValue (valMult (left->operand.valOperand,
1617 right->operand.valOperand));
1619 if (IS_LITERAL(retype)) {
1620 p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
1623 resType = usualBinaryConversions (&left, &right);
1625 rtype = operandType (right);
1626 retype = getSpec (rtype);
1627 ltype = operandType (left);
1628 letype = getSpec (ltype);
1632 SPEC_NOUN(getSpec(resType))=V_INT;
1635 /* if the right is a literal & power of 2 */
1636 /* then make it a left shift */
1637 /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
1638 efficient in most cases than 2 bytes result = 2 bytes << literal
1639 if port has 1 byte muldiv */
1640 if (p2 && !IS_FLOAT (letype) &&
1641 !((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
1642 (port->support.muldiv == 1)))
1644 if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
1646 /* LEFT_OP need same size for left and result, */
1647 left = geniCodeCast (resType, left, TRUE);
1648 ltype = operandType (left);
1650 ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
1654 ic = newiCode ('*', left, right); /* normal multiplication */
1655 /* if the size left or right > 1 then support routine */
1656 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1660 IC_RESULT (ic) = newiTempOperand (resType, 1);
1663 return IC_RESULT (ic);
1666 /*-----------------------------------------------------------------*/
1667 /* geniCodeDivision - gen intermediate code for division */
1668 /*-----------------------------------------------------------------*/
1670 geniCodeDivision (operand * left, operand * right)
1675 sym_link *rtype = operandType (right);
1676 sym_link *retype = getSpec (rtype);
1677 sym_link *ltype = operandType (left);
1678 sym_link *letype = getSpec (ltype);
1680 resType = usualBinaryConversions (&left, &right);
1682 /* if the right is a literal & power of 2 */
1683 /* then make it a right shift */
1684 if (IS_LITERAL (retype) &&
1685 !IS_FLOAT (letype) &&
1686 (p2 = powof2 ((unsigned long)
1687 floatFromVal (right->operand.valOperand)))) {
1688 ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
1692 ic = newiCode ('/', left, right); /* normal division */
1693 /* if the size left or right > 1 then support routine */
1694 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1697 IC_RESULT (ic) = newiTempOperand (resType, 0);
1700 return IC_RESULT (ic);
1702 /*-----------------------------------------------------------------*/
1703 /* geniCodeModulus - gen intermediate code for modulus */
1704 /*-----------------------------------------------------------------*/
1706 geniCodeModulus (operand * left, operand * right)
1712 /* if they are both literal then we know the result */
1713 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1714 return operandFromValue (valMod (left->operand.valOperand,
1715 right->operand.valOperand));
1717 resType = usualBinaryConversions (&left, &right);
1719 /* now they are the same size */
1720 ic = newiCode ('%', left, right);
1722 /* if the size left or right > 1 then support routine */
1723 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1725 IC_RESULT (ic) = newiTempOperand (resType, 0);
1728 return IC_RESULT (ic);
1731 /*-----------------------------------------------------------------*/
1732 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
1733 /*-----------------------------------------------------------------*/
1735 geniCodePtrPtrSubtract (operand * left, operand * right)
1741 /* if they are both literals then */
1742 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1744 result = operandFromValue (valMinus (left->operand.valOperand,
1745 right->operand.valOperand));
1749 ic = newiCode ('-', left, right);
1751 IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
1755 return geniCodeDivision (result,
1756 operandFromLit (getSize (ltype->next)));
1759 /*-----------------------------------------------------------------*/
1760 /* geniCodeSubtract - generates code for subtraction */
1761 /*-----------------------------------------------------------------*/
1763 geniCodeSubtract (operand * left, operand * right)
1770 /* if they both pointers then */
1771 if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
1772 (IS_PTR (rtype) || IS_ARRAY (rtype)))
1773 return geniCodePtrPtrSubtract (left, right);
1775 /* if they are both literal then we know the result */
1776 if (IS_LITERAL (letype) && IS_LITERAL (retype)
1777 && left->isLiteral && right->isLiteral)
1778 return operandFromValue (valMinus (left->operand.valOperand,
1779 right->operand.valOperand));
1781 /* if left is an array or pointer */
1782 if (IS_PTR (ltype) || IS_ARRAY (ltype))
1784 isarray = left->isaddr;
1785 right = geniCodeMultiply (right,
1786 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
1787 resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
1790 { /* make them the same size */
1791 resType = usualBinaryConversions (&left, &right);
1794 ic = newiCode ('-', left, right);
1796 IC_RESULT (ic) = newiTempOperand (resType, 1);
1797 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
1799 /* if left or right is a float */
1800 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
1804 return IC_RESULT (ic);
1807 /*-----------------------------------------------------------------*/
1808 /* geniCodeAdd - generates iCode for addition */
1809 /*-----------------------------------------------------------------*/
1811 geniCodeAdd (operand * left, operand * right,int lvl)
1819 /* if left is an array then array access */
1820 if (IS_ARRAY (ltype))
1821 return geniCodeArray (left, right,lvl);
1823 /* if the right side is LITERAL zero */
1824 /* return the left side */
1825 if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
1828 /* if left is literal zero return right */
1829 if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
1832 /* if left is an array or pointer then size */
1835 isarray = left->isaddr;
1836 // there is no need to multiply with 1
1837 if (getSize(ltype->next)!=1) {
1838 size = operandFromLit (getSize (ltype->next));
1839 right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
1841 resType = copyLinkChain (ltype);
1844 { /* make them the same size */
1845 resType = usualBinaryConversions (&left, &right);
1848 /* if they are both literals then we know */
1849 if (IS_LITERAL (letype) && IS_LITERAL (retype)
1850 && left->isLiteral && right->isLiteral)
1851 return operandFromValue (valPlus (valFromType (letype),
1852 valFromType (retype)));
1854 ic = newiCode ('+', left, right);
1856 IC_RESULT (ic) = newiTempOperand (resType, 1);
1857 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
1859 /* if left or right is a float then support
1861 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
1866 return IC_RESULT (ic);
1870 /*-----------------------------------------------------------------*/
1871 /* aggrToPtr - changes an aggregate to pointer to an aggregate */
1872 /*-----------------------------------------------------------------*/
1874 aggrToPtr (sym_link * type, bool force)
1880 if (IS_PTR (type) && !force)
1883 etype = getSpec (type);
1887 /* if the output class is generic */
1888 if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER)
1889 DCL_PTR_CONST (ptype) = port->mem.code_ro;
1891 /* if the variable was declared a constant */
1892 /* then the pointer points to a constant */
1893 if (IS_CONSTANT (etype))
1894 DCL_PTR_CONST (ptype) = 1;
1896 /* the variable was volatile then pointer to volatile */
1897 if (IS_VOLATILE (etype))
1898 DCL_PTR_VOLATILE (ptype) = 1;
1902 /*-----------------------------------------------------------------*/
1903 /* geniCodeArray2Ptr - array to pointer */
1904 /*-----------------------------------------------------------------*/
1906 geniCodeArray2Ptr (operand * op)
1908 sym_link *optype = operandType (op);
1909 sym_link *opetype = getSpec (optype);
1911 /* set the pointer depending on the storage class */
1912 if ((DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
1913 DCL_PTR_CONST (optype) = port->mem.code_ro;
1916 /* if the variable was declared a constant */
1917 /* then the pointer points to a constant */
1918 if (IS_CONSTANT (opetype))
1919 DCL_PTR_CONST (optype) = 1;
1921 /* the variable was volatile then pointer to volatile */
1922 if (IS_VOLATILE (opetype))
1923 DCL_PTR_VOLATILE (optype) = 1;
1929 /*-----------------------------------------------------------------*/
1930 /* geniCodeArray - array access */
1931 /*-----------------------------------------------------------------*/
1933 geniCodeArray (operand * left, operand * right,int lvl)
1936 sym_link *ltype = operandType (left);
1940 if (IS_PTR (ltype->next) && left->isaddr)
1942 left = geniCodeRValue (left, FALSE);
1944 return geniCodeDerefPtr (geniCodeAdd (left, right,lvl),lvl);
1947 right = geniCodeMultiply (right,
1948 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
1950 /* we can check for limits here */
1951 if (isOperandLiteral (right) &&
1954 (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
1956 werror (E_ARRAY_BOUND);
1957 right = operandFromLit (0);
1960 ic = newiCode ('+', left, right);
1962 IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
1963 !IS_AGGREGATE (ltype->next) &&
1964 !IS_PTR (ltype->next))
1965 ? ltype : ltype->next), 0);
1967 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
1969 return IC_RESULT (ic);
1972 /*-----------------------------------------------------------------*/
1973 /* geniCodeStruct - generates intermediate code for structres */
1974 /*-----------------------------------------------------------------*/
1976 geniCodeStruct (operand * left, operand * right, bool islval)
1979 sym_link *type = operandType (left);
1980 sym_link *etype = getSpec (type);
1982 symbol *element = getStructElement (SPEC_STRUCT (etype),
1983 right->operand.symOperand);
1985 /* add the offset */
1986 ic = newiCode ('+', left, operandFromLit (element->offset));
1988 IC_RESULT (ic) = newiTempOperand (element->type, 0);
1990 /* preserve the storage & output class of the struct */
1991 /* as well as the volatile attribute */
1992 retype = getSpec (operandType (IC_RESULT (ic)));
1993 SPEC_SCLS (retype) = SPEC_SCLS (etype);
1994 SPEC_OCLS (retype) = SPEC_OCLS (etype);
1995 SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
1997 if (IS_PTR (element->type))
1998 setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2000 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2004 return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2007 /*-----------------------------------------------------------------*/
2008 /* geniCodePostInc - generate int code for Post increment */
2009 /*-----------------------------------------------------------------*/
2011 geniCodePostInc (operand * op)
2015 sym_link *optype = operandType (op);
2017 operand *rv = (IS_ITEMP (op) ?
2018 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2020 sym_link *rvtype = operandType (rv);
2023 /* if this is not an address we have trouble */
2026 werror (E_LVALUE_REQUIRED, "++");
2030 rOp = newiTempOperand (rvtype, 0);
2031 OP_SYMBOL(rOp)->noSpilLoc = 1;
2034 OP_SYMBOL(rv)->noSpilLoc = 1;
2036 geniCodeAssign (rOp, rv, 0);
2038 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2039 if (IS_FLOAT (rvtype))
2040 ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2042 ic = newiCode ('+', rv, operandFromLit (size));
2044 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2047 geniCodeAssign (op, result, 0);
2053 /*-----------------------------------------------------------------*/
2054 /* geniCodePreInc - generate code for preIncrement */
2055 /*-----------------------------------------------------------------*/
2057 geniCodePreInc (operand * op)
2060 sym_link *optype = operandType (op);
2061 operand *rop = (IS_ITEMP (op) ?
2062 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2064 sym_link *roptype = operandType (rop);
2070 werror (E_LVALUE_REQUIRED, "++");
2075 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2076 if (IS_FLOAT (roptype))
2077 ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2079 ic = newiCode ('+', rop, operandFromLit (size));
2080 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2084 return geniCodeAssign (op, result, 0);
2087 /*-----------------------------------------------------------------*/
2088 /* geniCodePostDec - generates code for Post decrement */
2089 /*-----------------------------------------------------------------*/
2091 geniCodePostDec (operand * op)
2095 sym_link *optype = operandType (op);
2097 operand *rv = (IS_ITEMP (op) ?
2098 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2100 sym_link *rvtype = operandType (rv);
2103 /* if this is not an address we have trouble */
2106 werror (E_LVALUE_REQUIRED, "--");
2110 rOp = newiTempOperand (rvtype, 0);
2111 OP_SYMBOL(rOp)->noSpilLoc = 1;
2114 OP_SYMBOL(rv)->noSpilLoc = 1;
2116 geniCodeAssign (rOp, rv, 0);
2118 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2119 if (IS_FLOAT (rvtype))
2120 ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2122 ic = newiCode ('-', rv, operandFromLit (size));
2124 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2127 geniCodeAssign (op, result, 0);
2133 /*-----------------------------------------------------------------*/
2134 /* geniCodePreDec - generate code for pre decrement */
2135 /*-----------------------------------------------------------------*/
2137 geniCodePreDec (operand * op)
2140 sym_link *optype = operandType (op);
2141 operand *rop = (IS_ITEMP (op) ?
2142 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2144 sym_link *roptype = operandType (rop);
2150 werror (E_LVALUE_REQUIRED, "--");
2155 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2156 if (IS_FLOAT (roptype))
2157 ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2159 ic = newiCode ('-', rop, operandFromLit (size));
2160 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2164 return geniCodeAssign (op, result, 0);
2168 /*-----------------------------------------------------------------*/
2169 /* geniCodeBitwise - gen int code for bitWise operators */
2170 /*-----------------------------------------------------------------*/
2172 geniCodeBitwise (operand * left, operand * right,
2173 int oper, sym_link * resType)
2177 left = geniCodeCast (resType, left, TRUE);
2178 right = geniCodeCast (resType, right, TRUE);
2180 ic = newiCode (oper, left, right);
2181 IC_RESULT (ic) = newiTempOperand (resType, 0);
2184 return IC_RESULT (ic);
2187 /*-----------------------------------------------------------------*/
2188 /* geniCodeAddressOf - gens icode for '&' address of operator */
2189 /*-----------------------------------------------------------------*/
2191 geniCodeAddressOf (operand * op)
2195 sym_link *optype = operandType (op);
2196 sym_link *opetype = getSpec (optype);
2198 /* lvalue check already done in decorateType */
2199 /* this must be a lvalue */
2200 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2201 /* werror (E_LVALUE_REQUIRED,"&"); */
2206 p->class = DECLARATOR;
2208 /* set the pointer depending on the storage class */
2209 if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2210 DCL_PTR_CONST (p) = port->mem.code_ro;
2212 /* make sure we preserve the const & volatile */
2213 if (IS_CONSTANT (opetype))
2214 DCL_PTR_CONST (p) = 1;
2216 if (IS_VOLATILE (opetype))
2217 DCL_PTR_VOLATILE (p) = 1;
2219 p->next = copyLinkChain (optype);
2221 /* if already a temp */
2224 setOperandType (op, p);
2229 /* other wise make this of the type coming in */
2230 ic = newiCode (ADDRESS_OF, op, NULL);
2231 IC_RESULT (ic) = newiTempOperand (p, 1);
2232 IC_RESULT (ic)->isaddr = 0;
2234 return IC_RESULT (ic);
2236 /*-----------------------------------------------------------------*/
2237 /* setOClass - sets the output class depending on the pointer type */
2238 /*-----------------------------------------------------------------*/
2240 setOClass (sym_link * ptr, sym_link * spec)
2242 switch (DCL_TYPE (ptr))
2245 SPEC_OCLS (spec) = data;
2249 SPEC_OCLS (spec) = generic;
2253 SPEC_OCLS (spec) = xdata;
2257 SPEC_OCLS (spec) = code;
2261 SPEC_OCLS (spec) = idata;
2265 SPEC_OCLS (spec) = xstack;
2269 SPEC_OCLS (spec) = eeprom;
2278 /*-----------------------------------------------------------------*/
2279 /* geniCodeDerefPtr - dereference pointer with '*' */
2280 /*-----------------------------------------------------------------*/
2282 geniCodeDerefPtr (operand * op,int lvl)
2284 sym_link *rtype, *retype;
2285 sym_link *optype = operandType (op);
2287 /* if this is a pointer then generate the rvalue */
2288 if (IS_PTR (optype))
2290 if (IS_TRUE_SYMOP (op))
2293 op = geniCodeRValue (op, TRUE);
2296 op = geniCodeRValue (op, TRUE);
2299 /* now get rid of the pointer part */
2300 if (isLvaluereq(lvl) && IS_ITEMP (op))
2302 retype = getSpec (rtype = copyLinkChain (optype));
2306 retype = getSpec (rtype = copyLinkChain (optype->next));
2309 /* if this is a pointer then outputclass needs 2b updated */
2310 if (IS_PTR (optype))
2311 setOClass (optype, retype);
2313 op->isGptr = IS_GENPTR (optype);
2315 /* if the pointer was declared as a constant */
2316 /* then we cannot allow assignment to the derefed */
2317 if (IS_PTR_CONST (optype))
2318 SPEC_CONST (retype) = 1;
2320 op->isaddr = (IS_PTR (rtype) ||
2321 IS_STRUCT (rtype) ||
2326 if (!isLvaluereq(lvl))
2327 op = geniCodeRValue (op, TRUE);
2329 setOperandType (op, rtype);
2334 /*-----------------------------------------------------------------*/
2335 /* geniCodeUnaryMinus - does a unary minus of the operand */
2336 /*-----------------------------------------------------------------*/
2338 geniCodeUnaryMinus (operand * op)
2341 sym_link *optype = operandType (op);
2343 if (IS_LITERAL (optype))
2344 return operandFromLit (-floatFromVal (op->operand.valOperand));
2346 ic = newiCode (UNARYMINUS, op, NULL);
2347 IC_RESULT (ic) = newiTempOperand (optype, 0);
2349 return IC_RESULT (ic);
2352 /*-----------------------------------------------------------------*/
2353 /* geniCodeLeftShift - gen i code for left shift */
2354 /*-----------------------------------------------------------------*/
2356 geniCodeLeftShift (operand * left, operand * right)
2360 ic = newiCode (LEFT_OP, left, right);
2361 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2363 return IC_RESULT (ic);
2366 /*-----------------------------------------------------------------*/
2367 /* geniCodeRightShift - gen i code for right shift */
2368 /*-----------------------------------------------------------------*/
2370 geniCodeRightShift (operand * left, operand * right)
2374 ic = newiCode (RIGHT_OP, left, right);
2375 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2377 return IC_RESULT (ic);
2380 #if defined(__BORLANDC__) || defined(_MSC_VER)
2381 #define LONG_LONG __int64
2383 #define LONG_LONG long long
2386 /*-----------------------------------------------------------------*/
2387 /* geniCodeLogic- logic code */
2388 /*-----------------------------------------------------------------*/
2390 geniCodeLogic (operand * left, operand * right, int op)
2394 sym_link *rtype = operandType (right);
2395 sym_link *ltype = operandType (left);
2397 /* left is integral type and right is literal then
2398 check if the literal value is within bounds */
2399 if (IS_INTEGRAL (ltype) && IS_LITERAL (rtype))
2401 int nbits = bitsForType (ltype);
2402 long v = (long) operandLitValue (right);
2404 if (v >= ((LONG_LONG) 1 << nbits) && v > 0)
2405 werror (W_CONST_RANGE, " compare operation ");
2408 ctype = usualBinaryConversions (&left, &right);
2410 ic = newiCode (op, left, right);
2411 IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2413 /* if comparing float
2414 and not a '==' || '!=' || '&&' || '||' (these
2416 if (IS_FLOAT(ctype) &&
2424 return IC_RESULT (ic);
2427 /*-----------------------------------------------------------------*/
2428 /* geniCodeUnary - for a a generic unary operation */
2429 /*-----------------------------------------------------------------*/
2431 geniCodeUnary (operand * op, int oper)
2433 iCode *ic = newiCode (oper, op, NULL);
2435 IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2437 return IC_RESULT (ic);
2440 /*-----------------------------------------------------------------*/
2441 /* geniCodeConditional - geniCode for '?' ':' operation */
2442 /*-----------------------------------------------------------------*/
2444 geniCodeConditional (ast * tree,int lvl)
2447 symbol *falseLabel = newiTempLabel (NULL);
2448 symbol *exitLabel = newiTempLabel (NULL);
2449 operand *cond = ast2iCode (tree->left,lvl+1);
2450 operand *true, *false, *result;
2452 ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
2456 true = ast2iCode (tree->right->left,lvl+1);
2458 /* move the value to a new Operand */
2459 result = newiTempOperand (operandType (true), 0);
2460 geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
2462 /* generate an unconditional goto */
2463 geniCodeGoto (exitLabel);
2465 /* now for the right side */
2466 geniCodeLabel (falseLabel);
2468 false = ast2iCode (tree->right->right,lvl+1);
2469 geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
2471 /* create the exit label */
2472 geniCodeLabel (exitLabel);
2477 /*-----------------------------------------------------------------*/
2478 /* geniCodeAssign - generate code for assignment */
2479 /*-----------------------------------------------------------------*/
2481 geniCodeAssign (operand * left, operand * right, int nosupdate)
2484 sym_link *ltype = operandType (left);
2485 sym_link *rtype = operandType (right);
2487 if (!left->isaddr && !IS_ITEMP (left))
2489 werror (E_LVALUE_REQUIRED, "assignment");
2493 /* left is integral type and right is literal then
2494 check if the literal value is within bounds */
2495 if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
2497 int nbits = bitsForType (ltype);
2498 long v = (long) operandLitValue (right);
2500 if (v >= ((LONG_LONG) 1 << nbits) && v > 0)
2501 werror (W_CONST_RANGE, " = operation");
2504 /* if the left & right type don't exactly match */
2505 /* if pointer set then make sure the check is
2506 done with the type & not the pointer */
2507 /* then cast rights type to left */
2509 /* first check the type for pointer assignement */
2510 if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
2511 compareType (ltype, rtype) < 0)
2513 if (compareType (ltype->next, rtype) < 0)
2514 right = geniCodeCast (ltype->next, right, TRUE);
2516 else if (compareType (ltype, rtype) < 0)
2517 right = geniCodeCast (ltype, right, TRUE);
2519 /* if left is a true symbol & ! volatile
2520 create an assignment to temporary for
2521 the right & then assign this temporary
2522 to the symbol this is SSA . isn't it simple
2523 and folks have published mountains of paper on it */
2524 if (IS_TRUE_SYMOP (left) &&
2525 !isOperandVolatile (left, FALSE) &&
2526 isOperandGlobal (left))
2530 if (IS_TRUE_SYMOP (right))
2531 sym = OP_SYMBOL (right);
2532 ic = newiCode ('=', NULL, right);
2533 IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
2534 SPIL_LOC (right) = sym;
2538 ic = newiCode ('=', NULL, right);
2539 IC_RESULT (ic) = left;
2542 /* if left isgptr flag is set then support
2543 routine will be required */
2547 ic->nosupdate = nosupdate;
2551 /*-----------------------------------------------------------------*/
2552 /* geniCodeSEParms - generate code for side effecting fcalls */
2553 /*-----------------------------------------------------------------*/
2555 geniCodeSEParms (ast * parms,int lvl)
2560 if (parms->type == EX_OP && parms->opval.op == PARAM)
2562 geniCodeSEParms (parms->left,lvl);
2563 geniCodeSEParms (parms->right,lvl);
2567 /* hack don't like this but too lazy to think of
2569 if (IS_ADDRESS_OF_OP (parms))
2570 parms->left->lvalue = 1;
2572 if (IS_CAST_OP (parms) &&
2573 IS_PTR (parms->ftype) &&
2574 IS_ADDRESS_OF_OP (parms->right))
2575 parms->right->left->lvalue = 1;
2577 parms->opval.oprnd =
2578 geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2580 parms->type = EX_OPERAND;
2583 /*-----------------------------------------------------------------*/
2584 /* geniCodeParms - generates parameters */
2585 /*-----------------------------------------------------------------*/
2587 geniCodeParms (ast * parms, int *stack, sym_link * fetype, symbol * func,int lvl)
2595 /* if this is a param node then do the left & right */
2596 if (parms->type == EX_OP && parms->opval.op == PARAM)
2598 geniCodeParms (parms->left, stack, fetype, func,lvl);
2599 geniCodeParms (parms->right, stack, fetype, func,lvl);
2603 /* get the parameter value */
2604 if (parms->type == EX_OPERAND)
2605 pval = parms->opval.oprnd;
2608 /* maybe this else should go away ?? */
2609 /* hack don't like this but too lazy to think of
2611 if (IS_ADDRESS_OF_OP (parms))
2612 parms->left->lvalue = 1;
2614 if (IS_CAST_OP (parms) &&
2615 IS_PTR (parms->ftype) &&
2616 IS_ADDRESS_OF_OP (parms->right))
2617 parms->right->left->lvalue = 1;
2619 pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2622 /* if register parm then make it a send */
2623 if (((parms->argSym && IS_REGPARM (parms->argSym->etype)) ||
2624 IS_REGPARM (parms->etype)) && !func->hasVargs)
2626 ic = newiCode (SEND, pval, NULL);
2631 /* now decide whether to push or assign */
2632 if (!(options.stackAuto || IS_RENT (fetype)))
2636 operand *top = operandFromSymbol (parms->argSym);
2637 geniCodeAssign (top, pval, 1);
2641 sym_link *p = operandType (pval);
2643 ic = newiCode (IPUSH, pval, NULL);
2645 /* update the stack adjustment */
2646 *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2653 /*-----------------------------------------------------------------*/
2654 /* geniCodeCall - generates temp code for calling */
2655 /*-----------------------------------------------------------------*/
2657 geniCodeCall (operand * left, ast * parms,int lvl)
2661 sym_link *type, *etype;
2664 if (!IS_FUNC(OP_SYMBOL(left)->type)) {
2665 werror (E_FUNCTION_EXPECTED);
2669 /* take care of parameters with side-effecting
2670 function calls in them, this is required to take care
2671 of overlaying function parameters */
2672 geniCodeSEParms (parms,lvl);
2674 /* first the parameters */
2675 geniCodeParms (parms, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
2677 /* now call : if symbol then pcall */
2678 if (IS_OP_POINTER (left) || IS_ITEMP(left))
2679 ic = newiCode (PCALL, left, NULL);
2681 ic = newiCode (CALL, left, NULL);
2683 IC_ARGS (ic) = left->operand.symOperand->args;
2684 type = copyLinkChain (operandType (left)->next);
2685 etype = getSpec (type);
2686 SPEC_EXTR (etype) = 0;
2687 IC_RESULT (ic) = result = newiTempOperand (type, 1);
2691 /* stack adjustment after call */
2692 ic->parmBytes = stack;
2697 /*-----------------------------------------------------------------*/
2698 /* geniCodeReceive - generate intermediate code for "receive" */
2699 /*-----------------------------------------------------------------*/
2701 geniCodeReceive (value * args)
2703 /* for all arguments that are passed in registers */
2707 if (IS_REGPARM (args->etype))
2709 operand *opr = operandFromValue (args);
2711 symbol *sym = OP_SYMBOL (opr);
2714 /* we will use it after all optimizations
2715 and before liveRange calculation */
2716 if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
2719 if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
2720 options.stackAuto == 0 &&
2721 /* !TARGET_IS_DS390) */
2722 (!(options.model == MODEL_FLAT24)) )
2727 opl = newiTempOperand (args->type, 0);
2729 sym->reqv->key = sym->key;
2730 OP_SYMBOL (sym->reqv)->key = sym->key;
2731 OP_SYMBOL (sym->reqv)->isreqv = 1;
2732 OP_SYMBOL (sym->reqv)->islocal = 0;
2733 SPIL_LOC (sym->reqv) = sym;
2737 ic = newiCode (RECEIVE, NULL, NULL);
2738 currFunc->recvSize = getSize (sym->etype);
2739 IC_RESULT (ic) = opr;
2747 /*-----------------------------------------------------------------*/
2748 /* geniCodeFunctionBody - create the function body */
2749 /*-----------------------------------------------------------------*/
2751 geniCodeFunctionBody (ast * tree,int lvl)
2758 /* reset the auto generation */
2764 func = ast2iCode (tree->left,lvl+1);
2765 fetype = getSpec (operandType (func));
2767 savelineno = lineno;
2768 lineno = OP_SYMBOL (func)->lineDef;
2769 /* create an entry label */
2770 geniCodeLabel (entryLabel);
2771 lineno = savelineno;
2773 /* create a proc icode */
2774 ic = newiCode (FUNCTION, func, NULL);
2775 /* if the function has parmas then */
2776 /* save the parameters information */
2777 ic->argLabel.args = tree->values.args;
2778 ic->lineno = OP_SYMBOL (func)->lineDef;
2782 /* for all parameters that are passed
2783 on registers add a "receive" */
2784 geniCodeReceive (tree->values.args);
2786 /* generate code for the body */
2787 ast2iCode (tree->right,lvl+1);
2789 /* create a label for return */
2790 geniCodeLabel (returnLabel);
2792 /* now generate the end proc */
2793 ic = newiCode (ENDFUNCTION, func, NULL);
2798 /*-----------------------------------------------------------------*/
2799 /* geniCodeReturn - gen icode for 'return' statement */
2800 /*-----------------------------------------------------------------*/
2802 geniCodeReturn (operand * op)
2806 /* if the operand is present force an rvalue */
2808 op = geniCodeRValue (op, FALSE);
2810 ic = newiCode (RETURN, op, NULL);
2814 /*-----------------------------------------------------------------*/
2815 /* geniCodeIfx - generates code for extended if statement */
2816 /*-----------------------------------------------------------------*/
2818 geniCodeIfx (ast * tree,int lvl)
2821 operand *condition = ast2iCode (tree->left,lvl+1);
2824 /* if condition is null then exit */
2828 condition = geniCodeRValue (condition, FALSE);
2830 cetype = getSpec (operandType (condition));
2831 /* if the condition is a literal */
2832 if (IS_LITERAL (cetype))
2834 if (floatFromVal (condition->operand.valOperand))
2836 if (tree->trueLabel)
2837 geniCodeGoto (tree->trueLabel);
2843 if (tree->falseLabel)
2844 geniCodeGoto (tree->falseLabel);
2851 if (tree->trueLabel)
2853 ic = newiCodeCondition (condition,
2858 if (tree->falseLabel)
2859 geniCodeGoto (tree->falseLabel);
2863 ic = newiCodeCondition (condition,
2870 ast2iCode (tree->right,lvl+1);
2873 /*-----------------------------------------------------------------*/
2874 /* geniCodeJumpTable - tries to create a jump table for switch */
2875 /*-----------------------------------------------------------------*/
2877 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
2879 int min = 0, max = 0, t, cnt = 0;
2886 if (!tree || !caseVals)
2889 /* the criteria for creating a jump table is */
2890 /* all integer numbers between the maximum & minimum must */
2891 /* be present , the maximum value should not exceed 255 */
2892 min = max = (int) floatFromVal (vch = caseVals);
2893 sprintf (buffer, "_case_%d_%d",
2894 tree->values.switchVals.swNum,
2896 addSet (&labels, newiTempLabel (buffer));
2898 /* if there is only one case value then no need */
2899 if (!(vch = vch->next))
2904 if (((t = (int) floatFromVal (vch)) - max) != 1)
2906 sprintf (buffer, "_case_%d_%d",
2907 tree->values.switchVals.swNum,
2909 addSet (&labels, newiTempLabel (buffer));
2915 /* if the number of case statements <= 2 then */
2916 /* it is not economical to create the jump table */
2917 /* since two compares are needed for boundary conditions */
2918 if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
2921 if (tree->values.switchVals.swDefault)
2922 sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
2924 sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
2926 falseLabel = newiTempLabel (buffer);
2928 /* so we can create a jumptable */
2929 /* first we rule out the boundary conditions */
2930 /* if only optimization says so */
2931 if (!optimize.noJTabBoundary)
2933 sym_link *cetype = getSpec (operandType (cond));
2934 /* no need to check the lower bound if
2935 the condition is unsigned & minimum value is zero */
2936 if (!(min == 0 && SPEC_USIGN (cetype)))
2938 boundary = geniCodeLogic (cond, operandFromLit (min), '<');
2939 ic = newiCodeCondition (boundary, falseLabel, NULL);
2943 /* now for upper bounds */
2944 boundary = geniCodeLogic (cond, operandFromLit (max), '>');
2945 ic = newiCodeCondition (boundary, falseLabel, NULL);
2949 /* if the min is not zero then we no make it zero */
2952 cond = geniCodeSubtract (cond, operandFromLit (min));
2953 setOperandType (cond, UCHARTYPE);
2956 /* now create the jumptable */
2957 ic = newiCode (JUMPTABLE, NULL, NULL);
2958 IC_JTCOND (ic) = cond;
2959 IC_JTLABELS (ic) = labels;
2964 /*-----------------------------------------------------------------*/
2965 /* geniCodeSwitch - changes a switch to a if statement */
2966 /*-----------------------------------------------------------------*/
2968 geniCodeSwitch (ast * tree,int lvl)
2971 operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
2972 value *caseVals = tree->values.switchVals.swVals;
2973 symbol *trueLabel, *falseLabel;
2975 /* if we can make this a jump table */
2976 if (geniCodeJumpTable (cond, caseVals, tree))
2977 goto jumpTable; /* no need for the comparison */
2979 /* for the cases defined do */
2983 operand *compare = geniCodeLogic (cond,
2984 operandFromValue (caseVals),
2987 sprintf (buffer, "_case_%d_%d",
2988 tree->values.switchVals.swNum,
2989 (int) floatFromVal (caseVals));
2990 trueLabel = newiTempLabel (buffer);
2992 ic = newiCodeCondition (compare, trueLabel, NULL);
2994 caseVals = caseVals->next;
2999 /* if default is present then goto break else break */
3000 if (tree->values.switchVals.swDefault)
3001 sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3003 sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3005 falseLabel = newiTempLabel (buffer);
3006 geniCodeGoto (falseLabel);
3009 ast2iCode (tree->right,lvl+1);
3012 /*-----------------------------------------------------------------*/
3013 /* geniCodeInline - intermediate code for inline assembler */
3014 /*-----------------------------------------------------------------*/
3016 geniCodeInline (ast * tree)
3020 ic = newiCode (INLINEASM, NULL, NULL);
3021 IC_INLINE (ic) = tree->values.inlineasm;
3025 /*-----------------------------------------------------------------*/
3026 /* geniCodeArrayInit - intermediate code for array initializer */
3027 /*-----------------------------------------------------------------*/
3029 geniCodeArrayInit (ast * tree, operand *array)
3033 ic = newiCode (ARRAYINIT, array, NULL);
3034 IC_ARRAYILIST (ic) = tree->values.constlist;
3038 /*-----------------------------------------------------------------*/
3039 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
3040 /* particular case. Ie : assigning or dereferencing array or ptr */
3041 /*-----------------------------------------------------------------*/
3042 set * lvaluereqSet = NULL;
3043 typedef struct lvalItem
3050 /*-----------------------------------------------------------------*/
3051 /* addLvaluereq - add a flag for lvalreq for current ast level */
3052 /*-----------------------------------------------------------------*/
3053 void addLvaluereq(int lvl)
3055 lvalItem * lpItem = (lvalItem *)Safe_calloc (1, sizeof (lvalItem));
3058 addSetHead(&lvaluereqSet,lpItem);
3061 /*-----------------------------------------------------------------*/
3062 /* delLvaluereq - del a flag for lvalreq for current ast level */
3063 /*-----------------------------------------------------------------*/
3067 lpItem = getSet(&lvaluereqSet);
3068 if(lpItem) free(lpItem);
3070 /*-----------------------------------------------------------------*/
3071 /* clearLvaluereq - clear lvalreq flag */
3072 /*-----------------------------------------------------------------*/
3073 void clearLvaluereq()
3076 lpItem = peekSet(lvaluereqSet);
3077 if(lpItem) lpItem->req = 0;
3079 /*-----------------------------------------------------------------*/
3080 /* getLvaluereq - get the last lvalreq level */
3081 /*-----------------------------------------------------------------*/
3082 int getLvaluereqLvl()
3085 lpItem = peekSet(lvaluereqSet);
3086 if(lpItem) return lpItem->lvl;
3089 /*-----------------------------------------------------------------*/
3090 /* isLvaluereq - is lvalreq valid for this level ? */
3091 /*-----------------------------------------------------------------*/
3092 int isLvaluereq(int lvl)
3095 lpItem = peekSet(lvaluereqSet);
3096 if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3100 /*-----------------------------------------------------------------*/
3101 /* ast2iCode - creates an icodeList from an ast */
3102 /*-----------------------------------------------------------------*/
3104 ast2iCode (ast * tree,int lvl)
3106 operand *left = NULL;
3107 operand *right = NULL;
3110 /* set the global variables for filename & line number */
3112 filename = tree->filename;
3114 lineno = tree->lineno;
3116 block = tree->block;
3118 scopeLevel = tree->level;
3120 if (tree->type == EX_VALUE)
3121 return operandFromValue (tree->opval.val);
3123 if (tree->type == EX_LINK)
3124 return operandFromLink (tree->opval.lnk);
3126 /* if we find a nullop */
3127 if (tree->type == EX_OP &&
3128 (tree->opval.op == NULLOP ||
3129 tree->opval.op == BLOCK))
3131 ast2iCode (tree->left,lvl+1);
3132 ast2iCode (tree->right,lvl+1);
3136 /* special cases for not evaluating */
3137 if (tree->opval.op != ':' &&
3138 tree->opval.op != '?' &&
3139 tree->opval.op != CALL &&
3140 tree->opval.op != IFX &&
3141 tree->opval.op != LABEL &&
3142 tree->opval.op != GOTO &&
3143 tree->opval.op != SWITCH &&
3144 tree->opval.op != FUNCTION &&
3145 tree->opval.op != INLINEASM)
3148 if (IS_ASSIGN_OP (tree->opval.op) ||
3149 IS_DEREF_OP (tree) ||
3150 (tree->opval.op == '&' && !tree->right) ||
3151 tree->opval.op == PTR_OP)
3154 if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3155 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3158 left = operandFromAst (tree->left,lvl);
3160 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3161 left = geniCodeRValue (left, TRUE);
3165 left = operandFromAst (tree->left,lvl);
3167 if (tree->opval.op == INC_OP ||
3168 tree->opval.op == DEC_OP)
3171 right = operandFromAst (tree->right,lvl);
3176 right = operandFromAst (tree->right,lvl);
3180 /* now depending on the type of operand */
3181 /* this will be a biggy */
3182 switch (tree->opval.op)
3185 case '[': /* array operation */
3187 sym_link *ltype = operandType (left);
3188 left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3189 right = geniCodeRValue (right, TRUE);
3192 return geniCodeArray (left, right,lvl);
3194 case '.': /* structure dereference */
3195 if (IS_PTR (operandType (left)))
3196 left = geniCodeRValue (left, TRUE);
3198 left = geniCodeRValue (left, FALSE);
3200 return geniCodeStruct (left, right, tree->lvalue);
3202 case PTR_OP: /* structure pointer dereference */
3205 pType = operandType (left);
3206 left = geniCodeRValue (left, TRUE);
3208 setOClass (pType, getSpec (operandType (left)));
3211 return geniCodeStruct (left, right, tree->lvalue);
3213 case INC_OP: /* increment operator */
3215 return geniCodePostInc (left);
3217 return geniCodePreInc (right);
3219 case DEC_OP: /* decrement operator */
3221 return geniCodePostDec (left);
3223 return geniCodePreDec (right);
3225 case '&': /* bitwise and or address of operator */
3227 { /* this is a bitwise operator */
3228 left = geniCodeRValue (left, FALSE);
3229 right = geniCodeRValue (right, FALSE);
3230 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3233 return geniCodeAddressOf (left);
3235 case '|': /* bitwise or & xor */
3237 return geniCodeBitwise (geniCodeRValue (left, FALSE),
3238 geniCodeRValue (right, FALSE),
3243 return geniCodeDivision (geniCodeRValue (left, FALSE),
3244 geniCodeRValue (right, FALSE));
3247 return geniCodeModulus (geniCodeRValue (left, FALSE),
3248 geniCodeRValue (right, FALSE));
3251 return geniCodeMultiply (geniCodeRValue (left, FALSE),
3252 geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3254 return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3258 return geniCodeSubtract (geniCodeRValue (left, FALSE),
3259 geniCodeRValue (right, FALSE));
3261 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3265 return geniCodeAdd (geniCodeRValue (left, FALSE),
3266 geniCodeRValue (right, FALSE),lvl);
3268 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
3271 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3272 geniCodeRValue (right, FALSE));
3275 return geniCodeRightShift (geniCodeRValue (left, FALSE),
3276 geniCodeRValue (right, FALSE));
3278 return geniCodeCast (operandType (left),
3279 geniCodeRValue (right, FALSE), FALSE);
3285 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3289 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3290 setOperandType (op, UCHARTYPE);
3301 return geniCodeLogic (geniCodeRValue (left, FALSE),
3302 geniCodeRValue (right, FALSE),
3305 return geniCodeConditional (tree,lvl);
3308 return operandFromLit (getSize (tree->right->ftype));
3312 sym_link *rtype = operandType (right);
3313 sym_link *ltype = operandType (left);
3314 if (IS_PTR (rtype) && IS_ITEMP (right)
3315 && right->isaddr && compareType (rtype->next, ltype) == 1)
3316 right = geniCodeRValue (right, TRUE);
3318 right = geniCodeRValue (right, FALSE);
3320 geniCodeAssign (left, right, 0);
3325 geniCodeAssign (left,
3326 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3328 geniCodeRValue (right, FALSE),FALSE), 0);
3332 geniCodeAssign (left,
3333 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3335 geniCodeRValue (right, FALSE)), 0);
3338 geniCodeAssign (left,
3339 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3341 geniCodeRValue (right, FALSE)), 0);
3344 sym_link *rtype = operandType (right);
3345 sym_link *ltype = operandType (left);
3346 if (IS_PTR (rtype) && IS_ITEMP (right)
3347 && right->isaddr && compareType (rtype->next, ltype) == 1)
3348 right = geniCodeRValue (right, TRUE);
3350 right = geniCodeRValue (right, FALSE);
3353 return geniCodeAssign (left,
3354 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3360 sym_link *rtype = operandType (right);
3361 sym_link *ltype = operandType (left);
3362 if (IS_PTR (rtype) && IS_ITEMP (right)
3363 && right->isaddr && compareType (rtype->next, ltype) == 1)
3365 right = geniCodeRValue (right, TRUE);
3369 right = geniCodeRValue (right, FALSE);
3372 geniCodeAssign (left,
3373 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3379 geniCodeAssign (left,
3380 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3382 geniCodeRValue (right, FALSE)), 0);
3385 geniCodeAssign (left,
3386 geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3388 geniCodeRValue (right, FALSE)), 0);
3391 geniCodeAssign (left,
3392 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3394 geniCodeRValue (right, FALSE),
3396 operandType (left)), 0);
3399 geniCodeAssign (left,
3400 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3402 geniCodeRValue (right, FALSE),
3404 operandType (left)), 0);
3407 geniCodeAssign (left,
3408 geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3410 geniCodeRValue (right, FALSE),
3412 operandType (left)), 0);
3414 return geniCodeRValue (right, FALSE);
3417 return geniCodeCall (ast2iCode (tree->left,lvl+1),
3420 geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3421 return ast2iCode (tree->right,lvl+1);
3424 geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3425 return ast2iCode (tree->right,lvl+1);
3428 geniCodeFunctionBody (tree,lvl);
3432 geniCodeReturn (right);
3436 geniCodeIfx (tree,lvl);
3440 geniCodeSwitch (tree,lvl);
3444 geniCodeInline (tree);
3448 geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
3455 /*-----------------------------------------------------------------*/
3456 /* reverseICChain - gets from the list and creates a linkedlist */
3457 /*-----------------------------------------------------------------*/
3464 while ((loop = getSet (&iCodeChain)))
3476 /*-----------------------------------------------------------------*/
3477 /* iCodeFromAst - given an ast will convert it to iCode */
3478 /*-----------------------------------------------------------------*/
3480 iCodeFromAst (ast * tree)
3482 returnLabel = newiTempLabel ("_return");
3483 entryLabel = newiTempLabel ("_entry");
3485 return reverseiCChain ();