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);
1620 *op1 = geniCodeCast (ctype, *op1, TRUE);
1621 *op2 = geniCodeCast (ctype, *op2, TRUE);
1626 /*-----------------------------------------------------------------*/
1627 /* geniCodeValueAtAddress - generate intermeditate code for value */
1629 /*-----------------------------------------------------------------*/
1631 geniCodeRValue (operand * op, bool force)
1634 sym_link *type = operandType (op);
1635 sym_link *etype = getSpec (type);
1637 /* if this is an array & already */
1638 /* an address then return this */
1639 if (IS_AGGREGATE (type) ||
1640 (IS_PTR (type) && !force && !op->isaddr))
1641 return operandFromOperand (op);
1643 /* if this is not an address then must be */
1644 /* rvalue already so return this one */
1648 /* if this is not a temp symbol then */
1649 if (!IS_ITEMP (op) &&
1651 !IN_FARSPACE (SPEC_OCLS (etype)))
1653 op = operandFromOperand (op);
1658 if (IS_SPEC (type) &&
1659 IS_TRUE_SYMOP (op) &&
1660 (!IN_FARSPACE (SPEC_OCLS (etype)) ||
1661 (options.model == MODEL_FLAT24) ))
1663 op = operandFromOperand (op);
1668 ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1669 if (IS_PTR (type) && op->isaddr && force)
1672 type = copyLinkChain (type);
1674 IC_RESULT (ic) = newiTempOperand (type, 1);
1675 IC_RESULT (ic)->isaddr = 0;
1677 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1681 return IC_RESULT (ic);
1684 /*-----------------------------------------------------------------*/
1685 /* geniCodeCast - changes the value from one type to another */
1686 /*-----------------------------------------------------------------*/
1688 geniCodeCast (sym_link * type, operand * op, bool implicit)
1692 sym_link *opetype = getSpec (optype = operandType (op));
1696 /* one of them has size zero then error */
1697 if (IS_VOID (optype))
1699 werror (E_CAST_ZERO);
1703 /* if the operand is already the desired type then do nothing */
1704 if (compareType (type, optype) == 1)
1707 /* if this is a literal then just change the type & return */
1708 if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1709 return operandFromValue (valCastLiteral (type,
1710 operandLitValue (op)));
1712 /* if casting to/from pointers, do some checking */
1713 if (IS_PTR(type)) { // to a pointer
1714 if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer
1715 if (IS_INTEGRAL(optype)) {
1716 // maybe this is NULL, than it's ok.
1717 if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
1718 if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80 && IS_GENPTR(type)) {
1719 // no way to set the storage
1720 if (IS_LITERAL(optype)) {
1721 werror(E_LITERAL_GENERIC);
1724 werror(E_NONPTR2_GENPTR);
1727 } else if (implicit) {
1728 werror(W_INTEGRAL2PTR_NOCAST);
1733 // shouldn't do that with float, array or structure unless to void
1734 if (!IS_VOID(getSpec(type)) &&
1735 !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1736 werror(E_INCOMPAT_TYPES);
1740 } else { // from a pointer to a pointer
1741 if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80) {
1742 // if not a pointer to a function
1743 if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1744 if (implicit) { // if not to generic, they have to match
1745 if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
1746 werror(E_INCOMPAT_PTYPES);
1753 } else { // to a non pointer
1754 if (IS_PTR(optype)) { // from a pointer
1755 if (implicit) { // sneaky
1756 if (IS_INTEGRAL(type)) {
1757 werror(W_PTR2INTEGRAL_NOCAST);
1759 } else { // shouldn't do that with float, array or structure
1760 werror(E_INCOMPAT_TYPES);
1767 printFromToType (optype, type);
1770 /* if they are the same size create an assignment */
1771 if (getSize (type) == getSize (optype) &&
1772 !IS_BITFIELD (type) &&
1774 !IS_FLOAT (optype) &&
1775 ((IS_SPEC (type) && IS_SPEC (optype)) ||
1776 (!IS_SPEC (type) && !IS_SPEC (optype))))
1779 ic = newiCode ('=', NULL, op);
1780 IC_RESULT (ic) = newiTempOperand (type, 0);
1781 SPIL_LOC (IC_RESULT (ic)) =
1782 (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
1783 IC_RESULT (ic)->isaddr = 0;
1787 ic = newiCode (CAST, operandFromLink (type),
1788 geniCodeRValue (op, FALSE));
1790 IC_RESULT (ic) = newiTempOperand (type, 0);
1793 /* preserve the storage class & output class */
1794 /* of the original variable */
1795 restype = getSpec (operandType (IC_RESULT (ic)));
1796 if (!IS_LITERAL(opetype))
1797 SPEC_SCLS (restype) = SPEC_SCLS (opetype);
1798 SPEC_OCLS (restype) = SPEC_OCLS (opetype);
1801 return IC_RESULT (ic);
1804 /*-----------------------------------------------------------------*/
1805 /* geniCodeLabel - will create a Label */
1806 /*-----------------------------------------------------------------*/
1808 geniCodeLabel (symbol * label)
1812 ic = newiCodeLabelGoto (LABEL, label);
1816 /*-----------------------------------------------------------------*/
1817 /* geniCodeGoto - will create a Goto */
1818 /*-----------------------------------------------------------------*/
1820 geniCodeGoto (symbol * label)
1824 ic = newiCodeLabelGoto (GOTO, label);
1828 /*-----------------------------------------------------------------*/
1829 /* geniCodeMultiply - gen intermediate code for multiplication */
1830 /*-----------------------------------------------------------------*/
1832 geniCodeMultiply (operand * left, operand * right,int resultIsInt)
1839 /* if they are both literal then we know the result */
1840 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1841 return operandFromValue (valMult (left->operand.valOperand,
1842 right->operand.valOperand));
1844 if (IS_LITERAL(retype)) {
1845 p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
1848 resType = usualBinaryConversions (&left, &right);
1850 rtype = operandType (right);
1851 retype = getSpec (rtype);
1852 ltype = operandType (left);
1853 letype = getSpec (ltype);
1857 SPEC_NOUN(getSpec(resType))=V_INT;
1860 /* if the right is a literal & power of 2 */
1861 /* then make it a left shift */
1862 /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
1863 efficient in most cases than 2 bytes result = 2 bytes << literal
1864 if port has 1 byte muldiv */
1865 if (p2 && !IS_FLOAT (letype) &&
1866 !((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
1867 (port->support.muldiv == 1)))
1869 if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
1871 /* LEFT_OP need same size for left and result, */
1872 left = geniCodeCast (resType, left, TRUE);
1873 ltype = operandType (left);
1875 ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
1879 ic = newiCode ('*', left, right); /* normal multiplication */
1880 /* if the size left or right > 1 then support routine */
1881 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1885 IC_RESULT (ic) = newiTempOperand (resType, 1);
1888 return IC_RESULT (ic);
1891 /*-----------------------------------------------------------------*/
1892 /* geniCodeDivision - gen intermediate code for division */
1893 /*-----------------------------------------------------------------*/
1895 geniCodeDivision (operand * left, operand * right)
1900 sym_link *rtype = operandType (right);
1901 sym_link *retype = getSpec (rtype);
1902 sym_link *ltype = operandType (left);
1903 sym_link *letype = getSpec (ltype);
1905 resType = usualBinaryConversions (&left, &right);
1907 /* if the right is a literal & power of 2
1908 and left is unsigned then make it a
1910 if (IS_LITERAL (retype) &&
1911 !IS_FLOAT (letype) &&
1912 SPEC_USIGN(letype) &&
1913 (p2 = powof2 ((unsigned long)
1914 floatFromVal (right->operand.valOperand)))) {
1915 ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
1919 ic = newiCode ('/', left, right); /* normal division */
1920 /* if the size left or right > 1 then support routine */
1921 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1924 IC_RESULT (ic) = newiTempOperand (resType, 0);
1927 return IC_RESULT (ic);
1929 /*-----------------------------------------------------------------*/
1930 /* geniCodeModulus - gen intermediate code for modulus */
1931 /*-----------------------------------------------------------------*/
1933 geniCodeModulus (operand * left, operand * right)
1939 /* if they are both literal then we know the result */
1940 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1941 return operandFromValue (valMod (left->operand.valOperand,
1942 right->operand.valOperand));
1944 resType = usualBinaryConversions (&left, &right);
1946 /* now they are the same size */
1947 ic = newiCode ('%', left, right);
1949 /* if the size left or right > 1 then support routine */
1950 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1952 IC_RESULT (ic) = newiTempOperand (resType, 0);
1955 return IC_RESULT (ic);
1958 /*-----------------------------------------------------------------*/
1959 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
1960 /*-----------------------------------------------------------------*/
1962 geniCodePtrPtrSubtract (operand * left, operand * right)
1968 /* if they are both literals then */
1969 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1971 result = operandFromValue (valMinus (left->operand.valOperand,
1972 right->operand.valOperand));
1976 ic = newiCode ('-', left, right);
1978 IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
1982 if (IS_VOID(ltype->next) || IS_VOID(rtype->next)) {
1986 // should we really do this? is this ANSI?
1987 return geniCodeDivision (result,
1988 operandFromLit (getSize (ltype->next)));
1991 /*-----------------------------------------------------------------*/
1992 /* geniCodeSubtract - generates code for subtraction */
1993 /*-----------------------------------------------------------------*/
1995 geniCodeSubtract (operand * left, operand * right)
2002 /* if they both pointers then */
2003 if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
2004 (IS_PTR (rtype) || IS_ARRAY (rtype)))
2005 return geniCodePtrPtrSubtract (left, right);
2007 /* if they are both literal then we know the result */
2008 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2009 && left->isLiteral && right->isLiteral)
2010 return operandFromValue (valMinus (left->operand.valOperand,
2011 right->operand.valOperand));
2013 /* if left is an array or pointer */
2014 if (IS_PTR (ltype) || IS_ARRAY (ltype))
2016 isarray = left->isaddr;
2017 right = geniCodeMultiply (right,
2018 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2019 resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
2022 { /* make them the same size */
2023 resType = usualBinaryConversions (&left, &right);
2026 ic = newiCode ('-', left, right);
2028 IC_RESULT (ic) = newiTempOperand (resType, 1);
2029 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2031 /* if left or right is a float */
2032 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2036 return IC_RESULT (ic);
2039 /*-----------------------------------------------------------------*/
2040 /* geniCodeAdd - generates iCode for addition */
2041 /*-----------------------------------------------------------------*/
2043 geniCodeAdd (operand * left, operand * right, int lvl)
2051 /* if left is an array then array access */
2052 if (IS_ARRAY (ltype))
2053 return geniCodeArray (left, right,lvl);
2055 /* if the right side is LITERAL zero */
2056 /* return the left side */
2057 if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
2060 /* if left is literal zero return right */
2061 if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
2064 /* if left is a pointer then size */
2067 isarray = left->isaddr;
2068 // there is no need to multiply with 1
2069 if (getSize(ltype->next)!=1) {
2070 size = operandFromLit (getSize (ltype->next));
2071 right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
2073 resType = copyLinkChain (ltype);
2076 { // make them the same size
2077 resType = usualBinaryConversions (&left, &right);
2080 /* if they are both literals then we know */
2081 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2082 && left->isLiteral && right->isLiteral)
2083 return operandFromValue (valPlus (valFromType (letype),
2084 valFromType (retype)));
2086 ic = newiCode ('+', left, right);
2088 IC_RESULT (ic) = newiTempOperand (resType, 1);
2089 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2091 /* if left or right is a float then support
2093 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2098 return IC_RESULT (ic);
2102 /*-----------------------------------------------------------------*/
2103 /* aggrToPtr - changes an aggregate to pointer to an aggregate */
2104 /*-----------------------------------------------------------------*/
2106 aggrToPtr (sym_link * type, bool force)
2112 if (IS_PTR (type) && !force)
2115 etype = getSpec (type);
2119 /* if the output class is generic */
2120 if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER)
2121 DCL_PTR_CONST (ptype) = port->mem.code_ro;
2123 /* if the variable was declared a constant */
2124 /* then the pointer points to a constant */
2125 if (IS_CONSTANT (etype))
2126 DCL_PTR_CONST (ptype) = 1;
2128 /* the variable was volatile then pointer to volatile */
2129 if (IS_VOLATILE (etype))
2130 DCL_PTR_VOLATILE (ptype) = 1;
2134 /*-----------------------------------------------------------------*/
2135 /* geniCodeArray2Ptr - array to pointer */
2136 /*-----------------------------------------------------------------*/
2138 geniCodeArray2Ptr (operand * op)
2140 sym_link *optype = operandType (op);
2141 sym_link *opetype = getSpec (optype);
2143 /* set the pointer depending on the storage class */
2144 if ((DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2145 DCL_PTR_CONST (optype) = port->mem.code_ro;
2148 /* if the variable was declared a constant */
2149 /* then the pointer points to a constant */
2150 if (IS_CONSTANT (opetype))
2151 DCL_PTR_CONST (optype) = 1;
2153 /* the variable was volatile then pointer to volatile */
2154 if (IS_VOLATILE (opetype))
2155 DCL_PTR_VOLATILE (optype) = 1;
2161 /*-----------------------------------------------------------------*/
2162 /* geniCodeArray - array access */
2163 /*-----------------------------------------------------------------*/
2165 geniCodeArray (operand * left, operand * right,int lvl)
2168 sym_link *ltype = operandType (left);
2172 if (IS_PTR (ltype->next) && left->isaddr)
2174 left = geniCodeRValue (left, FALSE);
2176 return geniCodeDerefPtr (geniCodeAdd (left, right, lvl), lvl);
2179 right = geniCodeMultiply (right,
2180 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2182 /* we can check for limits here */
2183 if (isOperandLiteral (right) &&
2186 (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2188 werror (E_ARRAY_BOUND);
2189 right = operandFromLit (0);
2192 ic = newiCode ('+', left, right);
2194 IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2195 !IS_AGGREGATE (ltype->next) &&
2196 !IS_PTR (ltype->next))
2197 ? ltype : ltype->next), 0);
2199 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
2201 return IC_RESULT (ic);
2204 /*-----------------------------------------------------------------*/
2205 /* geniCodeStruct - generates intermediate code for structres */
2206 /*-----------------------------------------------------------------*/
2208 geniCodeStruct (operand * left, operand * right, bool islval)
2211 sym_link *type = operandType (left);
2212 sym_link *etype = getSpec (type);
2214 symbol *element = getStructElement (SPEC_STRUCT (etype),
2215 right->operand.symOperand);
2217 /* add the offset */
2218 ic = newiCode ('+', left, operandFromLit (element->offset));
2220 IC_RESULT (ic) = newiTempOperand (element->type, 0);
2222 /* preserve the storage & output class of the struct */
2223 /* as well as the volatile attribute */
2224 retype = getSpec (operandType (IC_RESULT (ic)));
2225 SPEC_SCLS (retype) = SPEC_SCLS (etype);
2226 SPEC_OCLS (retype) = SPEC_OCLS (etype);
2227 SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2229 if (IS_PTR (element->type))
2230 setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2232 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2236 return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2239 /*-----------------------------------------------------------------*/
2240 /* geniCodePostInc - generate int code for Post increment */
2241 /*-----------------------------------------------------------------*/
2243 geniCodePostInc (operand * op)
2247 sym_link *optype = operandType (op);
2249 operand *rv = (IS_ITEMP (op) ?
2250 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2252 sym_link *rvtype = operandType (rv);
2255 /* if this is not an address we have trouble */
2258 werror (E_LVALUE_REQUIRED, "++");
2262 rOp = newiTempOperand (rvtype, 0);
2263 OP_SYMBOL(rOp)->noSpilLoc = 1;
2266 OP_SYMBOL(rv)->noSpilLoc = 1;
2268 geniCodeAssign (rOp, rv, 0);
2270 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2271 if (IS_FLOAT (rvtype))
2272 ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2274 ic = newiCode ('+', rv, operandFromLit (size));
2276 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2279 geniCodeAssign (op, result, 0);
2285 /*-----------------------------------------------------------------*/
2286 /* geniCodePreInc - generate code for preIncrement */
2287 /*-----------------------------------------------------------------*/
2289 geniCodePreInc (operand * op)
2292 sym_link *optype = operandType (op);
2293 operand *rop = (IS_ITEMP (op) ?
2294 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2296 sym_link *roptype = operandType (rop);
2302 werror (E_LVALUE_REQUIRED, "++");
2307 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2308 if (IS_FLOAT (roptype))
2309 ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2311 ic = newiCode ('+', rop, operandFromLit (size));
2312 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2316 return geniCodeAssign (op, result, 0);
2319 /*-----------------------------------------------------------------*/
2320 /* geniCodePostDec - generates code for Post decrement */
2321 /*-----------------------------------------------------------------*/
2323 geniCodePostDec (operand * op)
2327 sym_link *optype = operandType (op);
2329 operand *rv = (IS_ITEMP (op) ?
2330 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2332 sym_link *rvtype = operandType (rv);
2335 /* if this is not an address we have trouble */
2338 werror (E_LVALUE_REQUIRED, "--");
2342 rOp = newiTempOperand (rvtype, 0);
2343 OP_SYMBOL(rOp)->noSpilLoc = 1;
2346 OP_SYMBOL(rv)->noSpilLoc = 1;
2348 geniCodeAssign (rOp, rv, 0);
2350 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2351 if (IS_FLOAT (rvtype))
2352 ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2354 ic = newiCode ('-', rv, operandFromLit (size));
2356 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2359 geniCodeAssign (op, result, 0);
2365 /*-----------------------------------------------------------------*/
2366 /* geniCodePreDec - generate code for pre decrement */
2367 /*-----------------------------------------------------------------*/
2369 geniCodePreDec (operand * op)
2372 sym_link *optype = operandType (op);
2373 operand *rop = (IS_ITEMP (op) ?
2374 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2376 sym_link *roptype = operandType (rop);
2382 werror (E_LVALUE_REQUIRED, "--");
2387 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2388 if (IS_FLOAT (roptype))
2389 ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2391 ic = newiCode ('-', rop, operandFromLit (size));
2392 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2396 return geniCodeAssign (op, result, 0);
2400 /*-----------------------------------------------------------------*/
2401 /* geniCodeBitwise - gen int code for bitWise operators */
2402 /*-----------------------------------------------------------------*/
2404 geniCodeBitwise (operand * left, operand * right,
2405 int oper, sym_link * resType)
2409 left = geniCodeCast (resType, left, TRUE);
2410 right = geniCodeCast (resType, right, TRUE);
2412 ic = newiCode (oper, left, right);
2413 IC_RESULT (ic) = newiTempOperand (resType, 0);
2416 return IC_RESULT (ic);
2419 /*-----------------------------------------------------------------*/
2420 /* geniCodeAddressOf - gens icode for '&' address of operator */
2421 /*-----------------------------------------------------------------*/
2423 geniCodeAddressOf (operand * op)
2427 sym_link *optype = operandType (op);
2428 sym_link *opetype = getSpec (optype);
2430 /* lvalue check already done in decorateType */
2431 /* this must be a lvalue */
2432 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2433 /* werror (E_LVALUE_REQUIRED,"&"); */
2438 p->class = DECLARATOR;
2440 /* set the pointer depending on the storage class */
2441 if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2442 DCL_PTR_CONST (p) = port->mem.code_ro;
2444 /* make sure we preserve the const & volatile */
2445 if (IS_CONSTANT (opetype))
2446 DCL_PTR_CONST (p) = 1;
2448 if (IS_VOLATILE (opetype))
2449 DCL_PTR_VOLATILE (p) = 1;
2451 p->next = copyLinkChain (optype);
2453 /* if already a temp */
2456 setOperandType (op, p);
2461 /* other wise make this of the type coming in */
2462 ic = newiCode (ADDRESS_OF, op, NULL);
2463 IC_RESULT (ic) = newiTempOperand (p, 1);
2464 IC_RESULT (ic)->isaddr = 0;
2466 return IC_RESULT (ic);
2468 /*-----------------------------------------------------------------*/
2469 /* setOClass - sets the output class depending on the pointer type */
2470 /*-----------------------------------------------------------------*/
2472 setOClass (sym_link * ptr, sym_link * spec)
2474 switch (DCL_TYPE (ptr))
2477 SPEC_OCLS (spec) = data;
2481 SPEC_OCLS (spec) = generic;
2485 SPEC_OCLS (spec) = xdata;
2489 SPEC_OCLS (spec) = code;
2493 SPEC_OCLS (spec) = idata;
2497 SPEC_OCLS (spec) = xstack;
2501 SPEC_OCLS (spec) = eeprom;
2510 /*-----------------------------------------------------------------*/
2511 /* geniCodeDerefPtr - dereference pointer with '*' */
2512 /*-----------------------------------------------------------------*/
2514 geniCodeDerefPtr (operand * op,int lvl)
2516 sym_link *rtype, *retype;
2517 sym_link *optype = operandType (op);
2519 /* if this is a pointer then generate the rvalue */
2520 if (IS_PTR (optype))
2522 if (IS_TRUE_SYMOP (op))
2525 op = geniCodeRValue (op, TRUE);
2528 op = geniCodeRValue (op, TRUE);
2531 /* now get rid of the pointer part */
2532 if (isLvaluereq(lvl) && IS_ITEMP (op))
2534 retype = getSpec (rtype = copyLinkChain (optype));
2538 retype = getSpec (rtype = copyLinkChain (optype->next));
2541 /* if this is a pointer then outputclass needs 2b updated */
2542 if (IS_PTR (optype))
2543 setOClass (optype, retype);
2545 op->isGptr = IS_GENPTR (optype);
2547 /* if the pointer was declared as a constant */
2548 /* then we cannot allow assignment to the derefed */
2549 if (IS_PTR_CONST (optype))
2550 SPEC_CONST (retype) = 1;
2552 op->isaddr = (IS_PTR (rtype) ||
2553 IS_STRUCT (rtype) ||
2558 if (!isLvaluereq(lvl))
2559 op = geniCodeRValue (op, TRUE);
2561 setOperandType (op, rtype);
2566 /*-----------------------------------------------------------------*/
2567 /* geniCodeUnaryMinus - does a unary minus of the operand */
2568 /*-----------------------------------------------------------------*/
2570 geniCodeUnaryMinus (operand * op)
2573 sym_link *optype = operandType (op);
2575 if (IS_LITERAL (optype))
2576 return operandFromLit (-floatFromVal (op->operand.valOperand));
2578 ic = newiCode (UNARYMINUS, op, NULL);
2579 IC_RESULT (ic) = newiTempOperand (optype, 0);
2581 return IC_RESULT (ic);
2584 /*-----------------------------------------------------------------*/
2585 /* geniCodeLeftShift - gen i code for left shift */
2586 /*-----------------------------------------------------------------*/
2588 geniCodeLeftShift (operand * left, operand * right)
2592 ic = newiCode (LEFT_OP, left, right);
2593 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2595 return IC_RESULT (ic);
2598 /*-----------------------------------------------------------------*/
2599 /* geniCodeRightShift - gen i code for right shift */
2600 /*-----------------------------------------------------------------*/
2602 geniCodeRightShift (operand * left, operand * right)
2606 ic = newiCode (RIGHT_OP, left, right);
2607 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2609 return IC_RESULT (ic);
2612 /*-----------------------------------------------------------------*/
2613 /* geniCodeLogic- logic code */
2614 /*-----------------------------------------------------------------*/
2616 geniCodeLogic (operand * left, operand * right, int op)
2620 sym_link *rtype = operandType (right);
2621 sym_link *ltype = operandType (left);
2623 /* left is integral type and right is literal then
2624 check if the literal value is within bounds */
2625 if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2627 checkConstantRange(ltype,
2628 OP_VALUE(right), "compare operation", 1);
2631 ctype = usualBinaryConversions (&left, &right);
2633 ic = newiCode (op, left, right);
2634 IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2636 /* if comparing float
2637 and not a '==' || '!=' || '&&' || '||' (these
2639 if (IS_FLOAT(ctype) &&
2647 return IC_RESULT (ic);
2650 /*-----------------------------------------------------------------*/
2651 /* geniCodeUnary - for a a generic unary operation */
2652 /*-----------------------------------------------------------------*/
2654 geniCodeUnary (operand * op, int oper)
2656 iCode *ic = newiCode (oper, op, NULL);
2658 IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2660 return IC_RESULT (ic);
2663 /*-----------------------------------------------------------------*/
2664 /* geniCodeConditional - geniCode for '?' ':' operation */
2665 /*-----------------------------------------------------------------*/
2667 geniCodeConditional (ast * tree,int lvl)
2670 symbol *falseLabel = newiTempLabel (NULL);
2671 symbol *exitLabel = newiTempLabel (NULL);
2672 operand *cond = ast2iCode (tree->left,lvl+1);
2673 operand *true, *false, *result;
2675 ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
2679 true = ast2iCode (tree->right->left,lvl+1);
2681 /* move the value to a new Operand */
2682 result = newiTempOperand (tree->right->ftype, 0);
2683 geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
2685 /* generate an unconditional goto */
2686 geniCodeGoto (exitLabel);
2688 /* now for the right side */
2689 geniCodeLabel (falseLabel);
2691 false = ast2iCode (tree->right->right,lvl+1);
2692 geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
2694 /* create the exit label */
2695 geniCodeLabel (exitLabel);
2700 /*-----------------------------------------------------------------*/
2701 /* geniCodeAssign - generate code for assignment */
2702 /*-----------------------------------------------------------------*/
2704 geniCodeAssign (operand * left, operand * right, int nosupdate)
2707 sym_link *ltype = operandType (left);
2708 sym_link *rtype = operandType (right);
2710 if (!left->isaddr && !IS_ITEMP (left))
2712 werror (E_LVALUE_REQUIRED, "assignment");
2716 /* left is integral type and right is literal then
2717 check if the literal value is within bounds */
2718 if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
2720 checkConstantRange(ltype,
2721 OP_VALUE(right), "= operation", 0);
2724 /* if the left & right type don't exactly match */
2725 /* if pointer set then make sure the check is
2726 done with the type & not the pointer */
2727 /* then cast rights type to left */
2729 /* first check the type for pointer assignement */
2730 if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
2731 compareType (ltype, rtype) <= 0)
2733 if (compareType (ltype->next, rtype) < 0)
2734 right = geniCodeCast (ltype->next, right, TRUE);
2736 else if (compareType (ltype, rtype) < 0)
2737 right = geniCodeCast (ltype, right, TRUE);
2739 /* if left is a true symbol & ! volatile
2740 create an assignment to temporary for
2741 the right & then assign this temporary
2742 to the symbol this is SSA . isn't it simple
2743 and folks have published mountains of paper on it */
2744 if (IS_TRUE_SYMOP (left) &&
2745 !isOperandVolatile (left, FALSE) &&
2746 isOperandGlobal (left))
2750 if (IS_TRUE_SYMOP (right))
2751 sym = OP_SYMBOL (right);
2752 ic = newiCode ('=', NULL, right);
2753 IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
2754 SPIL_LOC (right) = sym;
2758 ic = newiCode ('=', NULL, right);
2759 IC_RESULT (ic) = left;
2762 /* if left isgptr flag is set then support
2763 routine will be required */
2767 ic->nosupdate = nosupdate;
2771 /*-----------------------------------------------------------------*/
2772 /* geniCodeSEParms - generate code for side effecting fcalls */
2773 /*-----------------------------------------------------------------*/
2775 geniCodeSEParms (ast * parms,int lvl)
2780 if (parms->type == EX_OP && parms->opval.op == PARAM)
2782 geniCodeSEParms (parms->left,lvl);
2783 geniCodeSEParms (parms->right,lvl);
2787 /* hack don't like this but too lazy to think of
2789 if (IS_ADDRESS_OF_OP (parms))
2790 parms->left->lvalue = 1;
2792 if (IS_CAST_OP (parms) &&
2793 IS_PTR (parms->ftype) &&
2794 IS_ADDRESS_OF_OP (parms->right))
2795 parms->right->left->lvalue = 1;
2797 parms->opval.oprnd =
2798 geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2800 parms->type = EX_OPERAND;
2801 AST_ARGREG(parms) = parms->etype ? SPEC_ARGREG(parms->etype) :
2802 SPEC_ARGREG(parms->ftype);
2805 /*-----------------------------------------------------------------*/
2806 /* geniCodeParms - generates parameters */
2807 /*-----------------------------------------------------------------*/
2809 geniCodeParms (ast * parms, value *argVals, int *stack,
2810 sym_link * fetype, symbol * func,int lvl)
2818 if (argVals==NULL) {
2820 argVals=FUNC_ARGS(func->type);
2823 /* if this is a param node then do the left & right */
2824 if (parms->type == EX_OP && parms->opval.op == PARAM)
2826 argVals=geniCodeParms (parms->left, argVals, stack, fetype, func,lvl);
2827 argVals=geniCodeParms (parms->right, argVals, stack, fetype, func,lvl);
2831 /* get the parameter value */
2832 if (parms->type == EX_OPERAND)
2833 pval = parms->opval.oprnd;
2836 /* maybe this else should go away ?? */
2837 /* hack don't like this but too lazy to think of
2839 if (IS_ADDRESS_OF_OP (parms))
2840 parms->left->lvalue = 1;
2842 if (IS_CAST_OP (parms) &&
2843 IS_PTR (parms->ftype) &&
2844 IS_ADDRESS_OF_OP (parms->right))
2845 parms->right->left->lvalue = 1;
2847 pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2850 /* if register parm then make it a send */
2851 if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(func->type)) ||
2852 IFFUNC_ISBUILTIN(func->type))
2854 ic = newiCode (SEND, pval, NULL);
2855 ic->argreg = SPEC_ARGREG(parms->etype);
2856 ic->builtinSEND = FUNC_ISBUILTIN(func->type);
2861 /* now decide whether to push or assign */
2862 if (!(options.stackAuto || IFFUNC_ISREENT (func->type)))
2866 operand *top = operandFromSymbol (argVals->sym);
2867 /* clear useDef and other bitVectors */
2868 OP_USES (top) = OP_DEFS (top) = OP_SYMBOL(top)->clashes = NULL;
2869 geniCodeAssign (top, pval, 1);
2873 sym_link *p = operandType (pval);
2875 ic = newiCode (IPUSH, pval, NULL);
2877 /* update the stack adjustment */
2878 *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2883 argVals=argVals->next;
2887 /*-----------------------------------------------------------------*/
2888 /* geniCodeCall - generates temp code for calling */
2889 /*-----------------------------------------------------------------*/
2891 geniCodeCall (operand * left, ast * parms,int lvl)
2895 sym_link *type, *etype;
2898 if (!IS_FUNC(OP_SYMBOL(left)->type) &&
2899 !IS_CODEPTR(OP_SYMBOL(left)->type)) {
2900 werror (E_FUNCTION_EXPECTED);
2904 /* take care of parameters with side-effecting
2905 function calls in them, this is required to take care
2906 of overlaying function parameters */
2907 geniCodeSEParms (parms,lvl);
2909 /* first the parameters */
2910 geniCodeParms (parms, NULL, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
2912 /* now call : if symbol then pcall */
2913 if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
2914 ic = newiCode (PCALL, left, NULL);
2916 ic = newiCode (CALL, left, NULL);
2919 type = copyLinkChain (operandType (left)->next);
2920 etype = getSpec (type);
2921 SPEC_EXTR (etype) = 0;
2922 IC_RESULT (ic) = result = newiTempOperand (type, 1);
2926 /* stack adjustment after call */
2927 ic->parmBytes = stack;
2932 /*-----------------------------------------------------------------*/
2933 /* geniCodeReceive - generate intermediate code for "receive" */
2934 /*-----------------------------------------------------------------*/
2936 geniCodeReceive (value * args)
2938 /* for all arguments that are passed in registers */
2942 if (IS_REGPARM (args->etype))
2944 operand *opr = operandFromValue (args);
2946 symbol *sym = OP_SYMBOL (opr);
2949 /* we will use it after all optimizations
2950 and before liveRange calculation */
2951 if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
2954 if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
2955 options.stackAuto == 0 &&
2956 (!(options.model == MODEL_FLAT24)) )
2961 opl = newiTempOperand (args->type, 0);
2963 sym->reqv->key = sym->key;
2964 OP_SYMBOL (sym->reqv)->key = sym->key;
2965 OP_SYMBOL (sym->reqv)->isreqv = 1;
2966 OP_SYMBOL (sym->reqv)->islocal = 0;
2967 SPIL_LOC (sym->reqv) = sym;
2971 ic = newiCode (RECEIVE, NULL, NULL);
2972 ic->argreg = SPEC_ARGREG(args->etype);
2974 currFunc->recvSize = getSize (sym->type);
2977 IC_RESULT (ic) = opr;
2985 /*-----------------------------------------------------------------*/
2986 /* geniCodeFunctionBody - create the function body */
2987 /*-----------------------------------------------------------------*/
2989 geniCodeFunctionBody (ast * tree,int lvl)
2996 /* reset the auto generation */
3002 func = ast2iCode (tree->left,lvl+1);
3003 fetype = getSpec (operandType (func));
3005 savelineno = lineno;
3006 lineno = OP_SYMBOL (func)->lineDef;
3007 /* create an entry label */
3008 geniCodeLabel (entryLabel);
3009 lineno = savelineno;
3011 /* create a proc icode */
3012 ic = newiCode (FUNCTION, func, NULL);
3013 lineno=ic->lineno = OP_SYMBOL (func)->lineDef;
3017 /* for all parameters that are passed
3018 on registers add a "receive" */
3019 geniCodeReceive (tree->values.args);
3021 /* generate code for the body */
3022 ast2iCode (tree->right,lvl+1);
3024 /* create a label for return */
3025 geniCodeLabel (returnLabel);
3027 /* now generate the end proc */
3028 ic = newiCode (ENDFUNCTION, func, NULL);
3033 /*-----------------------------------------------------------------*/
3034 /* geniCodeReturn - gen icode for 'return' statement */
3035 /*-----------------------------------------------------------------*/
3037 geniCodeReturn (operand * op)
3041 /* if the operand is present force an rvalue */
3043 op = geniCodeRValue (op, FALSE);
3045 ic = newiCode (RETURN, op, NULL);
3049 /*-----------------------------------------------------------------*/
3050 /* geniCodeIfx - generates code for extended if statement */
3051 /*-----------------------------------------------------------------*/
3053 geniCodeIfx (ast * tree,int lvl)
3056 operand *condition = ast2iCode (tree->left,lvl+1);
3059 /* if condition is null then exit */
3063 condition = geniCodeRValue (condition, FALSE);
3065 cetype = getSpec (operandType (condition));
3066 /* if the condition is a literal */
3067 if (IS_LITERAL (cetype))
3069 if (floatFromVal (condition->operand.valOperand))
3071 if (tree->trueLabel)
3072 geniCodeGoto (tree->trueLabel);
3078 if (tree->falseLabel)
3079 geniCodeGoto (tree->falseLabel);
3086 if (tree->trueLabel)
3088 ic = newiCodeCondition (condition,
3093 if (tree->falseLabel)
3094 geniCodeGoto (tree->falseLabel);
3098 ic = newiCodeCondition (condition,
3105 ast2iCode (tree->right,lvl+1);
3108 /*-----------------------------------------------------------------*/
3109 /* geniCodeJumpTable - tries to create a jump table for switch */
3110 /*-----------------------------------------------------------------*/
3112 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
3114 int min = 0, max = 0, t, cnt = 0;
3121 if (!tree || !caseVals)
3124 /* the criteria for creating a jump table is */
3125 /* all integer numbers between the maximum & minimum must */
3126 /* be present , the maximum value should not exceed 255 */
3127 min = max = (int) floatFromVal (vch = caseVals);
3128 sprintf (buffer, "_case_%d_%d",
3129 tree->values.switchVals.swNum,
3131 addSet (&labels, newiTempLabel (buffer));
3133 /* if there is only one case value then no need */
3134 if (!(vch = vch->next))
3139 if (((t = (int) floatFromVal (vch)) - max) != 1)
3141 sprintf (buffer, "_case_%d_%d",
3142 tree->values.switchVals.swNum,
3144 addSet (&labels, newiTempLabel (buffer));
3150 /* if the number of case statements <= 2 then */
3151 /* it is not economical to create the jump table */
3152 /* since two compares are needed for boundary conditions */
3153 if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
3156 if (tree->values.switchVals.swDefault)
3157 sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3159 sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3161 falseLabel = newiTempLabel (buffer);
3163 /* so we can create a jumptable */
3164 /* first we rule out the boundary conditions */
3165 /* if only optimization says so */
3166 if (!optimize.noJTabBoundary)
3168 sym_link *cetype = getSpec (operandType (cond));
3169 /* no need to check the lower bound if
3170 the condition is unsigned & minimum value is zero */
3171 if (!(min == 0 && SPEC_USIGN (cetype)))
3173 boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3174 ic = newiCodeCondition (boundary, falseLabel, NULL);
3178 /* now for upper bounds */
3179 boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3180 ic = newiCodeCondition (boundary, falseLabel, NULL);
3184 /* if the min is not zero then we no make it zero */
3187 cond = geniCodeSubtract (cond, operandFromLit (min));
3188 setOperandType (cond, UCHARTYPE);
3191 /* now create the jumptable */
3192 ic = newiCode (JUMPTABLE, NULL, NULL);
3193 IC_JTCOND (ic) = cond;
3194 IC_JTLABELS (ic) = labels;
3199 /*-----------------------------------------------------------------*/
3200 /* geniCodeSwitch - changes a switch to a if statement */
3201 /*-----------------------------------------------------------------*/
3203 geniCodeSwitch (ast * tree,int lvl)
3206 operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3207 value *caseVals = tree->values.switchVals.swVals;
3208 symbol *trueLabel, *falseLabel;
3210 /* if we can make this a jump table */
3211 if (geniCodeJumpTable (cond, caseVals, tree))
3212 goto jumpTable; /* no need for the comparison */
3214 /* for the cases defined do */
3218 operand *compare = geniCodeLogic (cond,
3219 operandFromValue (caseVals),
3222 sprintf (buffer, "_case_%d_%d",
3223 tree->values.switchVals.swNum,
3224 (int) floatFromVal (caseVals));
3225 trueLabel = newiTempLabel (buffer);
3227 ic = newiCodeCondition (compare, trueLabel, NULL);
3229 caseVals = caseVals->next;
3234 /* if default is present then goto break else break */
3235 if (tree->values.switchVals.swDefault)
3236 sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3238 sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3240 falseLabel = newiTempLabel (buffer);
3241 geniCodeGoto (falseLabel);
3244 ast2iCode (tree->right,lvl+1);
3247 /*-----------------------------------------------------------------*/
3248 /* geniCodeInline - intermediate code for inline assembler */
3249 /*-----------------------------------------------------------------*/
3251 geniCodeInline (ast * tree)
3255 ic = newiCode (INLINEASM, NULL, NULL);
3256 IC_INLINE (ic) = tree->values.inlineasm;
3260 /*-----------------------------------------------------------------*/
3261 /* geniCodeArrayInit - intermediate code for array initializer */
3262 /*-----------------------------------------------------------------*/
3264 geniCodeArrayInit (ast * tree, operand *array)
3268 if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3269 ic = newiCode (ARRAYINIT, array, NULL);
3270 IC_ARRAYILIST (ic) = tree->values.constlist;
3272 operand *left=newOperand(), *right=newOperand();
3273 left->type=right->type=SYMBOL;
3274 OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3275 OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3276 ic = newiCode (ARRAYINIT, left, right);
3281 /*-----------------------------------------------------------------*/
3282 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
3283 /* particular case. Ie : assigning or dereferencing array or ptr */
3284 /*-----------------------------------------------------------------*/
3285 set * lvaluereqSet = NULL;
3286 typedef struct lvalItem
3293 /*-----------------------------------------------------------------*/
3294 /* addLvaluereq - add a flag for lvalreq for current ast level */
3295 /*-----------------------------------------------------------------*/
3296 void addLvaluereq(int lvl)
3298 lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3301 addSetHead(&lvaluereqSet,lpItem);
3304 /*-----------------------------------------------------------------*/
3305 /* delLvaluereq - del a flag for lvalreq for current ast level */
3306 /*-----------------------------------------------------------------*/
3310 lpItem = getSet(&lvaluereqSet);
3311 if(lpItem) Safe_free(lpItem);
3313 /*-----------------------------------------------------------------*/
3314 /* clearLvaluereq - clear lvalreq flag */
3315 /*-----------------------------------------------------------------*/
3316 void clearLvaluereq()
3319 lpItem = peekSet(lvaluereqSet);
3320 if(lpItem) lpItem->req = 0;
3322 /*-----------------------------------------------------------------*/
3323 /* getLvaluereq - get the last lvalreq level */
3324 /*-----------------------------------------------------------------*/
3325 int getLvaluereqLvl()
3328 lpItem = peekSet(lvaluereqSet);
3329 if(lpItem) return lpItem->lvl;
3332 /*-----------------------------------------------------------------*/
3333 /* isLvaluereq - is lvalreq valid for this level ? */
3334 /*-----------------------------------------------------------------*/
3335 int isLvaluereq(int lvl)
3338 lpItem = peekSet(lvaluereqSet);
3339 if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3343 /*-----------------------------------------------------------------*/
3344 /* ast2iCode - creates an icodeList from an ast */
3345 /*-----------------------------------------------------------------*/
3347 ast2iCode (ast * tree,int lvl)
3349 operand *left = NULL;
3350 operand *right = NULL;
3354 /* set the global variables for filename & line number */
3356 filename = tree->filename;
3358 lineno = tree->lineno;
3360 block = tree->block;
3362 scopeLevel = tree->level;
3364 if (tree->type == EX_VALUE)
3365 return operandFromValue (tree->opval.val);
3367 if (tree->type == EX_LINK)
3368 return operandFromLink (tree->opval.lnk);
3370 /* if we find a nullop */
3371 if (tree->type == EX_OP &&
3372 (tree->opval.op == NULLOP ||
3373 tree->opval.op == BLOCK))
3375 ast2iCode (tree->left,lvl+1);
3376 ast2iCode (tree->right,lvl+1);
3380 /* special cases for not evaluating */
3381 if (tree->opval.op != ':' &&
3382 tree->opval.op != '?' &&
3383 tree->opval.op != CALL &&
3384 tree->opval.op != IFX &&
3385 tree->opval.op != LABEL &&
3386 tree->opval.op != GOTO &&
3387 tree->opval.op != SWITCH &&
3388 tree->opval.op != FUNCTION &&
3389 tree->opval.op != INLINEASM)
3392 if (IS_ASSIGN_OP (tree->opval.op) ||
3393 IS_DEREF_OP (tree) ||
3394 (tree->opval.op == '&' && !tree->right) ||
3395 tree->opval.op == PTR_OP)
3398 if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3399 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3402 left = operandFromAst (tree->left,lvl);
3404 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3405 left = geniCodeRValue (left, TRUE);
3409 left = operandFromAst (tree->left,lvl);
3411 if (tree->opval.op == INC_OP ||
3412 tree->opval.op == DEC_OP)
3415 right = operandFromAst (tree->right,lvl);
3420 right = operandFromAst (tree->right,lvl);
3424 /* now depending on the type of operand */
3425 /* this will be a biggy */
3426 switch (tree->opval.op)
3429 case '[': /* array operation */
3431 //sym_link *ltype = operandType (left);
3432 //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3433 left = geniCodeRValue (left, FALSE);
3434 right = geniCodeRValue (right, TRUE);
3437 return geniCodeArray (left, right,lvl);
3439 case '.': /* structure dereference */
3440 if (IS_PTR (operandType (left)))
3441 left = geniCodeRValue (left, TRUE);
3443 left = geniCodeRValue (left, FALSE);
3445 return geniCodeStruct (left, right, tree->lvalue);
3447 case PTR_OP: /* structure pointer dereference */
3450 pType = operandType (left);
3451 left = geniCodeRValue (left, TRUE);
3453 setOClass (pType, getSpec (operandType (left)));
3456 return geniCodeStruct (left, right, tree->lvalue);
3458 case INC_OP: /* increment operator */
3460 return geniCodePostInc (left);
3462 return geniCodePreInc (right);
3464 case DEC_OP: /* decrement operator */
3466 return geniCodePostDec (left);
3468 return geniCodePreDec (right);
3470 case '&': /* bitwise and or address of operator */
3472 { /* this is a bitwise operator */
3473 left = geniCodeRValue (left, FALSE);
3474 right = geniCodeRValue (right, FALSE);
3475 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3478 return geniCodeAddressOf (left);
3480 case '|': /* bitwise or & xor */
3482 return geniCodeBitwise (geniCodeRValue (left, FALSE),
3483 geniCodeRValue (right, FALSE),
3488 return geniCodeDivision (geniCodeRValue (left, FALSE),
3489 geniCodeRValue (right, FALSE));
3492 return geniCodeModulus (geniCodeRValue (left, FALSE),
3493 geniCodeRValue (right, FALSE));
3496 return geniCodeMultiply (geniCodeRValue (left, FALSE),
3497 geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3499 return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3503 return geniCodeSubtract (geniCodeRValue (left, FALSE),
3504 geniCodeRValue (right, FALSE));
3506 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3510 return geniCodeAdd (geniCodeRValue (left, FALSE),
3511 geniCodeRValue (right, FALSE),lvl);
3513 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
3516 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3517 geniCodeRValue (right, FALSE));
3520 return geniCodeRightShift (geniCodeRValue (left, FALSE),
3521 geniCodeRValue (right, FALSE));
3523 return geniCodeCast (operandType (left),
3524 geniCodeRValue (right, FALSE), FALSE);
3530 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3534 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3535 setOperandType (op, UCHARTYPE);
3546 return geniCodeLogic (geniCodeRValue (left, FALSE),
3547 geniCodeRValue (right, FALSE),
3550 return geniCodeConditional (tree,lvl);
3553 return operandFromLit (getSize (tree->right->ftype));
3557 sym_link *rtype = operandType (right);
3558 sym_link *ltype = operandType (left);
3559 if (IS_PTR (rtype) && IS_ITEMP (right)
3560 && right->isaddr && compareType (rtype->next, ltype) == 1)
3561 right = geniCodeRValue (right, TRUE);
3563 right = geniCodeRValue (right, FALSE);
3565 geniCodeAssign (left, right, 0);
3570 geniCodeAssign (left,
3571 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3573 geniCodeRValue (right, FALSE),FALSE), 0);
3577 geniCodeAssign (left,
3578 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3580 geniCodeRValue (right, FALSE)), 0);
3583 geniCodeAssign (left,
3584 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3586 geniCodeRValue (right, FALSE)), 0);
3589 sym_link *rtype = operandType (right);
3590 sym_link *ltype = operandType (left);
3591 if (IS_PTR (rtype) && IS_ITEMP (right)
3592 && right->isaddr && compareType (rtype->next, ltype) == 1)
3593 right = geniCodeRValue (right, TRUE);
3595 right = geniCodeRValue (right, FALSE);
3598 return geniCodeAssign (left,
3599 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3605 sym_link *rtype = operandType (right);
3606 sym_link *ltype = operandType (left);
3607 if (IS_PTR (rtype) && IS_ITEMP (right)
3608 && right->isaddr && compareType (rtype->next, ltype) == 1)
3610 right = geniCodeRValue (right, TRUE);
3614 right = geniCodeRValue (right, FALSE);
3617 geniCodeAssign (left,
3618 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3624 geniCodeAssign (left,
3625 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3627 geniCodeRValue (right, FALSE)), 0);
3630 geniCodeAssign (left,
3631 geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3633 geniCodeRValue (right, FALSE)), 0);
3636 geniCodeAssign (left,
3637 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3639 geniCodeRValue (right, FALSE),
3641 operandType (left)), 0);
3644 geniCodeAssign (left,
3645 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3647 geniCodeRValue (right, FALSE),
3649 operandType (left)), 0);
3652 geniCodeAssign (left,
3653 geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3655 geniCodeRValue (right, FALSE),
3657 operandType (left)), 0);
3659 return geniCodeRValue (right, FALSE);
3662 return geniCodeCall (ast2iCode (tree->left,lvl+1),
3665 geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3666 return ast2iCode (tree->right,lvl+1);
3669 geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3670 return ast2iCode (tree->right,lvl+1);
3673 geniCodeFunctionBody (tree,lvl);
3677 geniCodeReturn (right);
3681 geniCodeIfx (tree,lvl);
3685 geniCodeSwitch (tree,lvl);
3689 geniCodeInline (tree);
3693 geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
3700 /*-----------------------------------------------------------------*/
3701 /* reverseICChain - gets from the list and creates a linkedlist */
3702 /*-----------------------------------------------------------------*/
3709 while ((loop = getSet (&iCodeChain)))
3721 /*-----------------------------------------------------------------*/
3722 /* iCodeFromAst - given an ast will convert it to iCode */
3723 /*-----------------------------------------------------------------*/
3725 iCodeFromAst (ast * tree)
3727 returnLabel = newiTempLabel ("_return");
3728 entryLabel = newiTempLabel ("_entry");
3730 return reverseiCChain ();