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, int pedantic) {
131 char message[132]="";
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;
182 sprintf (message, "for %s %s in %s",
183 SPEC_USIGN(ltype) ? "unsigned" : "signed",
184 nounName(ltype), msg);
185 werror (W_CONST_RANGE, message);
192 /*-----------------------------------------------------------------*/
193 /* operandName - returns the name of the operand */
194 /*-----------------------------------------------------------------*/
196 printOperand (operand * op, FILE * file)
213 opetype = getSpec (operandType (op));
214 if (SPEC_NOUN (opetype) == V_FLOAT)
215 fprintf (file, "%g {", SPEC_CVAL (opetype).v_float);
217 fprintf (file, "0x%x {", (int) floatFromVal (op->operand.valOperand));
218 printTypeChain (operandType (op), file);
225 fprintf (file, "%s [k%d lr%d:%d so:%d]{ ia%d re%d rm%d nos%d}", /*{ar%d rm%d ru%d p%d a%d u%d i%d au%d k%d ks%d}" , */
226 (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name),
228 OP_LIVEFROM (op), OP_LIVETO (op),
229 OP_SYMBOL (op)->stack,
230 op->isaddr, OP_SYMBOL (op)->isreqv, OP_SYMBOL (op)->remat,OP_SYMBOL(op)->noSpilLoc
234 printTypeChain (operandType (op), file);
235 if (SPIL_LOC (op) && IS_ITEMP (op))
236 fprintf (file, "}{ sir@ %s", SPIL_LOC (op)->rname);
241 /* if assigned to registers */
242 if (OP_SYMBOL (op)->nRegs)
244 if (OP_SYMBOL (op)->isspilt)
246 if (!OP_SYMBOL (op)->remat)
247 if (OP_SYMBOL (op)->usl.spillLoc)
248 fprintf (file, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
249 OP_SYMBOL (op)->usl.spillLoc->rname :
250 OP_SYMBOL (op)->usl.spillLoc->name));
252 fprintf (file, "[err]");
254 fprintf (file, "[remat]");
260 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
261 fprintf (file, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i]));
266 fprintf (file, "%s", (OP_SYMBOL (op)->rname[0] ?
267 OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name));
268 /* if assigned to registers */
269 if (OP_SYMBOL (op)->nRegs && !OP_SYMBOL (op)->isspilt)
273 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
274 fprintf (file, "%s ", (OP_SYMBOL (op)->regs[i] ?
275 OP_SYMBOL (op)->regs[i]->name :
284 printTypeChain (op->operand.typeOperand, file);
290 fprintf (file, "\n");
295 /*-----------------------------------------------------------------*/
296 /* print functions */
297 /*-----------------------------------------------------------------*/
298 PRINTFUNC (picGetValueAtAddr)
301 printOperand (IC_RESULT (ic), of);
304 printOperand (IC_LEFT (ic), of);
310 PRINTFUNC (picSetValueAtAddr)
314 printOperand (IC_LEFT (ic), of);
315 fprintf (of, "] = ");
316 printOperand (IC_RIGHT (ic), of);
320 PRINTFUNC (picAddrOf)
323 printOperand (IC_RESULT (ic), of);
324 if (IS_ITEMP (IC_LEFT (ic)))
327 fprintf (of, " = &[");
328 printOperand (IC_LEFT (ic), of);
331 if (IS_ITEMP (IC_LEFT (ic)))
332 fprintf (of, " offsetAdd ");
335 printOperand (IC_RIGHT (ic), of);
337 if (IS_ITEMP (IC_LEFT (ic)))
343 PRINTFUNC (picJumpTable)
348 fprintf (of, "%s\t", s);
349 printOperand (IC_JTCOND (ic), of);
351 for (sym = setFirstItem (IC_JTLABELS (ic)); sym;
352 sym = setNextItem (IC_JTLABELS (ic)))
353 fprintf (of, "\t\t\t%s\n", sym->name);
356 PRINTFUNC (picGeneric)
359 printOperand (IC_RESULT (ic), of);
361 printOperand (IC_LEFT (ic), of);
362 fprintf (of, " %s ", s);
363 printOperand (IC_RIGHT (ic), of);
367 PRINTFUNC (picGenericOne)
372 printOperand (IC_RESULT (ic), of);
378 fprintf (of, "%s ", s);
379 printOperand (IC_LEFT (ic), of);
382 if (!IC_RESULT (ic) && !IC_LEFT (ic))
391 printOperand (IC_RESULT (ic), of);
393 printOperand (IC_LEFT (ic), of);
394 printOperand (IC_RIGHT (ic), of);
399 PRINTFUNC (picAssign)
403 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
406 printOperand (IC_RESULT (ic), of);
408 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
411 fprintf (of, " %s ", s);
412 printOperand (IC_RIGHT (ic), of);
419 fprintf (of, " %s($%d) :\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
425 fprintf (of, " goto %s($%d)\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
432 printOperand (IC_COND (ic), of);
435 fprintf (of, " == 0 goto %s($%d)\n", IC_FALSE (ic)->name, IC_FALSE (ic)->key);
438 fprintf (of, " != 0 goto %s($%d)\n", IC_TRUE (ic)->name, IC_TRUE (ic)->key);
440 fprintf (of, "\tzzgoto %s\n", IC_FALSE (ic)->name);
444 PRINTFUNC (picInline)
446 fprintf (of, "%s", IC_INLINE (ic));
449 PRINTFUNC (picReceive)
451 printOperand (IC_RESULT (ic), of);
452 fprintf (of, " = %s ", s);
453 printOperand (IC_LEFT (ic), of);
457 /*-----------------------------------------------------------------*/
458 /* piCode - prints one iCode */
459 /*-----------------------------------------------------------------*/
461 piCode (void *item, FILE * of)
469 icTab = getTableEntry (ic->op);
470 fprintf (stdout, "%s(%d:%d:%d:%d:%d)\t",
471 ic->filename, ic->lineno,
472 ic->seq, ic->key, ic->depth, ic->supportRtn);
473 icTab->iCodePrint (of, ic, icTab->printName);
479 printiCChain(ic,stdout);
481 /*-----------------------------------------------------------------*/
482 /* printiCChain - prints intermediate code for humans */
483 /*-----------------------------------------------------------------*/
485 printiCChain (iCode * icChain, FILE * of)
492 for (loop = icChain; loop; loop = loop->next)
494 if ((icTab = getTableEntry (loop->op)))
496 fprintf (of, "%s(%d:%d:%d:%d:%d)\t",
497 loop->filename, loop->lineno,
498 loop->seq, loop->key, loop->depth, loop->supportRtn);
500 icTab->iCodePrint (of, loop, icTab->printName);
506 /*-----------------------------------------------------------------*/
507 /* newOperand - allocate, init & return a new iCode */
508 /*-----------------------------------------------------------------*/
514 op = Safe_alloc ( sizeof (operand));
520 /*-----------------------------------------------------------------*/
521 /* newiCode - create and return a new iCode entry initialised */
522 /*-----------------------------------------------------------------*/
524 newiCode (int op, operand * left, operand * right)
528 ic = Safe_alloc ( sizeof (iCode));
531 ic->filename = filename;
533 ic->level = scopeLevel;
535 ic->key = iCodeKey++;
537 IC_RIGHT (ic) = right;
542 /*-----------------------------------------------------------------*/
543 /* newiCode for conditional statements */
544 /*-----------------------------------------------------------------*/
546 newiCodeCondition (operand * condition,
552 if (IS_VOID(operandType(condition))) {
553 werror(E_VOID_VALUE_USED);
556 ic = newiCode (IFX, NULL, NULL);
557 IC_COND (ic) = condition;
558 IC_TRUE (ic) = trueLabel;
559 IC_FALSE (ic) = falseLabel;
563 /*-----------------------------------------------------------------*/
564 /* newiCodeLabelGoto - unconditional goto statement| label stmnt */
565 /*-----------------------------------------------------------------*/
567 newiCodeLabelGoto (int op, symbol * label)
571 ic = newiCode (op, NULL, NULL);
573 ic->argLabel.label = label;
575 IC_RIGHT (ic) = NULL;
576 IC_RESULT (ic) = NULL;
580 /*-----------------------------------------------------------------*/
581 /* newiTemp - allocate & return a newItemp Variable */
582 /*-----------------------------------------------------------------*/
589 sprintf (buffer, "%s", s);
591 sprintf (buffer, "iTemp%d", iTempNum++);
592 itmp = newSymbol (buffer, 1);
593 strcpy (itmp->rname, itmp->name);
599 /*-----------------------------------------------------------------*/
600 /* newiTempLabel - creates a temp variable label */
601 /*-----------------------------------------------------------------*/
603 newiTempLabel (char *s)
607 /* check if this alredy exists */
608 if (s && (itmplbl = findSym (LabelTab, NULL, s)))
612 itmplbl = newSymbol (s, 1);
615 sprintf (buffer, "iTempLbl%d", iTempLblNum++);
616 itmplbl = newSymbol (buffer, 1);
621 itmplbl->key = labelKey++;
622 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
626 /*-----------------------------------------------------------------*/
627 /* newiTempPreheaderLabel - creates a new preheader label */
628 /*-----------------------------------------------------------------*/
630 newiTempPreheaderLabel ()
634 sprintf (buffer, "preHeaderLbl%d", iTempLblNum++);
635 itmplbl = newSymbol (buffer, 1);
639 itmplbl->key = labelKey++;
640 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
645 /*-----------------------------------------------------------------*/
646 /* initiCode - initialises some iCode related stuff */
647 /*-----------------------------------------------------------------*/
654 /*-----------------------------------------------------------------*/
655 /* copyiCode - make a copy of the iCode given */
656 /*-----------------------------------------------------------------*/
658 copyiCode (iCode * ic)
660 iCode *nic = newiCode (ic->op, NULL, NULL);
662 nic->lineno = ic->lineno;
663 nic->filename = ic->filename;
664 nic->block = ic->block;
665 nic->level = ic->level;
666 nic->parmBytes = ic->parmBytes;
668 /* deal with the special cases first */
672 IC_COND (nic) = operandFromOperand (IC_COND (ic));
673 IC_TRUE (nic) = IC_TRUE (ic);
674 IC_FALSE (nic) = IC_FALSE (ic);
678 IC_JTCOND (nic) = operandFromOperand (IC_JTCOND (ic));
679 IC_JTLABELS (nic) = IC_JTLABELS (ic);
684 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
685 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
689 IC_INLINE (nic) = IC_INLINE (ic);
693 IC_ARRAYILIST(nic) = IC_ARRAYILIST(ic);
697 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
698 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
699 IC_RIGHT (nic) = operandFromOperand (IC_RIGHT (ic));
705 /*-----------------------------------------------------------------*/
706 /* getTableEntry - gets the table entry for the given operator */
707 /*-----------------------------------------------------------------*/
709 getTableEntry (int oper)
713 for (i = 0; i < (sizeof (codeTable) / sizeof (iCodeTable)); i++)
714 if (oper == codeTable[i].icode)
715 return &codeTable[i];
720 /*-----------------------------------------------------------------*/
721 /* newiTempOperand - new intermediate temp operand */
722 /*-----------------------------------------------------------------*/
724 newiTempOperand (sym_link * type, char throwType)
727 operand *op = newOperand ();
731 itmp = newiTemp (NULL);
733 etype = getSpec (type);
735 if (IS_LITERAL (etype))
738 /* copy the type information */
740 itmp->etype = getSpec (itmp->type = (throwType ? type :
741 copyLinkChain (type)));
742 if (IS_LITERAL (itmp->etype))
744 SPEC_SCLS (itmp->etype) = S_REGISTER;
745 SPEC_OCLS (itmp->etype) = reg;
748 op->operand.symOperand = itmp;
749 op->key = itmp->key = ++operandKey;
753 /*-----------------------------------------------------------------*/
754 /* operandType - returns the type chain for an operand */
755 /*-----------------------------------------------------------------*/
757 operandType (operand * op)
759 /* depending on type of operand */
764 return op->operand.valOperand->type;
767 return op->operand.symOperand->type;
770 return op->operand.typeOperand;
772 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
773 " operand type not known ");
774 assert (0); /* should never come here */
775 /* Just to keep the compiler happy */
776 return (sym_link *) 0;
780 /*-----------------------------------------------------------------*/
781 /* isParamterToCall - will return 1 if op is a parameter to args */
782 /*-----------------------------------------------------------------*/
784 isParameterToCall (value * args, operand * op)
791 isSymbolEqual (op->operand.symOperand, tval->sym))
798 /*-----------------------------------------------------------------*/
799 /* isOperandGlobal - return 1 if operand is a global variable */
800 /*-----------------------------------------------------------------*/
802 isOperandGlobal (operand * op)
810 if (op->type == SYMBOL &&
811 (op->operand.symOperand->level == 0 ||
812 IS_STATIC (op->operand.symOperand->etype) ||
813 IS_EXTERN (op->operand.symOperand->etype))
820 /*-----------------------------------------------------------------*/
821 /* isOperandVolatile - return 1 if the operand is volatile */
822 /*-----------------------------------------------------------------*/
824 isOperandVolatile (operand * op, bool chkTemp)
829 if (IS_ITEMP (op) && !chkTemp)
832 opetype = getSpec (optype = operandType (op));
834 if (IS_PTR (optype) && DCL_PTR_VOLATILE (optype))
837 if (IS_VOLATILE (opetype))
842 /*-----------------------------------------------------------------*/
843 /* isOperandLiteral - returns 1 if an operand contains a literal */
844 /*-----------------------------------------------------------------*/
846 isOperandLiteral (operand * op)
853 opetype = getSpec (operandType (op));
855 if (IS_LITERAL (opetype))
860 /*-----------------------------------------------------------------*/
861 /* isOperandInFarSpace - will return true if operand is in farSpace */
862 /*-----------------------------------------------------------------*/
864 isOperandInFarSpace (operand * op)
874 if (!IS_TRUE_SYMOP (op))
877 etype = SPIL_LOC (op)->etype;
883 etype = getSpec (operandType (op));
885 return (IN_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
888 /*-----------------------------------------------------------------*/
889 /* isOperandOnStack - will return true if operand is on stack */
890 /*-----------------------------------------------------------------*/
892 isOperandOnStack (operand * op)
902 etype = getSpec (operandType (op));
904 return ((IN_STACK (etype)) ? TRUE : FALSE);
907 /*-----------------------------------------------------------------*/
908 /* operandLitValue - literal value of an operand */
909 /*-----------------------------------------------------------------*/
911 operandLitValue (operand * op)
913 assert (isOperandLiteral (op));
915 return floatFromVal (op->operand.valOperand);
918 /*-----------------------------------------------------------------*/
919 /* operandOperation - perforoms operations on operands */
920 /*-----------------------------------------------------------------*/
922 operandOperation (operand * left, operand * right,
923 int op, sym_link * type)
925 sym_link *let , *ret=NULL;
926 operand *retval = (operand *) 0;
928 assert (isOperandLiteral (left));
929 let = getSpec(operandType(left));
931 assert (isOperandLiteral (right));
932 ret = getSpec(operandType(left));
938 retval = operandFromValue (valCastLiteral (type,
939 operandLitValue (left) +
940 operandLitValue (right)));
943 retval = operandFromValue (valCastLiteral (type,
944 operandLitValue (left) -
945 operandLitValue (right)));
948 retval = operandFromValue (valCastLiteral (type,
949 operandLitValue (left) *
950 operandLitValue (right)));
953 if ((unsigned long) operandLitValue (right) == 0)
955 werror (E_DIVIDE_BY_ZERO);
960 retval = operandFromValue (valCastLiteral (type,
961 operandLitValue (left) /
962 operandLitValue (right)));
965 if ((unsigned long) operandLitValue (right) == 0) {
966 werror (E_DIVIDE_BY_ZERO);
970 retval = operandFromLit ((SPEC_USIGN(let) ?
971 (unsigned long) operandLitValue (left) :
972 (long) operandLitValue (left)) %
974 (unsigned long) operandLitValue (right) :
975 (long) operandLitValue (right)));
979 retval = operandFromLit ((SPEC_USIGN(let) ?
980 (unsigned long) operandLitValue (left) :
981 (long) operandLitValue (left)) <<
983 (unsigned long) operandLitValue (right) :
984 (long) operandLitValue (right)));
987 retval = operandFromLit ((SPEC_USIGN(let) ?
988 (unsigned long) operandLitValue (left) :
989 (long) operandLitValue (left)) >>
991 (unsigned long) operandLitValue (right) :
992 (long) operandLitValue (right)));
995 retval = operandFromLit (operandLitValue (left) ==
996 operandLitValue (right));
999 retval = operandFromLit (operandLitValue (left) <
1000 operandLitValue (right));
1003 retval = operandFromLit (operandLitValue (left) <=
1004 operandLitValue (right));
1007 retval = operandFromLit (operandLitValue (left) !=
1008 operandLitValue (right));
1011 retval = operandFromLit (operandLitValue (left) >
1012 operandLitValue (right));
1015 retval = operandFromLit (operandLitValue (left) >=
1016 operandLitValue (right));
1019 retval = operandFromLit ((long)operandLitValue(left) &
1020 (long)operandLitValue(right));
1023 retval = operandFromLit ((long)operandLitValue (left) |
1024 (long)operandLitValue (right));
1027 retval = operandFromLit ((long)operandLitValue (left) ^
1028 (long)operandLitValue (right));
1031 retval = operandFromLit (operandLitValue (left) &&
1032 operandLitValue (right));
1035 retval = operandFromLit (operandLitValue (left) ||
1036 operandLitValue (right));
1040 long i = (long) operandLitValue (left);
1042 retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
1048 long i = (long) operandLitValue (left);
1050 retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
1056 retval = operandFromLit (-1 * operandLitValue (left));
1060 retval = operandFromLit (~((long) operandLitValue (left)));
1064 retval = operandFromLit (!operandLitValue (left));
1068 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1069 " operandOperation invalid operator ");
1077 /*-----------------------------------------------------------------*/
1078 /* isOperandEqual - compares two operand & return 1 if they r = */
1079 /*-----------------------------------------------------------------*/
1081 isOperandEqual (operand * left, operand * right)
1083 /* if the pointers are equal then they are equal */
1087 /* if either of them null then false */
1088 if (!left || !right)
1091 if (left->type != right->type)
1094 if (IS_SYMOP (left) && IS_SYMOP (right))
1095 return left->key == right->key;
1097 /* if types are the same */
1101 return isSymbolEqual (left->operand.symOperand,
1102 right->operand.symOperand);
1104 return (floatFromVal (left->operand.valOperand) ==
1105 floatFromVal (right->operand.valOperand));
1107 if (compareType (left->operand.typeOperand,
1108 right->operand.typeOperand) == 1)
1115 /*-------------------------------------------------------------------*/
1116 /* isiCodeEqual - compares two iCodes are equal, returns true if yes */
1117 /*-------------------------------------------------------------------*/
1119 isiCodeEqual (iCode * left, iCode * right)
1121 /* if the same pointer */
1125 /* if either of them null */
1126 if (!left || !right)
1129 /* if operand are the same */
1130 if (left->op == right->op)
1133 /* compare all the elements depending on type */
1134 if (left->op != IFX)
1136 if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
1138 if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
1144 if (!isOperandEqual (IC_COND (left), IC_COND (right)))
1146 if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
1148 if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
1157 /*-----------------------------------------------------------------*/
1158 /* newiTempFromOp - create a temp Operand with same attributes */
1159 /*-----------------------------------------------------------------*/
1161 newiTempFromOp (operand * op)
1171 nop = newiTempOperand (operandType (op), TRUE);
1172 nop->isaddr = op->isaddr;
1173 nop->isvolatile = op->isvolatile;
1174 nop->isGlobal = op->isGlobal;
1175 nop->isLiteral = op->isLiteral;
1176 nop->usesDefs = op->usesDefs;
1177 nop->isParm = op->isParm;
1181 /*-----------------------------------------------------------------*/
1182 /* operand from operand - creates an operand holder for the type */
1183 /*-----------------------------------------------------------------*/
1185 operandFromOperand (operand * op)
1191 nop = newOperand ();
1192 nop->type = op->type;
1193 nop->isaddr = op->isaddr;
1195 nop->isvolatile = op->isvolatile;
1196 nop->isGlobal = op->isGlobal;
1197 nop->isLiteral = op->isLiteral;
1198 nop->usesDefs = op->usesDefs;
1199 nop->isParm = op->isParm;
1204 nop->operand.symOperand = op->operand.symOperand;
1207 nop->operand.valOperand = op->operand.valOperand;
1210 nop->operand.typeOperand = op->operand.typeOperand;
1217 /*-----------------------------------------------------------------*/
1218 /* opFromOpWithDU - makes a copy of the operand and DU chains */
1219 /*-----------------------------------------------------------------*/
1221 opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
1223 operand *nop = operandFromOperand (op);
1225 if (nop->type == SYMBOL)
1227 OP_SYMBOL (nop)->defs = bitVectCopy (defs);
1228 OP_SYMBOL (nop)->uses = bitVectCopy (uses);
1234 /*-----------------------------------------------------------------*/
1235 /* operandFromSymbol - creates an operand from a symbol */
1236 /*-----------------------------------------------------------------*/
1238 operandFromSymbol (symbol * sym)
1243 /* if the symbol's type is a literal */
1244 /* then it is an enumerator type */
1245 if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
1246 return operandFromValue (valFromType (sym->etype));
1249 sym->key = ++operandKey;
1251 /* if this an implicit variable, means struct/union */
1252 /* member so just return it */
1253 if (sym->implicit || IS_FUNC (sym->type))
1257 op->operand.symOperand = sym;
1259 op->isvolatile = isOperandVolatile (op, TRUE);
1260 op->isGlobal = isOperandGlobal (op);
1264 /* under the following conditions create a
1265 register equivalent for a local symbol */
1266 if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
1267 (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
1268 (!(options.model == MODEL_FLAT24)) ) &&
1269 options.stackAuto == 0)
1272 if (!IS_AGGREGATE (sym->type) && /* not an aggregate */
1273 !IS_FUNC (sym->type) && /* not a function */
1274 !sym->_isparm && /* not a parameter */
1275 sym->level && /* is a local variable */
1276 !sym->addrtaken && /* whose address has not been taken */
1277 !sym->reqv && /* does not already have a reg equivalence */
1278 !IS_VOLATILE (sym->etype) && /* not declared as volatile */
1279 !IS_STATIC (sym->etype) && /* and not declared static */
1280 !sym->islbl && /* not a label */
1281 ok && /* farspace check */
1282 !IS_BITVAR (sym->etype) /* not a bit variable */
1286 /* we will use it after all optimizations
1287 and before liveRange calculation */
1288 sym->reqv = newiTempOperand (sym->type, 0);
1289 sym->reqv->key = sym->key;
1290 OP_SYMBOL (sym->reqv)->key = sym->key;
1291 OP_SYMBOL (sym->reqv)->isreqv = 1;
1292 OP_SYMBOL (sym->reqv)->islocal = 1;
1293 OP_SYMBOL (sym->reqv)->onStack = sym->onStack;
1294 SPIL_LOC (sym->reqv) = sym;
1297 if (!IS_AGGREGATE (sym->type))
1301 op->operand.symOperand = sym;
1304 op->isvolatile = isOperandVolatile (op, TRUE);
1305 op->isGlobal = isOperandGlobal (op);
1306 op->isPtr = IS_PTR (operandType (op));
1307 op->isParm = sym->_isparm;
1312 /* itemp = &[_symbol] */
1314 ic = newiCode (ADDRESS_OF, newOperand (), NULL);
1315 IC_LEFT (ic)->type = SYMBOL;
1316 IC_LEFT (ic)->operand.symOperand = sym;
1317 IC_LEFT (ic)->key = sym->key;
1318 (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
1319 (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
1320 IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
1323 IC_RESULT (ic) = newiTempOperand (sym->type, 0);
1324 if (IS_ARRAY (sym->type))
1326 IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
1327 IC_RESULT (ic)->isaddr = 0;
1330 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
1334 return IC_RESULT (ic);
1337 /*-----------------------------------------------------------------*/
1338 /* operandFromValue - creates an operand from value */
1339 /*-----------------------------------------------------------------*/
1341 operandFromValue (value * val)
1345 /* if this is a symbol then do the symbol thing */
1347 return operandFromSymbol (val->sym);
1349 /* this is not a symbol */
1352 op->operand.valOperand = val;
1353 op->isLiteral = isOperandLiteral (op);
1357 /*-----------------------------------------------------------------*/
1358 /* operandFromLink - operand from typeChain */
1359 /*-----------------------------------------------------------------*/
1361 operandFromLink (sym_link * type)
1365 /* operand from sym_link */
1371 op->operand.typeOperand = copyLinkChain (type);
1375 /*-----------------------------------------------------------------*/
1376 /* operandFromLit - makes an operand from a literal value */
1377 /*-----------------------------------------------------------------*/
1379 operandFromLit (double i)
1381 return operandFromValue (valueFromLit (i));
1384 /*-----------------------------------------------------------------*/
1385 /* operandFromAst - creates an operand from an ast */
1386 /*-----------------------------------------------------------------*/
1388 operandFromAst (ast * tree,int lvl)
1394 /* depending on type do */
1398 return ast2iCode (tree,lvl+1);
1402 return operandFromValue (tree->opval.val);
1406 return operandFromLink (tree->opval.lnk);
1410 /* Just to keep the comiler happy */
1411 return (operand *) 0;
1414 /*-----------------------------------------------------------------*/
1415 /* setOperandType - sets the operand's type to the given type */
1416 /*-----------------------------------------------------------------*/
1418 setOperandType (operand * op, sym_link * type)
1420 /* depending on the type of operand */
1425 op->operand.valOperand->etype =
1426 getSpec (op->operand.valOperand->type =
1427 copyLinkChain (type));
1431 if (op->operand.symOperand->isitmp)
1432 op->operand.symOperand->etype =
1433 getSpec (op->operand.symOperand->type =
1434 copyLinkChain (type));
1436 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1437 "attempt to modify type of source");
1441 op->operand.typeOperand = copyLinkChain (type);
1446 /*-----------------------------------------------------------------*/
1447 /* Get size in byte of ptr need to access an array */
1448 /*-----------------------------------------------------------------*/
1450 getArraySizePtr (operand * op)
1452 sym_link *ltype = operandType(op);
1456 int size = getSize(ltype);
1457 return(IS_GENPTR(ltype)?(size-1):size);
1462 sym_link *letype = getSpec(ltype);
1463 switch (PTR_TYPE (SPEC_OCLS (letype)))
1475 return (GPTRSIZE-1);
1484 /*-----------------------------------------------------------------*/
1485 /* perform "usual unary conversions" */
1486 /*-----------------------------------------------------------------*/
1488 usualUnaryConversions (operand * op)
1490 if (IS_INTEGRAL (operandType (op)))
1492 if (getSize (operandType (op)) < (unsigned int) INTSIZE)
1495 return geniCodeCast (INTTYPE, op, TRUE);
1501 /*-----------------------------------------------------------------*/
1502 /* perform "usual binary conversions" */
1503 /*-----------------------------------------------------------------*/
1505 usualBinaryConversions (operand ** op1, operand ** op2)
1508 sym_link *rtype = operandType (*op2);
1509 sym_link *ltype = operandType (*op1);
1511 ctype = computeType (ltype, rtype);
1512 *op1 = geniCodeCast (ctype, *op1, TRUE);
1513 *op2 = geniCodeCast (ctype, *op2, TRUE);
1518 /*-----------------------------------------------------------------*/
1519 /* geniCodeValueAtAddress - generate intermeditate code for value */
1521 /*-----------------------------------------------------------------*/
1523 geniCodeRValue (operand * op, bool force)
1526 sym_link *type = operandType (op);
1527 sym_link *etype = getSpec (type);
1529 /* if this is an array & already */
1530 /* an address then return this */
1531 if (IS_AGGREGATE (type) ||
1532 (IS_PTR (type) && !force && !op->isaddr))
1533 return operandFromOperand (op);
1535 /* if this is not an address then must be */
1536 /* rvalue already so return this one */
1540 /* if this is not a temp symbol then */
1541 if (!IS_ITEMP (op) &&
1543 !IN_FARSPACE (SPEC_OCLS (etype)))
1545 op = operandFromOperand (op);
1550 if (IS_SPEC (type) &&
1551 IS_TRUE_SYMOP (op) &&
1552 (!IN_FARSPACE (SPEC_OCLS (etype)) ||
1553 /* TARGET_IS_DS390)) */
1554 (options.model == MODEL_FLAT24) ))
1556 op = operandFromOperand (op);
1561 ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1562 if (IS_PTR (type) && op->isaddr && force)
1565 type = copyLinkChain (type);
1567 IC_RESULT (ic) = newiTempOperand (type, 1);
1568 IC_RESULT (ic)->isaddr = 0;
1570 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1574 return IC_RESULT (ic);
1577 /*-----------------------------------------------------------------*/
1578 /* geniCodeCast - changes the value from one type to another */
1579 /*-----------------------------------------------------------------*/
1581 geniCodeCast (sym_link * type, operand * op, bool implicit)
1585 sym_link *opetype = getSpec (optype = operandType (op));
1589 /* one of them has size zero then error */
1590 if (IS_VOID (optype))
1592 werror (E_CAST_ZERO);
1596 /* if the operand is already the desired type then do nothing */
1597 if (compareType (type, optype) == 1)
1600 /* if this is a literal then just change the type & return */
1601 if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1602 return operandFromValue (valCastLiteral (type,
1603 operandLitValue (op)));
1605 /* if casting to/from pointers, do some checking */
1606 if (IS_PTR(type)) { // to a pointer
1607 if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer
1608 if (IS_INTEGRAL(optype)) {
1609 // maybe this is NULL, than it's ok.
1610 if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
1611 if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80 && IS_GENPTR(type)) {
1612 // no way to set the storage
1613 if (IS_LITERAL(optype)) {
1614 werror(E_LITERAL_GENERIC);
1617 werror(E_NONPTR2_GENPTR);
1620 } else if (implicit) {
1621 werror(W_INTEGRAL2PTR_NOCAST);
1626 // shouldn't do that with float, array or structure unless to void
1627 if (!IS_VOID(getSpec(type)) &&
1628 !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1629 werror(E_INCOMPAT_TYPES);
1633 } else { // from a pointer to a pointer
1634 if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80) {
1635 // if not a pointer to a function
1636 if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1637 if (implicit) { // if not to generic, they have to match
1638 if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
1639 werror(E_INCOMPAT_PTYPES);
1646 } else { // to a non pointer
1647 if (IS_PTR(optype)) { // from a pointer
1648 if (implicit) { // sneaky
1649 if (IS_INTEGRAL(type)) {
1650 werror(W_PTR2INTEGRAL_NOCAST);
1652 } else { // shouldn't do that with float, array or structure
1653 werror(E_INCOMPAT_TYPES);
1660 printFromToType (optype, type);
1663 /* if they are the same size create an assignment */
1664 if (getSize (type) == getSize (optype) &&
1665 !IS_BITFIELD (type) &&
1667 !IS_FLOAT (optype) &&
1668 ((IS_SPEC (type) && IS_SPEC (optype)) ||
1669 (!IS_SPEC (type) && !IS_SPEC (optype))))
1672 ic = newiCode ('=', NULL, op);
1673 IC_RESULT (ic) = newiTempOperand (type, 0);
1674 SPIL_LOC (IC_RESULT (ic)) =
1675 (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
1676 IC_RESULT (ic)->isaddr = 0;
1680 ic = newiCode (CAST, operandFromLink (type),
1681 geniCodeRValue (op, FALSE));
1683 IC_RESULT (ic) = newiTempOperand (type, 0);
1686 /* preserve the storage class & output class */
1687 /* of the original variable */
1688 restype = getSpec (operandType (IC_RESULT (ic)));
1689 SPEC_SCLS (restype) = SPEC_SCLS (opetype);
1690 SPEC_OCLS (restype) = SPEC_OCLS (opetype);
1693 return IC_RESULT (ic);
1696 /*-----------------------------------------------------------------*/
1697 /* geniCodeLabel - will create a Label */
1698 /*-----------------------------------------------------------------*/
1700 geniCodeLabel (symbol * label)
1704 ic = newiCodeLabelGoto (LABEL, label);
1708 /*-----------------------------------------------------------------*/
1709 /* geniCodeGoto - will create a Goto */
1710 /*-----------------------------------------------------------------*/
1712 geniCodeGoto (symbol * label)
1716 ic = newiCodeLabelGoto (GOTO, label);
1720 /*-----------------------------------------------------------------*/
1721 /* geniCodeMultiply - gen intermediate code for multiplication */
1722 /*-----------------------------------------------------------------*/
1724 geniCodeMultiply (operand * left, operand * right,int resultIsInt)
1731 /* if they are both literal then we know the result */
1732 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1733 return operandFromValue (valMult (left->operand.valOperand,
1734 right->operand.valOperand));
1736 if (IS_LITERAL(retype)) {
1737 p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
1740 resType = usualBinaryConversions (&left, &right);
1742 rtype = operandType (right);
1743 retype = getSpec (rtype);
1744 ltype = operandType (left);
1745 letype = getSpec (ltype);
1749 SPEC_NOUN(getSpec(resType))=V_INT;
1752 /* if the right is a literal & power of 2 */
1753 /* then make it a left shift */
1754 /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
1755 efficient in most cases than 2 bytes result = 2 bytes << literal
1756 if port has 1 byte muldiv */
1757 if (p2 && !IS_FLOAT (letype) &&
1758 !((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
1759 (port->support.muldiv == 1)))
1761 if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
1763 /* LEFT_OP need same size for left and result, */
1764 left = geniCodeCast (resType, left, TRUE);
1765 ltype = operandType (left);
1767 ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
1771 ic = newiCode ('*', left, right); /* normal multiplication */
1772 /* if the size left or right > 1 then support routine */
1773 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1777 IC_RESULT (ic) = newiTempOperand (resType, 1);
1780 return IC_RESULT (ic);
1783 /*-----------------------------------------------------------------*/
1784 /* geniCodeDivision - gen intermediate code for division */
1785 /*-----------------------------------------------------------------*/
1787 geniCodeDivision (operand * left, operand * right)
1792 sym_link *rtype = operandType (right);
1793 sym_link *retype = getSpec (rtype);
1794 sym_link *ltype = operandType (left);
1795 sym_link *letype = getSpec (ltype);
1797 resType = usualBinaryConversions (&left, &right);
1799 /* if the right is a literal & power of 2 */
1800 /* then make it a right shift */
1801 if (IS_LITERAL (retype) &&
1802 !IS_FLOAT (letype) &&
1803 (p2 = powof2 ((unsigned long)
1804 floatFromVal (right->operand.valOperand)))) {
1805 ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
1809 ic = newiCode ('/', left, right); /* normal division */
1810 /* if the size left or right > 1 then support routine */
1811 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1814 IC_RESULT (ic) = newiTempOperand (resType, 0);
1817 return IC_RESULT (ic);
1819 /*-----------------------------------------------------------------*/
1820 /* geniCodeModulus - gen intermediate code for modulus */
1821 /*-----------------------------------------------------------------*/
1823 geniCodeModulus (operand * left, operand * right)
1829 /* if they are both literal then we know the result */
1830 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1831 return operandFromValue (valMod (left->operand.valOperand,
1832 right->operand.valOperand));
1834 resType = usualBinaryConversions (&left, &right);
1836 /* now they are the same size */
1837 ic = newiCode ('%', left, right);
1839 /* if the size left or right > 1 then support routine */
1840 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1842 IC_RESULT (ic) = newiTempOperand (resType, 0);
1845 return IC_RESULT (ic);
1848 /*-----------------------------------------------------------------*/
1849 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
1850 /*-----------------------------------------------------------------*/
1852 geniCodePtrPtrSubtract (operand * left, operand * right)
1858 /* if they are both literals then */
1859 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1861 result = operandFromValue (valMinus (left->operand.valOperand,
1862 right->operand.valOperand));
1866 ic = newiCode ('-', left, right);
1868 IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
1872 return geniCodeDivision (result,
1873 operandFromLit (getSize (ltype->next)));
1876 /*-----------------------------------------------------------------*/
1877 /* geniCodeSubtract - generates code for subtraction */
1878 /*-----------------------------------------------------------------*/
1880 geniCodeSubtract (operand * left, operand * right)
1887 /* if they both pointers then */
1888 if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
1889 (IS_PTR (rtype) || IS_ARRAY (rtype)))
1890 return geniCodePtrPtrSubtract (left, right);
1892 /* if they are both literal then we know the result */
1893 if (IS_LITERAL (letype) && IS_LITERAL (retype)
1894 && left->isLiteral && right->isLiteral)
1895 return operandFromValue (valMinus (left->operand.valOperand,
1896 right->operand.valOperand));
1898 /* if left is an array or pointer */
1899 if (IS_PTR (ltype) || IS_ARRAY (ltype))
1901 isarray = left->isaddr;
1902 right = geniCodeMultiply (right,
1903 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
1904 resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
1907 { /* make them the same size */
1908 resType = usualBinaryConversions (&left, &right);
1911 ic = newiCode ('-', left, right);
1913 IC_RESULT (ic) = newiTempOperand (resType, 1);
1914 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
1916 /* if left or right is a float */
1917 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
1921 return IC_RESULT (ic);
1924 /*-----------------------------------------------------------------*/
1925 /* geniCodeAdd - generates iCode for addition */
1926 /*-----------------------------------------------------------------*/
1928 geniCodeAdd (operand * left, operand * right,int lvl)
1936 /* if left is an array then array access */
1937 if (IS_ARRAY (ltype))
1938 return geniCodeArray (left, right,lvl);
1940 /* if the right side is LITERAL zero */
1941 /* return the left side */
1942 if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
1945 /* if left is literal zero return right */
1946 if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
1949 /* if left is an array or pointer then size */
1952 isarray = left->isaddr;
1953 // there is no need to multiply with 1
1954 if (getSize(ltype->next)!=1) {
1955 size = operandFromLit (getSize (ltype->next));
1956 right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
1958 resType = copyLinkChain (ltype);
1961 { /* make them the same size */
1962 resType = usualBinaryConversions (&left, &right);
1965 /* if they are both literals then we know */
1966 if (IS_LITERAL (letype) && IS_LITERAL (retype)
1967 && left->isLiteral && right->isLiteral)
1968 return operandFromValue (valPlus (valFromType (letype),
1969 valFromType (retype)));
1971 ic = newiCode ('+', left, right);
1973 IC_RESULT (ic) = newiTempOperand (resType, 1);
1974 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
1976 /* if left or right is a float then support
1978 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
1983 return IC_RESULT (ic);
1987 /*-----------------------------------------------------------------*/
1988 /* aggrToPtr - changes an aggregate to pointer to an aggregate */
1989 /*-----------------------------------------------------------------*/
1991 aggrToPtr (sym_link * type, bool force)
1997 if (IS_PTR (type) && !force)
2000 etype = getSpec (type);
2004 /* if the output class is generic */
2005 if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER)
2006 DCL_PTR_CONST (ptype) = port->mem.code_ro;
2008 /* if the variable was declared a constant */
2009 /* then the pointer points to a constant */
2010 if (IS_CONSTANT (etype))
2011 DCL_PTR_CONST (ptype) = 1;
2013 /* the variable was volatile then pointer to volatile */
2014 if (IS_VOLATILE (etype))
2015 DCL_PTR_VOLATILE (ptype) = 1;
2019 /*-----------------------------------------------------------------*/
2020 /* geniCodeArray2Ptr - array to pointer */
2021 /*-----------------------------------------------------------------*/
2023 geniCodeArray2Ptr (operand * op)
2025 sym_link *optype = operandType (op);
2026 sym_link *opetype = getSpec (optype);
2028 /* set the pointer depending on the storage class */
2029 if ((DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2030 DCL_PTR_CONST (optype) = port->mem.code_ro;
2033 /* if the variable was declared a constant */
2034 /* then the pointer points to a constant */
2035 if (IS_CONSTANT (opetype))
2036 DCL_PTR_CONST (optype) = 1;
2038 /* the variable was volatile then pointer to volatile */
2039 if (IS_VOLATILE (opetype))
2040 DCL_PTR_VOLATILE (optype) = 1;
2046 /*-----------------------------------------------------------------*/
2047 /* geniCodeArray - array access */
2048 /*-----------------------------------------------------------------*/
2050 geniCodeArray (operand * left, operand * right,int lvl)
2053 sym_link *ltype = operandType (left);
2057 if (IS_PTR (ltype->next) && left->isaddr)
2059 left = geniCodeRValue (left, FALSE);
2061 return geniCodeDerefPtr (geniCodeAdd (left, right,lvl),lvl);
2064 right = geniCodeMultiply (right,
2065 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2067 /* we can check for limits here */
2068 if (isOperandLiteral (right) &&
2071 (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2073 werror (E_ARRAY_BOUND);
2074 right = operandFromLit (0);
2077 ic = newiCode ('+', left, right);
2079 IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2080 !IS_AGGREGATE (ltype->next) &&
2081 !IS_PTR (ltype->next))
2082 ? ltype : ltype->next), 0);
2084 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
2086 return IC_RESULT (ic);
2089 /*-----------------------------------------------------------------*/
2090 /* geniCodeStruct - generates intermediate code for structres */
2091 /*-----------------------------------------------------------------*/
2093 geniCodeStruct (operand * left, operand * right, bool islval)
2096 sym_link *type = operandType (left);
2097 sym_link *etype = getSpec (type);
2099 symbol *element = getStructElement (SPEC_STRUCT (etype),
2100 right->operand.symOperand);
2102 /* add the offset */
2103 ic = newiCode ('+', left, operandFromLit (element->offset));
2105 IC_RESULT (ic) = newiTempOperand (element->type, 0);
2107 /* preserve the storage & output class of the struct */
2108 /* as well as the volatile attribute */
2109 retype = getSpec (operandType (IC_RESULT (ic)));
2110 SPEC_SCLS (retype) = SPEC_SCLS (etype);
2111 SPEC_OCLS (retype) = SPEC_OCLS (etype);
2112 SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2114 if (IS_PTR (element->type))
2115 setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2117 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2121 return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2124 /*-----------------------------------------------------------------*/
2125 /* geniCodePostInc - generate int code for Post increment */
2126 /*-----------------------------------------------------------------*/
2128 geniCodePostInc (operand * op)
2132 sym_link *optype = operandType (op);
2134 operand *rv = (IS_ITEMP (op) ?
2135 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2137 sym_link *rvtype = operandType (rv);
2140 /* if this is not an address we have trouble */
2143 werror (E_LVALUE_REQUIRED, "++");
2147 rOp = newiTempOperand (rvtype, 0);
2148 OP_SYMBOL(rOp)->noSpilLoc = 1;
2151 OP_SYMBOL(rv)->noSpilLoc = 1;
2153 geniCodeAssign (rOp, rv, 0);
2155 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2156 if (IS_FLOAT (rvtype))
2157 ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2159 ic = newiCode ('+', rv, operandFromLit (size));
2161 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2164 geniCodeAssign (op, result, 0);
2170 /*-----------------------------------------------------------------*/
2171 /* geniCodePreInc - generate code for preIncrement */
2172 /*-----------------------------------------------------------------*/
2174 geniCodePreInc (operand * op)
2177 sym_link *optype = operandType (op);
2178 operand *rop = (IS_ITEMP (op) ?
2179 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2181 sym_link *roptype = operandType (rop);
2187 werror (E_LVALUE_REQUIRED, "++");
2192 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2193 if (IS_FLOAT (roptype))
2194 ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2196 ic = newiCode ('+', rop, operandFromLit (size));
2197 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2201 return geniCodeAssign (op, result, 0);
2204 /*-----------------------------------------------------------------*/
2205 /* geniCodePostDec - generates code for Post decrement */
2206 /*-----------------------------------------------------------------*/
2208 geniCodePostDec (operand * op)
2212 sym_link *optype = operandType (op);
2214 operand *rv = (IS_ITEMP (op) ?
2215 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2217 sym_link *rvtype = operandType (rv);
2220 /* if this is not an address we have trouble */
2223 werror (E_LVALUE_REQUIRED, "--");
2227 rOp = newiTempOperand (rvtype, 0);
2228 OP_SYMBOL(rOp)->noSpilLoc = 1;
2231 OP_SYMBOL(rv)->noSpilLoc = 1;
2233 geniCodeAssign (rOp, rv, 0);
2235 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2236 if (IS_FLOAT (rvtype))
2237 ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2239 ic = newiCode ('-', rv, operandFromLit (size));
2241 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2244 geniCodeAssign (op, result, 0);
2250 /*-----------------------------------------------------------------*/
2251 /* geniCodePreDec - generate code for pre decrement */
2252 /*-----------------------------------------------------------------*/
2254 geniCodePreDec (operand * op)
2257 sym_link *optype = operandType (op);
2258 operand *rop = (IS_ITEMP (op) ?
2259 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2261 sym_link *roptype = operandType (rop);
2267 werror (E_LVALUE_REQUIRED, "--");
2272 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2273 if (IS_FLOAT (roptype))
2274 ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2276 ic = newiCode ('-', rop, operandFromLit (size));
2277 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2281 return geniCodeAssign (op, result, 0);
2285 /*-----------------------------------------------------------------*/
2286 /* geniCodeBitwise - gen int code for bitWise operators */
2287 /*-----------------------------------------------------------------*/
2289 geniCodeBitwise (operand * left, operand * right,
2290 int oper, sym_link * resType)
2294 // bitwise operations must be done unsigned
2295 SPEC_USIGN(resType)=1;
2297 left = geniCodeCast (resType, left, TRUE);
2298 right = geniCodeCast (resType, right, TRUE);
2300 ic = newiCode (oper, left, right);
2301 IC_RESULT (ic) = newiTempOperand (resType, 0);
2304 return IC_RESULT (ic);
2307 /*-----------------------------------------------------------------*/
2308 /* geniCodeAddressOf - gens icode for '&' address of operator */
2309 /*-----------------------------------------------------------------*/
2311 geniCodeAddressOf (operand * op)
2315 sym_link *optype = operandType (op);
2316 sym_link *opetype = getSpec (optype);
2318 /* lvalue check already done in decorateType */
2319 /* this must be a lvalue */
2320 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2321 /* werror (E_LVALUE_REQUIRED,"&"); */
2326 p->class = DECLARATOR;
2328 /* set the pointer depending on the storage class */
2329 if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2330 DCL_PTR_CONST (p) = port->mem.code_ro;
2332 /* make sure we preserve the const & volatile */
2333 if (IS_CONSTANT (opetype))
2334 DCL_PTR_CONST (p) = 1;
2336 if (IS_VOLATILE (opetype))
2337 DCL_PTR_VOLATILE (p) = 1;
2339 p->next = copyLinkChain (optype);
2341 /* if already a temp */
2344 setOperandType (op, p);
2349 /* other wise make this of the type coming in */
2350 ic = newiCode (ADDRESS_OF, op, NULL);
2351 IC_RESULT (ic) = newiTempOperand (p, 1);
2352 IC_RESULT (ic)->isaddr = 0;
2354 return IC_RESULT (ic);
2356 /*-----------------------------------------------------------------*/
2357 /* setOClass - sets the output class depending on the pointer type */
2358 /*-----------------------------------------------------------------*/
2360 setOClass (sym_link * ptr, sym_link * spec)
2362 switch (DCL_TYPE (ptr))
2365 SPEC_OCLS (spec) = data;
2369 SPEC_OCLS (spec) = generic;
2373 SPEC_OCLS (spec) = xdata;
2377 SPEC_OCLS (spec) = code;
2381 SPEC_OCLS (spec) = idata;
2385 SPEC_OCLS (spec) = xstack;
2389 SPEC_OCLS (spec) = eeprom;
2398 /*-----------------------------------------------------------------*/
2399 /* geniCodeDerefPtr - dereference pointer with '*' */
2400 /*-----------------------------------------------------------------*/
2402 geniCodeDerefPtr (operand * op,int lvl)
2404 sym_link *rtype, *retype;
2405 sym_link *optype = operandType (op);
2407 /* if this is a pointer then generate the rvalue */
2408 if (IS_PTR (optype))
2410 if (IS_TRUE_SYMOP (op))
2413 op = geniCodeRValue (op, TRUE);
2416 op = geniCodeRValue (op, TRUE);
2419 /* now get rid of the pointer part */
2420 if (isLvaluereq(lvl) && IS_ITEMP (op))
2422 retype = getSpec (rtype = copyLinkChain (optype));
2426 retype = getSpec (rtype = copyLinkChain (optype->next));
2429 /* if this is a pointer then outputclass needs 2b updated */
2430 if (IS_PTR (optype))
2431 setOClass (optype, retype);
2433 op->isGptr = IS_GENPTR (optype);
2435 /* if the pointer was declared as a constant */
2436 /* then we cannot allow assignment to the derefed */
2437 if (IS_PTR_CONST (optype))
2438 SPEC_CONST (retype) = 1;
2440 op->isaddr = (IS_PTR (rtype) ||
2441 IS_STRUCT (rtype) ||
2446 if (!isLvaluereq(lvl))
2447 op = geniCodeRValue (op, TRUE);
2449 setOperandType (op, rtype);
2454 /*-----------------------------------------------------------------*/
2455 /* geniCodeUnaryMinus - does a unary minus of the operand */
2456 /*-----------------------------------------------------------------*/
2458 geniCodeUnaryMinus (operand * op)
2461 sym_link *optype = operandType (op);
2463 if (IS_LITERAL (optype))
2464 return operandFromLit (-floatFromVal (op->operand.valOperand));
2466 ic = newiCode (UNARYMINUS, op, NULL);
2467 IC_RESULT (ic) = newiTempOperand (optype, 0);
2469 return IC_RESULT (ic);
2472 /*-----------------------------------------------------------------*/
2473 /* geniCodeLeftShift - gen i code for left shift */
2474 /*-----------------------------------------------------------------*/
2476 geniCodeLeftShift (operand * left, operand * right)
2480 ic = newiCode (LEFT_OP, left, right);
2481 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2483 return IC_RESULT (ic);
2486 /*-----------------------------------------------------------------*/
2487 /* geniCodeRightShift - gen i code for right shift */
2488 /*-----------------------------------------------------------------*/
2490 geniCodeRightShift (operand * left, operand * right)
2494 ic = newiCode (RIGHT_OP, left, right);
2495 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2497 return IC_RESULT (ic);
2500 /*-----------------------------------------------------------------*/
2501 /* geniCodeLogic- logic code */
2502 /*-----------------------------------------------------------------*/
2504 geniCodeLogic (operand * left, operand * right, int op)
2508 sym_link *rtype = operandType (right);
2509 sym_link *ltype = operandType (left);
2511 /* left is integral type and right is literal then
2512 check if the literal value is within bounds */
2513 if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2515 checkConstantRange(ltype,
2516 OP_VALUE(right), "compare operation", 1);
2519 ctype = usualBinaryConversions (&left, &right);
2521 ic = newiCode (op, left, right);
2522 IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2524 /* if comparing float
2525 and not a '==' || '!=' || '&&' || '||' (these
2527 if (IS_FLOAT(ctype) &&
2535 return IC_RESULT (ic);
2538 /*-----------------------------------------------------------------*/
2539 /* geniCodeUnary - for a a generic unary operation */
2540 /*-----------------------------------------------------------------*/
2542 geniCodeUnary (operand * op, int oper)
2544 iCode *ic = newiCode (oper, op, NULL);
2546 IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2548 return IC_RESULT (ic);
2551 /*-----------------------------------------------------------------*/
2552 /* geniCodeConditional - geniCode for '?' ':' operation */
2553 /*-----------------------------------------------------------------*/
2555 geniCodeConditional (ast * tree,int lvl)
2558 symbol *falseLabel = newiTempLabel (NULL);
2559 symbol *exitLabel = newiTempLabel (NULL);
2560 operand *cond = ast2iCode (tree->left,lvl+1);
2561 operand *true, *false, *result;
2563 ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
2567 true = ast2iCode (tree->right->left,lvl+1);
2569 /* move the value to a new Operand */
2570 result = newiTempOperand (operandType (true), 0);
2571 geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
2573 /* generate an unconditional goto */
2574 geniCodeGoto (exitLabel);
2576 /* now for the right side */
2577 geniCodeLabel (falseLabel);
2579 false = ast2iCode (tree->right->right,lvl+1);
2580 geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
2582 /* create the exit label */
2583 geniCodeLabel (exitLabel);
2588 /*-----------------------------------------------------------------*/
2589 /* geniCodeAssign - generate code for assignment */
2590 /*-----------------------------------------------------------------*/
2592 geniCodeAssign (operand * left, operand * right, int nosupdate)
2595 sym_link *ltype = operandType (left);
2596 sym_link *rtype = operandType (right);
2598 if (!left->isaddr && !IS_ITEMP (left))
2600 werror (E_LVALUE_REQUIRED, "assignment");
2604 /* left is integral type and right is literal then
2605 check if the literal value is within bounds */
2606 if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
2608 checkConstantRange(ltype,
2609 OP_VALUE(right), "= operation", 0);
2612 /* if the left & right type don't exactly match */
2613 /* if pointer set then make sure the check is
2614 done with the type & not the pointer */
2615 /* then cast rights type to left */
2617 /* first check the type for pointer assignement */
2618 if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
2619 compareType (ltype, rtype) <= 0)
2621 if (compareType (ltype->next, rtype) < 0)
2622 right = geniCodeCast (ltype->next, right, TRUE);
2624 else if (compareType (ltype, rtype) < 0)
2625 right = geniCodeCast (ltype, right, TRUE);
2627 /* if left is a true symbol & ! volatile
2628 create an assignment to temporary for
2629 the right & then assign this temporary
2630 to the symbol this is SSA . isn't it simple
2631 and folks have published mountains of paper on it */
2632 if (IS_TRUE_SYMOP (left) &&
2633 !isOperandVolatile (left, FALSE) &&
2634 isOperandGlobal (left))
2638 if (IS_TRUE_SYMOP (right))
2639 sym = OP_SYMBOL (right);
2640 ic = newiCode ('=', NULL, right);
2641 IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
2642 SPIL_LOC (right) = sym;
2646 ic = newiCode ('=', NULL, right);
2647 IC_RESULT (ic) = left;
2650 /* if left isgptr flag is set then support
2651 routine will be required */
2655 ic->nosupdate = nosupdate;
2659 /*-----------------------------------------------------------------*/
2660 /* geniCodeSEParms - generate code for side effecting fcalls */
2661 /*-----------------------------------------------------------------*/
2663 geniCodeSEParms (ast * parms,int lvl)
2668 if (parms->type == EX_OP && parms->opval.op == PARAM)
2670 geniCodeSEParms (parms->left,lvl);
2671 geniCodeSEParms (parms->right,lvl);
2675 /* hack don't like this but too lazy to think of
2677 if (IS_ADDRESS_OF_OP (parms))
2678 parms->left->lvalue = 1;
2680 if (IS_CAST_OP (parms) &&
2681 IS_PTR (parms->ftype) &&
2682 IS_ADDRESS_OF_OP (parms->right))
2683 parms->right->left->lvalue = 1;
2685 parms->opval.oprnd =
2686 geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2688 parms->type = EX_OPERAND;
2691 /*-----------------------------------------------------------------*/
2692 /* geniCodeParms - generates parameters */
2693 /*-----------------------------------------------------------------*/
2695 geniCodeParms (ast * parms, value *argVals, int *stack,
2696 sym_link * fetype, symbol * func,int lvl)
2704 if (argVals==NULL) {
2706 argVals=FUNC_ARGS(func->type);
2709 /* if this is a param node then do the left & right */
2710 if (parms->type == EX_OP && parms->opval.op == PARAM)
2712 argVals=geniCodeParms (parms->left, argVals, stack, fetype, func,lvl);
2713 argVals=geniCodeParms (parms->right, argVals, stack, fetype, func,lvl);
2717 /* get the parameter value */
2718 if (parms->type == EX_OPERAND)
2719 pval = parms->opval.oprnd;
2722 /* maybe this else should go away ?? */
2723 /* hack don't like this but too lazy to think of
2725 if (IS_ADDRESS_OF_OP (parms))
2726 parms->left->lvalue = 1;
2728 if (IS_CAST_OP (parms) &&
2729 IS_PTR (parms->ftype) &&
2730 IS_ADDRESS_OF_OP (parms->right))
2731 parms->right->left->lvalue = 1;
2733 pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2736 /* if register parm then make it a send */
2737 if (IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(func->type))
2739 ic = newiCode (SEND, pval, NULL);
2744 /* now decide whether to push or assign */
2745 if (!(options.stackAuto || IFFUNC_ISREENT (func->type)))
2749 operand *top = operandFromSymbol (argVals->sym);
2750 geniCodeAssign (top, pval, 1);
2754 sym_link *p = operandType (pval);
2756 ic = newiCode (IPUSH, pval, NULL);
2758 /* update the stack adjustment */
2759 *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2764 argVals=argVals->next;
2768 /*-----------------------------------------------------------------*/
2769 /* geniCodeCall - generates temp code for calling */
2770 /*-----------------------------------------------------------------*/
2772 geniCodeCall (operand * left, ast * parms,int lvl)
2776 sym_link *type, *etype;
2779 if (!IS_FUNC(OP_SYMBOL(left)->type) &&
2780 !IS_CODEPTR(OP_SYMBOL(left)->type)) {
2781 werror (E_FUNCTION_EXPECTED);
2785 /* take care of parameters with side-effecting
2786 function calls in them, this is required to take care
2787 of overlaying function parameters */
2788 geniCodeSEParms (parms,lvl);
2790 /* first the parameters */
2791 geniCodeParms (parms, NULL, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
2793 /* now call : if symbol then pcall */
2794 if (IS_OP_POINTER (left) || IS_ITEMP(left))
2795 ic = newiCode (PCALL, left, NULL);
2797 ic = newiCode (CALL, left, NULL);
2799 type = copyLinkChain (operandType (left)->next);
2800 etype = getSpec (type);
2801 SPEC_EXTR (etype) = 0;
2802 IC_RESULT (ic) = result = newiTempOperand (type, 1);
2806 /* stack adjustment after call */
2807 ic->parmBytes = stack;
2812 /*-----------------------------------------------------------------*/
2813 /* geniCodeReceive - generate intermediate code for "receive" */
2814 /*-----------------------------------------------------------------*/
2816 geniCodeReceive (value * args)
2818 /* for all arguments that are passed in registers */
2822 if (IS_REGPARM (args->etype))
2824 operand *opr = operandFromValue (args);
2826 symbol *sym = OP_SYMBOL (opr);
2829 /* we will use it after all optimizations
2830 and before liveRange calculation */
2831 if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
2834 if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
2835 options.stackAuto == 0 &&
2836 /* !TARGET_IS_DS390) */
2837 (!(options.model == MODEL_FLAT24)) )
2842 opl = newiTempOperand (args->type, 0);
2844 sym->reqv->key = sym->key;
2845 OP_SYMBOL (sym->reqv)->key = sym->key;
2846 OP_SYMBOL (sym->reqv)->isreqv = 1;
2847 OP_SYMBOL (sym->reqv)->islocal = 0;
2848 SPIL_LOC (sym->reqv) = sym;
2852 ic = newiCode (RECEIVE, NULL, NULL);
2853 currFunc->recvSize = getSize (sym->etype);
2854 IC_RESULT (ic) = opr;
2862 /*-----------------------------------------------------------------*/
2863 /* geniCodeFunctionBody - create the function body */
2864 /*-----------------------------------------------------------------*/
2866 geniCodeFunctionBody (ast * tree,int lvl)
2873 /* reset the auto generation */
2879 func = ast2iCode (tree->left,lvl+1);
2880 fetype = getSpec (operandType (func));
2882 savelineno = lineno;
2883 lineno = OP_SYMBOL (func)->lineDef;
2884 /* create an entry label */
2885 geniCodeLabel (entryLabel);
2886 lineno = savelineno;
2888 /* create a proc icode */
2889 ic = newiCode (FUNCTION, func, NULL);
2890 ic->lineno = OP_SYMBOL (func)->lineDef;
2894 /* for all parameters that are passed
2895 on registers add a "receive" */
2896 geniCodeReceive (tree->values.args);
2898 /* generate code for the body */
2899 ast2iCode (tree->right,lvl+1);
2901 /* create a label for return */
2902 geniCodeLabel (returnLabel);
2904 /* now generate the end proc */
2905 ic = newiCode (ENDFUNCTION, func, NULL);
2910 /*-----------------------------------------------------------------*/
2911 /* geniCodeReturn - gen icode for 'return' statement */
2912 /*-----------------------------------------------------------------*/
2914 geniCodeReturn (operand * op)
2918 /* if the operand is present force an rvalue */
2920 op = geniCodeRValue (op, FALSE);
2922 ic = newiCode (RETURN, op, NULL);
2926 /*-----------------------------------------------------------------*/
2927 /* geniCodeIfx - generates code for extended if statement */
2928 /*-----------------------------------------------------------------*/
2930 geniCodeIfx (ast * tree,int lvl)
2933 operand *condition = ast2iCode (tree->left,lvl+1);
2936 /* if condition is null then exit */
2940 condition = geniCodeRValue (condition, FALSE);
2942 cetype = getSpec (operandType (condition));
2943 /* if the condition is a literal */
2944 if (IS_LITERAL (cetype))
2946 if (floatFromVal (condition->operand.valOperand))
2948 if (tree->trueLabel)
2949 geniCodeGoto (tree->trueLabel);
2955 if (tree->falseLabel)
2956 geniCodeGoto (tree->falseLabel);
2963 if (tree->trueLabel)
2965 ic = newiCodeCondition (condition,
2970 if (tree->falseLabel)
2971 geniCodeGoto (tree->falseLabel);
2975 ic = newiCodeCondition (condition,
2982 ast2iCode (tree->right,lvl+1);
2985 /*-----------------------------------------------------------------*/
2986 /* geniCodeJumpTable - tries to create a jump table for switch */
2987 /*-----------------------------------------------------------------*/
2989 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
2991 int min = 0, max = 0, t, cnt = 0;
2998 if (!tree || !caseVals)
3001 /* the criteria for creating a jump table is */
3002 /* all integer numbers between the maximum & minimum must */
3003 /* be present , the maximum value should not exceed 255 */
3004 min = max = (int) floatFromVal (vch = caseVals);
3005 sprintf (buffer, "_case_%d_%d",
3006 tree->values.switchVals.swNum,
3008 addSet (&labels, newiTempLabel (buffer));
3010 /* if there is only one case value then no need */
3011 if (!(vch = vch->next))
3016 if (((t = (int) floatFromVal (vch)) - max) != 1)
3018 sprintf (buffer, "_case_%d_%d",
3019 tree->values.switchVals.swNum,
3021 addSet (&labels, newiTempLabel (buffer));
3027 /* if the number of case statements <= 2 then */
3028 /* it is not economical to create the jump table */
3029 /* since two compares are needed for boundary conditions */
3030 if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
3033 if (tree->values.switchVals.swDefault)
3034 sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3036 sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3038 falseLabel = newiTempLabel (buffer);
3040 /* so we can create a jumptable */
3041 /* first we rule out the boundary conditions */
3042 /* if only optimization says so */
3043 if (!optimize.noJTabBoundary)
3045 sym_link *cetype = getSpec (operandType (cond));
3046 /* no need to check the lower bound if
3047 the condition is unsigned & minimum value is zero */
3048 if (!(min == 0 && SPEC_USIGN (cetype)))
3050 boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3051 ic = newiCodeCondition (boundary, falseLabel, NULL);
3055 /* now for upper bounds */
3056 boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3057 ic = newiCodeCondition (boundary, falseLabel, NULL);
3061 /* if the min is not zero then we no make it zero */
3064 cond = geniCodeSubtract (cond, operandFromLit (min));
3065 setOperandType (cond, UCHARTYPE);
3068 /* now create the jumptable */
3069 ic = newiCode (JUMPTABLE, NULL, NULL);
3070 IC_JTCOND (ic) = cond;
3071 IC_JTLABELS (ic) = labels;
3076 /*-----------------------------------------------------------------*/
3077 /* geniCodeSwitch - changes a switch to a if statement */
3078 /*-----------------------------------------------------------------*/
3080 geniCodeSwitch (ast * tree,int lvl)
3083 operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3084 value *caseVals = tree->values.switchVals.swVals;
3085 symbol *trueLabel, *falseLabel;
3087 /* if we can make this a jump table */
3088 if (geniCodeJumpTable (cond, caseVals, tree))
3089 goto jumpTable; /* no need for the comparison */
3091 /* for the cases defined do */
3095 operand *compare = geniCodeLogic (cond,
3096 operandFromValue (caseVals),
3099 sprintf (buffer, "_case_%d_%d",
3100 tree->values.switchVals.swNum,
3101 (int) floatFromVal (caseVals));
3102 trueLabel = newiTempLabel (buffer);
3104 ic = newiCodeCondition (compare, trueLabel, NULL);
3106 caseVals = caseVals->next;
3111 /* if default is present then goto break else break */
3112 if (tree->values.switchVals.swDefault)
3113 sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3115 sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3117 falseLabel = newiTempLabel (buffer);
3118 geniCodeGoto (falseLabel);
3121 ast2iCode (tree->right,lvl+1);
3124 /*-----------------------------------------------------------------*/
3125 /* geniCodeInline - intermediate code for inline assembler */
3126 /*-----------------------------------------------------------------*/
3128 geniCodeInline (ast * tree)
3132 ic = newiCode (INLINEASM, NULL, NULL);
3133 IC_INLINE (ic) = tree->values.inlineasm;
3137 /*-----------------------------------------------------------------*/
3138 /* geniCodeArrayInit - intermediate code for array initializer */
3139 /*-----------------------------------------------------------------*/
3141 geniCodeArrayInit (ast * tree, operand *array)
3145 if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3146 ic = newiCode (ARRAYINIT, array, NULL);
3147 IC_ARRAYILIST (ic) = tree->values.constlist;
3149 operand *left=newOperand(), *right=newOperand();
3150 left->type=right->type=SYMBOL;
3151 OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3152 OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3153 ic = newiCode (ARRAYINIT, left, right);
3158 /*-----------------------------------------------------------------*/
3159 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
3160 /* particular case. Ie : assigning or dereferencing array or ptr */
3161 /*-----------------------------------------------------------------*/
3162 set * lvaluereqSet = NULL;
3163 typedef struct lvalItem
3170 /*-----------------------------------------------------------------*/
3171 /* addLvaluereq - add a flag for lvalreq for current ast level */
3172 /*-----------------------------------------------------------------*/
3173 void addLvaluereq(int lvl)
3175 lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3178 addSetHead(&lvaluereqSet,lpItem);
3181 /*-----------------------------------------------------------------*/
3182 /* delLvaluereq - del a flag for lvalreq for current ast level */
3183 /*-----------------------------------------------------------------*/
3187 lpItem = getSet(&lvaluereqSet);
3188 if(lpItem) Safe_free(lpItem);
3190 /*-----------------------------------------------------------------*/
3191 /* clearLvaluereq - clear lvalreq flag */
3192 /*-----------------------------------------------------------------*/
3193 void clearLvaluereq()
3196 lpItem = peekSet(lvaluereqSet);
3197 if(lpItem) lpItem->req = 0;
3199 /*-----------------------------------------------------------------*/
3200 /* getLvaluereq - get the last lvalreq level */
3201 /*-----------------------------------------------------------------*/
3202 int getLvaluereqLvl()
3205 lpItem = peekSet(lvaluereqSet);
3206 if(lpItem) return lpItem->lvl;
3209 /*-----------------------------------------------------------------*/
3210 /* isLvaluereq - is lvalreq valid for this level ? */
3211 /*-----------------------------------------------------------------*/
3212 int isLvaluereq(int lvl)
3215 lpItem = peekSet(lvaluereqSet);
3216 if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3220 /*-----------------------------------------------------------------*/
3221 /* ast2iCode - creates an icodeList from an ast */
3222 /*-----------------------------------------------------------------*/
3224 ast2iCode (ast * tree,int lvl)
3226 operand *left = NULL;
3227 operand *right = NULL;
3230 /* set the global variables for filename & line number */
3232 filename = tree->filename;
3234 lineno = tree->lineno;
3236 block = tree->block;
3238 scopeLevel = tree->level;
3240 if (tree->type == EX_VALUE)
3241 return operandFromValue (tree->opval.val);
3243 if (tree->type == EX_LINK)
3244 return operandFromLink (tree->opval.lnk);
3246 /* if we find a nullop */
3247 if (tree->type == EX_OP &&
3248 (tree->opval.op == NULLOP ||
3249 tree->opval.op == BLOCK))
3251 ast2iCode (tree->left,lvl+1);
3252 ast2iCode (tree->right,lvl+1);
3256 /* special cases for not evaluating */
3257 if (tree->opval.op != ':' &&
3258 tree->opval.op != '?' &&
3259 tree->opval.op != CALL &&
3260 tree->opval.op != IFX &&
3261 tree->opval.op != LABEL &&
3262 tree->opval.op != GOTO &&
3263 tree->opval.op != SWITCH &&
3264 tree->opval.op != FUNCTION &&
3265 tree->opval.op != INLINEASM)
3268 if (IS_ASSIGN_OP (tree->opval.op) ||
3269 IS_DEREF_OP (tree) ||
3270 (tree->opval.op == '&' && !tree->right) ||
3271 tree->opval.op == PTR_OP)
3274 if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3275 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3278 left = operandFromAst (tree->left,lvl);
3280 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3281 left = geniCodeRValue (left, TRUE);
3285 left = operandFromAst (tree->left,lvl);
3287 if (tree->opval.op == INC_OP ||
3288 tree->opval.op == DEC_OP)
3291 right = operandFromAst (tree->right,lvl);
3296 right = operandFromAst (tree->right,lvl);
3300 /* now depending on the type of operand */
3301 /* this will be a biggy */
3302 switch (tree->opval.op)
3305 case '[': /* array operation */
3307 //sym_link *ltype = operandType (left);
3308 //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3309 left = geniCodeRValue (left, FALSE);
3310 right = geniCodeRValue (right, TRUE);
3313 return geniCodeArray (left, right,lvl);
3315 case '.': /* structure dereference */
3316 if (IS_PTR (operandType (left)))
3317 left = geniCodeRValue (left, TRUE);
3319 left = geniCodeRValue (left, FALSE);
3321 return geniCodeStruct (left, right, tree->lvalue);
3323 case PTR_OP: /* structure pointer dereference */
3326 pType = operandType (left);
3327 left = geniCodeRValue (left, TRUE);
3329 setOClass (pType, getSpec (operandType (left)));
3332 return geniCodeStruct (left, right, tree->lvalue);
3334 case INC_OP: /* increment operator */
3336 return geniCodePostInc (left);
3338 return geniCodePreInc (right);
3340 case DEC_OP: /* decrement operator */
3342 return geniCodePostDec (left);
3344 return geniCodePreDec (right);
3346 case '&': /* bitwise and or address of operator */
3348 { /* this is a bitwise operator */
3349 left = geniCodeRValue (left, FALSE);
3350 right = geniCodeRValue (right, FALSE);
3351 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3354 return geniCodeAddressOf (left);
3356 case '|': /* bitwise or & xor */
3358 return geniCodeBitwise (geniCodeRValue (left, FALSE),
3359 geniCodeRValue (right, FALSE),
3364 return geniCodeDivision (geniCodeRValue (left, FALSE),
3365 geniCodeRValue (right, FALSE));
3368 return geniCodeModulus (geniCodeRValue (left, FALSE),
3369 geniCodeRValue (right, FALSE));
3372 return geniCodeMultiply (geniCodeRValue (left, FALSE),
3373 geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3375 return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3379 return geniCodeSubtract (geniCodeRValue (left, FALSE),
3380 geniCodeRValue (right, FALSE));
3382 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3386 return geniCodeAdd (geniCodeRValue (left, FALSE),
3387 geniCodeRValue (right, FALSE),lvl);
3389 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
3392 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3393 geniCodeRValue (right, FALSE));
3396 return geniCodeRightShift (geniCodeRValue (left, FALSE),
3397 geniCodeRValue (right, FALSE));
3399 return geniCodeCast (operandType (left),
3400 geniCodeRValue (right, FALSE), FALSE);
3406 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3410 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3411 setOperandType (op, UCHARTYPE);
3422 return geniCodeLogic (geniCodeRValue (left, FALSE),
3423 geniCodeRValue (right, FALSE),
3426 return geniCodeConditional (tree,lvl);
3429 return operandFromLit (getSize (tree->right->ftype));
3433 sym_link *rtype = operandType (right);
3434 sym_link *ltype = operandType (left);
3435 if (IS_PTR (rtype) && IS_ITEMP (right)
3436 && right->isaddr && compareType (rtype->next, ltype) == 1)
3437 right = geniCodeRValue (right, TRUE);
3439 right = geniCodeRValue (right, FALSE);
3441 geniCodeAssign (left, right, 0);
3446 geniCodeAssign (left,
3447 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3449 geniCodeRValue (right, FALSE),FALSE), 0);
3453 geniCodeAssign (left,
3454 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3456 geniCodeRValue (right, FALSE)), 0);
3459 geniCodeAssign (left,
3460 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3462 geniCodeRValue (right, FALSE)), 0);
3465 sym_link *rtype = operandType (right);
3466 sym_link *ltype = operandType (left);
3467 if (IS_PTR (rtype) && IS_ITEMP (right)
3468 && right->isaddr && compareType (rtype->next, ltype) == 1)
3469 right = geniCodeRValue (right, TRUE);
3471 right = geniCodeRValue (right, FALSE);
3474 return geniCodeAssign (left,
3475 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3481 sym_link *rtype = operandType (right);
3482 sym_link *ltype = operandType (left);
3483 if (IS_PTR (rtype) && IS_ITEMP (right)
3484 && right->isaddr && compareType (rtype->next, ltype) == 1)
3486 right = geniCodeRValue (right, TRUE);
3490 right = geniCodeRValue (right, FALSE);
3493 geniCodeAssign (left,
3494 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3500 geniCodeAssign (left,
3501 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3503 geniCodeRValue (right, FALSE)), 0);
3506 geniCodeAssign (left,
3507 geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3509 geniCodeRValue (right, FALSE)), 0);
3512 geniCodeAssign (left,
3513 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3515 geniCodeRValue (right, FALSE),
3517 operandType (left)), 0);
3520 geniCodeAssign (left,
3521 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3523 geniCodeRValue (right, FALSE),
3525 operandType (left)), 0);
3528 geniCodeAssign (left,
3529 geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3531 geniCodeRValue (right, FALSE),
3533 operandType (left)), 0);
3535 return geniCodeRValue (right, FALSE);
3538 return geniCodeCall (ast2iCode (tree->left,lvl+1),
3541 geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3542 return ast2iCode (tree->right,lvl+1);
3545 geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3546 return ast2iCode (tree->right,lvl+1);
3549 geniCodeFunctionBody (tree,lvl);
3553 geniCodeReturn (right);
3557 geniCodeIfx (tree,lvl);
3561 geniCodeSwitch (tree,lvl);
3565 geniCodeInline (tree);
3569 geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
3576 /*-----------------------------------------------------------------*/
3577 /* reverseICChain - gets from the list and creates a linkedlist */
3578 /*-----------------------------------------------------------------*/
3585 while ((loop = getSet (&iCodeChain)))
3597 /*-----------------------------------------------------------------*/
3598 /* iCodeFromAst - given an ast will convert it to iCode */
3599 /*-----------------------------------------------------------------*/
3601 iCodeFromAst (ast * tree)
3603 returnLabel = newiTempLabel ("_return");
3604 entryLabel = newiTempLabel ("_entry");
3606 return reverseiCChain ();