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);
70 PRINTFUNC (picDummyRead);
72 iCodeTable codeTable[] =
74 {'!', "not", picGenericOne, NULL},
75 {'~', "~", picGenericOne, NULL},
76 {RRC, "rrc", picGenericOne, NULL},
77 {RLC, "rlc", picGenericOne, NULL},
78 {GETHBIT, "ghbit", picGenericOne, NULL},
79 {UNARYMINUS, "-", picGenericOne, NULL},
80 {IPUSH, "push", picGenericOne, NULL},
81 {IPOP, "pop", picGenericOne, NULL},
82 {CALL, "call", picGenericOne, NULL},
83 {PCALL, "pcall", picGenericOne, NULL},
84 {FUNCTION, "proc", picGenericOne, NULL},
85 {ENDFUNCTION, "eproc", picGenericOne, NULL},
86 {RETURN, "ret", picGenericOne, NULL},
87 {'+', "+", picGeneric, NULL},
88 {'-', "-", picGeneric, NULL},
89 {'*', "*", picGeneric, NULL},
90 {'/', "/", picGeneric, NULL},
91 {'%', "%", picGeneric, NULL},
92 {'>', ">", picGeneric, NULL},
93 {'<', "<", picGeneric, NULL},
94 {LE_OP, "<=", picGeneric, NULL},
95 {GE_OP, ">=", picGeneric, NULL},
96 {EQ_OP, "==", picGeneric, NULL},
97 {NE_OP, "!=", picGeneric, NULL},
98 {AND_OP, "&&", picGeneric, NULL},
99 {OR_OP, "||", picGeneric, NULL},
100 {'^', "^", picGeneric, NULL},
101 {'|', "|", picGeneric, NULL},
102 {BITWISEAND, "&", picGeneric, NULL},
103 {LEFT_OP, "<<", picGeneric, NULL},
104 {RIGHT_OP, ">>", picGeneric, NULL},
105 {GET_VALUE_AT_ADDRESS, "@", picGetValueAtAddr, NULL},
106 {ADDRESS_OF, "&", picAddrOf, NULL},
107 {CAST, "<>", picCast, NULL},
108 {'=', ":=", picAssign, NULL},
109 {LABEL, "", picLabel, NULL},
110 {GOTO, "", picGoto, NULL},
111 {JUMPTABLE, "jtab", picJumpTable, NULL},
112 {IFX, "if", picIfx, NULL},
113 {INLINEASM, "", picInline, NULL},
114 {RECEIVE, "recv", picReceive, NULL},
115 {SEND, "send", picGenericOne, NULL},
116 {ARRAYINIT, "arrayInit", picGenericOne, NULL},
117 {DUMMY_READ_VOLATILE, "dummy = (volatile)", picDummyRead, NULL}
120 /*-----------------------------------------------------------------*/
121 /* checkConstantRange: check a constant against the type */
122 /*-----------------------------------------------------------------*/
124 /* pedantic=0: allmost anything is allowed as long as the absolute
125 value is within the bit range of the type, and -1 is treated as
126 0xf..f for unsigned types (e.g. in assign)
127 pedantic=1: -1==-1, not allowed for unsigned types (e.g. in compare)
128 pedantic>1: "char c=200" is not allowed (evaluates to -56)
131 void checkConstantRange(sym_link *ltype, value *val, char *msg,
138 max = pow ((double)2.0, (double)bitsForType(ltype));
140 if (SPEC_LONG(val->type)) {
141 if (SPEC_USIGN(val->type)) {
142 v=SPEC_CVAL(val->type).v_ulong;
144 v=SPEC_CVAL(val->type).v_long;
147 if (SPEC_USIGN(val->type)) {
148 v=SPEC_CVAL(val->type).v_uint;
150 v=SPEC_CVAL(val->type).v_int;
156 // this could be a good idea
157 if (options.pedantic)
161 if (SPEC_NOUN(ltype)==FLOAT) {
166 if (!SPEC_USIGN(val->type) && v<0) {
168 if (SPEC_USIGN(ltype) && (pedantic>1)) {
174 // if very pedantic: "char c=200" is not allowed
175 if (pedantic>1 && !SPEC_USIGN(ltype)) {
176 max = max/2 + negative;
183 #if 0 // temporary disabled, leaving the warning as a reminder
185 SNPRINTF (message, sizeof(message), "for %s %s in %s",
186 SPEC_USIGN(ltype) ? "unsigned" : "signed",
187 nounName(ltype), msg);
188 werror (W_CONST_RANGE, message);
196 /*-----------------------------------------------------------------*/
197 /* operandName - returns the name of the operand */
198 /*-----------------------------------------------------------------*/
200 printOperand (operand * op, FILE * file)
217 opetype = getSpec (operandType (op));
218 if (SPEC_NOUN (opetype) == V_FLOAT)
219 fprintf (file, "%g {", SPEC_CVAL (opetype).v_float);
221 fprintf (file, "0x%x {", (unsigned) floatFromVal (op->operand.valOperand));
222 printTypeChain (operandType (op), file);
229 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}" , */
230 (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name),
232 OP_LIVEFROM (op), OP_LIVETO (op),
233 OP_SYMBOL (op)->stack,
234 op->isaddr, OP_SYMBOL (op)->isreqv,
235 OP_SYMBOL (op)->remat,OP_SYMBOL(op)->noSpilLoc,
236 OP_SYMBOL(op)->ruonly,OP_SYMBOL(op)->dptr
240 printTypeChain (operandType (op), file);
241 if (SPIL_LOC (op) && IS_ITEMP (op))
242 fprintf (file, "}{ sir@ %s", SPIL_LOC (op)->rname);
247 /* if assigned to registers */
248 if (OP_SYMBOL (op)->nRegs)
250 if (OP_SYMBOL (op)->isspilt)
252 if (!OP_SYMBOL (op)->remat)
253 if (OP_SYMBOL (op)->usl.spillLoc)
254 fprintf (file, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
255 OP_SYMBOL (op)->usl.spillLoc->rname :
256 OP_SYMBOL (op)->usl.spillLoc->name));
258 fprintf (file, "[err]");
260 fprintf (file, "[remat]");
266 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
267 fprintf (file, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i]));
272 fprintf (file, "%s", (OP_SYMBOL (op)->rname[0] ?
273 OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name));
274 /* if assigned to registers */
275 if (OP_SYMBOL (op)->nRegs && !OP_SYMBOL (op)->isspilt)
279 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
280 fprintf (file, "%s ", (OP_SYMBOL (op)->regs[i] ?
281 OP_SYMBOL (op)->regs[i]->name :
290 printTypeChain (op->operand.typeOperand, file);
296 fprintf (file, "\n");
301 /*-----------------------------------------------------------------*/
302 /* print functions */
303 /*-----------------------------------------------------------------*/
304 PRINTFUNC (picGetValueAtAddr)
307 printOperand (IC_RESULT (ic), of);
310 printOperand (IC_LEFT (ic), of);
316 PRINTFUNC (picSetValueAtAddr)
320 printOperand (IC_LEFT (ic), of);
321 fprintf (of, "] = ");
322 printOperand (IC_RIGHT (ic), of);
326 PRINTFUNC (picAddrOf)
329 printOperand (IC_RESULT (ic), of);
330 if (IS_ITEMP (IC_LEFT (ic)))
333 fprintf (of, " = &[");
334 printOperand (IC_LEFT (ic), of);
337 if (IS_ITEMP (IC_LEFT (ic)))
338 fprintf (of, " offsetAdd ");
341 printOperand (IC_RIGHT (ic), of);
343 if (IS_ITEMP (IC_LEFT (ic)))
349 PRINTFUNC (picJumpTable)
354 fprintf (of, "%s\t", s);
355 printOperand (IC_JTCOND (ic), of);
357 for (sym = setFirstItem (IC_JTLABELS (ic)); sym;
358 sym = setNextItem (IC_JTLABELS (ic)))
359 fprintf (of, "\t\t\t%s\n", sym->name);
362 PRINTFUNC (picGeneric)
365 printOperand (IC_RESULT (ic), of);
367 printOperand (IC_LEFT (ic), of);
368 fprintf (of, " %s ", s);
369 printOperand (IC_RIGHT (ic), of);
373 PRINTFUNC (picGenericOne)
378 printOperand (IC_RESULT (ic), of);
384 fprintf (of, "%s ", s);
385 printOperand (IC_LEFT (ic), of);
388 if (!IC_RESULT (ic) && !IC_LEFT (ic))
391 if (ic->op == SEND || ic->op == RECEIVE) {
392 fprintf(of,"{argreg = %d}",ic->argreg);
400 printOperand (IC_RESULT (ic), of);
402 printOperand (IC_LEFT (ic), of);
403 printOperand (IC_RIGHT (ic), of);
408 PRINTFUNC (picAssign)
412 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
415 printOperand (IC_RESULT (ic), of);
417 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
420 fprintf (of, " %s ", s);
421 printOperand (IC_RIGHT (ic), of);
428 fprintf (of, " %s($%d) :\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
434 fprintf (of, " goto %s($%d)\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
441 printOperand (IC_COND (ic), of);
444 fprintf (of, " == 0 goto %s($%d)\n", IC_FALSE (ic)->name, IC_FALSE (ic)->key);
447 fprintf (of, " != 0 goto %s($%d)\n", IC_TRUE (ic)->name, IC_TRUE (ic)->key);
449 fprintf (of, "\tzzgoto %s\n", IC_FALSE (ic)->name);
453 PRINTFUNC (picInline)
455 fprintf (of, "%s", IC_INLINE (ic));
458 PRINTFUNC (picReceive)
460 printOperand (IC_RESULT (ic), of);
461 fprintf (of, " = %s ", s);
462 printOperand (IC_LEFT (ic), of);
466 PRINTFUNC (picDummyRead)
469 fprintf (of, "%s ", s);
470 printOperand (IC_RIGHT (ic), of);
474 /*-----------------------------------------------------------------*/
475 /* piCode - prints one iCode */
476 /*-----------------------------------------------------------------*/
478 piCode (void *item, FILE * of)
486 icTab = getTableEntry (ic->op);
487 fprintf (stdout, "%s(%d:%d:%d:%d:%d)\t",
488 ic->filename, ic->lineno,
489 ic->seq, ic->key, ic->depth, ic->supportRtn);
490 icTab->iCodePrint (of, ic, icTab->printName);
496 printiCChain(ic,stdout);
498 /*-----------------------------------------------------------------*/
499 /* printiCChain - prints intermediate code for humans */
500 /*-----------------------------------------------------------------*/
502 printiCChain (iCode * icChain, FILE * of)
509 for (loop = icChain; loop; loop = loop->next)
511 if ((icTab = getTableEntry (loop->op)))
513 fprintf (of, "%s(l%d:s%d:k%d:d%d:s%d)\t",
514 loop->filename, loop->lineno,
515 loop->seq, loop->key, loop->depth, loop->supportRtn);
517 icTab->iCodePrint (of, loop, icTab->printName);
523 /*-----------------------------------------------------------------*/
524 /* newOperand - allocate, init & return a new iCode */
525 /*-----------------------------------------------------------------*/
531 op = Safe_alloc ( sizeof (operand));
537 /*-----------------------------------------------------------------*/
538 /* newiCode - create and return a new iCode entry initialised */
539 /*-----------------------------------------------------------------*/
541 newiCode (int op, operand * left, operand * right)
545 ic = Safe_alloc ( sizeof (iCode));
548 ic->filename = filename;
550 ic->level = scopeLevel;
552 ic->key = iCodeKey++;
554 IC_RIGHT (ic) = right;
559 /*-----------------------------------------------------------------*/
560 /* newiCode for conditional statements */
561 /*-----------------------------------------------------------------*/
563 newiCodeCondition (operand * condition,
569 if (IS_VOID(operandType(condition))) {
570 werror(E_VOID_VALUE_USED);
573 ic = newiCode (IFX, NULL, NULL);
574 IC_COND (ic) = condition;
575 IC_TRUE (ic) = trueLabel;
576 IC_FALSE (ic) = falseLabel;
580 /*-----------------------------------------------------------------*/
581 /* newiCodeLabelGoto - unconditional goto statement| label stmnt */
582 /*-----------------------------------------------------------------*/
584 newiCodeLabelGoto (int op, symbol * label)
588 ic = newiCode (op, NULL, NULL);
592 IC_RIGHT (ic) = NULL;
593 IC_RESULT (ic) = NULL;
597 /*-----------------------------------------------------------------*/
598 /* newiTemp - allocate & return a newItemp Variable */
599 /*-----------------------------------------------------------------*/
607 SNPRINTF (buffer, sizeof(buffer), "%s", s);
611 SNPRINTF (buffer, sizeof(buffer), "iTemp%d", iTempNum++);
614 itmp = newSymbol (buffer, 1);
615 strncpyz (itmp->rname, itmp->name, SDCC_NAME_MAX);
621 /*-----------------------------------------------------------------*/
622 /* newiTempLabel - creates a temp variable label */
623 /*-----------------------------------------------------------------*/
625 newiTempLabel (char *s)
629 /* check if this alredy exists */
630 if (s && (itmplbl = findSym (LabelTab, NULL, s)))
635 itmplbl = newSymbol (s, 1);
639 SNPRINTF (buffer, sizeof(buffer), "iTempLbl%d", iTempLblNum++);
640 itmplbl = newSymbol (buffer, 1);
645 itmplbl->key = labelKey++;
646 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
650 /*-----------------------------------------------------------------*/
651 /* newiTempPreheaderLabel - creates a new preheader label */
652 /*-----------------------------------------------------------------*/
654 newiTempPreheaderLabel ()
658 SNPRINTF (buffer, sizeof(buffer), "preHeaderLbl%d", iTempLblNum++);
659 itmplbl = newSymbol (buffer, 1);
663 itmplbl->key = labelKey++;
664 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
669 /*-----------------------------------------------------------------*/
670 /* initiCode - initialises some iCode related stuff */
671 /*-----------------------------------------------------------------*/
678 /*-----------------------------------------------------------------*/
679 /* copyiCode - make a copy of the iCode given */
680 /*-----------------------------------------------------------------*/
682 copyiCode (iCode * ic)
684 iCode *nic = newiCode (ic->op, NULL, NULL);
686 nic->lineno = ic->lineno;
687 nic->filename = ic->filename;
688 nic->block = ic->block;
689 nic->level = ic->level;
690 nic->parmBytes = ic->parmBytes;
692 /* deal with the special cases first */
696 IC_COND (nic) = operandFromOperand (IC_COND (ic));
697 IC_TRUE (nic) = IC_TRUE (ic);
698 IC_FALSE (nic) = IC_FALSE (ic);
702 IC_JTCOND (nic) = operandFromOperand (IC_JTCOND (ic));
703 IC_JTLABELS (nic) = IC_JTLABELS (ic);
708 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
709 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
713 IC_INLINE (nic) = IC_INLINE (ic);
717 IC_ARRAYILIST(nic) = IC_ARRAYILIST(ic);
721 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
722 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
723 IC_RIGHT (nic) = operandFromOperand (IC_RIGHT (ic));
729 /*-----------------------------------------------------------------*/
730 /* getTableEntry - gets the table entry for the given operator */
731 /*-----------------------------------------------------------------*/
733 getTableEntry (int oper)
737 for (i = 0; i < (sizeof (codeTable) / sizeof (iCodeTable)); i++)
738 if (oper == codeTable[i].icode)
739 return &codeTable[i];
744 /*-----------------------------------------------------------------*/
745 /* newiTempOperand - new intermediate temp operand */
746 /*-----------------------------------------------------------------*/
748 newiTempOperand (sym_link * type, char throwType)
751 operand *op = newOperand ();
755 itmp = newiTemp (NULL);
757 etype = getSpec (type);
759 if (IS_LITERAL (etype))
762 /* copy the type information */
764 itmp->etype = getSpec (itmp->type = (throwType ? type :
765 copyLinkChain (type)));
766 if (IS_LITERAL (itmp->etype))
768 SPEC_SCLS (itmp->etype) = S_REGISTER;
769 SPEC_OCLS (itmp->etype) = reg;
772 op->operand.symOperand = itmp;
773 op->key = itmp->key = ++operandKey;
777 /*-----------------------------------------------------------------*/
778 /* operandType - returns the type chain for an operand */
779 /*-----------------------------------------------------------------*/
781 operandType (operand * op)
783 /* depending on type of operand */
788 return op->operand.valOperand->type;
791 return op->operand.symOperand->type;
794 return op->operand.typeOperand;
796 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
797 " operand type not known ");
798 assert (0); /* should never come here */
799 /* Just to keep the compiler happy */
800 return (sym_link *) 0;
804 /*-----------------------------------------------------------------*/
805 /* isParamterToCall - will return 1 if op is a parameter to args */
806 /*-----------------------------------------------------------------*/
808 isParameterToCall (value * args, operand * op)
812 wassert (IS_SYMOP(op));
817 isSymbolEqual (op->operand.symOperand, tval->sym))
824 /*-----------------------------------------------------------------*/
825 /* isOperandGlobal - return 1 if operand is a global variable */
826 /*-----------------------------------------------------------------*/
828 isOperandGlobal (operand * op)
837 (op->operand.symOperand->level == 0 ||
838 IS_STATIC (op->operand.symOperand->etype) ||
839 IS_EXTERN (op->operand.symOperand->etype))
846 /*-----------------------------------------------------------------*/
847 /* isOperandVolatile - return 1 if the operand is volatile */
848 /*-----------------------------------------------------------------*/
850 isOperandVolatile (operand * op, bool chkTemp)
855 if (IS_ITEMP (op) && !chkTemp)
858 opetype = getSpec (optype = operandType (op));
860 if (IS_PTR (optype) && DCL_PTR_VOLATILE (optype))
863 if (IS_VOLATILE (opetype))
868 /*-----------------------------------------------------------------*/
869 /* isOperandLiteral - returns 1 if an operand contains a literal */
870 /*-----------------------------------------------------------------*/
872 isOperandLiteral (operand * op)
879 opetype = getSpec (operandType (op));
881 if (IS_LITERAL (opetype))
887 /*-----------------------------------------------------------------*/
888 /* isOperandInFarSpace - will return true if operand is in farSpace */
889 /*-----------------------------------------------------------------*/
891 isOperandInFarSpace (operand * op)
901 if (!IS_TRUE_SYMOP (op))
904 etype = SPIL_LOC (op)->etype;
910 etype = getSpec (operandType (op));
912 return (IN_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
915 /*------------------------------------------------------------------*/
916 /* isOperandInDirSpace - will return true if operand is in dirSpace */
917 /*------------------------------------------------------------------*/
919 isOperandInDirSpace (operand * op)
929 if (!IS_TRUE_SYMOP (op))
932 etype = SPIL_LOC (op)->etype;
938 etype = getSpec (operandType (op));
940 return (IN_DIRSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
943 /*--------------------------------------------------------------------*/
944 /* isOperandInCodeSpace - will return true if operand is in codeSpace */
945 /*--------------------------------------------------------------------*/
947 isOperandInCodeSpace (operand * op)
957 etype = getSpec (operandType (op));
959 if (!IS_TRUE_SYMOP (op))
962 etype = SPIL_LOC (op)->etype;
968 etype = getSpec (operandType (op));
970 return (IN_CODESPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
973 /*-----------------------------------------------------------------*/
974 /* isOperandOnStack - will return true if operand is on stack */
975 /*-----------------------------------------------------------------*/
977 isOperandOnStack (operand * op)
987 etype = getSpec (operandType (op));
988 if (IN_STACK (etype) ||
989 OP_SYMBOL(op)->onStack ||
990 (SPIL_LOC(op) && SPIL_LOC(op)->onStack))
996 /*-----------------------------------------------------------------*/
997 /* operandLitValue - literal value of an operand */
998 /*-----------------------------------------------------------------*/
1000 operandLitValue (operand * op)
1002 assert (isOperandLiteral (op));
1004 return floatFromVal (op->operand.valOperand);
1007 /*-----------------------------------------------------------------*/
1008 /* getBuiltInParms - returns parameters to a builtin functions */
1009 /*-----------------------------------------------------------------*/
1010 iCode *getBuiltinParms (iCode *ic, int *pcount, operand **parms)
1015 /* builtin functions uses only SEND for parameters */
1016 while (ic->op != CALL) {
1017 assert(ic->op == SEND && ic->builtinSEND);
1018 ic->generated = 1; /* mark the icode as generated */
1019 parms[*pcount] = IC_LEFT(ic);
1025 /* make sure this is a builtin function call */
1026 assert(IS_SYMOP(IC_LEFT(ic)));
1027 ftype = operandType(IC_LEFT(ic));
1028 assert(IFFUNC_ISBUILTIN(ftype));
1032 /*-----------------------------------------------------------------*/
1033 /* operandOperation - perforoms operations on operands */
1034 /*-----------------------------------------------------------------*/
1036 operandOperation (operand * left, operand * right,
1037 int op, sym_link * type)
1039 sym_link *let , *ret=NULL;
1040 operand *retval = (operand *) 0;
1042 assert (isOperandLiteral (left));
1043 let = getSpec(operandType(left));
1045 assert (isOperandLiteral (right));
1046 ret = getSpec(operandType(left));
1052 retval = operandFromValue (valCastLiteral (type,
1053 operandLitValue (left) +
1054 operandLitValue (right)));
1057 retval = operandFromValue (valCastLiteral (type,
1058 operandLitValue (left) -
1059 operandLitValue (right)));
1062 retval = operandFromValue (valCastLiteral (type,
1063 operandLitValue (left) *
1064 operandLitValue (right)));
1067 if ((unsigned long) operandLitValue (right) == 0)
1069 werror (E_DIVIDE_BY_ZERO);
1074 retval = operandFromValue (valCastLiteral (type,
1075 operandLitValue (left) /
1076 operandLitValue (right)));
1079 if ((unsigned long) operandLitValue (right) == 0) {
1080 werror (E_DIVIDE_BY_ZERO);
1084 retval = operandFromLit ((SPEC_USIGN(let) ?
1085 (unsigned long) operandLitValue (left) :
1086 (long) operandLitValue (left)) %
1088 (unsigned long) operandLitValue (right) :
1089 (long) operandLitValue (right)));
1093 retval = operandFromLit ((SPEC_USIGN(let) ?
1094 (unsigned long) operandLitValue (left) :
1095 (long) operandLitValue (left)) <<
1097 (unsigned long) operandLitValue (right) :
1098 (long) operandLitValue (right)));
1101 double lval = operandLitValue(left), rval = operandLitValue(right);
1103 switch ((SPEC_USIGN(let) ? 2 : 0) + (SPEC_USIGN(ret) ? 1 : 0))
1105 case 0: // left=unsigned right=unsigned
1106 res=(unsigned long)lval >> (unsigned long)rval;
1108 case 1: // left=unsigned right=signed
1109 res=(unsigned long)lval >> (signed long)rval;
1111 case 2: // left=signed right=unsigned
1112 res=(signed long)lval >> (unsigned long)rval;
1114 case 3: // left=signed right=signed
1115 res=(signed long)lval >> (signed long)rval;
1118 retval = operandFromLit (res);
1122 retval = operandFromLit (operandLitValue (left) ==
1123 operandLitValue (right));
1126 retval = operandFromLit (operandLitValue (left) <
1127 operandLitValue (right));
1130 retval = operandFromLit (operandLitValue (left) <=
1131 operandLitValue (right));
1134 retval = operandFromLit (operandLitValue (left) !=
1135 operandLitValue (right));
1138 retval = operandFromLit (operandLitValue (left) >
1139 operandLitValue (right));
1142 retval = operandFromLit (operandLitValue (left) >=
1143 operandLitValue (right));
1146 retval = operandFromValue (valCastLiteral (type,
1147 (unsigned long)operandLitValue(left) &
1148 (unsigned long)operandLitValue(right)));
1151 retval = operandFromValue (valCastLiteral (type,
1152 (unsigned long)operandLitValue(left) |
1153 (unsigned long)operandLitValue(right)));
1156 retval = operandFromValue (valCastLiteral (type,
1157 (unsigned long)operandLitValue(left) ^
1158 (unsigned long)operandLitValue(right)));
1161 retval = operandFromLit (operandLitValue (left) &&
1162 operandLitValue (right));
1165 retval = operandFromLit (operandLitValue (left) ||
1166 operandLitValue (right));
1170 unsigned long i = (unsigned long) operandLitValue (left);
1172 retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
1178 unsigned long i = (unsigned long) operandLitValue (left);
1180 retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
1186 retval = operandFromLit (-1 * operandLitValue (left));
1190 retval = operandFromLit (~((unsigned long) operandLitValue (left)));
1194 retval = operandFromLit (!operandLitValue (left));
1198 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1199 " operandOperation invalid operator ");
1207 /*-----------------------------------------------------------------*/
1208 /* isOperandEqual - compares two operand & return 1 if they r = */
1209 /*-----------------------------------------------------------------*/
1211 isOperandEqual (operand * left, operand * right)
1213 /* if the pointers are equal then they are equal */
1217 /* if either of them null then false */
1218 if (!left || !right)
1221 if (left->type != right->type)
1224 if (IS_SYMOP (left) && IS_SYMOP (right))
1225 return left->key == right->key;
1227 /* if types are the same */
1231 return isSymbolEqual (left->operand.symOperand,
1232 right->operand.symOperand);
1234 return (floatFromVal (left->operand.valOperand) ==
1235 floatFromVal (right->operand.valOperand));
1237 if (compareType (left->operand.typeOperand,
1238 right->operand.typeOperand) == 1)
1245 /*-------------------------------------------------------------------*/
1246 /* isiCodeEqual - compares two iCodes are equal, returns true if yes */
1247 /*-------------------------------------------------------------------*/
1249 isiCodeEqual (iCode * left, iCode * right)
1251 /* if the same pointer */
1255 /* if either of them null */
1256 if (!left || !right)
1259 /* if operand are the same */
1260 if (left->op == right->op)
1263 /* compare all the elements depending on type */
1264 if (left->op != IFX)
1266 if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
1268 if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
1274 if (!isOperandEqual (IC_COND (left), IC_COND (right)))
1276 if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
1278 if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
1287 /*-----------------------------------------------------------------*/
1288 /* newiTempFromOp - create a temp Operand with same attributes */
1289 /*-----------------------------------------------------------------*/
1291 newiTempFromOp (operand * op)
1301 nop = newiTempOperand (operandType (op), TRUE);
1302 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;
1311 /*-----------------------------------------------------------------*/
1312 /* operand from operand - creates an operand holder for the type */
1313 /*-----------------------------------------------------------------*/
1315 operandFromOperand (operand * op)
1321 nop = newOperand ();
1322 nop->type = op->type;
1323 nop->isaddr = op->isaddr;
1325 nop->isvolatile = op->isvolatile;
1326 nop->isGlobal = op->isGlobal;
1327 nop->isLiteral = op->isLiteral;
1328 nop->usesDefs = op->usesDefs;
1329 nop->isParm = op->isParm;
1334 nop->operand.symOperand = op->operand.symOperand;
1337 nop->operand.valOperand = op->operand.valOperand;
1340 nop->operand.typeOperand = op->operand.typeOperand;
1347 /*-----------------------------------------------------------------*/
1348 /* opFromOpWithDU - makes a copy of the operand and DU chains */
1349 /*-----------------------------------------------------------------*/
1351 opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
1353 operand *nop = operandFromOperand (op);
1355 if (nop->type == SYMBOL)
1357 OP_SYMBOL (nop)->defs = bitVectCopy (defs);
1358 OP_SYMBOL (nop)->uses = bitVectCopy (uses);
1364 /*-----------------------------------------------------------------*/
1365 /* operandFromSymbol - creates an operand from a symbol */
1366 /*-----------------------------------------------------------------*/
1368 operandFromSymbol (symbol * sym)
1373 /* if the symbol's type is a literal */
1374 /* then it is an enumerator type */
1375 if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
1376 return operandFromValue (valFromType (sym->etype));
1379 sym->key = ++operandKey;
1381 /* if this an implicit variable, means struct/union */
1382 /* member so just return it */
1383 if (sym->implicit || IS_FUNC (sym->type))
1387 op->operand.symOperand = sym;
1389 op->isvolatile = isOperandVolatile (op, TRUE);
1390 op->isGlobal = isOperandGlobal (op);
1394 /* under the following conditions create a
1395 register equivalent for a local symbol */
1396 if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
1397 (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
1398 (!(options.model == MODEL_FLAT24)) ) &&
1399 options.stackAuto == 0)
1402 if (!IS_AGGREGATE (sym->type) && /* not an aggregate */
1403 !IS_FUNC (sym->type) && /* not a function */
1404 !sym->_isparm && /* not a parameter */
1405 sym->level && /* is a local variable */
1406 !sym->addrtaken && /* whose address has not been taken */
1407 !sym->reqv && /* does not already have a reg equivalence */
1408 !IS_VOLATILE (sym->etype) && /* not declared as volatile */
1409 !IS_STATIC (sym->etype) && /* and not declared static */
1410 !sym->islbl && /* not a label */
1411 ok && /* farspace check */
1412 !IS_BITVAR (sym->etype) /* not a bit variable */
1416 /* we will use it after all optimizations
1417 and before liveRange calculation */
1418 sym->reqv = newiTempOperand (sym->type, 0);
1419 sym->reqv->key = sym->key;
1420 OP_SYMBOL (sym->reqv)->key = sym->key;
1421 OP_SYMBOL (sym->reqv)->isreqv = 1;
1422 OP_SYMBOL (sym->reqv)->islocal = 1;
1423 OP_SYMBOL (sym->reqv)->onStack = sym->onStack;
1424 SPIL_LOC (sym->reqv) = sym;
1427 if (!IS_AGGREGATE (sym->type))
1431 op->operand.symOperand = sym;
1434 op->isvolatile = isOperandVolatile (op, TRUE);
1435 op->isGlobal = isOperandGlobal (op);
1436 op->isPtr = IS_PTR (operandType (op));
1437 op->isParm = sym->_isparm;
1442 /* itemp = &[_symbol] */
1444 ic = newiCode (ADDRESS_OF, newOperand (), NULL);
1445 IC_LEFT (ic)->type = SYMBOL;
1446 IC_LEFT (ic)->operand.symOperand = sym;
1447 IC_LEFT (ic)->key = sym->key;
1448 (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
1449 (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
1450 IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
1453 IC_RESULT (ic) = newiTempOperand (sym->type, 0);
1454 if (IS_ARRAY (sym->type))
1456 IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
1457 IC_RESULT (ic)->isaddr = 0;
1460 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
1464 return IC_RESULT (ic);
1467 /*-----------------------------------------------------------------*/
1468 /* operandFromValue - creates an operand from value */
1469 /*-----------------------------------------------------------------*/
1471 operandFromValue (value * val)
1475 /* if this is a symbol then do the symbol thing */
1477 return operandFromSymbol (val->sym);
1479 /* this is not a symbol */
1482 op->operand.valOperand = val;
1483 op->isLiteral = isOperandLiteral (op);
1487 /*-----------------------------------------------------------------*/
1488 /* operandFromLink - operand from typeChain */
1489 /*-----------------------------------------------------------------*/
1491 operandFromLink (sym_link * type)
1495 /* operand from sym_link */
1501 op->operand.typeOperand = copyLinkChain (type);
1505 /*-----------------------------------------------------------------*/
1506 /* operandFromLit - makes an operand from a literal value */
1507 /*-----------------------------------------------------------------*/
1509 operandFromLit (double i)
1511 return operandFromValue (valueFromLit (i));
1514 /*-----------------------------------------------------------------*/
1515 /* operandFromAst - creates an operand from an ast */
1516 /*-----------------------------------------------------------------*/
1518 operandFromAst (ast * tree,int lvl)
1524 /* depending on type do */
1528 return ast2iCode (tree,lvl+1);
1532 return operandFromValue (tree->opval.val);
1536 return operandFromLink (tree->opval.lnk);
1543 /* Just to keep the compiler happy */
1544 return (operand *) 0;
1547 /*-----------------------------------------------------------------*/
1548 /* setOperandType - sets the operand's type to the given type */
1549 /*-----------------------------------------------------------------*/
1551 setOperandType (operand * op, sym_link * type)
1553 /* depending on the type of operand */
1558 op->operand.valOperand->etype =
1559 getSpec (op->operand.valOperand->type =
1560 copyLinkChain (type));
1564 if (op->operand.symOperand->isitmp)
1565 op->operand.symOperand->etype =
1566 getSpec (op->operand.symOperand->type =
1567 copyLinkChain (type));
1569 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1570 "attempt to modify type of source");
1574 op->operand.typeOperand = copyLinkChain (type);
1579 /*-----------------------------------------------------------------*/
1580 /* Get size in byte of ptr need to access an array */
1581 /*-----------------------------------------------------------------*/
1583 getArraySizePtr (operand * op)
1585 sym_link *ltype = operandType(op);
1589 int size = getSize(ltype);
1590 return(IS_GENPTR(ltype)?(size-1):size);
1595 sym_link *letype = getSpec(ltype);
1596 switch (PTR_TYPE (SPEC_OCLS (letype)))
1608 return (GPTRSIZE-1);
1617 /*-----------------------------------------------------------------*/
1618 /* perform "usual unary conversions" */
1619 /*-----------------------------------------------------------------*/
1621 usualUnaryConversions (operand * op)
1623 if (IS_INTEGRAL (operandType (op)))
1625 if (getSize (operandType (op)) < (unsigned int) INTSIZE)
1628 return geniCodeCast (INTTYPE, op, TRUE);
1634 /*-----------------------------------------------------------------*/
1635 /* perform "usual binary conversions" */
1636 /*-----------------------------------------------------------------*/
1638 usualBinaryConversions (operand ** op1, operand ** op2)
1641 sym_link *rtype = operandType (*op2);
1642 sym_link *ltype = operandType (*op1);
1644 ctype = computeType (ltype, rtype);
1646 *op1 = geniCodeCast (ctype, *op1, TRUE);
1647 *op2 = geniCodeCast (ctype, *op2, TRUE);
1652 /*-----------------------------------------------------------------*/
1653 /* geniCodeValueAtAddress - generate intermeditate code for value */
1655 /*-----------------------------------------------------------------*/
1657 geniCodeRValue (operand * op, bool force)
1660 sym_link *type = operandType (op);
1661 sym_link *etype = getSpec (type);
1663 /* if this is an array & already */
1664 /* an address then return this */
1665 if (IS_AGGREGATE (type) ||
1666 (IS_PTR (type) && !force && !op->isaddr))
1667 return operandFromOperand (op);
1669 /* if this is not an address then must be */
1670 /* rvalue already so return this one */
1674 /* if this is not a temp symbol then */
1675 if (!IS_ITEMP (op) &&
1677 !IN_FARSPACE (SPEC_OCLS (etype)))
1679 op = operandFromOperand (op);
1684 if (IS_SPEC (type) &&
1685 IS_TRUE_SYMOP (op) &&
1686 (!IN_FARSPACE (SPEC_OCLS (etype)) ||
1687 (options.model == MODEL_FLAT24) ))
1689 op = operandFromOperand (op);
1694 ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1695 if (IS_PTR (type) && op->isaddr && force)
1698 type = copyLinkChain (type);
1700 IC_RESULT (ic) = newiTempOperand (type, 1);
1701 IC_RESULT (ic)->isaddr = 0;
1703 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1707 return IC_RESULT (ic);
1710 /*-----------------------------------------------------------------*/
1711 /* geniCodeCast - changes the value from one type to another */
1712 /*-----------------------------------------------------------------*/
1714 geniCodeCast (sym_link * type, operand * op, bool implicit)
1718 sym_link *opetype = getSpec (optype = operandType (op));
1722 /* one of them has size zero then error */
1723 if (IS_VOID (optype))
1725 werror (E_CAST_ZERO);
1729 /* if the operand is already the desired type then do nothing */
1730 if (compareType (type, optype) == 1)
1733 /* if this is a literal then just change the type & return */
1734 if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1735 return operandFromValue (valCastLiteral (type,
1736 operandLitValue (op)));
1738 /* if casting to/from pointers, do some checking */
1739 if (IS_PTR(type)) { // to a pointer
1740 if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer
1741 if (IS_INTEGRAL(optype)) {
1742 // maybe this is NULL, than it's ok.
1743 if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
1744 if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80 && IS_GENPTR(type)) {
1745 // no way to set the storage
1746 if (IS_LITERAL(optype)) {
1747 werror(E_LITERAL_GENERIC);
1750 werror(E_NONPTR2_GENPTR);
1753 } else if (implicit) {
1754 werror(W_INTEGRAL2PTR_NOCAST);
1759 // shouldn't do that with float, array or structure unless to void
1760 if (!IS_VOID(getSpec(type)) &&
1761 !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1762 werror(E_INCOMPAT_TYPES);
1766 } else { // from a pointer to a pointer
1767 if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80) {
1768 // if not a pointer to a function
1769 if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1770 if (implicit) { // if not to generic, they have to match
1771 if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
1772 werror(E_INCOMPAT_PTYPES);
1779 } else { // to a non pointer
1780 if (IS_PTR(optype)) { // from a pointer
1781 if (implicit) { // sneaky
1782 if (IS_INTEGRAL(type)) {
1783 werror(W_PTR2INTEGRAL_NOCAST);
1785 } else { // shouldn't do that with float, array or structure
1786 werror(E_INCOMPAT_TYPES);
1793 printFromToType (optype, type);
1796 /* if they are the same size create an assignment */
1797 if (getSize (type) == getSize (optype) &&
1798 !IS_BITFIELD (type) &&
1800 !IS_FLOAT (optype) &&
1801 ((IS_SPEC (type) && IS_SPEC (optype)) ||
1802 (!IS_SPEC (type) && !IS_SPEC (optype))))
1805 ic = newiCode ('=', NULL, op);
1806 IC_RESULT (ic) = newiTempOperand (type, 0);
1807 SPIL_LOC (IC_RESULT (ic)) =
1808 (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
1809 IC_RESULT (ic)->isaddr = 0;
1813 ic = newiCode (CAST, operandFromLink (type),
1814 geniCodeRValue (op, FALSE));
1816 IC_RESULT (ic) = newiTempOperand (type, 0);
1819 /* preserve the storage class & output class */
1820 /* of the original variable */
1821 restype = getSpec (operandType (IC_RESULT (ic)));
1822 if (!IS_LITERAL(opetype))
1823 SPEC_SCLS (restype) = SPEC_SCLS (opetype);
1824 SPEC_OCLS (restype) = SPEC_OCLS (opetype);
1827 return IC_RESULT (ic);
1830 /*-----------------------------------------------------------------*/
1831 /* geniCodeLabel - will create a Label */
1832 /*-----------------------------------------------------------------*/
1834 geniCodeLabel (symbol * label)
1838 ic = newiCodeLabelGoto (LABEL, label);
1842 /*-----------------------------------------------------------------*/
1843 /* geniCodeGoto - will create a Goto */
1844 /*-----------------------------------------------------------------*/
1846 geniCodeGoto (symbol * label)
1850 ic = newiCodeLabelGoto (GOTO, label);
1854 /*-----------------------------------------------------------------*/
1855 /* geniCodeMultiply - gen intermediate code for multiplication */
1856 /*-----------------------------------------------------------------*/
1858 geniCodeMultiply (operand * left, operand * right,int resultIsInt)
1865 /* if they are both literal then we know the result */
1866 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1867 return operandFromValue (valMult (left->operand.valOperand,
1868 right->operand.valOperand));
1870 if (IS_LITERAL(retype)) {
1871 p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
1874 resType = usualBinaryConversions (&left, &right);
1876 rtype = operandType (right);
1877 retype = getSpec (rtype);
1878 ltype = operandType (left);
1879 letype = getSpec (ltype);
1883 SPEC_NOUN(getSpec(resType))=V_INT;
1886 /* if the right is a literal & power of 2 */
1887 /* then make it a left shift */
1888 /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
1889 efficient in most cases than 2 bytes result = 2 bytes << literal
1890 if port has 1 byte muldiv */
1891 if (p2 && !IS_FLOAT (letype) &&
1892 !((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
1893 (port->support.muldiv == 1)))
1895 if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
1897 /* LEFT_OP need same size for left and result, */
1898 left = geniCodeCast (resType, left, TRUE);
1899 ltype = operandType (left);
1901 ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
1905 ic = newiCode ('*', left, right); /* normal multiplication */
1906 /* if the size left or right > 1 then support routine */
1907 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1911 IC_RESULT (ic) = newiTempOperand (resType, 1);
1914 return IC_RESULT (ic);
1917 /*-----------------------------------------------------------------*/
1918 /* geniCodeDivision - gen intermediate code for division */
1919 /*-----------------------------------------------------------------*/
1921 geniCodeDivision (operand * left, operand * right)
1926 sym_link *rtype = operandType (right);
1927 sym_link *retype = getSpec (rtype);
1928 sym_link *ltype = operandType (left);
1929 sym_link *letype = getSpec (ltype);
1931 resType = usualBinaryConversions (&left, &right);
1933 /* if the right is a literal & power of 2
1934 and left is unsigned then make it a
1936 if (IS_LITERAL (retype) &&
1937 !IS_FLOAT (letype) &&
1938 SPEC_USIGN(letype) &&
1939 (p2 = powof2 ((unsigned long)
1940 floatFromVal (right->operand.valOperand)))) {
1941 ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
1945 ic = newiCode ('/', left, right); /* normal division */
1946 /* if the size left or right > 1 then support routine */
1947 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1950 IC_RESULT (ic) = newiTempOperand (resType, 0);
1953 return IC_RESULT (ic);
1955 /*-----------------------------------------------------------------*/
1956 /* geniCodeModulus - gen intermediate code for modulus */
1957 /*-----------------------------------------------------------------*/
1959 geniCodeModulus (operand * left, operand * right)
1965 /* if they are both literal then we know the result */
1966 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1967 return operandFromValue (valMod (left->operand.valOperand,
1968 right->operand.valOperand));
1970 resType = usualBinaryConversions (&left, &right);
1972 /* now they are the same size */
1973 ic = newiCode ('%', left, right);
1975 /* if the size left or right > 1 then support routine */
1976 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1978 IC_RESULT (ic) = newiTempOperand (resType, 0);
1981 return IC_RESULT (ic);
1984 /*-----------------------------------------------------------------*/
1985 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
1986 /*-----------------------------------------------------------------*/
1988 geniCodePtrPtrSubtract (operand * left, operand * right)
1994 /* if they are both literals then */
1995 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1997 result = operandFromValue (valMinus (left->operand.valOperand,
1998 right->operand.valOperand));
2002 ic = newiCode ('-', left, right);
2004 IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
2008 if (IS_VOID(ltype->next) || IS_VOID(rtype->next)) {
2012 // should we really do this? is this ANSI?
2013 return geniCodeDivision (result,
2014 operandFromLit (getSize (ltype->next)));
2017 /*-----------------------------------------------------------------*/
2018 /* geniCodeSubtract - generates code for subtraction */
2019 /*-----------------------------------------------------------------*/
2021 geniCodeSubtract (operand * left, operand * right)
2028 /* if they both pointers then */
2029 if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
2030 (IS_PTR (rtype) || IS_ARRAY (rtype)))
2031 return geniCodePtrPtrSubtract (left, right);
2033 /* if they are both literal then we know the result */
2034 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2035 && left->isLiteral && right->isLiteral)
2036 return operandFromValue (valMinus (left->operand.valOperand,
2037 right->operand.valOperand));
2039 /* if left is an array or pointer */
2040 if (IS_PTR (ltype) || IS_ARRAY (ltype))
2042 isarray = left->isaddr;
2043 right = geniCodeMultiply (right,
2044 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2045 resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
2048 { /* make them the same size */
2049 resType = usualBinaryConversions (&left, &right);
2052 ic = newiCode ('-', left, right);
2054 IC_RESULT (ic) = newiTempOperand (resType, 1);
2055 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2057 /* if left or right is a float */
2058 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2062 return IC_RESULT (ic);
2065 /*-----------------------------------------------------------------*/
2066 /* geniCodeAdd - generates iCode for addition */
2067 /*-----------------------------------------------------------------*/
2069 geniCodeAdd (operand * left, operand * right, int lvl)
2077 /* if the right side is LITERAL zero */
2078 /* return the left side */
2079 if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
2082 /* if left is literal zero return right */
2083 if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
2086 /* if left is a pointer then size */
2087 if (IS_PTR (ltype) || IS_ARRAY(ltype))
2089 isarray = left->isaddr;
2090 // there is no need to multiply with 1
2091 if (getSize(ltype->next)!=1) {
2092 size = operandFromLit (getSize (ltype->next));
2093 right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
2095 resType = copyLinkChain (ltype);
2098 { // make them the same size
2099 resType = usualBinaryConversions (&left, &right);
2102 /* if they are both literals then we know */
2103 if (IS_LITERAL (letype) && IS_LITERAL (retype)
2104 && left->isLiteral && right->isLiteral)
2105 return operandFromValue (valPlus (valFromType (letype),
2106 valFromType (retype)));
2108 ic = newiCode ('+', left, right);
2110 IC_RESULT (ic) = newiTempOperand (resType, 1);
2111 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2113 /* if left or right is a float then support
2115 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2120 return IC_RESULT (ic);
2124 /*-----------------------------------------------------------------*/
2125 /* aggrToPtr - changes an aggregate to pointer to an aggregate */
2126 /*-----------------------------------------------------------------*/
2128 aggrToPtr (sym_link * type, bool force)
2134 if (IS_PTR (type) && !force)
2137 etype = getSpec (type);
2138 ptype = newLink (DECLARATOR);
2142 /* if the output class is code */
2143 if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER)
2144 DCL_PTR_CONST (ptype) = port->mem.code_ro;
2146 /* if the variable was declared a constant */
2147 /* then the pointer points to a constant */
2148 if (IS_CONSTANT (etype))
2149 DCL_PTR_CONST (ptype) = 1;
2151 /* the variable was volatile then pointer to volatile */
2152 if (IS_VOLATILE (etype))
2153 DCL_PTR_VOLATILE (ptype) = 1;
2158 /*-----------------------------------------------------------------*/
2159 /* geniCodeArray2Ptr - array to pointer */
2160 /*-----------------------------------------------------------------*/
2162 geniCodeArray2Ptr (operand * op)
2164 sym_link *optype = operandType (op);
2165 sym_link *opetype = getSpec (optype);
2167 /* set the pointer depending on the storage class */
2168 if ((DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2169 DCL_PTR_CONST (optype) = port->mem.code_ro;
2171 /* if the variable was declared a constant */
2172 /* then the pointer points to a constant */
2173 if (IS_CONSTANT (opetype))
2174 DCL_PTR_CONST (optype) = 1;
2176 /* the variable was volatile then pointer to volatile */
2177 if (IS_VOLATILE (opetype))
2178 DCL_PTR_VOLATILE (optype) = 1;
2185 /*-----------------------------------------------------------------*/
2186 /* geniCodeArray - array access */
2187 /*-----------------------------------------------------------------*/
2189 geniCodeArray (operand * left, operand * right,int lvl)
2192 sym_link *ltype = operandType (left);
2196 if (IS_PTR (ltype->next) && left->isaddr)
2198 left = geniCodeRValue (left, FALSE);
2200 return geniCodeDerefPtr (geniCodeAdd (left, right, lvl), lvl);
2203 right = geniCodeMultiply (right,
2204 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2206 /* we can check for limits here */
2207 if (isOperandLiteral (right) &&
2210 (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2212 werror (E_ARRAY_BOUND);
2213 right = operandFromLit (0);
2216 ic = newiCode ('+', left, right);
2218 IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2219 !IS_AGGREGATE (ltype->next) &&
2220 !IS_PTR (ltype->next))
2221 ? ltype : ltype->next), 0);
2223 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
2225 return IC_RESULT (ic);
2228 /*-----------------------------------------------------------------*/
2229 /* geniCodeStruct - generates intermediate code for structres */
2230 /*-----------------------------------------------------------------*/
2232 geniCodeStruct (operand * left, operand * right, bool islval)
2235 sym_link *type = operandType (left);
2236 sym_link *etype = getSpec (type);
2238 symbol *element = getStructElement (SPEC_STRUCT (etype),
2239 right->operand.symOperand);
2241 wassert(IS_SYMOP(right));
2243 /* add the offset */
2244 ic = newiCode ('+', left, operandFromLit (element->offset));
2246 IC_RESULT (ic) = newiTempOperand (element->type, 0);
2248 /* preserve the storage & output class of the struct */
2249 /* as well as the volatile attribute */
2250 retype = getSpec (operandType (IC_RESULT (ic)));
2251 SPEC_SCLS (retype) = SPEC_SCLS (etype);
2252 SPEC_OCLS (retype) = SPEC_OCLS (etype);
2253 SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2255 if (IS_PTR (element->type))
2256 setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2258 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2262 return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2265 /*-----------------------------------------------------------------*/
2266 /* geniCodePostInc - generate int code for Post increment */
2267 /*-----------------------------------------------------------------*/
2269 geniCodePostInc (operand * op)
2273 sym_link *optype = operandType (op);
2275 operand *rv = (IS_ITEMP (op) ?
2276 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2278 sym_link *rvtype = operandType (rv);
2281 /* if this is not an address we have trouble */
2284 werror (E_LVALUE_REQUIRED, "++");
2288 rOp = newiTempOperand (rvtype, 0);
2289 OP_SYMBOL(rOp)->noSpilLoc = 1;
2292 OP_SYMBOL(rv)->noSpilLoc = 1;
2294 geniCodeAssign (rOp, rv, 0);
2296 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2297 if (IS_FLOAT (rvtype))
2298 ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2300 ic = newiCode ('+', rv, operandFromLit (size));
2302 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2305 geniCodeAssign (op, result, 0);
2311 /*-----------------------------------------------------------------*/
2312 /* geniCodePreInc - generate code for preIncrement */
2313 /*-----------------------------------------------------------------*/
2315 geniCodePreInc (operand * op)
2318 sym_link *optype = operandType (op);
2319 operand *rop = (IS_ITEMP (op) ?
2320 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2322 sym_link *roptype = operandType (rop);
2328 werror (E_LVALUE_REQUIRED, "++");
2333 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2334 if (IS_FLOAT (roptype))
2335 ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2337 ic = newiCode ('+', rop, operandFromLit (size));
2338 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2342 return geniCodeAssign (op, result, 0);
2345 /*-----------------------------------------------------------------*/
2346 /* geniCodePostDec - generates code for Post decrement */
2347 /*-----------------------------------------------------------------*/
2349 geniCodePostDec (operand * op)
2353 sym_link *optype = operandType (op);
2355 operand *rv = (IS_ITEMP (op) ?
2356 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2358 sym_link *rvtype = operandType (rv);
2361 /* if this is not an address we have trouble */
2364 werror (E_LVALUE_REQUIRED, "--");
2368 rOp = newiTempOperand (rvtype, 0);
2369 OP_SYMBOL(rOp)->noSpilLoc = 1;
2372 OP_SYMBOL(rv)->noSpilLoc = 1;
2374 geniCodeAssign (rOp, rv, 0);
2376 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2377 if (IS_FLOAT (rvtype))
2378 ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2380 ic = newiCode ('-', rv, operandFromLit (size));
2382 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2385 geniCodeAssign (op, result, 0);
2391 /*-----------------------------------------------------------------*/
2392 /* geniCodePreDec - generate code for pre decrement */
2393 /*-----------------------------------------------------------------*/
2395 geniCodePreDec (operand * op)
2398 sym_link *optype = operandType (op);
2399 operand *rop = (IS_ITEMP (op) ?
2400 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2402 sym_link *roptype = operandType (rop);
2408 werror (E_LVALUE_REQUIRED, "--");
2413 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2414 if (IS_FLOAT (roptype))
2415 ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2417 ic = newiCode ('-', rop, operandFromLit (size));
2418 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2422 return geniCodeAssign (op, result, 0);
2426 /*-----------------------------------------------------------------*/
2427 /* geniCodeBitwise - gen int code for bitWise operators */
2428 /*-----------------------------------------------------------------*/
2430 geniCodeBitwise (operand * left, operand * right,
2431 int oper, sym_link * resType)
2435 left = geniCodeCast (resType, left, TRUE);
2436 right = geniCodeCast (resType, right, TRUE);
2438 ic = newiCode (oper, left, right);
2439 IC_RESULT (ic) = newiTempOperand (resType, 0);
2442 return IC_RESULT (ic);
2445 /*-----------------------------------------------------------------*/
2446 /* geniCodeAddressOf - gens icode for '&' address of operator */
2447 /*-----------------------------------------------------------------*/
2449 geniCodeAddressOf (operand * op)
2453 sym_link *optype = operandType (op);
2454 sym_link *opetype = getSpec (optype);
2456 /* lvalue check already done in decorateType */
2457 /* this must be a lvalue */
2458 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2459 /* werror (E_LVALUE_REQUIRED,"&"); */
2463 p = newLink (DECLARATOR);
2465 /* set the pointer depending on the storage class */
2466 if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2467 DCL_PTR_CONST (p) = port->mem.code_ro;
2469 /* make sure we preserve the const & volatile */
2470 if (IS_CONSTANT (opetype))
2471 DCL_PTR_CONST (p) = 1;
2473 if (IS_VOLATILE (opetype))
2474 DCL_PTR_VOLATILE (p) = 1;
2476 p->next = copyLinkChain (optype);
2478 /* if already a temp */
2481 setOperandType (op, p);
2486 /* other wise make this of the type coming in */
2487 ic = newiCode (ADDRESS_OF, op, NULL);
2488 IC_RESULT (ic) = newiTempOperand (p, 1);
2489 IC_RESULT (ic)->isaddr = 0;
2491 return IC_RESULT (ic);
2493 /*-----------------------------------------------------------------*/
2494 /* setOClass - sets the output class depending on the pointer type */
2495 /*-----------------------------------------------------------------*/
2497 setOClass (sym_link * ptr, sym_link * spec)
2499 switch (DCL_TYPE (ptr))
2502 SPEC_OCLS (spec) = data;
2506 SPEC_OCLS (spec) = generic;
2510 SPEC_OCLS (spec) = xdata;
2514 SPEC_OCLS (spec) = code;
2518 SPEC_OCLS (spec) = idata;
2522 SPEC_OCLS (spec) = xstack;
2526 SPEC_OCLS (spec) = eeprom;
2535 /*-----------------------------------------------------------------*/
2536 /* geniCodeDerefPtr - dereference pointer with '*' */
2537 /*-----------------------------------------------------------------*/
2539 geniCodeDerefPtr (operand * op,int lvl)
2541 sym_link *rtype, *retype;
2542 sym_link *optype = operandType (op);
2544 // if this is an array then array access
2545 if (IS_ARRAY (optype)) {
2546 // don't worry, this will be optimized out later
2547 return geniCodeArray (op, operandFromLit (0), lvl);
2550 // just in case someone screws up
2551 wassert (IS_PTR (optype));
2553 if (IS_TRUE_SYMOP (op))
2556 op = geniCodeRValue (op, TRUE);
2559 /* now get rid of the pointer part */
2560 if (isLvaluereq(lvl) && IS_ITEMP (op))
2562 retype = getSpec (rtype = copyLinkChain (optype));
2566 retype = getSpec (rtype = copyLinkChain (optype->next));
2569 /* outputclass needs 2b updated */
2570 setOClass (optype, retype);
2572 op->isGptr = IS_GENPTR (optype);
2574 /* if the pointer was declared as a constant */
2575 /* then we cannot allow assignment to the derefed */
2576 if (IS_PTR_CONST (optype))
2577 SPEC_CONST (retype) = 1;
2579 op->isaddr = (IS_PTR (rtype) ||
2580 IS_STRUCT (rtype) ||
2585 if (!isLvaluereq(lvl))
2586 op = geniCodeRValue (op, TRUE);
2588 setOperandType (op, rtype);
2593 /*-----------------------------------------------------------------*/
2594 /* geniCodeUnaryMinus - does a unary minus of the operand */
2595 /*-----------------------------------------------------------------*/
2597 geniCodeUnaryMinus (operand * op)
2600 sym_link *optype = operandType (op);
2602 if (IS_LITERAL (optype))
2603 return operandFromLit (-floatFromVal (op->operand.valOperand));
2605 ic = newiCode (UNARYMINUS, op, NULL);
2606 IC_RESULT (ic) = newiTempOperand (optype, 0);
2608 return IC_RESULT (ic);
2611 /*-----------------------------------------------------------------*/
2612 /* geniCodeLeftShift - gen i code for left shift */
2613 /*-----------------------------------------------------------------*/
2615 geniCodeLeftShift (operand * left, operand * right)
2619 ic = newiCode (LEFT_OP, left, right);
2620 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2622 return IC_RESULT (ic);
2625 /*-----------------------------------------------------------------*/
2626 /* geniCodeRightShift - gen i code for right shift */
2627 /*-----------------------------------------------------------------*/
2629 geniCodeRightShift (operand * left, operand * right)
2633 ic = newiCode (RIGHT_OP, left, right);
2634 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2636 return IC_RESULT (ic);
2639 /*-----------------------------------------------------------------*/
2640 /* geniCodeLogic- logic code */
2641 /*-----------------------------------------------------------------*/
2643 geniCodeLogic (operand * left, operand * right, int op)
2647 sym_link *rtype = operandType (right);
2648 sym_link *ltype = operandType (left);
2650 /* left is integral type and right is literal then
2651 check if the literal value is within bounds */
2652 if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2654 checkConstantRange(ltype,
2655 OP_VALUE(right), "compare operation", 1);
2658 ctype = usualBinaryConversions (&left, &right);
2660 ic = newiCode (op, left, right);
2661 IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2663 /* if comparing float
2664 and not a '==' || '!=' || '&&' || '||' (these
2666 if (IS_FLOAT(ctype) &&
2674 return IC_RESULT (ic);
2677 /*-----------------------------------------------------------------*/
2678 /* geniCodeUnary - for a a generic unary operation */
2679 /*-----------------------------------------------------------------*/
2681 geniCodeUnary (operand * op, int oper)
2683 iCode *ic = newiCode (oper, op, NULL);
2685 IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2687 return IC_RESULT (ic);
2690 /*-----------------------------------------------------------------*/
2691 /* geniCodeConditional - geniCode for '?' ':' operation */
2692 /*-----------------------------------------------------------------*/
2694 geniCodeConditional (ast * tree,int lvl)
2697 symbol *falseLabel = newiTempLabel (NULL);
2698 symbol *exitLabel = newiTempLabel (NULL);
2699 operand *cond = ast2iCode (tree->left,lvl+1);
2700 operand *true, *false, *result;
2702 ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
2706 true = ast2iCode (tree->right->left,lvl+1);
2708 /* move the value to a new Operand */
2709 result = newiTempOperand (tree->right->ftype, 0);
2710 geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
2712 /* generate an unconditional goto */
2713 geniCodeGoto (exitLabel);
2715 /* now for the right side */
2716 geniCodeLabel (falseLabel);
2718 false = ast2iCode (tree->right->right,lvl+1);
2719 geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
2721 /* create the exit label */
2722 geniCodeLabel (exitLabel);
2727 /*-----------------------------------------------------------------*/
2728 /* geniCodeAssign - generate code for assignment */
2729 /*-----------------------------------------------------------------*/
2731 geniCodeAssign (operand * left, operand * right, int nosupdate)
2734 sym_link *ltype = operandType (left);
2735 sym_link *rtype = operandType (right);
2737 if (!left->isaddr && !IS_ITEMP (left))
2739 werror (E_LVALUE_REQUIRED, "assignment");
2743 /* left is integral type and right is literal then
2744 check if the literal value is within bounds */
2745 if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
2747 checkConstantRange(ltype,
2748 OP_VALUE(right), "= operation", 0);
2751 /* if the left & right type don't exactly match */
2752 /* if pointer set then make sure the check is
2753 done with the type & not the pointer */
2754 /* then cast rights type to left */
2756 /* first check the type for pointer assignement */
2757 if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
2758 compareType (ltype, rtype) <= 0)
2760 if (compareType (ltype->next, rtype) < 0)
2761 right = geniCodeCast (ltype->next, right, TRUE);
2763 else if (compareType (ltype, rtype) < 0)
2764 right = geniCodeCast (ltype, right, TRUE);
2766 /* if left is a true symbol & ! volatile
2767 create an assignment to temporary for
2768 the right & then assign this temporary
2769 to the symbol this is SSA . isn't it simple
2770 and folks have published mountains of paper on it */
2771 if (IS_TRUE_SYMOP (left) &&
2772 !isOperandVolatile (left, FALSE) &&
2773 isOperandGlobal (left))
2777 if (IS_TRUE_SYMOP (right))
2778 sym = OP_SYMBOL (right);
2779 ic = newiCode ('=', NULL, right);
2780 IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
2781 SPIL_LOC (right) = sym;
2785 ic = newiCode ('=', NULL, right);
2786 IC_RESULT (ic) = left;
2789 /* if left isgptr flag is set then support
2790 routine will be required */
2794 ic->nosupdate = nosupdate;
2798 /*-----------------------------------------------------------------*/
2799 /* geniCodeSEParms - generate code for side effecting fcalls */
2800 /*-----------------------------------------------------------------*/
2802 geniCodeSEParms (ast * parms,int lvl)
2807 if (parms->type == EX_OP && parms->opval.op == PARAM)
2809 geniCodeSEParms (parms->left,lvl);
2810 geniCodeSEParms (parms->right,lvl);
2814 /* hack don't like this but too lazy to think of
2816 if (IS_ADDRESS_OF_OP (parms))
2817 parms->left->lvalue = 1;
2819 if (IS_CAST_OP (parms) &&
2820 IS_PTR (parms->ftype) &&
2821 IS_ADDRESS_OF_OP (parms->right))
2822 parms->right->left->lvalue = 1;
2824 parms->opval.oprnd =
2825 geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2827 parms->type = EX_OPERAND;
2828 AST_ARGREG(parms) = parms->etype ? SPEC_ARGREG(parms->etype) :
2829 SPEC_ARGREG(parms->ftype);
2832 /*-----------------------------------------------------------------*/
2833 /* geniCodeParms - generates parameters */
2834 /*-----------------------------------------------------------------*/
2836 geniCodeParms (ast * parms, value *argVals, int *stack,
2837 sym_link * fetype, symbol * func,int lvl)
2845 if (argVals==NULL) {
2847 argVals=FUNC_ARGS(func->type);
2850 /* if this is a param node then do the left & right */
2851 if (parms->type == EX_OP && parms->opval.op == PARAM)
2853 argVals=geniCodeParms (parms->left, argVals, stack, fetype, func,lvl);
2854 argVals=geniCodeParms (parms->right, argVals, stack, fetype, func,lvl);
2858 /* get the parameter value */
2859 if (parms->type == EX_OPERAND)
2860 pval = parms->opval.oprnd;
2863 /* maybe this else should go away ?? */
2864 /* hack don't like this but too lazy to think of
2866 if (IS_ADDRESS_OF_OP (parms))
2867 parms->left->lvalue = 1;
2869 if (IS_CAST_OP (parms) &&
2870 IS_PTR (parms->ftype) &&
2871 IS_ADDRESS_OF_OP (parms->right))
2872 parms->right->left->lvalue = 1;
2874 pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2877 /* if register parm then make it a send */
2878 if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(func->type)) ||
2879 IFFUNC_ISBUILTIN(func->type))
2881 ic = newiCode (SEND, pval, NULL);
2882 ic->argreg = SPEC_ARGREG(parms->etype);
2883 ic->builtinSEND = FUNC_ISBUILTIN(func->type);
2888 /* now decide whether to push or assign */
2889 if (!(options.stackAuto || IFFUNC_ISREENT (func->type)))
2893 operand *top = operandFromSymbol (argVals->sym);
2894 /* clear useDef and other bitVectors */
2895 OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
2896 geniCodeAssign (top, pval, 1);
2900 sym_link *p = operandType (pval);
2902 ic = newiCode (IPUSH, pval, NULL);
2904 /* update the stack adjustment */
2905 *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2910 argVals=argVals->next;
2914 /*-----------------------------------------------------------------*/
2915 /* geniCodeCall - generates temp code for calling */
2916 /*-----------------------------------------------------------------*/
2918 geniCodeCall (operand * left, ast * parms,int lvl)
2922 sym_link *type, *etype;
2925 if (!IS_FUNC(OP_SYMBOL(left)->type) &&
2926 !IS_CODEPTR(OP_SYMBOL(left)->type)) {
2927 werror (E_FUNCTION_EXPECTED);
2931 /* take care of parameters with side-effecting
2932 function calls in them, this is required to take care
2933 of overlaying function parameters */
2934 geniCodeSEParms (parms,lvl);
2936 /* first the parameters */
2937 geniCodeParms (parms, NULL, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
2939 /* now call : if symbol then pcall */
2940 if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
2941 ic = newiCode (PCALL, left, NULL);
2943 ic = newiCode (CALL, left, NULL);
2946 type = copyLinkChain (operandType (left)->next);
2947 etype = getSpec (type);
2948 SPEC_EXTR (etype) = 0;
2949 IC_RESULT (ic) = result = newiTempOperand (type, 1);
2953 /* stack adjustment after call */
2954 ic->parmBytes = stack;
2959 /*-----------------------------------------------------------------*/
2960 /* geniCodeReceive - generate intermediate code for "receive" */
2961 /*-----------------------------------------------------------------*/
2963 geniCodeReceive (value * args)
2965 /* for all arguments that are passed in registers */
2969 if (IS_REGPARM (args->etype))
2971 operand *opr = operandFromValue (args);
2973 symbol *sym = OP_SYMBOL (opr);
2976 /* we will use it after all optimizations
2977 and before liveRange calculation */
2978 if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
2981 if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
2982 options.stackAuto == 0 &&
2983 (!(options.model == MODEL_FLAT24)) )
2988 opl = newiTempOperand (args->type, 0);
2990 sym->reqv->key = sym->key;
2991 OP_SYMBOL (sym->reqv)->key = sym->key;
2992 OP_SYMBOL (sym->reqv)->isreqv = 1;
2993 OP_SYMBOL (sym->reqv)->islocal = 0;
2994 SPIL_LOC (sym->reqv) = sym;
2998 ic = newiCode (RECEIVE, NULL, NULL);
2999 ic->argreg = SPEC_ARGREG(args->etype);
3001 currFunc->recvSize = getSize (sym->type);
3004 IC_RESULT (ic) = opr;
3012 /*-----------------------------------------------------------------*/
3013 /* geniCodeFunctionBody - create the function body */
3014 /*-----------------------------------------------------------------*/
3016 geniCodeFunctionBody (ast * tree,int lvl)
3023 /* reset the auto generation */
3029 func = ast2iCode (tree->left,lvl+1);
3030 fetype = getSpec (operandType (func));
3032 savelineno = lineno;
3033 lineno = OP_SYMBOL (func)->lineDef;
3034 /* create an entry label */
3035 geniCodeLabel (entryLabel);
3036 lineno = savelineno;
3038 /* create a proc icode */
3039 ic = newiCode (FUNCTION, func, NULL);
3040 lineno=ic->lineno = OP_SYMBOL (func)->lineDef;
3044 /* for all parameters that are passed
3045 on registers add a "receive" */
3046 geniCodeReceive (tree->values.args);
3048 /* generate code for the body */
3049 ast2iCode (tree->right,lvl+1);
3051 /* create a label for return */
3052 geniCodeLabel (returnLabel);
3054 /* now generate the end proc */
3055 ic = newiCode (ENDFUNCTION, func, NULL);
3060 /*-----------------------------------------------------------------*/
3061 /* geniCodeReturn - gen icode for 'return' statement */
3062 /*-----------------------------------------------------------------*/
3064 geniCodeReturn (operand * op)
3068 /* if the operand is present force an rvalue */
3070 op = geniCodeRValue (op, FALSE);
3072 ic = newiCode (RETURN, op, NULL);
3076 /*-----------------------------------------------------------------*/
3077 /* geniCodeIfx - generates code for extended if statement */
3078 /*-----------------------------------------------------------------*/
3080 geniCodeIfx (ast * tree,int lvl)
3083 operand *condition = ast2iCode (tree->left,lvl+1);
3086 /* if condition is null then exit */
3090 condition = geniCodeRValue (condition, FALSE);
3092 cetype = getSpec (operandType (condition));
3093 /* if the condition is a literal */
3094 if (IS_LITERAL (cetype))
3096 if (floatFromVal (condition->operand.valOperand))
3098 if (tree->trueLabel)
3099 geniCodeGoto (tree->trueLabel);
3105 if (tree->falseLabel)
3106 geniCodeGoto (tree->falseLabel);
3113 if (tree->trueLabel)
3115 ic = newiCodeCondition (condition,
3120 if (tree->falseLabel)
3121 geniCodeGoto (tree->falseLabel);
3125 ic = newiCodeCondition (condition,
3132 ast2iCode (tree->right,lvl+1);
3135 /*-----------------------------------------------------------------*/
3136 /* geniCodeJumpTable - tries to create a jump table for switch */
3137 /*-----------------------------------------------------------------*/
3139 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
3141 int min = 0, max = 0, t, cnt = 0;
3148 if (!tree || !caseVals)
3151 /* the criteria for creating a jump table is */
3152 /* all integer numbers between the maximum & minimum must */
3153 /* be present , the maximum value should not exceed 255 */
3154 min = max = (int) floatFromVal (vch = caseVals);
3155 SNPRINTF (buffer, sizeof(buffer),
3157 tree->values.switchVals.swNum,
3159 addSet (&labels, newiTempLabel (buffer));
3161 /* if there is only one case value then no need */
3162 if (!(vch = vch->next))
3167 if (((t = (int) floatFromVal (vch)) - max) != 1)
3169 SNPRINTF (buffer, sizeof(buffer),
3171 tree->values.switchVals.swNum,
3173 addSet (&labels, newiTempLabel (buffer));
3179 /* if the number of case statements <= 2 then */
3180 /* it is not economical to create the jump table */
3181 /* since two compares are needed for boundary conditions */
3182 if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
3185 if (tree->values.switchVals.swDefault)
3187 SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3191 SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3195 falseLabel = newiTempLabel (buffer);
3197 /* so we can create a jumptable */
3198 /* first we rule out the boundary conditions */
3199 /* if only optimization says so */
3200 if (!optimize.noJTabBoundary)
3202 sym_link *cetype = getSpec (operandType (cond));
3203 /* no need to check the lower bound if
3204 the condition is unsigned & minimum value is zero */
3205 if (!(min == 0 && SPEC_USIGN (cetype)))
3207 boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3208 ic = newiCodeCondition (boundary, falseLabel, NULL);
3212 /* now for upper bounds */
3213 boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3214 ic = newiCodeCondition (boundary, falseLabel, NULL);
3218 /* if the min is not zero then we no make it zero */
3221 cond = geniCodeSubtract (cond, operandFromLit (min));
3222 setOperandType (cond, UCHARTYPE);
3225 /* now create the jumptable */
3226 ic = newiCode (JUMPTABLE, NULL, NULL);
3227 IC_JTCOND (ic) = cond;
3228 IC_JTLABELS (ic) = labels;
3233 /*-----------------------------------------------------------------*/
3234 /* geniCodeSwitch - changes a switch to a if statement */
3235 /*-----------------------------------------------------------------*/
3237 geniCodeSwitch (ast * tree,int lvl)
3240 operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3241 value *caseVals = tree->values.switchVals.swVals;
3242 symbol *trueLabel, *falseLabel;
3244 /* if we can make this a jump table */
3245 if (geniCodeJumpTable (cond, caseVals, tree))
3246 goto jumpTable; /* no need for the comparison */
3248 /* for the cases defined do */
3252 operand *compare = geniCodeLogic (cond,
3253 operandFromValue (caseVals),
3256 SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3257 tree->values.switchVals.swNum,
3258 (int) floatFromVal (caseVals));
3259 trueLabel = newiTempLabel (buffer);
3261 ic = newiCodeCondition (compare, trueLabel, NULL);
3263 caseVals = caseVals->next;
3268 /* if default is present then goto break else break */
3269 if (tree->values.switchVals.swDefault)
3271 SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3275 SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3278 falseLabel = newiTempLabel (buffer);
3279 geniCodeGoto (falseLabel);
3282 ast2iCode (tree->right,lvl+1);
3285 /*-----------------------------------------------------------------*/
3286 /* geniCodeInline - intermediate code for inline assembler */
3287 /*-----------------------------------------------------------------*/
3289 geniCodeInline (ast * tree)
3293 ic = newiCode (INLINEASM, NULL, NULL);
3294 IC_INLINE (ic) = tree->values.inlineasm;
3298 /*-----------------------------------------------------------------*/
3299 /* geniCodeArrayInit - intermediate code for array initializer */
3300 /*-----------------------------------------------------------------*/
3302 geniCodeArrayInit (ast * tree, operand *array)
3306 if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3307 ic = newiCode (ARRAYINIT, array, NULL);
3308 IC_ARRAYILIST (ic) = tree->values.constlist;
3310 operand *left=newOperand(), *right=newOperand();
3311 left->type=right->type=SYMBOL;
3312 OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3313 OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3314 ic = newiCode (ARRAYINIT, left, right);
3319 /*-----------------------------------------------------------------*/
3320 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
3321 /* particular case. Ie : assigning or dereferencing array or ptr */
3322 /*-----------------------------------------------------------------*/
3323 set * lvaluereqSet = NULL;
3324 typedef struct lvalItem
3331 /*-----------------------------------------------------------------*/
3332 /* addLvaluereq - add a flag for lvalreq for current ast level */
3333 /*-----------------------------------------------------------------*/
3334 void addLvaluereq(int lvl)
3336 lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3339 addSetHead(&lvaluereqSet,lpItem);
3342 /*-----------------------------------------------------------------*/
3343 /* delLvaluereq - del a flag for lvalreq for current ast level */
3344 /*-----------------------------------------------------------------*/
3348 lpItem = getSet(&lvaluereqSet);
3349 if(lpItem) Safe_free(lpItem);
3351 /*-----------------------------------------------------------------*/
3352 /* clearLvaluereq - clear lvalreq flag */
3353 /*-----------------------------------------------------------------*/
3354 void clearLvaluereq()
3357 lpItem = peekSet(lvaluereqSet);
3358 if(lpItem) lpItem->req = 0;
3360 /*-----------------------------------------------------------------*/
3361 /* getLvaluereq - get the last lvalreq level */
3362 /*-----------------------------------------------------------------*/
3363 int getLvaluereqLvl()
3366 lpItem = peekSet(lvaluereqSet);
3367 if(lpItem) return lpItem->lvl;
3370 /*-----------------------------------------------------------------*/
3371 /* isLvaluereq - is lvalreq valid for this level ? */
3372 /*-----------------------------------------------------------------*/
3373 int isLvaluereq(int lvl)
3376 lpItem = peekSet(lvaluereqSet);
3377 if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3381 /*-----------------------------------------------------------------*/
3382 /* ast2iCode - creates an icodeList from an ast */
3383 /*-----------------------------------------------------------------*/
3385 ast2iCode (ast * tree,int lvl)
3387 operand *left = NULL;
3388 operand *right = NULL;
3392 /* set the global variables for filename & line number */
3394 filename = tree->filename;
3396 lineno = tree->lineno;
3398 block = tree->block;
3400 scopeLevel = tree->level;
3402 if (tree->type == EX_VALUE)
3403 return operandFromValue (tree->opval.val);
3405 if (tree->type == EX_LINK)
3406 return operandFromLink (tree->opval.lnk);
3408 /* if we find a nullop */
3409 if (tree->type == EX_OP &&
3410 (tree->opval.op == NULLOP ||
3411 tree->opval.op == BLOCK))
3413 ast2iCode (tree->left,lvl+1);
3414 ast2iCode (tree->right,lvl+1);
3418 /* special cases for not evaluating */
3419 if (tree->opval.op != ':' &&
3420 tree->opval.op != '?' &&
3421 tree->opval.op != CALL &&
3422 tree->opval.op != IFX &&
3423 tree->opval.op != LABEL &&
3424 tree->opval.op != GOTO &&
3425 tree->opval.op != SWITCH &&
3426 tree->opval.op != FUNCTION &&
3427 tree->opval.op != INLINEASM)
3430 if (IS_ASSIGN_OP (tree->opval.op) ||
3431 IS_DEREF_OP (tree) ||
3432 (tree->opval.op == '&' && !tree->right) ||
3433 tree->opval.op == PTR_OP)
3436 if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3437 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3440 left = operandFromAst (tree->left,lvl);
3442 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3443 left = geniCodeRValue (left, TRUE);
3447 left = operandFromAst (tree->left,lvl);
3449 if (tree->opval.op == INC_OP ||
3450 tree->opval.op == DEC_OP)
3453 right = operandFromAst (tree->right,lvl);
3458 right = operandFromAst (tree->right,lvl);
3462 /* now depending on the type of operand */
3463 /* this will be a biggy */
3464 switch (tree->opval.op)
3467 case '[': /* array operation */
3469 //sym_link *ltype = operandType (left);
3470 //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3471 left = geniCodeRValue (left, FALSE);
3472 right = geniCodeRValue (right, TRUE);
3475 return geniCodeArray (left, right,lvl);
3477 case '.': /* structure dereference */
3478 if (IS_PTR (operandType (left)))
3479 left = geniCodeRValue (left, TRUE);
3481 left = geniCodeRValue (left, FALSE);
3483 return geniCodeStruct (left, right, tree->lvalue);
3485 case PTR_OP: /* structure pointer dereference */
3488 pType = operandType (left);
3489 left = geniCodeRValue (left, TRUE);
3491 setOClass (pType, getSpec (operandType (left)));
3494 return geniCodeStruct (left, right, tree->lvalue);
3496 case INC_OP: /* increment operator */
3498 return geniCodePostInc (left);
3500 return geniCodePreInc (right);
3502 case DEC_OP: /* decrement operator */
3504 return geniCodePostDec (left);
3506 return geniCodePreDec (right);
3508 case '&': /* bitwise and or address of operator */
3510 { /* this is a bitwise operator */
3511 left = geniCodeRValue (left, FALSE);
3512 right = geniCodeRValue (right, FALSE);
3513 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3516 return geniCodeAddressOf (left);
3518 case '|': /* bitwise or & xor */
3520 return geniCodeBitwise (geniCodeRValue (left, FALSE),
3521 geniCodeRValue (right, FALSE),
3526 return geniCodeDivision (geniCodeRValue (left, FALSE),
3527 geniCodeRValue (right, FALSE));
3530 return geniCodeModulus (geniCodeRValue (left, FALSE),
3531 geniCodeRValue (right, FALSE));
3534 return geniCodeMultiply (geniCodeRValue (left, FALSE),
3535 geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3537 return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3541 return geniCodeSubtract (geniCodeRValue (left, FALSE),
3542 geniCodeRValue (right, FALSE));
3544 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3548 return geniCodeAdd (geniCodeRValue (left, FALSE),
3549 geniCodeRValue (right, FALSE),lvl);
3551 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
3554 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3555 geniCodeRValue (right, FALSE));
3558 return geniCodeRightShift (geniCodeRValue (left, FALSE),
3559 geniCodeRValue (right, FALSE));
3561 #if 0 // this indeed needs a second thought
3565 // let's keep this simple: get the rvalue we need
3566 op=geniCodeRValue (right, FALSE);
3567 // now cast it to whatever we want
3568 op=geniCodeCast (operandType(left), op, FALSE);
3569 // if this is going to be used as an lvalue, make it so
3575 #else // bug #604575, is it a bug ????
3576 return geniCodeCast (operandType (left),
3577 geniCodeRValue (right, FALSE), FALSE);
3584 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3588 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3589 setOperandType (op, UCHARTYPE);
3600 return geniCodeLogic (geniCodeRValue (left, FALSE),
3601 geniCodeRValue (right, FALSE),
3604 return geniCodeConditional (tree,lvl);
3607 return operandFromLit (getSize (tree->right->ftype));
3611 sym_link *rtype = operandType (right);
3612 sym_link *ltype = operandType (left);
3613 if (IS_PTR (rtype) && IS_ITEMP (right)
3614 && right->isaddr && compareType (rtype->next, ltype) == 1)
3615 right = geniCodeRValue (right, TRUE);
3617 right = geniCodeRValue (right, FALSE);
3619 geniCodeAssign (left, right, 0);
3624 geniCodeAssign (left,
3625 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3627 geniCodeRValue (right, FALSE),FALSE), 0);
3631 geniCodeAssign (left,
3632 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3634 geniCodeRValue (right, FALSE)), 0);
3637 geniCodeAssign (left,
3638 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3640 geniCodeRValue (right, FALSE)), 0);
3643 sym_link *rtype = operandType (right);
3644 sym_link *ltype = operandType (left);
3645 if (IS_PTR (rtype) && IS_ITEMP (right)
3646 && right->isaddr && compareType (rtype->next, ltype) == 1)
3647 right = geniCodeRValue (right, TRUE);
3649 right = geniCodeRValue (right, FALSE);
3652 return geniCodeAssign (left,
3653 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3659 sym_link *rtype = operandType (right);
3660 sym_link *ltype = operandType (left);
3661 if (IS_PTR (rtype) && IS_ITEMP (right)
3662 && right->isaddr && compareType (rtype->next, ltype) == 1)
3664 right = geniCodeRValue (right, TRUE);
3668 right = geniCodeRValue (right, FALSE);
3671 geniCodeAssign (left,
3672 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3678 geniCodeAssign (left,
3679 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3681 geniCodeRValue (right, FALSE)), 0);
3684 geniCodeAssign (left,
3685 geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3687 geniCodeRValue (right, FALSE)), 0);
3690 geniCodeAssign (left,
3691 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3693 geniCodeRValue (right, FALSE),
3695 operandType (left)), 0);
3698 geniCodeAssign (left,
3699 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3701 geniCodeRValue (right, FALSE),
3703 operandType (left)), 0);
3706 geniCodeAssign (left,
3707 geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3709 geniCodeRValue (right, FALSE),
3711 operandType (left)), 0);
3713 return geniCodeRValue (right, FALSE);
3716 return geniCodeCall (ast2iCode (tree->left,lvl+1),
3719 geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3720 return ast2iCode (tree->right,lvl+1);
3723 geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3724 return ast2iCode (tree->right,lvl+1);
3727 geniCodeFunctionBody (tree,lvl);
3731 geniCodeReturn (right);
3735 geniCodeIfx (tree,lvl);
3739 geniCodeSwitch (tree,lvl);
3743 geniCodeInline (tree);
3747 geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
3754 /*-----------------------------------------------------------------*/
3755 /* reverseICChain - gets from the list and creates a linkedlist */
3756 /*-----------------------------------------------------------------*/
3763 while ((loop = getSet (&iCodeChain)))
3775 /*-----------------------------------------------------------------*/
3776 /* iCodeFromAst - given an ast will convert it to iCode */
3777 /*-----------------------------------------------------------------*/
3779 iCodeFromAst (ast * tree)
3781 returnLabel = newiTempLabel ("_return");
3782 entryLabel = newiTempLabel ("_entry");
3784 return reverseiCChain ();
3787 static const char *opTypeToStr(OPTYPE op)
3791 case SYMBOL: return "symbol";
3792 case VALUE: return "value";
3793 case TYPE: return "type";
3795 return "undefined type";
3799 operand *validateOpType(operand *op,
3806 if (op && op->type == type)
3811 "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
3812 " expected %s, got %s\n",
3813 macro, args, file, line,
3814 opTypeToStr(type), op ? opTypeToStr(op->type) : "null op");
3816 return op; // never reached, makes compiler happy.