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 -------------------------------------------------------------------------*/
28 /*-----------------------------------------------------------------*/
29 /* global variables */
31 set *iCodeChain = NULL;
41 symbol *returnLabel; /* function return label */
42 symbol *entryLabel; /* function entry label */
44 #if defined(__BORLANDC__) || defined(_MSC_VER)
45 #define LONG_LONG __int64
47 #define LONG_LONG long long
50 /*-----------------------------------------------------------------*/
51 /* forward definition of some functions */
52 operand *geniCodeDivision (operand *, operand *);
53 operand *geniCodeAssign (operand *, operand *, int);
54 operand *geniCodeArray (operand *, operand *,int);
55 operand *geniCodeArray2Ptr (operand *);
56 operand *geniCodeRValue (operand *, bool);
57 operand *geniCodeDerefPtr (operand *,int);
58 int isLvaluereq(int lvl);
60 #define PRINTFUNC(x) void x (FILE *of, iCode *ic, char *s)
61 /* forward definition of ic print functions */
62 PRINTFUNC (picGetValueAtAddr);
63 PRINTFUNC (picSetValueAtAddr);
64 PRINTFUNC (picAddrOf);
65 PRINTFUNC (picGeneric);
66 PRINTFUNC (picGenericOne);
68 PRINTFUNC (picAssign);
72 PRINTFUNC (picJumpTable);
73 PRINTFUNC (picInline);
74 PRINTFUNC (picReceive);
76 iCodeTable codeTable[] =
78 {'!', "not", picGenericOne, NULL},
79 {'~', "~", picGenericOne, NULL},
80 {RRC, "rrc", picGenericOne, NULL},
81 {RLC, "rlc", picGenericOne, NULL},
82 {GETHBIT, "ghbit", picGenericOne, NULL},
83 {UNARYMINUS, "-", picGenericOne, NULL},
84 {IPUSH, "push", picGenericOne, NULL},
85 {IPOP, "pop", picGenericOne, NULL},
86 {CALL, "call", picGenericOne, NULL},
87 {PCALL, "pcall", picGenericOne, NULL},
88 {FUNCTION, "proc", picGenericOne, NULL},
89 {ENDFUNCTION, "eproc", picGenericOne, NULL},
90 {RETURN, "ret", picGenericOne, NULL},
91 {'+', "+", picGeneric, NULL},
92 {'-', "-", picGeneric, NULL},
93 {'*', "*", picGeneric, NULL},
94 {'/', "/", picGeneric, NULL},
95 {'%', "%", picGeneric, NULL},
96 {'>', ">", picGeneric, NULL},
97 {'<', "<", picGeneric, NULL},
98 {LE_OP, "<=", picGeneric, NULL},
99 {GE_OP, ">=", picGeneric, NULL},
100 {EQ_OP, "==", picGeneric, NULL},
101 {NE_OP, "!=", picGeneric, NULL},
102 {AND_OP, "&&", picGeneric, NULL},
103 {OR_OP, "||", picGeneric, NULL},
104 {'^', "^", picGeneric, NULL},
105 {'|', "|", picGeneric, NULL},
106 {BITWISEAND, "&", picGeneric, NULL},
107 {LEFT_OP, "<<", picGeneric, NULL},
108 {RIGHT_OP, ">>", picGeneric, NULL},
109 {GET_VALUE_AT_ADDRESS, "@", picGetValueAtAddr, NULL},
110 {ADDRESS_OF, "&", picAddrOf, NULL},
111 {CAST, "<>", picCast, NULL},
112 {'=', ":=", picAssign, NULL},
113 {LABEL, "", picLabel, NULL},
114 {GOTO, "", picGoto, NULL},
115 {JUMPTABLE, "jtab", picJumpTable, NULL},
116 {IFX, "if", picIfx, NULL},
117 {INLINEASM, "", picInline, NULL},
118 {RECEIVE, "recv", picReceive, NULL},
119 {SEND, "send", picGenericOne, NULL},
120 {ARRAYINIT, "arrayInit", picGenericOne, NULL},
123 /*-----------------------------------------------------------------*/
124 /* checkConstantRange: check a constant against the type */
125 /*-----------------------------------------------------------------*/
127 /* pedantic=0: allmost anything is allowed as long as the absolute
128 value is within the bit range of the type, and -1 is treated as
129 0xf..f for unsigned types (e.g. in assign)
130 pedantic=1: -1==-1, not allowed for unsigned types (e.g. in compare)
131 pedantic>1: "char c=200" is not allowed (evaluates to -56)
134 void checkConstantRange(sym_link *ltype, value *val, char *msg, int pedantic) {
135 LONG_LONG max = (LONG_LONG) 1 << bitsForType(ltype);
136 char message[132]="";
139 long v=SPEC_CVAL(val->type).v_long;
142 // this could be a good idea
143 if (options.pedantic)
147 if (SPEC_NOUN(ltype)==FLOAT) {
152 if (!SPEC_USIGN(val->type) && v<0) {
154 if (SPEC_USIGN(ltype) && (pedantic>1)) {
160 // if very pedantic: "char c=200" is not allowed
161 if (pedantic>1 && !SPEC_USIGN(ltype)) {
162 max = max/2 + negative;
170 sprintf (message, "for %s %s in %s",
171 SPEC_USIGN(ltype) ? "unsigned" : "signed",
172 nounName(ltype), msg);
173 werror (W_CONST_RANGE, message);
180 /*-----------------------------------------------------------------*/
181 /* operandName - returns the name of the operand */
182 /*-----------------------------------------------------------------*/
184 printOperand (operand * op, FILE * file)
201 opetype = getSpec (operandType (op));
202 if (SPEC_NOUN (opetype) == V_FLOAT)
203 fprintf (file, "%g {", SPEC_CVAL (opetype).v_float);
205 fprintf (file, "0x%x {", (int) floatFromVal (op->operand.valOperand));
206 printTypeChain (operandType (op), file);
213 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}" , */
214 (OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name),
216 OP_LIVEFROM (op), OP_LIVETO (op),
217 OP_SYMBOL (op)->stack,
218 op->isaddr, OP_SYMBOL (op)->isreqv, OP_SYMBOL (op)->remat,OP_SYMBOL(op)->noSpilLoc
222 printTypeChain (operandType (op), file);
223 if (SPIL_LOC (op) && IS_ITEMP (op))
224 fprintf (file, "}{ sir@ %s", SPIL_LOC (op)->rname);
229 /* if assigned to registers */
230 if (OP_SYMBOL (op)->nRegs)
232 if (OP_SYMBOL (op)->isspilt)
234 if (!OP_SYMBOL (op)->remat)
235 if (OP_SYMBOL (op)->usl.spillLoc)
236 fprintf (file, "[%s]", (OP_SYMBOL (op)->usl.spillLoc->rname[0] ?
237 OP_SYMBOL (op)->usl.spillLoc->rname :
238 OP_SYMBOL (op)->usl.spillLoc->name));
240 fprintf (file, "[err]");
242 fprintf (file, "[remat]");
248 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
249 fprintf (file, "%s ", port->getRegName (OP_SYMBOL (op)->regs[i]));
254 fprintf (file, "%s", (OP_SYMBOL (op)->rname[0] ?
255 OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name));
256 /* if assigned to registers */
257 if (OP_SYMBOL (op)->nRegs && !OP_SYMBOL (op)->isspilt)
261 for (i = 0; i < OP_SYMBOL (op)->nRegs; i++)
262 fprintf (file, "%s ", (OP_SYMBOL (op)->regs[i] ?
263 OP_SYMBOL (op)->regs[i]->name :
272 printTypeChain (op->operand.typeOperand, file);
278 fprintf (file, "\n");
283 /*-----------------------------------------------------------------*/
284 /* print functions */
285 /*-----------------------------------------------------------------*/
286 PRINTFUNC (picGetValueAtAddr)
289 printOperand (IC_RESULT (ic), of);
292 printOperand (IC_LEFT (ic), of);
298 PRINTFUNC (picSetValueAtAddr)
302 printOperand (IC_LEFT (ic), of);
303 fprintf (of, "] = ");
304 printOperand (IC_RIGHT (ic), of);
308 PRINTFUNC (picAddrOf)
311 printOperand (IC_RESULT (ic), of);
312 if (IS_ITEMP (IC_LEFT (ic)))
315 fprintf (of, " = &[");
316 printOperand (IC_LEFT (ic), of);
319 if (IS_ITEMP (IC_LEFT (ic)))
320 fprintf (of, " offsetAdd ");
323 printOperand (IC_RIGHT (ic), of);
325 if (IS_ITEMP (IC_LEFT (ic)))
331 PRINTFUNC (picJumpTable)
336 fprintf (of, "%s\t", s);
337 printOperand (IC_JTCOND (ic), of);
339 for (sym = setFirstItem (IC_JTLABELS (ic)); sym;
340 sym = setNextItem (IC_JTLABELS (ic)))
341 fprintf (of, "\t\t\t%s\n", sym->name);
344 PRINTFUNC (picGeneric)
347 printOperand (IC_RESULT (ic), of);
349 printOperand (IC_LEFT (ic), of);
350 fprintf (of, " %s ", s);
351 printOperand (IC_RIGHT (ic), of);
355 PRINTFUNC (picGenericOne)
360 printOperand (IC_RESULT (ic), of);
366 fprintf (of, "%s ", s);
367 printOperand (IC_LEFT (ic), of);
370 if (!IC_RESULT (ic) && !IC_LEFT (ic))
379 printOperand (IC_RESULT (ic), of);
381 printOperand (IC_LEFT (ic), of);
382 printOperand (IC_RIGHT (ic), of);
387 PRINTFUNC (picAssign)
391 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
394 printOperand (IC_RESULT (ic), of);
396 if (IC_RESULT (ic)->isaddr && IS_ITEMP (IC_RESULT (ic)))
399 fprintf (of, " %s ", s);
400 printOperand (IC_RIGHT (ic), of);
407 fprintf (of, " %s($%d) :\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
413 fprintf (of, " goto %s($%d)\n", IC_LABEL (ic)->name, IC_LABEL (ic)->key);
420 printOperand (IC_COND (ic), of);
423 fprintf (of, " == 0 goto %s($%d)\n", IC_FALSE (ic)->name, IC_FALSE (ic)->key);
426 fprintf (of, " != 0 goto %s($%d)\n", IC_TRUE (ic)->name, IC_TRUE (ic)->key);
428 fprintf (of, "\tzzgoto %s\n", IC_FALSE (ic)->name);
432 PRINTFUNC (picInline)
434 fprintf (of, "%s", IC_INLINE (ic));
437 PRINTFUNC (picReceive)
439 printOperand (IC_RESULT (ic), of);
440 fprintf (of, " = %s ", s);
441 printOperand (IC_LEFT (ic), of);
445 /*-----------------------------------------------------------------*/
446 /* piCode - prints one iCode */
447 /*-----------------------------------------------------------------*/
449 piCode (void *item, FILE * of)
457 icTab = getTableEntry (ic->op);
458 fprintf (stdout, "%s(%d:%d:%d:%d:%d)\t",
459 ic->filename, ic->lineno,
460 ic->seq, ic->key, ic->depth, ic->supportRtn);
461 icTab->iCodePrint (of, ic, icTab->printName);
467 printiCChain(ic,stdout);
469 /*-----------------------------------------------------------------*/
470 /* printiCChain - prints intermediate code for humans */
471 /*-----------------------------------------------------------------*/
473 printiCChain (iCode * icChain, FILE * of)
480 for (loop = icChain; loop; loop = loop->next)
482 if ((icTab = getTableEntry (loop->op)))
484 fprintf (of, "%s(%d:%d:%d:%d:%d)\t",
485 loop->filename, loop->lineno,
486 loop->seq, loop->key, loop->depth, loop->supportRtn);
488 icTab->iCodePrint (of, loop, icTab->printName);
494 /*-----------------------------------------------------------------*/
495 /* newOperand - allocate, init & return a new iCode */
496 /*-----------------------------------------------------------------*/
502 op = Safe_calloc (1, sizeof (operand));
508 /*-----------------------------------------------------------------*/
509 /* newiCode - create and return a new iCode entry initialised */
510 /*-----------------------------------------------------------------*/
512 newiCode (int op, operand * left, operand * right)
516 ic = Safe_calloc (1, sizeof (iCode));
519 ic->filename = filename;
521 ic->level = scopeLevel;
523 ic->key = iCodeKey++;
525 IC_RIGHT (ic) = right;
530 /*-----------------------------------------------------------------*/
531 /* newiCode for conditional statements */
532 /*-----------------------------------------------------------------*/
534 newiCodeCondition (operand * condition,
540 if (IS_VOID(OP_SYMBOL(condition)->type)) {
541 werror(E_VOID_VALUE_USED);
544 ic = newiCode (IFX, NULL, NULL);
545 IC_COND (ic) = condition;
546 IC_TRUE (ic) = trueLabel;
547 IC_FALSE (ic) = falseLabel;
551 /*-----------------------------------------------------------------*/
552 /* newiCodeLabelGoto - unconditional goto statement| label stmnt */
553 /*-----------------------------------------------------------------*/
555 newiCodeLabelGoto (int op, symbol * label)
559 ic = newiCode (op, NULL, NULL);
561 ic->argLabel.label = label;
563 IC_RIGHT (ic) = NULL;
564 IC_RESULT (ic) = NULL;
568 /*-----------------------------------------------------------------*/
569 /* newiTemp - allocate & return a newItemp Variable */
570 /*-----------------------------------------------------------------*/
577 sprintf (buffer, "%s", s);
579 sprintf (buffer, "iTemp%d", iTempNum++);
580 itmp = newSymbol (buffer, 1);
581 strcpy (itmp->rname, itmp->name);
587 /*-----------------------------------------------------------------*/
588 /* newiTempLabel - creates a temp variable label */
589 /*-----------------------------------------------------------------*/
591 newiTempLabel (char *s)
595 /* check if this alredy exists */
596 if (s && (itmplbl = findSym (LabelTab, NULL, s)))
600 itmplbl = newSymbol (s, 1);
603 sprintf (buffer, "iTempLbl%d", iTempLblNum++);
604 itmplbl = newSymbol (buffer, 1);
609 itmplbl->key = labelKey++;
610 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
614 /*-----------------------------------------------------------------*/
615 /* newiTempPreheaderLabel - creates a new preheader label */
616 /*-----------------------------------------------------------------*/
618 newiTempPreheaderLabel ()
622 sprintf (buffer, "preHeaderLbl%d", iTempLblNum++);
623 itmplbl = newSymbol (buffer, 1);
627 itmplbl->key = labelKey++;
628 addSym (LabelTab, itmplbl, itmplbl->name, 0, 0, 0);
633 /*-----------------------------------------------------------------*/
634 /* initiCode - initialises some iCode related stuff */
635 /*-----------------------------------------------------------------*/
642 /*-----------------------------------------------------------------*/
643 /* copyiCode - make a copy of the iCode given */
644 /*-----------------------------------------------------------------*/
646 copyiCode (iCode * ic)
648 iCode *nic = newiCode (ic->op, NULL, NULL);
650 nic->lineno = ic->lineno;
651 nic->filename = ic->filename;
652 nic->block = ic->block;
653 nic->level = ic->level;
654 nic->parmBytes = ic->parmBytes;
656 /* deal with the special cases first */
660 IC_COND (nic) = operandFromOperand (IC_COND (ic));
661 IC_TRUE (nic) = IC_TRUE (ic);
662 IC_FALSE (nic) = IC_FALSE (ic);
666 IC_JTCOND (nic) = operandFromOperand (IC_JTCOND (ic));
667 IC_JTLABELS (nic) = IC_JTLABELS (ic);
672 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
673 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
674 IC_ARGS (nic) = IC_ARGS (ic);
678 IC_INLINE (nic) = IC_INLINE (ic);
682 IC_ARRAYILIST(nic) = IC_ARRAYILIST(ic);
686 IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
687 IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
688 IC_RIGHT (nic) = operandFromOperand (IC_RIGHT (ic));
694 /*-----------------------------------------------------------------*/
695 /* getTableEntry - gets the table entry for the given operator */
696 /*-----------------------------------------------------------------*/
698 getTableEntry (int oper)
702 for (i = 0; i < (sizeof (codeTable) / sizeof (iCodeTable)); i++)
703 if (oper == codeTable[i].icode)
704 return &codeTable[i];
709 /*-----------------------------------------------------------------*/
710 /* newiTempOperand - new intermediate temp operand */
711 /*-----------------------------------------------------------------*/
713 newiTempOperand (sym_link * type, char throwType)
716 operand *op = newOperand ();
720 itmp = newiTemp (NULL);
722 etype = getSpec (type);
724 if (IS_LITERAL (etype))
727 /* copy the type information */
729 itmp->etype = getSpec (itmp->type = (throwType ? type :
730 copyLinkChain (type)));
731 if (IS_LITERAL (itmp->etype))
733 SPEC_SCLS (itmp->etype) = S_REGISTER;
734 SPEC_OCLS (itmp->etype) = reg;
737 op->operand.symOperand = itmp;
738 op->key = itmp->key = ++operandKey;
742 /*-----------------------------------------------------------------*/
743 /* operandType - returns the type chain for an operand */
744 /*-----------------------------------------------------------------*/
746 operandType (operand * op)
748 /* depending on type of operand */
753 return op->operand.valOperand->type;
756 return op->operand.symOperand->type;
759 return op->operand.typeOperand;
761 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
762 " operand type not known ");
763 assert (0); /* should never come here */
764 /* Just to keep the compiler happy */
765 return (sym_link *) 0;
769 /*-----------------------------------------------------------------*/
770 /* isParamterToCall - will return 1 if op is a parameter to args */
771 /*-----------------------------------------------------------------*/
773 isParameterToCall (value * args, operand * op)
780 isSymbolEqual (op->operand.symOperand, tval->sym))
787 /*-----------------------------------------------------------------*/
788 /* isOperandGlobal - return 1 if operand is a global variable */
789 /*-----------------------------------------------------------------*/
791 isOperandGlobal (operand * op)
799 if (op->type == SYMBOL &&
800 (op->operand.symOperand->level == 0 ||
801 IS_STATIC (op->operand.symOperand->etype) ||
802 IS_EXTERN (op->operand.symOperand->etype))
809 /*-----------------------------------------------------------------*/
810 /* isOperandVolatile - return 1 if the operand is volatile */
811 /*-----------------------------------------------------------------*/
813 isOperandVolatile (operand * op, bool chkTemp)
818 if (IS_ITEMP (op) && !chkTemp)
821 opetype = getSpec (optype = operandType (op));
823 if (IS_PTR (optype) && DCL_PTR_VOLATILE (optype))
826 if (IS_VOLATILE (opetype))
831 /*-----------------------------------------------------------------*/
832 /* isOperandLiteral - returns 1 if an operand contains a literal */
833 /*-----------------------------------------------------------------*/
835 isOperandLiteral (operand * op)
842 opetype = getSpec (operandType (op));
844 if (IS_LITERAL (opetype))
849 /*-----------------------------------------------------------------*/
850 /* isOperandInFarSpace - will return true if operand is in farSpace */
851 /*-----------------------------------------------------------------*/
853 isOperandInFarSpace (operand * op)
863 if (!IS_TRUE_SYMOP (op))
866 etype = SPIL_LOC (op)->etype;
872 etype = getSpec (operandType (op));
874 return (IN_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
877 /*-----------------------------------------------------------------*/
878 /* isOperandOnStack - will return true if operand is on stack */
879 /*-----------------------------------------------------------------*/
881 isOperandOnStack (operand * op)
891 etype = getSpec (operandType (op));
893 return ((IN_STACK (etype)) ? TRUE : FALSE);
896 /*-----------------------------------------------------------------*/
897 /* operandLitValue - literal value of an operand */
898 /*-----------------------------------------------------------------*/
900 operandLitValue (operand * op)
902 assert (isOperandLiteral (op));
904 return floatFromVal (op->operand.valOperand);
907 /*-----------------------------------------------------------------*/
908 /* operandOperation - perforoms operations on operands */
909 /*-----------------------------------------------------------------*/
911 operandOperation (operand * left, operand * right,
912 int op, sym_link * type)
914 sym_link *let , *ret=NULL;
915 operand *retval = (operand *) 0;
917 assert (isOperandLiteral (left));
918 let = getSpec(operandType(left));
920 assert (isOperandLiteral (right));
921 ret = getSpec(operandType(left));
927 retval = operandFromValue (valCastLiteral (type,
928 operandLitValue (left) +
929 operandLitValue (right)));
932 retval = operandFromValue (valCastLiteral (type,
933 operandLitValue (left) -
934 operandLitValue (right)));
937 retval = operandFromValue (valCastLiteral (type,
938 operandLitValue (left) *
939 operandLitValue (right)));
942 if ((unsigned long) operandLitValue (right) == 0)
944 werror (E_DIVIDE_BY_ZERO);
949 retval = operandFromValue (valCastLiteral (type,
950 operandLitValue (left) /
951 operandLitValue (right)));
954 if ((unsigned long) operandLitValue (right) == 0) {
955 werror (E_DIVIDE_BY_ZERO);
959 retval = operandFromLit ((SPEC_USIGN(let) ?
960 (unsigned long) operandLitValue (left) :
961 (long) operandLitValue (left)) %
963 (unsigned long) operandLitValue (right) :
964 (long) operandLitValue (right)));
968 retval = operandFromLit (((SPEC_USIGN(let) ?
969 (unsigned long) operandLitValue (left) :
970 (long) operandLitValue (left)) <<
972 (unsigned long) operandLitValue (right) :
973 (long) operandLitValue (right))));
976 retval = operandFromLit (((SPEC_USIGN(let) ?
977 (unsigned long) operandLitValue (left) :
978 (long) operandLitValue (left)) >>
980 (unsigned long) operandLitValue (right) :
981 (long) operandLitValue (right))));
984 retval = operandFromLit (operandLitValue (left) ==
985 operandLitValue (right));
988 retval = operandFromLit (operandLitValue (left) <
989 operandLitValue (right));
992 retval = operandFromLit (operandLitValue (left) <=
993 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 ((unsigned long) operandLitValue (left) &
1009 (unsigned long) operandLitValue (right));
1012 retval = operandFromLit ((unsigned long) operandLitValue (left) |
1013 (unsigned long) operandLitValue (right));
1016 retval = operandFromLit ((unsigned long) operandLitValue (left) ^
1017 (unsigned long) operandLitValue (right));
1020 retval = operandFromLit (operandLitValue (left) &&
1021 operandLitValue (right));
1024 retval = operandFromLit (operandLitValue (left) ||
1025 operandLitValue (right));
1029 long i = (long) operandLitValue (left);
1031 retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
1037 long i = (long) operandLitValue (left);
1039 retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
1045 retval = operandFromLit (-1 * operandLitValue (left));
1049 retval = operandFromLit (~((long) operandLitValue (left)));
1053 retval = operandFromLit (!operandLitValue (left));
1057 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1058 " operandOperation invalid operator ");
1066 /*-----------------------------------------------------------------*/
1067 /* isOperandEqual - compares two operand & return 1 if they r = */
1068 /*-----------------------------------------------------------------*/
1070 isOperandEqual (operand * left, operand * right)
1072 /* if the pointers are equal then they are equal */
1076 /* if either of them null then false */
1077 if (!left || !right)
1080 if (left->type != right->type)
1083 if (IS_SYMOP (left) && IS_SYMOP (right))
1084 return left->key == right->key;
1086 /* if types are the same */
1090 return isSymbolEqual (left->operand.symOperand,
1091 right->operand.symOperand);
1093 return (floatFromVal (left->operand.valOperand) ==
1094 floatFromVal (right->operand.valOperand));
1096 if (compareType (left->operand.typeOperand,
1097 right->operand.typeOperand) == 1)
1104 /*-------------------------------------------------------------------*/
1105 /* isiCodeEqual - compares two iCodes are equal, returns true if yes */
1106 /*-------------------------------------------------------------------*/
1108 isiCodeEqual (iCode * left, iCode * right)
1110 /* if the same pointer */
1114 /* if either of them null */
1115 if (!left || !right)
1118 /* if operand are the same */
1119 if (left->op == right->op)
1122 /* compare all the elements depending on type */
1123 if (left->op != IFX)
1125 if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
1127 if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
1133 if (!isOperandEqual (IC_COND (left), IC_COND (right)))
1135 if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
1137 if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
1146 /*-----------------------------------------------------------------*/
1147 /* newiTempFromOp - create a temp Operand with same attributes */
1148 /*-----------------------------------------------------------------*/
1150 newiTempFromOp (operand * op)
1160 nop = newiTempOperand (operandType (op), TRUE);
1161 nop->isaddr = op->isaddr;
1162 nop->isvolatile = op->isvolatile;
1163 nop->isGlobal = op->isGlobal;
1164 nop->isLiteral = op->isLiteral;
1165 nop->usesDefs = op->usesDefs;
1166 nop->isParm = op->isParm;
1170 /*-----------------------------------------------------------------*/
1171 /* operand from operand - creates an operand holder for the type */
1172 /*-----------------------------------------------------------------*/
1174 operandFromOperand (operand * op)
1180 nop = newOperand ();
1181 nop->type = op->type;
1182 nop->isaddr = op->isaddr;
1184 nop->isvolatile = op->isvolatile;
1185 nop->isGlobal = op->isGlobal;
1186 nop->isLiteral = op->isLiteral;
1187 nop->usesDefs = op->usesDefs;
1188 nop->isParm = op->isParm;
1193 nop->operand.symOperand = op->operand.symOperand;
1196 nop->operand.valOperand = op->operand.valOperand;
1199 nop->operand.typeOperand = op->operand.typeOperand;
1206 /*-----------------------------------------------------------------*/
1207 /* opFromOpWithDU - makes a copy of the operand and DU chains */
1208 /*-----------------------------------------------------------------*/
1210 opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
1212 operand *nop = operandFromOperand (op);
1214 if (nop->type == SYMBOL)
1216 OP_SYMBOL (nop)->defs = bitVectCopy (defs);
1217 OP_SYMBOL (nop)->uses = bitVectCopy (uses);
1223 /*-----------------------------------------------------------------*/
1224 /* operandFromSymbol - creates an operand from a symbol */
1225 /*-----------------------------------------------------------------*/
1227 operandFromSymbol (symbol * sym)
1232 /* if the symbol's type is a literal */
1233 /* then it is an enumerator type */
1234 if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
1235 return operandFromValue (valFromType (sym->etype));
1238 sym->key = ++operandKey;
1240 /* if this an implicit variable, means struct/union */
1241 /* member so just return it */
1242 if (sym->implicit || IS_FUNC (sym->type))
1246 op->operand.symOperand = sym;
1248 op->isvolatile = isOperandVolatile (op, TRUE);
1249 op->isGlobal = isOperandGlobal (op);
1253 /* under the following conditions create a
1254 register equivalent for a local symbol */
1255 if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
1256 (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
1257 /* (!TARGET_IS_DS390)) && */
1258 (!(options.model == MODEL_FLAT24)) ) &&
1259 options.stackAuto == 0)
1262 if (!IS_AGGREGATE (sym->type) && /* not an aggregate */
1263 !IS_FUNC (sym->type) && /* not a function */
1264 !sym->_isparm && /* not a parameter */
1265 sym->level && /* is a local variable */
1266 !sym->addrtaken && /* whose address has not been taken */
1267 !sym->reqv && /* does not already have a register euivalence */
1268 !IS_VOLATILE (sym->etype) && /* not declared as volatile */
1269 !IS_STATIC (sym->etype) && /* and not declared static */
1270 !sym->islbl && /* not a label */
1271 ok && /* farspace check */
1272 !IS_BITVAR (sym->etype) /* not a bit variable */
1276 /* we will use it after all optimizations
1277 and before liveRange calculation */
1278 sym->reqv = newiTempOperand (sym->type, 0);
1279 sym->reqv->key = sym->key;
1280 OP_SYMBOL (sym->reqv)->key = sym->key;
1281 OP_SYMBOL (sym->reqv)->isreqv = 1;
1282 OP_SYMBOL (sym->reqv)->islocal = 1;
1283 SPIL_LOC (sym->reqv) = sym;
1286 if (!IS_AGGREGATE (sym->type))
1290 op->operand.symOperand = sym;
1293 op->isvolatile = isOperandVolatile (op, TRUE);
1294 op->isGlobal = isOperandGlobal (op);
1295 op->isPtr = IS_PTR (operandType (op));
1296 op->isParm = sym->_isparm;
1301 /* itemp = &[_symbol] */
1303 ic = newiCode (ADDRESS_OF, newOperand (), NULL);
1304 IC_LEFT (ic)->type = SYMBOL;
1305 IC_LEFT (ic)->operand.symOperand = sym;
1306 IC_LEFT (ic)->key = sym->key;
1307 (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
1308 (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
1309 IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
1312 IC_RESULT (ic) = newiTempOperand (sym->type, 0);
1313 if (IS_ARRAY (sym->type))
1315 IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
1316 IC_RESULT (ic)->isaddr = 0;
1319 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
1321 IC_RESULT (ic)->operand.symOperand->args = sym->args;
1325 return IC_RESULT (ic);
1328 /*-----------------------------------------------------------------*/
1329 /* operandFromValue - creates an operand from value */
1330 /*-----------------------------------------------------------------*/
1332 operandFromValue (value * val)
1336 /* if this is a symbol then do the symbol thing */
1338 return operandFromSymbol (val->sym);
1340 /* this is not a symbol */
1343 op->operand.valOperand = val;
1344 op->isLiteral = isOperandLiteral (op);
1348 /*-----------------------------------------------------------------*/
1349 /* operandFromLink - operand from typeChain */
1350 /*-----------------------------------------------------------------*/
1352 operandFromLink (sym_link * type)
1356 /* operand from sym_link */
1362 op->operand.typeOperand = copyLinkChain (type);
1366 /*-----------------------------------------------------------------*/
1367 /* operandFromLit - makes an operand from a literal value */
1368 /*-----------------------------------------------------------------*/
1370 operandFromLit (double i)
1372 return operandFromValue (valueFromLit (i));
1375 /*-----------------------------------------------------------------*/
1376 /* operandFromAst - creates an operand from an ast */
1377 /*-----------------------------------------------------------------*/
1379 operandFromAst (ast * tree,int lvl)
1385 /* depending on type do */
1389 return ast2iCode (tree,lvl+1);
1393 return operandFromValue (tree->opval.val);
1397 return operandFromLink (tree->opval.lnk);
1401 /* Just to keep the comiler happy */
1402 return (operand *) 0;
1405 /*-----------------------------------------------------------------*/
1406 /* setOperandType - sets the operand's type to the given type */
1407 /*-----------------------------------------------------------------*/
1409 setOperandType (operand * op, sym_link * type)
1411 /* depending on the type of operand */
1416 op->operand.valOperand->etype =
1417 getSpec (op->operand.valOperand->type =
1418 copyLinkChain (type));
1422 if (op->operand.symOperand->isitmp)
1423 op->operand.symOperand->etype =
1424 getSpec (op->operand.symOperand->type =
1425 copyLinkChain (type));
1427 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1428 "attempt to modify type of source");
1432 op->operand.typeOperand = copyLinkChain (type);
1437 /*-----------------------------------------------------------------*/
1438 /* Get size in byte of ptr need to access an array */
1439 /*-----------------------------------------------------------------*/
1441 getArraySizePtr (operand * op)
1443 sym_link *ltype = operandType(op);
1447 int size = getSize(ltype);
1448 return(IS_GENPTR(ltype)?(size-1):size);
1453 sym_link *letype = getSpec(ltype);
1454 switch (PTR_TYPE (SPEC_OCLS (letype)))
1466 return (GPTRSIZE-1);
1475 /*-----------------------------------------------------------------*/
1476 /* perform "usual unary conversions" */
1477 /*-----------------------------------------------------------------*/
1479 usualUnaryConversions (operand * op)
1481 if (IS_INTEGRAL (operandType (op)))
1483 if (getSize (operandType (op)) < (unsigned int) INTSIZE)
1486 return geniCodeCast (INTTYPE, op, TRUE);
1492 /*-----------------------------------------------------------------*/
1493 /* perform "usual binary conversions" */
1494 /*-----------------------------------------------------------------*/
1496 usualBinaryConversions (operand ** op1, operand ** op2)
1499 sym_link *rtype = operandType (*op2);
1500 sym_link *ltype = operandType (*op1);
1502 ctype = computeType (ltype, rtype);
1503 *op1 = geniCodeCast (ctype, *op1, TRUE);
1504 *op2 = geniCodeCast (ctype, *op2, TRUE);
1509 /*-----------------------------------------------------------------*/
1510 /* geniCodeValueAtAddress - generate intermeditate code for value */
1512 /*-----------------------------------------------------------------*/
1514 geniCodeRValue (operand * op, bool force)
1517 sym_link *type = operandType (op);
1518 sym_link *etype = getSpec (type);
1520 /* if this is an array & already */
1521 /* an address then return this */
1522 if (IS_AGGREGATE (type) ||
1523 (IS_PTR (type) && !force && !op->isaddr))
1524 return operandFromOperand (op);
1526 /* if this is not an address then must be */
1527 /* rvalue already so return this one */
1531 /* if this is not a temp symbol then */
1532 if (!IS_ITEMP (op) &&
1534 !IN_FARSPACE (SPEC_OCLS (etype)))
1536 op = operandFromOperand (op);
1541 if (IS_SPEC (type) &&
1542 IS_TRUE_SYMOP (op) &&
1543 (!IN_FARSPACE (SPEC_OCLS (etype)) ||
1544 /* TARGET_IS_DS390)) */
1545 (options.model == MODEL_FLAT24) ))
1547 op = operandFromOperand (op);
1552 ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1553 if (IS_PTR (type) && op->isaddr && force)
1556 type = copyLinkChain (type);
1558 IC_RESULT (ic) = newiTempOperand (type, 1);
1559 IC_RESULT (ic)->isaddr = 0;
1561 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1563 /* if the right is a symbol */
1564 if (op->type == SYMBOL)
1565 IC_RESULT (ic)->operand.symOperand->args =
1566 op->operand.symOperand->args;
1569 return IC_RESULT (ic);
1572 /*-----------------------------------------------------------------*/
1573 /* geniCodeCast - changes the value from one type to another */
1574 /*-----------------------------------------------------------------*/
1576 geniCodeCast (sym_link * type, operand * op, bool implicit)
1580 sym_link *opetype = getSpec (optype = operandType (op));
1584 /* one of them has size zero then error */
1585 if (IS_VOID (optype))
1587 werror (E_CAST_ZERO);
1591 /* if the operand is already the desired type then do nothing */
1592 if (compareType (type, optype) == 1)
1595 /* if this is a literal then just change the type & return */
1596 if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1597 return operandFromValue (valCastLiteral (type,
1598 operandLitValue (op)));
1600 /* if casting to/from pointers, do some checking */
1601 if (IS_PTR(type)) { // to a pointer
1602 if (!IS_PTR(optype) && !IS_FUNC(optype)) { // from a non pointer
1603 if (IS_INTEGRAL(optype)) {
1604 // maybe this is NULL, than it's ok.
1605 if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
1606 if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80 && IS_GENPTR(type)) {
1607 // no way to set the storage
1608 if (IS_LITERAL(optype)) {
1609 werror(E_LITERAL_GENERIC);
1612 werror(E_NONPTR2_GENPTR);
1615 } else if (implicit) {
1616 werror(W_INTEGRAL2PTR_NOCAST);
1621 // shouldn't do that with float, array or structure unless to void
1622 if (!IS_VOID(getSpec(type)) &&
1623 !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1624 werror(E_INCOMPAT_TYPES);
1628 } else { // from a pointer to a pointer
1629 if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80) {
1630 // if not a pointer to a function
1631 if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1632 if (implicit) { // if not to generic, they have to match
1633 if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
1634 werror(E_INCOMPAT_PTYPES);
1641 } else { // to a non pointer
1642 if (IS_PTR(optype)) { // from a pointer
1643 if (implicit) { // sneaky
1644 if (IS_INTEGRAL(type)) {
1645 werror(W_PTR2INTEGRAL_NOCAST);
1647 } else { // shouldn't do that with float, array or structure
1648 werror(E_INCOMPAT_TYPES);
1655 /* fprintf (stderr, "%s%s %d: ", op->operand.symOperand->name,
1656 implicit?"(implicit)":"", errors); */
1657 fprintf (stderr, "from type '");
1658 printTypeChain (optype, stderr);
1659 fprintf (stderr, "' to type '");
1660 printTypeChain (type, stderr);
1661 fprintf (stderr, "'\n");
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);
2115 if (IS_PTR (element->type))
2116 setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2118 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2122 return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2125 /*-----------------------------------------------------------------*/
2126 /* geniCodePostInc - generate int code for Post increment */
2127 /*-----------------------------------------------------------------*/
2129 geniCodePostInc (operand * op)
2133 sym_link *optype = operandType (op);
2135 operand *rv = (IS_ITEMP (op) ?
2136 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2138 sym_link *rvtype = operandType (rv);
2141 /* if this is not an address we have trouble */
2144 werror (E_LVALUE_REQUIRED, "++");
2148 rOp = newiTempOperand (rvtype, 0);
2149 OP_SYMBOL(rOp)->noSpilLoc = 1;
2152 OP_SYMBOL(rv)->noSpilLoc = 1;
2154 geniCodeAssign (rOp, rv, 0);
2156 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2157 if (IS_FLOAT (rvtype))
2158 ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2160 ic = newiCode ('+', rv, operandFromLit (size));
2162 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2165 geniCodeAssign (op, result, 0);
2171 /*-----------------------------------------------------------------*/
2172 /* geniCodePreInc - generate code for preIncrement */
2173 /*-----------------------------------------------------------------*/
2175 geniCodePreInc (operand * op)
2178 sym_link *optype = operandType (op);
2179 operand *rop = (IS_ITEMP (op) ?
2180 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2182 sym_link *roptype = operandType (rop);
2188 werror (E_LVALUE_REQUIRED, "++");
2193 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2194 if (IS_FLOAT (roptype))
2195 ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2197 ic = newiCode ('+', rop, operandFromLit (size));
2198 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2202 return geniCodeAssign (op, result, 0);
2205 /*-----------------------------------------------------------------*/
2206 /* geniCodePostDec - generates code for Post decrement */
2207 /*-----------------------------------------------------------------*/
2209 geniCodePostDec (operand * op)
2213 sym_link *optype = operandType (op);
2215 operand *rv = (IS_ITEMP (op) ?
2216 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2218 sym_link *rvtype = operandType (rv);
2221 /* if this is not an address we have trouble */
2224 werror (E_LVALUE_REQUIRED, "--");
2228 rOp = newiTempOperand (rvtype, 0);
2229 OP_SYMBOL(rOp)->noSpilLoc = 1;
2232 OP_SYMBOL(rv)->noSpilLoc = 1;
2234 geniCodeAssign (rOp, rv, 0);
2236 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2237 if (IS_FLOAT (rvtype))
2238 ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2240 ic = newiCode ('-', rv, operandFromLit (size));
2242 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2245 geniCodeAssign (op, result, 0);
2251 /*-----------------------------------------------------------------*/
2252 /* geniCodePreDec - generate code for pre decrement */
2253 /*-----------------------------------------------------------------*/
2255 geniCodePreDec (operand * op)
2258 sym_link *optype = operandType (op);
2259 operand *rop = (IS_ITEMP (op) ?
2260 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2262 sym_link *roptype = operandType (rop);
2268 werror (E_LVALUE_REQUIRED, "--");
2273 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2274 if (IS_FLOAT (roptype))
2275 ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2277 ic = newiCode ('-', rop, operandFromLit (size));
2278 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2282 return geniCodeAssign (op, result, 0);
2286 /*-----------------------------------------------------------------*/
2287 /* geniCodeBitwise - gen int code for bitWise operators */
2288 /*-----------------------------------------------------------------*/
2290 geniCodeBitwise (operand * left, operand * right,
2291 int oper, sym_link * resType)
2295 left = geniCodeCast (resType, left, TRUE);
2296 right = geniCodeCast (resType, right, TRUE);
2298 ic = newiCode (oper, left, right);
2299 IC_RESULT (ic) = newiTempOperand (resType, 0);
2302 return IC_RESULT (ic);
2305 /*-----------------------------------------------------------------*/
2306 /* geniCodeAddressOf - gens icode for '&' address of operator */
2307 /*-----------------------------------------------------------------*/
2309 geniCodeAddressOf (operand * op)
2313 sym_link *optype = operandType (op);
2314 sym_link *opetype = getSpec (optype);
2316 /* lvalue check already done in decorateType */
2317 /* this must be a lvalue */
2318 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2319 /* werror (E_LVALUE_REQUIRED,"&"); */
2324 p->class = DECLARATOR;
2326 /* set the pointer depending on the storage class */
2327 if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2328 DCL_PTR_CONST (p) = port->mem.code_ro;
2330 /* make sure we preserve the const & volatile */
2331 if (IS_CONSTANT (opetype))
2332 DCL_PTR_CONST (p) = 1;
2334 if (IS_VOLATILE (opetype))
2335 DCL_PTR_VOLATILE (p) = 1;
2337 p->next = copyLinkChain (optype);
2339 /* if already a temp */
2342 setOperandType (op, p);
2347 /* other wise make this of the type coming in */
2348 ic = newiCode (ADDRESS_OF, op, NULL);
2349 IC_RESULT (ic) = newiTempOperand (p, 1);
2350 IC_RESULT (ic)->isaddr = 0;
2352 return IC_RESULT (ic);
2354 /*-----------------------------------------------------------------*/
2355 /* setOClass - sets the output class depending on the pointer type */
2356 /*-----------------------------------------------------------------*/
2358 setOClass (sym_link * ptr, sym_link * spec)
2360 switch (DCL_TYPE (ptr))
2363 SPEC_OCLS (spec) = data;
2367 SPEC_OCLS (spec) = generic;
2371 SPEC_OCLS (spec) = xdata;
2375 SPEC_OCLS (spec) = code;
2379 SPEC_OCLS (spec) = idata;
2383 SPEC_OCLS (spec) = xstack;
2387 SPEC_OCLS (spec) = eeprom;
2396 /*-----------------------------------------------------------------*/
2397 /* geniCodeDerefPtr - dereference pointer with '*' */
2398 /*-----------------------------------------------------------------*/
2400 geniCodeDerefPtr (operand * op,int lvl)
2402 sym_link *rtype, *retype;
2403 sym_link *optype = operandType (op);
2405 /* if this is a pointer then generate the rvalue */
2406 if (IS_PTR (optype))
2408 if (IS_TRUE_SYMOP (op))
2411 op = geniCodeRValue (op, TRUE);
2414 op = geniCodeRValue (op, TRUE);
2417 /* now get rid of the pointer part */
2418 if (isLvaluereq(lvl) && IS_ITEMP (op))
2420 retype = getSpec (rtype = copyLinkChain (optype));
2424 retype = getSpec (rtype = copyLinkChain (optype->next));
2427 /* if this is a pointer then outputclass needs 2b updated */
2428 if (IS_PTR (optype))
2429 setOClass (optype, retype);
2431 op->isGptr = IS_GENPTR (optype);
2433 /* if the pointer was declared as a constant */
2434 /* then we cannot allow assignment to the derefed */
2435 if (IS_PTR_CONST (optype))
2436 SPEC_CONST (retype) = 1;
2438 op->isaddr = (IS_PTR (rtype) ||
2439 IS_STRUCT (rtype) ||
2444 if (!isLvaluereq(lvl))
2445 op = geniCodeRValue (op, TRUE);
2447 setOperandType (op, rtype);
2452 /*-----------------------------------------------------------------*/
2453 /* geniCodeUnaryMinus - does a unary minus of the operand */
2454 /*-----------------------------------------------------------------*/
2456 geniCodeUnaryMinus (operand * op)
2459 sym_link *optype = operandType (op);
2461 if (IS_LITERAL (optype))
2462 return operandFromLit (-floatFromVal (op->operand.valOperand));
2464 ic = newiCode (UNARYMINUS, op, NULL);
2465 IC_RESULT (ic) = newiTempOperand (optype, 0);
2467 return IC_RESULT (ic);
2470 /*-----------------------------------------------------------------*/
2471 /* geniCodeLeftShift - gen i code for left shift */
2472 /*-----------------------------------------------------------------*/
2474 geniCodeLeftShift (operand * left, operand * right)
2478 ic = newiCode (LEFT_OP, left, right);
2479 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2481 return IC_RESULT (ic);
2484 /*-----------------------------------------------------------------*/
2485 /* geniCodeRightShift - gen i code for right shift */
2486 /*-----------------------------------------------------------------*/
2488 geniCodeRightShift (operand * left, operand * right)
2492 ic = newiCode (RIGHT_OP, left, right);
2493 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2495 return IC_RESULT (ic);
2498 /*-----------------------------------------------------------------*/
2499 /* geniCodeLogic- logic code */
2500 /*-----------------------------------------------------------------*/
2502 geniCodeLogic (operand * left, operand * right, int op)
2506 sym_link *rtype = operandType (right);
2507 sym_link *ltype = operandType (left);
2509 /* left is integral type and right is literal then
2510 check if the literal value is within bounds */
2511 if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2513 checkConstantRange(ltype,
2514 OP_VALUE(right), "compare operation", 1);
2517 ctype = usualBinaryConversions (&left, &right);
2519 ic = newiCode (op, left, right);
2520 IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2522 /* if comparing float
2523 and not a '==' || '!=' || '&&' || '||' (these
2525 if (IS_FLOAT(ctype) &&
2533 return IC_RESULT (ic);
2536 /*-----------------------------------------------------------------*/
2537 /* geniCodeUnary - for a a generic unary operation */
2538 /*-----------------------------------------------------------------*/
2540 geniCodeUnary (operand * op, int oper)
2542 iCode *ic = newiCode (oper, op, NULL);
2544 IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2546 return IC_RESULT (ic);
2549 /*-----------------------------------------------------------------*/
2550 /* geniCodeConditional - geniCode for '?' ':' operation */
2551 /*-----------------------------------------------------------------*/
2553 geniCodeConditional (ast * tree,int lvl)
2556 symbol *falseLabel = newiTempLabel (NULL);
2557 symbol *exitLabel = newiTempLabel (NULL);
2558 operand *cond = ast2iCode (tree->left,lvl+1);
2559 operand *true, *false, *result;
2561 ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
2565 true = ast2iCode (tree->right->left,lvl+1);
2567 /* move the value to a new Operand */
2568 result = newiTempOperand (operandType (true), 0);
2569 geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
2571 /* generate an unconditional goto */
2572 geniCodeGoto (exitLabel);
2574 /* now for the right side */
2575 geniCodeLabel (falseLabel);
2577 false = ast2iCode (tree->right->right,lvl+1);
2578 geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
2580 /* create the exit label */
2581 geniCodeLabel (exitLabel);
2586 /*-----------------------------------------------------------------*/
2587 /* geniCodeAssign - generate code for assignment */
2588 /*-----------------------------------------------------------------*/
2590 geniCodeAssign (operand * left, operand * right, int nosupdate)
2593 sym_link *ltype = operandType (left);
2594 sym_link *rtype = operandType (right);
2596 if (!left->isaddr && !IS_ITEMP (left))
2598 werror (E_LVALUE_REQUIRED, "assignment");
2602 /* left is integral type and right is literal then
2603 check if the literal value is within bounds */
2604 if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
2606 checkConstantRange(ltype,
2607 OP_VALUE(right), "= operation", 0);
2610 /* if the left & right type don't exactly match */
2611 /* if pointer set then make sure the check is
2612 done with the type & not the pointer */
2613 /* then cast rights type to left */
2615 /* first check the type for pointer assignement */
2616 if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
2617 compareType (ltype, rtype) < 0)
2619 if (compareType (ltype->next, rtype) < 0)
2620 right = geniCodeCast (ltype->next, right, TRUE);
2622 else if (compareType (ltype, rtype) < 0)
2623 right = geniCodeCast (ltype, right, TRUE);
2625 /* if left is a true symbol & ! volatile
2626 create an assignment to temporary for
2627 the right & then assign this temporary
2628 to the symbol this is SSA . isn't it simple
2629 and folks have published mountains of paper on it */
2630 if (IS_TRUE_SYMOP (left) &&
2631 !isOperandVolatile (left, FALSE) &&
2632 isOperandGlobal (left))
2636 if (IS_TRUE_SYMOP (right))
2637 sym = OP_SYMBOL (right);
2638 ic = newiCode ('=', NULL, right);
2639 IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
2640 SPIL_LOC (right) = sym;
2644 ic = newiCode ('=', NULL, right);
2645 IC_RESULT (ic) = left;
2648 /* if left isgptr flag is set then support
2649 routine will be required */
2653 ic->nosupdate = nosupdate;
2657 /*-----------------------------------------------------------------*/
2658 /* geniCodeSEParms - generate code for side effecting fcalls */
2659 /*-----------------------------------------------------------------*/
2661 geniCodeSEParms (ast * parms,int lvl)
2666 if (parms->type == EX_OP && parms->opval.op == PARAM)
2668 geniCodeSEParms (parms->left,lvl);
2669 geniCodeSEParms (parms->right,lvl);
2673 /* hack don't like this but too lazy to think of
2675 if (IS_ADDRESS_OF_OP (parms))
2676 parms->left->lvalue = 1;
2678 if (IS_CAST_OP (parms) &&
2679 IS_PTR (parms->ftype) &&
2680 IS_ADDRESS_OF_OP (parms->right))
2681 parms->right->left->lvalue = 1;
2683 parms->opval.oprnd =
2684 geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2686 parms->type = EX_OPERAND;
2689 /*-----------------------------------------------------------------*/
2690 /* geniCodeParms - generates parameters */
2691 /*-----------------------------------------------------------------*/
2693 geniCodeParms (ast * parms, int *stack, sym_link * fetype, symbol * func,int lvl)
2701 /* if this is a param node then do the left & right */
2702 if (parms->type == EX_OP && parms->opval.op == PARAM)
2704 geniCodeParms (parms->left, stack, fetype, func,lvl);
2705 geniCodeParms (parms->right, stack, fetype, func,lvl);
2709 /* get the parameter value */
2710 if (parms->type == EX_OPERAND)
2711 pval = parms->opval.oprnd;
2714 /* maybe this else should go away ?? */
2715 /* hack don't like this but too lazy to think of
2717 if (IS_ADDRESS_OF_OP (parms))
2718 parms->left->lvalue = 1;
2720 if (IS_CAST_OP (parms) &&
2721 IS_PTR (parms->ftype) &&
2722 IS_ADDRESS_OF_OP (parms->right))
2723 parms->right->left->lvalue = 1;
2725 pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2728 /* if register parm then make it a send */
2729 if (((parms->argSym && IS_REGPARM (parms->argSym->etype)) ||
2730 IS_REGPARM (parms->etype)) && !func->hasVargs)
2732 ic = newiCode (SEND, pval, NULL);
2737 /* now decide whether to push or assign */
2738 if (!(options.stackAuto || IS_RENT (fetype)))
2742 operand *top = operandFromSymbol (parms->argSym);
2743 geniCodeAssign (top, pval, 1);
2747 sym_link *p = operandType (pval);
2749 ic = newiCode (IPUSH, pval, NULL);
2751 /* update the stack adjustment */
2752 *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2759 /*-----------------------------------------------------------------*/
2760 /* geniCodeCall - generates temp code for calling */
2761 /*-----------------------------------------------------------------*/
2763 geniCodeCall (operand * left, ast * parms,int lvl)
2767 sym_link *type, *etype;
2770 if (!IS_FUNC(OP_SYMBOL(left)->type) &&
2771 !IS_CODEPTR(OP_SYMBOL(left)->type)) {
2772 werror (E_FUNCTION_EXPECTED);
2776 /* take care of parameters with side-effecting
2777 function calls in them, this is required to take care
2778 of overlaying function parameters */
2779 geniCodeSEParms (parms,lvl);
2781 /* first the parameters */
2782 geniCodeParms (parms, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
2784 /* now call : if symbol then pcall */
2785 if (IS_OP_POINTER (left) || IS_ITEMP(left))
2786 ic = newiCode (PCALL, left, NULL);
2788 ic = newiCode (CALL, left, NULL);
2790 IC_ARGS (ic) = left->operand.symOperand->args;
2791 type = copyLinkChain (operandType (left)->next);
2792 etype = getSpec (type);
2793 SPEC_EXTR (etype) = 0;
2794 IC_RESULT (ic) = result = newiTempOperand (type, 1);
2798 /* stack adjustment after call */
2799 ic->parmBytes = stack;
2804 /*-----------------------------------------------------------------*/
2805 /* geniCodeReceive - generate intermediate code for "receive" */
2806 /*-----------------------------------------------------------------*/
2808 geniCodeReceive (value * args)
2810 /* for all arguments that are passed in registers */
2814 if (IS_REGPARM (args->etype))
2816 operand *opr = operandFromValue (args);
2818 symbol *sym = OP_SYMBOL (opr);
2821 /* we will use it after all optimizations
2822 and before liveRange calculation */
2823 if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
2826 if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
2827 options.stackAuto == 0 &&
2828 /* !TARGET_IS_DS390) */
2829 (!(options.model == MODEL_FLAT24)) )
2834 opl = newiTempOperand (args->type, 0);
2836 sym->reqv->key = sym->key;
2837 OP_SYMBOL (sym->reqv)->key = sym->key;
2838 OP_SYMBOL (sym->reqv)->isreqv = 1;
2839 OP_SYMBOL (sym->reqv)->islocal = 0;
2840 SPIL_LOC (sym->reqv) = sym;
2844 ic = newiCode (RECEIVE, NULL, NULL);
2845 currFunc->recvSize = getSize (sym->etype);
2846 IC_RESULT (ic) = opr;
2854 /*-----------------------------------------------------------------*/
2855 /* geniCodeFunctionBody - create the function body */
2856 /*-----------------------------------------------------------------*/
2858 geniCodeFunctionBody (ast * tree,int lvl)
2865 /* reset the auto generation */
2871 func = ast2iCode (tree->left,lvl+1);
2872 fetype = getSpec (operandType (func));
2874 savelineno = lineno;
2875 lineno = OP_SYMBOL (func)->lineDef;
2876 /* create an entry label */
2877 geniCodeLabel (entryLabel);
2878 lineno = savelineno;
2880 /* create a proc icode */
2881 ic = newiCode (FUNCTION, func, NULL);
2882 /* if the function has parmas then */
2883 /* save the parameters information */
2884 ic->argLabel.args = tree->values.args;
2885 ic->lineno = OP_SYMBOL (func)->lineDef;
2889 /* for all parameters that are passed
2890 on registers add a "receive" */
2891 geniCodeReceive (tree->values.args);
2893 /* generate code for the body */
2894 ast2iCode (tree->right,lvl+1);
2896 /* create a label for return */
2897 geniCodeLabel (returnLabel);
2899 /* now generate the end proc */
2900 ic = newiCode (ENDFUNCTION, func, NULL);
2905 /*-----------------------------------------------------------------*/
2906 /* geniCodeReturn - gen icode for 'return' statement */
2907 /*-----------------------------------------------------------------*/
2909 geniCodeReturn (operand * op)
2913 /* if the operand is present force an rvalue */
2915 op = geniCodeRValue (op, FALSE);
2917 ic = newiCode (RETURN, op, NULL);
2921 /*-----------------------------------------------------------------*/
2922 /* geniCodeIfx - generates code for extended if statement */
2923 /*-----------------------------------------------------------------*/
2925 geniCodeIfx (ast * tree,int lvl)
2928 operand *condition = ast2iCode (tree->left,lvl+1);
2931 /* if condition is null then exit */
2935 condition = geniCodeRValue (condition, FALSE);
2937 cetype = getSpec (operandType (condition));
2938 /* if the condition is a literal */
2939 if (IS_LITERAL (cetype))
2941 if (floatFromVal (condition->operand.valOperand))
2943 if (tree->trueLabel)
2944 geniCodeGoto (tree->trueLabel);
2950 if (tree->falseLabel)
2951 geniCodeGoto (tree->falseLabel);
2958 if (tree->trueLabel)
2960 ic = newiCodeCondition (condition,
2965 if (tree->falseLabel)
2966 geniCodeGoto (tree->falseLabel);
2970 ic = newiCodeCondition (condition,
2977 ast2iCode (tree->right,lvl+1);
2980 /*-----------------------------------------------------------------*/
2981 /* geniCodeJumpTable - tries to create a jump table for switch */
2982 /*-----------------------------------------------------------------*/
2984 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
2986 int min = 0, max = 0, t, cnt = 0;
2993 if (!tree || !caseVals)
2996 /* the criteria for creating a jump table is */
2997 /* all integer numbers between the maximum & minimum must */
2998 /* be present , the maximum value should not exceed 255 */
2999 min = max = (int) floatFromVal (vch = caseVals);
3000 sprintf (buffer, "_case_%d_%d",
3001 tree->values.switchVals.swNum,
3003 addSet (&labels, newiTempLabel (buffer));
3005 /* if there is only one case value then no need */
3006 if (!(vch = vch->next))
3011 if (((t = (int) floatFromVal (vch)) - max) != 1)
3013 sprintf (buffer, "_case_%d_%d",
3014 tree->values.switchVals.swNum,
3016 addSet (&labels, newiTempLabel (buffer));
3022 /* if the number of case statements <= 2 then */
3023 /* it is not economical to create the jump table */
3024 /* since two compares are needed for boundary conditions */
3025 if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
3028 if (tree->values.switchVals.swDefault)
3029 sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3031 sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3033 falseLabel = newiTempLabel (buffer);
3035 /* so we can create a jumptable */
3036 /* first we rule out the boundary conditions */
3037 /* if only optimization says so */
3038 if (!optimize.noJTabBoundary)
3040 sym_link *cetype = getSpec (operandType (cond));
3041 /* no need to check the lower bound if
3042 the condition is unsigned & minimum value is zero */
3043 if (!(min == 0 && SPEC_USIGN (cetype)))
3045 boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3046 ic = newiCodeCondition (boundary, falseLabel, NULL);
3050 /* now for upper bounds */
3051 boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3052 ic = newiCodeCondition (boundary, falseLabel, NULL);
3056 /* if the min is not zero then we no make it zero */
3059 cond = geniCodeSubtract (cond, operandFromLit (min));
3060 setOperandType (cond, UCHARTYPE);
3063 /* now create the jumptable */
3064 ic = newiCode (JUMPTABLE, NULL, NULL);
3065 IC_JTCOND (ic) = cond;
3066 IC_JTLABELS (ic) = labels;
3071 /*-----------------------------------------------------------------*/
3072 /* geniCodeSwitch - changes a switch to a if statement */
3073 /*-----------------------------------------------------------------*/
3075 geniCodeSwitch (ast * tree,int lvl)
3078 operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3079 value *caseVals = tree->values.switchVals.swVals;
3080 symbol *trueLabel, *falseLabel;
3082 /* if we can make this a jump table */
3083 if (geniCodeJumpTable (cond, caseVals, tree))
3084 goto jumpTable; /* no need for the comparison */
3086 /* for the cases defined do */
3090 operand *compare = geniCodeLogic (cond,
3091 operandFromValue (caseVals),
3094 sprintf (buffer, "_case_%d_%d",
3095 tree->values.switchVals.swNum,
3096 (int) floatFromVal (caseVals));
3097 trueLabel = newiTempLabel (buffer);
3099 ic = newiCodeCondition (compare, trueLabel, NULL);
3101 caseVals = caseVals->next;
3106 /* if default is present then goto break else break */
3107 if (tree->values.switchVals.swDefault)
3108 sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3110 sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3112 falseLabel = newiTempLabel (buffer);
3113 geniCodeGoto (falseLabel);
3116 ast2iCode (tree->right,lvl+1);
3119 /*-----------------------------------------------------------------*/
3120 /* geniCodeInline - intermediate code for inline assembler */
3121 /*-----------------------------------------------------------------*/
3123 geniCodeInline (ast * tree)
3127 ic = newiCode (INLINEASM, NULL, NULL);
3128 IC_INLINE (ic) = tree->values.inlineasm;
3132 /*-----------------------------------------------------------------*/
3133 /* geniCodeArrayInit - intermediate code for array initializer */
3134 /*-----------------------------------------------------------------*/
3136 geniCodeArrayInit (ast * tree, operand *array)
3140 if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3141 ic = newiCode (ARRAYINIT, array, NULL);
3142 IC_ARRAYILIST (ic) = tree->values.constlist;
3144 operand *left=newOperand(), *right=newOperand();
3145 left->type=right->type=SYMBOL;
3146 OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3147 OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3148 ic = newiCode (ARRAYINIT, left, right);
3153 /*-----------------------------------------------------------------*/
3154 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
3155 /* particular case. Ie : assigning or dereferencing array or ptr */
3156 /*-----------------------------------------------------------------*/
3157 set * lvaluereqSet = NULL;
3158 typedef struct lvalItem
3165 /*-----------------------------------------------------------------*/
3166 /* addLvaluereq - add a flag for lvalreq for current ast level */
3167 /*-----------------------------------------------------------------*/
3168 void addLvaluereq(int lvl)
3170 lvalItem * lpItem = (lvalItem *)Safe_calloc (1, sizeof (lvalItem));
3173 addSetHead(&lvaluereqSet,lpItem);
3176 /*-----------------------------------------------------------------*/
3177 /* delLvaluereq - del a flag for lvalreq for current ast level */
3178 /*-----------------------------------------------------------------*/
3182 lpItem = getSet(&lvaluereqSet);
3183 if(lpItem) free(lpItem);
3185 /*-----------------------------------------------------------------*/
3186 /* clearLvaluereq - clear lvalreq flag */
3187 /*-----------------------------------------------------------------*/
3188 void clearLvaluereq()
3191 lpItem = peekSet(lvaluereqSet);
3192 if(lpItem) lpItem->req = 0;
3194 /*-----------------------------------------------------------------*/
3195 /* getLvaluereq - get the last lvalreq level */
3196 /*-----------------------------------------------------------------*/
3197 int getLvaluereqLvl()
3200 lpItem = peekSet(lvaluereqSet);
3201 if(lpItem) return lpItem->lvl;
3204 /*-----------------------------------------------------------------*/
3205 /* isLvaluereq - is lvalreq valid for this level ? */
3206 /*-----------------------------------------------------------------*/
3207 int isLvaluereq(int lvl)
3210 lpItem = peekSet(lvaluereqSet);
3211 if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3215 /*-----------------------------------------------------------------*/
3216 /* ast2iCode - creates an icodeList from an ast */
3217 /*-----------------------------------------------------------------*/
3219 ast2iCode (ast * tree,int lvl)
3221 operand *left = NULL;
3222 operand *right = NULL;
3225 /* set the global variables for filename & line number */
3227 filename = tree->filename;
3229 lineno = tree->lineno;
3231 block = tree->block;
3233 scopeLevel = tree->level;
3235 if (tree->type == EX_VALUE)
3236 return operandFromValue (tree->opval.val);
3238 if (tree->type == EX_LINK)
3239 return operandFromLink (tree->opval.lnk);
3241 /* if we find a nullop */
3242 if (tree->type == EX_OP &&
3243 (tree->opval.op == NULLOP ||
3244 tree->opval.op == BLOCK))
3246 ast2iCode (tree->left,lvl+1);
3247 ast2iCode (tree->right,lvl+1);
3251 /* special cases for not evaluating */
3252 if (tree->opval.op != ':' &&
3253 tree->opval.op != '?' &&
3254 tree->opval.op != CALL &&
3255 tree->opval.op != IFX &&
3256 tree->opval.op != LABEL &&
3257 tree->opval.op != GOTO &&
3258 tree->opval.op != SWITCH &&
3259 tree->opval.op != FUNCTION &&
3260 tree->opval.op != INLINEASM)
3263 if (IS_ASSIGN_OP (tree->opval.op) ||
3264 IS_DEREF_OP (tree) ||
3265 (tree->opval.op == '&' && !tree->right) ||
3266 tree->opval.op == PTR_OP)
3269 if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3270 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3273 left = operandFromAst (tree->left,lvl);
3275 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3276 left = geniCodeRValue (left, TRUE);
3280 left = operandFromAst (tree->left,lvl);
3282 if (tree->opval.op == INC_OP ||
3283 tree->opval.op == DEC_OP)
3286 right = operandFromAst (tree->right,lvl);
3291 right = operandFromAst (tree->right,lvl);
3295 /* now depending on the type of operand */
3296 /* this will be a biggy */
3297 switch (tree->opval.op)
3300 case '[': /* array operation */
3302 //sym_link *ltype = operandType (left);
3303 //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3304 left = geniCodeRValue (left, FALSE);
3305 right = geniCodeRValue (right, TRUE);
3308 return geniCodeArray (left, right,lvl);
3310 case '.': /* structure dereference */
3311 if (IS_PTR (operandType (left)))
3312 left = geniCodeRValue (left, TRUE);
3314 left = geniCodeRValue (left, FALSE);
3316 return geniCodeStruct (left, right, tree->lvalue);
3318 case PTR_OP: /* structure pointer dereference */
3321 pType = operandType (left);
3322 left = geniCodeRValue (left, TRUE);
3324 setOClass (pType, getSpec (operandType (left)));
3327 return geniCodeStruct (left, right, tree->lvalue);
3329 case INC_OP: /* increment operator */
3331 return geniCodePostInc (left);
3333 return geniCodePreInc (right);
3335 case DEC_OP: /* decrement operator */
3337 return geniCodePostDec (left);
3339 return geniCodePreDec (right);
3341 case '&': /* bitwise and or address of operator */
3343 { /* this is a bitwise operator */
3344 left = geniCodeRValue (left, FALSE);
3345 right = geniCodeRValue (right, FALSE);
3346 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3349 return geniCodeAddressOf (left);
3351 case '|': /* bitwise or & xor */
3353 return geniCodeBitwise (geniCodeRValue (left, FALSE),
3354 geniCodeRValue (right, FALSE),
3359 return geniCodeDivision (geniCodeRValue (left, FALSE),
3360 geniCodeRValue (right, FALSE));
3363 return geniCodeModulus (geniCodeRValue (left, FALSE),
3364 geniCodeRValue (right, FALSE));
3367 return geniCodeMultiply (geniCodeRValue (left, FALSE),
3368 geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3370 return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3374 return geniCodeSubtract (geniCodeRValue (left, FALSE),
3375 geniCodeRValue (right, FALSE));
3377 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3381 return geniCodeAdd (geniCodeRValue (left, FALSE),
3382 geniCodeRValue (right, FALSE),lvl);
3384 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
3387 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3388 geniCodeRValue (right, FALSE));
3391 return geniCodeRightShift (geniCodeRValue (left, FALSE),
3392 geniCodeRValue (right, FALSE));
3394 return geniCodeCast (operandType (left),
3395 geniCodeRValue (right, FALSE), FALSE);
3401 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3405 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3406 setOperandType (op, UCHARTYPE);
3417 return geniCodeLogic (geniCodeRValue (left, FALSE),
3418 geniCodeRValue (right, FALSE),
3421 return geniCodeConditional (tree,lvl);
3424 return operandFromLit (getSize (tree->right->ftype));
3428 sym_link *rtype = operandType (right);
3429 sym_link *ltype = operandType (left);
3430 if (IS_PTR (rtype) && IS_ITEMP (right)
3431 && right->isaddr && compareType (rtype->next, ltype) == 1)
3432 right = geniCodeRValue (right, TRUE);
3434 right = geniCodeRValue (right, FALSE);
3436 geniCodeAssign (left, right, 0);
3441 geniCodeAssign (left,
3442 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3444 geniCodeRValue (right, FALSE),FALSE), 0);
3448 geniCodeAssign (left,
3449 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3451 geniCodeRValue (right, FALSE)), 0);
3454 geniCodeAssign (left,
3455 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3457 geniCodeRValue (right, FALSE)), 0);
3460 sym_link *rtype = operandType (right);
3461 sym_link *ltype = operandType (left);
3462 if (IS_PTR (rtype) && IS_ITEMP (right)
3463 && right->isaddr && compareType (rtype->next, ltype) == 1)
3464 right = geniCodeRValue (right, TRUE);
3466 right = geniCodeRValue (right, FALSE);
3469 return geniCodeAssign (left,
3470 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3476 sym_link *rtype = operandType (right);
3477 sym_link *ltype = operandType (left);
3478 if (IS_PTR (rtype) && IS_ITEMP (right)
3479 && right->isaddr && compareType (rtype->next, ltype) == 1)
3481 right = geniCodeRValue (right, TRUE);
3485 right = geniCodeRValue (right, FALSE);
3488 geniCodeAssign (left,
3489 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3495 geniCodeAssign (left,
3496 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3498 geniCodeRValue (right, FALSE)), 0);
3501 geniCodeAssign (left,
3502 geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3504 geniCodeRValue (right, FALSE)), 0);
3507 geniCodeAssign (left,
3508 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3510 geniCodeRValue (right, FALSE),
3512 operandType (left)), 0);
3515 geniCodeAssign (left,
3516 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3518 geniCodeRValue (right, FALSE),
3520 operandType (left)), 0);
3523 geniCodeAssign (left,
3524 geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3526 geniCodeRValue (right, FALSE),
3528 operandType (left)), 0);
3530 return geniCodeRValue (right, FALSE);
3533 return geniCodeCall (ast2iCode (tree->left,lvl+1),
3536 geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3537 return ast2iCode (tree->right,lvl+1);
3540 geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3541 return ast2iCode (tree->right,lvl+1);
3544 geniCodeFunctionBody (tree,lvl);
3548 geniCodeReturn (right);
3552 geniCodeIfx (tree,lvl);
3556 geniCodeSwitch (tree,lvl);
3560 geniCodeInline (tree);
3564 geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
3571 /*-----------------------------------------------------------------*/
3572 /* reverseICChain - gets from the list and creates a linkedlist */
3573 /*-----------------------------------------------------------------*/
3580 while ((loop = getSet (&iCodeChain)))
3592 /*-----------------------------------------------------------------*/
3593 /* iCodeFromAst - given an ast will convert it to iCode */
3594 /*-----------------------------------------------------------------*/
3596 iCodeFromAst (ast * tree)
3598 returnLabel = newiTempLabel ("_return");
3599 entryLabel = newiTempLabel ("_entry");
3601 return reverseiCChain ();