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, double v, char *msg, int pedantic) {
135 LONG_LONG max = (LONG_LONG) 1 << bitsForType(ltype);
136 char message[132]="";
141 // this could be a good idea
142 if (options.pedantic)
146 if (SPEC_NOUN(ltype)==FLOAT) {
153 // if not pedantic: -1 equals to 0xf..f
154 if (SPEC_USIGN(ltype) && (!pedantic ? v!=-1 : 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 - comapres two iCodes are 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)))
1145 /*-----------------------------------------------------------------*/
1146 /* newiTempFromOp - create a temp Operand with same attributes */
1147 /*-----------------------------------------------------------------*/
1149 newiTempFromOp (operand * op)
1159 nop = newiTempOperand (operandType (op), TRUE);
1160 nop->isaddr = op->isaddr;
1161 nop->isvolatile = op->isvolatile;
1162 nop->isGlobal = op->isGlobal;
1163 nop->isLiteral = op->isLiteral;
1164 nop->usesDefs = op->usesDefs;
1165 nop->isParm = op->isParm;
1169 /*-----------------------------------------------------------------*/
1170 /* operand from operand - creates an operand holder for the type */
1171 /*-----------------------------------------------------------------*/
1173 operandFromOperand (operand * op)
1179 nop = newOperand ();
1180 nop->type = op->type;
1181 nop->isaddr = op->isaddr;
1183 nop->isvolatile = op->isvolatile;
1184 nop->isGlobal = op->isGlobal;
1185 nop->isLiteral = op->isLiteral;
1186 nop->usesDefs = op->usesDefs;
1187 nop->isParm = op->isParm;
1192 nop->operand.symOperand = op->operand.symOperand;
1195 nop->operand.valOperand = op->operand.valOperand;
1198 nop->operand.typeOperand = op->operand.typeOperand;
1205 /*-----------------------------------------------------------------*/
1206 /* opFromOpWithDU - makes a copy of the operand and DU chains */
1207 /*-----------------------------------------------------------------*/
1209 opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
1211 operand *nop = operandFromOperand (op);
1213 if (nop->type == SYMBOL)
1215 OP_SYMBOL (nop)->defs = bitVectCopy (defs);
1216 OP_SYMBOL (nop)->uses = bitVectCopy (uses);
1222 /*-----------------------------------------------------------------*/
1223 /* operandFromSymbol - creates an operand from a symbol */
1224 /*-----------------------------------------------------------------*/
1226 operandFromSymbol (symbol * sym)
1231 /* if the symbol's type is a literal */
1232 /* then it is an enumerator type */
1233 if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
1234 return operandFromValue (valFromType (sym->etype));
1237 sym->key = ++operandKey;
1239 /* if this an implicit variable, means struct/union */
1240 /* member so just return it */
1241 if (sym->implicit || IS_FUNC (sym->type))
1245 op->operand.symOperand = sym;
1247 op->isvolatile = isOperandVolatile (op, TRUE);
1248 op->isGlobal = isOperandGlobal (op);
1252 /* under the following conditions create a
1253 register equivalent for a local symbol */
1254 if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
1255 (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
1256 /* (!TARGET_IS_DS390)) && */
1257 (!(options.model == MODEL_FLAT24)) ) &&
1258 options.stackAuto == 0)
1261 if (!IS_AGGREGATE (sym->type) && /* not an aggregate */
1262 !IS_FUNC (sym->type) && /* not a function */
1263 !sym->_isparm && /* not a parameter */
1264 sym->level && /* is a local variable */
1265 !sym->addrtaken && /* whose address has not been taken */
1266 !sym->reqv && /* does not already have a register euivalence */
1267 !IS_VOLATILE (sym->etype) && /* not declared as volatile */
1268 !IS_STATIC (sym->etype) && /* and not declared static */
1269 !sym->islbl && /* not a label */
1270 ok && /* farspace check */
1271 !IS_BITVAR (sym->etype) /* not a bit variable */
1275 /* we will use it after all optimizations
1276 and before liveRange calculation */
1277 sym->reqv = newiTempOperand (sym->type, 0);
1278 sym->reqv->key = sym->key;
1279 OP_SYMBOL (sym->reqv)->key = sym->key;
1280 OP_SYMBOL (sym->reqv)->isreqv = 1;
1281 OP_SYMBOL (sym->reqv)->islocal = 1;
1282 SPIL_LOC (sym->reqv) = sym;
1285 if (!IS_AGGREGATE (sym->type))
1289 op->operand.symOperand = sym;
1292 op->isvolatile = isOperandVolatile (op, TRUE);
1293 op->isGlobal = isOperandGlobal (op);
1294 op->isPtr = IS_PTR (operandType (op));
1295 op->isParm = sym->_isparm;
1300 /* itemp = &[_symbol] */
1302 ic = newiCode (ADDRESS_OF, newOperand (), NULL);
1303 IC_LEFT (ic)->type = SYMBOL;
1304 IC_LEFT (ic)->operand.symOperand = sym;
1305 IC_LEFT (ic)->key = sym->key;
1306 (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
1307 (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
1308 IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
1311 IC_RESULT (ic) = newiTempOperand (sym->type, 0);
1312 if (IS_ARRAY (sym->type))
1314 IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
1315 IC_RESULT (ic)->isaddr = 0;
1318 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
1320 IC_RESULT (ic)->operand.symOperand->args = sym->args;
1324 return IC_RESULT (ic);
1327 /*-----------------------------------------------------------------*/
1328 /* operandFromValue - creates an operand from value */
1329 /*-----------------------------------------------------------------*/
1331 operandFromValue (value * val)
1335 /* if this is a symbol then do the symbol thing */
1337 return operandFromSymbol (val->sym);
1339 /* this is not a symbol */
1342 op->operand.valOperand = val;
1343 op->isLiteral = isOperandLiteral (op);
1347 /*-----------------------------------------------------------------*/
1348 /* operandFromLink - operand from typeChain */
1349 /*-----------------------------------------------------------------*/
1351 operandFromLink (sym_link * type)
1355 /* operand from sym_link */
1361 op->operand.typeOperand = copyLinkChain (type);
1365 /*-----------------------------------------------------------------*/
1366 /* operandFromLit - makes an operand from a literal value */
1367 /*-----------------------------------------------------------------*/
1369 operandFromLit (double i)
1371 return operandFromValue (valueFromLit (i));
1374 /*-----------------------------------------------------------------*/
1375 /* operandFromAst - creates an operand from an ast */
1376 /*-----------------------------------------------------------------*/
1378 operandFromAst (ast * tree,int lvl)
1384 /* depending on type do */
1388 return ast2iCode (tree,lvl+1);
1392 return operandFromValue (tree->opval.val);
1396 return operandFromLink (tree->opval.lnk);
1400 /* Just to keep the comiler happy */
1401 return (operand *) 0;
1404 /*-----------------------------------------------------------------*/
1405 /* setOperandType - sets the operand's type to the given type */
1406 /*-----------------------------------------------------------------*/
1408 setOperandType (operand * op, sym_link * type)
1410 /* depending on the type of operand */
1415 op->operand.valOperand->etype =
1416 getSpec (op->operand.valOperand->type =
1417 copyLinkChain (type));
1421 if (op->operand.symOperand->isitmp)
1422 op->operand.symOperand->etype =
1423 getSpec (op->operand.symOperand->type =
1424 copyLinkChain (type));
1426 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1427 "attempt to modify type of source");
1431 op->operand.typeOperand = copyLinkChain (type);
1436 /*-----------------------------------------------------------------*/
1437 /* Get size in byte of ptr need to access an array */
1438 /*-----------------------------------------------------------------*/
1440 getArraySizePtr (operand * op)
1442 sym_link *ltype = operandType(op);
1446 int size = getSize(ltype);
1447 return(IS_GENPTR(ltype)?(size-1):size);
1452 sym_link *letype = getSpec(ltype);
1453 switch (PTR_TYPE (SPEC_OCLS (letype)))
1465 return (GPTRSIZE-1);
1474 /*-----------------------------------------------------------------*/
1475 /* perform "usual unary conversions" */
1476 /*-----------------------------------------------------------------*/
1478 usualUnaryConversions (operand * op)
1480 if (IS_INTEGRAL (operandType (op)))
1482 if (getSize (operandType (op)) < (unsigned int) INTSIZE)
1485 return geniCodeCast (INTTYPE, op, TRUE);
1491 /*-----------------------------------------------------------------*/
1492 /* perform "usual binary conversions" */
1493 /*-----------------------------------------------------------------*/
1495 usualBinaryConversions (operand ** op1, operand ** op2)
1498 sym_link *rtype = operandType (*op2);
1499 sym_link *ltype = operandType (*op1);
1501 ctype = computeType (ltype, rtype);
1502 *op1 = geniCodeCast (ctype, *op1, TRUE);
1503 *op2 = geniCodeCast (ctype, *op2, TRUE);
1508 /*-----------------------------------------------------------------*/
1509 /* geniCodeValueAtAddress - generate intermeditate code for value */
1511 /*-----------------------------------------------------------------*/
1513 geniCodeRValue (operand * op, bool force)
1516 sym_link *type = operandType (op);
1517 sym_link *etype = getSpec (type);
1519 /* if this is an array & already */
1520 /* an address then return this */
1521 if (IS_AGGREGATE (type) ||
1522 (IS_PTR (type) && !force && !op->isaddr))
1523 return operandFromOperand (op);
1525 /* if this is not an address then must be */
1526 /* rvalue already so return this one */
1530 /* if this is not a temp symbol then */
1531 if (!IS_ITEMP (op) &&
1533 !IN_FARSPACE (SPEC_OCLS (etype)))
1535 op = operandFromOperand (op);
1540 if (IS_SPEC (type) &&
1541 IS_TRUE_SYMOP (op) &&
1542 (!IN_FARSPACE (SPEC_OCLS (etype)) ||
1543 /* TARGET_IS_DS390)) */
1544 (options.model == MODEL_FLAT24) ))
1546 op = operandFromOperand (op);
1551 ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1552 if (IS_PTR (type) && op->isaddr && force)
1555 type = copyLinkChain (type);
1557 IC_RESULT (ic) = newiTempOperand (type, 1);
1558 IC_RESULT (ic)->isaddr = 0;
1560 /* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1562 /* if the right is a symbol */
1563 if (op->type == SYMBOL)
1564 IC_RESULT (ic)->operand.symOperand->args =
1565 op->operand.symOperand->args;
1568 return IC_RESULT (ic);
1571 /*-----------------------------------------------------------------*/
1572 /* geniCodeCast - changes the value from one type to another */
1573 /*-----------------------------------------------------------------*/
1575 geniCodeCast (sym_link * type, operand * op, bool implicit)
1579 sym_link *opetype = getSpec (optype = operandType (op));
1583 /* one of them has size zero then error */
1584 if (IS_VOID (optype))
1586 werror (E_CAST_ZERO);
1590 /* if the operand is already the desired type then do nothing */
1591 if (compareType (type, optype) == 1)
1594 /* if this is a literal then just change the type & return */
1595 if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1596 return operandFromValue (valCastLiteral (type,
1597 operandLitValue (op)));
1599 /* if casting to/from pointers, do some checking */
1600 if (IS_PTR(type)) { // to a pointer
1601 if (!IS_PTR(optype) && !IS_FUNC(optype)) { // from a non pointer
1602 if (IS_INTEGRAL(optype)) {
1603 // maybe this is NULL, than it's ok.
1604 if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
1605 if (IS_GENPTR(type)) {
1606 // no way to set the storage
1607 if (IS_LITERAL(optype)) {
1608 werror(E_LITERAL_GENERIC);
1611 werror(E_NONPTR2_GENPTR);
1614 } else if (implicit) {
1615 werror(W_INTEGRAL2PTR_NOCAST);
1620 // shouldn't do that with float, array or structure unless to void
1621 if (!IS_VOID(getSpec(type)) &&
1622 !(IS_CODEPTR(type) && IS_FUNC(optype))) {
1623 werror(E_INCOMPAT_TYPES);
1627 } else { // from a pointer to a pointer
1628 if (implicit) { // if not to generic, they have to match
1629 if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
1630 werror(E_INCOMPAT_PTYPES);
1635 } else { // to a non pointer
1636 if (IS_PTR(optype)) { // from a pointer
1637 if (implicit) { // sneaky
1638 if (IS_INTEGRAL(type)) {
1639 werror(W_PTR2INTEGRAL_NOCAST);
1641 } else { // shouldn't do that with float, array or structure
1642 werror(E_INCOMPAT_TYPES);
1649 /* fprintf (stderr, "%s%s %d: ", op->operand.symOperand->name,
1650 implicit?"(implicit)":"", errors); */
1651 fprintf (stderr, "from type '");
1652 printTypeChain (optype, stderr);
1653 fprintf (stderr, "' to type '");
1654 printTypeChain (type, stderr);
1655 fprintf (stderr, "'\n");
1658 /* if they are the same size create an assignment */
1659 if (getSize (type) == getSize (optype) &&
1660 !IS_BITFIELD (type) &&
1662 !IS_FLOAT (optype) &&
1663 ((IS_SPEC (type) && IS_SPEC (optype)) ||
1664 (!IS_SPEC (type) && !IS_SPEC (optype))))
1667 ic = newiCode ('=', NULL, op);
1668 IC_RESULT (ic) = newiTempOperand (type, 0);
1669 SPIL_LOC (IC_RESULT (ic)) =
1670 (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
1671 IC_RESULT (ic)->isaddr = 0;
1675 ic = newiCode (CAST, operandFromLink (type),
1676 geniCodeRValue (op, FALSE));
1678 IC_RESULT (ic) = newiTempOperand (type, 0);
1681 /* preserve the storage class & output class */
1682 /* of the original variable */
1683 restype = getSpec (operandType (IC_RESULT (ic)));
1684 SPEC_SCLS (restype) = SPEC_SCLS (opetype);
1685 SPEC_OCLS (restype) = SPEC_OCLS (opetype);
1688 return IC_RESULT (ic);
1691 /*-----------------------------------------------------------------*/
1692 /* geniCodeLabel - will create a Label */
1693 /*-----------------------------------------------------------------*/
1695 geniCodeLabel (symbol * label)
1699 ic = newiCodeLabelGoto (LABEL, label);
1703 /*-----------------------------------------------------------------*/
1704 /* geniCodeGoto - will create a Goto */
1705 /*-----------------------------------------------------------------*/
1707 geniCodeGoto (symbol * label)
1711 ic = newiCodeLabelGoto (GOTO, label);
1715 /*-----------------------------------------------------------------*/
1716 /* geniCodeMultiply - gen intermediate code for multiplication */
1717 /*-----------------------------------------------------------------*/
1719 geniCodeMultiply (operand * left, operand * right,int resultIsInt)
1726 /* if they are both literal then we know the result */
1727 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1728 return operandFromValue (valMult (left->operand.valOperand,
1729 right->operand.valOperand));
1731 if (IS_LITERAL(retype)) {
1732 p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
1735 resType = usualBinaryConversions (&left, &right);
1737 rtype = operandType (right);
1738 retype = getSpec (rtype);
1739 ltype = operandType (left);
1740 letype = getSpec (ltype);
1744 SPEC_NOUN(getSpec(resType))=V_INT;
1747 /* if the right is a literal & power of 2 */
1748 /* then make it a left shift */
1749 /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
1750 efficient in most cases than 2 bytes result = 2 bytes << literal
1751 if port has 1 byte muldiv */
1752 if (p2 && !IS_FLOAT (letype) &&
1753 !((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
1754 (port->support.muldiv == 1)))
1756 if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
1758 /* LEFT_OP need same size for left and result, */
1759 left = geniCodeCast (resType, left, TRUE);
1760 ltype = operandType (left);
1762 ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
1766 ic = newiCode ('*', left, right); /* normal multiplication */
1767 /* if the size left or right > 1 then support routine */
1768 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1772 IC_RESULT (ic) = newiTempOperand (resType, 1);
1775 return IC_RESULT (ic);
1778 /*-----------------------------------------------------------------*/
1779 /* geniCodeDivision - gen intermediate code for division */
1780 /*-----------------------------------------------------------------*/
1782 geniCodeDivision (operand * left, operand * right)
1787 sym_link *rtype = operandType (right);
1788 sym_link *retype = getSpec (rtype);
1789 sym_link *ltype = operandType (left);
1790 sym_link *letype = getSpec (ltype);
1792 resType = usualBinaryConversions (&left, &right);
1794 /* if the right is a literal & power of 2 */
1795 /* then make it a right shift */
1796 if (IS_LITERAL (retype) &&
1797 !IS_FLOAT (letype) &&
1798 (p2 = powof2 ((unsigned long)
1799 floatFromVal (right->operand.valOperand)))) {
1800 ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
1804 ic = newiCode ('/', left, right); /* normal division */
1805 /* if the size left or right > 1 then support routine */
1806 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1809 IC_RESULT (ic) = newiTempOperand (resType, 0);
1812 return IC_RESULT (ic);
1814 /*-----------------------------------------------------------------*/
1815 /* geniCodeModulus - gen intermediate code for modulus */
1816 /*-----------------------------------------------------------------*/
1818 geniCodeModulus (operand * left, operand * right)
1824 /* if they are both literal then we know the result */
1825 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1826 return operandFromValue (valMod (left->operand.valOperand,
1827 right->operand.valOperand));
1829 resType = usualBinaryConversions (&left, &right);
1831 /* now they are the same size */
1832 ic = newiCode ('%', left, right);
1834 /* if the size left or right > 1 then support routine */
1835 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1837 IC_RESULT (ic) = newiTempOperand (resType, 0);
1840 return IC_RESULT (ic);
1843 /*-----------------------------------------------------------------*/
1844 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
1845 /*-----------------------------------------------------------------*/
1847 geniCodePtrPtrSubtract (operand * left, operand * right)
1853 /* if they are both literals then */
1854 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1856 result = operandFromValue (valMinus (left->operand.valOperand,
1857 right->operand.valOperand));
1861 ic = newiCode ('-', left, right);
1863 IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
1867 return geniCodeDivision (result,
1868 operandFromLit (getSize (ltype->next)));
1871 /*-----------------------------------------------------------------*/
1872 /* geniCodeSubtract - generates code for subtraction */
1873 /*-----------------------------------------------------------------*/
1875 geniCodeSubtract (operand * left, operand * right)
1882 /* if they both pointers then */
1883 if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
1884 (IS_PTR (rtype) || IS_ARRAY (rtype)))
1885 return geniCodePtrPtrSubtract (left, right);
1887 /* if they are both literal then we know the result */
1888 if (IS_LITERAL (letype) && IS_LITERAL (retype)
1889 && left->isLiteral && right->isLiteral)
1890 return operandFromValue (valMinus (left->operand.valOperand,
1891 right->operand.valOperand));
1893 /* if left is an array or pointer */
1894 if (IS_PTR (ltype) || IS_ARRAY (ltype))
1896 isarray = left->isaddr;
1897 right = geniCodeMultiply (right,
1898 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
1899 resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
1902 { /* make them the same size */
1903 resType = usualBinaryConversions (&left, &right);
1906 ic = newiCode ('-', left, right);
1908 IC_RESULT (ic) = newiTempOperand (resType, 1);
1909 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
1911 /* if left or right is a float */
1912 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
1916 return IC_RESULT (ic);
1919 /*-----------------------------------------------------------------*/
1920 /* geniCodeAdd - generates iCode for addition */
1921 /*-----------------------------------------------------------------*/
1923 geniCodeAdd (operand * left, operand * right,int lvl)
1931 /* if left is an array then array access */
1932 if (IS_ARRAY (ltype))
1933 return geniCodeArray (left, right,lvl);
1935 /* if the right side is LITERAL zero */
1936 /* return the left side */
1937 if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
1940 /* if left is literal zero return right */
1941 if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
1944 /* if left is an array or pointer then size */
1947 isarray = left->isaddr;
1948 // there is no need to multiply with 1
1949 if (getSize(ltype->next)!=1) {
1950 size = operandFromLit (getSize (ltype->next));
1951 right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
1953 resType = copyLinkChain (ltype);
1956 { /* make them the same size */
1957 resType = usualBinaryConversions (&left, &right);
1960 /* if they are both literals then we know */
1961 if (IS_LITERAL (letype) && IS_LITERAL (retype)
1962 && left->isLiteral && right->isLiteral)
1963 return operandFromValue (valPlus (valFromType (letype),
1964 valFromType (retype)));
1966 ic = newiCode ('+', left, right);
1968 IC_RESULT (ic) = newiTempOperand (resType, 1);
1969 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
1971 /* if left or right is a float then support
1973 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
1978 return IC_RESULT (ic);
1982 /*-----------------------------------------------------------------*/
1983 /* aggrToPtr - changes an aggregate to pointer to an aggregate */
1984 /*-----------------------------------------------------------------*/
1986 aggrToPtr (sym_link * type, bool force)
1992 if (IS_PTR (type) && !force)
1995 etype = getSpec (type);
1999 /* if the output class is generic */
2000 if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER)
2001 DCL_PTR_CONST (ptype) = port->mem.code_ro;
2003 /* if the variable was declared a constant */
2004 /* then the pointer points to a constant */
2005 if (IS_CONSTANT (etype))
2006 DCL_PTR_CONST (ptype) = 1;
2008 /* the variable was volatile then pointer to volatile */
2009 if (IS_VOLATILE (etype))
2010 DCL_PTR_VOLATILE (ptype) = 1;
2014 /*-----------------------------------------------------------------*/
2015 /* geniCodeArray2Ptr - array to pointer */
2016 /*-----------------------------------------------------------------*/
2018 geniCodeArray2Ptr (operand * op)
2020 sym_link *optype = operandType (op);
2021 sym_link *opetype = getSpec (optype);
2023 /* set the pointer depending on the storage class */
2024 if ((DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2025 DCL_PTR_CONST (optype) = port->mem.code_ro;
2028 /* if the variable was declared a constant */
2029 /* then the pointer points to a constant */
2030 if (IS_CONSTANT (opetype))
2031 DCL_PTR_CONST (optype) = 1;
2033 /* the variable was volatile then pointer to volatile */
2034 if (IS_VOLATILE (opetype))
2035 DCL_PTR_VOLATILE (optype) = 1;
2041 /*-----------------------------------------------------------------*/
2042 /* geniCodeArray - array access */
2043 /*-----------------------------------------------------------------*/
2045 geniCodeArray (operand * left, operand * right,int lvl)
2048 sym_link *ltype = operandType (left);
2052 if (IS_PTR (ltype->next) && left->isaddr)
2054 left = geniCodeRValue (left, FALSE);
2056 return geniCodeDerefPtr (geniCodeAdd (left, right,lvl),lvl);
2059 right = geniCodeMultiply (right,
2060 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2062 /* we can check for limits here */
2063 if (isOperandLiteral (right) &&
2066 (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2068 werror (E_ARRAY_BOUND);
2069 right = operandFromLit (0);
2072 ic = newiCode ('+', left, right);
2074 IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2075 !IS_AGGREGATE (ltype->next) &&
2076 !IS_PTR (ltype->next))
2077 ? ltype : ltype->next), 0);
2079 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
2081 return IC_RESULT (ic);
2084 /*-----------------------------------------------------------------*/
2085 /* geniCodeStruct - generates intermediate code for structres */
2086 /*-----------------------------------------------------------------*/
2088 geniCodeStruct (operand * left, operand * right, bool islval)
2091 sym_link *type = operandType (left);
2092 sym_link *etype = getSpec (type);
2094 symbol *element = getStructElement (SPEC_STRUCT (etype),
2095 right->operand.symOperand);
2097 /* add the offset */
2098 ic = newiCode ('+', left, operandFromLit (element->offset));
2100 IC_RESULT (ic) = newiTempOperand (element->type, 0);
2102 /* preserve the storage & output class of the struct */
2103 /* as well as the volatile attribute */
2104 retype = getSpec (operandType (IC_RESULT (ic)));
2105 SPEC_SCLS (retype) = SPEC_SCLS (etype);
2106 SPEC_OCLS (retype) = SPEC_OCLS (etype);
2107 SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2109 if (IS_PTR (element->type))
2110 setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2112 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2116 return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2119 /*-----------------------------------------------------------------*/
2120 /* geniCodePostInc - generate int code for Post increment */
2121 /*-----------------------------------------------------------------*/
2123 geniCodePostInc (operand * op)
2127 sym_link *optype = operandType (op);
2129 operand *rv = (IS_ITEMP (op) ?
2130 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2132 sym_link *rvtype = operandType (rv);
2135 /* if this is not an address we have trouble */
2138 werror (E_LVALUE_REQUIRED, "++");
2142 rOp = newiTempOperand (rvtype, 0);
2143 OP_SYMBOL(rOp)->noSpilLoc = 1;
2146 OP_SYMBOL(rv)->noSpilLoc = 1;
2148 geniCodeAssign (rOp, rv, 0);
2150 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2151 if (IS_FLOAT (rvtype))
2152 ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2154 ic = newiCode ('+', rv, operandFromLit (size));
2156 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2159 geniCodeAssign (op, result, 0);
2165 /*-----------------------------------------------------------------*/
2166 /* geniCodePreInc - generate code for preIncrement */
2167 /*-----------------------------------------------------------------*/
2169 geniCodePreInc (operand * op)
2172 sym_link *optype = operandType (op);
2173 operand *rop = (IS_ITEMP (op) ?
2174 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2176 sym_link *roptype = operandType (rop);
2182 werror (E_LVALUE_REQUIRED, "++");
2187 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2188 if (IS_FLOAT (roptype))
2189 ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2191 ic = newiCode ('+', rop, operandFromLit (size));
2192 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2196 return geniCodeAssign (op, result, 0);
2199 /*-----------------------------------------------------------------*/
2200 /* geniCodePostDec - generates code for Post decrement */
2201 /*-----------------------------------------------------------------*/
2203 geniCodePostDec (operand * op)
2207 sym_link *optype = operandType (op);
2209 operand *rv = (IS_ITEMP (op) ?
2210 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2212 sym_link *rvtype = operandType (rv);
2215 /* if this is not an address we have trouble */
2218 werror (E_LVALUE_REQUIRED, "--");
2222 rOp = newiTempOperand (rvtype, 0);
2223 OP_SYMBOL(rOp)->noSpilLoc = 1;
2226 OP_SYMBOL(rv)->noSpilLoc = 1;
2228 geniCodeAssign (rOp, rv, 0);
2230 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2231 if (IS_FLOAT (rvtype))
2232 ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2234 ic = newiCode ('-', rv, operandFromLit (size));
2236 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2239 geniCodeAssign (op, result, 0);
2245 /*-----------------------------------------------------------------*/
2246 /* geniCodePreDec - generate code for pre decrement */
2247 /*-----------------------------------------------------------------*/
2249 geniCodePreDec (operand * op)
2252 sym_link *optype = operandType (op);
2253 operand *rop = (IS_ITEMP (op) ?
2254 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2256 sym_link *roptype = operandType (rop);
2262 werror (E_LVALUE_REQUIRED, "--");
2267 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2268 if (IS_FLOAT (roptype))
2269 ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2271 ic = newiCode ('-', rop, operandFromLit (size));
2272 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2276 return geniCodeAssign (op, result, 0);
2280 /*-----------------------------------------------------------------*/
2281 /* geniCodeBitwise - gen int code for bitWise operators */
2282 /*-----------------------------------------------------------------*/
2284 geniCodeBitwise (operand * left, operand * right,
2285 int oper, sym_link * resType)
2289 left = geniCodeCast (resType, left, TRUE);
2290 right = geniCodeCast (resType, right, TRUE);
2292 ic = newiCode (oper, left, right);
2293 IC_RESULT (ic) = newiTempOperand (resType, 0);
2296 return IC_RESULT (ic);
2299 /*-----------------------------------------------------------------*/
2300 /* geniCodeAddressOf - gens icode for '&' address of operator */
2301 /*-----------------------------------------------------------------*/
2303 geniCodeAddressOf (operand * op)
2307 sym_link *optype = operandType (op);
2308 sym_link *opetype = getSpec (optype);
2310 /* lvalue check already done in decorateType */
2311 /* this must be a lvalue */
2312 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2313 /* werror (E_LVALUE_REQUIRED,"&"); */
2318 p->class = DECLARATOR;
2320 /* set the pointer depending on the storage class */
2321 if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2322 DCL_PTR_CONST (p) = port->mem.code_ro;
2324 /* make sure we preserve the const & volatile */
2325 if (IS_CONSTANT (opetype))
2326 DCL_PTR_CONST (p) = 1;
2328 if (IS_VOLATILE (opetype))
2329 DCL_PTR_VOLATILE (p) = 1;
2331 p->next = copyLinkChain (optype);
2333 /* if already a temp */
2336 setOperandType (op, p);
2341 /* other wise make this of the type coming in */
2342 ic = newiCode (ADDRESS_OF, op, NULL);
2343 IC_RESULT (ic) = newiTempOperand (p, 1);
2344 IC_RESULT (ic)->isaddr = 0;
2346 return IC_RESULT (ic);
2348 /*-----------------------------------------------------------------*/
2349 /* setOClass - sets the output class depending on the pointer type */
2350 /*-----------------------------------------------------------------*/
2352 setOClass (sym_link * ptr, sym_link * spec)
2354 switch (DCL_TYPE (ptr))
2357 SPEC_OCLS (spec) = data;
2361 SPEC_OCLS (spec) = generic;
2365 SPEC_OCLS (spec) = xdata;
2369 SPEC_OCLS (spec) = code;
2373 SPEC_OCLS (spec) = idata;
2377 SPEC_OCLS (spec) = xstack;
2381 SPEC_OCLS (spec) = eeprom;
2390 /*-----------------------------------------------------------------*/
2391 /* geniCodeDerefPtr - dereference pointer with '*' */
2392 /*-----------------------------------------------------------------*/
2394 geniCodeDerefPtr (operand * op,int lvl)
2396 sym_link *rtype, *retype;
2397 sym_link *optype = operandType (op);
2399 /* if this is a pointer then generate the rvalue */
2400 if (IS_PTR (optype))
2402 if (IS_TRUE_SYMOP (op))
2405 op = geniCodeRValue (op, TRUE);
2408 op = geniCodeRValue (op, TRUE);
2411 /* now get rid of the pointer part */
2412 if (isLvaluereq(lvl) && IS_ITEMP (op))
2414 retype = getSpec (rtype = copyLinkChain (optype));
2418 retype = getSpec (rtype = copyLinkChain (optype->next));
2421 /* if this is a pointer then outputclass needs 2b updated */
2422 if (IS_PTR (optype))
2423 setOClass (optype, retype);
2425 op->isGptr = IS_GENPTR (optype);
2427 /* if the pointer was declared as a constant */
2428 /* then we cannot allow assignment to the derefed */
2429 if (IS_PTR_CONST (optype))
2430 SPEC_CONST (retype) = 1;
2432 op->isaddr = (IS_PTR (rtype) ||
2433 IS_STRUCT (rtype) ||
2438 if (!isLvaluereq(lvl))
2439 op = geniCodeRValue (op, TRUE);
2441 setOperandType (op, rtype);
2446 /*-----------------------------------------------------------------*/
2447 /* geniCodeUnaryMinus - does a unary minus of the operand */
2448 /*-----------------------------------------------------------------*/
2450 geniCodeUnaryMinus (operand * op)
2453 sym_link *optype = operandType (op);
2455 if (IS_LITERAL (optype))
2456 return operandFromLit (-floatFromVal (op->operand.valOperand));
2458 ic = newiCode (UNARYMINUS, op, NULL);
2459 IC_RESULT (ic) = newiTempOperand (optype, 0);
2461 return IC_RESULT (ic);
2464 /*-----------------------------------------------------------------*/
2465 /* geniCodeLeftShift - gen i code for left shift */
2466 /*-----------------------------------------------------------------*/
2468 geniCodeLeftShift (operand * left, operand * right)
2472 ic = newiCode (LEFT_OP, left, right);
2473 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2475 return IC_RESULT (ic);
2478 /*-----------------------------------------------------------------*/
2479 /* geniCodeRightShift - gen i code for right shift */
2480 /*-----------------------------------------------------------------*/
2482 geniCodeRightShift (operand * left, operand * right)
2486 ic = newiCode (RIGHT_OP, left, right);
2487 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2489 return IC_RESULT (ic);
2492 /*-----------------------------------------------------------------*/
2493 /* geniCodeLogic- logic code */
2494 /*-----------------------------------------------------------------*/
2496 geniCodeLogic (operand * left, operand * right, int op)
2500 sym_link *rtype = operandType (right);
2501 sym_link *ltype = operandType (left);
2503 /* left is integral type and right is literal then
2504 check if the literal value is within bounds */
2505 if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2507 checkConstantRange(ltype,
2508 operandLitValue(right), "compare operation", 1);
2511 ctype = usualBinaryConversions (&left, &right);
2513 ic = newiCode (op, left, right);
2514 IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2516 /* if comparing float
2517 and not a '==' || '!=' || '&&' || '||' (these
2519 if (IS_FLOAT(ctype) &&
2527 return IC_RESULT (ic);
2530 /*-----------------------------------------------------------------*/
2531 /* geniCodeUnary - for a a generic unary operation */
2532 /*-----------------------------------------------------------------*/
2534 geniCodeUnary (operand * op, int oper)
2536 iCode *ic = newiCode (oper, op, NULL);
2538 IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2540 return IC_RESULT (ic);
2543 /*-----------------------------------------------------------------*/
2544 /* geniCodeConditional - geniCode for '?' ':' operation */
2545 /*-----------------------------------------------------------------*/
2547 geniCodeConditional (ast * tree,int lvl)
2550 symbol *falseLabel = newiTempLabel (NULL);
2551 symbol *exitLabel = newiTempLabel (NULL);
2552 operand *cond = ast2iCode (tree->left,lvl+1);
2553 operand *true, *false, *result;
2555 ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
2559 true = ast2iCode (tree->right->left,lvl+1);
2561 /* move the value to a new Operand */
2562 result = newiTempOperand (operandType (true), 0);
2563 geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
2565 /* generate an unconditional goto */
2566 geniCodeGoto (exitLabel);
2568 /* now for the right side */
2569 geniCodeLabel (falseLabel);
2571 false = ast2iCode (tree->right->right,lvl+1);
2572 geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
2574 /* create the exit label */
2575 geniCodeLabel (exitLabel);
2580 /*-----------------------------------------------------------------*/
2581 /* geniCodeAssign - generate code for assignment */
2582 /*-----------------------------------------------------------------*/
2584 geniCodeAssign (operand * left, operand * right, int nosupdate)
2587 sym_link *ltype = operandType (left);
2588 sym_link *rtype = operandType (right);
2590 if (!left->isaddr && !IS_ITEMP (left))
2592 werror (E_LVALUE_REQUIRED, "assignment");
2596 /* left is integral type and right is literal then
2597 check if the literal value is within bounds */
2598 if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
2600 checkConstantRange(ltype,
2601 operandLitValue(right), "= operation", 0);
2604 /* if the left & right type don't exactly match */
2605 /* if pointer set then make sure the check is
2606 done with the type & not the pointer */
2607 /* then cast rights type to left */
2609 /* first check the type for pointer assignement */
2610 if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
2611 compareType (ltype, rtype) < 0)
2613 if (compareType (ltype->next, rtype) < 0)
2614 right = geniCodeCast (ltype->next, right, TRUE);
2616 else if (compareType (ltype, rtype) < 0)
2617 right = geniCodeCast (ltype, right, TRUE);
2619 /* if left is a true symbol & ! volatile
2620 create an assignment to temporary for
2621 the right & then assign this temporary
2622 to the symbol this is SSA . isn't it simple
2623 and folks have published mountains of paper on it */
2624 if (IS_TRUE_SYMOP (left) &&
2625 !isOperandVolatile (left, FALSE) &&
2626 isOperandGlobal (left))
2630 if (IS_TRUE_SYMOP (right))
2631 sym = OP_SYMBOL (right);
2632 ic = newiCode ('=', NULL, right);
2633 IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
2634 SPIL_LOC (right) = sym;
2638 ic = newiCode ('=', NULL, right);
2639 IC_RESULT (ic) = left;
2642 /* if left isgptr flag is set then support
2643 routine will be required */
2647 ic->nosupdate = nosupdate;
2651 /*-----------------------------------------------------------------*/
2652 /* geniCodeSEParms - generate code for side effecting fcalls */
2653 /*-----------------------------------------------------------------*/
2655 geniCodeSEParms (ast * parms,int lvl)
2660 if (parms->type == EX_OP && parms->opval.op == PARAM)
2662 geniCodeSEParms (parms->left,lvl);
2663 geniCodeSEParms (parms->right,lvl);
2667 /* hack don't like this but too lazy to think of
2669 if (IS_ADDRESS_OF_OP (parms))
2670 parms->left->lvalue = 1;
2672 if (IS_CAST_OP (parms) &&
2673 IS_PTR (parms->ftype) &&
2674 IS_ADDRESS_OF_OP (parms->right))
2675 parms->right->left->lvalue = 1;
2677 parms->opval.oprnd =
2678 geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2680 parms->type = EX_OPERAND;
2683 /*-----------------------------------------------------------------*/
2684 /* geniCodeParms - generates parameters */
2685 /*-----------------------------------------------------------------*/
2687 geniCodeParms (ast * parms, int *stack, sym_link * fetype, symbol * func,int lvl)
2695 /* if this is a param node then do the left & right */
2696 if (parms->type == EX_OP && parms->opval.op == PARAM)
2698 geniCodeParms (parms->left, stack, fetype, func,lvl);
2699 geniCodeParms (parms->right, stack, fetype, func,lvl);
2703 /* get the parameter value */
2704 if (parms->type == EX_OPERAND)
2705 pval = parms->opval.oprnd;
2708 /* maybe this else should go away ?? */
2709 /* hack don't like this but too lazy to think of
2711 if (IS_ADDRESS_OF_OP (parms))
2712 parms->left->lvalue = 1;
2714 if (IS_CAST_OP (parms) &&
2715 IS_PTR (parms->ftype) &&
2716 IS_ADDRESS_OF_OP (parms->right))
2717 parms->right->left->lvalue = 1;
2719 pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2722 /* if register parm then make it a send */
2723 if (((parms->argSym && IS_REGPARM (parms->argSym->etype)) ||
2724 IS_REGPARM (parms->etype)) && !func->hasVargs)
2726 ic = newiCode (SEND, pval, NULL);
2731 /* now decide whether to push or assign */
2732 if (!(options.stackAuto || IS_RENT (fetype)))
2736 operand *top = operandFromSymbol (parms->argSym);
2737 geniCodeAssign (top, pval, 1);
2741 sym_link *p = operandType (pval);
2743 ic = newiCode (IPUSH, pval, NULL);
2745 /* update the stack adjustment */
2746 *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2753 /*-----------------------------------------------------------------*/
2754 /* geniCodeCall - generates temp code for calling */
2755 /*-----------------------------------------------------------------*/
2757 geniCodeCall (operand * left, ast * parms,int lvl)
2761 sym_link *type, *etype;
2764 if (!IS_FUNC(OP_SYMBOL(left)->type) &&
2765 !IS_CODEPTR(OP_SYMBOL(left)->type)) {
2766 werror (E_FUNCTION_EXPECTED);
2770 /* take care of parameters with side-effecting
2771 function calls in them, this is required to take care
2772 of overlaying function parameters */
2773 geniCodeSEParms (parms,lvl);
2775 /* first the parameters */
2776 geniCodeParms (parms, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
2778 /* now call : if symbol then pcall */
2779 if (IS_OP_POINTER (left) || IS_ITEMP(left))
2780 ic = newiCode (PCALL, left, NULL);
2782 ic = newiCode (CALL, left, NULL);
2784 IC_ARGS (ic) = left->operand.symOperand->args;
2785 type = copyLinkChain (operandType (left)->next);
2786 etype = getSpec (type);
2787 SPEC_EXTR (etype) = 0;
2788 IC_RESULT (ic) = result = newiTempOperand (type, 1);
2792 /* stack adjustment after call */
2793 ic->parmBytes = stack;
2798 /*-----------------------------------------------------------------*/
2799 /* geniCodeReceive - generate intermediate code for "receive" */
2800 /*-----------------------------------------------------------------*/
2802 geniCodeReceive (value * args)
2804 /* for all arguments that are passed in registers */
2808 if (IS_REGPARM (args->etype))
2810 operand *opr = operandFromValue (args);
2812 symbol *sym = OP_SYMBOL (opr);
2815 /* we will use it after all optimizations
2816 and before liveRange calculation */
2817 if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
2820 if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
2821 options.stackAuto == 0 &&
2822 /* !TARGET_IS_DS390) */
2823 (!(options.model == MODEL_FLAT24)) )
2828 opl = newiTempOperand (args->type, 0);
2830 sym->reqv->key = sym->key;
2831 OP_SYMBOL (sym->reqv)->key = sym->key;
2832 OP_SYMBOL (sym->reqv)->isreqv = 1;
2833 OP_SYMBOL (sym->reqv)->islocal = 0;
2834 SPIL_LOC (sym->reqv) = sym;
2838 ic = newiCode (RECEIVE, NULL, NULL);
2839 currFunc->recvSize = getSize (sym->etype);
2840 IC_RESULT (ic) = opr;
2848 /*-----------------------------------------------------------------*/
2849 /* geniCodeFunctionBody - create the function body */
2850 /*-----------------------------------------------------------------*/
2852 geniCodeFunctionBody (ast * tree,int lvl)
2859 /* reset the auto generation */
2865 func = ast2iCode (tree->left,lvl+1);
2866 fetype = getSpec (operandType (func));
2868 savelineno = lineno;
2869 lineno = OP_SYMBOL (func)->lineDef;
2870 /* create an entry label */
2871 geniCodeLabel (entryLabel);
2872 lineno = savelineno;
2874 /* create a proc icode */
2875 ic = newiCode (FUNCTION, func, NULL);
2876 /* if the function has parmas then */
2877 /* save the parameters information */
2878 ic->argLabel.args = tree->values.args;
2879 ic->lineno = OP_SYMBOL (func)->lineDef;
2883 /* for all parameters that are passed
2884 on registers add a "receive" */
2885 geniCodeReceive (tree->values.args);
2887 /* generate code for the body */
2888 ast2iCode (tree->right,lvl+1);
2890 /* create a label for return */
2891 geniCodeLabel (returnLabel);
2893 /* now generate the end proc */
2894 ic = newiCode (ENDFUNCTION, func, NULL);
2899 /*-----------------------------------------------------------------*/
2900 /* geniCodeReturn - gen icode for 'return' statement */
2901 /*-----------------------------------------------------------------*/
2903 geniCodeReturn (operand * op)
2907 /* if the operand is present force an rvalue */
2909 op = geniCodeRValue (op, FALSE);
2911 ic = newiCode (RETURN, op, NULL);
2915 /*-----------------------------------------------------------------*/
2916 /* geniCodeIfx - generates code for extended if statement */
2917 /*-----------------------------------------------------------------*/
2919 geniCodeIfx (ast * tree,int lvl)
2922 operand *condition = ast2iCode (tree->left,lvl+1);
2925 /* if condition is null then exit */
2929 condition = geniCodeRValue (condition, FALSE);
2931 cetype = getSpec (operandType (condition));
2932 /* if the condition is a literal */
2933 if (IS_LITERAL (cetype))
2935 if (floatFromVal (condition->operand.valOperand))
2937 if (tree->trueLabel)
2938 geniCodeGoto (tree->trueLabel);
2944 if (tree->falseLabel)
2945 geniCodeGoto (tree->falseLabel);
2952 if (tree->trueLabel)
2954 ic = newiCodeCondition (condition,
2959 if (tree->falseLabel)
2960 geniCodeGoto (tree->falseLabel);
2964 ic = newiCodeCondition (condition,
2971 ast2iCode (tree->right,lvl+1);
2974 /*-----------------------------------------------------------------*/
2975 /* geniCodeJumpTable - tries to create a jump table for switch */
2976 /*-----------------------------------------------------------------*/
2978 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
2980 int min = 0, max = 0, t, cnt = 0;
2987 if (!tree || !caseVals)
2990 /* the criteria for creating a jump table is */
2991 /* all integer numbers between the maximum & minimum must */
2992 /* be present , the maximum value should not exceed 255 */
2993 min = max = (int) floatFromVal (vch = caseVals);
2994 sprintf (buffer, "_case_%d_%d",
2995 tree->values.switchVals.swNum,
2997 addSet (&labels, newiTempLabel (buffer));
2999 /* if there is only one case value then no need */
3000 if (!(vch = vch->next))
3005 if (((t = (int) floatFromVal (vch)) - max) != 1)
3007 sprintf (buffer, "_case_%d_%d",
3008 tree->values.switchVals.swNum,
3010 addSet (&labels, newiTempLabel (buffer));
3016 /* if the number of case statements <= 2 then */
3017 /* it is not economical to create the jump table */
3018 /* since two compares are needed for boundary conditions */
3019 if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
3022 if (tree->values.switchVals.swDefault)
3023 sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3025 sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3027 falseLabel = newiTempLabel (buffer);
3029 /* so we can create a jumptable */
3030 /* first we rule out the boundary conditions */
3031 /* if only optimization says so */
3032 if (!optimize.noJTabBoundary)
3034 sym_link *cetype = getSpec (operandType (cond));
3035 /* no need to check the lower bound if
3036 the condition is unsigned & minimum value is zero */
3037 if (!(min == 0 && SPEC_USIGN (cetype)))
3039 boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3040 ic = newiCodeCondition (boundary, falseLabel, NULL);
3044 /* now for upper bounds */
3045 boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3046 ic = newiCodeCondition (boundary, falseLabel, NULL);
3050 /* if the min is not zero then we no make it zero */
3053 cond = geniCodeSubtract (cond, operandFromLit (min));
3054 setOperandType (cond, UCHARTYPE);
3057 /* now create the jumptable */
3058 ic = newiCode (JUMPTABLE, NULL, NULL);
3059 IC_JTCOND (ic) = cond;
3060 IC_JTLABELS (ic) = labels;
3065 /*-----------------------------------------------------------------*/
3066 /* geniCodeSwitch - changes a switch to a if statement */
3067 /*-----------------------------------------------------------------*/
3069 geniCodeSwitch (ast * tree,int lvl)
3072 operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3073 value *caseVals = tree->values.switchVals.swVals;
3074 symbol *trueLabel, *falseLabel;
3076 /* if we can make this a jump table */
3077 if (geniCodeJumpTable (cond, caseVals, tree))
3078 goto jumpTable; /* no need for the comparison */
3080 /* for the cases defined do */
3084 operand *compare = geniCodeLogic (cond,
3085 operandFromValue (caseVals),
3088 sprintf (buffer, "_case_%d_%d",
3089 tree->values.switchVals.swNum,
3090 (int) floatFromVal (caseVals));
3091 trueLabel = newiTempLabel (buffer);
3093 ic = newiCodeCondition (compare, trueLabel, NULL);
3095 caseVals = caseVals->next;
3100 /* if default is present then goto break else break */
3101 if (tree->values.switchVals.swDefault)
3102 sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3104 sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3106 falseLabel = newiTempLabel (buffer);
3107 geniCodeGoto (falseLabel);
3110 ast2iCode (tree->right,lvl+1);
3113 /*-----------------------------------------------------------------*/
3114 /* geniCodeInline - intermediate code for inline assembler */
3115 /*-----------------------------------------------------------------*/
3117 geniCodeInline (ast * tree)
3121 ic = newiCode (INLINEASM, NULL, NULL);
3122 IC_INLINE (ic) = tree->values.inlineasm;
3126 /*-----------------------------------------------------------------*/
3127 /* geniCodeArrayInit - intermediate code for array initializer */
3128 /*-----------------------------------------------------------------*/
3130 geniCodeArrayInit (ast * tree, operand *array)
3134 if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3135 ic = newiCode (ARRAYINIT, array, NULL);
3136 IC_ARRAYILIST (ic) = tree->values.constlist;
3138 operand *left=newOperand(), *right=newOperand();
3139 left->type=right->type=SYMBOL;
3140 OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3141 OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3142 ic = newiCode (ARRAYINIT, left, right);
3147 /*-----------------------------------------------------------------*/
3148 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
3149 /* particular case. Ie : assigning or dereferencing array or ptr */
3150 /*-----------------------------------------------------------------*/
3151 set * lvaluereqSet = NULL;
3152 typedef struct lvalItem
3159 /*-----------------------------------------------------------------*/
3160 /* addLvaluereq - add a flag for lvalreq for current ast level */
3161 /*-----------------------------------------------------------------*/
3162 void addLvaluereq(int lvl)
3164 lvalItem * lpItem = (lvalItem *)Safe_calloc (1, sizeof (lvalItem));
3167 addSetHead(&lvaluereqSet,lpItem);
3170 /*-----------------------------------------------------------------*/
3171 /* delLvaluereq - del a flag for lvalreq for current ast level */
3172 /*-----------------------------------------------------------------*/
3176 lpItem = getSet(&lvaluereqSet);
3177 if(lpItem) free(lpItem);
3179 /*-----------------------------------------------------------------*/
3180 /* clearLvaluereq - clear lvalreq flag */
3181 /*-----------------------------------------------------------------*/
3182 void clearLvaluereq()
3185 lpItem = peekSet(lvaluereqSet);
3186 if(lpItem) lpItem->req = 0;
3188 /*-----------------------------------------------------------------*/
3189 /* getLvaluereq - get the last lvalreq level */
3190 /*-----------------------------------------------------------------*/
3191 int getLvaluereqLvl()
3194 lpItem = peekSet(lvaluereqSet);
3195 if(lpItem) return lpItem->lvl;
3198 /*-----------------------------------------------------------------*/
3199 /* isLvaluereq - is lvalreq valid for this level ? */
3200 /*-----------------------------------------------------------------*/
3201 int isLvaluereq(int lvl)
3204 lpItem = peekSet(lvaluereqSet);
3205 if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3209 /*-----------------------------------------------------------------*/
3210 /* ast2iCode - creates an icodeList from an ast */
3211 /*-----------------------------------------------------------------*/
3213 ast2iCode (ast * tree,int lvl)
3215 operand *left = NULL;
3216 operand *right = NULL;
3219 /* set the global variables for filename & line number */
3221 filename = tree->filename;
3223 lineno = tree->lineno;
3225 block = tree->block;
3227 scopeLevel = tree->level;
3229 if (tree->type == EX_VALUE)
3230 return operandFromValue (tree->opval.val);
3232 if (tree->type == EX_LINK)
3233 return operandFromLink (tree->opval.lnk);
3235 /* if we find a nullop */
3236 if (tree->type == EX_OP &&
3237 (tree->opval.op == NULLOP ||
3238 tree->opval.op == BLOCK))
3240 ast2iCode (tree->left,lvl+1);
3241 ast2iCode (tree->right,lvl+1);
3245 /* special cases for not evaluating */
3246 if (tree->opval.op != ':' &&
3247 tree->opval.op != '?' &&
3248 tree->opval.op != CALL &&
3249 tree->opval.op != IFX &&
3250 tree->opval.op != LABEL &&
3251 tree->opval.op != GOTO &&
3252 tree->opval.op != SWITCH &&
3253 tree->opval.op != FUNCTION &&
3254 tree->opval.op != INLINEASM)
3257 if (IS_ASSIGN_OP (tree->opval.op) ||
3258 IS_DEREF_OP (tree) ||
3259 (tree->opval.op == '&' && !tree->right) ||
3260 tree->opval.op == PTR_OP)
3263 if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3264 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3267 left = operandFromAst (tree->left,lvl);
3269 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3270 left = geniCodeRValue (left, TRUE);
3274 left = operandFromAst (tree->left,lvl);
3276 if (tree->opval.op == INC_OP ||
3277 tree->opval.op == DEC_OP)
3280 right = operandFromAst (tree->right,lvl);
3285 right = operandFromAst (tree->right,lvl);
3289 /* now depending on the type of operand */
3290 /* this will be a biggy */
3291 switch (tree->opval.op)
3294 case '[': /* array operation */
3296 sym_link *ltype = operandType (left);
3297 left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3298 right = geniCodeRValue (right, TRUE);
3301 return geniCodeArray (left, right,lvl);
3303 case '.': /* structure dereference */
3304 if (IS_PTR (operandType (left)))
3305 left = geniCodeRValue (left, TRUE);
3307 left = geniCodeRValue (left, FALSE);
3309 return geniCodeStruct (left, right, tree->lvalue);
3311 case PTR_OP: /* structure pointer dereference */
3314 pType = operandType (left);
3315 left = geniCodeRValue (left, TRUE);
3317 setOClass (pType, getSpec (operandType (left)));
3320 return geniCodeStruct (left, right, tree->lvalue);
3322 case INC_OP: /* increment operator */
3324 return geniCodePostInc (left);
3326 return geniCodePreInc (right);
3328 case DEC_OP: /* decrement operator */
3330 return geniCodePostDec (left);
3332 return geniCodePreDec (right);
3334 case '&': /* bitwise and or address of operator */
3336 { /* this is a bitwise operator */
3337 left = geniCodeRValue (left, FALSE);
3338 right = geniCodeRValue (right, FALSE);
3339 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3342 return geniCodeAddressOf (left);
3344 case '|': /* bitwise or & xor */
3346 return geniCodeBitwise (geniCodeRValue (left, FALSE),
3347 geniCodeRValue (right, FALSE),
3352 return geniCodeDivision (geniCodeRValue (left, FALSE),
3353 geniCodeRValue (right, FALSE));
3356 return geniCodeModulus (geniCodeRValue (left, FALSE),
3357 geniCodeRValue (right, FALSE));
3360 return geniCodeMultiply (geniCodeRValue (left, FALSE),
3361 geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3363 return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3367 return geniCodeSubtract (geniCodeRValue (left, FALSE),
3368 geniCodeRValue (right, FALSE));
3370 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3374 return geniCodeAdd (geniCodeRValue (left, FALSE),
3375 geniCodeRValue (right, FALSE),lvl);
3377 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
3380 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3381 geniCodeRValue (right, FALSE));
3384 return geniCodeRightShift (geniCodeRValue (left, FALSE),
3385 geniCodeRValue (right, FALSE));
3387 return geniCodeCast (operandType (left),
3388 geniCodeRValue (right, FALSE), FALSE);
3394 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3398 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3399 setOperandType (op, UCHARTYPE);
3410 return geniCodeLogic (geniCodeRValue (left, FALSE),
3411 geniCodeRValue (right, FALSE),
3414 return geniCodeConditional (tree,lvl);
3417 return operandFromLit (getSize (tree->right->ftype));
3421 sym_link *rtype = operandType (right);
3422 sym_link *ltype = operandType (left);
3423 if (IS_PTR (rtype) && IS_ITEMP (right)
3424 && right->isaddr && compareType (rtype->next, ltype) == 1)
3425 right = geniCodeRValue (right, TRUE);
3427 right = geniCodeRValue (right, FALSE);
3429 geniCodeAssign (left, right, 0);
3434 geniCodeAssign (left,
3435 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3437 geniCodeRValue (right, FALSE),FALSE), 0);
3441 geniCodeAssign (left,
3442 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3444 geniCodeRValue (right, FALSE)), 0);
3447 geniCodeAssign (left,
3448 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3450 geniCodeRValue (right, FALSE)), 0);
3453 sym_link *rtype = operandType (right);
3454 sym_link *ltype = operandType (left);
3455 if (IS_PTR (rtype) && IS_ITEMP (right)
3456 && right->isaddr && compareType (rtype->next, ltype) == 1)
3457 right = geniCodeRValue (right, TRUE);
3459 right = geniCodeRValue (right, FALSE);
3462 return geniCodeAssign (left,
3463 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3469 sym_link *rtype = operandType (right);
3470 sym_link *ltype = operandType (left);
3471 if (IS_PTR (rtype) && IS_ITEMP (right)
3472 && right->isaddr && compareType (rtype->next, ltype) == 1)
3474 right = geniCodeRValue (right, TRUE);
3478 right = geniCodeRValue (right, FALSE);
3481 geniCodeAssign (left,
3482 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3488 geniCodeAssign (left,
3489 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3491 geniCodeRValue (right, FALSE)), 0);
3494 geniCodeAssign (left,
3495 geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3497 geniCodeRValue (right, FALSE)), 0);
3500 geniCodeAssign (left,
3501 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3503 geniCodeRValue (right, FALSE),
3505 operandType (left)), 0);
3508 geniCodeAssign (left,
3509 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3511 geniCodeRValue (right, FALSE),
3513 operandType (left)), 0);
3516 geniCodeAssign (left,
3517 geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3519 geniCodeRValue (right, FALSE),
3521 operandType (left)), 0);
3523 return geniCodeRValue (right, FALSE);
3526 return geniCodeCall (ast2iCode (tree->left,lvl+1),
3529 geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3530 return ast2iCode (tree->right,lvl+1);
3533 geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3534 return ast2iCode (tree->right,lvl+1);
3537 geniCodeFunctionBody (tree,lvl);
3541 geniCodeReturn (right);
3545 geniCodeIfx (tree,lvl);
3549 geniCodeSwitch (tree,lvl);
3553 geniCodeInline (tree);
3557 geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
3564 /*-----------------------------------------------------------------*/
3565 /* reverseICChain - gets from the list and creates a linkedlist */
3566 /*-----------------------------------------------------------------*/
3573 while ((loop = getSet (&iCodeChain)))
3585 /*-----------------------------------------------------------------*/
3586 /* iCodeFromAst - given an ast will convert it to iCode */
3587 /*-----------------------------------------------------------------*/
3589 iCodeFromAst (ast * tree)
3591 returnLabel = newiTempLabel ("_return");
3592 entryLabel = newiTempLabel ("_entry");
3594 return reverseiCChain ();