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}", /*{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
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))
395 printOperand (IC_RESULT (ic), of);
397 printOperand (IC_LEFT (ic), of);
398 printOperand (IC_RIGHT (ic), of);
403 PRINTFUNC (picAssign)
407 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
410 printOperand (IC_RESULT (ic), of);
412 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
415 fprintf (of, " %s ", s);
416 printOperand (IC_RIGHT (ic), of);
423 fprintf (of, " %s($%d) :\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
429 fprintf (of, " goto %s($%d)\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
436 printOperand (IC_COND (ic), of);
439 fprintf (of, " == 0 goto %s($%d)\n", IC_FALSE (ic)->name, IC_FALSE (ic)->key);
442 fprintf (of, " != 0 goto %s($%d)\n", IC_TRUE (ic)->name, IC_TRUE (ic)->key);
444 fprintf (of, "\tzzgoto %s\n", IC_FALSE (ic)->name);
448 PRINTFUNC (picInline)
450 fprintf (of, "%s", IC_INLINE (ic));
453 PRINTFUNC (picReceive)
455 printOperand (IC_RESULT (ic), of);
456 fprintf (of, " = %s ", s);
457 printOperand (IC_LEFT (ic), of);
461 /*-----------------------------------------------------------------*/
462 /* piCode - prints one iCode */
463 /*-----------------------------------------------------------------*/
465 piCode (void *item, FILE * of)
473 icTab = getTableEntry (ic->op);
474 fprintf (stdout, "%s(%d:%d:%d:%d:%d)\t",
475 ic->filename, ic->lineno,
476 ic->seq, ic->key, ic->depth, ic->supportRtn);
477 icTab->iCodePrint (of, ic, icTab->printName);
483 printiCChain(ic,stdout);
485 /*-----------------------------------------------------------------*/
486 /* printiCChain - prints intermediate code for humans */
487 /*-----------------------------------------------------------------*/
489 printiCChain (iCode * icChain, FILE * of)
496 for (loop = icChain; loop; loop = loop->next)
498 if ((icTab = getTableEntry (loop->op)))
500 fprintf (of, "%s(%d:%d:%d:%d:%d)\t",
501 loop->filename, loop->lineno,
502 loop->seq, loop->key, loop->depth, loop->supportRtn);
504 icTab->iCodePrint (of, loop, icTab->printName);
510 /*-----------------------------------------------------------------*/
511 /* newOperand - allocate, init & return a new iCode */
512 /*-----------------------------------------------------------------*/
518 op = Safe_alloc ( sizeof (operand));
524 /*-----------------------------------------------------------------*/
525 /* newiCode - create and return a new iCode entry initialised */
526 /*-----------------------------------------------------------------*/
528 newiCode (int op, operand * left, operand * right)
532 ic = Safe_alloc ( sizeof (iCode));
535 ic->filename = filename;
537 ic->level = scopeLevel;
539 ic->key = iCodeKey++;
541 IC_RIGHT (ic) = right;
546 /*-----------------------------------------------------------------*/
547 /* newiCode for conditional statements */
548 /*-----------------------------------------------------------------*/
550 newiCodeCondition (operand * condition,
556 if (IS_VOID(operandType(condition))) {
557 werror(E_VOID_VALUE_USED);
560 ic = newiCode (IFX, NULL, NULL);
561 IC_COND (ic) = condition;
562 IC_TRUE (ic) = trueLabel;
563 IC_FALSE (ic) = falseLabel;
567 /*-----------------------------------------------------------------*/
568 /* newiCodeLabelGoto - unconditional goto statement| label stmnt */
569 /*-----------------------------------------------------------------*/
571 newiCodeLabelGoto (int op, symbol * label)
575 ic = newiCode (op, NULL, NULL);
577 ic->argLabel.label = label;
579 IC_RIGHT (ic) = NULL;
580 IC_RESULT (ic) = NULL;
584 /*-----------------------------------------------------------------*/
585 /* newiTemp - allocate & return a newItemp Variable */
586 /*-----------------------------------------------------------------*/
593 sprintf (buffer, "%s", s);
595 sprintf (buffer, "iTemp%d", iTempNum++);
596 itmp = newSymbol (buffer, 1);
597 strcpy (itmp->rname, itmp->name);
603 /*-----------------------------------------------------------------*/
604 /* newiTempLabel - creates a temp variable label */
605 /*-----------------------------------------------------------------*/
607 newiTempLabel (char *s)
611 /* check if this alredy exists */
612 if (s && (itmplbl = findSym (LabelTab, NULL, s)))
616 itmplbl = newSymbol (s, 1);
619 sprintf (buffer, "iTempLbl%d", iTempLblNum++);
620 itmplbl = newSymbol (buffer, 1);
625 itmplbl->key = labelKey++;
626 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
630 /*-----------------------------------------------------------------*/
631 /* newiTempPreheaderLabel - creates a new preheader label */
632 /*-----------------------------------------------------------------*/
634 newiTempPreheaderLabel ()
638 sprintf (buffer, "preHeaderLbl%d", iTempLblNum++);
639 itmplbl = newSymbol (buffer, 1);
643 itmplbl->key = labelKey++;
644 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
649 /*-----------------------------------------------------------------*/
650 /* initiCode - initialises some iCode related stuff */
651 /*-----------------------------------------------------------------*/
658 /*-----------------------------------------------------------------*/
659 /* copyiCode - make a copy of the iCode given */
660 /*-----------------------------------------------------------------*/
662 copyiCode (iCode * ic)
664 iCode *nic = newiCode (ic->op, NULL, NULL);
666 nic->lineno = ic->lineno;
667 nic->filename = ic->filename;
668 nic->block = ic->block;
669 nic->level = ic->level;
670 nic->parmBytes = ic->parmBytes;
672 /* deal with the special cases first */
676 IC_COND (nic) = operandFromOperand (IC_COND (ic));
677 IC_TRUE (nic) = IC_TRUE (ic);
678 IC_FALSE (nic) = IC_FALSE (ic);
682 IC_JTCOND (nic) = operandFromOperand (IC_JTCOND (ic));
683 IC_JTLABELS (nic) = IC_JTLABELS (ic);
688 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
689 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
693 IC_INLINE (nic) = IC_INLINE (ic);
697 IC_ARRAYILIST(nic) = IC_ARRAYILIST(ic);
701 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
702 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
703 IC_RIGHT (nic) = operandFromOperand (IC_RIGHT (ic));
709 /*-----------------------------------------------------------------*/
710 /* getTableEntry - gets the table entry for the given operator */
711 /*-----------------------------------------------------------------*/
713 getTableEntry (int oper)
717 for (i = 0; i < (sizeof (codeTable) / sizeof (iCodeTable)); i++)
718 if (oper == codeTable[i].icode)
719 return &codeTable[i];
724 /*-----------------------------------------------------------------*/
725 /* newiTempOperand - new intermediate temp operand */
726 /*-----------------------------------------------------------------*/
728 newiTempOperand (sym_link * type, char throwType)
731 operand *op = newOperand ();
735 itmp = newiTemp (NULL);
737 etype = getSpec (type);
739 if (IS_LITERAL (etype))
742 /* copy the type information */
744 itmp->etype = getSpec (itmp->type = (throwType ? type :
745 copyLinkChain (type)));
746 if (IS_LITERAL (itmp->etype))
748 SPEC_SCLS (itmp->etype) = S_REGISTER;
749 SPEC_OCLS (itmp->etype) = reg;
752 op->operand.symOperand = itmp;
753 op->key = itmp->key = ++operandKey;
757 /*-----------------------------------------------------------------*/
758 /* operandType - returns the type chain for an operand */
759 /*-----------------------------------------------------------------*/
761 operandType (operand * op)
763 /* depending on type of operand */
768 return op->operand.valOperand->type;
771 return op->operand.symOperand->type;
774 return op->operand.typeOperand;
776 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
777 " operand type not known ");
778 assert (0); /* should never come here */
779 /* Just to keep the compiler happy */
780 return (sym_link *) 0;
784 /*-----------------------------------------------------------------*/
785 /* isParamterToCall - will return 1 if op is a parameter to args */
786 /*-----------------------------------------------------------------*/
788 isParameterToCall (value * args, operand * op)
795 isSymbolEqual (op->operand.symOperand, tval->sym))
802 /*-----------------------------------------------------------------*/
803 /* isOperandGlobal - return 1 if operand is a global variable */
804 /*-----------------------------------------------------------------*/
806 isOperandGlobal (operand * op)
814 if (op->type == SYMBOL &&
815 (op->operand.symOperand->level == 0 ||
816 IS_STATIC (op->operand.symOperand->etype) ||
817 IS_EXTERN (op->operand.symOperand->etype))
824 /*-----------------------------------------------------------------*/
825 /* isOperandVolatile - return 1 if the operand is volatile */
826 /*-----------------------------------------------------------------*/
828 isOperandVolatile (operand * op, bool chkTemp)
833 if (IS_ITEMP (op) && !chkTemp)
836 opetype = getSpec (optype = operandType (op));
838 if (IS_PTR (optype) && DCL_PTR_VOLATILE (optype))
841 if (IS_VOLATILE (opetype))
846 /*-----------------------------------------------------------------*/
847 /* isOperandLiteral - returns 1 if an operand contains a literal */
848 /*-----------------------------------------------------------------*/
850 isOperandLiteral (operand * op)
857 opetype = getSpec (operandType (op));
859 if (IS_LITERAL (opetype))
865 /*-----------------------------------------------------------------*/
866 /* isOperandInFarSpace - will return true if operand is in farSpace */
867 /*-----------------------------------------------------------------*/
869 isOperandInFarSpace (operand * op)
879 if (!IS_TRUE_SYMOP (op))
882 etype = SPIL_LOC (op)->etype;
888 etype = getSpec (operandType (op));
890 return (IN_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
893 /*------------------------------------------------------------------*/
894 /* isOperandInDirSpace - will return true if operand is in dirSpace */
895 /*------------------------------------------------------------------*/
897 isOperandInDirSpace (operand * op)
907 if (!IS_TRUE_SYMOP (op))
910 etype = SPIL_LOC (op)->etype;
916 etype = getSpec (operandType (op));
918 return (IN_DIRSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
921 /*------------------------------------------------------------------*/
922 /* isOperandInDirSpace - will return true if operand is in dirSpace */
923 /*------------------------------------------------------------------*/
925 isOperandInCodeSpace (operand * op)
935 if (!IS_TRUE_SYMOP (op))
938 etype = SPIL_LOC (op)->etype;
944 etype = getSpec (operandType (op));
946 return (IN_CODESPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
949 /*-----------------------------------------------------------------*/
950 /* isOperandOnStack - will return true if operand is on stack */
951 /*-----------------------------------------------------------------*/
953 isOperandOnStack (operand * op)
963 etype = getSpec (operandType (op));
964 if (IN_STACK (etype) ||
965 OP_SYMBOL(op)->onStack ||
966 (SPIL_LOC(op) && SPIL_LOC(op)->onStack))
972 /*-----------------------------------------------------------------*/
973 /* operandLitValue - literal value of an operand */
974 /*-----------------------------------------------------------------*/
976 operandLitValue (operand * op)
978 assert (isOperandLiteral (op));
980 return floatFromVal (op->operand.valOperand);
983 /*-----------------------------------------------------------------*/
984 /* getBuiltInParms - returns parameters to a builtin functions */
985 /*-----------------------------------------------------------------*/
986 iCode *getBuiltinParms (iCode *ic, int *pcount, operand **parms)
991 /* builtin functions uses only SEND for parameters */
992 while (ic->op != CALL) {
993 assert(ic->op == SEND && ic->builtinSEND);
994 ic->generated = 1; /* mark the icode as generated */
995 parms[*pcount] = IC_LEFT(ic);
1001 /* make sure this is a builtin function call */
1002 assert(IS_SYMOP(IC_LEFT(ic)));
1003 ftype = operandType(IC_LEFT(ic));
1004 assert(IFFUNC_ISBUILTIN(ftype));
1008 /*-----------------------------------------------------------------*/
1009 /* operandOperation - perforoms operations on operands */
1010 /*-----------------------------------------------------------------*/
1012 operandOperation (operand * left, operand * right,
1013 int op, sym_link * type)
1015 sym_link *let , *ret=NULL;
1016 operand *retval = (operand *) 0;
1018 assert (isOperandLiteral (left));
1019 let = getSpec(operandType(left));
1021 assert (isOperandLiteral (right));
1022 ret = getSpec(operandType(left));
1028 retval = operandFromValue (valCastLiteral (type,
1029 operandLitValue (left) +
1030 operandLitValue (right)));
1033 retval = operandFromValue (valCastLiteral (type,
1034 operandLitValue (left) -
1035 operandLitValue (right)));
1038 retval = operandFromValue (valCastLiteral (type,
1039 operandLitValue (left) *
1040 operandLitValue (right)));
1043 if ((unsigned long) operandLitValue (right) == 0)
1045 werror (E_DIVIDE_BY_ZERO);
1050 retval = operandFromValue (valCastLiteral (type,
1051 operandLitValue (left) /
1052 operandLitValue (right)));
1055 if ((unsigned long) operandLitValue (right) == 0) {
1056 werror (E_DIVIDE_BY_ZERO);
1060 retval = operandFromLit ((SPEC_USIGN(let) ?
1061 (unsigned long) operandLitValue (left) :
1062 (long) operandLitValue (left)) %
1064 (unsigned long) operandLitValue (right) :
1065 (long) operandLitValue (right)));
1069 retval = operandFromLit ((SPEC_USIGN(let) ?
1070 (unsigned long) operandLitValue (left) :
1071 (long) operandLitValue (left)) <<
1073 (unsigned long) operandLitValue (right) :
1074 (long) operandLitValue (right)));
1077 retval = operandFromLit ((SPEC_USIGN(let) ?
1078 (unsigned long) operandLitValue (left) :
1079 (long) operandLitValue (left)) >>
1081 (unsigned long) operandLitValue (right) :
1082 (long) operandLitValue (right)));
1085 retval = operandFromLit (operandLitValue (left) ==
1086 operandLitValue (right));
1089 retval = operandFromLit (operandLitValue (left) <
1090 operandLitValue (right));
1093 retval = operandFromLit (operandLitValue (left) <=
1094 operandLitValue (right));
1097 retval = operandFromLit (operandLitValue (left) !=
1098 operandLitValue (right));
1101 retval = operandFromLit (operandLitValue (left) >
1102 operandLitValue (right));
1105 retval = operandFromLit (operandLitValue (left) >=
1106 operandLitValue (right));
1109 retval = operandFromLit ((long)operandLitValue(left) &
1110 (long)operandLitValue(right));
1113 retval = operandFromLit ((long)operandLitValue (left) |
1114 (long)operandLitValue (right));
1117 retval = operandFromLit ((long)operandLitValue (left) ^
1118 (long)operandLitValue (right));
1121 retval = operandFromLit (operandLitValue (left) &&
1122 operandLitValue (right));
1125 retval = operandFromLit (operandLitValue (left) ||
1126 operandLitValue (right));
1130 long i = (long) operandLitValue (left);
1132 retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
1138 long i = (long) operandLitValue (left);
1140 retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
1146 retval = operandFromLit (-1 * operandLitValue (left));
1150 retval = operandFromLit (~((long) operandLitValue (left)));
1154 retval = operandFromLit (!operandLitValue (left));
1158 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1159 " operandOperation invalid operator ");
1167 /*-----------------------------------------------------------------*/
1168 /* isOperandEqual - compares two operand & return 1 if they r = */
1169 /*-----------------------------------------------------------------*/
1171 isOperandEqual (operand * left, operand * right)
1173 /* if the pointers are equal then they are equal */
1177 /* if either of them null then false */
1178 if (!left || !right)
1181 if (left->type != right->type)
1184 if (IS_SYMOP (left) && IS_SYMOP (right))
1185 return left->key == right->key;
1187 /* if types are the same */
1191 return isSymbolEqual (left->operand.symOperand,
1192 right->operand.symOperand);
1194 return (floatFromVal (left->operand.valOperand) ==
1195 floatFromVal (right->operand.valOperand));
1197 if (compareType (left->operand.typeOperand,
1198 right->operand.typeOperand) == 1)
1205 /*-------------------------------------------------------------------*/
1206 /* isiCodeEqual - compares two iCodes are equal, returns true if yes */
1207 /*-------------------------------------------------------------------*/
1209 isiCodeEqual (iCode * left, iCode * right)
1211 /* if the same pointer */
1215 /* if either of them null */
1216 if (!left || !right)
1219 /* if operand are the same */
1220 if (left->op == right->op)
1223 /* compare all the elements depending on type */
1224 if (left->op != IFX)
1226 if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
1228 if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
1234 if (!isOperandEqual (IC_COND (left), IC_COND (right)))
1236 if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
1238 if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
1247 /*-----------------------------------------------------------------*/
1248 /* newiTempFromOp - create a temp Operand with same attributes */
1249 /*-----------------------------------------------------------------*/
1251 newiTempFromOp (operand * op)
1261 nop = newiTempOperand (operandType (op), TRUE);
1262 nop->isaddr = op->isaddr;
1263 nop->isvolatile = op->isvolatile;
1264 nop->isGlobal = op->isGlobal;
1265 nop->isLiteral = op->isLiteral;
1266 nop->usesDefs = op->usesDefs;
1267 nop->isParm = op->isParm;
1271 /*-----------------------------------------------------------------*/
1272 /* operand from operand - creates an operand holder for the type */
1273 /*-----------------------------------------------------------------*/
1275 operandFromOperand (operand * op)
1281 nop = newOperand ();
1282 nop->type = op->type;
1283 nop->isaddr = op->isaddr;
1285 nop->isvolatile = op->isvolatile;
1286 nop->isGlobal = op->isGlobal;
1287 nop->isLiteral = op->isLiteral;
1288 nop->usesDefs = op->usesDefs;
1289 nop->isParm = op->isParm;
1294 nop->operand.symOperand = op->operand.symOperand;
1297 nop->operand.valOperand = op->operand.valOperand;
1300 nop->operand.typeOperand = op->operand.typeOperand;
1307 /*-----------------------------------------------------------------*/
1308 /* opFromOpWithDU - makes a copy of the operand and DU chains */
1309 /*-----------------------------------------------------------------*/
1311 opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
1313 operand *nop = operandFromOperand (op);
1315 if (nop->type == SYMBOL)
1317 OP_SYMBOL (nop)->defs = bitVectCopy (defs);
1318 OP_SYMBOL (nop)->uses = bitVectCopy (uses);
1324 /*-----------------------------------------------------------------*/
1325 /* operandFromSymbol - creates an operand from a symbol */
1326 /*-----------------------------------------------------------------*/
1328 operandFromSymbol (symbol * sym)
1333 /* if the symbol's type is a literal */
1334 /* then it is an enumerator type */
1335 if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
1336 return operandFromValue (valFromType (sym->etype));
1339 sym->key = ++operandKey;
1341 /* if this an implicit variable, means struct/union */
1342 /* member so just return it */
1343 if (sym->implicit || IS_FUNC (sym->type))
1347 op->operand.symOperand = sym;
1349 op->isvolatile = isOperandVolatile (op, TRUE);
1350 op->isGlobal = isOperandGlobal (op);
1354 /* under the following conditions create a
1355 register equivalent for a local symbol */
1356 if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
1357 (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
1358 (!(options.model == MODEL_FLAT24)) ) &&
1359 options.stackAuto == 0)
1362 if (!IS_AGGREGATE (sym->type) && /* not an aggregate */
1363 !IS_FUNC (sym->type) && /* not a function */
1364 !sym->_isparm && /* not a parameter */
1365 sym->level && /* is a local variable */
1366 !sym->addrtaken && /* whose address has not been taken */
1367 !sym->reqv && /* does not already have a reg equivalence */
1368 !IS_VOLATILE (sym->etype) && /* not declared as volatile */
1369 !IS_STATIC (sym->etype) && /* and not declared static */
1370 !sym->islbl && /* not a label */
1371 ok && /* farspace check */
1372 !IS_BITVAR (sym->etype) /* not a bit variable */
1376 /* we will use it after all optimizations
1377 and before liveRange calculation */
1378 sym->reqv = newiTempOperand (sym->type, 0);
1379 sym->reqv->key = sym->key;
1380 OP_SYMBOL (sym->reqv)->key = sym->key;
1381 OP_SYMBOL (sym->reqv)->isreqv = 1;
1382 OP_SYMBOL (sym->reqv)->islocal = 1;
1383 OP_SYMBOL (sym->reqv)->onStack = sym->onStack;
1384 SPIL_LOC (sym->reqv) = sym;
1387 if (!IS_AGGREGATE (sym->type))
1391 op->operand.symOperand = sym;
1394 op->isvolatile = isOperandVolatile (op, TRUE);
1395 op->isGlobal = isOperandGlobal (op);
1396 op->isPtr = IS_PTR (operandType (op));
1397 op->isParm = sym->_isparm;
1402 /* itemp = &[_symbol] */
1404 ic = newiCode (ADDRESS_OF, newOperand (), NULL);
1405 IC_LEFT (ic)->type = SYMBOL;
1406 IC_LEFT (ic)->operand.symOperand = sym;
1407 IC_LEFT (ic)->key = sym->key;
1408 (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
1409 (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
1410 IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
1413 IC_RESULT (ic) = newiTempOperand (sym->type, 0);
1414 if (IS_ARRAY (sym->type))
1416 IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
1417 IC_RESULT (ic)->isaddr = 0;
1420 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
1424 return IC_RESULT (ic);
1427 /*-----------------------------------------------------------------*/
1428 /* operandFromValue - creates an operand from value */
1429 /*-----------------------------------------------------------------*/
1431 operandFromValue (value * val)
1435 /* if this is a symbol then do the symbol thing */
1437 return operandFromSymbol (val->sym);
1439 /* this is not a symbol */
1442 op->operand.valOperand = val;
1443 op->isLiteral = isOperandLiteral (op);
1447 /*-----------------------------------------------------------------*/
1448 /* operandFromLink - operand from typeChain */
1449 /*-----------------------------------------------------------------*/
1451 operandFromLink (sym_link * type)
1455 /* operand from sym_link */
1461 op->operand.typeOperand = copyLinkChain (type);
1465 /*-----------------------------------------------------------------*/
1466 /* operandFromLit - makes an operand from a literal value */
1467 /*-----------------------------------------------------------------*/
1469 operandFromLit (double i)
1471 return operandFromValue (valueFromLit (i));
1474 /*-----------------------------------------------------------------*/
1475 /* operandFromAst - creates an operand from an ast */
1476 /*-----------------------------------------------------------------*/
1478 operandFromAst (ast * tree,int lvl)
1484 /* depending on type do */
1488 return ast2iCode (tree,lvl+1);
1492 return operandFromValue (tree->opval.val);
1496 return operandFromLink (tree->opval.lnk);
1500 /* Just to keep the comiler happy */
1501 return (operand *) 0;
1504 /*-----------------------------------------------------------------*/
1505 /* setOperandType - sets the operand's type to the given type */
1506 /*-----------------------------------------------------------------*/
1508 setOperandType (operand * op, sym_link * type)
1510 /* depending on the type of operand */
1515 op->operand.valOperand->etype =
1516 getSpec (op->operand.valOperand->type =
1517 copyLinkChain (type));
1521 if (op->operand.symOperand->isitmp)
1522 op->operand.symOperand->etype =
1523 getSpec (op->operand.symOperand->type =
1524 copyLinkChain (type));
1526 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1527 "attempt to modify type of source");
1531 op->operand.typeOperand = copyLinkChain (type);
1536 /*-----------------------------------------------------------------*/
1537 /* Get size in byte of ptr need to access an array */
1538 /*-----------------------------------------------------------------*/
1540 getArraySizePtr (operand * op)
1542 sym_link *ltype = operandType(op);
1546 int size = getSize(ltype);
1547 return(IS_GENPTR(ltype)?(size-1):size);
1552 sym_link *letype = getSpec(ltype);
1553 switch (PTR_TYPE (SPEC_OCLS (letype)))
1565 return (GPTRSIZE-1);
1574 /*-----------------------------------------------------------------*/
1575 /* perform "usual unary conversions" */
1576 /*-----------------------------------------------------------------*/
1578 usualUnaryConversions (operand * op)
1580 if (IS_INTEGRAL (operandType (op)))
1582 if (getSize (operandType (op)) < (unsigned int) INTSIZE)
1585 return geniCodeCast (INTTYPE, op, TRUE);
1591 /*-----------------------------------------------------------------*/
1592 /* perform "usual binary conversions" */
1593 /*-----------------------------------------------------------------*/
1595 usualBinaryConversions (operand ** op1, operand ** op2)
1598 sym_link *rtype = operandType (*op2);
1599 sym_link *ltype = operandType (*op1);
1601 ctype = computeType (ltype, rtype);
1602 *op1 = geniCodeCast (ctype, *op1, TRUE);
1603 *op2 = geniCodeCast (ctype, *op2, TRUE);
1608 /*-----------------------------------------------------------------*/
1609 /* geniCodeValueAtAddress - generate intermeditate code for value */
1611 /*-----------------------------------------------------------------*/
1613 geniCodeRValue (operand * op, bool force)
1616 sym_link *type = operandType (op);
1617 sym_link *etype = getSpec (type);
1619 /* if this is an array & already */
1620 /* an address then return this */
1621 if (IS_AGGREGATE (type) ||
1622 (IS_PTR (type) && !force && !op->isaddr))
1623 return operandFromOperand (op);
1625 /* if this is not an address then must be */
1626 /* rvalue already so return this one */
1630 /* if this is not a temp symbol then */
1631 if (!IS_ITEMP (op) &&
1633 !IN_FARSPACE (SPEC_OCLS (etype)))
1635 op = operandFromOperand (op);
1640 if (IS_SPEC (type) &&
1641 IS_TRUE_SYMOP (op) &&
1642 (!IN_FARSPACE (SPEC_OCLS (etype)) ||
1643 /* TARGET_IS_DS390)) */
1644 (options.model == MODEL_FLAT24) ))
1646 op = operandFromOperand (op);
1651 ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1652 if (IS_PTR (type) && op->isaddr && force)
1655 type = copyLinkChain (type);
1657 IC_RESULT (ic) = newiTempOperand (type, 1);
1658 IC_RESULT (ic)->isaddr = 0;
1660 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1664 return IC_RESULT (ic);
1667 /*-----------------------------------------------------------------*/
1668 /* geniCodeCast - changes the value from one type to another */
1669 /*-----------------------------------------------------------------*/
1671 geniCodeCast (sym_link * type, operand * op, bool implicit)
1675 sym_link *opetype = getSpec (optype = operandType (op));
1679 /* one of them has size zero then error */
1680 if (IS_VOID (optype))
1682 werror (E_CAST_ZERO);
1686 /* if the operand is already the desired type then do nothing */
1687 if (compareType (type, optype) == 1)
1690 /* if this is a literal then just change the type & return */
1691 if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1692 return operandFromValue (valCastLiteral (type,
1693 operandLitValue (op)));
1695 /* if casting to/from pointers, do some checking */
1696 if (IS_PTR(type)) { // to a pointer
1697 if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer
1698 if (IS_INTEGRAL(optype)) {
1699 // maybe this is NULL, than it's ok.
1700 if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
1701 if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80 && IS_GENPTR(type)) {
1702 // no way to set the storage
1703 if (IS_LITERAL(optype)) {
1704 werror(E_LITERAL_GENERIC);
1707 werror(E_NONPTR2_GENPTR);
1710 } else if (implicit) {
1711 werror(W_INTEGRAL2PTR_NOCAST);
1716 // shouldn't do that with float, array or structure unless to void
1717 if (!IS_VOID(getSpec(type)) &&
1718 !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1719 werror(E_INCOMPAT_TYPES);
1723 } else { // from a pointer to a pointer
1724 if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80) {
1725 // if not a pointer to a function
1726 if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1727 if (implicit) { // if not to generic, they have to match
1728 if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
1729 werror(E_INCOMPAT_PTYPES);
1736 } else { // to a non pointer
1737 if (IS_PTR(optype)) { // from a pointer
1738 if (implicit) { // sneaky
1739 if (IS_INTEGRAL(type)) {
1740 werror(W_PTR2INTEGRAL_NOCAST);
1742 } else { // shouldn't do that with float, array or structure
1743 werror(E_INCOMPAT_TYPES);
1750 printFromToType (optype, type);
1753 /* if they are the same size create an assignment */
1754 if (getSize (type) == getSize (optype) &&
1755 !IS_BITFIELD (type) &&
1757 !IS_FLOAT (optype) &&
1758 ((IS_SPEC (type) && IS_SPEC (optype)) ||
1759 (!IS_SPEC (type) && !IS_SPEC (optype))))
1762 ic = newiCode ('=', NULL, op);
1763 IC_RESULT (ic) = newiTempOperand (type, 0);
1764 SPIL_LOC (IC_RESULT (ic)) =
1765 (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
1766 IC_RESULT (ic)->isaddr = 0;
1770 ic = newiCode (CAST, operandFromLink (type),
1771 geniCodeRValue (op, FALSE));
1773 IC_RESULT (ic) = newiTempOperand (type, 0);
1776 /* preserve the storage class & output class */
1777 /* of the original variable */
1778 restype = getSpec (operandType (IC_RESULT (ic)));
1779 SPEC_SCLS (restype) = SPEC_SCLS (opetype);
1780 SPEC_OCLS (restype) = SPEC_OCLS (opetype);
1783 return IC_RESULT (ic);
1786 /*-----------------------------------------------------------------*/
1787 /* geniCodeLabel - will create a Label */
1788 /*-----------------------------------------------------------------*/
1790 geniCodeLabel (symbol * label)
1794 ic = newiCodeLabelGoto (LABEL, label);
1798 /*-----------------------------------------------------------------*/
1799 /* geniCodeGoto - will create a Goto */
1800 /*-----------------------------------------------------------------*/
1802 geniCodeGoto (symbol * label)
1806 ic = newiCodeLabelGoto (GOTO, label);
1810 /*-----------------------------------------------------------------*/
1811 /* geniCodeMultiply - gen intermediate code for multiplication */
1812 /*-----------------------------------------------------------------*/
1814 geniCodeMultiply (operand * left, operand * right,int resultIsInt)
1821 /* if they are both literal then we know the result */
1822 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1823 return operandFromValue (valMult (left->operand.valOperand,
1824 right->operand.valOperand));
1826 if (IS_LITERAL(retype)) {
1827 p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
1830 resType = usualBinaryConversions (&left, &right);
1832 rtype = operandType (right);
1833 retype = getSpec (rtype);
1834 ltype = operandType (left);
1835 letype = getSpec (ltype);
1839 SPEC_NOUN(getSpec(resType))=V_INT;
1842 /* if the right is a literal & power of 2 */
1843 /* then make it a left shift */
1844 /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
1845 efficient in most cases than 2 bytes result = 2 bytes << literal
1846 if port has 1 byte muldiv */
1847 if (p2 && !IS_FLOAT (letype) &&
1848 !((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
1849 (port->support.muldiv == 1)))
1851 if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
1853 /* LEFT_OP need same size for left and result, */
1854 left = geniCodeCast (resType, left, TRUE);
1855 ltype = operandType (left);
1857 ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
1861 ic = newiCode ('*', left, right); /* normal multiplication */
1862 /* if the size left or right > 1 then support routine */
1863 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1867 IC_RESULT (ic) = newiTempOperand (resType, 1);
1870 return IC_RESULT (ic);
1873 /*-----------------------------------------------------------------*/
1874 /* geniCodeDivision - gen intermediate code for division */
1875 /*-----------------------------------------------------------------*/
1877 geniCodeDivision (operand * left, operand * right)
1882 sym_link *rtype = operandType (right);
1883 sym_link *retype = getSpec (rtype);
1884 sym_link *ltype = operandType (left);
1885 sym_link *letype = getSpec (ltype);
1887 resType = usualBinaryConversions (&left, &right);
1889 /* if the right is a literal & power of 2 */
1890 /* then make it a right shift */
1891 if (IS_LITERAL (retype) &&
1892 !IS_FLOAT (letype) &&
1893 (p2 = powof2 ((unsigned long)
1894 floatFromVal (right->operand.valOperand)))) {
1895 ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
1899 ic = newiCode ('/', left, right); /* normal division */
1900 /* if the size left or right > 1 then support routine */
1901 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1904 IC_RESULT (ic) = newiTempOperand (resType, 0);
1907 return IC_RESULT (ic);
1909 /*-----------------------------------------------------------------*/
1910 /* geniCodeModulus - gen intermediate code for modulus */
1911 /*-----------------------------------------------------------------*/
1913 geniCodeModulus (operand * left, operand * right)
1919 /* if they are both literal then we know the result */
1920 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1921 return operandFromValue (valMod (left->operand.valOperand,
1922 right->operand.valOperand));
1924 resType = usualBinaryConversions (&left, &right);
1926 /* now they are the same size */
1927 ic = newiCode ('%', left, right);
1929 /* if the size left or right > 1 then support routine */
1930 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1932 IC_RESULT (ic) = newiTempOperand (resType, 0);
1935 return IC_RESULT (ic);
1938 /*-----------------------------------------------------------------*/
1939 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
1940 /*-----------------------------------------------------------------*/
1942 geniCodePtrPtrSubtract (operand * left, operand * right)
1948 /* if they are both literals then */
1949 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1951 result = operandFromValue (valMinus (left->operand.valOperand,
1952 right->operand.valOperand));
1956 ic = newiCode ('-', left, right);
1958 IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
1962 return geniCodeDivision (result,
1963 operandFromLit (getSize (ltype->next)));
1966 /*-----------------------------------------------------------------*/
1967 /* geniCodeSubtract - generates code for subtraction */
1968 /*-----------------------------------------------------------------*/
1970 geniCodeSubtract (operand * left, operand * right)
1977 /* if they both pointers then */
1978 if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
1979 (IS_PTR (rtype) || IS_ARRAY (rtype)))
1980 return geniCodePtrPtrSubtract (left, right);
1982 /* if they are both literal then we know the result */
1983 if (IS_LITERAL (letype) && IS_LITERAL (retype)
1984 && left->isLiteral && right->isLiteral)
1985 return operandFromValue (valMinus (left->operand.valOperand,
1986 right->operand.valOperand));
1988 /* if left is an array or pointer */
1989 if (IS_PTR (ltype) || IS_ARRAY (ltype))
1991 isarray = left->isaddr;
1992 right = geniCodeMultiply (right,
1993 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
1994 resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
1997 { /* make them the same size */
1998 resType = usualBinaryConversions (&left, &right);
2001 ic = newiCode ('-', left, right);
2003 IC_RESULT (ic) = newiTempOperand (resType, 1);
2004 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2006 /* if left or right is a float */
2007 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2011 return IC_RESULT (ic);
2014 /*-----------------------------------------------------------------*/
2015 /* geniCodeAdd - generates iCode for addition */
2016 /*-----------------------------------------------------------------*/
2018 geniCodeAdd (operand * left, operand * right, int lvl)
2026 /* if left is an array then array access */
2027 if (IS_ARRAY (ltype))
2028 return geniCodeArray (left, right,lvl);
2030 /* if the right side is LITERAL zero */
2031 /* return the left side */
2032 if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
2035 /* if left is literal zero return right */
2036 if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
2039 /* if left is a pointer then size */
2042 isarray = left->isaddr;
2043 // there is no need to multiply with 1
2044 if (getSize(ltype->next)!=1) {
2045 size = operandFromLit (getSize (ltype->next));
2046 right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
2048 resType = copyLinkChain (ltype);
2051 { // make them the same size
2052 resType = usualBinaryConversions (&left, &right);
2055 /* if they are both literals then we know */
2056 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2057 && left->isLiteral && right->isLiteral)
2058 return operandFromValue (valPlus (valFromType (letype),
2059 valFromType (retype)));
2061 ic = newiCode ('+', left, right);
2063 IC_RESULT (ic) = newiTempOperand (resType, 1);
2064 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2066 /* if left or right is a float then support
2068 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2073 return IC_RESULT (ic);
2077 /*-----------------------------------------------------------------*/
2078 /* aggrToPtr - changes an aggregate to pointer to an aggregate */
2079 /*-----------------------------------------------------------------*/
2081 aggrToPtr (sym_link * type, bool force)
2087 if (IS_PTR (type) && !force)
2090 etype = getSpec (type);
2094 /* if the output class is generic */
2095 if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER)
2096 DCL_PTR_CONST (ptype) = port->mem.code_ro;
2098 /* if the variable was declared a constant */
2099 /* then the pointer points to a constant */
2100 if (IS_CONSTANT (etype))
2101 DCL_PTR_CONST (ptype) = 1;
2103 /* the variable was volatile then pointer to volatile */
2104 if (IS_VOLATILE (etype))
2105 DCL_PTR_VOLATILE (ptype) = 1;
2109 /*-----------------------------------------------------------------*/
2110 /* geniCodeArray2Ptr - array to pointer */
2111 /*-----------------------------------------------------------------*/
2113 geniCodeArray2Ptr (operand * op)
2115 sym_link *optype = operandType (op);
2116 sym_link *opetype = getSpec (optype);
2118 /* set the pointer depending on the storage class */
2119 if ((DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2120 DCL_PTR_CONST (optype) = port->mem.code_ro;
2123 /* if the variable was declared a constant */
2124 /* then the pointer points to a constant */
2125 if (IS_CONSTANT (opetype))
2126 DCL_PTR_CONST (optype) = 1;
2128 /* the variable was volatile then pointer to volatile */
2129 if (IS_VOLATILE (opetype))
2130 DCL_PTR_VOLATILE (optype) = 1;
2136 /*-----------------------------------------------------------------*/
2137 /* geniCodeArray - array access */
2138 /*-----------------------------------------------------------------*/
2140 geniCodeArray (operand * left, operand * right,int lvl)
2143 sym_link *ltype = operandType (left);
2147 if (IS_PTR (ltype->next) && left->isaddr)
2149 left = geniCodeRValue (left, FALSE);
2151 return geniCodeDerefPtr (geniCodeAdd (left, right, lvl), lvl);
2154 right = geniCodeMultiply (right,
2155 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2157 /* we can check for limits here */
2158 if (isOperandLiteral (right) &&
2161 (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2163 werror (E_ARRAY_BOUND);
2164 right = operandFromLit (0);
2167 ic = newiCode ('+', left, right);
2169 IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2170 !IS_AGGREGATE (ltype->next) &&
2171 !IS_PTR (ltype->next))
2172 ? ltype : ltype->next), 0);
2174 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
2176 return IC_RESULT (ic);
2179 /*-----------------------------------------------------------------*/
2180 /* geniCodeStruct - generates intermediate code for structres */
2181 /*-----------------------------------------------------------------*/
2183 geniCodeStruct (operand * left, operand * right, bool islval)
2186 sym_link *type = operandType (left);
2187 sym_link *etype = getSpec (type);
2189 symbol *element = getStructElement (SPEC_STRUCT (etype),
2190 right->operand.symOperand);
2192 /* add the offset */
2193 ic = newiCode ('+', left, operandFromLit (element->offset));
2195 IC_RESULT (ic) = newiTempOperand (element->type, 0);
2197 /* preserve the storage & output class of the struct */
2198 /* as well as the volatile attribute */
2199 retype = getSpec (operandType (IC_RESULT (ic)));
2200 SPEC_SCLS (retype) = SPEC_SCLS (etype);
2201 SPEC_OCLS (retype) = SPEC_OCLS (etype);
2202 SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2204 if (IS_PTR (element->type))
2205 setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2207 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2211 return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2214 /*-----------------------------------------------------------------*/
2215 /* geniCodePostInc - generate int code for Post increment */
2216 /*-----------------------------------------------------------------*/
2218 geniCodePostInc (operand * op)
2222 sym_link *optype = operandType (op);
2224 operand *rv = (IS_ITEMP (op) ?
2225 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2227 sym_link *rvtype = operandType (rv);
2230 /* if this is not an address we have trouble */
2233 werror (E_LVALUE_REQUIRED, "++");
2237 rOp = newiTempOperand (rvtype, 0);
2238 OP_SYMBOL(rOp)->noSpilLoc = 1;
2241 OP_SYMBOL(rv)->noSpilLoc = 1;
2243 geniCodeAssign (rOp, rv, 0);
2245 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2246 if (IS_FLOAT (rvtype))
2247 ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2249 ic = newiCode ('+', rv, operandFromLit (size));
2251 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2254 geniCodeAssign (op, result, 0);
2260 /*-----------------------------------------------------------------*/
2261 /* geniCodePreInc - generate code for preIncrement */
2262 /*-----------------------------------------------------------------*/
2264 geniCodePreInc (operand * op)
2267 sym_link *optype = operandType (op);
2268 operand *rop = (IS_ITEMP (op) ?
2269 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2271 sym_link *roptype = operandType (rop);
2277 werror (E_LVALUE_REQUIRED, "++");
2282 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2283 if (IS_FLOAT (roptype))
2284 ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2286 ic = newiCode ('+', rop, operandFromLit (size));
2287 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2291 return geniCodeAssign (op, result, 0);
2294 /*-----------------------------------------------------------------*/
2295 /* geniCodePostDec - generates code for Post decrement */
2296 /*-----------------------------------------------------------------*/
2298 geniCodePostDec (operand * op)
2302 sym_link *optype = operandType (op);
2304 operand *rv = (IS_ITEMP (op) ?
2305 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2307 sym_link *rvtype = operandType (rv);
2310 /* if this is not an address we have trouble */
2313 werror (E_LVALUE_REQUIRED, "--");
2317 rOp = newiTempOperand (rvtype, 0);
2318 OP_SYMBOL(rOp)->noSpilLoc = 1;
2321 OP_SYMBOL(rv)->noSpilLoc = 1;
2323 geniCodeAssign (rOp, rv, 0);
2325 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2326 if (IS_FLOAT (rvtype))
2327 ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2329 ic = newiCode ('-', rv, operandFromLit (size));
2331 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2334 geniCodeAssign (op, result, 0);
2340 /*-----------------------------------------------------------------*/
2341 /* geniCodePreDec - generate code for pre decrement */
2342 /*-----------------------------------------------------------------*/
2344 geniCodePreDec (operand * op)
2347 sym_link *optype = operandType (op);
2348 operand *rop = (IS_ITEMP (op) ?
2349 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2351 sym_link *roptype = operandType (rop);
2357 werror (E_LVALUE_REQUIRED, "--");
2362 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2363 if (IS_FLOAT (roptype))
2364 ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2366 ic = newiCode ('-', rop, operandFromLit (size));
2367 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2371 return geniCodeAssign (op, result, 0);
2375 /*-----------------------------------------------------------------*/
2376 /* geniCodeBitwise - gen int code for bitWise operators */
2377 /*-----------------------------------------------------------------*/
2379 geniCodeBitwise (operand * left, operand * right,
2380 int oper, sym_link * resType)
2384 left = geniCodeCast (resType, left, TRUE);
2385 right = geniCodeCast (resType, right, TRUE);
2387 ic = newiCode (oper, left, right);
2388 IC_RESULT (ic) = newiTempOperand (resType, 0);
2391 return IC_RESULT (ic);
2394 /*-----------------------------------------------------------------*/
2395 /* geniCodeAddressOf - gens icode for '&' address of operator */
2396 /*-----------------------------------------------------------------*/
2398 geniCodeAddressOf (operand * op)
2402 sym_link *optype = operandType (op);
2403 sym_link *opetype = getSpec (optype);
2405 /* lvalue check already done in decorateType */
2406 /* this must be a lvalue */
2407 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2408 /* werror (E_LVALUE_REQUIRED,"&"); */
2413 p->class = DECLARATOR;
2415 /* set the pointer depending on the storage class */
2416 if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2417 DCL_PTR_CONST (p) = port->mem.code_ro;
2419 /* make sure we preserve the const & volatile */
2420 if (IS_CONSTANT (opetype))
2421 DCL_PTR_CONST (p) = 1;
2423 if (IS_VOLATILE (opetype))
2424 DCL_PTR_VOLATILE (p) = 1;
2426 p->next = copyLinkChain (optype);
2428 /* if already a temp */
2431 setOperandType (op, p);
2436 /* other wise make this of the type coming in */
2437 ic = newiCode (ADDRESS_OF, op, NULL);
2438 IC_RESULT (ic) = newiTempOperand (p, 1);
2439 IC_RESULT (ic)->isaddr = 0;
2441 return IC_RESULT (ic);
2443 /*-----------------------------------------------------------------*/
2444 /* setOClass - sets the output class depending on the pointer type */
2445 /*-----------------------------------------------------------------*/
2447 setOClass (sym_link * ptr, sym_link * spec)
2449 switch (DCL_TYPE (ptr))
2452 SPEC_OCLS (spec) = data;
2456 SPEC_OCLS (spec) = generic;
2460 SPEC_OCLS (spec) = xdata;
2464 SPEC_OCLS (spec) = code;
2468 SPEC_OCLS (spec) = idata;
2472 SPEC_OCLS (spec) = xstack;
2476 SPEC_OCLS (spec) = eeprom;
2485 /*-----------------------------------------------------------------*/
2486 /* geniCodeDerefPtr - dereference pointer with '*' */
2487 /*-----------------------------------------------------------------*/
2489 geniCodeDerefPtr (operand * op,int lvl)
2491 sym_link *rtype, *retype;
2492 sym_link *optype = operandType (op);
2494 /* if this is a pointer then generate the rvalue */
2495 if (IS_PTR (optype))
2497 if (IS_TRUE_SYMOP (op))
2500 op = geniCodeRValue (op, TRUE);
2503 op = geniCodeRValue (op, TRUE);
2506 /* now get rid of the pointer part */
2507 if (isLvaluereq(lvl) && IS_ITEMP (op))
2509 retype = getSpec (rtype = copyLinkChain (optype));
2513 retype = getSpec (rtype = copyLinkChain (optype->next));
2516 /* if this is a pointer then outputclass needs 2b updated */
2517 if (IS_PTR (optype))
2518 setOClass (optype, retype);
2520 op->isGptr = IS_GENPTR (optype);
2522 /* if the pointer was declared as a constant */
2523 /* then we cannot allow assignment to the derefed */
2524 if (IS_PTR_CONST (optype))
2525 SPEC_CONST (retype) = 1;
2527 op->isaddr = (IS_PTR (rtype) ||
2528 IS_STRUCT (rtype) ||
2533 if (!isLvaluereq(lvl))
2534 op = geniCodeRValue (op, TRUE);
2536 setOperandType (op, rtype);
2541 /*-----------------------------------------------------------------*/
2542 /* geniCodeUnaryMinus - does a unary minus of the operand */
2543 /*-----------------------------------------------------------------*/
2545 geniCodeUnaryMinus (operand * op)
2548 sym_link *optype = operandType (op);
2550 if (IS_LITERAL (optype))
2551 return operandFromLit (-floatFromVal (op->operand.valOperand));
2553 ic = newiCode (UNARYMINUS, op, NULL);
2554 IC_RESULT (ic) = newiTempOperand (optype, 0);
2556 return IC_RESULT (ic);
2559 /*-----------------------------------------------------------------*/
2560 /* geniCodeLeftShift - gen i code for left shift */
2561 /*-----------------------------------------------------------------*/
2563 geniCodeLeftShift (operand * left, operand * right)
2567 ic = newiCode (LEFT_OP, left, right);
2568 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2570 return IC_RESULT (ic);
2573 /*-----------------------------------------------------------------*/
2574 /* geniCodeRightShift - gen i code for right shift */
2575 /*-----------------------------------------------------------------*/
2577 geniCodeRightShift (operand * left, operand * right)
2581 ic = newiCode (RIGHT_OP, left, right);
2582 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2584 return IC_RESULT (ic);
2587 /*-----------------------------------------------------------------*/
2588 /* geniCodeLogic- logic code */
2589 /*-----------------------------------------------------------------*/
2591 geniCodeLogic (operand * left, operand * right, int op)
2595 sym_link *rtype = operandType (right);
2596 sym_link *ltype = operandType (left);
2598 /* left is integral type and right is literal then
2599 check if the literal value is within bounds */
2600 if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2602 checkConstantRange(ltype,
2603 OP_VALUE(right), "compare operation", 1);
2606 ctype = usualBinaryConversions (&left, &right);
2608 ic = newiCode (op, left, right);
2609 IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2611 /* if comparing float
2612 and not a '==' || '!=' || '&&' || '||' (these
2614 if (IS_FLOAT(ctype) &&
2622 return IC_RESULT (ic);
2625 /*-----------------------------------------------------------------*/
2626 /* geniCodeUnary - for a a generic unary operation */
2627 /*-----------------------------------------------------------------*/
2629 geniCodeUnary (operand * op, int oper)
2631 iCode *ic = newiCode (oper, op, NULL);
2633 IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2635 return IC_RESULT (ic);
2638 /*-----------------------------------------------------------------*/
2639 /* geniCodeConditional - geniCode for '?' ':' operation */
2640 /*-----------------------------------------------------------------*/
2642 geniCodeConditional (ast * tree,int lvl)
2645 symbol *falseLabel = newiTempLabel (NULL);
2646 symbol *exitLabel = newiTempLabel (NULL);
2647 operand *cond = ast2iCode (tree->left,lvl+1);
2648 operand *true, *false, *result;
2650 ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
2654 true = ast2iCode (tree->right->left,lvl+1);
2656 /* move the value to a new Operand */
2657 result = newiTempOperand (tree->right->ftype, 0);
2658 geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
2660 /* generate an unconditional goto */
2661 geniCodeGoto (exitLabel);
2663 /* now for the right side */
2664 geniCodeLabel (falseLabel);
2666 false = ast2iCode (tree->right->right,lvl+1);
2667 geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
2669 /* create the exit label */
2670 geniCodeLabel (exitLabel);
2675 /*-----------------------------------------------------------------*/
2676 /* geniCodeAssign - generate code for assignment */
2677 /*-----------------------------------------------------------------*/
2679 geniCodeAssign (operand * left, operand * right, int nosupdate)
2682 sym_link *ltype = operandType (left);
2683 sym_link *rtype = operandType (right);
2685 if (!left->isaddr && !IS_ITEMP (left))
2687 werror (E_LVALUE_REQUIRED, "assignment");
2691 /* left is integral type and right is literal then
2692 check if the literal value is within bounds */
2693 if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
2695 checkConstantRange(ltype,
2696 OP_VALUE(right), "= operation", 0);
2699 /* if the left & right type don't exactly match */
2700 /* if pointer set then make sure the check is
2701 done with the type & not the pointer */
2702 /* then cast rights type to left */
2704 /* first check the type for pointer assignement */
2705 if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
2706 compareType (ltype, rtype) <= 0)
2708 if (compareType (ltype->next, rtype) < 0)
2709 right = geniCodeCast (ltype->next, right, TRUE);
2711 else if (compareType (ltype, rtype) < 0)
2712 right = geniCodeCast (ltype, right, TRUE);
2714 /* if left is a true symbol & ! volatile
2715 create an assignment to temporary for
2716 the right & then assign this temporary
2717 to the symbol this is SSA . isn't it simple
2718 and folks have published mountains of paper on it */
2719 if (IS_TRUE_SYMOP (left) &&
2720 !isOperandVolatile (left, FALSE) &&
2721 isOperandGlobal (left))
2725 if (IS_TRUE_SYMOP (right))
2726 sym = OP_SYMBOL (right);
2727 ic = newiCode ('=', NULL, right);
2728 IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
2729 SPIL_LOC (right) = sym;
2733 ic = newiCode ('=', NULL, right);
2734 IC_RESULT (ic) = left;
2737 /* if left isgptr flag is set then support
2738 routine will be required */
2742 ic->nosupdate = nosupdate;
2746 /*-----------------------------------------------------------------*/
2747 /* geniCodeSEParms - generate code for side effecting fcalls */
2748 /*-----------------------------------------------------------------*/
2750 geniCodeSEParms (ast * parms,int lvl)
2755 if (parms->type == EX_OP && parms->opval.op == PARAM)
2757 geniCodeSEParms (parms->left,lvl);
2758 geniCodeSEParms (parms->right,lvl);
2762 /* hack don't like this but too lazy to think of
2764 if (IS_ADDRESS_OF_OP (parms))
2765 parms->left->lvalue = 1;
2767 if (IS_CAST_OP (parms) &&
2768 IS_PTR (parms->ftype) &&
2769 IS_ADDRESS_OF_OP (parms->right))
2770 parms->right->left->lvalue = 1;
2772 parms->opval.oprnd =
2773 geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2775 parms->type = EX_OPERAND;
2778 /*-----------------------------------------------------------------*/
2779 /* geniCodeParms - generates parameters */
2780 /*-----------------------------------------------------------------*/
2782 geniCodeParms (ast * parms, value *argVals, int *stack,
2783 sym_link * fetype, symbol * func,int lvl)
2791 if (argVals==NULL) {
2793 argVals=FUNC_ARGS(func->type);
2796 /* if this is a param node then do the left & right */
2797 if (parms->type == EX_OP && parms->opval.op == PARAM)
2799 argVals=geniCodeParms (parms->left, argVals, stack, fetype, func,lvl);
2800 argVals=geniCodeParms (parms->right, argVals, stack, fetype, func,lvl);
2804 /* get the parameter value */
2805 if (parms->type == EX_OPERAND)
2806 pval = parms->opval.oprnd;
2809 /* maybe this else should go away ?? */
2810 /* hack don't like this but too lazy to think of
2812 if (IS_ADDRESS_OF_OP (parms))
2813 parms->left->lvalue = 1;
2815 if (IS_CAST_OP (parms) &&
2816 IS_PTR (parms->ftype) &&
2817 IS_ADDRESS_OF_OP (parms->right))
2818 parms->right->left->lvalue = 1;
2820 pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2823 /* if register parm then make it a send */
2824 if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(func->type)) ||
2825 IFFUNC_ISBUILTIN(func->type))
2827 ic = newiCode (SEND, pval, NULL);
2828 ic->builtinSEND = FUNC_ISBUILTIN(func->type);
2833 /* now decide whether to push or assign */
2834 if (!(options.stackAuto || IFFUNC_ISREENT (func->type)))
2838 operand *top = operandFromSymbol (argVals->sym);
2839 /* clear useDef and other bitVectors */
2840 OP_USES (top) = OP_DEFS (top) = OP_SYMBOL(top)->clashes = NULL;
2841 geniCodeAssign (top, pval, 1);
2845 sym_link *p = operandType (pval);
2847 ic = newiCode (IPUSH, pval, NULL);
2849 /* update the stack adjustment */
2850 *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2855 argVals=argVals->next;
2859 /*-----------------------------------------------------------------*/
2860 /* geniCodeCall - generates temp code for calling */
2861 /*-----------------------------------------------------------------*/
2863 geniCodeCall (operand * left, ast * parms,int lvl)
2867 sym_link *type, *etype;
2870 if (!IS_FUNC(OP_SYMBOL(left)->type) &&
2871 !IS_CODEPTR(OP_SYMBOL(left)->type)) {
2872 werror (E_FUNCTION_EXPECTED);
2876 /* take care of parameters with side-effecting
2877 function calls in them, this is required to take care
2878 of overlaying function parameters */
2879 geniCodeSEParms (parms,lvl);
2881 /* first the parameters */
2882 geniCodeParms (parms, NULL, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
2884 /* now call : if symbol then pcall */
2885 if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
2886 ic = newiCode (PCALL, left, NULL);
2888 ic = newiCode (CALL, left, NULL);
2891 type = copyLinkChain (operandType (left)->next);
2892 etype = getSpec (type);
2893 SPEC_EXTR (etype) = 0;
2894 IC_RESULT (ic) = result = newiTempOperand (type, 1);
2898 /* stack adjustment after call */
2899 ic->parmBytes = stack;
2904 /*-----------------------------------------------------------------*/
2905 /* geniCodeReceive - generate intermediate code for "receive" */
2906 /*-----------------------------------------------------------------*/
2908 geniCodeReceive (value * args)
2910 /* for all arguments that are passed in registers */
2914 if (IS_REGPARM (args->etype))
2916 operand *opr = operandFromValue (args);
2918 symbol *sym = OP_SYMBOL (opr);
2921 /* we will use it after all optimizations
2922 and before liveRange calculation */
2923 if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
2926 if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
2927 options.stackAuto == 0 &&
2928 /* !TARGET_IS_DS390) */
2929 (!(options.model == MODEL_FLAT24)) )
2934 opl = newiTempOperand (args->type, 0);
2936 sym->reqv->key = sym->key;
2937 OP_SYMBOL (sym->reqv)->key = sym->key;
2938 OP_SYMBOL (sym->reqv)->isreqv = 1;
2939 OP_SYMBOL (sym->reqv)->islocal = 0;
2940 SPIL_LOC (sym->reqv) = sym;
2944 ic = newiCode (RECEIVE, NULL, NULL);
2945 currFunc->recvSize = getSize (sym->etype);
2946 IC_RESULT (ic) = opr;
2954 /*-----------------------------------------------------------------*/
2955 /* geniCodeFunctionBody - create the function body */
2956 /*-----------------------------------------------------------------*/
2958 geniCodeFunctionBody (ast * tree,int lvl)
2965 /* reset the auto generation */
2971 func = ast2iCode (tree->left,lvl+1);
2972 fetype = getSpec (operandType (func));
2974 savelineno = lineno;
2975 lineno = OP_SYMBOL (func)->lineDef;
2976 /* create an entry label */
2977 geniCodeLabel (entryLabel);
2978 lineno = savelineno;
2980 /* create a proc icode */
2981 ic = newiCode (FUNCTION, func, NULL);
2982 ic->lineno = OP_SYMBOL (func)->lineDef;
2986 /* for all parameters that are passed
2987 on registers add a "receive" */
2988 geniCodeReceive (tree->values.args);
2990 /* generate code for the body */
2991 ast2iCode (tree->right,lvl+1);
2993 /* create a label for return */
2994 geniCodeLabel (returnLabel);
2996 /* now generate the end proc */
2997 ic = newiCode (ENDFUNCTION, func, NULL);
3002 /*-----------------------------------------------------------------*/
3003 /* geniCodeReturn - gen icode for 'return' statement */
3004 /*-----------------------------------------------------------------*/
3006 geniCodeReturn (operand * op)
3010 /* if the operand is present force an rvalue */
3012 op = geniCodeRValue (op, FALSE);
3014 ic = newiCode (RETURN, op, NULL);
3018 /*-----------------------------------------------------------------*/
3019 /* geniCodeIfx - generates code for extended if statement */
3020 /*-----------------------------------------------------------------*/
3022 geniCodeIfx (ast * tree,int lvl)
3025 operand *condition = ast2iCode (tree->left,lvl+1);
3028 /* if condition is null then exit */
3032 condition = geniCodeRValue (condition, FALSE);
3034 cetype = getSpec (operandType (condition));
3035 /* if the condition is a literal */
3036 if (IS_LITERAL (cetype))
3038 if (floatFromVal (condition->operand.valOperand))
3040 if (tree->trueLabel)
3041 geniCodeGoto (tree->trueLabel);
3047 if (tree->falseLabel)
3048 geniCodeGoto (tree->falseLabel);
3055 if (tree->trueLabel)
3057 ic = newiCodeCondition (condition,
3062 if (tree->falseLabel)
3063 geniCodeGoto (tree->falseLabel);
3067 ic = newiCodeCondition (condition,
3074 ast2iCode (tree->right,lvl+1);
3077 /*-----------------------------------------------------------------*/
3078 /* geniCodeJumpTable - tries to create a jump table for switch */
3079 /*-----------------------------------------------------------------*/
3081 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
3083 int min = 0, max = 0, t, cnt = 0;
3090 if (!tree || !caseVals)
3093 /* the criteria for creating a jump table is */
3094 /* all integer numbers between the maximum & minimum must */
3095 /* be present , the maximum value should not exceed 255 */
3096 min = max = (int) floatFromVal (vch = caseVals);
3097 sprintf (buffer, "_case_%d_%d",
3098 tree->values.switchVals.swNum,
3100 addSet (&labels, newiTempLabel (buffer));
3102 /* if there is only one case value then no need */
3103 if (!(vch = vch->next))
3108 if (((t = (int) floatFromVal (vch)) - max) != 1)
3110 sprintf (buffer, "_case_%d_%d",
3111 tree->values.switchVals.swNum,
3113 addSet (&labels, newiTempLabel (buffer));
3119 /* if the number of case statements <= 2 then */
3120 /* it is not economical to create the jump table */
3121 /* since two compares are needed for boundary conditions */
3122 if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
3125 if (tree->values.switchVals.swDefault)
3126 sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3128 sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3130 falseLabel = newiTempLabel (buffer);
3132 /* so we can create a jumptable */
3133 /* first we rule out the boundary conditions */
3134 /* if only optimization says so */
3135 if (!optimize.noJTabBoundary)
3137 sym_link *cetype = getSpec (operandType (cond));
3138 /* no need to check the lower bound if
3139 the condition is unsigned & minimum value is zero */
3140 if (!(min == 0 && SPEC_USIGN (cetype)))
3142 boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3143 ic = newiCodeCondition (boundary, falseLabel, NULL);
3147 /* now for upper bounds */
3148 boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3149 ic = newiCodeCondition (boundary, falseLabel, NULL);
3153 /* if the min is not zero then we no make it zero */
3156 cond = geniCodeSubtract (cond, operandFromLit (min));
3157 setOperandType (cond, UCHARTYPE);
3160 /* now create the jumptable */
3161 ic = newiCode (JUMPTABLE, NULL, NULL);
3162 IC_JTCOND (ic) = cond;
3163 IC_JTLABELS (ic) = labels;
3168 /*-----------------------------------------------------------------*/
3169 /* geniCodeSwitch - changes a switch to a if statement */
3170 /*-----------------------------------------------------------------*/
3172 geniCodeSwitch (ast * tree,int lvl)
3175 operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3176 value *caseVals = tree->values.switchVals.swVals;
3177 symbol *trueLabel, *falseLabel;
3179 /* if we can make this a jump table */
3180 if (geniCodeJumpTable (cond, caseVals, tree))
3181 goto jumpTable; /* no need for the comparison */
3183 /* for the cases defined do */
3187 operand *compare = geniCodeLogic (cond,
3188 operandFromValue (caseVals),
3191 sprintf (buffer, "_case_%d_%d",
3192 tree->values.switchVals.swNum,
3193 (int) floatFromVal (caseVals));
3194 trueLabel = newiTempLabel (buffer);
3196 ic = newiCodeCondition (compare, trueLabel, NULL);
3198 caseVals = caseVals->next;
3203 /* if default is present then goto break else break */
3204 if (tree->values.switchVals.swDefault)
3205 sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3207 sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3209 falseLabel = newiTempLabel (buffer);
3210 geniCodeGoto (falseLabel);
3213 ast2iCode (tree->right,lvl+1);
3216 /*-----------------------------------------------------------------*/
3217 /* geniCodeInline - intermediate code for inline assembler */
3218 /*-----------------------------------------------------------------*/
3220 geniCodeInline (ast * tree)
3224 ic = newiCode (INLINEASM, NULL, NULL);
3225 IC_INLINE (ic) = tree->values.inlineasm;
3229 /*-----------------------------------------------------------------*/
3230 /* geniCodeArrayInit - intermediate code for array initializer */
3231 /*-----------------------------------------------------------------*/
3233 geniCodeArrayInit (ast * tree, operand *array)
3237 if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3238 ic = newiCode (ARRAYINIT, array, NULL);
3239 IC_ARRAYILIST (ic) = tree->values.constlist;
3241 operand *left=newOperand(), *right=newOperand();
3242 left->type=right->type=SYMBOL;
3243 OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3244 OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3245 ic = newiCode (ARRAYINIT, left, right);
3250 /*-----------------------------------------------------------------*/
3251 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
3252 /* particular case. Ie : assigning or dereferencing array or ptr */
3253 /*-----------------------------------------------------------------*/
3254 set * lvaluereqSet = NULL;
3255 typedef struct lvalItem
3262 /*-----------------------------------------------------------------*/
3263 /* addLvaluereq - add a flag for lvalreq for current ast level */
3264 /*-----------------------------------------------------------------*/
3265 void addLvaluereq(int lvl)
3267 lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3270 addSetHead(&lvaluereqSet,lpItem);
3273 /*-----------------------------------------------------------------*/
3274 /* delLvaluereq - del a flag for lvalreq for current ast level */
3275 /*-----------------------------------------------------------------*/
3279 lpItem = getSet(&lvaluereqSet);
3280 if(lpItem) Safe_free(lpItem);
3282 /*-----------------------------------------------------------------*/
3283 /* clearLvaluereq - clear lvalreq flag */
3284 /*-----------------------------------------------------------------*/
3285 void clearLvaluereq()
3288 lpItem = peekSet(lvaluereqSet);
3289 if(lpItem) lpItem->req = 0;
3291 /*-----------------------------------------------------------------*/
3292 /* getLvaluereq - get the last lvalreq level */
3293 /*-----------------------------------------------------------------*/
3294 int getLvaluereqLvl()
3297 lpItem = peekSet(lvaluereqSet);
3298 if(lpItem) return lpItem->lvl;
3301 /*-----------------------------------------------------------------*/
3302 /* isLvaluereq - is lvalreq valid for this level ? */
3303 /*-----------------------------------------------------------------*/
3304 int isLvaluereq(int lvl)
3307 lpItem = peekSet(lvaluereqSet);
3308 if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3312 /*-----------------------------------------------------------------*/
3313 /* ast2iCode - creates an icodeList from an ast */
3314 /*-----------------------------------------------------------------*/
3316 ast2iCode (ast * tree,int lvl)
3318 operand *left = NULL;
3319 operand *right = NULL;
3322 /* set the global variables for filename & line number */
3324 filename = tree->filename;
3326 lineno = tree->lineno;
3328 block = tree->block;
3330 scopeLevel = tree->level;
3332 if (tree->type == EX_VALUE)
3333 return operandFromValue (tree->opval.val);
3335 if (tree->type == EX_LINK)
3336 return operandFromLink (tree->opval.lnk);
3338 /* if we find a nullop */
3339 if (tree->type == EX_OP &&
3340 (tree->opval.op == NULLOP ||
3341 tree->opval.op == BLOCK))
3343 ast2iCode (tree->left,lvl+1);
3344 ast2iCode (tree->right,lvl+1);
3348 /* special cases for not evaluating */
3349 if (tree->opval.op != ':' &&
3350 tree->opval.op != '?' &&
3351 tree->opval.op != CALL &&
3352 tree->opval.op != IFX &&
3353 tree->opval.op != LABEL &&
3354 tree->opval.op != GOTO &&
3355 tree->opval.op != SWITCH &&
3356 tree->opval.op != FUNCTION &&
3357 tree->opval.op != INLINEASM)
3360 if (IS_ASSIGN_OP (tree->opval.op) ||
3361 IS_DEREF_OP (tree) ||
3362 (tree->opval.op == '&' && !tree->right) ||
3363 tree->opval.op == PTR_OP)
3366 if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3367 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3370 left = operandFromAst (tree->left,lvl);
3372 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3373 left = geniCodeRValue (left, TRUE);
3377 left = operandFromAst (tree->left,lvl);
3379 if (tree->opval.op == INC_OP ||
3380 tree->opval.op == DEC_OP)
3383 right = operandFromAst (tree->right,lvl);
3388 right = operandFromAst (tree->right,lvl);
3392 /* now depending on the type of operand */
3393 /* this will be a biggy */
3394 switch (tree->opval.op)
3397 case '[': /* array operation */
3399 //sym_link *ltype = operandType (left);
3400 //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3401 left = geniCodeRValue (left, FALSE);
3402 right = geniCodeRValue (right, TRUE);
3405 return geniCodeArray (left, right,lvl);
3407 case '.': /* structure dereference */
3408 if (IS_PTR (operandType (left)))
3409 left = geniCodeRValue (left, TRUE);
3411 left = geniCodeRValue (left, FALSE);
3413 return geniCodeStruct (left, right, tree->lvalue);
3415 case PTR_OP: /* structure pointer dereference */
3418 pType = operandType (left);
3419 left = geniCodeRValue (left, TRUE);
3421 setOClass (pType, getSpec (operandType (left)));
3424 return geniCodeStruct (left, right, tree->lvalue);
3426 case INC_OP: /* increment operator */
3428 return geniCodePostInc (left);
3430 return geniCodePreInc (right);
3432 case DEC_OP: /* decrement operator */
3434 return geniCodePostDec (left);
3436 return geniCodePreDec (right);
3438 case '&': /* bitwise and or address of operator */
3440 { /* this is a bitwise operator */
3441 left = geniCodeRValue (left, FALSE);
3442 right = geniCodeRValue (right, FALSE);
3443 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3446 return geniCodeAddressOf (left);
3448 case '|': /* bitwise or & xor */
3450 return geniCodeBitwise (geniCodeRValue (left, FALSE),
3451 geniCodeRValue (right, FALSE),
3456 return geniCodeDivision (geniCodeRValue (left, FALSE),
3457 geniCodeRValue (right, FALSE));
3460 return geniCodeModulus (geniCodeRValue (left, FALSE),
3461 geniCodeRValue (right, FALSE));
3464 return geniCodeMultiply (geniCodeRValue (left, FALSE),
3465 geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3467 return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3471 return geniCodeSubtract (geniCodeRValue (left, FALSE),
3472 geniCodeRValue (right, FALSE));
3474 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3478 return geniCodeAdd (geniCodeRValue (left, FALSE),
3479 geniCodeRValue (right, FALSE),lvl);
3481 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
3484 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3485 geniCodeRValue (right, FALSE));
3488 return geniCodeRightShift (geniCodeRValue (left, FALSE),
3489 geniCodeRValue (right, FALSE));
3491 return geniCodeCast (operandType (left),
3492 geniCodeRValue (right, FALSE), FALSE);
3498 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3502 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3503 setOperandType (op, UCHARTYPE);
3514 return geniCodeLogic (geniCodeRValue (left, FALSE),
3515 geniCodeRValue (right, FALSE),
3518 return geniCodeConditional (tree,lvl);
3521 return operandFromLit (getSize (tree->right->ftype));
3525 sym_link *rtype = operandType (right);
3526 sym_link *ltype = operandType (left);
3527 if (IS_PTR (rtype) && IS_ITEMP (right)
3528 && right->isaddr && compareType (rtype->next, ltype) == 1)
3529 right = geniCodeRValue (right, TRUE);
3531 right = geniCodeRValue (right, FALSE);
3533 geniCodeAssign (left, right, 0);
3538 geniCodeAssign (left,
3539 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3541 geniCodeRValue (right, FALSE),FALSE), 0);
3545 geniCodeAssign (left,
3546 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3548 geniCodeRValue (right, FALSE)), 0);
3551 geniCodeAssign (left,
3552 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3554 geniCodeRValue (right, FALSE)), 0);
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);
3566 return geniCodeAssign (left,
3567 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3573 sym_link *rtype = operandType (right);
3574 sym_link *ltype = operandType (left);
3575 if (IS_PTR (rtype) && IS_ITEMP (right)
3576 && right->isaddr && compareType (rtype->next, ltype) == 1)
3578 right = geniCodeRValue (right, TRUE);
3582 right = geniCodeRValue (right, FALSE);
3585 geniCodeAssign (left,
3586 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3592 geniCodeAssign (left,
3593 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3595 geniCodeRValue (right, FALSE)), 0);
3598 geniCodeAssign (left,
3599 geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3601 geniCodeRValue (right, FALSE)), 0);
3604 geniCodeAssign (left,
3605 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3607 geniCodeRValue (right, FALSE),
3609 operandType (left)), 0);
3612 geniCodeAssign (left,
3613 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3615 geniCodeRValue (right, FALSE),
3617 operandType (left)), 0);
3620 geniCodeAssign (left,
3621 geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3623 geniCodeRValue (right, FALSE),
3625 operandType (left)), 0);
3627 return geniCodeRValue (right, FALSE);
3630 return geniCodeCall (ast2iCode (tree->left,lvl+1),
3633 geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3634 return ast2iCode (tree->right,lvl+1);
3637 geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3638 return ast2iCode (tree->right,lvl+1);
3641 geniCodeFunctionBody (tree,lvl);
3645 geniCodeReturn (right);
3649 geniCodeIfx (tree,lvl);
3653 geniCodeSwitch (tree,lvl);
3657 geniCodeInline (tree);
3661 geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
3668 /*-----------------------------------------------------------------*/
3669 /* reverseICChain - gets from the list and creates a linkedlist */
3670 /*-----------------------------------------------------------------*/
3677 while ((loop = getSet (&iCodeChain)))
3689 /*-----------------------------------------------------------------*/
3690 /* iCodeFromAst - given an ast will convert it to iCode */
3691 /*-----------------------------------------------------------------*/
3693 iCodeFromAst (ast * tree)
3695 returnLabel = newiTempLabel ("_return");
3696 entryLabel = newiTempLabel ("_entry");
3698 return reverseiCChain ();