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));
686 IC_ARGS (nic) = IC_ARGS (ic);
690 IC_INLINE (nic) = IC_INLINE (ic);
694 IC_ARRAYILIST(nic) = IC_ARRAYILIST(ic);
698 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
699 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
700 IC_RIGHT (nic) = operandFromOperand (IC_RIGHT (ic));
706 /*-----------------------------------------------------------------*/
707 /* getTableEntry - gets the table entry for the given operator */
708 /*-----------------------------------------------------------------*/
710 getTableEntry (int oper)
714 for (i = 0; i < (sizeof (codeTable) / sizeof (iCodeTable)); i++)
715 if (oper == codeTable[i].icode)
716 return &codeTable[i];
721 /*-----------------------------------------------------------------*/
722 /* newiTempOperand - new intermediate temp operand */
723 /*-----------------------------------------------------------------*/
725 newiTempOperand (sym_link * type, char throwType)
728 operand *op = newOperand ();
732 itmp = newiTemp (NULL);
734 etype = getSpec (type);
736 if (IS_LITERAL (etype))
739 /* copy the type information */
741 itmp->etype = getSpec (itmp->type = (throwType ? type :
742 copyLinkChain (type)));
743 if (IS_LITERAL (itmp->etype))
745 SPEC_SCLS (itmp->etype) = S_REGISTER;
746 SPEC_OCLS (itmp->etype) = reg;
749 op->operand.symOperand = itmp;
750 op->key = itmp->key = ++operandKey;
754 /*-----------------------------------------------------------------*/
755 /* operandType - returns the type chain for an operand */
756 /*-----------------------------------------------------------------*/
758 operandType (operand * op)
760 /* depending on type of operand */
765 return op->operand.valOperand->type;
768 return op->operand.symOperand->type;
771 return op->operand.typeOperand;
773 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
774 " operand type not known ");
775 assert (0); /* should never come here */
776 /* Just to keep the compiler happy */
777 return (sym_link *) 0;
781 /*-----------------------------------------------------------------*/
782 /* isParamterToCall - will return 1 if op is a parameter to args */
783 /*-----------------------------------------------------------------*/
785 isParameterToCall (value * args, operand * op)
792 isSymbolEqual (op->operand.symOperand, tval->sym))
799 /*-----------------------------------------------------------------*/
800 /* isOperandGlobal - return 1 if operand is a global variable */
801 /*-----------------------------------------------------------------*/
803 isOperandGlobal (operand * op)
811 if (op->type == SYMBOL &&
812 (op->operand.symOperand->level == 0 ||
813 IS_STATIC (op->operand.symOperand->etype) ||
814 IS_EXTERN (op->operand.symOperand->etype))
821 /*-----------------------------------------------------------------*/
822 /* isOperandVolatile - return 1 if the operand is volatile */
823 /*-----------------------------------------------------------------*/
825 isOperandVolatile (operand * op, bool chkTemp)
830 if (IS_ITEMP (op) && !chkTemp)
833 opetype = getSpec (optype = operandType (op));
835 if (IS_PTR (optype) && DCL_PTR_VOLATILE (optype))
838 if (IS_VOLATILE (opetype))
843 /*-----------------------------------------------------------------*/
844 /* isOperandLiteral - returns 1 if an operand contains a literal */
845 /*-----------------------------------------------------------------*/
847 isOperandLiteral (operand * op)
854 opetype = getSpec (operandType (op));
856 if (IS_LITERAL (opetype))
861 /*-----------------------------------------------------------------*/
862 /* isOperandInFarSpace - will return true if operand is in farSpace */
863 /*-----------------------------------------------------------------*/
865 isOperandInFarSpace (operand * op)
875 if (!IS_TRUE_SYMOP (op))
878 etype = SPIL_LOC (op)->etype;
884 etype = getSpec (operandType (op));
886 return (IN_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
889 /*-----------------------------------------------------------------*/
890 /* isOperandOnStack - will return true if operand is on stack */
891 /*-----------------------------------------------------------------*/
893 isOperandOnStack (operand * op)
903 etype = getSpec (operandType (op));
905 return ((IN_STACK (etype)) ? TRUE : FALSE);
908 /*-----------------------------------------------------------------*/
909 /* operandLitValue - literal value of an operand */
910 /*-----------------------------------------------------------------*/
912 operandLitValue (operand * op)
914 assert (isOperandLiteral (op));
916 return floatFromVal (op->operand.valOperand);
919 /*-----------------------------------------------------------------*/
920 /* operandOperation - perforoms operations on operands */
921 /*-----------------------------------------------------------------*/
923 operandOperation (operand * left, operand * right,
924 int op, sym_link * type)
926 sym_link *let , *ret=NULL;
927 operand *retval = (operand *) 0;
929 assert (isOperandLiteral (left));
930 let = getSpec(operandType(left));
932 assert (isOperandLiteral (right));
933 ret = getSpec(operandType(left));
939 retval = operandFromValue (valCastLiteral (type,
940 operandLitValue (left) +
941 operandLitValue (right)));
944 retval = operandFromValue (valCastLiteral (type,
945 operandLitValue (left) -
946 operandLitValue (right)));
949 retval = operandFromValue (valCastLiteral (type,
950 operandLitValue (left) *
951 operandLitValue (right)));
954 if ((unsigned long) operandLitValue (right) == 0)
956 werror (E_DIVIDE_BY_ZERO);
961 retval = operandFromValue (valCastLiteral (type,
962 operandLitValue (left) /
963 operandLitValue (right)));
966 if ((unsigned long) operandLitValue (right) == 0) {
967 werror (E_DIVIDE_BY_ZERO);
971 retval = operandFromLit ((SPEC_USIGN(let) ?
972 (unsigned long) operandLitValue (left) :
973 (long) operandLitValue (left)) %
975 (unsigned long) operandLitValue (right) :
976 (long) operandLitValue (right)));
980 retval = operandFromLit ((SPEC_USIGN(let) ?
981 (unsigned long) operandLitValue (left) :
982 (long) operandLitValue (left)) <<
984 (unsigned long) operandLitValue (right) :
985 (long) operandLitValue (right)));
988 retval = operandFromLit ((SPEC_USIGN(let) ?
989 (unsigned long) operandLitValue (left) :
990 (long) operandLitValue (left)) >>
992 (unsigned long) operandLitValue (right) :
993 (long) operandLitValue (right)));
996 retval = operandFromLit (operandLitValue (left) ==
997 operandLitValue (right));
1000 retval = operandFromLit (operandLitValue (left) <
1001 operandLitValue (right));
1004 retval = operandFromLit (operandLitValue (left) <=
1005 operandLitValue (right));
1008 retval = operandFromLit (operandLitValue (left) !=
1009 operandLitValue (right));
1012 retval = operandFromLit (operandLitValue (left) >
1013 operandLitValue (right));
1016 retval = operandFromLit (operandLitValue (left) >=
1017 operandLitValue (right));
1020 retval = operandFromLit ((long)operandLitValue(left) &
1021 (long)operandLitValue(right));
1024 retval = operandFromLit ((long)operandLitValue (left) |
1025 (long)operandLitValue (right));
1028 retval = operandFromLit ((long)operandLitValue (left) ^
1029 (long)operandLitValue (right));
1032 retval = operandFromLit (operandLitValue (left) &&
1033 operandLitValue (right));
1036 retval = operandFromLit (operandLitValue (left) ||
1037 operandLitValue (right));
1041 long i = (long) operandLitValue (left);
1043 retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
1049 long i = (long) operandLitValue (left);
1051 retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
1057 retval = operandFromLit (-1 * operandLitValue (left));
1061 retval = operandFromLit (~((long) operandLitValue (left)));
1065 retval = operandFromLit (!operandLitValue (left));
1069 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1070 " operandOperation invalid operator ");
1078 /*-----------------------------------------------------------------*/
1079 /* isOperandEqual - compares two operand & return 1 if they r = */
1080 /*-----------------------------------------------------------------*/
1082 isOperandEqual (operand * left, operand * right)
1084 /* if the pointers are equal then they are equal */
1088 /* if either of them null then false */
1089 if (!left || !right)
1092 if (left->type != right->type)
1095 if (IS_SYMOP (left) && IS_SYMOP (right))
1096 return left->key == right->key;
1098 /* if types are the same */
1102 return isSymbolEqual (left->operand.symOperand,
1103 right->operand.symOperand);
1105 return (floatFromVal (left->operand.valOperand) ==
1106 floatFromVal (right->operand.valOperand));
1108 if (compareType (left->operand.typeOperand,
1109 right->operand.typeOperand) == 1)
1116 /*-------------------------------------------------------------------*/
1117 /* isiCodeEqual - compares two iCodes are equal, returns true if yes */
1118 /*-------------------------------------------------------------------*/
1120 isiCodeEqual (iCode * left, iCode * right)
1122 /* if the same pointer */
1126 /* if either of them null */
1127 if (!left || !right)
1130 /* if operand are the same */
1131 if (left->op == right->op)
1134 /* compare all the elements depending on type */
1135 if (left->op != IFX)
1137 if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
1139 if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
1145 if (!isOperandEqual (IC_COND (left), IC_COND (right)))
1147 if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
1149 if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
1158 /*-----------------------------------------------------------------*/
1159 /* newiTempFromOp - create a temp Operand with same attributes */
1160 /*-----------------------------------------------------------------*/
1162 newiTempFromOp (operand * op)
1172 nop = newiTempOperand (operandType (op), TRUE);
1173 nop->isaddr = op->isaddr;
1174 nop->isvolatile = op->isvolatile;
1175 nop->isGlobal = op->isGlobal;
1176 nop->isLiteral = op->isLiteral;
1177 nop->usesDefs = op->usesDefs;
1178 nop->isParm = op->isParm;
1182 /*-----------------------------------------------------------------*/
1183 /* operand from operand - creates an operand holder for the type */
1184 /*-----------------------------------------------------------------*/
1186 operandFromOperand (operand * op)
1192 nop = newOperand ();
1193 nop->type = op->type;
1194 nop->isaddr = op->isaddr;
1196 nop->isvolatile = op->isvolatile;
1197 nop->isGlobal = op->isGlobal;
1198 nop->isLiteral = op->isLiteral;
1199 nop->usesDefs = op->usesDefs;
1200 nop->isParm = op->isParm;
1205 nop->operand.symOperand = op->operand.symOperand;
1208 nop->operand.valOperand = op->operand.valOperand;
1211 nop->operand.typeOperand = op->operand.typeOperand;
1218 /*-----------------------------------------------------------------*/
1219 /* opFromOpWithDU - makes a copy of the operand and DU chains */
1220 /*-----------------------------------------------------------------*/
1222 opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
1224 operand *nop = operandFromOperand (op);
1226 if (nop->type == SYMBOL)
1228 OP_SYMBOL (nop)->defs = bitVectCopy (defs);
1229 OP_SYMBOL (nop)->uses = bitVectCopy (uses);
1235 /*-----------------------------------------------------------------*/
1236 /* operandFromSymbol - creates an operand from a symbol */
1237 /*-----------------------------------------------------------------*/
1239 operandFromSymbol (symbol * sym)
1244 /* if the symbol's type is a literal */
1245 /* then it is an enumerator type */
1246 if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
1247 return operandFromValue (valFromType (sym->etype));
1250 sym->key = ++operandKey;
1252 /* if this an implicit variable, means struct/union */
1253 /* member so just return it */
1254 if (sym->implicit || IS_FUNC (sym->type))
1258 op->operand.symOperand = sym;
1260 op->isvolatile = isOperandVolatile (op, TRUE);
1261 op->isGlobal = isOperandGlobal (op);
1265 /* under the following conditions create a
1266 register equivalent for a local symbol */
1267 if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
1268 (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
1269 (!(options.model == MODEL_FLAT24)) ) &&
1270 options.stackAuto == 0)
1273 if (!IS_AGGREGATE (sym->type) && /* not an aggregate */
1274 !IS_FUNC (sym->type) && /* not a function */
1275 !sym->_isparm && /* not a parameter */
1276 sym->level && /* is a local variable */
1277 !sym->addrtaken && /* whose address has not been taken */
1278 !sym->reqv && /* does not already have a reg equivalence */
1279 !IS_VOLATILE (sym->etype) && /* not declared as volatile */
1280 !IS_STATIC (sym->etype) && /* and not declared static */
1281 !sym->islbl && /* not a label */
1282 ok && /* farspace check */
1283 !IS_BITVAR (sym->etype) /* not a bit variable */
1287 /* we will use it after all optimizations
1288 and before liveRange calculation */
1289 sym->reqv = newiTempOperand (sym->type, 0);
1290 sym->reqv->key = sym->key;
1291 OP_SYMBOL (sym->reqv)->key = sym->key;
1292 OP_SYMBOL (sym->reqv)->isreqv = 1;
1293 OP_SYMBOL (sym->reqv)->islocal = 1;
1294 OP_SYMBOL (sym->reqv)->onStack = sym->onStack;
1295 SPIL_LOC (sym->reqv) = sym;
1298 if (!IS_AGGREGATE (sym->type))
1302 op->operand.symOperand = sym;
1305 op->isvolatile = isOperandVolatile (op, TRUE);
1306 op->isGlobal = isOperandGlobal (op);
1307 op->isPtr = IS_PTR (operandType (op));
1308 op->isParm = sym->_isparm;
1313 /* itemp = &[_symbol] */
1315 ic = newiCode (ADDRESS_OF, newOperand (), NULL);
1316 IC_LEFT (ic)->type = SYMBOL;
1317 IC_LEFT (ic)->operand.symOperand = sym;
1318 IC_LEFT (ic)->key = sym->key;
1319 (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
1320 (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
1321 IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
1324 IC_RESULT (ic) = newiTempOperand (sym->type, 0);
1325 if (IS_ARRAY (sym->type))
1327 IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
1328 IC_RESULT (ic)->isaddr = 0;
1331 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
1335 return IC_RESULT (ic);
1338 /*-----------------------------------------------------------------*/
1339 /* operandFromValue - creates an operand from value */
1340 /*-----------------------------------------------------------------*/
1342 operandFromValue (value * val)
1346 /* if this is a symbol then do the symbol thing */
1348 return operandFromSymbol (val->sym);
1350 /* this is not a symbol */
1353 op->operand.valOperand = val;
1354 op->isLiteral = isOperandLiteral (op);
1358 /*-----------------------------------------------------------------*/
1359 /* operandFromLink - operand from typeChain */
1360 /*-----------------------------------------------------------------*/
1362 operandFromLink (sym_link * type)
1366 /* operand from sym_link */
1372 op->operand.typeOperand = copyLinkChain (type);
1376 /*-----------------------------------------------------------------*/
1377 /* operandFromLit - makes an operand from a literal value */
1378 /*-----------------------------------------------------------------*/
1380 operandFromLit (double i)
1382 return operandFromValue (valueFromLit (i));
1385 /*-----------------------------------------------------------------*/
1386 /* operandFromAst - creates an operand from an ast */
1387 /*-----------------------------------------------------------------*/
1389 operandFromAst (ast * tree,int lvl)
1395 /* depending on type do */
1399 return ast2iCode (tree,lvl+1);
1403 return operandFromValue (tree->opval.val);
1407 return operandFromLink (tree->opval.lnk);
1411 /* Just to keep the comiler happy */
1412 return (operand *) 0;
1415 /*-----------------------------------------------------------------*/
1416 /* setOperandType - sets the operand's type to the given type */
1417 /*-----------------------------------------------------------------*/
1419 setOperandType (operand * op, sym_link * type)
1421 /* depending on the type of operand */
1426 op->operand.valOperand->etype =
1427 getSpec (op->operand.valOperand->type =
1428 copyLinkChain (type));
1432 if (op->operand.symOperand->isitmp)
1433 op->operand.symOperand->etype =
1434 getSpec (op->operand.symOperand->type =
1435 copyLinkChain (type));
1437 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1438 "attempt to modify type of source");
1442 op->operand.typeOperand = copyLinkChain (type);
1447 /*-----------------------------------------------------------------*/
1448 /* Get size in byte of ptr need to access an array */
1449 /*-----------------------------------------------------------------*/
1451 getArraySizePtr (operand * op)
1453 sym_link *ltype = operandType(op);
1457 int size = getSize(ltype);
1458 return(IS_GENPTR(ltype)?(size-1):size);
1463 sym_link *letype = getSpec(ltype);
1464 switch (PTR_TYPE (SPEC_OCLS (letype)))
1476 return (GPTRSIZE-1);
1485 /*-----------------------------------------------------------------*/
1486 /* perform "usual unary conversions" */
1487 /*-----------------------------------------------------------------*/
1489 usualUnaryConversions (operand * op)
1491 if (IS_INTEGRAL (operandType (op)))
1493 if (getSize (operandType (op)) < (unsigned int) INTSIZE)
1496 return geniCodeCast (INTTYPE, op, TRUE);
1502 /*-----------------------------------------------------------------*/
1503 /* perform "usual binary conversions" */
1504 /*-----------------------------------------------------------------*/
1506 usualBinaryConversions (operand ** op1, operand ** op2)
1509 sym_link *rtype = operandType (*op2);
1510 sym_link *ltype = operandType (*op1);
1512 ctype = computeType (ltype, rtype);
1513 *op1 = geniCodeCast (ctype, *op1, TRUE);
1514 *op2 = geniCodeCast (ctype, *op2, TRUE);
1519 /*-----------------------------------------------------------------*/
1520 /* geniCodeValueAtAddress - generate intermeditate code for value */
1522 /*-----------------------------------------------------------------*/
1524 geniCodeRValue (operand * op, bool force)
1527 sym_link *type = operandType (op);
1528 sym_link *etype = getSpec (type);
1530 /* if this is an array & already */
1531 /* an address then return this */
1532 if (IS_AGGREGATE (type) ||
1533 (IS_PTR (type) && !force && !op->isaddr))
1534 return operandFromOperand (op);
1536 /* if this is not an address then must be */
1537 /* rvalue already so return this one */
1541 /* if this is not a temp symbol then */
1542 if (!IS_ITEMP (op) &&
1544 !IN_FARSPACE (SPEC_OCLS (etype)))
1546 op = operandFromOperand (op);
1551 if (IS_SPEC (type) &&
1552 IS_TRUE_SYMOP (op) &&
1553 (!IN_FARSPACE (SPEC_OCLS (etype)) ||
1554 /* TARGET_IS_DS390)) */
1555 (options.model == MODEL_FLAT24) ))
1557 op = operandFromOperand (op);
1562 ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1563 if (IS_PTR (type) && op->isaddr && force)
1566 type = copyLinkChain (type);
1568 IC_RESULT (ic) = newiTempOperand (type, 1);
1569 IC_RESULT (ic)->isaddr = 0;
1571 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1575 return IC_RESULT (ic);
1578 /*-----------------------------------------------------------------*/
1579 /* geniCodeCast - changes the value from one type to another */
1580 /*-----------------------------------------------------------------*/
1582 geniCodeCast (sym_link * type, operand * op, bool implicit)
1586 sym_link *opetype = getSpec (optype = operandType (op));
1590 /* one of them has size zero then error */
1591 if (IS_VOID (optype))
1593 werror (E_CAST_ZERO);
1597 /* if the operand is already the desired type then do nothing */
1598 if (compareType (type, optype) == 1)
1601 /* if this is a literal then just change the type & return */
1602 if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1603 return operandFromValue (valCastLiteral (type,
1604 operandLitValue (op)));
1606 /* if casting to/from pointers, do some checking */
1607 if (IS_PTR(type)) { // to a pointer
1608 if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer
1609 if (IS_INTEGRAL(optype)) {
1610 // maybe this is NULL, than it's ok.
1611 if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
1612 if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80 && IS_GENPTR(type)) {
1613 // no way to set the storage
1614 if (IS_LITERAL(optype)) {
1615 werror(E_LITERAL_GENERIC);
1618 werror(E_NONPTR2_GENPTR);
1621 } else if (implicit) {
1622 werror(W_INTEGRAL2PTR_NOCAST);
1627 // shouldn't do that with float, array or structure unless to void
1628 if (!IS_VOID(getSpec(type)) &&
1629 !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1630 werror(E_INCOMPAT_TYPES);
1634 } else { // from a pointer to a pointer
1635 if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80) {
1636 // if not a pointer to a function
1637 if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1638 if (implicit) { // if not to generic, they have to match
1639 if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
1640 werror(E_INCOMPAT_PTYPES);
1647 } else { // to a non pointer
1648 if (IS_PTR(optype)) { // from a pointer
1649 if (implicit) { // sneaky
1650 if (IS_INTEGRAL(type)) {
1651 werror(W_PTR2INTEGRAL_NOCAST);
1653 } else { // shouldn't do that with float, array or structure
1654 werror(E_INCOMPAT_TYPES);
1661 printFromToType (optype, type);
1664 /* if they are the same size create an assignment */
1665 if (getSize (type) == getSize (optype) &&
1666 !IS_BITFIELD (type) &&
1668 !IS_FLOAT (optype) &&
1669 ((IS_SPEC (type) && IS_SPEC (optype)) ||
1670 (!IS_SPEC (type) && !IS_SPEC (optype))))
1673 ic = newiCode ('=', NULL, op);
1674 IC_RESULT (ic) = newiTempOperand (type, 0);
1675 SPIL_LOC (IC_RESULT (ic)) =
1676 (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
1677 IC_RESULT (ic)->isaddr = 0;
1681 ic = newiCode (CAST, operandFromLink (type),
1682 geniCodeRValue (op, FALSE));
1684 IC_RESULT (ic) = newiTempOperand (type, 0);
1687 /* preserve the storage class & output class */
1688 /* of the original variable */
1689 restype = getSpec (operandType (IC_RESULT (ic)));
1690 SPEC_SCLS (restype) = SPEC_SCLS (opetype);
1691 SPEC_OCLS (restype) = SPEC_OCLS (opetype);
1694 return IC_RESULT (ic);
1697 /*-----------------------------------------------------------------*/
1698 /* geniCodeLabel - will create a Label */
1699 /*-----------------------------------------------------------------*/
1701 geniCodeLabel (symbol * label)
1705 ic = newiCodeLabelGoto (LABEL, label);
1709 /*-----------------------------------------------------------------*/
1710 /* geniCodeGoto - will create a Goto */
1711 /*-----------------------------------------------------------------*/
1713 geniCodeGoto (symbol * label)
1717 ic = newiCodeLabelGoto (GOTO, label);
1721 /*-----------------------------------------------------------------*/
1722 /* geniCodeMultiply - gen intermediate code for multiplication */
1723 /*-----------------------------------------------------------------*/
1725 geniCodeMultiply (operand * left, operand * right,int resultIsInt)
1732 /* if they are both literal then we know the result */
1733 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1734 return operandFromValue (valMult (left->operand.valOperand,
1735 right->operand.valOperand));
1737 if (IS_LITERAL(retype)) {
1738 p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
1741 resType = usualBinaryConversions (&left, &right);
1743 rtype = operandType (right);
1744 retype = getSpec (rtype);
1745 ltype = operandType (left);
1746 letype = getSpec (ltype);
1750 SPEC_NOUN(getSpec(resType))=V_INT;
1753 /* if the right is a literal & power of 2 */
1754 /* then make it a left shift */
1755 /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
1756 efficient in most cases than 2 bytes result = 2 bytes << literal
1757 if port has 1 byte muldiv */
1758 if (p2 && !IS_FLOAT (letype) &&
1759 !((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
1760 (port->support.muldiv == 1)))
1762 if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
1764 /* LEFT_OP need same size for left and result, */
1765 left = geniCodeCast (resType, left, TRUE);
1766 ltype = operandType (left);
1768 ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
1772 ic = newiCode ('*', left, right); /* normal multiplication */
1773 /* if the size left or right > 1 then support routine */
1774 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1778 IC_RESULT (ic) = newiTempOperand (resType, 1);
1781 return IC_RESULT (ic);
1784 /*-----------------------------------------------------------------*/
1785 /* geniCodeDivision - gen intermediate code for division */
1786 /*-----------------------------------------------------------------*/
1788 geniCodeDivision (operand * left, operand * right)
1793 sym_link *rtype = operandType (right);
1794 sym_link *retype = getSpec (rtype);
1795 sym_link *ltype = operandType (left);
1796 sym_link *letype = getSpec (ltype);
1798 resType = usualBinaryConversions (&left, &right);
1800 /* if the right is a literal & power of 2 */
1801 /* then make it a right shift */
1802 if (IS_LITERAL (retype) &&
1803 !IS_FLOAT (letype) &&
1804 (p2 = powof2 ((unsigned long)
1805 floatFromVal (right->operand.valOperand)))) {
1806 ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
1810 ic = newiCode ('/', left, right); /* normal division */
1811 /* if the size left or right > 1 then support routine */
1812 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1815 IC_RESULT (ic) = newiTempOperand (resType, 0);
1818 return IC_RESULT (ic);
1820 /*-----------------------------------------------------------------*/
1821 /* geniCodeModulus - gen intermediate code for modulus */
1822 /*-----------------------------------------------------------------*/
1824 geniCodeModulus (operand * left, operand * right)
1830 /* if they are both literal then we know the result */
1831 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1832 return operandFromValue (valMod (left->operand.valOperand,
1833 right->operand.valOperand));
1835 resType = usualBinaryConversions (&left, &right);
1837 /* now they are the same size */
1838 ic = newiCode ('%', left, right);
1840 /* if the size left or right > 1 then support routine */
1841 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1843 IC_RESULT (ic) = newiTempOperand (resType, 0);
1846 return IC_RESULT (ic);
1849 /*-----------------------------------------------------------------*/
1850 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
1851 /*-----------------------------------------------------------------*/
1853 geniCodePtrPtrSubtract (operand * left, operand * right)
1859 /* if they are both literals then */
1860 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1862 result = operandFromValue (valMinus (left->operand.valOperand,
1863 right->operand.valOperand));
1867 ic = newiCode ('-', left, right);
1869 IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
1873 return geniCodeDivision (result,
1874 operandFromLit (getSize (ltype->next)));
1877 /*-----------------------------------------------------------------*/
1878 /* geniCodeSubtract - generates code for subtraction */
1879 /*-----------------------------------------------------------------*/
1881 geniCodeSubtract (operand * left, operand * right)
1888 /* if they both pointers then */
1889 if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
1890 (IS_PTR (rtype) || IS_ARRAY (rtype)))
1891 return geniCodePtrPtrSubtract (left, right);
1893 /* if they are both literal then we know the result */
1894 if (IS_LITERAL (letype) && IS_LITERAL (retype)
1895 && left->isLiteral && right->isLiteral)
1896 return operandFromValue (valMinus (left->operand.valOperand,
1897 right->operand.valOperand));
1899 /* if left is an array or pointer */
1900 if (IS_PTR (ltype) || IS_ARRAY (ltype))
1902 isarray = left->isaddr;
1903 right = geniCodeMultiply (right,
1904 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
1905 resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
1908 { /* make them the same size */
1909 resType = usualBinaryConversions (&left, &right);
1912 ic = newiCode ('-', left, right);
1914 IC_RESULT (ic) = newiTempOperand (resType, 1);
1915 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
1917 /* if left or right is a float */
1918 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
1922 return IC_RESULT (ic);
1925 /*-----------------------------------------------------------------*/
1926 /* geniCodeAdd - generates iCode for addition */
1927 /*-----------------------------------------------------------------*/
1929 geniCodeAdd (operand * left, operand * right,int lvl)
1937 /* if left is an array then array access */
1938 if (IS_ARRAY (ltype))
1939 return geniCodeArray (left, right,lvl);
1941 /* if the right side is LITERAL zero */
1942 /* return the left side */
1943 if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
1946 /* if left is literal zero return right */
1947 if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
1950 /* if left is an array or pointer then size */
1953 isarray = left->isaddr;
1954 // there is no need to multiply with 1
1955 if (getSize(ltype->next)!=1) {
1956 size = operandFromLit (getSize (ltype->next));
1957 right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
1959 resType = copyLinkChain (ltype);
1962 { /* make them the same size */
1963 resType = usualBinaryConversions (&left, &right);
1966 /* if they are both literals then we know */
1967 if (IS_LITERAL (letype) && IS_LITERAL (retype)
1968 && left->isLiteral && right->isLiteral)
1969 return operandFromValue (valPlus (valFromType (letype),
1970 valFromType (retype)));
1972 ic = newiCode ('+', left, right);
1974 IC_RESULT (ic) = newiTempOperand (resType, 1);
1975 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
1977 /* if left or right is a float then support
1979 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
1984 return IC_RESULT (ic);
1988 /*-----------------------------------------------------------------*/
1989 /* aggrToPtr - changes an aggregate to pointer to an aggregate */
1990 /*-----------------------------------------------------------------*/
1992 aggrToPtr (sym_link * type, bool force)
1998 if (IS_PTR (type) && !force)
2001 etype = getSpec (type);
2005 /* if the output class is generic */
2006 if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER)
2007 DCL_PTR_CONST (ptype) = port->mem.code_ro;
2009 /* if the variable was declared a constant */
2010 /* then the pointer points to a constant */
2011 if (IS_CONSTANT (etype))
2012 DCL_PTR_CONST (ptype) = 1;
2014 /* the variable was volatile then pointer to volatile */
2015 if (IS_VOLATILE (etype))
2016 DCL_PTR_VOLATILE (ptype) = 1;
2020 /*-----------------------------------------------------------------*/
2021 /* geniCodeArray2Ptr - array to pointer */
2022 /*-----------------------------------------------------------------*/
2024 geniCodeArray2Ptr (operand * op)
2026 sym_link *optype = operandType (op);
2027 sym_link *opetype = getSpec (optype);
2029 /* set the pointer depending on the storage class */
2030 if ((DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2031 DCL_PTR_CONST (optype) = port->mem.code_ro;
2034 /* if the variable was declared a constant */
2035 /* then the pointer points to a constant */
2036 if (IS_CONSTANT (opetype))
2037 DCL_PTR_CONST (optype) = 1;
2039 /* the variable was volatile then pointer to volatile */
2040 if (IS_VOLATILE (opetype))
2041 DCL_PTR_VOLATILE (optype) = 1;
2047 /*-----------------------------------------------------------------*/
2048 /* geniCodeArray - array access */
2049 /*-----------------------------------------------------------------*/
2051 geniCodeArray (operand * left, operand * right,int lvl)
2054 sym_link *ltype = operandType (left);
2058 if (IS_PTR (ltype->next) && left->isaddr)
2060 left = geniCodeRValue (left, FALSE);
2062 return geniCodeDerefPtr (geniCodeAdd (left, right,lvl),lvl);
2065 right = geniCodeMultiply (right,
2066 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2068 /* we can check for limits here */
2069 if (isOperandLiteral (right) &&
2072 (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2074 werror (E_ARRAY_BOUND);
2075 right = operandFromLit (0);
2078 ic = newiCode ('+', left, right);
2080 IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2081 !IS_AGGREGATE (ltype->next) &&
2082 !IS_PTR (ltype->next))
2083 ? ltype : ltype->next), 0);
2085 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
2087 return IC_RESULT (ic);
2090 /*-----------------------------------------------------------------*/
2091 /* geniCodeStruct - generates intermediate code for structres */
2092 /*-----------------------------------------------------------------*/
2094 geniCodeStruct (operand * left, operand * right, bool islval)
2097 sym_link *type = operandType (left);
2098 sym_link *etype = getSpec (type);
2100 symbol *element = getStructElement (SPEC_STRUCT (etype),
2101 right->operand.symOperand);
2103 /* add the offset */
2104 ic = newiCode ('+', left, operandFromLit (element->offset));
2106 IC_RESULT (ic) = newiTempOperand (element->type, 0);
2108 /* preserve the storage & output class of the struct */
2109 /* as well as the volatile attribute */
2110 retype = getSpec (operandType (IC_RESULT (ic)));
2111 SPEC_SCLS (retype) = SPEC_SCLS (etype);
2112 SPEC_OCLS (retype) = SPEC_OCLS (etype);
2113 SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2116 if (IS_PTR (element->type))
2117 setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2120 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2124 return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2127 /*-----------------------------------------------------------------*/
2128 /* geniCodePostInc - generate int code for Post increment */
2129 /*-----------------------------------------------------------------*/
2131 geniCodePostInc (operand * op)
2135 sym_link *optype = operandType (op);
2137 operand *rv = (IS_ITEMP (op) ?
2138 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2140 sym_link *rvtype = operandType (rv);
2143 /* if this is not an address we have trouble */
2146 werror (E_LVALUE_REQUIRED, "++");
2150 rOp = newiTempOperand (rvtype, 0);
2151 OP_SYMBOL(rOp)->noSpilLoc = 1;
2154 OP_SYMBOL(rv)->noSpilLoc = 1;
2156 geniCodeAssign (rOp, rv, 0);
2158 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2159 if (IS_FLOAT (rvtype))
2160 ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2162 ic = newiCode ('+', rv, operandFromLit (size));
2164 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2167 geniCodeAssign (op, result, 0);
2173 /*-----------------------------------------------------------------*/
2174 /* geniCodePreInc - generate code for preIncrement */
2175 /*-----------------------------------------------------------------*/
2177 geniCodePreInc (operand * op)
2180 sym_link *optype = operandType (op);
2181 operand *rop = (IS_ITEMP (op) ?
2182 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2184 sym_link *roptype = operandType (rop);
2190 werror (E_LVALUE_REQUIRED, "++");
2195 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2196 if (IS_FLOAT (roptype))
2197 ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2199 ic = newiCode ('+', rop, operandFromLit (size));
2200 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2204 return geniCodeAssign (op, result, 0);
2207 /*-----------------------------------------------------------------*/
2208 /* geniCodePostDec - generates code for Post decrement */
2209 /*-----------------------------------------------------------------*/
2211 geniCodePostDec (operand * op)
2215 sym_link *optype = operandType (op);
2217 operand *rv = (IS_ITEMP (op) ?
2218 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2220 sym_link *rvtype = operandType (rv);
2223 /* if this is not an address we have trouble */
2226 werror (E_LVALUE_REQUIRED, "--");
2230 rOp = newiTempOperand (rvtype, 0);
2231 OP_SYMBOL(rOp)->noSpilLoc = 1;
2234 OP_SYMBOL(rv)->noSpilLoc = 1;
2236 geniCodeAssign (rOp, rv, 0);
2238 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2239 if (IS_FLOAT (rvtype))
2240 ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2242 ic = newiCode ('-', rv, operandFromLit (size));
2244 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2247 geniCodeAssign (op, result, 0);
2253 /*-----------------------------------------------------------------*/
2254 /* geniCodePreDec - generate code for pre decrement */
2255 /*-----------------------------------------------------------------*/
2257 geniCodePreDec (operand * op)
2260 sym_link *optype = operandType (op);
2261 operand *rop = (IS_ITEMP (op) ?
2262 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2264 sym_link *roptype = operandType (rop);
2270 werror (E_LVALUE_REQUIRED, "--");
2275 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2276 if (IS_FLOAT (roptype))
2277 ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2279 ic = newiCode ('-', rop, operandFromLit (size));
2280 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2284 return geniCodeAssign (op, result, 0);
2288 /*-----------------------------------------------------------------*/
2289 /* geniCodeBitwise - gen int code for bitWise operators */
2290 /*-----------------------------------------------------------------*/
2292 geniCodeBitwise (operand * left, operand * right,
2293 int oper, sym_link * resType)
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 ((parms->argSym && IS_REGPARM(parms->argSym->etype)) ||
2738 (IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(func->type)))
2740 ic = newiCode (SEND, pval, NULL);
2745 /* now decide whether to push or assign */
2746 if (!(options.stackAuto || IFFUNC_ISREENT (func->type)))
2750 operand *top = operandFromSymbol (argVals->sym);
2751 geniCodeAssign (top, pval, 1);
2755 sym_link *p = operandType (pval);
2757 ic = newiCode (IPUSH, pval, NULL);
2759 /* update the stack adjustment */
2760 *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2765 argVals=argVals->next;
2769 /*-----------------------------------------------------------------*/
2770 /* geniCodeCall - generates temp code for calling */
2771 /*-----------------------------------------------------------------*/
2773 geniCodeCall (operand * left, ast * parms,int lvl)
2777 sym_link *type, *etype;
2780 if (!IS_FUNC(OP_SYMBOL(left)->type) &&
2781 !IS_CODEPTR(OP_SYMBOL(left)->type)) {
2782 werror (E_FUNCTION_EXPECTED);
2786 /* take care of parameters with side-effecting
2787 function calls in them, this is required to take care
2788 of overlaying function parameters */
2789 geniCodeSEParms (parms,lvl);
2791 /* first the parameters */
2792 geniCodeParms (parms, NULL, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
2794 /* now call : if symbol then pcall */
2795 if (IS_OP_POINTER (left) || IS_ITEMP(left))
2796 ic = newiCode (PCALL, left, NULL);
2798 ic = newiCode (CALL, left, NULL);
2800 IC_ARGS (ic) = FUNC_ARGS(left->operand.symOperand->type);
2801 type = copyLinkChain (operandType (left)->next);
2802 etype = getSpec (type);
2803 SPEC_EXTR (etype) = 0;
2804 IC_RESULT (ic) = result = newiTempOperand (type, 1);
2808 /* stack adjustment after call */
2809 ic->parmBytes = stack;
2814 /*-----------------------------------------------------------------*/
2815 /* geniCodeReceive - generate intermediate code for "receive" */
2816 /*-----------------------------------------------------------------*/
2818 geniCodeReceive (value * args)
2820 /* for all arguments that are passed in registers */
2824 if (IS_REGPARM (args->etype))
2826 operand *opr = operandFromValue (args);
2828 symbol *sym = OP_SYMBOL (opr);
2831 /* we will use it after all optimizations
2832 and before liveRange calculation */
2833 if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
2836 if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
2837 options.stackAuto == 0 &&
2838 /* !TARGET_IS_DS390) */
2839 (!(options.model == MODEL_FLAT24)) )
2844 opl = newiTempOperand (args->type, 0);
2846 sym->reqv->key = sym->key;
2847 OP_SYMBOL (sym->reqv)->key = sym->key;
2848 OP_SYMBOL (sym->reqv)->isreqv = 1;
2849 OP_SYMBOL (sym->reqv)->islocal = 0;
2850 SPIL_LOC (sym->reqv) = sym;
2854 ic = newiCode (RECEIVE, NULL, NULL);
2855 currFunc->recvSize = getSize (sym->etype);
2856 IC_RESULT (ic) = opr;
2864 /*-----------------------------------------------------------------*/
2865 /* geniCodeFunctionBody - create the function body */
2866 /*-----------------------------------------------------------------*/
2868 geniCodeFunctionBody (ast * tree,int lvl)
2875 /* reset the auto generation */
2881 func = ast2iCode (tree->left,lvl+1);
2882 fetype = getSpec (operandType (func));
2884 savelineno = lineno;
2885 lineno = OP_SYMBOL (func)->lineDef;
2886 /* create an entry label */
2887 geniCodeLabel (entryLabel);
2888 lineno = savelineno;
2890 /* create a proc icode */
2891 ic = newiCode (FUNCTION, func, NULL);
2892 /* if the function has parmas then */
2893 /* save the parameters information */
2894 ic->argLabel.args = tree->values.args;
2895 ic->lineno = OP_SYMBOL (func)->lineDef;
2899 /* for all parameters that are passed
2900 on registers add a "receive" */
2901 geniCodeReceive (tree->values.args);
2903 /* generate code for the body */
2904 ast2iCode (tree->right,lvl+1);
2906 /* create a label for return */
2907 geniCodeLabel (returnLabel);
2909 /* now generate the end proc */
2910 ic = newiCode (ENDFUNCTION, func, NULL);
2915 /*-----------------------------------------------------------------*/
2916 /* geniCodeReturn - gen icode for 'return' statement */
2917 /*-----------------------------------------------------------------*/
2919 geniCodeReturn (operand * op)
2923 /* if the operand is present force an rvalue */
2925 op = geniCodeRValue (op, FALSE);
2927 ic = newiCode (RETURN, op, NULL);
2931 /*-----------------------------------------------------------------*/
2932 /* geniCodeIfx - generates code for extended if statement */
2933 /*-----------------------------------------------------------------*/
2935 geniCodeIfx (ast * tree,int lvl)
2938 operand *condition = ast2iCode (tree->left,lvl+1);
2941 /* if condition is null then exit */
2945 condition = geniCodeRValue (condition, FALSE);
2947 cetype = getSpec (operandType (condition));
2948 /* if the condition is a literal */
2949 if (IS_LITERAL (cetype))
2951 if (floatFromVal (condition->operand.valOperand))
2953 if (tree->trueLabel)
2954 geniCodeGoto (tree->trueLabel);
2960 if (tree->falseLabel)
2961 geniCodeGoto (tree->falseLabel);
2968 if (tree->trueLabel)
2970 ic = newiCodeCondition (condition,
2975 if (tree->falseLabel)
2976 geniCodeGoto (tree->falseLabel);
2980 ic = newiCodeCondition (condition,
2987 ast2iCode (tree->right,lvl+1);
2990 /*-----------------------------------------------------------------*/
2991 /* geniCodeJumpTable - tries to create a jump table for switch */
2992 /*-----------------------------------------------------------------*/
2994 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
2996 int min = 0, max = 0, t, cnt = 0;
3003 if (!tree || !caseVals)
3006 /* the criteria for creating a jump table is */
3007 /* all integer numbers between the maximum & minimum must */
3008 /* be present , the maximum value should not exceed 255 */
3009 min = max = (int) floatFromVal (vch = caseVals);
3010 sprintf (buffer, "_case_%d_%d",
3011 tree->values.switchVals.swNum,
3013 addSet (&labels, newiTempLabel (buffer));
3015 /* if there is only one case value then no need */
3016 if (!(vch = vch->next))
3021 if (((t = (int) floatFromVal (vch)) - max) != 1)
3023 sprintf (buffer, "_case_%d_%d",
3024 tree->values.switchVals.swNum,
3026 addSet (&labels, newiTempLabel (buffer));
3032 /* if the number of case statements <= 2 then */
3033 /* it is not economical to create the jump table */
3034 /* since two compares are needed for boundary conditions */
3035 if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
3038 if (tree->values.switchVals.swDefault)
3039 sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3041 sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3043 falseLabel = newiTempLabel (buffer);
3045 /* so we can create a jumptable */
3046 /* first we rule out the boundary conditions */
3047 /* if only optimization says so */
3048 if (!optimize.noJTabBoundary)
3050 sym_link *cetype = getSpec (operandType (cond));
3051 /* no need to check the lower bound if
3052 the condition is unsigned & minimum value is zero */
3053 if (!(min == 0 && SPEC_USIGN (cetype)))
3055 boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3056 ic = newiCodeCondition (boundary, falseLabel, NULL);
3060 /* now for upper bounds */
3061 boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3062 ic = newiCodeCondition (boundary, falseLabel, NULL);
3066 /* if the min is not zero then we no make it zero */
3069 cond = geniCodeSubtract (cond, operandFromLit (min));
3070 setOperandType (cond, UCHARTYPE);
3073 /* now create the jumptable */
3074 ic = newiCode (JUMPTABLE, NULL, NULL);
3075 IC_JTCOND (ic) = cond;
3076 IC_JTLABELS (ic) = labels;
3081 /*-----------------------------------------------------------------*/
3082 /* geniCodeSwitch - changes a switch to a if statement */
3083 /*-----------------------------------------------------------------*/
3085 geniCodeSwitch (ast * tree,int lvl)
3088 operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3089 value *caseVals = tree->values.switchVals.swVals;
3090 symbol *trueLabel, *falseLabel;
3092 /* if we can make this a jump table */
3093 if (geniCodeJumpTable (cond, caseVals, tree))
3094 goto jumpTable; /* no need for the comparison */
3096 /* for the cases defined do */
3100 operand *compare = geniCodeLogic (cond,
3101 operandFromValue (caseVals),
3104 sprintf (buffer, "_case_%d_%d",
3105 tree->values.switchVals.swNum,
3106 (int) floatFromVal (caseVals));
3107 trueLabel = newiTempLabel (buffer);
3109 ic = newiCodeCondition (compare, trueLabel, NULL);
3111 caseVals = caseVals->next;
3116 /* if default is present then goto break else break */
3117 if (tree->values.switchVals.swDefault)
3118 sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3120 sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3122 falseLabel = newiTempLabel (buffer);
3123 geniCodeGoto (falseLabel);
3126 ast2iCode (tree->right,lvl+1);
3129 /*-----------------------------------------------------------------*/
3130 /* geniCodeInline - intermediate code for inline assembler */
3131 /*-----------------------------------------------------------------*/
3133 geniCodeInline (ast * tree)
3137 ic = newiCode (INLINEASM, NULL, NULL);
3138 IC_INLINE (ic) = tree->values.inlineasm;
3142 /*-----------------------------------------------------------------*/
3143 /* geniCodeArrayInit - intermediate code for array initializer */
3144 /*-----------------------------------------------------------------*/
3146 geniCodeArrayInit (ast * tree, operand *array)
3150 if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3151 ic = newiCode (ARRAYINIT, array, NULL);
3152 IC_ARRAYILIST (ic) = tree->values.constlist;
3154 operand *left=newOperand(), *right=newOperand();
3155 left->type=right->type=SYMBOL;
3156 OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3157 OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3158 ic = newiCode (ARRAYINIT, left, right);
3163 /*-----------------------------------------------------------------*/
3164 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
3165 /* particular case. Ie : assigning or dereferencing array or ptr */
3166 /*-----------------------------------------------------------------*/
3167 set * lvaluereqSet = NULL;
3168 typedef struct lvalItem
3175 /*-----------------------------------------------------------------*/
3176 /* addLvaluereq - add a flag for lvalreq for current ast level */
3177 /*-----------------------------------------------------------------*/
3178 void addLvaluereq(int lvl)
3180 lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3183 addSetHead(&lvaluereqSet,lpItem);
3186 /*-----------------------------------------------------------------*/
3187 /* delLvaluereq - del a flag for lvalreq for current ast level */
3188 /*-----------------------------------------------------------------*/
3192 lpItem = getSet(&lvaluereqSet);
3193 if(lpItem) Safe_free(lpItem);
3195 /*-----------------------------------------------------------------*/
3196 /* clearLvaluereq - clear lvalreq flag */
3197 /*-----------------------------------------------------------------*/
3198 void clearLvaluereq()
3201 lpItem = peekSet(lvaluereqSet);
3202 if(lpItem) lpItem->req = 0;
3204 /*-----------------------------------------------------------------*/
3205 /* getLvaluereq - get the last lvalreq level */
3206 /*-----------------------------------------------------------------*/
3207 int getLvaluereqLvl()
3210 lpItem = peekSet(lvaluereqSet);
3211 if(lpItem) return lpItem->lvl;
3214 /*-----------------------------------------------------------------*/
3215 /* isLvaluereq - is lvalreq valid for this level ? */
3216 /*-----------------------------------------------------------------*/
3217 int isLvaluereq(int lvl)
3220 lpItem = peekSet(lvaluereqSet);
3221 if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3225 /*-----------------------------------------------------------------*/
3226 /* ast2iCode - creates an icodeList from an ast */
3227 /*-----------------------------------------------------------------*/
3229 ast2iCode (ast * tree,int lvl)
3231 operand *left = NULL;
3232 operand *right = NULL;
3235 /* set the global variables for filename & line number */
3237 filename = tree->filename;
3239 lineno = tree->lineno;
3241 block = tree->block;
3243 scopeLevel = tree->level;
3245 if (tree->type == EX_VALUE)
3246 return operandFromValue (tree->opval.val);
3248 if (tree->type == EX_LINK)
3249 return operandFromLink (tree->opval.lnk);
3251 /* if we find a nullop */
3252 if (tree->type == EX_OP &&
3253 (tree->opval.op == NULLOP ||
3254 tree->opval.op == BLOCK))
3256 ast2iCode (tree->left,lvl+1);
3257 ast2iCode (tree->right,lvl+1);
3261 /* special cases for not evaluating */
3262 if (tree->opval.op != ':' &&
3263 tree->opval.op != '?' &&
3264 tree->opval.op != CALL &&
3265 tree->opval.op != IFX &&
3266 tree->opval.op != LABEL &&
3267 tree->opval.op != GOTO &&
3268 tree->opval.op != SWITCH &&
3269 tree->opval.op != FUNCTION &&
3270 tree->opval.op != INLINEASM)
3273 if (IS_ASSIGN_OP (tree->opval.op) ||
3274 IS_DEREF_OP (tree) ||
3275 (tree->opval.op == '&' && !tree->right) ||
3276 tree->opval.op == PTR_OP)
3279 if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3280 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3283 left = operandFromAst (tree->left,lvl);
3285 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3286 left = geniCodeRValue (left, TRUE);
3290 left = operandFromAst (tree->left,lvl);
3292 if (tree->opval.op == INC_OP ||
3293 tree->opval.op == DEC_OP)
3296 right = operandFromAst (tree->right,lvl);
3301 right = operandFromAst (tree->right,lvl);
3305 /* now depending on the type of operand */
3306 /* this will be a biggy */
3307 switch (tree->opval.op)
3310 case '[': /* array operation */
3312 //sym_link *ltype = operandType (left);
3313 //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3314 left = geniCodeRValue (left, FALSE);
3315 right = geniCodeRValue (right, TRUE);
3318 return geniCodeArray (left, right,lvl);
3320 case '.': /* structure dereference */
3321 if (IS_PTR (operandType (left)))
3322 left = geniCodeRValue (left, TRUE);
3324 left = geniCodeRValue (left, FALSE);
3326 return geniCodeStruct (left, right, tree->lvalue);
3328 case PTR_OP: /* structure pointer dereference */
3331 pType = operandType (left);
3332 left = geniCodeRValue (left, TRUE);
3334 setOClass (pType, getSpec (operandType (left)));
3337 return geniCodeStruct (left, right, tree->lvalue);
3339 case INC_OP: /* increment operator */
3341 return geniCodePostInc (left);
3343 return geniCodePreInc (right);
3345 case DEC_OP: /* decrement operator */
3347 return geniCodePostDec (left);
3349 return geniCodePreDec (right);
3351 case '&': /* bitwise and or address of operator */
3353 { /* this is a bitwise operator */
3354 left = geniCodeRValue (left, FALSE);
3355 right = geniCodeRValue (right, FALSE);
3356 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3359 return geniCodeAddressOf (left);
3361 case '|': /* bitwise or & xor */
3363 return geniCodeBitwise (geniCodeRValue (left, FALSE),
3364 geniCodeRValue (right, FALSE),
3369 return geniCodeDivision (geniCodeRValue (left, FALSE),
3370 geniCodeRValue (right, FALSE));
3373 return geniCodeModulus (geniCodeRValue (left, FALSE),
3374 geniCodeRValue (right, FALSE));
3377 return geniCodeMultiply (geniCodeRValue (left, FALSE),
3378 geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3380 return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3384 return geniCodeSubtract (geniCodeRValue (left, FALSE),
3385 geniCodeRValue (right, FALSE));
3387 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3391 return geniCodeAdd (geniCodeRValue (left, FALSE),
3392 geniCodeRValue (right, FALSE),lvl);
3394 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
3397 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3398 geniCodeRValue (right, FALSE));
3401 return geniCodeRightShift (geniCodeRValue (left, FALSE),
3402 geniCodeRValue (right, FALSE));
3404 return geniCodeCast (operandType (left),
3405 geniCodeRValue (right, FALSE), FALSE);
3411 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3415 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3416 setOperandType (op, UCHARTYPE);
3427 return geniCodeLogic (geniCodeRValue (left, FALSE),
3428 geniCodeRValue (right, FALSE),
3431 return geniCodeConditional (tree,lvl);
3434 return operandFromLit (getSize (tree->right->ftype));
3438 sym_link *rtype = operandType (right);
3439 sym_link *ltype = operandType (left);
3440 if (IS_PTR (rtype) && IS_ITEMP (right)
3441 && right->isaddr && compareType (rtype->next, ltype) == 1)
3442 right = geniCodeRValue (right, TRUE);
3444 right = geniCodeRValue (right, FALSE);
3446 geniCodeAssign (left, right, 0);
3451 geniCodeAssign (left,
3452 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3454 geniCodeRValue (right, FALSE),FALSE), 0);
3458 geniCodeAssign (left,
3459 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3461 geniCodeRValue (right, FALSE)), 0);
3464 geniCodeAssign (left,
3465 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3467 geniCodeRValue (right, FALSE)), 0);
3470 sym_link *rtype = operandType (right);
3471 sym_link *ltype = operandType (left);
3472 if (IS_PTR (rtype) && IS_ITEMP (right)
3473 && right->isaddr && compareType (rtype->next, ltype) == 1)
3474 right = geniCodeRValue (right, TRUE);
3476 right = geniCodeRValue (right, FALSE);
3479 return geniCodeAssign (left,
3480 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3486 sym_link *rtype = operandType (right);
3487 sym_link *ltype = operandType (left);
3488 if (IS_PTR (rtype) && IS_ITEMP (right)
3489 && right->isaddr && compareType (rtype->next, ltype) == 1)
3491 right = geniCodeRValue (right, TRUE);
3495 right = geniCodeRValue (right, FALSE);
3498 geniCodeAssign (left,
3499 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3505 geniCodeAssign (left,
3506 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3508 geniCodeRValue (right, FALSE)), 0);
3511 geniCodeAssign (left,
3512 geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3514 geniCodeRValue (right, FALSE)), 0);
3517 geniCodeAssign (left,
3518 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3520 geniCodeRValue (right, FALSE),
3522 operandType (left)), 0);
3525 geniCodeAssign (left,
3526 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3528 geniCodeRValue (right, FALSE),
3530 operandType (left)), 0);
3533 geniCodeAssign (left,
3534 geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3536 geniCodeRValue (right, FALSE),
3538 operandType (left)), 0);
3540 return geniCodeRValue (right, FALSE);
3543 return geniCodeCall (ast2iCode (tree->left,lvl+1),
3546 geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3547 return ast2iCode (tree->right,lvl+1);
3550 geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3551 return ast2iCode (tree->right,lvl+1);
3554 geniCodeFunctionBody (tree,lvl);
3558 geniCodeReturn (right);
3562 geniCodeIfx (tree,lvl);
3566 geniCodeSwitch (tree,lvl);
3570 geniCodeInline (tree);
3574 geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
3581 /*-----------------------------------------------------------------*/
3582 /* reverseICChain - gets from the list and creates a linkedlist */
3583 /*-----------------------------------------------------------------*/
3590 while ((loop = getSet (&iCodeChain)))
3602 /*-----------------------------------------------------------------*/
3603 /* iCodeFromAst - given an ast will convert it to iCode */
3604 /*-----------------------------------------------------------------*/
3606 iCodeFromAst (ast * tree)
3608 returnLabel = newiTempLabel ("_return");
3609 entryLabel = newiTempLabel ("_entry");
3611 return reverseiCChain ();