1 /*-------------------------------------------------------------------------
3 SDCCicode.c - intermediate code generation etc.
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
29 /*-----------------------------------------------------------------*/
30 /* global variables */
32 set *iCodeChain = NULL;
42 symbol *returnLabel; /* function return label */
43 symbol *entryLabel; /* function entry label */
45 /*-----------------------------------------------------------------*/
46 /* forward definition of some functions */
47 operand *geniCodeDivision (operand *, operand *);
48 operand *geniCodeAssign (operand *, operand *, int);
49 operand *geniCodeArray (operand *, operand *,int);
50 operand *geniCodeArray2Ptr (operand *);
51 operand *geniCodeRValue (operand *, bool);
52 operand *geniCodeDerefPtr (operand *,int);
53 int isLvaluereq(int lvl);
55 #define PRINTFUNC(x) void x (FILE *of, iCode *ic, char *s)
56 /* forward definition of ic print functions */
57 PRINTFUNC (picGetValueAtAddr);
58 PRINTFUNC (picSetValueAtAddr);
59 PRINTFUNC (picAddrOf);
60 PRINTFUNC (picGeneric);
61 PRINTFUNC (picGenericOne);
63 PRINTFUNC (picAssign);
67 PRINTFUNC (picJumpTable);
68 PRINTFUNC (picInline);
69 PRINTFUNC (picReceive);
71 iCodeTable codeTable[] =
73 {'!', "not", picGenericOne, NULL},
74 {'~', "~", picGenericOne, NULL},
75 {RRC, "rrc", picGenericOne, NULL},
76 {RLC, "rlc", picGenericOne, NULL},
77 {GETHBIT, "ghbit", picGenericOne, NULL},
78 {UNARYMINUS, "-", picGenericOne, NULL},
79 {IPUSH, "push", picGenericOne, NULL},
80 {IPOP, "pop", picGenericOne, NULL},
81 {CALL, "call", picGenericOne, NULL},
82 {PCALL, "pcall", picGenericOne, NULL},
83 {FUNCTION, "proc", picGenericOne, NULL},
84 {ENDFUNCTION, "eproc", picGenericOne, NULL},
85 {RETURN, "ret", picGenericOne, NULL},
86 {'+', "+", picGeneric, NULL},
87 {'-', "-", picGeneric, NULL},
88 {'*', "*", picGeneric, NULL},
89 {'/', "/", picGeneric, NULL},
90 {'%', "%", picGeneric, NULL},
91 {'>', ">", picGeneric, NULL},
92 {'<', "<", picGeneric, NULL},
93 {LE_OP, "<=", picGeneric, NULL},
94 {GE_OP, ">=", picGeneric, NULL},
95 {EQ_OP, "==", picGeneric, NULL},
96 {NE_OP, "!=", picGeneric, NULL},
97 {AND_OP, "&&", picGeneric, NULL},
98 {OR_OP, "||", picGeneric, NULL},
99 {'^', "^", picGeneric, NULL},
100 {'|', "|", picGeneric, NULL},
101 {BITWISEAND, "&", picGeneric, NULL},
102 {LEFT_OP, "<<", picGeneric, NULL},
103 {RIGHT_OP, ">>", picGeneric, NULL},
104 {GET_VALUE_AT_ADDRESS, "@", picGetValueAtAddr, NULL},
105 {ADDRESS_OF, "&", picAddrOf, NULL},
106 {CAST, "<>", picCast, NULL},
107 {'=', ":=", picAssign, NULL},
108 {LABEL, "", picLabel, NULL},
109 {GOTO, "", picGoto, NULL},
110 {JUMPTABLE, "jtab", picJumpTable, NULL},
111 {IFX, "if", picIfx, NULL},
112 {INLINEASM, "", picInline, NULL},
113 {RECEIVE, "recv", picReceive, NULL},
114 {SEND, "send", picGenericOne, NULL},
115 {ARRAYINIT, "arrayInit", picGenericOne, NULL},
118 /*-----------------------------------------------------------------*/
119 /* checkConstantRange: check a constant against the type */
120 /*-----------------------------------------------------------------*/
122 /* pedantic=0: allmost anything is allowed as long as the absolute
123 value is within the bit range of the type, and -1 is treated as
124 0xf..f for unsigned types (e.g. in assign)
125 pedantic=1: -1==-1, not allowed for unsigned types (e.g. in compare)
126 pedantic>1: "char c=200" is not allowed (evaluates to -56)
129 void checkConstantRange(sym_link *ltype, value *val, char *msg,
136 max = pow ((double)2.0, (double)bitsForType(ltype));
138 if (SPEC_LONG(val->type)) {
139 if (SPEC_USIGN(val->type)) {
140 v=SPEC_CVAL(val->type).v_ulong;
142 v=SPEC_CVAL(val->type).v_long;
145 if (SPEC_USIGN(val->type)) {
146 v=SPEC_CVAL(val->type).v_uint;
148 v=SPEC_CVAL(val->type).v_int;
154 // this could be a good idea
155 if (options.pedantic)
159 if (SPEC_NOUN(ltype)==FLOAT) {
164 if (!SPEC_USIGN(val->type) && v<0) {
166 if (SPEC_USIGN(ltype) && (pedantic>1)) {
172 // if very pedantic: "char c=200" is not allowed
173 if (pedantic>1 && !SPEC_USIGN(ltype)) {
174 max = max/2 + negative;
181 #if 0 // temporary disabled, leaving the warning as a reminder
183 sprintf (message, "for %s %s in %s",
184 SPEC_USIGN(ltype) ? "unsigned" : "signed",
185 nounName(ltype), msg);
186 werror (W_CONST_RANGE, message);
194 /*-----------------------------------------------------------------*/
195 /* operandName - returns the name of the operand */
196 /*-----------------------------------------------------------------*/
198 printOperand (operand * op, FILE * file)
215 opetype = getSpec (operandType (op));
216 if (SPEC_NOUN (opetype) == V_FLOAT)
217 fprintf (file, "%g {", SPEC_CVAL (opetype).v_float);
219 fprintf (file, "0x%x {", (int) floatFromVal (op->operand.valOperand));
220 printTypeChain (operandType (op), file);
227 fprintf (file, "%s [k%d lr%d:%d so:%d]{ ia%d re%d rm%d nos%d ru%d dp%d}", /*{ar%d rm%d ru%d p%d a%d u%d i%d au%d k%d ks%d}" , */
228 (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name),
230 OP_LIVEFROM (op), OP_LIVETO (op),
231 OP_SYMBOL (op)->stack,
232 op->isaddr, OP_SYMBOL (op)->isreqv,
233 OP_SYMBOL (op)->remat,OP_SYMBOL(op)->noSpilLoc,
234 OP_SYMBOL(op)->ruonly,OP_SYMBOL(op)->dptr
238 printTypeChain (operandType (op), file);
239 if (SPIL_LOC (op) && IS_ITEMP (op))
240 fprintf (file, "}{ sir@ %s", SPIL_LOC (op)->rname);
245 /* if assigned to registers */
246 if (OP_SYMBOL (op)->nRegs)
248 if (OP_SYMBOL (op)->isspilt)
250 if (!OP_SYMBOL (op)->remat)
251 if (OP_SYMBOL (op)->usl.spillLoc)
252 fprintf (file, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
253 OP_SYMBOL (op)->usl.spillLoc->rname :
254 OP_SYMBOL (op)->usl.spillLoc->name));
256 fprintf (file, "[err]");
258 fprintf (file, "[remat]");
264 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
265 fprintf (file, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i]));
270 fprintf (file, "%s", (OP_SYMBOL (op)->rname[0] ?
271 OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name));
272 /* if assigned to registers */
273 if (OP_SYMBOL (op)->nRegs && !OP_SYMBOL (op)->isspilt)
277 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
278 fprintf (file, "%s ", (OP_SYMBOL (op)->regs[i] ?
279 OP_SYMBOL (op)->regs[i]->name :
288 printTypeChain (op->operand.typeOperand, file);
294 fprintf (file, "\n");
299 /*-----------------------------------------------------------------*/
300 /* print functions */
301 /*-----------------------------------------------------------------*/
302 PRINTFUNC (picGetValueAtAddr)
305 printOperand (IC_RESULT (ic), of);
308 printOperand (IC_LEFT (ic), of);
314 PRINTFUNC (picSetValueAtAddr)
318 printOperand (IC_LEFT (ic), of);
319 fprintf (of, "] = ");
320 printOperand (IC_RIGHT (ic), of);
324 PRINTFUNC (picAddrOf)
327 printOperand (IC_RESULT (ic), of);
328 if (IS_ITEMP (IC_LEFT (ic)))
331 fprintf (of, " = &[");
332 printOperand (IC_LEFT (ic), of);
335 if (IS_ITEMP (IC_LEFT (ic)))
336 fprintf (of, " offsetAdd ");
339 printOperand (IC_RIGHT (ic), of);
341 if (IS_ITEMP (IC_LEFT (ic)))
347 PRINTFUNC (picJumpTable)
352 fprintf (of, "%s\t", s);
353 printOperand (IC_JTCOND (ic), of);
355 for (sym = setFirstItem (IC_JTLABELS (ic)); sym;
356 sym = setNextItem (IC_JTLABELS (ic)))
357 fprintf (of, "\t\t\t%s\n", sym->name);
360 PRINTFUNC (picGeneric)
363 printOperand (IC_RESULT (ic), of);
365 printOperand (IC_LEFT (ic), of);
366 fprintf (of, " %s ", s);
367 printOperand (IC_RIGHT (ic), of);
371 PRINTFUNC (picGenericOne)
376 printOperand (IC_RESULT (ic), of);
382 fprintf (of, "%s ", s);
383 printOperand (IC_LEFT (ic), of);
386 if (!IC_RESULT (ic) && !IC_LEFT (ic))
389 if (ic->op == SEND || ic->op == RECEIVE) {
390 fprintf(of,"{argreg = %d}",ic->argreg);
398 printOperand (IC_RESULT (ic), of);
400 printOperand (IC_LEFT (ic), of);
401 printOperand (IC_RIGHT (ic), of);
406 PRINTFUNC (picAssign)
410 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
413 printOperand (IC_RESULT (ic), of);
415 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
418 fprintf (of, " %s ", s);
419 printOperand (IC_RIGHT (ic), of);
426 fprintf (of, " %s($%d) :\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
432 fprintf (of, " goto %s($%d)\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
439 printOperand (IC_COND (ic), of);
442 fprintf (of, " == 0 goto %s($%d)\n", IC_FALSE (ic)->name, IC_FALSE (ic)->key);
445 fprintf (of, " != 0 goto %s($%d)\n", IC_TRUE (ic)->name, IC_TRUE (ic)->key);
447 fprintf (of, "\tzzgoto %s\n", IC_FALSE (ic)->name);
451 PRINTFUNC (picInline)
453 fprintf (of, "%s", IC_INLINE (ic));
456 PRINTFUNC (picReceive)
458 printOperand (IC_RESULT (ic), of);
459 fprintf (of, " = %s ", s);
460 printOperand (IC_LEFT (ic), of);
464 /*-----------------------------------------------------------------*/
465 /* piCode - prints one iCode */
466 /*-----------------------------------------------------------------*/
468 piCode (void *item, FILE * of)
476 icTab = getTableEntry (ic->op);
477 fprintf (stdout, "%s(%d:%d:%d:%d:%d)\t",
478 ic->filename, ic->lineno,
479 ic->seq, ic->key, ic->depth, ic->supportRtn);
480 icTab->iCodePrint (of, ic, icTab->printName);
486 printiCChain(ic,stdout);
488 /*-----------------------------------------------------------------*/
489 /* printiCChain - prints intermediate code for humans */
490 /*-----------------------------------------------------------------*/
492 printiCChain (iCode * icChain, FILE * of)
499 for (loop = icChain; loop; loop = loop->next)
501 if ((icTab = getTableEntry (loop->op)))
503 fprintf (of, "%s(%d:%d:%d:%d:%d)\t",
504 loop->filename, loop->lineno,
505 loop->seq, loop->key, loop->depth, loop->supportRtn);
507 icTab->iCodePrint (of, loop, icTab->printName);
513 /*-----------------------------------------------------------------*/
514 /* newOperand - allocate, init & return a new iCode */
515 /*-----------------------------------------------------------------*/
521 op = Safe_alloc ( sizeof (operand));
527 /*-----------------------------------------------------------------*/
528 /* newiCode - create and return a new iCode entry initialised */
529 /*-----------------------------------------------------------------*/
531 newiCode (int op, operand * left, operand * right)
535 ic = Safe_alloc ( sizeof (iCode));
538 ic->filename = filename;
540 ic->level = scopeLevel;
542 ic->key = iCodeKey++;
544 IC_RIGHT (ic) = right;
549 /*-----------------------------------------------------------------*/
550 /* newiCode for conditional statements */
551 /*-----------------------------------------------------------------*/
553 newiCodeCondition (operand * condition,
559 if (IS_VOID(operandType(condition))) {
560 werror(E_VOID_VALUE_USED);
563 ic = newiCode (IFX, NULL, NULL);
564 IC_COND (ic) = condition;
565 IC_TRUE (ic) = trueLabel;
566 IC_FALSE (ic) = falseLabel;
570 /*-----------------------------------------------------------------*/
571 /* newiCodeLabelGoto - unconditional goto statement| label stmnt */
572 /*-----------------------------------------------------------------*/
574 newiCodeLabelGoto (int op, symbol * label)
578 ic = newiCode (op, NULL, NULL);
580 ic->argLabel.label = label;
582 IC_RIGHT (ic) = NULL;
583 IC_RESULT (ic) = NULL;
587 /*-----------------------------------------------------------------*/
588 /* newiTemp - allocate & return a newItemp Variable */
589 /*-----------------------------------------------------------------*/
596 sprintf (buffer, "%s", s);
598 sprintf (buffer, "iTemp%d", iTempNum++);
599 itmp = newSymbol (buffer, 1);
600 strcpy (itmp->rname, itmp->name);
606 /*-----------------------------------------------------------------*/
607 /* newiTempLabel - creates a temp variable label */
608 /*-----------------------------------------------------------------*/
610 newiTempLabel (char *s)
614 /* check if this alredy exists */
615 if (s && (itmplbl = findSym (LabelTab, NULL, s)))
619 itmplbl = newSymbol (s, 1);
622 sprintf (buffer, "iTempLbl%d", iTempLblNum++);
623 itmplbl = newSymbol (buffer, 1);
628 itmplbl->key = labelKey++;
629 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
633 /*-----------------------------------------------------------------*/
634 /* newiTempPreheaderLabel - creates a new preheader label */
635 /*-----------------------------------------------------------------*/
637 newiTempPreheaderLabel ()
641 sprintf (buffer, "preHeaderLbl%d", iTempLblNum++);
642 itmplbl = newSymbol (buffer, 1);
646 itmplbl->key = labelKey++;
647 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
652 /*-----------------------------------------------------------------*/
653 /* initiCode - initialises some iCode related stuff */
654 /*-----------------------------------------------------------------*/
661 /*-----------------------------------------------------------------*/
662 /* copyiCode - make a copy of the iCode given */
663 /*-----------------------------------------------------------------*/
665 copyiCode (iCode * ic)
667 iCode *nic = newiCode (ic->op, NULL, NULL);
669 nic->lineno = ic->lineno;
670 nic->filename = ic->filename;
671 nic->block = ic->block;
672 nic->level = ic->level;
673 nic->parmBytes = ic->parmBytes;
675 /* deal with the special cases first */
679 IC_COND (nic) = operandFromOperand (IC_COND (ic));
680 IC_TRUE (nic) = IC_TRUE (ic);
681 IC_FALSE (nic) = IC_FALSE (ic);
685 IC_JTCOND (nic) = operandFromOperand (IC_JTCOND (ic));
686 IC_JTLABELS (nic) = IC_JTLABELS (ic);
691 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
692 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
696 IC_INLINE (nic) = IC_INLINE (ic);
700 IC_ARRAYILIST(nic) = IC_ARRAYILIST(ic);
704 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
705 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
706 IC_RIGHT (nic) = operandFromOperand (IC_RIGHT (ic));
712 /*-----------------------------------------------------------------*/
713 /* getTableEntry - gets the table entry for the given operator */
714 /*-----------------------------------------------------------------*/
716 getTableEntry (int oper)
720 for (i = 0; i < (sizeof (codeTable) / sizeof (iCodeTable)); i++)
721 if (oper == codeTable[i].icode)
722 return &codeTable[i];
727 /*-----------------------------------------------------------------*/
728 /* newiTempOperand - new intermediate temp operand */
729 /*-----------------------------------------------------------------*/
731 newiTempOperand (sym_link * type, char throwType)
734 operand *op = newOperand ();
738 itmp = newiTemp (NULL);
740 etype = getSpec (type);
742 if (IS_LITERAL (etype))
745 /* copy the type information */
747 itmp->etype = getSpec (itmp->type = (throwType ? type :
748 copyLinkChain (type)));
749 if (IS_LITERAL (itmp->etype))
751 SPEC_SCLS (itmp->etype) = S_REGISTER;
752 SPEC_OCLS (itmp->etype) = reg;
755 op->operand.symOperand = itmp;
756 op->key = itmp->key = ++operandKey;
760 /*-----------------------------------------------------------------*/
761 /* operandType - returns the type chain for an operand */
762 /*-----------------------------------------------------------------*/
764 operandType (operand * op)
766 /* depending on type of operand */
771 return op->operand.valOperand->type;
774 return op->operand.symOperand->type;
777 return op->operand.typeOperand;
779 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
780 " operand type not known ");
781 assert (0); /* should never come here */
782 /* Just to keep the compiler happy */
783 return (sym_link *) 0;
787 /*-----------------------------------------------------------------*/
788 /* isParamterToCall - will return 1 if op is a parameter to args */
789 /*-----------------------------------------------------------------*/
791 isParameterToCall (value * args, operand * op)
798 isSymbolEqual (op->operand.symOperand, tval->sym))
805 /*-----------------------------------------------------------------*/
806 /* isOperandGlobal - return 1 if operand is a global variable */
807 /*-----------------------------------------------------------------*/
809 isOperandGlobal (operand * op)
817 if (op->type == SYMBOL &&
818 (op->operand.symOperand->level == 0 ||
819 IS_STATIC (op->operand.symOperand->etype) ||
820 IS_EXTERN (op->operand.symOperand->etype))
827 /*-----------------------------------------------------------------*/
828 /* isOperandVolatile - return 1 if the operand is volatile */
829 /*-----------------------------------------------------------------*/
831 isOperandVolatile (operand * op, bool chkTemp)
836 if (IS_ITEMP (op) && !chkTemp)
839 opetype = getSpec (optype = operandType (op));
841 if (IS_PTR (optype) && DCL_PTR_VOLATILE (optype))
844 if (IS_VOLATILE (opetype))
849 /*-----------------------------------------------------------------*/
850 /* isOperandLiteral - returns 1 if an operand contains a literal */
851 /*-----------------------------------------------------------------*/
853 isOperandLiteral (operand * op)
860 opetype = getSpec (operandType (op));
862 if (IS_LITERAL (opetype))
868 /*-----------------------------------------------------------------*/
869 /* isOperandInFarSpace - will return true if operand is in farSpace */
870 /*-----------------------------------------------------------------*/
872 isOperandInFarSpace (operand * op)
882 if (!IS_TRUE_SYMOP (op))
885 etype = SPIL_LOC (op)->etype;
891 etype = getSpec (operandType (op));
893 return (IN_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
896 /*------------------------------------------------------------------*/
897 /* isOperandInDirSpace - will return true if operand is in dirSpace */
898 /*------------------------------------------------------------------*/
900 isOperandInDirSpace (operand * op)
910 if (!IS_TRUE_SYMOP (op))
913 etype = SPIL_LOC (op)->etype;
919 etype = getSpec (operandType (op));
921 return (IN_DIRSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
924 /*--------------------------------------------------------------------*/
925 /* isOperandInCodeSpace - will return true if operand is in codeSpace */
926 /*--------------------------------------------------------------------*/
928 isOperandInCodeSpace (operand * op)
938 etype = getSpec (operandType (op));
940 if (!IS_TRUE_SYMOP (op))
943 etype = SPIL_LOC (op)->etype;
949 etype = getSpec (operandType (op));
951 return (IN_CODESPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
954 /*-----------------------------------------------------------------*/
955 /* isOperandOnStack - will return true if operand is on stack */
956 /*-----------------------------------------------------------------*/
958 isOperandOnStack (operand * op)
968 etype = getSpec (operandType (op));
969 if (IN_STACK (etype) ||
970 OP_SYMBOL(op)->onStack ||
971 (SPIL_LOC(op) && SPIL_LOC(op)->onStack))
977 /*-----------------------------------------------------------------*/
978 /* operandLitValue - literal value of an operand */
979 /*-----------------------------------------------------------------*/
981 operandLitValue (operand * op)
983 assert (isOperandLiteral (op));
985 return floatFromVal (op->operand.valOperand);
988 /*-----------------------------------------------------------------*/
989 /* getBuiltInParms - returns parameters to a builtin functions */
990 /*-----------------------------------------------------------------*/
991 iCode *getBuiltinParms (iCode *ic, int *pcount, operand **parms)
996 /* builtin functions uses only SEND for parameters */
997 while (ic->op != CALL) {
998 assert(ic->op == SEND && ic->builtinSEND);
999 ic->generated = 1; /* mark the icode as generated */
1000 parms[*pcount] = IC_LEFT(ic);
1006 /* make sure this is a builtin function call */
1007 assert(IS_SYMOP(IC_LEFT(ic)));
1008 ftype = operandType(IC_LEFT(ic));
1009 assert(IFFUNC_ISBUILTIN(ftype));
1013 /*-----------------------------------------------------------------*/
1014 /* operandOperation - perforoms operations on operands */
1015 /*-----------------------------------------------------------------*/
1017 operandOperation (operand * left, operand * right,
1018 int op, sym_link * type)
1020 sym_link *let , *ret=NULL;
1021 operand *retval = (operand *) 0;
1023 assert (isOperandLiteral (left));
1024 let = getSpec(operandType(left));
1026 assert (isOperandLiteral (right));
1027 ret = getSpec(operandType(left));
1033 retval = operandFromValue (valCastLiteral (type,
1034 operandLitValue (left) +
1035 operandLitValue (right)));
1038 retval = operandFromValue (valCastLiteral (type,
1039 operandLitValue (left) -
1040 operandLitValue (right)));
1043 retval = operandFromValue (valCastLiteral (type,
1044 operandLitValue (left) *
1045 operandLitValue (right)));
1048 if ((unsigned long) operandLitValue (right) == 0)
1050 werror (E_DIVIDE_BY_ZERO);
1055 retval = operandFromValue (valCastLiteral (type,
1056 operandLitValue (left) /
1057 operandLitValue (right)));
1060 if ((unsigned long) operandLitValue (right) == 0) {
1061 werror (E_DIVIDE_BY_ZERO);
1065 retval = operandFromLit ((SPEC_USIGN(let) ?
1066 (unsigned long) operandLitValue (left) :
1067 (long) operandLitValue (left)) %
1069 (unsigned long) operandLitValue (right) :
1070 (long) operandLitValue (right)));
1074 retval = operandFromLit ((SPEC_USIGN(let) ?
1075 (unsigned long) operandLitValue (left) :
1076 (long) operandLitValue (left)) <<
1078 (unsigned long) operandLitValue (right) :
1079 (long) operandLitValue (right)));
1082 double lval = operandLitValue(left), rval = operandLitValue(right);
1084 switch ((SPEC_USIGN(let) ? 2 : 0) + (SPEC_USIGN(ret) ? 1 : 0))
1086 case 0: // left=unsigned right=unsigned
1087 res=(unsigned long)lval >> (unsigned long)rval;
1089 case 1: // left=unsigned right=signed
1090 res=(unsigned long)lval >> (signed long)rval;
1092 case 2: // left=signed right=unsigned
1093 res=(signed long)lval >> (unsigned long)rval;
1095 case 3: // left=signed right=signed
1096 res=(signed long)lval >> (signed long)rval;
1099 retval = operandFromLit (res);
1103 retval = operandFromLit (operandLitValue (left) ==
1104 operandLitValue (right));
1107 retval = operandFromLit (operandLitValue (left) <
1108 operandLitValue (right));
1111 retval = operandFromLit (operandLitValue (left) <=
1112 operandLitValue (right));
1115 retval = operandFromLit (operandLitValue (left) !=
1116 operandLitValue (right));
1119 retval = operandFromLit (operandLitValue (left) >
1120 operandLitValue (right));
1123 retval = operandFromLit (operandLitValue (left) >=
1124 operandLitValue (right));
1127 retval = operandFromLit ((long)operandLitValue(left) &
1128 (long)operandLitValue(right));
1131 retval = operandFromLit ((long)operandLitValue (left) |
1132 (long)operandLitValue (right));
1135 retval = operandFromLit ((long)operandLitValue (left) ^
1136 (long)operandLitValue (right));
1139 retval = operandFromLit (operandLitValue (left) &&
1140 operandLitValue (right));
1143 retval = operandFromLit (operandLitValue (left) ||
1144 operandLitValue (right));
1148 long i = (long) operandLitValue (left);
1150 retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
1156 long i = (long) operandLitValue (left);
1158 retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
1164 retval = operandFromLit (-1 * operandLitValue (left));
1168 retval = operandFromLit (~((long) operandLitValue (left)));
1172 retval = operandFromLit (!operandLitValue (left));
1176 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1177 " operandOperation invalid operator ");
1185 /*-----------------------------------------------------------------*/
1186 /* isOperandEqual - compares two operand & return 1 if they r = */
1187 /*-----------------------------------------------------------------*/
1189 isOperandEqual (operand * left, operand * right)
1191 /* if the pointers are equal then they are equal */
1195 /* if either of them null then false */
1196 if (!left || !right)
1199 if (left->type != right->type)
1202 if (IS_SYMOP (left) && IS_SYMOP (right))
1203 return left->key == right->key;
1205 /* if types are the same */
1209 return isSymbolEqual (left->operand.symOperand,
1210 right->operand.symOperand);
1212 return (floatFromVal (left->operand.valOperand) ==
1213 floatFromVal (right->operand.valOperand));
1215 if (compareType (left->operand.typeOperand,
1216 right->operand.typeOperand) == 1)
1223 /*-------------------------------------------------------------------*/
1224 /* isiCodeEqual - compares two iCodes are equal, returns true if yes */
1225 /*-------------------------------------------------------------------*/
1227 isiCodeEqual (iCode * left, iCode * right)
1229 /* if the same pointer */
1233 /* if either of them null */
1234 if (!left || !right)
1237 /* if operand are the same */
1238 if (left->op == right->op)
1241 /* compare all the elements depending on type */
1242 if (left->op != IFX)
1244 if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
1246 if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
1252 if (!isOperandEqual (IC_COND (left), IC_COND (right)))
1254 if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
1256 if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
1265 /*-----------------------------------------------------------------*/
1266 /* newiTempFromOp - create a temp Operand with same attributes */
1267 /*-----------------------------------------------------------------*/
1269 newiTempFromOp (operand * op)
1279 nop = newiTempOperand (operandType (op), TRUE);
1280 nop->isaddr = op->isaddr;
1281 nop->isvolatile = op->isvolatile;
1282 nop->isGlobal = op->isGlobal;
1283 nop->isLiteral = op->isLiteral;
1284 nop->usesDefs = op->usesDefs;
1285 nop->isParm = op->isParm;
1289 /*-----------------------------------------------------------------*/
1290 /* operand from operand - creates an operand holder for the type */
1291 /*-----------------------------------------------------------------*/
1293 operandFromOperand (operand * op)
1299 nop = newOperand ();
1300 nop->type = op->type;
1301 nop->isaddr = op->isaddr;
1303 nop->isvolatile = op->isvolatile;
1304 nop->isGlobal = op->isGlobal;
1305 nop->isLiteral = op->isLiteral;
1306 nop->usesDefs = op->usesDefs;
1307 nop->isParm = op->isParm;
1312 nop->operand.symOperand = op->operand.symOperand;
1315 nop->operand.valOperand = op->operand.valOperand;
1318 nop->operand.typeOperand = op->operand.typeOperand;
1325 /*-----------------------------------------------------------------*/
1326 /* opFromOpWithDU - makes a copy of the operand and DU chains */
1327 /*-----------------------------------------------------------------*/
1329 opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
1331 operand *nop = operandFromOperand (op);
1333 if (nop->type == SYMBOL)
1335 OP_SYMBOL (nop)->defs = bitVectCopy (defs);
1336 OP_SYMBOL (nop)->uses = bitVectCopy (uses);
1342 /*-----------------------------------------------------------------*/
1343 /* operandFromSymbol - creates an operand from a symbol */
1344 /*-----------------------------------------------------------------*/
1346 operandFromSymbol (symbol * sym)
1351 /* if the symbol's type is a literal */
1352 /* then it is an enumerator type */
1353 if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
1354 return operandFromValue (valFromType (sym->etype));
1357 sym->key = ++operandKey;
1359 /* if this an implicit variable, means struct/union */
1360 /* member so just return it */
1361 if (sym->implicit || IS_FUNC (sym->type))
1365 op->operand.symOperand = sym;
1367 op->isvolatile = isOperandVolatile (op, TRUE);
1368 op->isGlobal = isOperandGlobal (op);
1372 /* under the following conditions create a
1373 register equivalent for a local symbol */
1374 if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
1375 (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
1376 (!(options.model == MODEL_FLAT24)) ) &&
1377 options.stackAuto == 0)
1380 if (!IS_AGGREGATE (sym->type) && /* not an aggregate */
1381 !IS_FUNC (sym->type) && /* not a function */
1382 !sym->_isparm && /* not a parameter */
1383 sym->level && /* is a local variable */
1384 !sym->addrtaken && /* whose address has not been taken */
1385 !sym->reqv && /* does not already have a reg equivalence */
1386 !IS_VOLATILE (sym->etype) && /* not declared as volatile */
1387 !IS_STATIC (sym->etype) && /* and not declared static */
1388 !sym->islbl && /* not a label */
1389 ok && /* farspace check */
1390 !IS_BITVAR (sym->etype) /* not a bit variable */
1394 /* we will use it after all optimizations
1395 and before liveRange calculation */
1396 sym->reqv = newiTempOperand (sym->type, 0);
1397 sym->reqv->key = sym->key;
1398 OP_SYMBOL (sym->reqv)->key = sym->key;
1399 OP_SYMBOL (sym->reqv)->isreqv = 1;
1400 OP_SYMBOL (sym->reqv)->islocal = 1;
1401 OP_SYMBOL (sym->reqv)->onStack = sym->onStack;
1402 SPIL_LOC (sym->reqv) = sym;
1405 if (!IS_AGGREGATE (sym->type))
1409 op->operand.symOperand = sym;
1412 op->isvolatile = isOperandVolatile (op, TRUE);
1413 op->isGlobal = isOperandGlobal (op);
1414 op->isPtr = IS_PTR (operandType (op));
1415 op->isParm = sym->_isparm;
1420 /* itemp = &[_symbol] */
1422 ic = newiCode (ADDRESS_OF, newOperand (), NULL);
1423 IC_LEFT (ic)->type = SYMBOL;
1424 IC_LEFT (ic)->operand.symOperand = sym;
1425 IC_LEFT (ic)->key = sym->key;
1426 (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
1427 (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
1428 IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
1431 IC_RESULT (ic) = newiTempOperand (sym->type, 0);
1432 if (IS_ARRAY (sym->type))
1434 IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
1435 IC_RESULT (ic)->isaddr = 0;
1438 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
1442 return IC_RESULT (ic);
1445 /*-----------------------------------------------------------------*/
1446 /* operandFromValue - creates an operand from value */
1447 /*-----------------------------------------------------------------*/
1449 operandFromValue (value * val)
1453 /* if this is a symbol then do the symbol thing */
1455 return operandFromSymbol (val->sym);
1457 /* this is not a symbol */
1460 op->operand.valOperand = val;
1461 op->isLiteral = isOperandLiteral (op);
1465 /*-----------------------------------------------------------------*/
1466 /* operandFromLink - operand from typeChain */
1467 /*-----------------------------------------------------------------*/
1469 operandFromLink (sym_link * type)
1473 /* operand from sym_link */
1479 op->operand.typeOperand = copyLinkChain (type);
1483 /*-----------------------------------------------------------------*/
1484 /* operandFromLit - makes an operand from a literal value */
1485 /*-----------------------------------------------------------------*/
1487 operandFromLit (double i)
1489 return operandFromValue (valueFromLit (i));
1492 /*-----------------------------------------------------------------*/
1493 /* operandFromAst - creates an operand from an ast */
1494 /*-----------------------------------------------------------------*/
1496 operandFromAst (ast * tree,int lvl)
1502 /* depending on type do */
1506 return ast2iCode (tree,lvl+1);
1510 return operandFromValue (tree->opval.val);
1514 return operandFromLink (tree->opval.lnk);
1518 /* Just to keep the comiler happy */
1519 return (operand *) 0;
1522 /*-----------------------------------------------------------------*/
1523 /* setOperandType - sets the operand's type to the given type */
1524 /*-----------------------------------------------------------------*/
1526 setOperandType (operand * op, sym_link * type)
1528 /* depending on the type of operand */
1533 op->operand.valOperand->etype =
1534 getSpec (op->operand.valOperand->type =
1535 copyLinkChain (type));
1539 if (op->operand.symOperand->isitmp)
1540 op->operand.symOperand->etype =
1541 getSpec (op->operand.symOperand->type =
1542 copyLinkChain (type));
1544 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1545 "attempt to modify type of source");
1549 op->operand.typeOperand = copyLinkChain (type);
1554 /*-----------------------------------------------------------------*/
1555 /* Get size in byte of ptr need to access an array */
1556 /*-----------------------------------------------------------------*/
1558 getArraySizePtr (operand * op)
1560 sym_link *ltype = operandType(op);
1564 int size = getSize(ltype);
1565 return(IS_GENPTR(ltype)?(size-1):size);
1570 sym_link *letype = getSpec(ltype);
1571 switch (PTR_TYPE (SPEC_OCLS (letype)))
1583 return (GPTRSIZE-1);
1592 /*-----------------------------------------------------------------*/
1593 /* perform "usual unary conversions" */
1594 /*-----------------------------------------------------------------*/
1596 usualUnaryConversions (operand * op)
1598 if (IS_INTEGRAL (operandType (op)))
1600 if (getSize (operandType (op)) < (unsigned int) INTSIZE)
1603 return geniCodeCast (INTTYPE, op, TRUE);
1609 /*-----------------------------------------------------------------*/
1610 /* perform "usual binary conversions" */
1611 /*-----------------------------------------------------------------*/
1613 usualBinaryConversions (operand ** op1, operand ** op2)
1616 sym_link *rtype = operandType (*op2);
1617 sym_link *ltype = operandType (*op1);
1619 ctype = computeType (ltype, rtype);
1621 *op1 = geniCodeCast (ctype, *op1, TRUE);
1622 *op2 = geniCodeCast (ctype, *op2, TRUE);
1627 /*-----------------------------------------------------------------*/
1628 /* geniCodeValueAtAddress - generate intermeditate code for value */
1630 /*-----------------------------------------------------------------*/
1632 geniCodeRValue (operand * op, bool force)
1635 sym_link *type = operandType (op);
1636 sym_link *etype = getSpec (type);
1638 /* if this is an array & already */
1639 /* an address then return this */
1640 if (IS_AGGREGATE (type) ||
1641 (IS_PTR (type) && !force && !op->isaddr))
1642 return operandFromOperand (op);
1644 /* if this is not an address then must be */
1645 /* rvalue already so return this one */
1649 /* if this is not a temp symbol then */
1650 if (!IS_ITEMP (op) &&
1652 !IN_FARSPACE (SPEC_OCLS (etype)))
1654 op = operandFromOperand (op);
1659 if (IS_SPEC (type) &&
1660 IS_TRUE_SYMOP (op) &&
1661 (!IN_FARSPACE (SPEC_OCLS (etype)) ||
1662 (options.model == MODEL_FLAT24) ))
1664 op = operandFromOperand (op);
1669 ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1670 if (IS_PTR (type) && op->isaddr && force)
1673 type = copyLinkChain (type);
1675 IC_RESULT (ic) = newiTempOperand (type, 1);
1676 IC_RESULT (ic)->isaddr = 0;
1678 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1682 return IC_RESULT (ic);
1685 /*-----------------------------------------------------------------*/
1686 /* geniCodeCast - changes the value from one type to another */
1687 /*-----------------------------------------------------------------*/
1689 geniCodeCast (sym_link * type, operand * op, bool implicit)
1693 sym_link *opetype = getSpec (optype = operandType (op));
1697 /* one of them has size zero then error */
1698 if (IS_VOID (optype))
1700 werror (E_CAST_ZERO);
1704 /* if the operand is already the desired type then do nothing */
1705 if (compareType (type, optype) == 1)
1708 /* if this is a literal then just change the type & return */
1709 if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1710 return operandFromValue (valCastLiteral (type,
1711 operandLitValue (op)));
1713 /* if casting to/from pointers, do some checking */
1714 if (IS_PTR(type)) { // to a pointer
1715 if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer
1716 if (IS_INTEGRAL(optype)) {
1717 // maybe this is NULL, than it's ok.
1718 if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
1719 if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80 && IS_GENPTR(type)) {
1720 // no way to set the storage
1721 if (IS_LITERAL(optype)) {
1722 werror(E_LITERAL_GENERIC);
1725 werror(E_NONPTR2_GENPTR);
1728 } else if (implicit) {
1729 werror(W_INTEGRAL2PTR_NOCAST);
1734 // shouldn't do that with float, array or structure unless to void
1735 if (!IS_VOID(getSpec(type)) &&
1736 !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1737 werror(E_INCOMPAT_TYPES);
1741 } else { // from a pointer to a pointer
1742 if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80) {
1743 // if not a pointer to a function
1744 if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1745 if (implicit) { // if not to generic, they have to match
1746 if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
1747 werror(E_INCOMPAT_PTYPES);
1754 } else { // to a non pointer
1755 if (IS_PTR(optype)) { // from a pointer
1756 if (implicit) { // sneaky
1757 if (IS_INTEGRAL(type)) {
1758 werror(W_PTR2INTEGRAL_NOCAST);
1760 } else { // shouldn't do that with float, array or structure
1761 werror(E_INCOMPAT_TYPES);
1768 printFromToType (optype, type);
1771 /* if they are the same size create an assignment */
1772 if (getSize (type) == getSize (optype) &&
1773 !IS_BITFIELD (type) &&
1775 !IS_FLOAT (optype) &&
1776 ((IS_SPEC (type) && IS_SPEC (optype)) ||
1777 (!IS_SPEC (type) && !IS_SPEC (optype))))
1780 ic = newiCode ('=', NULL, op);
1781 IC_RESULT (ic) = newiTempOperand (type, 0);
1782 SPIL_LOC (IC_RESULT (ic)) =
1783 (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
1784 IC_RESULT (ic)->isaddr = 0;
1788 ic = newiCode (CAST, operandFromLink (type),
1789 geniCodeRValue (op, FALSE));
1791 IC_RESULT (ic) = newiTempOperand (type, 0);
1794 /* preserve the storage class & output class */
1795 /* of the original variable */
1796 restype = getSpec (operandType (IC_RESULT (ic)));
1797 if (!IS_LITERAL(opetype))
1798 SPEC_SCLS (restype) = SPEC_SCLS (opetype);
1799 SPEC_OCLS (restype) = SPEC_OCLS (opetype);
1802 return IC_RESULT (ic);
1805 /*-----------------------------------------------------------------*/
1806 /* geniCodeLabel - will create a Label */
1807 /*-----------------------------------------------------------------*/
1809 geniCodeLabel (symbol * label)
1813 ic = newiCodeLabelGoto (LABEL, label);
1817 /*-----------------------------------------------------------------*/
1818 /* geniCodeGoto - will create a Goto */
1819 /*-----------------------------------------------------------------*/
1821 geniCodeGoto (symbol * label)
1825 ic = newiCodeLabelGoto (GOTO, label);
1829 /*-----------------------------------------------------------------*/
1830 /* geniCodeMultiply - gen intermediate code for multiplication */
1831 /*-----------------------------------------------------------------*/
1833 geniCodeMultiply (operand * left, operand * right,int resultIsInt)
1840 /* if they are both literal then we know the result */
1841 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1842 return operandFromValue (valMult (left->operand.valOperand,
1843 right->operand.valOperand));
1845 if (IS_LITERAL(retype)) {
1846 p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
1849 resType = usualBinaryConversions (&left, &right);
1851 rtype = operandType (right);
1852 retype = getSpec (rtype);
1853 ltype = operandType (left);
1854 letype = getSpec (ltype);
1858 SPEC_NOUN(getSpec(resType))=V_INT;
1861 /* if the right is a literal & power of 2 */
1862 /* then make it a left shift */
1863 /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
1864 efficient in most cases than 2 bytes result = 2 bytes << literal
1865 if port has 1 byte muldiv */
1866 if (p2 && !IS_FLOAT (letype) &&
1867 !((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
1868 (port->support.muldiv == 1)))
1870 if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
1872 /* LEFT_OP need same size for left and result, */
1873 left = geniCodeCast (resType, left, TRUE);
1874 ltype = operandType (left);
1876 ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
1880 ic = newiCode ('*', left, right); /* normal multiplication */
1881 /* if the size left or right > 1 then support routine */
1882 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1886 IC_RESULT (ic) = newiTempOperand (resType, 1);
1889 return IC_RESULT (ic);
1892 /*-----------------------------------------------------------------*/
1893 /* geniCodeDivision - gen intermediate code for division */
1894 /*-----------------------------------------------------------------*/
1896 geniCodeDivision (operand * left, operand * right)
1901 sym_link *rtype = operandType (right);
1902 sym_link *retype = getSpec (rtype);
1903 sym_link *ltype = operandType (left);
1904 sym_link *letype = getSpec (ltype);
1906 resType = usualBinaryConversions (&left, &right);
1908 /* if the right is a literal & power of 2
1909 and left is unsigned then make it a
1911 if (IS_LITERAL (retype) &&
1912 !IS_FLOAT (letype) &&
1913 SPEC_USIGN(letype) &&
1914 (p2 = powof2 ((unsigned long)
1915 floatFromVal (right->operand.valOperand)))) {
1916 ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
1920 ic = newiCode ('/', left, right); /* normal division */
1921 /* if the size left or right > 1 then support routine */
1922 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1925 IC_RESULT (ic) = newiTempOperand (resType, 0);
1928 return IC_RESULT (ic);
1930 /*-----------------------------------------------------------------*/
1931 /* geniCodeModulus - gen intermediate code for modulus */
1932 /*-----------------------------------------------------------------*/
1934 geniCodeModulus (operand * left, operand * right)
1940 /* if they are both literal then we know the result */
1941 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1942 return operandFromValue (valMod (left->operand.valOperand,
1943 right->operand.valOperand));
1945 resType = usualBinaryConversions (&left, &right);
1947 /* now they are the same size */
1948 ic = newiCode ('%', left, right);
1950 /* if the size left or right > 1 then support routine */
1951 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1953 IC_RESULT (ic) = newiTempOperand (resType, 0);
1956 return IC_RESULT (ic);
1959 /*-----------------------------------------------------------------*/
1960 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
1961 /*-----------------------------------------------------------------*/
1963 geniCodePtrPtrSubtract (operand * left, operand * right)
1969 /* if they are both literals then */
1970 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1972 result = operandFromValue (valMinus (left->operand.valOperand,
1973 right->operand.valOperand));
1977 ic = newiCode ('-', left, right);
1979 IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
1983 if (IS_VOID(ltype->next) || IS_VOID(rtype->next)) {
1987 // should we really do this? is this ANSI?
1988 return geniCodeDivision (result,
1989 operandFromLit (getSize (ltype->next)));
1992 /*-----------------------------------------------------------------*/
1993 /* geniCodeSubtract - generates code for subtraction */
1994 /*-----------------------------------------------------------------*/
1996 geniCodeSubtract (operand * left, operand * right)
2003 /* if they both pointers then */
2004 if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
2005 (IS_PTR (rtype) || IS_ARRAY (rtype)))
2006 return geniCodePtrPtrSubtract (left, right);
2008 /* if they are both literal then we know the result */
2009 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2010 && left->isLiteral && right->isLiteral)
2011 return operandFromValue (valMinus (left->operand.valOperand,
2012 right->operand.valOperand));
2014 /* if left is an array or pointer */
2015 if (IS_PTR (ltype) || IS_ARRAY (ltype))
2017 isarray = left->isaddr;
2018 right = geniCodeMultiply (right,
2019 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2020 resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
2023 { /* make them the same size */
2024 resType = usualBinaryConversions (&left, &right);
2027 ic = newiCode ('-', left, right);
2029 IC_RESULT (ic) = newiTempOperand (resType, 1);
2030 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2032 /* if left or right is a float */
2033 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2037 return IC_RESULT (ic);
2040 /*-----------------------------------------------------------------*/
2041 /* geniCodeAdd - generates iCode for addition */
2042 /*-----------------------------------------------------------------*/
2044 geniCodeAdd (operand * left, operand * right, int lvl)
2053 /* if left is an array then array access */
2054 if (IS_ARRAY (ltype))
2055 return geniCodeArray (left, right,lvl);
2058 /* if the right side is LITERAL zero */
2059 /* return the left side */
2060 if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
2063 /* if left is literal zero return right */
2064 if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
2067 /* if left is a pointer then size */
2068 if (IS_PTR (ltype) || IS_ARRAY(ltype))
2070 isarray = left->isaddr;
2071 // there is no need to multiply with 1
2072 if (getSize(ltype->next)!=1) {
2073 size = operandFromLit (getSize (ltype->next));
2074 right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
2076 resType = copyLinkChain (ltype);
2079 { // make them the same size
2080 resType = usualBinaryConversions (&left, &right);
2083 /* if they are both literals then we know */
2084 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2085 && left->isLiteral && right->isLiteral)
2086 return operandFromValue (valPlus (valFromType (letype),
2087 valFromType (retype)));
2089 ic = newiCode ('+', left, right);
2091 IC_RESULT (ic) = newiTempOperand (resType, 1);
2092 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2094 /* if left or right is a float then support
2096 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2101 return IC_RESULT (ic);
2105 /*-----------------------------------------------------------------*/
2106 /* aggrToPtr - changes an aggregate to pointer to an aggregate */
2107 /*-----------------------------------------------------------------*/
2109 aggrToPtr (sym_link * type, bool force)
2115 if (IS_PTR (type) && !force)
2118 etype = getSpec (type);
2122 /* if the output class is generic */
2123 if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER)
2124 DCL_PTR_CONST (ptype) = port->mem.code_ro;
2126 /* if the variable was declared a constant */
2127 /* then the pointer points to a constant */
2128 if (IS_CONSTANT (etype))
2129 DCL_PTR_CONST (ptype) = 1;
2131 /* the variable was volatile then pointer to volatile */
2132 if (IS_VOLATILE (etype))
2133 DCL_PTR_VOLATILE (ptype) = 1;
2137 /*-----------------------------------------------------------------*/
2138 /* geniCodeArray2Ptr - array to pointer */
2139 /*-----------------------------------------------------------------*/
2141 geniCodeArray2Ptr (operand * op)
2143 sym_link *optype = operandType (op);
2144 sym_link *opetype = getSpec (optype);
2146 /* set the pointer depending on the storage class */
2147 if ((DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2148 DCL_PTR_CONST (optype) = port->mem.code_ro;
2151 /* if the variable was declared a constant */
2152 /* then the pointer points to a constant */
2153 if (IS_CONSTANT (opetype))
2154 DCL_PTR_CONST (optype) = 1;
2156 /* the variable was volatile then pointer to volatile */
2157 if (IS_VOLATILE (opetype))
2158 DCL_PTR_VOLATILE (optype) = 1;
2164 /*-----------------------------------------------------------------*/
2165 /* geniCodeArray - array access */
2166 /*-----------------------------------------------------------------*/
2168 geniCodeArray (operand * left, operand * right,int lvl)
2171 sym_link *ltype = operandType (left);
2175 if (IS_PTR (ltype->next) && left->isaddr)
2177 left = geniCodeRValue (left, FALSE);
2179 return geniCodeDerefPtr (geniCodeAdd (left, right, lvl), lvl);
2182 right = geniCodeMultiply (right,
2183 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2185 /* we can check for limits here */
2186 if (isOperandLiteral (right) &&
2189 (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2191 werror (E_ARRAY_BOUND);
2192 right = operandFromLit (0);
2195 ic = newiCode ('+', left, right);
2197 IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2198 !IS_AGGREGATE (ltype->next) &&
2199 !IS_PTR (ltype->next))
2200 ? ltype : ltype->next), 0);
2202 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
2204 return IC_RESULT (ic);
2207 /*-----------------------------------------------------------------*/
2208 /* geniCodeStruct - generates intermediate code for structres */
2209 /*-----------------------------------------------------------------*/
2211 geniCodeStruct (operand * left, operand * right, bool islval)
2214 sym_link *type = operandType (left);
2215 sym_link *etype = getSpec (type);
2217 symbol *element = getStructElement (SPEC_STRUCT (etype),
2218 right->operand.symOperand);
2220 /* add the offset */
2221 ic = newiCode ('+', left, operandFromLit (element->offset));
2223 IC_RESULT (ic) = newiTempOperand (element->type, 0);
2225 /* preserve the storage & output class of the struct */
2226 /* as well as the volatile attribute */
2227 retype = getSpec (operandType (IC_RESULT (ic)));
2228 SPEC_SCLS (retype) = SPEC_SCLS (etype);
2229 SPEC_OCLS (retype) = SPEC_OCLS (etype);
2230 SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2232 if (IS_PTR (element->type))
2233 setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2235 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2239 return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2242 /*-----------------------------------------------------------------*/
2243 /* geniCodePostInc - generate int code for Post increment */
2244 /*-----------------------------------------------------------------*/
2246 geniCodePostInc (operand * op)
2250 sym_link *optype = operandType (op);
2252 operand *rv = (IS_ITEMP (op) ?
2253 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2255 sym_link *rvtype = operandType (rv);
2258 /* if this is not an address we have trouble */
2261 werror (E_LVALUE_REQUIRED, "++");
2265 rOp = newiTempOperand (rvtype, 0);
2266 OP_SYMBOL(rOp)->noSpilLoc = 1;
2269 OP_SYMBOL(rv)->noSpilLoc = 1;
2271 geniCodeAssign (rOp, rv, 0);
2273 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2274 if (IS_FLOAT (rvtype))
2275 ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2277 ic = newiCode ('+', rv, operandFromLit (size));
2279 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2282 geniCodeAssign (op, result, 0);
2288 /*-----------------------------------------------------------------*/
2289 /* geniCodePreInc - generate code for preIncrement */
2290 /*-----------------------------------------------------------------*/
2292 geniCodePreInc (operand * op)
2295 sym_link *optype = operandType (op);
2296 operand *rop = (IS_ITEMP (op) ?
2297 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2299 sym_link *roptype = operandType (rop);
2305 werror (E_LVALUE_REQUIRED, "++");
2310 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2311 if (IS_FLOAT (roptype))
2312 ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2314 ic = newiCode ('+', rop, operandFromLit (size));
2315 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2319 return geniCodeAssign (op, result, 0);
2322 /*-----------------------------------------------------------------*/
2323 /* geniCodePostDec - generates code for Post decrement */
2324 /*-----------------------------------------------------------------*/
2326 geniCodePostDec (operand * op)
2330 sym_link *optype = operandType (op);
2332 operand *rv = (IS_ITEMP (op) ?
2333 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2335 sym_link *rvtype = operandType (rv);
2338 /* if this is not an address we have trouble */
2341 werror (E_LVALUE_REQUIRED, "--");
2345 rOp = newiTempOperand (rvtype, 0);
2346 OP_SYMBOL(rOp)->noSpilLoc = 1;
2349 OP_SYMBOL(rv)->noSpilLoc = 1;
2351 geniCodeAssign (rOp, rv, 0);
2353 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2354 if (IS_FLOAT (rvtype))
2355 ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2357 ic = newiCode ('-', rv, operandFromLit (size));
2359 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2362 geniCodeAssign (op, result, 0);
2368 /*-----------------------------------------------------------------*/
2369 /* geniCodePreDec - generate code for pre decrement */
2370 /*-----------------------------------------------------------------*/
2372 geniCodePreDec (operand * op)
2375 sym_link *optype = operandType (op);
2376 operand *rop = (IS_ITEMP (op) ?
2377 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2379 sym_link *roptype = operandType (rop);
2385 werror (E_LVALUE_REQUIRED, "--");
2390 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2391 if (IS_FLOAT (roptype))
2392 ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2394 ic = newiCode ('-', rop, operandFromLit (size));
2395 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2399 return geniCodeAssign (op, result, 0);
2403 /*-----------------------------------------------------------------*/
2404 /* geniCodeBitwise - gen int code for bitWise operators */
2405 /*-----------------------------------------------------------------*/
2407 geniCodeBitwise (operand * left, operand * right,
2408 int oper, sym_link * resType)
2412 left = geniCodeCast (resType, left, TRUE);
2413 right = geniCodeCast (resType, right, TRUE);
2415 ic = newiCode (oper, left, right);
2416 IC_RESULT (ic) = newiTempOperand (resType, 0);
2419 return IC_RESULT (ic);
2422 /*-----------------------------------------------------------------*/
2423 /* geniCodeAddressOf - gens icode for '&' address of operator */
2424 /*-----------------------------------------------------------------*/
2426 geniCodeAddressOf (operand * op)
2430 sym_link *optype = operandType (op);
2431 sym_link *opetype = getSpec (optype);
2433 /* lvalue check already done in decorateType */
2434 /* this must be a lvalue */
2435 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2436 /* werror (E_LVALUE_REQUIRED,"&"); */
2441 p->class = DECLARATOR;
2443 /* set the pointer depending on the storage class */
2444 if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2445 DCL_PTR_CONST (p) = port->mem.code_ro;
2447 /* make sure we preserve the const & volatile */
2448 if (IS_CONSTANT (opetype))
2449 DCL_PTR_CONST (p) = 1;
2451 if (IS_VOLATILE (opetype))
2452 DCL_PTR_VOLATILE (p) = 1;
2454 p->next = copyLinkChain (optype);
2456 /* if already a temp */
2459 setOperandType (op, p);
2464 /* other wise make this of the type coming in */
2465 ic = newiCode (ADDRESS_OF, op, NULL);
2466 IC_RESULT (ic) = newiTempOperand (p, 1);
2467 IC_RESULT (ic)->isaddr = 0;
2469 return IC_RESULT (ic);
2471 /*-----------------------------------------------------------------*/
2472 /* setOClass - sets the output class depending on the pointer type */
2473 /*-----------------------------------------------------------------*/
2475 setOClass (sym_link * ptr, sym_link * spec)
2477 switch (DCL_TYPE (ptr))
2480 SPEC_OCLS (spec) = data;
2484 SPEC_OCLS (spec) = generic;
2488 SPEC_OCLS (spec) = xdata;
2492 SPEC_OCLS (spec) = code;
2496 SPEC_OCLS (spec) = idata;
2500 SPEC_OCLS (spec) = xstack;
2504 SPEC_OCLS (spec) = eeprom;
2513 /*-----------------------------------------------------------------*/
2514 /* geniCodeDerefPtr - dereference pointer with '*' */
2515 /*-----------------------------------------------------------------*/
2517 geniCodeDerefPtr (operand * op,int lvl)
2519 sym_link *rtype, *retype;
2520 sym_link *optype = operandType (op);
2522 /* if this is a pointer then generate the rvalue */
2523 if (IS_PTR (optype))
2525 if (IS_TRUE_SYMOP (op))
2528 op = geniCodeRValue (op, TRUE);
2531 op = geniCodeRValue (op, TRUE);
2534 /* now get rid of the pointer part */
2535 if (isLvaluereq(lvl) && IS_ITEMP (op))
2537 retype = getSpec (rtype = copyLinkChain (optype));
2541 retype = getSpec (rtype = copyLinkChain (optype->next));
2544 /* if this is a pointer then outputclass needs 2b updated */
2545 if (IS_PTR (optype))
2546 setOClass (optype, retype);
2548 op->isGptr = IS_GENPTR (optype);
2550 /* if the pointer was declared as a constant */
2551 /* then we cannot allow assignment to the derefed */
2552 if (IS_PTR_CONST (optype))
2553 SPEC_CONST (retype) = 1;
2555 op->isaddr = (IS_PTR (rtype) ||
2556 IS_STRUCT (rtype) ||
2561 if (!isLvaluereq(lvl))
2562 op = geniCodeRValue (op, TRUE);
2564 setOperandType (op, rtype);
2569 /*-----------------------------------------------------------------*/
2570 /* geniCodeUnaryMinus - does a unary minus of the operand */
2571 /*-----------------------------------------------------------------*/
2573 geniCodeUnaryMinus (operand * op)
2576 sym_link *optype = operandType (op);
2578 if (IS_LITERAL (optype))
2579 return operandFromLit (-floatFromVal (op->operand.valOperand));
2581 ic = newiCode (UNARYMINUS, op, NULL);
2582 IC_RESULT (ic) = newiTempOperand (optype, 0);
2584 return IC_RESULT (ic);
2587 /*-----------------------------------------------------------------*/
2588 /* geniCodeLeftShift - gen i code for left shift */
2589 /*-----------------------------------------------------------------*/
2591 geniCodeLeftShift (operand * left, operand * right)
2595 ic = newiCode (LEFT_OP, left, right);
2596 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2598 return IC_RESULT (ic);
2601 /*-----------------------------------------------------------------*/
2602 /* geniCodeRightShift - gen i code for right shift */
2603 /*-----------------------------------------------------------------*/
2605 geniCodeRightShift (operand * left, operand * right)
2609 ic = newiCode (RIGHT_OP, left, right);
2610 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2612 return IC_RESULT (ic);
2615 /*-----------------------------------------------------------------*/
2616 /* geniCodeLogic- logic code */
2617 /*-----------------------------------------------------------------*/
2619 geniCodeLogic (operand * left, operand * right, int op)
2623 sym_link *rtype = operandType (right);
2624 sym_link *ltype = operandType (left);
2626 /* left is integral type and right is literal then
2627 check if the literal value is within bounds */
2628 if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2630 checkConstantRange(ltype,
2631 OP_VALUE(right), "compare operation", 1);
2634 ctype = usualBinaryConversions (&left, &right);
2636 ic = newiCode (op, left, right);
2637 IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2639 /* if comparing float
2640 and not a '==' || '!=' || '&&' || '||' (these
2642 if (IS_FLOAT(ctype) &&
2650 return IC_RESULT (ic);
2653 /*-----------------------------------------------------------------*/
2654 /* geniCodeUnary - for a a generic unary operation */
2655 /*-----------------------------------------------------------------*/
2657 geniCodeUnary (operand * op, int oper)
2659 iCode *ic = newiCode (oper, op, NULL);
2661 IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2663 return IC_RESULT (ic);
2666 /*-----------------------------------------------------------------*/
2667 /* geniCodeConditional - geniCode for '?' ':' operation */
2668 /*-----------------------------------------------------------------*/
2670 geniCodeConditional (ast * tree,int lvl)
2673 symbol *falseLabel = newiTempLabel (NULL);
2674 symbol *exitLabel = newiTempLabel (NULL);
2675 operand *cond = ast2iCode (tree->left,lvl+1);
2676 operand *true, *false, *result;
2678 ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
2682 true = ast2iCode (tree->right->left,lvl+1);
2684 /* move the value to a new Operand */
2685 result = newiTempOperand (tree->right->ftype, 0);
2686 geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
2688 /* generate an unconditional goto */
2689 geniCodeGoto (exitLabel);
2691 /* now for the right side */
2692 geniCodeLabel (falseLabel);
2694 false = ast2iCode (tree->right->right,lvl+1);
2695 geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
2697 /* create the exit label */
2698 geniCodeLabel (exitLabel);
2703 /*-----------------------------------------------------------------*/
2704 /* geniCodeAssign - generate code for assignment */
2705 /*-----------------------------------------------------------------*/
2707 geniCodeAssign (operand * left, operand * right, int nosupdate)
2710 sym_link *ltype = operandType (left);
2711 sym_link *rtype = operandType (right);
2713 if (!left->isaddr && !IS_ITEMP (left))
2715 werror (E_LVALUE_REQUIRED, "assignment");
2719 /* left is integral type and right is literal then
2720 check if the literal value is within bounds */
2721 if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
2723 checkConstantRange(ltype,
2724 OP_VALUE(right), "= operation", 0);
2727 /* if the left & right type don't exactly match */
2728 /* if pointer set then make sure the check is
2729 done with the type & not the pointer */
2730 /* then cast rights type to left */
2732 /* first check the type for pointer assignement */
2733 if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
2734 compareType (ltype, rtype) <= 0)
2736 if (compareType (ltype->next, rtype) < 0)
2737 right = geniCodeCast (ltype->next, right, TRUE);
2739 else if (compareType (ltype, rtype) < 0)
2740 right = geniCodeCast (ltype, right, TRUE);
2742 /* if left is a true symbol & ! volatile
2743 create an assignment to temporary for
2744 the right & then assign this temporary
2745 to the symbol this is SSA . isn't it simple
2746 and folks have published mountains of paper on it */
2747 if (IS_TRUE_SYMOP (left) &&
2748 !isOperandVolatile (left, FALSE) &&
2749 isOperandGlobal (left))
2753 if (IS_TRUE_SYMOP (right))
2754 sym = OP_SYMBOL (right);
2755 ic = newiCode ('=', NULL, right);
2756 IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
2757 SPIL_LOC (right) = sym;
2761 ic = newiCode ('=', NULL, right);
2762 IC_RESULT (ic) = left;
2765 /* if left isgptr flag is set then support
2766 routine will be required */
2770 ic->nosupdate = nosupdate;
2774 /*-----------------------------------------------------------------*/
2775 /* geniCodeSEParms - generate code for side effecting fcalls */
2776 /*-----------------------------------------------------------------*/
2778 geniCodeSEParms (ast * parms,int lvl)
2783 if (parms->type == EX_OP && parms->opval.op == PARAM)
2785 geniCodeSEParms (parms->left,lvl);
2786 geniCodeSEParms (parms->right,lvl);
2790 /* hack don't like this but too lazy to think of
2792 if (IS_ADDRESS_OF_OP (parms))
2793 parms->left->lvalue = 1;
2795 if (IS_CAST_OP (parms) &&
2796 IS_PTR (parms->ftype) &&
2797 IS_ADDRESS_OF_OP (parms->right))
2798 parms->right->left->lvalue = 1;
2800 parms->opval.oprnd =
2801 geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2803 parms->type = EX_OPERAND;
2804 AST_ARGREG(parms) = parms->etype ? SPEC_ARGREG(parms->etype) :
2805 SPEC_ARGREG(parms->ftype);
2808 /*-----------------------------------------------------------------*/
2809 /* geniCodeParms - generates parameters */
2810 /*-----------------------------------------------------------------*/
2812 geniCodeParms (ast * parms, value *argVals, int *stack,
2813 sym_link * fetype, symbol * func,int lvl)
2821 if (argVals==NULL) {
2823 argVals=FUNC_ARGS(func->type);
2826 /* if this is a param node then do the left & right */
2827 if (parms->type == EX_OP && parms->opval.op == PARAM)
2829 argVals=geniCodeParms (parms->left, argVals, stack, fetype, func,lvl);
2830 argVals=geniCodeParms (parms->right, argVals, stack, fetype, func,lvl);
2834 /* get the parameter value */
2835 if (parms->type == EX_OPERAND)
2836 pval = parms->opval.oprnd;
2839 /* maybe this else should go away ?? */
2840 /* hack don't like this but too lazy to think of
2842 if (IS_ADDRESS_OF_OP (parms))
2843 parms->left->lvalue = 1;
2845 if (IS_CAST_OP (parms) &&
2846 IS_PTR (parms->ftype) &&
2847 IS_ADDRESS_OF_OP (parms->right))
2848 parms->right->left->lvalue = 1;
2850 pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2853 /* if register parm then make it a send */
2854 if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(func->type)) ||
2855 IFFUNC_ISBUILTIN(func->type))
2857 ic = newiCode (SEND, pval, NULL);
2858 ic->argreg = SPEC_ARGREG(parms->etype);
2859 ic->builtinSEND = FUNC_ISBUILTIN(func->type);
2864 /* now decide whether to push or assign */
2865 if (!(options.stackAuto || IFFUNC_ISREENT (func->type)))
2869 operand *top = operandFromSymbol (argVals->sym);
2870 /* clear useDef and other bitVectors */
2871 OP_USES (top) = OP_DEFS (top) = OP_SYMBOL(top)->clashes = NULL;
2872 geniCodeAssign (top, pval, 1);
2876 sym_link *p = operandType (pval);
2878 ic = newiCode (IPUSH, pval, NULL);
2880 /* update the stack adjustment */
2881 *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2886 argVals=argVals->next;
2890 /*-----------------------------------------------------------------*/
2891 /* geniCodeCall - generates temp code for calling */
2892 /*-----------------------------------------------------------------*/
2894 geniCodeCall (operand * left, ast * parms,int lvl)
2898 sym_link *type, *etype;
2901 if (!IS_FUNC(OP_SYMBOL(left)->type) &&
2902 !IS_CODEPTR(OP_SYMBOL(left)->type)) {
2903 werror (E_FUNCTION_EXPECTED);
2907 /* take care of parameters with side-effecting
2908 function calls in them, this is required to take care
2909 of overlaying function parameters */
2910 geniCodeSEParms (parms,lvl);
2912 /* first the parameters */
2913 geniCodeParms (parms, NULL, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
2915 /* now call : if symbol then pcall */
2916 if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
2917 ic = newiCode (PCALL, left, NULL);
2919 ic = newiCode (CALL, left, NULL);
2922 type = copyLinkChain (operandType (left)->next);
2923 etype = getSpec (type);
2924 SPEC_EXTR (etype) = 0;
2925 IC_RESULT (ic) = result = newiTempOperand (type, 1);
2929 /* stack adjustment after call */
2930 ic->parmBytes = stack;
2935 /*-----------------------------------------------------------------*/
2936 /* geniCodeReceive - generate intermediate code for "receive" */
2937 /*-----------------------------------------------------------------*/
2939 geniCodeReceive (value * args)
2941 /* for all arguments that are passed in registers */
2945 if (IS_REGPARM (args->etype))
2947 operand *opr = operandFromValue (args);
2949 symbol *sym = OP_SYMBOL (opr);
2952 /* we will use it after all optimizations
2953 and before liveRange calculation */
2954 if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
2957 if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
2958 options.stackAuto == 0 &&
2959 (!(options.model == MODEL_FLAT24)) )
2964 opl = newiTempOperand (args->type, 0);
2966 sym->reqv->key = sym->key;
2967 OP_SYMBOL (sym->reqv)->key = sym->key;
2968 OP_SYMBOL (sym->reqv)->isreqv = 1;
2969 OP_SYMBOL (sym->reqv)->islocal = 0;
2970 SPIL_LOC (sym->reqv) = sym;
2974 ic = newiCode (RECEIVE, NULL, NULL);
2975 ic->argreg = SPEC_ARGREG(args->etype);
2977 currFunc->recvSize = getSize (sym->type);
2980 IC_RESULT (ic) = opr;
2988 /*-----------------------------------------------------------------*/
2989 /* geniCodeFunctionBody - create the function body */
2990 /*-----------------------------------------------------------------*/
2992 geniCodeFunctionBody (ast * tree,int lvl)
2999 /* reset the auto generation */
3005 func = ast2iCode (tree->left,lvl+1);
3006 fetype = getSpec (operandType (func));
3008 savelineno = lineno;
3009 lineno = OP_SYMBOL (func)->lineDef;
3010 /* create an entry label */
3011 geniCodeLabel (entryLabel);
3012 lineno = savelineno;
3014 /* create a proc icode */
3015 ic = newiCode (FUNCTION, func, NULL);
3016 lineno=ic->lineno = OP_SYMBOL (func)->lineDef;
3020 /* for all parameters that are passed
3021 on registers add a "receive" */
3022 geniCodeReceive (tree->values.args);
3024 /* generate code for the body */
3025 ast2iCode (tree->right,lvl+1);
3027 /* create a label for return */
3028 geniCodeLabel (returnLabel);
3030 /* now generate the end proc */
3031 ic = newiCode (ENDFUNCTION, func, NULL);
3036 /*-----------------------------------------------------------------*/
3037 /* geniCodeReturn - gen icode for 'return' statement */
3038 /*-----------------------------------------------------------------*/
3040 geniCodeReturn (operand * op)
3044 /* if the operand is present force an rvalue */
3046 op = geniCodeRValue (op, FALSE);
3048 ic = newiCode (RETURN, op, NULL);
3052 /*-----------------------------------------------------------------*/
3053 /* geniCodeIfx - generates code for extended if statement */
3054 /*-----------------------------------------------------------------*/
3056 geniCodeIfx (ast * tree,int lvl)
3059 operand *condition = ast2iCode (tree->left,lvl+1);
3062 /* if condition is null then exit */
3066 condition = geniCodeRValue (condition, FALSE);
3068 cetype = getSpec (operandType (condition));
3069 /* if the condition is a literal */
3070 if (IS_LITERAL (cetype))
3072 if (floatFromVal (condition->operand.valOperand))
3074 if (tree->trueLabel)
3075 geniCodeGoto (tree->trueLabel);
3081 if (tree->falseLabel)
3082 geniCodeGoto (tree->falseLabel);
3089 if (tree->trueLabel)
3091 ic = newiCodeCondition (condition,
3096 if (tree->falseLabel)
3097 geniCodeGoto (tree->falseLabel);
3101 ic = newiCodeCondition (condition,
3108 ast2iCode (tree->right,lvl+1);
3111 /*-----------------------------------------------------------------*/
3112 /* geniCodeJumpTable - tries to create a jump table for switch */
3113 /*-----------------------------------------------------------------*/
3115 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
3117 int min = 0, max = 0, t, cnt = 0;
3124 if (!tree || !caseVals)
3127 /* the criteria for creating a jump table is */
3128 /* all integer numbers between the maximum & minimum must */
3129 /* be present , the maximum value should not exceed 255 */
3130 min = max = (int) floatFromVal (vch = caseVals);
3131 sprintf (buffer, "_case_%d_%d",
3132 tree->values.switchVals.swNum,
3134 addSet (&labels, newiTempLabel (buffer));
3136 /* if there is only one case value then no need */
3137 if (!(vch = vch->next))
3142 if (((t = (int) floatFromVal (vch)) - max) != 1)
3144 sprintf (buffer, "_case_%d_%d",
3145 tree->values.switchVals.swNum,
3147 addSet (&labels, newiTempLabel (buffer));
3153 /* if the number of case statements <= 2 then */
3154 /* it is not economical to create the jump table */
3155 /* since two compares are needed for boundary conditions */
3156 if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
3159 if (tree->values.switchVals.swDefault)
3160 sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3162 sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3164 falseLabel = newiTempLabel (buffer);
3166 /* so we can create a jumptable */
3167 /* first we rule out the boundary conditions */
3168 /* if only optimization says so */
3169 if (!optimize.noJTabBoundary)
3171 sym_link *cetype = getSpec (operandType (cond));
3172 /* no need to check the lower bound if
3173 the condition is unsigned & minimum value is zero */
3174 if (!(min == 0 && SPEC_USIGN (cetype)))
3176 boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3177 ic = newiCodeCondition (boundary, falseLabel, NULL);
3181 /* now for upper bounds */
3182 boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3183 ic = newiCodeCondition (boundary, falseLabel, NULL);
3187 /* if the min is not zero then we no make it zero */
3190 cond = geniCodeSubtract (cond, operandFromLit (min));
3191 setOperandType (cond, UCHARTYPE);
3194 /* now create the jumptable */
3195 ic = newiCode (JUMPTABLE, NULL, NULL);
3196 IC_JTCOND (ic) = cond;
3197 IC_JTLABELS (ic) = labels;
3202 /*-----------------------------------------------------------------*/
3203 /* geniCodeSwitch - changes a switch to a if statement */
3204 /*-----------------------------------------------------------------*/
3206 geniCodeSwitch (ast * tree,int lvl)
3209 operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3210 value *caseVals = tree->values.switchVals.swVals;
3211 symbol *trueLabel, *falseLabel;
3213 /* if we can make this a jump table */
3214 if (geniCodeJumpTable (cond, caseVals, tree))
3215 goto jumpTable; /* no need for the comparison */
3217 /* for the cases defined do */
3221 operand *compare = geniCodeLogic (cond,
3222 operandFromValue (caseVals),
3225 sprintf (buffer, "_case_%d_%d",
3226 tree->values.switchVals.swNum,
3227 (int) floatFromVal (caseVals));
3228 trueLabel = newiTempLabel (buffer);
3230 ic = newiCodeCondition (compare, trueLabel, NULL);
3232 caseVals = caseVals->next;
3237 /* if default is present then goto break else break */
3238 if (tree->values.switchVals.swDefault)
3239 sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3241 sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3243 falseLabel = newiTempLabel (buffer);
3244 geniCodeGoto (falseLabel);
3247 ast2iCode (tree->right,lvl+1);
3250 /*-----------------------------------------------------------------*/
3251 /* geniCodeInline - intermediate code for inline assembler */
3252 /*-----------------------------------------------------------------*/
3254 geniCodeInline (ast * tree)
3258 ic = newiCode (INLINEASM, NULL, NULL);
3259 IC_INLINE (ic) = tree->values.inlineasm;
3263 /*-----------------------------------------------------------------*/
3264 /* geniCodeArrayInit - intermediate code for array initializer */
3265 /*-----------------------------------------------------------------*/
3267 geniCodeArrayInit (ast * tree, operand *array)
3271 if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3272 ic = newiCode (ARRAYINIT, array, NULL);
3273 IC_ARRAYILIST (ic) = tree->values.constlist;
3275 operand *left=newOperand(), *right=newOperand();
3276 left->type=right->type=SYMBOL;
3277 OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3278 OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3279 ic = newiCode (ARRAYINIT, left, right);
3284 /*-----------------------------------------------------------------*/
3285 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
3286 /* particular case. Ie : assigning or dereferencing array or ptr */
3287 /*-----------------------------------------------------------------*/
3288 set * lvaluereqSet = NULL;
3289 typedef struct lvalItem
3296 /*-----------------------------------------------------------------*/
3297 /* addLvaluereq - add a flag for lvalreq for current ast level */
3298 /*-----------------------------------------------------------------*/
3299 void addLvaluereq(int lvl)
3301 lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3304 addSetHead(&lvaluereqSet,lpItem);
3307 /*-----------------------------------------------------------------*/
3308 /* delLvaluereq - del a flag for lvalreq for current ast level */
3309 /*-----------------------------------------------------------------*/
3313 lpItem = getSet(&lvaluereqSet);
3314 if(lpItem) Safe_free(lpItem);
3316 /*-----------------------------------------------------------------*/
3317 /* clearLvaluereq - clear lvalreq flag */
3318 /*-----------------------------------------------------------------*/
3319 void clearLvaluereq()
3322 lpItem = peekSet(lvaluereqSet);
3323 if(lpItem) lpItem->req = 0;
3325 /*-----------------------------------------------------------------*/
3326 /* getLvaluereq - get the last lvalreq level */
3327 /*-----------------------------------------------------------------*/
3328 int getLvaluereqLvl()
3331 lpItem = peekSet(lvaluereqSet);
3332 if(lpItem) return lpItem->lvl;
3335 /*-----------------------------------------------------------------*/
3336 /* isLvaluereq - is lvalreq valid for this level ? */
3337 /*-----------------------------------------------------------------*/
3338 int isLvaluereq(int lvl)
3341 lpItem = peekSet(lvaluereqSet);
3342 if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3346 /*-----------------------------------------------------------------*/
3347 /* ast2iCode - creates an icodeList from an ast */
3348 /*-----------------------------------------------------------------*/
3350 ast2iCode (ast * tree,int lvl)
3352 operand *left = NULL;
3353 operand *right = NULL;
3357 /* set the global variables for filename & line number */
3359 filename = tree->filename;
3361 lineno = tree->lineno;
3363 block = tree->block;
3365 scopeLevel = tree->level;
3367 if (tree->type == EX_VALUE)
3368 return operandFromValue (tree->opval.val);
3370 if (tree->type == EX_LINK)
3371 return operandFromLink (tree->opval.lnk);
3373 /* if we find a nullop */
3374 if (tree->type == EX_OP &&
3375 (tree->opval.op == NULLOP ||
3376 tree->opval.op == BLOCK))
3378 ast2iCode (tree->left,lvl+1);
3379 ast2iCode (tree->right,lvl+1);
3383 /* special cases for not evaluating */
3384 if (tree->opval.op != ':' &&
3385 tree->opval.op != '?' &&
3386 tree->opval.op != CALL &&
3387 tree->opval.op != IFX &&
3388 tree->opval.op != LABEL &&
3389 tree->opval.op != GOTO &&
3390 tree->opval.op != SWITCH &&
3391 tree->opval.op != FUNCTION &&
3392 tree->opval.op != INLINEASM)
3395 if (IS_ASSIGN_OP (tree->opval.op) ||
3396 IS_DEREF_OP (tree) ||
3397 (tree->opval.op == '&' && !tree->right) ||
3398 tree->opval.op == PTR_OP)
3401 if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3402 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3405 left = operandFromAst (tree->left,lvl);
3407 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3408 left = geniCodeRValue (left, TRUE);
3412 left = operandFromAst (tree->left,lvl);
3414 if (tree->opval.op == INC_OP ||
3415 tree->opval.op == DEC_OP)
3418 right = operandFromAst (tree->right,lvl);
3423 right = operandFromAst (tree->right,lvl);
3427 /* now depending on the type of operand */
3428 /* this will be a biggy */
3429 switch (tree->opval.op)
3432 case '[': /* array operation */
3434 //sym_link *ltype = operandType (left);
3435 //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3436 left = geniCodeRValue (left, FALSE);
3437 right = geniCodeRValue (right, TRUE);
3440 return geniCodeArray (left, right,lvl);
3442 case '.': /* structure dereference */
3443 if (IS_PTR (operandType (left)))
3444 left = geniCodeRValue (left, TRUE);
3446 left = geniCodeRValue (left, FALSE);
3448 return geniCodeStruct (left, right, tree->lvalue);
3450 case PTR_OP: /* structure pointer dereference */
3453 pType = operandType (left);
3454 left = geniCodeRValue (left, TRUE);
3456 setOClass (pType, getSpec (operandType (left)));
3459 return geniCodeStruct (left, right, tree->lvalue);
3461 case INC_OP: /* increment operator */
3463 return geniCodePostInc (left);
3465 return geniCodePreInc (right);
3467 case DEC_OP: /* decrement operator */
3469 return geniCodePostDec (left);
3471 return geniCodePreDec (right);
3473 case '&': /* bitwise and or address of operator */
3475 { /* this is a bitwise operator */
3476 left = geniCodeRValue (left, FALSE);
3477 right = geniCodeRValue (right, FALSE);
3478 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3481 return geniCodeAddressOf (left);
3483 case '|': /* bitwise or & xor */
3485 return geniCodeBitwise (geniCodeRValue (left, FALSE),
3486 geniCodeRValue (right, FALSE),
3491 return geniCodeDivision (geniCodeRValue (left, FALSE),
3492 geniCodeRValue (right, FALSE));
3495 return geniCodeModulus (geniCodeRValue (left, FALSE),
3496 geniCodeRValue (right, FALSE));
3499 return geniCodeMultiply (geniCodeRValue (left, FALSE),
3500 geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3502 return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3506 return geniCodeSubtract (geniCodeRValue (left, FALSE),
3507 geniCodeRValue (right, FALSE));
3509 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3513 return geniCodeAdd (geniCodeRValue (left, FALSE),
3514 geniCodeRValue (right, FALSE),lvl);
3516 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
3519 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3520 geniCodeRValue (right, FALSE));
3523 return geniCodeRightShift (geniCodeRValue (left, FALSE),
3524 geniCodeRValue (right, FALSE));
3526 return geniCodeCast (operandType (left),
3527 geniCodeRValue (right, FALSE), FALSE);
3533 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3537 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3538 setOperandType (op, UCHARTYPE);
3549 return geniCodeLogic (geniCodeRValue (left, FALSE),
3550 geniCodeRValue (right, FALSE),
3553 return geniCodeConditional (tree,lvl);
3556 return operandFromLit (getSize (tree->right->ftype));
3560 sym_link *rtype = operandType (right);
3561 sym_link *ltype = operandType (left);
3562 if (IS_PTR (rtype) && IS_ITEMP (right)
3563 && right->isaddr && compareType (rtype->next, ltype) == 1)
3564 right = geniCodeRValue (right, TRUE);
3566 right = geniCodeRValue (right, FALSE);
3568 geniCodeAssign (left, right, 0);
3573 geniCodeAssign (left,
3574 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3576 geniCodeRValue (right, FALSE),FALSE), 0);
3580 geniCodeAssign (left,
3581 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3583 geniCodeRValue (right, FALSE)), 0);
3586 geniCodeAssign (left,
3587 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3589 geniCodeRValue (right, FALSE)), 0);
3592 sym_link *rtype = operandType (right);
3593 sym_link *ltype = operandType (left);
3594 if (IS_PTR (rtype) && IS_ITEMP (right)
3595 && right->isaddr && compareType (rtype->next, ltype) == 1)
3596 right = geniCodeRValue (right, TRUE);
3598 right = geniCodeRValue (right, FALSE);
3601 return geniCodeAssign (left,
3602 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3608 sym_link *rtype = operandType (right);
3609 sym_link *ltype = operandType (left);
3610 if (IS_PTR (rtype) && IS_ITEMP (right)
3611 && right->isaddr && compareType (rtype->next, ltype) == 1)
3613 right = geniCodeRValue (right, TRUE);
3617 right = geniCodeRValue (right, FALSE);
3620 geniCodeAssign (left,
3621 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3627 geniCodeAssign (left,
3628 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3630 geniCodeRValue (right, FALSE)), 0);
3633 geniCodeAssign (left,
3634 geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3636 geniCodeRValue (right, FALSE)), 0);
3639 geniCodeAssign (left,
3640 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3642 geniCodeRValue (right, FALSE),
3644 operandType (left)), 0);
3647 geniCodeAssign (left,
3648 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3650 geniCodeRValue (right, FALSE),
3652 operandType (left)), 0);
3655 geniCodeAssign (left,
3656 geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3658 geniCodeRValue (right, FALSE),
3660 operandType (left)), 0);
3662 return geniCodeRValue (right, FALSE);
3665 return geniCodeCall (ast2iCode (tree->left,lvl+1),
3668 geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3669 return ast2iCode (tree->right,lvl+1);
3672 geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3673 return ast2iCode (tree->right,lvl+1);
3676 geniCodeFunctionBody (tree,lvl);
3680 geniCodeReturn (right);
3684 geniCodeIfx (tree,lvl);
3688 geniCodeSwitch (tree,lvl);
3692 geniCodeInline (tree);
3696 geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
3703 /*-----------------------------------------------------------------*/
3704 /* reverseICChain - gets from the list and creates a linkedlist */
3705 /*-----------------------------------------------------------------*/
3712 while ((loop = getSet (&iCodeChain)))
3724 /*-----------------------------------------------------------------*/
3725 /* iCodeFromAst - given an ast will convert it to iCode */
3726 /*-----------------------------------------------------------------*/
3728 iCodeFromAst (ast * tree)
3730 returnLabel = newiTempLabel ("_return");
3731 entryLabel = newiTempLabel ("_entry");
3733 return reverseiCChain ();