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;
42 symbol *returnLabel; /* function return label */
43 symbol *entryLabel; /* function entry label */
44 /*-----------------------------------------------------------------*/
45 /* forward definition of some functions */
46 operand *geniCodeDivision (operand *, operand *);
47 operand *geniCodeAssign (operand *, operand *, int);
48 operand *geniCodeArray (operand *, operand *);
49 operand *geniCodeArray2Ptr (operand *);
50 operand *geniCodeRValue (operand *, bool);
51 operand *geniCodeDerefPtr (operand *);
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}
116 /*-----------------------------------------------------------------*/
117 /* operandName - returns the name of the operand */
118 /*-----------------------------------------------------------------*/
120 printOperand (operand * op, FILE * file)
137 opetype = getSpec (operandType (op));
138 if (SPEC_NOUN (opetype) == V_FLOAT)
139 fprintf (file, "%g {", SPEC_CVAL (opetype).v_float);
141 fprintf (file, "0x%x {", (int) floatFromVal (op->operand.valOperand));
142 printTypeChain (operandType (op), file);
149 fprintf (file, "%s [k%d lr%d:%d so:%d]{ ia%d re%d rm%d}", /*{ar%d rm%d ru%d p%d a%d u%d i%d au%d k%d ks%d}" , */
150 (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name),
152 OP_LIVEFROM (op), OP_LIVETO (op),
153 OP_SYMBOL (op)->stack,
154 op->isaddr, OP_SYMBOL (op)->isreqv, OP_SYMBOL (op)->remat
158 printTypeChain (operandType (op), file);
159 if (SPIL_LOC (op) && IS_ITEMP (op))
160 fprintf (file, "}{ sir@ %s", SPIL_LOC (op)->rname);
165 /* if assigned to registers */
166 if (OP_SYMBOL (op)->nRegs)
168 if (OP_SYMBOL (op)->isspilt)
170 if (!OP_SYMBOL (op)->remat)
171 if (OP_SYMBOL (op)->usl.spillLoc)
172 fprintf (file, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
173 OP_SYMBOL (op)->usl.spillLoc->rname :
174 OP_SYMBOL (op)->usl.spillLoc->name));
176 fprintf (file, "[err]");
178 fprintf (file, "[remat]");
184 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
185 fprintf (file, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i]));
190 fprintf (file, "%s", (OP_SYMBOL (op)->rname[0] ?
191 OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name));
192 /* if assigned to registers */
193 if (OP_SYMBOL (op)->nRegs && !OP_SYMBOL (op)->isspilt)
197 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
198 fprintf (file, "%s ", (OP_SYMBOL (op)->regs[i] ?
199 OP_SYMBOL (op)->regs[i]->name :
208 printTypeChain (op->operand.typeOperand, file);
214 fprintf (file, "\n");
219 /*-----------------------------------------------------------------*/
220 /* print functions */
221 /*-----------------------------------------------------------------*/
222 PRINTFUNC (picGetValueAtAddr)
225 printOperand (IC_RESULT (ic), of);
228 printOperand (IC_LEFT (ic), of);
234 PRINTFUNC (picSetValueAtAddr)
238 printOperand (IC_LEFT (ic), of);
239 fprintf (of, "] = ");
240 printOperand (IC_RIGHT (ic), of);
244 PRINTFUNC (picAddrOf)
247 printOperand (IC_RESULT (ic), of);
248 if (IS_ITEMP (IC_LEFT (ic)))
251 fprintf (of, " = &[");
252 printOperand (IC_LEFT (ic), of);
255 if (IS_ITEMP (IC_LEFT (ic)))
256 fprintf (of, " offsetAdd ");
259 printOperand (IC_RIGHT (ic), of);
261 if (IS_ITEMP (IC_LEFT (ic)))
267 PRINTFUNC (picJumpTable)
272 fprintf (of, "%s\t", s);
273 printOperand (IC_JTCOND (ic), of);
275 for (sym = setFirstItem (IC_JTLABELS (ic)); sym;
276 sym = setNextItem (IC_JTLABELS (ic)))
277 fprintf (of, "\t\t\t%s\n", sym->name);
280 PRINTFUNC (picGeneric)
283 printOperand (IC_RESULT (ic), of);
285 printOperand (IC_LEFT (ic), of);
286 fprintf (of, " %s ", s);
287 printOperand (IC_RIGHT (ic), of);
291 PRINTFUNC (picGenericOne)
296 printOperand (IC_RESULT (ic), of);
302 fprintf (of, "%s ", s);
303 printOperand (IC_LEFT (ic), of);
306 if (!IC_RESULT (ic) && !IC_LEFT (ic))
315 printOperand (IC_RESULT (ic), of);
317 printOperand (IC_LEFT (ic), of);
318 printOperand (IC_RIGHT (ic), of);
323 PRINTFUNC (picAssign)
327 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
330 printOperand (IC_RESULT (ic), of);
332 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
335 fprintf (of, " %s ", s);
336 printOperand (IC_RIGHT (ic), of);
343 fprintf (of, " %s($%d) :\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
349 fprintf (of, " goto %s($%d)\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
356 printOperand (IC_COND (ic), of);
359 fprintf (of, " == 0 goto %s($%d)\n", IC_FALSE (ic)->name, IC_FALSE (ic)->key);
362 fprintf (of, " != 0 goto %s($%d)\n", IC_TRUE (ic)->name, IC_TRUE (ic)->key);
364 fprintf (of, "\tzzgoto %s\n", IC_FALSE (ic)->name);
368 PRINTFUNC (picInline)
370 fprintf (of, "%s", IC_INLINE (ic));
373 PRINTFUNC (picReceive)
375 printOperand (IC_RESULT (ic), of);
376 fprintf (of, " = %s ", s);
377 printOperand (IC_LEFT (ic), of);
381 /*-----------------------------------------------------------------*/
382 /* piCode - prints one iCode */
383 /*-----------------------------------------------------------------*/
385 piCode (void *item, FILE * of)
393 icTab = getTableEntry (ic->op);
394 fprintf (stdout, "%s(%d:%d:%d:%d:%d)\t",
395 ic->filename, ic->lineno,
396 ic->seq, ic->key, ic->depth, ic->supportRtn);
397 icTab->iCodePrint (of, ic, icTab->printName);
403 printiCChain(ic,stdout);
405 /*-----------------------------------------------------------------*/
406 /* printiCChain - prints intermediate code for humans */
407 /*-----------------------------------------------------------------*/
409 printiCChain (iCode * icChain, FILE * of)
416 for (loop = icChain; loop; loop = loop->next)
418 if ((icTab = getTableEntry (loop->op)))
420 fprintf (of, "%s(%d:%d:%d:%d:%d)\t",
421 loop->filename, loop->lineno,
422 loop->seq, loop->key, loop->depth, loop->supportRtn);
424 icTab->iCodePrint (of, loop, icTab->printName);
430 /*-----------------------------------------------------------------*/
431 /* newOperand - allocate, init & return a new iCode */
432 /*-----------------------------------------------------------------*/
438 op = Safe_calloc (1, sizeof (operand));
444 /*-----------------------------------------------------------------*/
445 /* newiCode - create and return a new iCode entry initialised */
446 /*-----------------------------------------------------------------*/
448 newiCode (int op, operand * left, operand * right)
452 ic = Safe_calloc (1, sizeof (iCode));
455 ic->filename = filename;
457 ic->level = scopeLevel;
459 ic->key = iCodeKey++;
461 IC_RIGHT (ic) = right;
466 /*-----------------------------------------------------------------*/
467 /* newiCode for conditional statements */
468 /*-----------------------------------------------------------------*/
470 newiCodeCondition (operand * condition,
476 ic = newiCode (IFX, NULL, NULL);
477 IC_COND (ic) = condition;
478 IC_TRUE (ic) = trueLabel;
479 IC_FALSE (ic) = falseLabel;
483 /*-----------------------------------------------------------------*/
484 /* newiCodeLabelGoto - unconditional goto statement| label stmnt */
485 /*-----------------------------------------------------------------*/
487 newiCodeLabelGoto (int op, symbol * label)
491 ic = newiCode (op, NULL, NULL);
493 ic->argLabel.label = label;
495 IC_RIGHT (ic) = NULL;
496 IC_RESULT (ic) = NULL;
500 /*-----------------------------------------------------------------*/
501 /* newiTemp - allocate & return a newItemp Variable */
502 /*-----------------------------------------------------------------*/
509 sprintf (buffer, "%s", s);
511 sprintf (buffer, "iTemp%d", iTempNum++);
512 itmp = newSymbol (buffer, 1);
513 strcpy (itmp->rname, itmp->name);
519 /*-----------------------------------------------------------------*/
520 /* newiTempLabel - creates a temp variable label */
521 /*-----------------------------------------------------------------*/
523 newiTempLabel (char *s)
527 /* check if this alredy exists */
528 if (s && (itmplbl = findSym (LabelTab, NULL, s)))
532 itmplbl = newSymbol (s, 1);
535 sprintf (buffer, "iTempLbl%d", iTempLblNum++);
536 itmplbl = newSymbol (buffer, 1);
541 itmplbl->key = labelKey++;
542 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0);
546 /*-----------------------------------------------------------------*/
547 /* newiTempPreheaderLabel - creates a new preheader label */
548 /*-----------------------------------------------------------------*/
550 newiTempPreheaderLabel ()
554 sprintf (buffer, "preHeaderLbl%d", iTempLblNum++);
555 itmplbl = newSymbol (buffer, 1);
559 itmplbl->key = labelKey++;
560 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0);
565 /*-----------------------------------------------------------------*/
566 /* initiCode - initialises some iCode related stuff */
567 /*-----------------------------------------------------------------*/
574 /*-----------------------------------------------------------------*/
575 /* copyiCode - make a copy of the iCode given */
576 /*-----------------------------------------------------------------*/
578 copyiCode (iCode * ic)
580 iCode *nic = newiCode (ic->op, NULL, NULL);
582 nic->lineno = ic->lineno;
583 nic->filename = ic->filename;
584 nic->block = ic->block;
585 nic->level = ic->level;
586 nic->parmBytes = ic->parmBytes;
588 /* deal with the special cases first */
592 IC_COND (nic) = operandFromOperand (IC_COND (ic));
593 IC_TRUE (nic) = IC_TRUE (ic);
594 IC_FALSE (nic) = IC_FALSE (ic);
598 IC_JTCOND (nic) = operandFromOperand (IC_JTCOND (ic));
599 IC_JTLABELS (nic) = IC_JTLABELS (ic);
604 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
605 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
606 IC_ARGS (nic) = IC_ARGS (ic);
610 IC_INLINE (nic) = IC_INLINE (ic);
614 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
615 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
616 IC_RIGHT (nic) = operandFromOperand (IC_RIGHT (ic));
622 /*-----------------------------------------------------------------*/
623 /* getTableEntry - gets the table entry for the given operator */
624 /*-----------------------------------------------------------------*/
626 getTableEntry (int oper)
630 for (i = 0; i < (sizeof (codeTable) / sizeof (iCodeTable)); i++)
631 if (oper == codeTable[i].icode)
632 return &codeTable[i];
637 /*-----------------------------------------------------------------*/
638 /* newiTempOperand - new intermediate temp operand */
639 /*-----------------------------------------------------------------*/
641 newiTempOperand (sym_link * type, char throwType)
644 operand *op = newOperand ();
648 itmp = newiTemp (NULL);
650 etype = getSpec (type);
652 if (IS_LITERAL (etype))
655 /* copy the type information */
657 itmp->etype = getSpec (itmp->type = (throwType ? type :
658 copyLinkChain (type)));
659 if (IS_LITERAL (itmp->etype))
661 SPEC_SCLS (itmp->etype) = S_REGISTER;
662 SPEC_OCLS (itmp->etype) = reg;
665 op->operand.symOperand = itmp;
666 op->key = itmp->key = ++operandKey;
670 /*-----------------------------------------------------------------*/
671 /* operandType - returns the type chain for an operand */
672 /*-----------------------------------------------------------------*/
674 operandType (operand * op)
676 /* depending on type of operand */
681 return op->operand.valOperand->type;
684 return op->operand.symOperand->type;
687 return op->operand.typeOperand;
689 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
690 " operand type not known ");
691 assert (0); /* should never come here */
692 /* Just to keep the compiler happy */
693 return (sym_link *) 0;
697 /*-----------------------------------------------------------------*/
698 /* isParamterToCall - will return 1 if op is a parameter to args */
699 /*-----------------------------------------------------------------*/
701 isParameterToCall (value * args, operand * op)
708 isSymbolEqual (op->operand.symOperand, tval->sym))
715 /*-----------------------------------------------------------------*/
716 /* isOperandGlobal - return 1 if operand is a global variable */
717 /*-----------------------------------------------------------------*/
719 isOperandGlobal (operand * op)
727 if (op->type == SYMBOL &&
728 (op->operand.symOperand->level == 0 ||
729 IS_STATIC (op->operand.symOperand->etype) ||
730 IS_EXTERN (op->operand.symOperand->etype))
737 /*-----------------------------------------------------------------*/
738 /* isOperandVolatile - return 1 if the operand is volatile */
739 /*-----------------------------------------------------------------*/
741 isOperandVolatile (operand * op, bool chkTemp)
746 if (IS_ITEMP (op) && !chkTemp)
749 opetype = getSpec (optype = operandType (op));
751 if (IS_PTR (optype) && DCL_PTR_VOLATILE (optype))
754 if (IS_VOLATILE (opetype))
759 /*-----------------------------------------------------------------*/
760 /* isOperandLiteral - returns 1 if an operand contains a literal */
761 /*-----------------------------------------------------------------*/
763 isOperandLiteral (operand * op)
770 opetype = getSpec (operandType (op));
772 if (IS_LITERAL (opetype))
777 /*-----------------------------------------------------------------*/
778 /* isOperandInFarSpace - will return true if operand is in farSpace */
779 /*-----------------------------------------------------------------*/
781 isOperandInFarSpace (operand * op)
791 if (!IS_TRUE_SYMOP (op))
794 etype = SPIL_LOC (op)->etype;
800 etype = getSpec (operandType (op));
802 return (IN_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
805 /*-----------------------------------------------------------------*/
806 /* isOperandOnStack - will return true if operand is on stack */
807 /*-----------------------------------------------------------------*/
809 isOperandOnStack (operand * op)
819 etype = getSpec (operandType (op));
821 return ((IN_STACK (etype)) ? TRUE : FALSE);
824 /*-----------------------------------------------------------------*/
825 /* operandLitValue - literal value of an operand */
826 /*-----------------------------------------------------------------*/
828 operandLitValue (operand * op)
830 assert (isOperandLiteral (op));
832 return floatFromVal (op->operand.valOperand);
835 /*-----------------------------------------------------------------*/
836 /* operandOperation - perforoms operations on operands */
837 /*-----------------------------------------------------------------*/
839 operandOperation (operand * left, operand * right,
840 int op, sym_link * type)
842 operand *retval = (operand *) 0;
844 assert (isOperandLiteral (left));
846 assert (isOperandLiteral (right));
851 retval = operandFromValue (valCastLiteral (type,
852 operandLitValue (left) +
853 operandLitValue (right)));
856 retval = operandFromValue (valCastLiteral (type,
857 operandLitValue (left) -
858 operandLitValue (right)));
861 retval = operandFromValue (valCastLiteral (type,
862 operandLitValue (left) *
863 operandLitValue (right)));
866 if ((unsigned long) operandLitValue (right) == 0)
868 werror (E_DIVIDE_BY_ZERO);
873 retval = operandFromValue (valCastLiteral (type,
874 operandLitValue (left) /
875 operandLitValue (right)));
878 if ((unsigned long) operandLitValue (right) == 0)
880 werror (E_DIVIDE_BY_ZERO);
884 retval = operandFromLit ((unsigned long) operandLitValue (left) %
885 (unsigned long) operandLitValue (right));
888 retval = operandFromLit ((unsigned long) operandLitValue (left) <<
889 (unsigned long) operandLitValue (right));
892 retval = operandFromLit ((unsigned long) operandLitValue (left) >>
893 (unsigned long) operandLitValue (right));
896 retval = operandFromLit (operandLitValue (left) ==
897 operandLitValue (right));
900 retval = operandFromLit (operandLitValue (left) <
901 operandLitValue (right));
904 retval = operandFromLit (operandLitValue (left) <=
905 operandLitValue (right));
908 retval = operandFromLit (operandLitValue (left) !=
909 operandLitValue (right));
912 retval = operandFromLit (operandLitValue (left) >
913 operandLitValue (right));
916 retval = operandFromLit (operandLitValue (left) >=
917 operandLitValue (right));
920 retval = operandFromLit ((unsigned long) operandLitValue (left) &
921 (unsigned long) operandLitValue (right));
924 retval = operandFromLit ((unsigned long) operandLitValue (left) |
925 (unsigned long) operandLitValue (right));
928 retval = operandFromLit ((unsigned long) operandLitValue (left) ^
929 (unsigned long) operandLitValue (right));
932 retval = operandFromLit (operandLitValue (left) &&
933 operandLitValue (right));
936 retval = operandFromLit (operandLitValue (left) ||
937 operandLitValue (right));
941 long i = operandLitValue (left);
943 retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
949 long i = operandLitValue (left);
951 retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
957 retval = operandFromLit (-1 * operandLitValue (left));
961 retval = operandFromLit (~((long) operandLitValue (left)));
965 retval = operandFromLit (!operandLitValue (left));
969 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
970 " operandOperation invalid operator ");
978 /*-----------------------------------------------------------------*/
979 /* isOperandEqual - compares two operand & return 1 if they r = */
980 /*-----------------------------------------------------------------*/
982 isOperandEqual (operand * left, operand * right)
984 /* if the pointers are equal then they are equal */
988 /* if either of them null then false */
992 if (left->type != right->type)
995 if (IS_SYMOP (left) && IS_SYMOP (right))
996 return left->key == right->key;
998 /* if types are the same */
1002 return isSymbolEqual (left->operand.symOperand,
1003 right->operand.symOperand);
1005 return (floatFromVal (left->operand.valOperand) ==
1006 floatFromVal (right->operand.valOperand));
1008 if (checkType (left->operand.typeOperand,
1009 right->operand.typeOperand) == 1)
1016 /*-----------------------------------------------------------------*/
1017 /* isiCodeEqual - comapres two iCodes are returns true if yes */
1018 /*-----------------------------------------------------------------*/
1020 isiCodeEqual (iCode * left, iCode * right)
1022 /* if the same pointer */
1026 /* if either of them null */
1027 if (!left || !right)
1030 /* if operand are the same */
1031 if (left->op == right->op)
1034 /* compare all the elements depending on type */
1035 if (left->op != IFX)
1037 if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
1039 if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
1045 if (!isOperandEqual (IC_COND (left), IC_COND (right)))
1047 if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
1049 if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
1057 /*-----------------------------------------------------------------*/
1058 /* newiTempFromOp - create a temp Operand with same attributes */
1059 /*-----------------------------------------------------------------*/
1061 newiTempFromOp (operand * op)
1071 nop = newiTempOperand (operandType (op), TRUE);
1072 nop->isaddr = op->isaddr;
1073 nop->isvolatile = op->isvolatile;
1074 nop->isGlobal = op->isGlobal;
1075 nop->isLiteral = op->isLiteral;
1076 nop->noSpilLoc = op->noSpilLoc;
1077 nop->usesDefs = op->usesDefs;
1078 nop->isParm = op->isParm;
1082 /*-----------------------------------------------------------------*/
1083 /* operand from operand - creates an operand holder for the type */
1084 /*-----------------------------------------------------------------*/
1086 operandFromOperand (operand * op)
1092 nop = newOperand ();
1093 nop->type = op->type;
1094 nop->isaddr = op->isaddr;
1096 nop->isvolatile = op->isvolatile;
1097 nop->isGlobal = op->isGlobal;
1098 nop->isLiteral = op->isLiteral;
1099 nop->noSpilLoc = op->noSpilLoc;
1100 nop->usesDefs = op->usesDefs;
1101 nop->isParm = op->isParm;
1106 nop->operand.symOperand = op->operand.symOperand;
1109 nop->operand.valOperand = op->operand.valOperand;
1112 nop->operand.typeOperand = op->operand.typeOperand;
1119 /*-----------------------------------------------------------------*/
1120 /* opFromOpWithDU - makes a copy of the operand and DU chains */
1121 /*-----------------------------------------------------------------*/
1123 opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
1125 operand *nop = operandFromOperand (op);
1127 if (nop->type == SYMBOL)
1129 OP_SYMBOL (nop)->defs = bitVectCopy (defs);
1130 OP_SYMBOL (nop)->uses = bitVectCopy (uses);
1136 /*-----------------------------------------------------------------*/
1137 /* operandFromSymbol - creates an operand from a symbol */
1138 /*-----------------------------------------------------------------*/
1140 operandFromSymbol (symbol * sym)
1145 /* if the symbol's type is a literal */
1146 /* then it is an enumerator type */
1147 if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
1148 return operandFromValue (valFromType (sym->etype));
1151 sym->key = ++operandKey;
1153 /* if this an implicit variable, means struct/union */
1154 /* member so just return it */
1155 if (sym->implicit || IS_FUNC (sym->type))
1159 op->operand.symOperand = sym;
1161 op->isvolatile = isOperandVolatile (op, TRUE);
1162 op->isGlobal = isOperandGlobal (op);
1166 /* under the following conditions create a
1167 register equivalent for a local symbol */
1168 if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
1169 (IN_FARSPACE (SPEC_OCLS (sym->etype)) && (!TARGET_IS_DS390)) &&
1170 options.stackAuto == 0)
1173 if (!IS_AGGREGATE (sym->type) && /* not an aggregate */
1174 !IS_FUNC (sym->type) && /* not a function */
1175 !sym->_isparm && /* not a parameter */
1176 sym->level && /* is a local variable */
1177 !sym->addrtaken && /* whose address has not been taken */
1178 !sym->reqv && /* does not already have a register euivalence */
1179 !IS_VOLATILE (sym->etype) && /* not declared as volatile */
1180 !IS_STATIC (sym->etype) && /* and not declared static */
1181 !sym->islbl && /* not a label */
1182 ok && /* farspace check */
1183 !IS_BITVAR (sym->etype) /* not a bit variable */
1187 /* we will use it after all optimizations
1188 and before liveRange calculation */
1189 sym->reqv = newiTempOperand (sym->type, 0);
1190 sym->reqv->key = sym->key;
1191 OP_SYMBOL (sym->reqv)->key = sym->key;
1192 OP_SYMBOL (sym->reqv)->isreqv = 1;
1193 OP_SYMBOL (sym->reqv)->islocal = 1;
1194 SPIL_LOC (sym->reqv) = sym;
1197 if (!IS_AGGREGATE (sym->type))
1201 op->operand.symOperand = sym;
1204 op->isvolatile = isOperandVolatile (op, TRUE);
1205 op->isGlobal = isOperandGlobal (op);
1206 op->isPtr = IS_PTR (operandType (op));
1207 op->isParm = sym->_isparm;
1212 /* itemp = &[_symbol] */
1214 ic = newiCode (ADDRESS_OF, newOperand (), NULL);
1215 IC_LEFT (ic)->type = SYMBOL;
1216 IC_LEFT (ic)->operand.symOperand = sym;
1217 IC_LEFT (ic)->key = sym->key;
1218 (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
1219 (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
1220 IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
1223 IC_RESULT (ic) = newiTempOperand (sym->type, 0);
1224 if (IS_ARRAY (sym->type))
1226 IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
1227 IC_RESULT (ic)->isaddr = 0;
1230 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
1232 IC_RESULT (ic)->operand.symOperand->args = sym->args;
1236 return IC_RESULT (ic);
1239 /*-----------------------------------------------------------------*/
1240 /* operandFromValue - creates an operand from value */
1241 /*-----------------------------------------------------------------*/
1243 operandFromValue (value * val)
1247 /* if this is a symbol then do the symbol thing */
1249 return operandFromSymbol (val->sym);
1251 /* this is not a symbol */
1254 op->operand.valOperand = val;
1255 op->isLiteral = isOperandLiteral (op);
1259 /*-----------------------------------------------------------------*/
1260 /* operandFromLink - operand from typeChain */
1261 /*-----------------------------------------------------------------*/
1263 operandFromLink (sym_link * type)
1267 /* operand from sym_link */
1273 op->operand.typeOperand = copyLinkChain (type);
1277 /*-----------------------------------------------------------------*/
1278 /* operandFromLit - makes an operand from a literal value */
1279 /*-----------------------------------------------------------------*/
1281 operandFromLit (float i)
1283 return operandFromValue (valueFromLit (i));
1286 /*-----------------------------------------------------------------*/
1287 /* operandFromAst - creates an operand from an ast */
1288 /*-----------------------------------------------------------------*/
1290 operandFromAst (ast * tree)
1296 /* depending on type do */
1300 return ast2iCode (tree);
1304 return operandFromValue (tree->opval.val);
1308 return operandFromLink (tree->opval.lnk);
1312 /* Just to keep the comiler happy */
1313 return (operand *) 0;
1316 /*-----------------------------------------------------------------*/
1317 /* setOperandType - sets the operand's type to the given type */
1318 /*-----------------------------------------------------------------*/
1320 setOperandType (operand * op, sym_link * type)
1322 /* depending on the type of operand */
1327 op->operand.valOperand->etype =
1328 getSpec (op->operand.valOperand->type =
1329 copyLinkChain (type));
1333 if (op->operand.symOperand->isitmp)
1334 op->operand.symOperand->etype =
1335 getSpec (op->operand.symOperand->type =
1336 copyLinkChain (type));
1338 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1339 "attempt to modify type of source");
1343 op->operand.typeOperand = copyLinkChain (type);
1348 /*-----------------------------------------------------------------*/
1349 /* Get size in byte of ptr need to access an array */
1350 /*-----------------------------------------------------------------*/
1352 getArraySizePtr (operand * op)
1354 sym_link *ltype = operandType(op);
1358 int size = getSize(ltype);
1359 return(IS_GENPTR(ltype)?(size-1):size);
1364 sym_link *letype = getSpec(ltype);
1365 switch (PTR_TYPE (SPEC_OCLS (letype)))
1377 return (GPTRSIZE-1);
1386 /*-----------------------------------------------------------------*/
1387 /* perform "usual unary conversions" */
1388 /*-----------------------------------------------------------------*/
1390 usualUnaryConversions (operand * op)
1392 if (IS_INTEGRAL (operandType (op)))
1394 if (getSize (operandType (op)) < INTSIZE)
1397 return geniCodeCast (INTTYPE, op, TRUE);
1403 /*-----------------------------------------------------------------*/
1404 /* perform "usual binary conversions" */
1405 /*-----------------------------------------------------------------*/
1407 usualBinaryConversions (operand ** op1, operand ** op2)
1410 sym_link *rtype = operandType (*op2);
1411 sym_link *ltype = operandType (*op1);
1413 ctype = computeType (ltype, rtype);
1414 *op1 = geniCodeCast (ctype, *op1, TRUE);
1415 *op2 = geniCodeCast (ctype, *op2, TRUE);
1420 /*-----------------------------------------------------------------*/
1421 /* geniCodeValueAtAddress - generate intermeditate code for value */
1423 /*-----------------------------------------------------------------*/
1425 geniCodeRValue (operand * op, bool force)
1428 sym_link *type = operandType (op);
1429 sym_link *etype = getSpec (type);
1431 /* if this is an array & already */
1432 /* an address then return this */
1433 if (IS_AGGREGATE (type) ||
1434 (IS_PTR (type) && !force && !op->isaddr))
1435 return operandFromOperand (op);
1437 /* if this is not an address then must be */
1438 /* rvalue already so return this one */
1442 /* if this is not a temp symbol then */
1443 if (!IS_ITEMP (op) &&
1445 !IN_FARSPACE (SPEC_OCLS (etype)))
1447 op = operandFromOperand (op);
1452 if (IS_SPEC (type) &&
1453 IS_TRUE_SYMOP (op) &&
1454 (!IN_FARSPACE (SPEC_OCLS (etype)) || TARGET_IS_DS390))
1456 op = operandFromOperand (op);
1461 ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1462 if (IS_PTR (type) && op->isaddr && force)
1465 type = copyLinkChain (type);
1467 IC_RESULT (ic) = newiTempOperand (type, 1);
1468 IC_RESULT (ic)->isaddr = 0;
1470 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1472 /* if the right is a symbol */
1473 if (op->type == SYMBOL)
1474 IC_RESULT (ic)->operand.symOperand->args =
1475 op->operand.symOperand->args;
1478 return IC_RESULT (ic);
1481 /*-----------------------------------------------------------------*/
1482 /* geniCodeCast - changes the value from one type to another */
1483 /*-----------------------------------------------------------------*/
1485 geniCodeCast (sym_link * type, operand * op, bool implicit)
1489 sym_link *opetype = getSpec (optype = operandType (op));
1492 /* one of them has size zero then error */
1493 if (IS_VOID (optype))
1495 werror (E_CAST_ZERO);
1499 /* if the operand is already the desired type then do nothing */
1500 if (checkType (type, optype) == 1)
1503 /* if this is a literal then just change the type & return */
1504 if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1505 return operandFromValue (valCastLiteral (type,
1506 operandLitValue (op)));
1508 /* if casting to some pointer type &&
1509 the destination is not a generic pointer
1510 then give a warning : (only for implicit casts) */
1511 if (IS_PTR (optype) && implicit &&
1512 (DCL_TYPE (optype) != DCL_TYPE (type)) &&
1515 werror (E_INCOMPAT_CAST);
1516 werror (E_CONTINUE, "from type '");
1517 printTypeChain (optype, stderr);
1518 fprintf (stderr, "' to type '");
1519 printTypeChain (type, stderr);
1520 fprintf (stderr, "'\n");
1523 /* if they are the same size create an assignment */
1524 if (getSize (type) == getSize (optype) &&
1525 !IS_BITFIELD (type) &&
1527 !IS_FLOAT (optype) &&
1528 ((IS_SPEC (type) && IS_SPEC (optype)) ||
1529 (!IS_SPEC (type) && !IS_SPEC (optype))))
1532 ic = newiCode ('=', NULL, op);
1533 IC_RESULT (ic) = newiTempOperand (type, 0);
1534 SPIL_LOC (IC_RESULT (ic)) =
1535 (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
1536 IC_RESULT (ic)->isaddr = 0;
1540 ic = newiCode (CAST, operandFromLink (type),
1541 geniCodeRValue (op, FALSE));
1543 IC_RESULT (ic) = newiTempOperand (type, 0);
1546 /* preserve the storage class & output class */
1547 /* of the original variable */
1548 restype = getSpec (operandType (IC_RESULT (ic)));
1549 SPEC_SCLS (restype) = SPEC_SCLS (opetype);
1550 SPEC_OCLS (restype) = SPEC_OCLS (opetype);
1553 return IC_RESULT (ic);
1556 /*-----------------------------------------------------------------*/
1557 /* geniCodeLabel - will create a Label */
1558 /*-----------------------------------------------------------------*/
1560 geniCodeLabel (symbol * label)
1564 ic = newiCodeLabelGoto (LABEL, label);
1568 /*-----------------------------------------------------------------*/
1569 /* geniCodeGoto - will create a Goto */
1570 /*-----------------------------------------------------------------*/
1572 geniCodeGoto (symbol * label)
1576 ic = newiCodeLabelGoto (GOTO, label);
1580 /*-----------------------------------------------------------------*/
1581 /* geniCodeMultiply - gen intermediate code for multiplication */
1582 /*-----------------------------------------------------------------*/
1584 geniCodeMultiply (operand * left, operand * right,int resultIsInt)
1591 /* if they are both literal then we know the result */
1592 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1593 return operandFromValue (valMult (left->operand.valOperand,
1594 right->operand.valOperand));
1596 if (IS_LITERAL(retype)) {
1597 p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
1600 resType = usualBinaryConversions (&left, &right);
1602 rtype = operandType (right);
1603 retype = getSpec (rtype);
1604 ltype = operandType (left);
1605 letype = getSpec (ltype);
1609 SPEC_NOUN(getSpec(resType))=V_INT;
1610 SPEC_SHORT(getSpec(resType))=0;
1613 /* if the right is a literal & power of 2 */
1614 /* then make it a left shift */
1615 /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
1616 efficient in most cases than 2 bytes result = 2 bytes << literal
1617 if port has 1 byte muldiv */
1618 if (p2 && !IS_FLOAT (letype) &&
1619 !((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
1620 (port->muldiv.native_below == 1)))
1622 if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
1624 /* LEFT_OP need same size for left and result, */
1625 left = geniCodeCast (resType, left, TRUE);
1626 ltype = operandType (left);
1628 ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
1632 ic = newiCode ('*', left, right); /* normal multiplication */
1633 /* if the size left or right > 1 then support routine */
1634 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1638 IC_RESULT (ic) = newiTempOperand (resType, 1);
1641 return IC_RESULT (ic);
1644 /*-----------------------------------------------------------------*/
1645 /* geniCodeDivision - gen intermediate code for division */
1646 /*-----------------------------------------------------------------*/
1648 geniCodeDivision (operand * left, operand * right)
1653 sym_link *rtype = operandType (right);
1654 sym_link *retype = getSpec (rtype);
1655 sym_link *ltype = operandType (left);
1656 sym_link *letype = getSpec (ltype);
1658 resType = usualBinaryConversions (&left, &right);
1660 /* if the right is a literal & power of 2 */
1661 /* then make it a right shift */
1662 if (IS_LITERAL (retype) &&
1663 !IS_FLOAT (letype) &&
1664 (p2 = powof2 ((unsigned long)
1665 floatFromVal (right->operand.valOperand))))
1666 ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
1669 ic = newiCode ('/', left, right); /* normal division */
1670 /* if the size left or right > 1 then support routine */
1671 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1674 IC_RESULT (ic) = newiTempOperand (resType, 0);
1677 return IC_RESULT (ic);
1679 /*-----------------------------------------------------------------*/
1680 /* geniCodeModulus - gen intermediate code for modulus */
1681 /*-----------------------------------------------------------------*/
1683 geniCodeModulus (operand * left, operand * right)
1689 /* if they are both literal then we know the result */
1690 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1691 return operandFromValue (valMod (left->operand.valOperand,
1692 right->operand.valOperand));
1694 resType = usualBinaryConversions (&left, &right);
1696 /* now they are the same size */
1697 ic = newiCode ('%', left, right);
1699 /* if the size left or right > 1 then support routine */
1700 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1702 IC_RESULT (ic) = newiTempOperand (resType, 0);
1705 return IC_RESULT (ic);
1708 /*-----------------------------------------------------------------*/
1709 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
1710 /*-----------------------------------------------------------------*/
1712 geniCodePtrPtrSubtract (operand * left, operand * right)
1718 /* if they are both literals then */
1719 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1721 result = operandFromValue (valMinus (left->operand.valOperand,
1722 right->operand.valOperand));
1726 ic = newiCode ('-', left, right);
1728 IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
1732 return geniCodeDivision (result,
1733 operandFromLit (getSize (ltype->next)));
1736 /*-----------------------------------------------------------------*/
1737 /* geniCodeSubtract - generates code for subtraction */
1738 /*-----------------------------------------------------------------*/
1740 geniCodeSubtract (operand * left, operand * right)
1747 /* if they both pointers then */
1748 if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
1749 (IS_PTR (rtype) || IS_ARRAY (rtype)))
1750 return geniCodePtrPtrSubtract (left, right);
1752 /* if they are both literal then we know the result */
1753 if (IS_LITERAL (letype) && IS_LITERAL (retype)
1754 && left->isLiteral && right->isLiteral)
1755 return operandFromValue (valMinus (left->operand.valOperand,
1756 right->operand.valOperand));
1758 /* if left is an array or pointer */
1759 if (IS_PTR (ltype) || IS_ARRAY (ltype))
1761 isarray = left->isaddr;
1762 right = geniCodeMultiply (right,
1763 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
1764 resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
1767 { /* make them the same size */
1768 resType = usualBinaryConversions (&left, &right);
1771 ic = newiCode ('-', left, right);
1773 IC_RESULT (ic) = newiTempOperand (resType, 1);
1774 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
1776 /* if left or right is a float */
1777 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
1781 return IC_RESULT (ic);
1784 /*-----------------------------------------------------------------*/
1785 /* geniCodeAdd - generates iCode for addition */
1786 /*-----------------------------------------------------------------*/
1788 geniCodeAdd (operand * left, operand * right)
1796 /* if left is an array then array access */
1797 if (IS_ARRAY (ltype))
1798 return geniCodeArray (left, right);
1800 /* if the right side is LITERAL zero */
1801 /* return the left side */
1802 if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
1805 /* if left is literal zero return right */
1806 if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
1809 /* if left is an array or pointer then size */
1812 isarray = left->isaddr;
1813 // there is no need to multiply with 1
1814 if (getSize(ltype->next)!=1) {
1815 size = operandFromLit (getSize (ltype->next));
1816 right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
1818 resType = copyLinkChain (ltype);
1821 { /* make them the same size */
1822 resType = usualBinaryConversions (&left, &right);
1825 /* if they are both literals then we know */
1826 if (IS_LITERAL (letype) && IS_LITERAL (retype)
1827 && left->isLiteral && right->isLiteral)
1828 return operandFromValue (valPlus (valFromType (letype),
1829 valFromType (retype)));
1831 ic = newiCode ('+', left, right);
1833 IC_RESULT (ic) = newiTempOperand (resType, 1);
1834 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
1836 /* if left or right is a float then support
1838 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
1843 return IC_RESULT (ic);
1847 /*-----------------------------------------------------------------*/
1848 /* aggrToPtr - changes an aggregate to pointer to an aggregate */
1849 /*-----------------------------------------------------------------*/
1851 aggrToPtr (sym_link * type, bool force)
1857 if (IS_PTR (type) && !force)
1860 etype = getSpec (type);
1864 /* if the output class is generic */
1865 if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER)
1866 DCL_PTR_CONST (ptype) = port->mem.code_ro;
1868 /* if the variable was declared a constant */
1869 /* then the pointer points to a constant */
1870 if (IS_CONSTANT (etype))
1871 DCL_PTR_CONST (ptype) = 1;
1873 /* the variable was volatile then pointer to volatile */
1874 if (IS_VOLATILE (etype))
1875 DCL_PTR_VOLATILE (ptype) = 1;
1879 /*-----------------------------------------------------------------*/
1880 /* geniCodeArray2Ptr - array to pointer */
1881 /*-----------------------------------------------------------------*/
1883 geniCodeArray2Ptr (operand * op)
1885 sym_link *optype = operandType (op);
1886 sym_link *opetype = getSpec (optype);
1888 /* set the pointer depending on the storage class */
1889 if ((DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
1890 DCL_PTR_CONST (optype) = port->mem.code_ro;
1893 /* if the variable was declared a constant */
1894 /* then the pointer points to a constant */
1895 if (IS_CONSTANT (opetype))
1896 DCL_PTR_CONST (optype) = 1;
1898 /* the variable was volatile then pointer to volatile */
1899 if (IS_VOLATILE (opetype))
1900 DCL_PTR_VOLATILE (optype) = 1;
1906 /*-----------------------------------------------------------------*/
1907 /* geniCodeArray - array access */
1908 /*-----------------------------------------------------------------*/
1910 geniCodeArray (operand * left, operand * right)
1913 sym_link *ltype = operandType (left);
1917 if (IS_PTR (ltype->next) && left->isaddr)
1919 left = geniCodeRValue (left, FALSE);
1921 return geniCodeDerefPtr (geniCodeAdd (left, right));
1924 right = geniCodeMultiply (right,
1925 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
1927 /* we can check for limits here */
1928 if (isOperandLiteral (right) &&
1931 (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
1933 werror (E_ARRAY_BOUND);
1934 right = operandFromLit (0);
1937 ic = newiCode ('+', left, right);
1939 IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
1940 !IS_AGGREGATE (ltype->next) &&
1941 !IS_PTR (ltype->next))
1942 ? ltype : ltype->next), 0);
1944 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
1946 return IC_RESULT (ic);
1949 /*-----------------------------------------------------------------*/
1950 /* geniCodeStruct - generates intermediate code for structres */
1951 /*-----------------------------------------------------------------*/
1953 geniCodeStruct (operand * left, operand * right, bool islval)
1956 sym_link *type = operandType (left);
1957 sym_link *etype = getSpec (type);
1959 symbol *element = getStructElement (SPEC_STRUCT (etype),
1960 right->operand.symOperand);
1962 /* add the offset */
1963 ic = newiCode ('+', left, operandFromLit (element->offset));
1965 IC_RESULT (ic) = newiTempOperand (element->type, 0);
1967 /* preserve the storage & output class of the struct */
1968 /* as well as the volatile attribute */
1969 retype = getSpec (operandType (IC_RESULT (ic)));
1970 SPEC_SCLS (retype) = SPEC_SCLS (etype);
1971 SPEC_OCLS (retype) = SPEC_OCLS (etype);
1972 SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
1974 if (IS_PTR (element->type))
1975 setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
1977 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
1981 return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
1984 /*-----------------------------------------------------------------*/
1985 /* geniCodePostInc - generate int code for Post increment */
1986 /*-----------------------------------------------------------------*/
1988 geniCodePostInc (operand * op)
1992 sym_link *optype = operandType (op);
1994 operand *rv = (IS_ITEMP (op) ?
1995 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
1997 sym_link *rvtype = operandType (rv);
2000 /* if this is not an address we have trouble */
2003 werror (E_LVALUE_REQUIRED, "++");
2007 rOp = newiTempOperand (rvtype, 0);
2013 geniCodeAssign (rOp, rv, 0);
2015 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2016 if (IS_FLOAT (rvtype))
2017 ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2019 ic = newiCode ('+', rv, operandFromLit (size));
2021 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2024 geniCodeAssign (op, result, 0);
2030 /*-----------------------------------------------------------------*/
2031 /* geniCodePreInc - generate code for preIncrement */
2032 /*-----------------------------------------------------------------*/
2034 geniCodePreInc (operand * op)
2037 sym_link *optype = operandType (op);
2038 operand *rop = (IS_ITEMP (op) ?
2039 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2041 sym_link *roptype = operandType (rop);
2047 werror (E_LVALUE_REQUIRED, "++");
2052 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2053 if (IS_FLOAT (roptype))
2054 ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2056 ic = newiCode ('+', rop, operandFromLit (size));
2057 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2061 return geniCodeAssign (op, result, 0);
2064 /*-----------------------------------------------------------------*/
2065 /* geniCodePostDec - generates code for Post decrement */
2066 /*-----------------------------------------------------------------*/
2068 geniCodePostDec (operand * op)
2072 sym_link *optype = operandType (op);
2074 operand *rv = (IS_ITEMP (op) ?
2075 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2077 sym_link *rvtype = operandType (rv);
2080 /* if this is not an address we have trouble */
2083 werror (E_LVALUE_REQUIRED, "++");
2087 rOp = newiTempOperand (rvtype, 0);
2093 geniCodeAssign (rOp, rv, 0);
2095 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2096 if (IS_FLOAT (rvtype))
2097 ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2099 ic = newiCode ('-', rv, operandFromLit (size));
2101 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2104 geniCodeAssign (op, result, 0);
2110 /*-----------------------------------------------------------------*/
2111 /* geniCodePreDec - generate code for pre decrement */
2112 /*-----------------------------------------------------------------*/
2114 geniCodePreDec (operand * op)
2117 sym_link *optype = operandType (op);
2118 operand *rop = (IS_ITEMP (op) ?
2119 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2121 sym_link *roptype = operandType (rop);
2127 werror (E_LVALUE_REQUIRED, "++");
2132 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2133 if (IS_FLOAT (roptype))
2134 ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2136 ic = newiCode ('-', rop, operandFromLit (size));
2137 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2141 return geniCodeAssign (op, result, 0);
2145 /*-----------------------------------------------------------------*/
2146 /* geniCodeBitwise - gen int code for bitWise operators */
2147 /*-----------------------------------------------------------------*/
2149 geniCodeBitwise (operand * left, operand * right,
2150 int oper, sym_link * resType)
2154 left = geniCodeCast (resType, left, TRUE);
2155 right = geniCodeCast (resType, right, TRUE);
2157 ic = newiCode (oper, left, right);
2158 IC_RESULT (ic) = newiTempOperand (resType, 0);
2161 return IC_RESULT (ic);
2164 /*-----------------------------------------------------------------*/
2165 /* geniCodeAddressOf - gens icode for '&' address of operator */
2166 /*-----------------------------------------------------------------*/
2168 geniCodeAddressOf (operand * op)
2172 sym_link *optype = operandType (op);
2173 sym_link *opetype = getSpec (optype);
2175 /* lvalue check already done in decorateType */
2176 /* this must be a lvalue */
2177 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2178 /* werror (E_LVALUE_REQUIRED,"&"); */
2183 p->class = DECLARATOR;
2185 /* set the pointer depending on the storage class */
2186 if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2187 DCL_PTR_CONST (p) = port->mem.code_ro;
2189 /* make sure we preserve the const & volatile */
2190 if (IS_CONSTANT (opetype))
2191 DCL_PTR_CONST (p) = 1;
2193 if (IS_VOLATILE (opetype))
2194 DCL_PTR_VOLATILE (p) = 1;
2196 p->next = copyLinkChain (optype);
2198 /* if already a temp */
2201 setOperandType (op, p);
2206 /* other wise make this of the type coming in */
2207 ic = newiCode (ADDRESS_OF, op, NULL);
2208 IC_RESULT (ic) = newiTempOperand (p, 1);
2209 IC_RESULT (ic)->isaddr = 0;
2211 return IC_RESULT (ic);
2213 /*-----------------------------------------------------------------*/
2214 /* setOClass - sets the output class depending on the pointer type */
2215 /*-----------------------------------------------------------------*/
2217 setOClass (sym_link * ptr, sym_link * spec)
2219 switch (DCL_TYPE (ptr))
2222 SPEC_OCLS (spec) = data;
2226 SPEC_OCLS (spec) = generic;
2230 SPEC_OCLS (spec) = xdata;
2234 SPEC_OCLS (spec) = code;
2238 SPEC_OCLS (spec) = idata;
2242 SPEC_OCLS (spec) = xstack;
2246 SPEC_OCLS (spec) = eeprom;
2255 /*-----------------------------------------------------------------*/
2256 /* geniCodeDerefPtr - dereference pointer with '*' */
2257 /*-----------------------------------------------------------------*/
2259 geniCodeDerefPtr (operand * op)
2261 sym_link *rtype, *retype;
2262 sym_link *optype = operandType (op);
2264 /* if this is a pointer then generate the rvalue */
2265 if (IS_PTR (optype))
2267 if (IS_TRUE_SYMOP (op))
2270 op = geniCodeRValue (op, TRUE);
2273 op = geniCodeRValue (op, TRUE);
2276 /* now get rid of the pointer part */
2277 if (lvaluereq && IS_ITEMP (op))
2279 retype = getSpec (rtype = copyLinkChain (optype));
2283 retype = getSpec (rtype = copyLinkChain (optype->next));
2286 /* if this is a pointer then outputclass needs 2b updated */
2287 if (IS_PTR (optype))
2288 setOClass (optype, retype);
2290 op->isGptr = IS_GENPTR (optype);
2292 /* if the pointer was declared as a constant */
2293 /* then we cannot allow assignment to the derefed */
2294 if (IS_PTR_CONST (optype))
2295 SPEC_CONST (retype) = 1;
2297 op->isaddr = (IS_PTR (rtype) ||
2298 IS_STRUCT (rtype) ||
2304 op = geniCodeRValue (op, TRUE);
2306 setOperandType (op, rtype);
2311 /*-----------------------------------------------------------------*/
2312 /* geniCodeUnaryMinus - does a unary minus of the operand */
2313 /*-----------------------------------------------------------------*/
2315 geniCodeUnaryMinus (operand * op)
2318 sym_link *optype = operandType (op);
2320 if (IS_LITERAL (optype))
2321 return operandFromLit (-floatFromVal (op->operand.valOperand));
2323 ic = newiCode (UNARYMINUS, op, NULL);
2324 IC_RESULT (ic) = newiTempOperand (optype, 0);
2326 return IC_RESULT (ic);
2329 /*-----------------------------------------------------------------*/
2330 /* geniCodeLeftShift - gen i code for left shift */
2331 /*-----------------------------------------------------------------*/
2333 geniCodeLeftShift (operand * left, operand * right)
2337 ic = newiCode (LEFT_OP, left, right);
2338 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2340 return IC_RESULT (ic);
2343 /*-----------------------------------------------------------------*/
2344 /* geniCodeRightShift - gen i code for right shift */
2345 /*-----------------------------------------------------------------*/
2347 geniCodeRightShift (operand * left, operand * right)
2351 ic = newiCode (RIGHT_OP, left, right);
2352 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2354 return IC_RESULT (ic);
2357 #if defined(__BORLANDC__) || defined(_MSC_VER)
2358 #define LONG_LONG __int64
2360 #define LONG_LONG long long
2363 /*-----------------------------------------------------------------*/
2364 /* geniCodeLogic- logic code */
2365 /*-----------------------------------------------------------------*/
2367 geniCodeLogic (operand * left, operand * right, int op)
2371 sym_link *rtype = operandType (right);
2372 sym_link *ltype = operandType (left);
2374 /* left is integral type and right is literal then
2375 check if the literal value is within bounds */
2376 if (IS_INTEGRAL (ltype) && IS_LITERAL (rtype))
2378 int nbits = bitsForType (ltype);
2379 long v = operandLitValue (right);
2381 if (v > ((LONG_LONG) 1 << nbits) && v > 0)
2382 werror (W_CONST_RANGE, " compare operation ");
2385 ctype = usualBinaryConversions (&left, &right);
2387 ic = newiCode (op, left, right);
2388 IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2390 /* if comparing float
2391 and not a '==' || '!=' || '&&' || '||' (these
2393 if (IS_FLOAT(ctype) &&
2401 return IC_RESULT (ic);
2404 /*-----------------------------------------------------------------*/
2405 /* geniCodeUnary - for a a generic unary operation */
2406 /*-----------------------------------------------------------------*/
2408 geniCodeUnary (operand * op, int oper)
2410 iCode *ic = newiCode (oper, op, NULL);
2412 IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2414 return IC_RESULT (ic);
2417 /*-----------------------------------------------------------------*/
2418 /* geniCodeConditional - geniCode for '?' ':' operation */
2419 /*-----------------------------------------------------------------*/
2421 geniCodeConditional (ast * tree)
2424 symbol *falseLabel = newiTempLabel (NULL);
2425 symbol *exitLabel = newiTempLabel (NULL);
2426 operand *cond = ast2iCode (tree->left);
2427 operand *true, *false, *result;
2429 ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
2433 true = ast2iCode (tree->right->left);
2435 /* move the value to a new Operand */
2436 result = newiTempOperand (operandType (true), 0);
2437 geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
2439 /* generate an unconditional goto */
2440 geniCodeGoto (exitLabel);
2442 /* now for the right side */
2443 geniCodeLabel (falseLabel);
2445 false = ast2iCode (tree->right->right);
2446 geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
2448 /* create the exit label */
2449 geniCodeLabel (exitLabel);
2454 /*-----------------------------------------------------------------*/
2455 /* geniCodeAssign - generate code for assignment */
2456 /*-----------------------------------------------------------------*/
2458 geniCodeAssign (operand * left, operand * right, int nosupdate)
2461 sym_link *ltype = operandType (left);
2462 sym_link *rtype = operandType (right);
2464 if (!left->isaddr && !IS_ITEMP (left))
2466 werror (E_LVALUE_REQUIRED, "assignment");
2470 /* left is integral type and right is literal then
2471 check if the literal value is within bounds */
2472 if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
2474 int nbits = bitsForType (ltype);
2475 long v = operandLitValue (right);
2477 if (v > ((LONG_LONG) 1 << nbits) && v > 0)
2478 werror (W_CONST_RANGE, " = operation");
2481 /* if the left & right type don't exactly match */
2482 /* if pointer set then make sure the check is
2483 done with the type & not the pointer */
2484 /* then cast rights type to left */
2486 /* first check the type for pointer assignement */
2487 if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
2488 checkType (ltype, rtype) < 0)
2490 if (checkType (ltype->next, rtype) < 0)
2491 right = geniCodeCast (ltype->next, right, TRUE);
2493 else if (checkType (ltype, rtype) < 0)
2494 right = geniCodeCast (ltype, right, TRUE);
2496 /* if left is a true symbol & ! volatile
2497 create an assignment to temporary for
2498 the right & then assign this temporary
2499 to the symbol this is SSA . isn't it simple
2500 and folks have published mountains of paper on it */
2501 if (IS_TRUE_SYMOP (left) &&
2502 !isOperandVolatile (left, FALSE) &&
2503 isOperandGlobal (left))
2507 if (IS_TRUE_SYMOP (right))
2508 sym = OP_SYMBOL (right);
2509 ic = newiCode ('=', NULL, right);
2510 IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
2511 SPIL_LOC (right) = sym;
2515 ic = newiCode ('=', NULL, right);
2516 IC_RESULT (ic) = left;
2519 /* if left isgptr flag is set then support
2520 routine will be required */
2524 ic->nosupdate = nosupdate;
2528 /*-----------------------------------------------------------------*/
2529 /* geniCodeSEParms - generate code for side effecting fcalls */
2530 /*-----------------------------------------------------------------*/
2532 geniCodeSEParms (ast * parms)
2537 if (parms->type == EX_OP && parms->opval.op == PARAM)
2539 geniCodeSEParms (parms->left);
2540 geniCodeSEParms (parms->right);
2544 /* hack don't like this but too lazy to think of
2546 if (IS_ADDRESS_OF_OP (parms))
2547 parms->left->lvalue = 1;
2549 if (IS_CAST_OP (parms) &&
2550 IS_PTR (parms->ftype) &&
2551 IS_ADDRESS_OF_OP (parms->right))
2552 parms->right->left->lvalue = 1;
2554 parms->opval.oprnd =
2555 geniCodeRValue (ast2iCode (parms), FALSE);
2557 parms->type = EX_OPERAND;
2560 /*-----------------------------------------------------------------*/
2561 /* geniCodeParms - generates parameters */
2562 /*-----------------------------------------------------------------*/
2564 geniCodeParms (ast * parms, int *stack, sym_link * fetype, symbol * func)
2572 /* if this is a param node then do the left & right */
2573 if (parms->type == EX_OP && parms->opval.op == PARAM)
2575 geniCodeParms (parms->left, stack, fetype, func);
2576 geniCodeParms (parms->right, stack, fetype, func);
2580 /* get the parameter value */
2581 if (parms->type == EX_OPERAND)
2582 pval = parms->opval.oprnd;
2585 /* maybe this else should go away ?? */
2586 /* hack don't like this but too lazy to think of
2588 if (IS_ADDRESS_OF_OP (parms))
2589 parms->left->lvalue = 1;
2591 if (IS_CAST_OP (parms) &&
2592 IS_PTR (parms->ftype) &&
2593 IS_ADDRESS_OF_OP (parms->right))
2594 parms->right->left->lvalue = 1;
2596 pval = geniCodeRValue (ast2iCode (parms), FALSE);
2599 /* if register parm then make it a send */
2600 if (((parms->argSym && IS_REGPARM (parms->argSym->etype)) ||
2601 IS_REGPARM (parms->etype)) && !func->hasVargs)
2603 ic = newiCode (SEND, pval, NULL);
2608 /* now decide whether to push or assign */
2609 if (!(options.stackAuto || IS_RENT (fetype)))
2613 operand *top = operandFromSymbol (parms->argSym);
2614 geniCodeAssign (top, pval, 1);
2618 sym_link *p = operandType (pval);
2620 ic = newiCode (IPUSH, pval, NULL);
2622 /* update the stack adjustment */
2623 *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2630 /*-----------------------------------------------------------------*/
2631 /* geniCodeCall - generates temp code for calling */
2632 /*-----------------------------------------------------------------*/
2634 geniCodeCall (operand * left, ast * parms)
2638 sym_link *type, *etype;
2641 /* take care of parameters with side-effecting
2642 function calls in them, this is required to take care
2643 of overlaying function parameters */
2644 geniCodeSEParms (parms);
2646 /* first the parameters */
2647 geniCodeParms (parms, &stack, getSpec (operandType (left)), OP_SYMBOL (left));
2649 /* now call : if symbol then pcall */
2650 if (IS_OP_POINTER (left) || IS_ITEMP(left))
2651 ic = newiCode (PCALL, left, NULL);
2653 ic = newiCode (CALL, left, NULL);
2655 IC_ARGS (ic) = left->operand.symOperand->args;
2656 type = copyLinkChain (operandType (left)->next);
2657 etype = getSpec (type);
2658 SPEC_EXTR (etype) = 0;
2659 IC_RESULT (ic) = result = newiTempOperand (type, 1);
2663 /* stack adjustment after call */
2664 ic->parmBytes = stack;
2669 /*-----------------------------------------------------------------*/
2670 /* geniCodeReceive - generate intermediate code for "receive" */
2671 /*-----------------------------------------------------------------*/
2673 geniCodeReceive (value * args)
2675 /* for all arguments that are passed in registers */
2679 if (IS_REGPARM (args->etype))
2681 operand *opr = operandFromValue (args);
2683 symbol *sym = OP_SYMBOL (opr);
2686 /* we will use it after all optimizations
2687 and before liveRange calculation */
2688 if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
2691 if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
2692 options.stackAuto == 0 &&
2698 opl = newiTempOperand (args->type, 0);
2700 sym->reqv->key = sym->key;
2701 OP_SYMBOL (sym->reqv)->key = sym->key;
2702 OP_SYMBOL (sym->reqv)->isreqv = 1;
2703 OP_SYMBOL (sym->reqv)->islocal = 0;
2704 SPIL_LOC (sym->reqv) = sym;
2708 ic = newiCode (RECEIVE, NULL, NULL);
2709 currFunc->recvSize = getSize (sym->etype);
2710 IC_RESULT (ic) = opr;
2718 /*-----------------------------------------------------------------*/
2719 /* geniCodeFunctionBody - create the function body */
2720 /*-----------------------------------------------------------------*/
2722 geniCodeFunctionBody (ast * tree)
2729 /* reset the auto generation */
2735 func = ast2iCode (tree->left);
2736 fetype = getSpec (operandType (func));
2738 savelineno = lineno;
2739 lineno = OP_SYMBOL (func)->lineDef;
2740 /* create an entry label */
2741 geniCodeLabel (entryLabel);
2742 lineno = savelineno;
2744 /* create a proc icode */
2745 ic = newiCode (FUNCTION, func, NULL);
2746 /* if the function has parmas then */
2747 /* save the parameters information */
2748 ic->argLabel.args = tree->values.args;
2749 ic->lineno = OP_SYMBOL (func)->lineDef;
2753 /* for all parameters that are passed
2754 on registers add a "receive" */
2755 geniCodeReceive (tree->values.args);
2757 /* generate code for the body */
2758 ast2iCode (tree->right);
2760 /* create a label for return */
2761 geniCodeLabel (returnLabel);
2763 /* now generate the end proc */
2764 ic = newiCode (ENDFUNCTION, func, NULL);
2769 /*-----------------------------------------------------------------*/
2770 /* geniCodeReturn - gen icode for 'return' statement */
2771 /*-----------------------------------------------------------------*/
2773 geniCodeReturn (operand * op)
2777 /* if the operand is present force an rvalue */
2779 op = geniCodeRValue (op, FALSE);
2781 ic = newiCode (RETURN, op, NULL);
2785 /*-----------------------------------------------------------------*/
2786 /* geniCodeIfx - generates code for extended if statement */
2787 /*-----------------------------------------------------------------*/
2789 geniCodeIfx (ast * tree)
2792 operand *condition = ast2iCode (tree->left);
2795 /* if condition is null then exit */
2799 condition = geniCodeRValue (condition, FALSE);
2801 cetype = getSpec (operandType (condition));
2802 /* if the condition is a literal */
2803 if (IS_LITERAL (cetype))
2805 if (floatFromVal (condition->operand.valOperand))
2807 if (tree->trueLabel)
2808 geniCodeGoto (tree->trueLabel);
2814 if (tree->falseLabel)
2815 geniCodeGoto (tree->falseLabel);
2822 if (tree->trueLabel)
2824 ic = newiCodeCondition (condition,
2829 if (tree->falseLabel)
2830 geniCodeGoto (tree->falseLabel);
2834 ic = newiCodeCondition (condition,
2841 ast2iCode (tree->right);
2844 /*-----------------------------------------------------------------*/
2845 /* geniCodeJumpTable - tries to create a jump table for switch */
2846 /*-----------------------------------------------------------------*/
2848 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
2850 int min = 0, max = 0, t, cnt = 0;
2857 if (!tree || !caseVals)
2860 /* the criteria for creating a jump table is */
2861 /* all integer numbers between the maximum & minimum must */
2862 /* be present , the maximum value should not exceed 255 */
2863 min = max = (int) floatFromVal (vch = caseVals);
2864 sprintf (buffer, "_case_%d_%d",
2865 tree->values.switchVals.swNum,
2867 addSet (&labels, newiTempLabel (buffer));
2869 /* if there is only one case value then no need */
2870 if (!(vch = vch->next))
2875 if (((t = (int) floatFromVal (vch)) - max) != 1)
2877 sprintf (buffer, "_case_%d_%d",
2878 tree->values.switchVals.swNum,
2880 addSet (&labels, newiTempLabel (buffer));
2886 /* if the number of case statements <= 2 then */
2887 /* it is not economical to create the jump table */
2888 /* since two compares are needed for boundary conditions */
2889 if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
2892 if (tree->values.switchVals.swDefault)
2893 sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
2895 sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
2897 falseLabel = newiTempLabel (buffer);
2899 /* so we can create a jumptable */
2900 /* first we rule out the boundary conditions */
2901 /* if only optimization says so */
2902 if (!optimize.noJTabBoundary)
2904 sym_link *cetype = getSpec (operandType (cond));
2905 /* no need to check the lower bound if
2906 the condition is unsigned & minimum value is zero */
2907 if (!(min == 0 && SPEC_USIGN (cetype)))
2909 boundary = geniCodeLogic (cond, operandFromLit (min), '<');
2910 ic = newiCodeCondition (boundary, falseLabel, NULL);
2914 /* now for upper bounds */
2915 boundary = geniCodeLogic (cond, operandFromLit (max), '>');
2916 ic = newiCodeCondition (boundary, falseLabel, NULL);
2920 /* if the min is not zero then we no make it zero */
2923 cond = geniCodeSubtract (cond, operandFromLit (min));
2924 setOperandType (cond, UCHARTYPE);
2927 /* now create the jumptable */
2928 ic = newiCode (JUMPTABLE, NULL, NULL);
2929 IC_JTCOND (ic) = cond;
2930 IC_JTLABELS (ic) = labels;
2935 /*-----------------------------------------------------------------*/
2936 /* geniCodeSwitch - changes a switch to a if statement */
2937 /*-----------------------------------------------------------------*/
2939 geniCodeSwitch (ast * tree)
2942 operand *cond = geniCodeRValue (ast2iCode (tree->left), FALSE);
2943 value *caseVals = tree->values.switchVals.swVals;
2944 symbol *trueLabel, *falseLabel;
2946 /* if we can make this a jump table */
2947 if (geniCodeJumpTable (cond, caseVals, tree))
2948 goto jumpTable; /* no need for the comparison */
2950 /* for the cases defined do */
2954 operand *compare = geniCodeLogic (cond,
2955 operandFromValue (caseVals),
2958 sprintf (buffer, "_case_%d_%d",
2959 tree->values.switchVals.swNum,
2960 (int) floatFromVal (caseVals));
2961 trueLabel = newiTempLabel (buffer);
2963 ic = newiCodeCondition (compare, trueLabel, NULL);
2965 caseVals = caseVals->next;
2970 /* if default is present then goto break else break */
2971 if (tree->values.switchVals.swDefault)
2972 sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
2974 sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
2976 falseLabel = newiTempLabel (buffer);
2977 geniCodeGoto (falseLabel);
2980 ast2iCode (tree->right);
2983 /*-----------------------------------------------------------------*/
2984 /* geniCodeInline - intermediate code for inline assembler */
2985 /*-----------------------------------------------------------------*/
2987 geniCodeInline (ast * tree)
2991 ic = newiCode (INLINEASM, NULL, NULL);
2992 IC_INLINE (ic) = tree->values.inlineasm;
2996 /*-----------------------------------------------------------------*/
2997 /* ast2iCode - creates an icodeList from an ast */
2998 /*-----------------------------------------------------------------*/
3000 ast2iCode (ast * tree)
3002 operand *left = NULL;
3003 operand *right = NULL;
3008 /* set the global variables for filename & line number */
3010 filename = tree->filename;
3012 lineno = tree->lineno;
3014 block = tree->block;
3016 scopeLevel = tree->level;
3018 if (tree->type == EX_VALUE)
3019 return operandFromValue (tree->opval.val);
3021 if (tree->type == EX_LINK)
3022 return operandFromLink (tree->opval.lnk);
3024 /* if we find a nullop */
3025 if (tree->type == EX_OP &&
3026 (tree->opval.op == NULLOP ||
3027 tree->opval.op == BLOCK))
3029 ast2iCode (tree->left);
3030 ast2iCode (tree->right);
3034 /* special cases for not evaluating */
3035 if (tree->opval.op != ':' &&
3036 tree->opval.op != '?' &&
3037 tree->opval.op != CALL &&
3038 tree->opval.op != IFX &&
3039 tree->opval.op != LABEL &&
3040 tree->opval.op != GOTO &&
3041 tree->opval.op != SWITCH &&
3042 tree->opval.op != FUNCTION &&
3043 tree->opval.op != INLINEASM)
3046 if (IS_ASSIGN_OP (tree->opval.op) ||
3047 IS_DEREF_OP (tree) ||
3048 (tree->opval.op == '&' && !tree->right) ||
3049 tree->opval.op == PTR_OP)
3052 if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3053 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3055 int olvr = lvaluereq;
3057 left = operandFromAst (tree->left);
3058 lvaluereq = olvr - 1;
3062 left = operandFromAst (tree->left);
3065 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3066 left = geniCodeRValue (left, TRUE);
3070 left = operandFromAst (tree->left);
3072 if (tree->opval.op == INC_OP ||
3073 tree->opval.op == DEC_OP)
3076 right = operandFromAst (tree->right);
3081 right = operandFromAst (tree->right);
3085 /* now depending on the type of operand */
3086 /* this will be a biggy */
3087 switch (tree->opval.op)
3090 case '[': /* array operation */
3092 sym_link *ltype = operandType (left);
3093 left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3094 right = geniCodeRValue (right, TRUE);
3097 return geniCodeArray (left, right);
3099 case '.': /* structure dereference */
3100 if (IS_PTR (operandType (left)))
3101 left = geniCodeRValue (left, TRUE);
3103 left = geniCodeRValue (left, FALSE);
3105 return geniCodeStruct (left, right, tree->lvalue);
3107 case PTR_OP: /* structure pointer dereference */
3110 pType = operandType (left);
3111 left = geniCodeRValue (left, TRUE);
3113 setOClass (pType, getSpec (operandType (left)));
3116 return geniCodeStruct (left, right, tree->lvalue);
3118 case INC_OP: /* increment operator */
3120 return geniCodePostInc (left);
3122 return geniCodePreInc (right);
3124 case DEC_OP: /* decrement operator */
3126 return geniCodePostDec (left);
3128 return geniCodePreDec (right);
3130 case '&': /* bitwise and or address of operator */
3132 { /* this is a bitwise operator */
3133 left = geniCodeRValue (left, FALSE);
3134 right = geniCodeRValue (right, FALSE);
3135 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3138 return geniCodeAddressOf (left);
3140 case '|': /* bitwise or & xor */
3142 return geniCodeBitwise (geniCodeRValue (left, FALSE),
3143 geniCodeRValue (right, FALSE),
3148 return geniCodeDivision (geniCodeRValue (left, FALSE),
3149 geniCodeRValue (right, FALSE));
3152 return geniCodeModulus (geniCodeRValue (left, FALSE),
3153 geniCodeRValue (right, FALSE));
3156 return geniCodeMultiply (geniCodeRValue (left, FALSE),
3157 geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3159 return geniCodeDerefPtr (geniCodeRValue (left, FALSE));
3163 return geniCodeSubtract (geniCodeRValue (left, FALSE),
3164 geniCodeRValue (right, FALSE));
3166 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3170 return geniCodeAdd (geniCodeRValue (left, FALSE),
3171 geniCodeRValue (right, FALSE));
3173 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
3176 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3177 geniCodeRValue (right, FALSE));
3180 return geniCodeRightShift (geniCodeRValue (left, FALSE),
3181 geniCodeRValue (right, FALSE));
3183 return geniCodeCast (operandType (left),
3184 geniCodeRValue (right, FALSE), FALSE);
3190 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3194 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3195 setOperandType (op, UCHARTYPE);
3206 return geniCodeLogic (geniCodeRValue (left, FALSE),
3207 geniCodeRValue (right, FALSE),
3210 return geniCodeConditional (tree);
3213 return operandFromLit (getSize (tree->right->ftype));
3217 sym_link *rtype = operandType (right);
3218 sym_link *ltype = operandType (left);
3219 if (IS_PTR (rtype) && IS_ITEMP (right)
3220 && right->isaddr && checkType (rtype->next, ltype) == 1)
3221 right = geniCodeRValue (right, TRUE);
3223 right = geniCodeRValue (right, FALSE);
3225 geniCodeAssign (left, right, 0);
3230 geniCodeAssign (left,
3231 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3233 geniCodeRValue (right, FALSE),FALSE), 0);
3237 geniCodeAssign (left,
3238 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3240 geniCodeRValue (right, FALSE)), 0);
3243 geniCodeAssign (left,
3244 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3246 geniCodeRValue (right, FALSE)), 0);
3249 sym_link *rtype = operandType (right);
3250 sym_link *ltype = operandType (left);
3251 if (IS_PTR (rtype) && IS_ITEMP (right)
3252 && right->isaddr && checkType (rtype->next, ltype) == 1)
3253 right = geniCodeRValue (right, TRUE);
3255 right = geniCodeRValue (right, FALSE);
3258 return geniCodeAssign (left,
3259 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3265 sym_link *rtype = operandType (right);
3266 sym_link *ltype = operandType (left);
3267 if (IS_PTR (rtype) && IS_ITEMP (right)
3268 && right->isaddr && checkType (rtype->next, ltype) == 1)
3270 right = geniCodeRValue (right, TRUE);
3274 right = geniCodeRValue (right, FALSE);
3277 geniCodeAssign (left,
3278 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3284 geniCodeAssign (left,
3285 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3287 geniCodeRValue (right, FALSE)), 0);
3290 geniCodeAssign (left,
3291 geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3293 geniCodeRValue (right, FALSE)), 0);
3296 geniCodeAssign (left,
3297 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3299 geniCodeRValue (right, FALSE),
3301 operandType (left)), 0);
3304 geniCodeAssign (left,
3305 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3307 geniCodeRValue (right, FALSE),
3309 operandType (left)), 0);
3312 geniCodeAssign (left,
3313 geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3315 geniCodeRValue (right, FALSE),
3317 operandType (left)), 0);
3319 return geniCodeRValue (right, FALSE);
3322 return geniCodeCall (ast2iCode (tree->left),
3325 geniCodeLabel (ast2iCode (tree->left)->operand.symOperand);
3326 return ast2iCode (tree->right);
3329 geniCodeGoto (ast2iCode (tree->left)->operand.symOperand);
3330 return ast2iCode (tree->right);
3333 geniCodeFunctionBody (tree);
3337 geniCodeReturn (right);
3345 geniCodeSwitch (tree);
3349 geniCodeInline (tree);
3356 /*-----------------------------------------------------------------*/
3357 /* reverseICChain - gets from the list and creates a linkedlist */
3358 /*-----------------------------------------------------------------*/
3365 while ((loop = getSet (&iCodeChain)))
3377 /*-----------------------------------------------------------------*/
3378 /* iCodeFromAst - given an ast will convert it to iCode */
3379 /*-----------------------------------------------------------------*/
3381 iCodeFromAst (ast * tree)
3383 returnLabel = newiTempLabel ("_return");
3384 entryLabel = newiTempLabel ("_entry");
3386 return reverseiCChain ();