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 if (IS_VOID(OP_SYMBOL(condition)->type)) {
478 werror(E_VOID_VALUE_USED);
481 ic = newiCode (IFX, NULL, NULL);
482 IC_COND (ic) = condition;
483 IC_TRUE (ic) = trueLabel;
484 IC_FALSE (ic) = falseLabel;
488 /*-----------------------------------------------------------------*/
489 /* newiCodeLabelGoto - unconditional goto statement| label stmnt */
490 /*-----------------------------------------------------------------*/
492 newiCodeLabelGoto (int op, symbol * label)
496 ic = newiCode (op, NULL, NULL);
498 ic->argLabel.label = label;
500 IC_RIGHT (ic) = NULL;
501 IC_RESULT (ic) = NULL;
505 /*-----------------------------------------------------------------*/
506 /* newiTemp - allocate & return a newItemp Variable */
507 /*-----------------------------------------------------------------*/
514 sprintf (buffer, "%s", s);
516 sprintf (buffer, "iTemp%d", iTempNum++);
517 itmp = newSymbol (buffer, 1);
518 strcpy (itmp->rname, itmp->name);
524 /*-----------------------------------------------------------------*/
525 /* newiTempLabel - creates a temp variable label */
526 /*-----------------------------------------------------------------*/
528 newiTempLabel (char *s)
532 /* check if this alredy exists */
533 if (s && (itmplbl = findSym (LabelTab, NULL, s)))
537 itmplbl = newSymbol (s, 1);
540 sprintf (buffer, "iTempLbl%d", iTempLblNum++);
541 itmplbl = newSymbol (buffer, 1);
546 itmplbl->key = labelKey++;
547 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
551 /*-----------------------------------------------------------------*/
552 /* newiTempPreheaderLabel - creates a new preheader label */
553 /*-----------------------------------------------------------------*/
555 newiTempPreheaderLabel ()
559 sprintf (buffer, "preHeaderLbl%d", iTempLblNum++);
560 itmplbl = newSymbol (buffer, 1);
564 itmplbl->key = labelKey++;
565 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
570 /*-----------------------------------------------------------------*/
571 /* initiCode - initialises some iCode related stuff */
572 /*-----------------------------------------------------------------*/
579 /*-----------------------------------------------------------------*/
580 /* copyiCode - make a copy of the iCode given */
581 /*-----------------------------------------------------------------*/
583 copyiCode (iCode * ic)
585 iCode *nic = newiCode (ic->op, NULL, NULL);
587 nic->lineno = ic->lineno;
588 nic->filename = ic->filename;
589 nic->block = ic->block;
590 nic->level = ic->level;
591 nic->parmBytes = ic->parmBytes;
593 /* deal with the special cases first */
597 IC_COND (nic) = operandFromOperand (IC_COND (ic));
598 IC_TRUE (nic) = IC_TRUE (ic);
599 IC_FALSE (nic) = IC_FALSE (ic);
603 IC_JTCOND (nic) = operandFromOperand (IC_JTCOND (ic));
604 IC_JTLABELS (nic) = IC_JTLABELS (ic);
609 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
610 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
611 IC_ARGS (nic) = IC_ARGS (ic);
615 IC_INLINE (nic) = IC_INLINE (ic);
619 IC_ARRAYILIST(nic) = IC_ARRAYILIST(ic);
623 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
624 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
625 IC_RIGHT (nic) = operandFromOperand (IC_RIGHT (ic));
631 /*-----------------------------------------------------------------*/
632 /* getTableEntry - gets the table entry for the given operator */
633 /*-----------------------------------------------------------------*/
635 getTableEntry (int oper)
639 for (i = 0; i < (sizeof (codeTable) / sizeof (iCodeTable)); i++)
640 if (oper == codeTable[i].icode)
641 return &codeTable[i];
646 /*-----------------------------------------------------------------*/
647 /* newiTempOperand - new intermediate temp operand */
648 /*-----------------------------------------------------------------*/
650 newiTempOperand (sym_link * type, char throwType)
653 operand *op = newOperand ();
657 itmp = newiTemp (NULL);
659 etype = getSpec (type);
661 if (IS_LITERAL (etype))
664 /* copy the type information */
666 itmp->etype = getSpec (itmp->type = (throwType ? type :
667 copyLinkChain (type)));
668 if (IS_LITERAL (itmp->etype))
670 SPEC_SCLS (itmp->etype) = S_REGISTER;
671 SPEC_OCLS (itmp->etype) = reg;
674 op->operand.symOperand = itmp;
675 op->key = itmp->key = ++operandKey;
679 /*-----------------------------------------------------------------*/
680 /* operandType - returns the type chain for an operand */
681 /*-----------------------------------------------------------------*/
683 operandType (operand * op)
685 /* depending on type of operand */
690 return op->operand.valOperand->type;
693 return op->operand.symOperand->type;
696 return op->operand.typeOperand;
698 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
699 " operand type not known ");
700 assert (0); /* should never come here */
701 /* Just to keep the compiler happy */
702 return (sym_link *) 0;
706 /*-----------------------------------------------------------------*/
707 /* isParamterToCall - will return 1 if op is a parameter to args */
708 /*-----------------------------------------------------------------*/
710 isParameterToCall (value * args, operand * op)
717 isSymbolEqual (op->operand.symOperand, tval->sym))
724 /*-----------------------------------------------------------------*/
725 /* isOperandGlobal - return 1 if operand is a global variable */
726 /*-----------------------------------------------------------------*/
728 isOperandGlobal (operand * op)
736 if (op->type == SYMBOL &&
737 (op->operand.symOperand->level == 0 ||
738 IS_STATIC (op->operand.symOperand->etype) ||
739 IS_EXTERN (op->operand.symOperand->etype))
746 /*-----------------------------------------------------------------*/
747 /* isOperandVolatile - return 1 if the operand is volatile */
748 /*-----------------------------------------------------------------*/
750 isOperandVolatile (operand * op, bool chkTemp)
755 if (IS_ITEMP (op) && !chkTemp)
758 opetype = getSpec (optype = operandType (op));
760 if (IS_PTR (optype) && DCL_PTR_VOLATILE (optype))
763 if (IS_VOLATILE (opetype))
768 /*-----------------------------------------------------------------*/
769 /* isOperandLiteral - returns 1 if an operand contains a literal */
770 /*-----------------------------------------------------------------*/
772 isOperandLiteral (operand * op)
779 opetype = getSpec (operandType (op));
781 if (IS_LITERAL (opetype))
786 /*-----------------------------------------------------------------*/
787 /* isOperandInFarSpace - will return true if operand is in farSpace */
788 /*-----------------------------------------------------------------*/
790 isOperandInFarSpace (operand * op)
800 if (!IS_TRUE_SYMOP (op))
803 etype = SPIL_LOC (op)->etype;
809 etype = getSpec (operandType (op));
811 return (IN_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
814 /*-----------------------------------------------------------------*/
815 /* isOperandOnStack - will return true if operand is on stack */
816 /*-----------------------------------------------------------------*/
818 isOperandOnStack (operand * op)
828 etype = getSpec (operandType (op));
830 return ((IN_STACK (etype)) ? TRUE : FALSE);
833 /*-----------------------------------------------------------------*/
834 /* operandLitValue - literal value of an operand */
835 /*-----------------------------------------------------------------*/
837 operandLitValue (operand * op)
839 assert (isOperandLiteral (op));
841 return floatFromVal (op->operand.valOperand);
844 /*-----------------------------------------------------------------*/
845 /* operandOperation - perforoms operations on operands */
846 /*-----------------------------------------------------------------*/
848 operandOperation (operand * left, operand * right,
849 int op, sym_link * type)
851 sym_link *let , *ret=NULL;
852 operand *retval = (operand *) 0;
854 assert (isOperandLiteral (left));
855 let = getSpec(operandType(left));
857 assert (isOperandLiteral (right));
858 ret = getSpec(operandType(left));
864 retval = operandFromValue (valCastLiteral (type,
865 operandLitValue (left) +
866 operandLitValue (right)));
869 retval = operandFromValue (valCastLiteral (type,
870 operandLitValue (left) -
871 operandLitValue (right)));
874 retval = operandFromValue (valCastLiteral (type,
875 operandLitValue (left) *
876 operandLitValue (right)));
879 if ((unsigned long) operandLitValue (right) == 0)
881 werror (E_DIVIDE_BY_ZERO);
886 retval = operandFromValue (valCastLiteral (type,
887 operandLitValue (left) /
888 operandLitValue (right)));
891 if ((unsigned long) operandLitValue (right) == 0) {
892 werror (E_DIVIDE_BY_ZERO);
896 retval = operandFromLit ((SPEC_USIGN(let) ?
897 (unsigned long) operandLitValue (left) :
898 (long) operandLitValue (left)) %
900 (unsigned long) operandLitValue (right) :
901 (long) operandLitValue (right)));
905 retval = operandFromLit (((SPEC_USIGN(let) ?
906 (unsigned long) operandLitValue (left) :
907 (long) operandLitValue (left)) <<
909 (unsigned long) operandLitValue (right) :
910 (long) operandLitValue (right))));
913 retval = operandFromLit (((SPEC_USIGN(let) ?
914 (unsigned long) operandLitValue (left) :
915 (long) operandLitValue (left)) >>
917 (unsigned long) operandLitValue (right) :
918 (long) 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 (operandLitValue (left) >=
942 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 ((unsigned long) operandLitValue (left) ^
954 (unsigned long) operandLitValue (right));
957 retval = operandFromLit (operandLitValue (left) &&
958 operandLitValue (right));
961 retval = operandFromLit (operandLitValue (left) ||
962 operandLitValue (right));
966 long i = (long) operandLitValue (left);
968 retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
974 long i = (long) operandLitValue (left);
976 retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
982 retval = operandFromLit (-1 * operandLitValue (left));
986 retval = operandFromLit (~((long) operandLitValue (left)));
990 retval = operandFromLit (!operandLitValue (left));
994 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
995 " operandOperation invalid operator ");
1003 /*-----------------------------------------------------------------*/
1004 /* isOperandEqual - compares two operand & return 1 if they r = */
1005 /*-----------------------------------------------------------------*/
1007 isOperandEqual (operand * left, operand * right)
1009 /* if the pointers are equal then they are equal */
1013 /* if either of them null then false */
1014 if (!left || !right)
1017 if (left->type != right->type)
1020 if (IS_SYMOP (left) && IS_SYMOP (right))
1021 return left->key == right->key;
1023 /* if types are the same */
1027 return isSymbolEqual (left->operand.symOperand,
1028 right->operand.symOperand);
1030 return (floatFromVal (left->operand.valOperand) ==
1031 floatFromVal (right->operand.valOperand));
1033 if (compareType (left->operand.typeOperand,
1034 right->operand.typeOperand) == 1)
1041 /*-----------------------------------------------------------------*/
1042 /* isiCodeEqual - comapres two iCodes are returns true if yes */
1043 /*-----------------------------------------------------------------*/
1045 isiCodeEqual (iCode * left, iCode * right)
1047 /* if the same pointer */
1051 /* if either of them null */
1052 if (!left || !right)
1055 /* if operand are the same */
1056 if (left->op == right->op)
1059 /* compare all the elements depending on type */
1060 if (left->op != IFX)
1062 if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
1064 if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
1070 if (!isOperandEqual (IC_COND (left), IC_COND (right)))
1072 if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
1074 if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
1082 /*-----------------------------------------------------------------*/
1083 /* newiTempFromOp - create a temp Operand with same attributes */
1084 /*-----------------------------------------------------------------*/
1086 newiTempFromOp (operand * op)
1096 nop = newiTempOperand (operandType (op), TRUE);
1097 nop->isaddr = op->isaddr;
1098 nop->isvolatile = op->isvolatile;
1099 nop->isGlobal = op->isGlobal;
1100 nop->isLiteral = op->isLiteral;
1101 nop->usesDefs = op->usesDefs;
1102 nop->isParm = op->isParm;
1106 /*-----------------------------------------------------------------*/
1107 /* operand from operand - creates an operand holder for the type */
1108 /*-----------------------------------------------------------------*/
1110 operandFromOperand (operand * op)
1116 nop = newOperand ();
1117 nop->type = op->type;
1118 nop->isaddr = op->isaddr;
1120 nop->isvolatile = op->isvolatile;
1121 nop->isGlobal = op->isGlobal;
1122 nop->isLiteral = op->isLiteral;
1123 nop->usesDefs = op->usesDefs;
1124 nop->isParm = op->isParm;
1129 nop->operand.symOperand = op->operand.symOperand;
1132 nop->operand.valOperand = op->operand.valOperand;
1135 nop->operand.typeOperand = op->operand.typeOperand;
1142 /*-----------------------------------------------------------------*/
1143 /* opFromOpWithDU - makes a copy of the operand and DU chains */
1144 /*-----------------------------------------------------------------*/
1146 opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
1148 operand *nop = operandFromOperand (op);
1150 if (nop->type == SYMBOL)
1152 OP_SYMBOL (nop)->defs = bitVectCopy (defs);
1153 OP_SYMBOL (nop)->uses = bitVectCopy (uses);
1159 /*-----------------------------------------------------------------*/
1160 /* operandFromSymbol - creates an operand from a symbol */
1161 /*-----------------------------------------------------------------*/
1163 operandFromSymbol (symbol * sym)
1168 /* if the symbol's type is a literal */
1169 /* then it is an enumerator type */
1170 if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
1171 return operandFromValue (valFromType (sym->etype));
1174 sym->key = ++operandKey;
1176 /* if this an implicit variable, means struct/union */
1177 /* member so just return it */
1178 if (sym->implicit || IS_FUNC (sym->type))
1182 op->operand.symOperand = sym;
1184 op->isvolatile = isOperandVolatile (op, TRUE);
1185 op->isGlobal = isOperandGlobal (op);
1189 /* under the following conditions create a
1190 register equivalent for a local symbol */
1191 if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
1192 (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
1193 /* (!TARGET_IS_DS390)) && */
1194 (!(options.model == MODEL_FLAT24)) ) &&
1195 options.stackAuto == 0)
1198 if (!IS_AGGREGATE (sym->type) && /* not an aggregate */
1199 !IS_FUNC (sym->type) && /* not a function */
1200 !sym->_isparm && /* not a parameter */
1201 sym->level && /* is a local variable */
1202 !sym->addrtaken && /* whose address has not been taken */
1203 !sym->reqv && /* does not already have a register euivalence */
1204 !IS_VOLATILE (sym->etype) && /* not declared as volatile */
1205 !IS_STATIC (sym->etype) && /* and not declared static */
1206 !sym->islbl && /* not a label */
1207 ok && /* farspace check */
1208 !IS_BITVAR (sym->etype) /* not a bit variable */
1212 /* we will use it after all optimizations
1213 and before liveRange calculation */
1214 sym->reqv = newiTempOperand (sym->type, 0);
1215 sym->reqv->key = sym->key;
1216 OP_SYMBOL (sym->reqv)->key = sym->key;
1217 OP_SYMBOL (sym->reqv)->isreqv = 1;
1218 OP_SYMBOL (sym->reqv)->islocal = 1;
1219 SPIL_LOC (sym->reqv) = sym;
1222 if (!IS_AGGREGATE (sym->type))
1226 op->operand.symOperand = sym;
1229 op->isvolatile = isOperandVolatile (op, TRUE);
1230 op->isGlobal = isOperandGlobal (op);
1231 op->isPtr = IS_PTR (operandType (op));
1232 op->isParm = sym->_isparm;
1237 /* itemp = &[_symbol] */
1239 ic = newiCode (ADDRESS_OF, newOperand (), NULL);
1240 IC_LEFT (ic)->type = SYMBOL;
1241 IC_LEFT (ic)->operand.symOperand = sym;
1242 IC_LEFT (ic)->key = sym->key;
1243 (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
1244 (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
1245 IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
1248 IC_RESULT (ic) = newiTempOperand (sym->type, 0);
1249 if (IS_ARRAY (sym->type))
1251 IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
1252 IC_RESULT (ic)->isaddr = 0;
1255 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
1257 IC_RESULT (ic)->operand.symOperand->args = sym->args;
1261 return IC_RESULT (ic);
1264 /*-----------------------------------------------------------------*/
1265 /* operandFromValue - creates an operand from value */
1266 /*-----------------------------------------------------------------*/
1268 operandFromValue (value * val)
1272 /* if this is a symbol then do the symbol thing */
1274 return operandFromSymbol (val->sym);
1276 /* this is not a symbol */
1279 op->operand.valOperand = val;
1280 op->isLiteral = isOperandLiteral (op);
1284 /*-----------------------------------------------------------------*/
1285 /* operandFromLink - operand from typeChain */
1286 /*-----------------------------------------------------------------*/
1288 operandFromLink (sym_link * type)
1292 /* operand from sym_link */
1298 op->operand.typeOperand = copyLinkChain (type);
1302 /*-----------------------------------------------------------------*/
1303 /* operandFromLit - makes an operand from a literal value */
1304 /*-----------------------------------------------------------------*/
1306 operandFromLit (double i)
1308 return operandFromValue (valueFromLit (i));
1311 /*-----------------------------------------------------------------*/
1312 /* operandFromAst - creates an operand from an ast */
1313 /*-----------------------------------------------------------------*/
1315 operandFromAst (ast * tree,int lvl)
1321 /* depending on type do */
1325 return ast2iCode (tree,lvl+1);
1329 return operandFromValue (tree->opval.val);
1333 return operandFromLink (tree->opval.lnk);
1337 /* Just to keep the comiler happy */
1338 return (operand *) 0;
1341 /*-----------------------------------------------------------------*/
1342 /* setOperandType - sets the operand's type to the given type */
1343 /*-----------------------------------------------------------------*/
1345 setOperandType (operand * op, sym_link * type)
1347 /* depending on the type of operand */
1352 op->operand.valOperand->etype =
1353 getSpec (op->operand.valOperand->type =
1354 copyLinkChain (type));
1358 if (op->operand.symOperand->isitmp)
1359 op->operand.symOperand->etype =
1360 getSpec (op->operand.symOperand->type =
1361 copyLinkChain (type));
1363 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1364 "attempt to modify type of source");
1368 op->operand.typeOperand = copyLinkChain (type);
1373 /*-----------------------------------------------------------------*/
1374 /* Get size in byte of ptr need to access an array */
1375 /*-----------------------------------------------------------------*/
1377 getArraySizePtr (operand * op)
1379 sym_link *ltype = operandType(op);
1383 int size = getSize(ltype);
1384 return(IS_GENPTR(ltype)?(size-1):size);
1389 sym_link *letype = getSpec(ltype);
1390 switch (PTR_TYPE (SPEC_OCLS (letype)))
1402 return (GPTRSIZE-1);
1411 /*-----------------------------------------------------------------*/
1412 /* perform "usual unary conversions" */
1413 /*-----------------------------------------------------------------*/
1415 usualUnaryConversions (operand * op)
1417 if (IS_INTEGRAL (operandType (op)))
1419 if (getSize (operandType (op)) < (unsigned int) INTSIZE)
1422 return geniCodeCast (INTTYPE, op, TRUE);
1428 /*-----------------------------------------------------------------*/
1429 /* perform "usual binary conversions" */
1430 /*-----------------------------------------------------------------*/
1432 usualBinaryConversions (operand ** op1, operand ** op2)
1435 sym_link *rtype = operandType (*op2);
1436 sym_link *ltype = operandType (*op1);
1438 ctype = computeType (ltype, rtype);
1439 *op1 = geniCodeCast (ctype, *op1, TRUE);
1440 *op2 = geniCodeCast (ctype, *op2, TRUE);
1445 /*-----------------------------------------------------------------*/
1446 /* geniCodeValueAtAddress - generate intermeditate code for value */
1448 /*-----------------------------------------------------------------*/
1450 geniCodeRValue (operand * op, bool force)
1453 sym_link *type = operandType (op);
1454 sym_link *etype = getSpec (type);
1456 /* if this is an array & already */
1457 /* an address then return this */
1458 if (IS_AGGREGATE (type) ||
1459 (IS_PTR (type) && !force && !op->isaddr))
1460 return operandFromOperand (op);
1462 /* if this is not an address then must be */
1463 /* rvalue already so return this one */
1467 /* if this is not a temp symbol then */
1468 if (!IS_ITEMP (op) &&
1470 !IN_FARSPACE (SPEC_OCLS (etype)))
1472 op = operandFromOperand (op);
1477 if (IS_SPEC (type) &&
1478 IS_TRUE_SYMOP (op) &&
1479 (!IN_FARSPACE (SPEC_OCLS (etype)) ||
1480 /* TARGET_IS_DS390)) */
1481 (options.model == MODEL_FLAT24) ))
1483 op = operandFromOperand (op);
1488 ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1489 if (IS_PTR (type) && op->isaddr && force)
1492 type = copyLinkChain (type);
1494 IC_RESULT (ic) = newiTempOperand (type, 1);
1495 IC_RESULT (ic)->isaddr = 0;
1497 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1499 /* if the right is a symbol */
1500 if (op->type == SYMBOL)
1501 IC_RESULT (ic)->operand.symOperand->args =
1502 op->operand.symOperand->args;
1505 return IC_RESULT (ic);
1508 /*-----------------------------------------------------------------*/
1509 /* geniCodeCast - changes the value from one type to another */
1510 /*-----------------------------------------------------------------*/
1512 geniCodeCast (sym_link * type, operand * op, bool implicit)
1516 sym_link *opetype = getSpec (optype = operandType (op));
1519 /* one of them has size zero then error */
1520 if (IS_VOID (optype))
1522 werror (E_CAST_ZERO);
1526 /* if the operand is already the desired type then do nothing */
1527 if (compareType (type, optype) == 1)
1530 /* if this is a literal then just change the type & return */
1531 if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1532 return operandFromValue (valCastLiteral (type,
1533 operandLitValue (op)));
1535 /* if casting to some pointer type &&
1536 the destination is not a generic pointer
1537 then give a warning : (only for implicit casts) */
1538 if (IS_PTR (optype) && implicit &&
1539 (DCL_TYPE (optype) != DCL_TYPE (type)) &&
1542 werror (E_INCOMPAT_CAST);
1543 fprintf (stderr, "from type '");
1544 printTypeChain (optype, stderr);
1545 fprintf (stderr, "' to type '");
1546 printTypeChain (type, stderr);
1547 fprintf (stderr, "'\n");
1550 /* if they are the same size create an assignment */
1551 if (getSize (type) == getSize (optype) &&
1552 !IS_BITFIELD (type) &&
1554 !IS_FLOAT (optype) &&
1555 ((IS_SPEC (type) && IS_SPEC (optype)) ||
1556 (!IS_SPEC (type) && !IS_SPEC (optype))))
1559 ic = newiCode ('=', NULL, op);
1560 IC_RESULT (ic) = newiTempOperand (type, 0);
1561 SPIL_LOC (IC_RESULT (ic)) =
1562 (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
1563 IC_RESULT (ic)->isaddr = 0;
1567 ic = newiCode (CAST, operandFromLink (type),
1568 geniCodeRValue (op, FALSE));
1570 IC_RESULT (ic) = newiTempOperand (type, 0);
1573 /* preserve the storage class & output class */
1574 /* of the original variable */
1575 restype = getSpec (operandType (IC_RESULT (ic)));
1576 SPEC_SCLS (restype) = SPEC_SCLS (opetype);
1577 SPEC_OCLS (restype) = SPEC_OCLS (opetype);
1580 return IC_RESULT (ic);
1583 /*-----------------------------------------------------------------*/
1584 /* geniCodeLabel - will create a Label */
1585 /*-----------------------------------------------------------------*/
1587 geniCodeLabel (symbol * label)
1591 ic = newiCodeLabelGoto (LABEL, label);
1595 /*-----------------------------------------------------------------*/
1596 /* geniCodeGoto - will create a Goto */
1597 /*-----------------------------------------------------------------*/
1599 geniCodeGoto (symbol * label)
1603 ic = newiCodeLabelGoto (GOTO, label);
1607 /*-----------------------------------------------------------------*/
1608 /* geniCodeMultiply - gen intermediate code for multiplication */
1609 /*-----------------------------------------------------------------*/
1611 geniCodeMultiply (operand * left, operand * right,int resultIsInt)
1618 /* if they are both literal then we know the result */
1619 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1620 return operandFromValue (valMult (left->operand.valOperand,
1621 right->operand.valOperand));
1623 if (IS_LITERAL(retype)) {
1624 p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
1627 resType = usualBinaryConversions (&left, &right);
1629 rtype = operandType (right);
1630 retype = getSpec (rtype);
1631 ltype = operandType (left);
1632 letype = getSpec (ltype);
1636 SPEC_NOUN(getSpec(resType))=V_INT;
1639 /* if the right is a literal & power of 2 */
1640 /* then make it a left shift */
1641 /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
1642 efficient in most cases than 2 bytes result = 2 bytes << literal
1643 if port has 1 byte muldiv */
1644 if (p2 && !IS_FLOAT (letype) &&
1645 !((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
1646 (port->support.muldiv == 1)))
1648 if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
1650 /* LEFT_OP need same size for left and result, */
1651 left = geniCodeCast (resType, left, TRUE);
1652 ltype = operandType (left);
1654 ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
1658 ic = newiCode ('*', left, right); /* normal multiplication */
1659 /* if the size left or right > 1 then support routine */
1660 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1664 IC_RESULT (ic) = newiTempOperand (resType, 1);
1667 return IC_RESULT (ic);
1670 /*-----------------------------------------------------------------*/
1671 /* geniCodeDivision - gen intermediate code for division */
1672 /*-----------------------------------------------------------------*/
1674 geniCodeDivision (operand * left, operand * right)
1679 sym_link *rtype = operandType (right);
1680 sym_link *retype = getSpec (rtype);
1681 sym_link *ltype = operandType (left);
1682 sym_link *letype = getSpec (ltype);
1684 resType = usualBinaryConversions (&left, &right);
1686 /* if the right is a literal & power of 2 */
1687 /* then make it a right shift */
1688 if (IS_LITERAL (retype) &&
1689 !IS_FLOAT (letype) &&
1690 (p2 = powof2 ((unsigned long)
1691 floatFromVal (right->operand.valOperand)))) {
1692 ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
1696 ic = newiCode ('/', left, right); /* normal division */
1697 /* if the size left or right > 1 then support routine */
1698 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1701 IC_RESULT (ic) = newiTempOperand (resType, 0);
1704 return IC_RESULT (ic);
1706 /*-----------------------------------------------------------------*/
1707 /* geniCodeModulus - gen intermediate code for modulus */
1708 /*-----------------------------------------------------------------*/
1710 geniCodeModulus (operand * left, operand * right)
1716 /* if they are both literal then we know the result */
1717 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1718 return operandFromValue (valMod (left->operand.valOperand,
1719 right->operand.valOperand));
1721 resType = usualBinaryConversions (&left, &right);
1723 /* now they are the same size */
1724 ic = newiCode ('%', left, right);
1726 /* if the size left or right > 1 then support routine */
1727 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1729 IC_RESULT (ic) = newiTempOperand (resType, 0);
1732 return IC_RESULT (ic);
1735 /*-----------------------------------------------------------------*/
1736 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
1737 /*-----------------------------------------------------------------*/
1739 geniCodePtrPtrSubtract (operand * left, operand * right)
1745 /* if they are both literals then */
1746 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1748 result = operandFromValue (valMinus (left->operand.valOperand,
1749 right->operand.valOperand));
1753 ic = newiCode ('-', left, right);
1755 IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
1759 return geniCodeDivision (result,
1760 operandFromLit (getSize (ltype->next)));
1763 /*-----------------------------------------------------------------*/
1764 /* geniCodeSubtract - generates code for subtraction */
1765 /*-----------------------------------------------------------------*/
1767 geniCodeSubtract (operand * left, operand * right)
1774 /* if they both pointers then */
1775 if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
1776 (IS_PTR (rtype) || IS_ARRAY (rtype)))
1777 return geniCodePtrPtrSubtract (left, right);
1779 /* if they are both literal then we know the result */
1780 if (IS_LITERAL (letype) && IS_LITERAL (retype)
1781 && left->isLiteral && right->isLiteral)
1782 return operandFromValue (valMinus (left->operand.valOperand,
1783 right->operand.valOperand));
1785 /* if left is an array or pointer */
1786 if (IS_PTR (ltype) || IS_ARRAY (ltype))
1788 isarray = left->isaddr;
1789 right = geniCodeMultiply (right,
1790 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
1791 resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
1794 { /* make them the same size */
1795 resType = usualBinaryConversions (&left, &right);
1798 ic = newiCode ('-', left, right);
1800 IC_RESULT (ic) = newiTempOperand (resType, 1);
1801 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
1803 /* if left or right is a float */
1804 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
1808 return IC_RESULT (ic);
1811 /*-----------------------------------------------------------------*/
1812 /* geniCodeAdd - generates iCode for addition */
1813 /*-----------------------------------------------------------------*/
1815 geniCodeAdd (operand * left, operand * right,int lvl)
1823 /* if left is an array then array access */
1824 if (IS_ARRAY (ltype))
1825 return geniCodeArray (left, right,lvl);
1827 /* if the right side is LITERAL zero */
1828 /* return the left side */
1829 if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
1832 /* if left is literal zero return right */
1833 if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
1836 /* if left is an array or pointer then size */
1839 isarray = left->isaddr;
1840 // there is no need to multiply with 1
1841 if (getSize(ltype->next)!=1) {
1842 size = operandFromLit (getSize (ltype->next));
1843 right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
1845 resType = copyLinkChain (ltype);
1848 { /* make them the same size */
1849 resType = usualBinaryConversions (&left, &right);
1852 /* if they are both literals then we know */
1853 if (IS_LITERAL (letype) && IS_LITERAL (retype)
1854 && left->isLiteral && right->isLiteral)
1855 return operandFromValue (valPlus (valFromType (letype),
1856 valFromType (retype)));
1858 ic = newiCode ('+', left, right);
1860 IC_RESULT (ic) = newiTempOperand (resType, 1);
1861 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
1863 /* if left or right is a float then support
1865 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
1870 return IC_RESULT (ic);
1874 /*-----------------------------------------------------------------*/
1875 /* aggrToPtr - changes an aggregate to pointer to an aggregate */
1876 /*-----------------------------------------------------------------*/
1878 aggrToPtr (sym_link * type, bool force)
1884 if (IS_PTR (type) && !force)
1887 etype = getSpec (type);
1891 /* if the output class is generic */
1892 if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER)
1893 DCL_PTR_CONST (ptype) = port->mem.code_ro;
1895 /* if the variable was declared a constant */
1896 /* then the pointer points to a constant */
1897 if (IS_CONSTANT (etype))
1898 DCL_PTR_CONST (ptype) = 1;
1900 /* the variable was volatile then pointer to volatile */
1901 if (IS_VOLATILE (etype))
1902 DCL_PTR_VOLATILE (ptype) = 1;
1906 /*-----------------------------------------------------------------*/
1907 /* geniCodeArray2Ptr - array to pointer */
1908 /*-----------------------------------------------------------------*/
1910 geniCodeArray2Ptr (operand * op)
1912 sym_link *optype = operandType (op);
1913 sym_link *opetype = getSpec (optype);
1915 /* set the pointer depending on the storage class */
1916 if ((DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
1917 DCL_PTR_CONST (optype) = port->mem.code_ro;
1920 /* if the variable was declared a constant */
1921 /* then the pointer points to a constant */
1922 if (IS_CONSTANT (opetype))
1923 DCL_PTR_CONST (optype) = 1;
1925 /* the variable was volatile then pointer to volatile */
1926 if (IS_VOLATILE (opetype))
1927 DCL_PTR_VOLATILE (optype) = 1;
1933 /*-----------------------------------------------------------------*/
1934 /* geniCodeArray - array access */
1935 /*-----------------------------------------------------------------*/
1937 geniCodeArray (operand * left, operand * right,int lvl)
1940 sym_link *ltype = operandType (left);
1944 if (IS_PTR (ltype->next) && left->isaddr)
1946 left = geniCodeRValue (left, FALSE);
1948 return geniCodeDerefPtr (geniCodeAdd (left, right,lvl),lvl);
1951 right = geniCodeMultiply (right,
1952 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
1954 /* we can check for limits here */
1955 if (isOperandLiteral (right) &&
1958 (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
1960 werror (E_ARRAY_BOUND);
1961 right = operandFromLit (0);
1964 ic = newiCode ('+', left, right);
1966 IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
1967 !IS_AGGREGATE (ltype->next) &&
1968 !IS_PTR (ltype->next))
1969 ? ltype : ltype->next), 0);
1971 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
1973 return IC_RESULT (ic);
1976 /*-----------------------------------------------------------------*/
1977 /* geniCodeStruct - generates intermediate code for structres */
1978 /*-----------------------------------------------------------------*/
1980 geniCodeStruct (operand * left, operand * right, bool islval)
1983 sym_link *type = operandType (left);
1984 sym_link *etype = getSpec (type);
1986 symbol *element = getStructElement (SPEC_STRUCT (etype),
1987 right->operand.symOperand);
1989 /* add the offset */
1990 ic = newiCode ('+', left, operandFromLit (element->offset));
1992 IC_RESULT (ic) = newiTempOperand (element->type, 0);
1994 /* preserve the storage & output class of the struct */
1995 /* as well as the volatile attribute */
1996 retype = getSpec (operandType (IC_RESULT (ic)));
1997 SPEC_SCLS (retype) = SPEC_SCLS (etype);
1998 SPEC_OCLS (retype) = SPEC_OCLS (etype);
1999 SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2001 if (IS_PTR (element->type))
2002 setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2004 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2008 return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2011 /*-----------------------------------------------------------------*/
2012 /* geniCodePostInc - generate int code for Post increment */
2013 /*-----------------------------------------------------------------*/
2015 geniCodePostInc (operand * op)
2019 sym_link *optype = operandType (op);
2021 operand *rv = (IS_ITEMP (op) ?
2022 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2024 sym_link *rvtype = operandType (rv);
2027 /* if this is not an address we have trouble */
2030 werror (E_LVALUE_REQUIRED, "++");
2034 rOp = newiTempOperand (rvtype, 0);
2035 OP_SYMBOL(rOp)->noSpilLoc = 1;
2038 OP_SYMBOL(rv)->noSpilLoc = 1;
2040 geniCodeAssign (rOp, rv, 0);
2042 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2043 if (IS_FLOAT (rvtype))
2044 ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2046 ic = newiCode ('+', rv, operandFromLit (size));
2048 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2051 geniCodeAssign (op, result, 0);
2057 /*-----------------------------------------------------------------*/
2058 /* geniCodePreInc - generate code for preIncrement */
2059 /*-----------------------------------------------------------------*/
2061 geniCodePreInc (operand * op)
2064 sym_link *optype = operandType (op);
2065 operand *rop = (IS_ITEMP (op) ?
2066 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2068 sym_link *roptype = operandType (rop);
2074 werror (E_LVALUE_REQUIRED, "++");
2079 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2080 if (IS_FLOAT (roptype))
2081 ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2083 ic = newiCode ('+', rop, operandFromLit (size));
2084 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2088 return geniCodeAssign (op, result, 0);
2091 /*-----------------------------------------------------------------*/
2092 /* geniCodePostDec - generates code for Post decrement */
2093 /*-----------------------------------------------------------------*/
2095 geniCodePostDec (operand * op)
2099 sym_link *optype = operandType (op);
2101 operand *rv = (IS_ITEMP (op) ?
2102 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2104 sym_link *rvtype = operandType (rv);
2107 /* if this is not an address we have trouble */
2110 werror (E_LVALUE_REQUIRED, "--");
2114 rOp = newiTempOperand (rvtype, 0);
2115 OP_SYMBOL(rOp)->noSpilLoc = 1;
2118 OP_SYMBOL(rv)->noSpilLoc = 1;
2120 geniCodeAssign (rOp, rv, 0);
2122 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2123 if (IS_FLOAT (rvtype))
2124 ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2126 ic = newiCode ('-', rv, operandFromLit (size));
2128 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2131 geniCodeAssign (op, result, 0);
2137 /*-----------------------------------------------------------------*/
2138 /* geniCodePreDec - generate code for pre decrement */
2139 /*-----------------------------------------------------------------*/
2141 geniCodePreDec (operand * op)
2144 sym_link *optype = operandType (op);
2145 operand *rop = (IS_ITEMP (op) ?
2146 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2148 sym_link *roptype = operandType (rop);
2154 werror (E_LVALUE_REQUIRED, "--");
2159 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2160 if (IS_FLOAT (roptype))
2161 ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2163 ic = newiCode ('-', rop, operandFromLit (size));
2164 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2168 return geniCodeAssign (op, result, 0);
2172 /*-----------------------------------------------------------------*/
2173 /* geniCodeBitwise - gen int code for bitWise operators */
2174 /*-----------------------------------------------------------------*/
2176 geniCodeBitwise (operand * left, operand * right,
2177 int oper, sym_link * resType)
2181 left = geniCodeCast (resType, left, TRUE);
2182 right = geniCodeCast (resType, right, TRUE);
2184 ic = newiCode (oper, left, right);
2185 IC_RESULT (ic) = newiTempOperand (resType, 0);
2188 return IC_RESULT (ic);
2191 /*-----------------------------------------------------------------*/
2192 /* geniCodeAddressOf - gens icode for '&' address of operator */
2193 /*-----------------------------------------------------------------*/
2195 geniCodeAddressOf (operand * op)
2199 sym_link *optype = operandType (op);
2200 sym_link *opetype = getSpec (optype);
2202 /* lvalue check already done in decorateType */
2203 /* this must be a lvalue */
2204 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2205 /* werror (E_LVALUE_REQUIRED,"&"); */
2210 p->class = DECLARATOR;
2212 /* set the pointer depending on the storage class */
2213 if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2214 DCL_PTR_CONST (p) = port->mem.code_ro;
2216 /* make sure we preserve the const & volatile */
2217 if (IS_CONSTANT (opetype))
2218 DCL_PTR_CONST (p) = 1;
2220 if (IS_VOLATILE (opetype))
2221 DCL_PTR_VOLATILE (p) = 1;
2223 p->next = copyLinkChain (optype);
2225 /* if already a temp */
2228 setOperandType (op, p);
2233 /* other wise make this of the type coming in */
2234 ic = newiCode (ADDRESS_OF, op, NULL);
2235 IC_RESULT (ic) = newiTempOperand (p, 1);
2236 IC_RESULT (ic)->isaddr = 0;
2238 return IC_RESULT (ic);
2240 /*-----------------------------------------------------------------*/
2241 /* setOClass - sets the output class depending on the pointer type */
2242 /*-----------------------------------------------------------------*/
2244 setOClass (sym_link * ptr, sym_link * spec)
2246 switch (DCL_TYPE (ptr))
2249 SPEC_OCLS (spec) = data;
2253 SPEC_OCLS (spec) = generic;
2257 SPEC_OCLS (spec) = xdata;
2261 SPEC_OCLS (spec) = code;
2265 SPEC_OCLS (spec) = idata;
2269 SPEC_OCLS (spec) = xstack;
2273 SPEC_OCLS (spec) = eeprom;
2282 /*-----------------------------------------------------------------*/
2283 /* geniCodeDerefPtr - dereference pointer with '*' */
2284 /*-----------------------------------------------------------------*/
2286 geniCodeDerefPtr (operand * op,int lvl)
2288 sym_link *rtype, *retype;
2289 sym_link *optype = operandType (op);
2291 /* if this is a pointer then generate the rvalue */
2292 if (IS_PTR (optype))
2294 if (IS_TRUE_SYMOP (op))
2297 op = geniCodeRValue (op, TRUE);
2300 op = geniCodeRValue (op, TRUE);
2303 /* now get rid of the pointer part */
2304 if (isLvaluereq(lvl) && IS_ITEMP (op))
2306 retype = getSpec (rtype = copyLinkChain (optype));
2310 retype = getSpec (rtype = copyLinkChain (optype->next));
2313 /* if this is a pointer then outputclass needs 2b updated */
2314 if (IS_PTR (optype))
2315 setOClass (optype, retype);
2317 op->isGptr = IS_GENPTR (optype);
2319 /* if the pointer was declared as a constant */
2320 /* then we cannot allow assignment to the derefed */
2321 if (IS_PTR_CONST (optype))
2322 SPEC_CONST (retype) = 1;
2324 op->isaddr = (IS_PTR (rtype) ||
2325 IS_STRUCT (rtype) ||
2330 if (!isLvaluereq(lvl))
2331 op = geniCodeRValue (op, TRUE);
2333 setOperandType (op, rtype);
2338 /*-----------------------------------------------------------------*/
2339 /* geniCodeUnaryMinus - does a unary minus of the operand */
2340 /*-----------------------------------------------------------------*/
2342 geniCodeUnaryMinus (operand * op)
2345 sym_link *optype = operandType (op);
2347 if (IS_LITERAL (optype))
2348 return operandFromLit (-floatFromVal (op->operand.valOperand));
2350 ic = newiCode (UNARYMINUS, op, NULL);
2351 IC_RESULT (ic) = newiTempOperand (optype, 0);
2353 return IC_RESULT (ic);
2356 /*-----------------------------------------------------------------*/
2357 /* geniCodeLeftShift - gen i code for left shift */
2358 /*-----------------------------------------------------------------*/
2360 geniCodeLeftShift (operand * left, operand * right)
2364 ic = newiCode (LEFT_OP, left, right);
2365 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2367 return IC_RESULT (ic);
2370 /*-----------------------------------------------------------------*/
2371 /* geniCodeRightShift - gen i code for right shift */
2372 /*-----------------------------------------------------------------*/
2374 geniCodeRightShift (operand * left, operand * right)
2378 ic = newiCode (RIGHT_OP, left, right);
2379 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2381 return IC_RESULT (ic);
2384 #if defined(__BORLANDC__) || defined(_MSC_VER)
2385 #define LONG_LONG __int64
2387 #define LONG_LONG long long
2390 /*-----------------------------------------------------------------*/
2391 /* geniCodeLogic- logic code */
2392 /*-----------------------------------------------------------------*/
2394 geniCodeLogic (operand * left, operand * right, int op)
2398 sym_link *rtype = operandType (right);
2399 sym_link *ltype = operandType (left);
2401 /* left is integral type and right is literal then
2402 check if the literal value is within bounds */
2403 if (IS_INTEGRAL (ltype) && IS_LITERAL (rtype))
2405 int nbits = bitsForType (ltype);
2406 long v = (long) operandLitValue (right);
2408 if (v >= ((LONG_LONG) 1 << nbits) && v > 0)
2409 werror (W_CONST_RANGE, " compare operation ");
2412 ctype = usualBinaryConversions (&left, &right);
2414 ic = newiCode (op, left, right);
2415 IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2417 /* if comparing float
2418 and not a '==' || '!=' || '&&' || '||' (these
2420 if (IS_FLOAT(ctype) &&
2428 return IC_RESULT (ic);
2431 /*-----------------------------------------------------------------*/
2432 /* geniCodeUnary - for a a generic unary operation */
2433 /*-----------------------------------------------------------------*/
2435 geniCodeUnary (operand * op, int oper)
2437 iCode *ic = newiCode (oper, op, NULL);
2439 IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2441 return IC_RESULT (ic);
2444 /*-----------------------------------------------------------------*/
2445 /* geniCodeConditional - geniCode for '?' ':' operation */
2446 /*-----------------------------------------------------------------*/
2448 geniCodeConditional (ast * tree,int lvl)
2451 symbol *falseLabel = newiTempLabel (NULL);
2452 symbol *exitLabel = newiTempLabel (NULL);
2453 operand *cond = ast2iCode (tree->left,lvl+1);
2454 operand *true, *false, *result;
2456 ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
2460 true = ast2iCode (tree->right->left,lvl+1);
2462 /* move the value to a new Operand */
2463 result = newiTempOperand (operandType (true), 0);
2464 geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
2466 /* generate an unconditional goto */
2467 geniCodeGoto (exitLabel);
2469 /* now for the right side */
2470 geniCodeLabel (falseLabel);
2472 false = ast2iCode (tree->right->right,lvl+1);
2473 geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
2475 /* create the exit label */
2476 geniCodeLabel (exitLabel);
2481 /*-----------------------------------------------------------------*/
2482 /* geniCodeAssign - generate code for assignment */
2483 /*-----------------------------------------------------------------*/
2485 geniCodeAssign (operand * left, operand * right, int nosupdate)
2488 sym_link *ltype = operandType (left);
2489 sym_link *rtype = operandType (right);
2491 if (!left->isaddr && !IS_ITEMP (left))
2493 werror (E_LVALUE_REQUIRED, "assignment");
2497 /* left is integral type and right is literal then
2498 check if the literal value is within bounds */
2499 if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
2501 int nbits = bitsForType (ltype);
2502 long v = (long) operandLitValue (right);
2504 if (v >= ((LONG_LONG) 1 << nbits) && v > 0)
2505 werror (W_CONST_RANGE, " = operation");
2508 /* if the left & right type don't exactly match */
2509 /* if pointer set then make sure the check is
2510 done with the type & not the pointer */
2511 /* then cast rights type to left */
2513 /* first check the type for pointer assignement */
2514 if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
2515 compareType (ltype, rtype) < 0)
2517 if (compareType (ltype->next, rtype) < 0)
2518 right = geniCodeCast (ltype->next, right, TRUE);
2520 else if (compareType (ltype, rtype) < 0)
2521 right = geniCodeCast (ltype, right, TRUE);
2523 /* if left is a true symbol & ! volatile
2524 create an assignment to temporary for
2525 the right & then assign this temporary
2526 to the symbol this is SSA . isn't it simple
2527 and folks have published mountains of paper on it */
2528 if (IS_TRUE_SYMOP (left) &&
2529 !isOperandVolatile (left, FALSE) &&
2530 isOperandGlobal (left))
2534 if (IS_TRUE_SYMOP (right))
2535 sym = OP_SYMBOL (right);
2536 ic = newiCode ('=', NULL, right);
2537 IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
2538 SPIL_LOC (right) = sym;
2542 ic = newiCode ('=', NULL, right);
2543 IC_RESULT (ic) = left;
2546 /* if left isgptr flag is set then support
2547 routine will be required */
2551 ic->nosupdate = nosupdate;
2555 /*-----------------------------------------------------------------*/
2556 /* geniCodeSEParms - generate code for side effecting fcalls */
2557 /*-----------------------------------------------------------------*/
2559 geniCodeSEParms (ast * parms,int lvl)
2564 if (parms->type == EX_OP && parms->opval.op == PARAM)
2566 geniCodeSEParms (parms->left,lvl);
2567 geniCodeSEParms (parms->right,lvl);
2571 /* hack don't like this but too lazy to think of
2573 if (IS_ADDRESS_OF_OP (parms))
2574 parms->left->lvalue = 1;
2576 if (IS_CAST_OP (parms) &&
2577 IS_PTR (parms->ftype) &&
2578 IS_ADDRESS_OF_OP (parms->right))
2579 parms->right->left->lvalue = 1;
2581 parms->opval.oprnd =
2582 geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2584 parms->type = EX_OPERAND;
2587 /*-----------------------------------------------------------------*/
2588 /* geniCodeParms - generates parameters */
2589 /*-----------------------------------------------------------------*/
2591 geniCodeParms (ast * parms, int *stack, sym_link * fetype, symbol * func,int lvl)
2599 /* if this is a param node then do the left & right */
2600 if (parms->type == EX_OP && parms->opval.op == PARAM)
2602 geniCodeParms (parms->left, stack, fetype, func,lvl);
2603 geniCodeParms (parms->right, stack, fetype, func,lvl);
2607 /* get the parameter value */
2608 if (parms->type == EX_OPERAND)
2609 pval = parms->opval.oprnd;
2612 /* maybe this else should go away ?? */
2613 /* hack don't like this but too lazy to think of
2615 if (IS_ADDRESS_OF_OP (parms))
2616 parms->left->lvalue = 1;
2618 if (IS_CAST_OP (parms) &&
2619 IS_PTR (parms->ftype) &&
2620 IS_ADDRESS_OF_OP (parms->right))
2621 parms->right->left->lvalue = 1;
2623 pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2626 /* if register parm then make it a send */
2627 if (((parms->argSym && IS_REGPARM (parms->argSym->etype)) ||
2628 IS_REGPARM (parms->etype)) && !func->hasVargs)
2630 ic = newiCode (SEND, pval, NULL);
2635 /* now decide whether to push or assign */
2636 if (!(options.stackAuto || IS_RENT (fetype)))
2640 operand *top = operandFromSymbol (parms->argSym);
2641 geniCodeAssign (top, pval, 1);
2645 sym_link *p = operandType (pval);
2647 ic = newiCode (IPUSH, pval, NULL);
2649 /* update the stack adjustment */
2650 *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2657 /*-----------------------------------------------------------------*/
2658 /* geniCodeCall - generates temp code for calling */
2659 /*-----------------------------------------------------------------*/
2661 geniCodeCall (operand * left, ast * parms,int lvl)
2665 sym_link *type, *etype;
2668 if (!IS_FUNC(OP_SYMBOL(left)->type) &&
2669 !IS_CODEPTR(OP_SYMBOL(left)->type)) {
2670 werror (E_FUNCTION_EXPECTED);
2674 /* take care of parameters with side-effecting
2675 function calls in them, this is required to take care
2676 of overlaying function parameters */
2677 geniCodeSEParms (parms,lvl);
2679 /* first the parameters */
2680 geniCodeParms (parms, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
2682 /* now call : if symbol then pcall */
2683 if (IS_OP_POINTER (left) || IS_ITEMP(left))
2684 ic = newiCode (PCALL, left, NULL);
2686 ic = newiCode (CALL, left, NULL);
2688 IC_ARGS (ic) = left->operand.symOperand->args;
2689 type = copyLinkChain (operandType (left)->next);
2690 etype = getSpec (type);
2691 SPEC_EXTR (etype) = 0;
2692 IC_RESULT (ic) = result = newiTempOperand (type, 1);
2696 /* stack adjustment after call */
2697 ic->parmBytes = stack;
2702 /*-----------------------------------------------------------------*/
2703 /* geniCodeReceive - generate intermediate code for "receive" */
2704 /*-----------------------------------------------------------------*/
2706 geniCodeReceive (value * args)
2708 /* for all arguments that are passed in registers */
2712 if (IS_REGPARM (args->etype))
2714 operand *opr = operandFromValue (args);
2716 symbol *sym = OP_SYMBOL (opr);
2719 /* we will use it after all optimizations
2720 and before liveRange calculation */
2721 if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
2724 if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
2725 options.stackAuto == 0 &&
2726 /* !TARGET_IS_DS390) */
2727 (!(options.model == MODEL_FLAT24)) )
2732 opl = newiTempOperand (args->type, 0);
2734 sym->reqv->key = sym->key;
2735 OP_SYMBOL (sym->reqv)->key = sym->key;
2736 OP_SYMBOL (sym->reqv)->isreqv = 1;
2737 OP_SYMBOL (sym->reqv)->islocal = 0;
2738 SPIL_LOC (sym->reqv) = sym;
2742 ic = newiCode (RECEIVE, NULL, NULL);
2743 currFunc->recvSize = getSize (sym->etype);
2744 IC_RESULT (ic) = opr;
2752 /*-----------------------------------------------------------------*/
2753 /* geniCodeFunctionBody - create the function body */
2754 /*-----------------------------------------------------------------*/
2756 geniCodeFunctionBody (ast * tree,int lvl)
2763 /* reset the auto generation */
2769 func = ast2iCode (tree->left,lvl+1);
2770 fetype = getSpec (operandType (func));
2772 savelineno = lineno;
2773 lineno = OP_SYMBOL (func)->lineDef;
2774 /* create an entry label */
2775 geniCodeLabel (entryLabel);
2776 lineno = savelineno;
2778 /* create a proc icode */
2779 ic = newiCode (FUNCTION, func, NULL);
2780 /* if the function has parmas then */
2781 /* save the parameters information */
2782 ic->argLabel.args = tree->values.args;
2783 ic->lineno = OP_SYMBOL (func)->lineDef;
2787 /* for all parameters that are passed
2788 on registers add a "receive" */
2789 geniCodeReceive (tree->values.args);
2791 /* generate code for the body */
2792 ast2iCode (tree->right,lvl+1);
2794 /* create a label for return */
2795 geniCodeLabel (returnLabel);
2797 /* now generate the end proc */
2798 ic = newiCode (ENDFUNCTION, func, NULL);
2803 /*-----------------------------------------------------------------*/
2804 /* geniCodeReturn - gen icode for 'return' statement */
2805 /*-----------------------------------------------------------------*/
2807 geniCodeReturn (operand * op)
2811 /* if the operand is present force an rvalue */
2813 op = geniCodeRValue (op, FALSE);
2815 ic = newiCode (RETURN, op, NULL);
2819 /*-----------------------------------------------------------------*/
2820 /* geniCodeIfx - generates code for extended if statement */
2821 /*-----------------------------------------------------------------*/
2823 geniCodeIfx (ast * tree,int lvl)
2826 operand *condition = ast2iCode (tree->left,lvl+1);
2829 /* if condition is null then exit */
2833 condition = geniCodeRValue (condition, FALSE);
2835 cetype = getSpec (operandType (condition));
2836 /* if the condition is a literal */
2837 if (IS_LITERAL (cetype))
2839 if (floatFromVal (condition->operand.valOperand))
2841 if (tree->trueLabel)
2842 geniCodeGoto (tree->trueLabel);
2848 if (tree->falseLabel)
2849 geniCodeGoto (tree->falseLabel);
2856 if (tree->trueLabel)
2858 ic = newiCodeCondition (condition,
2863 if (tree->falseLabel)
2864 geniCodeGoto (tree->falseLabel);
2868 ic = newiCodeCondition (condition,
2875 ast2iCode (tree->right,lvl+1);
2878 /*-----------------------------------------------------------------*/
2879 /* geniCodeJumpTable - tries to create a jump table for switch */
2880 /*-----------------------------------------------------------------*/
2882 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
2884 int min = 0, max = 0, t, cnt = 0;
2891 if (!tree || !caseVals)
2894 /* the criteria for creating a jump table is */
2895 /* all integer numbers between the maximum & minimum must */
2896 /* be present , the maximum value should not exceed 255 */
2897 min = max = (int) floatFromVal (vch = caseVals);
2898 sprintf (buffer, "_case_%d_%d",
2899 tree->values.switchVals.swNum,
2901 addSet (&labels, newiTempLabel (buffer));
2903 /* if there is only one case value then no need */
2904 if (!(vch = vch->next))
2909 if (((t = (int) floatFromVal (vch)) - max) != 1)
2911 sprintf (buffer, "_case_%d_%d",
2912 tree->values.switchVals.swNum,
2914 addSet (&labels, newiTempLabel (buffer));
2920 /* if the number of case statements <= 2 then */
2921 /* it is not economical to create the jump table */
2922 /* since two compares are needed for boundary conditions */
2923 if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
2926 if (tree->values.switchVals.swDefault)
2927 sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
2929 sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
2931 falseLabel = newiTempLabel (buffer);
2933 /* so we can create a jumptable */
2934 /* first we rule out the boundary conditions */
2935 /* if only optimization says so */
2936 if (!optimize.noJTabBoundary)
2938 sym_link *cetype = getSpec (operandType (cond));
2939 /* no need to check the lower bound if
2940 the condition is unsigned & minimum value is zero */
2941 if (!(min == 0 && SPEC_USIGN (cetype)))
2943 boundary = geniCodeLogic (cond, operandFromLit (min), '<');
2944 ic = newiCodeCondition (boundary, falseLabel, NULL);
2948 /* now for upper bounds */
2949 boundary = geniCodeLogic (cond, operandFromLit (max), '>');
2950 ic = newiCodeCondition (boundary, falseLabel, NULL);
2954 /* if the min is not zero then we no make it zero */
2957 cond = geniCodeSubtract (cond, operandFromLit (min));
2958 setOperandType (cond, UCHARTYPE);
2961 /* now create the jumptable */
2962 ic = newiCode (JUMPTABLE, NULL, NULL);
2963 IC_JTCOND (ic) = cond;
2964 IC_JTLABELS (ic) = labels;
2969 /*-----------------------------------------------------------------*/
2970 /* geniCodeSwitch - changes a switch to a if statement */
2971 /*-----------------------------------------------------------------*/
2973 geniCodeSwitch (ast * tree,int lvl)
2976 operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
2977 value *caseVals = tree->values.switchVals.swVals;
2978 symbol *trueLabel, *falseLabel;
2980 /* if we can make this a jump table */
2981 if (geniCodeJumpTable (cond, caseVals, tree))
2982 goto jumpTable; /* no need for the comparison */
2984 /* for the cases defined do */
2988 operand *compare = geniCodeLogic (cond,
2989 operandFromValue (caseVals),
2992 sprintf (buffer, "_case_%d_%d",
2993 tree->values.switchVals.swNum,
2994 (int) floatFromVal (caseVals));
2995 trueLabel = newiTempLabel (buffer);
2997 ic = newiCodeCondition (compare, trueLabel, NULL);
2999 caseVals = caseVals->next;
3004 /* if default is present then goto break else break */
3005 if (tree->values.switchVals.swDefault)
3006 sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3008 sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3010 falseLabel = newiTempLabel (buffer);
3011 geniCodeGoto (falseLabel);
3014 ast2iCode (tree->right,lvl+1);
3017 /*-----------------------------------------------------------------*/
3018 /* geniCodeInline - intermediate code for inline assembler */
3019 /*-----------------------------------------------------------------*/
3021 geniCodeInline (ast * tree)
3025 ic = newiCode (INLINEASM, NULL, NULL);
3026 IC_INLINE (ic) = tree->values.inlineasm;
3030 /*-----------------------------------------------------------------*/
3031 /* geniCodeArrayInit - intermediate code for array initializer */
3032 /*-----------------------------------------------------------------*/
3034 geniCodeArrayInit (ast * tree, operand *array)
3038 ic = newiCode (ARRAYINIT, array, NULL);
3039 IC_ARRAYILIST (ic) = tree->values.constlist;
3043 /*-----------------------------------------------------------------*/
3044 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
3045 /* particular case. Ie : assigning or dereferencing array or ptr */
3046 /*-----------------------------------------------------------------*/
3047 set * lvaluereqSet = NULL;
3048 typedef struct lvalItem
3055 /*-----------------------------------------------------------------*/
3056 /* addLvaluereq - add a flag for lvalreq for current ast level */
3057 /*-----------------------------------------------------------------*/
3058 void addLvaluereq(int lvl)
3060 lvalItem * lpItem = (lvalItem *)Safe_calloc (1, sizeof (lvalItem));
3063 addSetHead(&lvaluereqSet,lpItem);
3066 /*-----------------------------------------------------------------*/
3067 /* delLvaluereq - del a flag for lvalreq for current ast level */
3068 /*-----------------------------------------------------------------*/
3072 lpItem = getSet(&lvaluereqSet);
3073 if(lpItem) free(lpItem);
3075 /*-----------------------------------------------------------------*/
3076 /* clearLvaluereq - clear lvalreq flag */
3077 /*-----------------------------------------------------------------*/
3078 void clearLvaluereq()
3081 lpItem = peekSet(lvaluereqSet);
3082 if(lpItem) lpItem->req = 0;
3084 /*-----------------------------------------------------------------*/
3085 /* getLvaluereq - get the last lvalreq level */
3086 /*-----------------------------------------------------------------*/
3087 int getLvaluereqLvl()
3090 lpItem = peekSet(lvaluereqSet);
3091 if(lpItem) return lpItem->lvl;
3094 /*-----------------------------------------------------------------*/
3095 /* isLvaluereq - is lvalreq valid for this level ? */
3096 /*-----------------------------------------------------------------*/
3097 int isLvaluereq(int lvl)
3100 lpItem = peekSet(lvaluereqSet);
3101 if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3105 /*-----------------------------------------------------------------*/
3106 /* ast2iCode - creates an icodeList from an ast */
3107 /*-----------------------------------------------------------------*/
3109 ast2iCode (ast * tree,int lvl)
3111 operand *left = NULL;
3112 operand *right = NULL;
3115 /* set the global variables for filename & line number */
3117 filename = tree->filename;
3119 lineno = tree->lineno;
3121 block = tree->block;
3123 scopeLevel = tree->level;
3125 if (tree->type == EX_VALUE)
3126 return operandFromValue (tree->opval.val);
3128 if (tree->type == EX_LINK)
3129 return operandFromLink (tree->opval.lnk);
3131 /* if we find a nullop */
3132 if (tree->type == EX_OP &&
3133 (tree->opval.op == NULLOP ||
3134 tree->opval.op == BLOCK))
3136 ast2iCode (tree->left,lvl+1);
3137 ast2iCode (tree->right,lvl+1);
3141 /* special cases for not evaluating */
3142 if (tree->opval.op != ':' &&
3143 tree->opval.op != '?' &&
3144 tree->opval.op != CALL &&
3145 tree->opval.op != IFX &&
3146 tree->opval.op != LABEL &&
3147 tree->opval.op != GOTO &&
3148 tree->opval.op != SWITCH &&
3149 tree->opval.op != FUNCTION &&
3150 tree->opval.op != INLINEASM)
3153 if (IS_ASSIGN_OP (tree->opval.op) ||
3154 IS_DEREF_OP (tree) ||
3155 (tree->opval.op == '&' && !tree->right) ||
3156 tree->opval.op == PTR_OP)
3159 if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3160 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3163 left = operandFromAst (tree->left,lvl);
3165 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3166 left = geniCodeRValue (left, TRUE);
3170 left = operandFromAst (tree->left,lvl);
3172 if (tree->opval.op == INC_OP ||
3173 tree->opval.op == DEC_OP)
3176 right = operandFromAst (tree->right,lvl);
3181 right = operandFromAst (tree->right,lvl);
3185 /* now depending on the type of operand */
3186 /* this will be a biggy */
3187 switch (tree->opval.op)
3190 case '[': /* array operation */
3192 sym_link *ltype = operandType (left);
3193 left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3194 right = geniCodeRValue (right, TRUE);
3197 return geniCodeArray (left, right,lvl);
3199 case '.': /* structure dereference */
3200 if (IS_PTR (operandType (left)))
3201 left = geniCodeRValue (left, TRUE);
3203 left = geniCodeRValue (left, FALSE);
3205 return geniCodeStruct (left, right, tree->lvalue);
3207 case PTR_OP: /* structure pointer dereference */
3210 pType = operandType (left);
3211 left = geniCodeRValue (left, TRUE);
3213 setOClass (pType, getSpec (operandType (left)));
3216 return geniCodeStruct (left, right, tree->lvalue);
3218 case INC_OP: /* increment operator */
3220 return geniCodePostInc (left);
3222 return geniCodePreInc (right);
3224 case DEC_OP: /* decrement operator */
3226 return geniCodePostDec (left);
3228 return geniCodePreDec (right);
3230 case '&': /* bitwise and or address of operator */
3232 { /* this is a bitwise operator */
3233 left = geniCodeRValue (left, FALSE);
3234 right = geniCodeRValue (right, FALSE);
3235 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3238 return geniCodeAddressOf (left);
3240 case '|': /* bitwise or & xor */
3242 return geniCodeBitwise (geniCodeRValue (left, FALSE),
3243 geniCodeRValue (right, FALSE),
3248 return geniCodeDivision (geniCodeRValue (left, FALSE),
3249 geniCodeRValue (right, FALSE));
3252 return geniCodeModulus (geniCodeRValue (left, FALSE),
3253 geniCodeRValue (right, FALSE));
3256 return geniCodeMultiply (geniCodeRValue (left, FALSE),
3257 geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3259 return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3263 return geniCodeSubtract (geniCodeRValue (left, FALSE),
3264 geniCodeRValue (right, FALSE));
3266 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3270 return geniCodeAdd (geniCodeRValue (left, FALSE),
3271 geniCodeRValue (right, FALSE),lvl);
3273 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
3276 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3277 geniCodeRValue (right, FALSE));
3280 return geniCodeRightShift (geniCodeRValue (left, FALSE),
3281 geniCodeRValue (right, FALSE));
3283 return geniCodeCast (operandType (left),
3284 geniCodeRValue (right, FALSE), FALSE);
3290 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3294 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3295 setOperandType (op, UCHARTYPE);
3306 return geniCodeLogic (geniCodeRValue (left, FALSE),
3307 geniCodeRValue (right, FALSE),
3310 return geniCodeConditional (tree,lvl);
3313 return operandFromLit (getSize (tree->right->ftype));
3317 sym_link *rtype = operandType (right);
3318 sym_link *ltype = operandType (left);
3319 if (IS_PTR (rtype) && IS_ITEMP (right)
3320 && right->isaddr && compareType (rtype->next, ltype) == 1)
3321 right = geniCodeRValue (right, TRUE);
3323 right = geniCodeRValue (right, FALSE);
3325 geniCodeAssign (left, right, 0);
3330 geniCodeAssign (left,
3331 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3333 geniCodeRValue (right, FALSE),FALSE), 0);
3337 geniCodeAssign (left,
3338 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3340 geniCodeRValue (right, FALSE)), 0);
3343 geniCodeAssign (left,
3344 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3346 geniCodeRValue (right, FALSE)), 0);
3349 sym_link *rtype = operandType (right);
3350 sym_link *ltype = operandType (left);
3351 if (IS_PTR (rtype) && IS_ITEMP (right)
3352 && right->isaddr && compareType (rtype->next, ltype) == 1)
3353 right = geniCodeRValue (right, TRUE);
3355 right = geniCodeRValue (right, FALSE);
3358 return geniCodeAssign (left,
3359 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3365 sym_link *rtype = operandType (right);
3366 sym_link *ltype = operandType (left);
3367 if (IS_PTR (rtype) && IS_ITEMP (right)
3368 && right->isaddr && compareType (rtype->next, ltype) == 1)
3370 right = geniCodeRValue (right, TRUE);
3374 right = geniCodeRValue (right, FALSE);
3377 geniCodeAssign (left,
3378 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3384 geniCodeAssign (left,
3385 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3387 geniCodeRValue (right, FALSE)), 0);
3390 geniCodeAssign (left,
3391 geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3393 geniCodeRValue (right, FALSE)), 0);
3396 geniCodeAssign (left,
3397 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3399 geniCodeRValue (right, FALSE),
3401 operandType (left)), 0);
3404 geniCodeAssign (left,
3405 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3407 geniCodeRValue (right, FALSE),
3409 operandType (left)), 0);
3412 geniCodeAssign (left,
3413 geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3415 geniCodeRValue (right, FALSE),
3417 operandType (left)), 0);
3419 return geniCodeRValue (right, FALSE);
3422 return geniCodeCall (ast2iCode (tree->left,lvl+1),
3425 geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3426 return ast2iCode (tree->right,lvl+1);
3429 geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3430 return ast2iCode (tree->right,lvl+1);
3433 geniCodeFunctionBody (tree,lvl);
3437 geniCodeReturn (right);
3441 geniCodeIfx (tree,lvl);
3445 geniCodeSwitch (tree,lvl);
3449 geniCodeInline (tree);
3453 geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
3460 /*-----------------------------------------------------------------*/
3461 /* reverseICChain - gets from the list and creates a linkedlist */
3462 /*-----------------------------------------------------------------*/
3469 while ((loop = getSet (&iCodeChain)))
3481 /*-----------------------------------------------------------------*/
3482 /* iCodeFromAst - given an ast will convert it to iCode */
3483 /*-----------------------------------------------------------------*/
3485 iCodeFromAst (ast * tree)
3487 returnLabel = newiTempLabel ("_return");
3488 entryLabel = newiTempLabel ("_entry");
3490 return reverseiCChain ();