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 - 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 (!TARGET_IS_Z80 && !TARGET_IS_GBZ80 && 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(type->next) && IS_FUNC(optype))) {
1623 werror(E_INCOMPAT_TYPES);
1627 } else { // from a pointer to a pointer
1628 if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80) {
1629 // if not a pointer to a function
1630 if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1631 if (implicit) { // if not to generic, they have to match
1632 if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
1633 werror(E_INCOMPAT_PTYPES);
1640 } else { // to a non pointer
1641 if (IS_PTR(optype)) { // from a pointer
1642 if (implicit) { // sneaky
1643 if (IS_INTEGRAL(type)) {
1644 werror(W_PTR2INTEGRAL_NOCAST);
1646 } else { // shouldn't do that with float, array or structure
1647 werror(E_INCOMPAT_TYPES);
1654 /* fprintf (stderr, "%s%s %d: ", op->operand.symOperand->name,
1655 implicit?"(implicit)":"", errors); */
1656 fprintf (stderr, "from type '");
1657 printTypeChain (optype, stderr);
1658 fprintf (stderr, "' to type '");
1659 printTypeChain (type, stderr);
1660 fprintf (stderr, "'\n");
1663 /* if they are the same size create an assignment */
1664 if (getSize (type) == getSize (optype) &&
1665 !IS_BITFIELD (type) &&
1667 !IS_FLOAT (optype) &&
1668 ((IS_SPEC (type) && IS_SPEC (optype)) ||
1669 (!IS_SPEC (type) && !IS_SPEC (optype))))
1672 ic = newiCode ('=', NULL, op);
1673 IC_RESULT (ic) = newiTempOperand (type, 0);
1674 SPIL_LOC (IC_RESULT (ic)) =
1675 (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
1676 IC_RESULT (ic)->isaddr = 0;
1680 ic = newiCode (CAST, operandFromLink (type),
1681 geniCodeRValue (op, FALSE));
1683 IC_RESULT (ic) = newiTempOperand (type, 0);
1686 /* preserve the storage class & output class */
1687 /* of the original variable */
1688 restype = getSpec (operandType (IC_RESULT (ic)));
1689 SPEC_SCLS (restype) = SPEC_SCLS (opetype);
1690 SPEC_OCLS (restype) = SPEC_OCLS (opetype);
1693 return IC_RESULT (ic);
1696 /*-----------------------------------------------------------------*/
1697 /* geniCodeLabel - will create a Label */
1698 /*-----------------------------------------------------------------*/
1700 geniCodeLabel (symbol * label)
1704 ic = newiCodeLabelGoto (LABEL, label);
1708 /*-----------------------------------------------------------------*/
1709 /* geniCodeGoto - will create a Goto */
1710 /*-----------------------------------------------------------------*/
1712 geniCodeGoto (symbol * label)
1716 ic = newiCodeLabelGoto (GOTO, label);
1720 /*-----------------------------------------------------------------*/
1721 /* geniCodeMultiply - gen intermediate code for multiplication */
1722 /*-----------------------------------------------------------------*/
1724 geniCodeMultiply (operand * left, operand * right,int resultIsInt)
1731 /* if they are both literal then we know the result */
1732 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1733 return operandFromValue (valMult (left->operand.valOperand,
1734 right->operand.valOperand));
1736 if (IS_LITERAL(retype)) {
1737 p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
1740 resType = usualBinaryConversions (&left, &right);
1742 rtype = operandType (right);
1743 retype = getSpec (rtype);
1744 ltype = operandType (left);
1745 letype = getSpec (ltype);
1749 SPEC_NOUN(getSpec(resType))=V_INT;
1752 /* if the right is a literal & power of 2 */
1753 /* then make it a left shift */
1754 /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
1755 efficient in most cases than 2 bytes result = 2 bytes << literal
1756 if port has 1 byte muldiv */
1757 if (p2 && !IS_FLOAT (letype) &&
1758 !((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
1759 (port->support.muldiv == 1)))
1761 if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
1763 /* LEFT_OP need same size for left and result, */
1764 left = geniCodeCast (resType, left, TRUE);
1765 ltype = operandType (left);
1767 ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
1771 ic = newiCode ('*', left, right); /* normal multiplication */
1772 /* if the size left or right > 1 then support routine */
1773 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1777 IC_RESULT (ic) = newiTempOperand (resType, 1);
1780 return IC_RESULT (ic);
1783 /*-----------------------------------------------------------------*/
1784 /* geniCodeDivision - gen intermediate code for division */
1785 /*-----------------------------------------------------------------*/
1787 geniCodeDivision (operand * left, operand * right)
1792 sym_link *rtype = operandType (right);
1793 sym_link *retype = getSpec (rtype);
1794 sym_link *ltype = operandType (left);
1795 sym_link *letype = getSpec (ltype);
1797 resType = usualBinaryConversions (&left, &right);
1799 /* if the right is a literal & power of 2 */
1800 /* then make it a right shift */
1801 if (IS_LITERAL (retype) &&
1802 !IS_FLOAT (letype) &&
1803 (p2 = powof2 ((unsigned long)
1804 floatFromVal (right->operand.valOperand)))) {
1805 ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
1809 ic = newiCode ('/', left, right); /* normal division */
1810 /* if the size left or right > 1 then support routine */
1811 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1814 IC_RESULT (ic) = newiTempOperand (resType, 0);
1817 return IC_RESULT (ic);
1819 /*-----------------------------------------------------------------*/
1820 /* geniCodeModulus - gen intermediate code for modulus */
1821 /*-----------------------------------------------------------------*/
1823 geniCodeModulus (operand * left, operand * right)
1829 /* if they are both literal then we know the result */
1830 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1831 return operandFromValue (valMod (left->operand.valOperand,
1832 right->operand.valOperand));
1834 resType = usualBinaryConversions (&left, &right);
1836 /* now they are the same size */
1837 ic = newiCode ('%', left, right);
1839 /* if the size left or right > 1 then support routine */
1840 if (getSize (ltype) > 1 || getSize (rtype) > 1)
1842 IC_RESULT (ic) = newiTempOperand (resType, 0);
1845 return IC_RESULT (ic);
1848 /*-----------------------------------------------------------------*/
1849 /* geniCodePtrPtrSubtract - subtracts pointer from pointer */
1850 /*-----------------------------------------------------------------*/
1852 geniCodePtrPtrSubtract (operand * left, operand * right)
1858 /* if they are both literals then */
1859 if (IS_LITERAL (letype) && IS_LITERAL (retype))
1861 result = operandFromValue (valMinus (left->operand.valOperand,
1862 right->operand.valOperand));
1866 ic = newiCode ('-', left, right);
1868 IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
1872 return geniCodeDivision (result,
1873 operandFromLit (getSize (ltype->next)));
1876 /*-----------------------------------------------------------------*/
1877 /* geniCodeSubtract - generates code for subtraction */
1878 /*-----------------------------------------------------------------*/
1880 geniCodeSubtract (operand * left, operand * right)
1887 /* if they both pointers then */
1888 if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
1889 (IS_PTR (rtype) || IS_ARRAY (rtype)))
1890 return geniCodePtrPtrSubtract (left, right);
1892 /* if they are both literal then we know the result */
1893 if (IS_LITERAL (letype) && IS_LITERAL (retype)
1894 && left->isLiteral && right->isLiteral)
1895 return operandFromValue (valMinus (left->operand.valOperand,
1896 right->operand.valOperand));
1898 /* if left is an array or pointer */
1899 if (IS_PTR (ltype) || IS_ARRAY (ltype))
1901 isarray = left->isaddr;
1902 right = geniCodeMultiply (right,
1903 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
1904 resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
1907 { /* make them the same size */
1908 resType = usualBinaryConversions (&left, &right);
1911 ic = newiCode ('-', left, right);
1913 IC_RESULT (ic) = newiTempOperand (resType, 1);
1914 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
1916 /* if left or right is a float */
1917 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
1921 return IC_RESULT (ic);
1924 /*-----------------------------------------------------------------*/
1925 /* geniCodeAdd - generates iCode for addition */
1926 /*-----------------------------------------------------------------*/
1928 geniCodeAdd (operand * left, operand * right,int lvl)
1936 /* if left is an array then array access */
1937 if (IS_ARRAY (ltype))
1938 return geniCodeArray (left, right,lvl);
1940 /* if the right side is LITERAL zero */
1941 /* return the left side */
1942 if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
1945 /* if left is literal zero return right */
1946 if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
1949 /* if left is an array or pointer then size */
1952 isarray = left->isaddr;
1953 // there is no need to multiply with 1
1954 if (getSize(ltype->next)!=1) {
1955 size = operandFromLit (getSize (ltype->next));
1956 right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
1958 resType = copyLinkChain (ltype);
1961 { /* make them the same size */
1962 resType = usualBinaryConversions (&left, &right);
1965 /* if they are both literals then we know */
1966 if (IS_LITERAL (letype) && IS_LITERAL (retype)
1967 && left->isLiteral && right->isLiteral)
1968 return operandFromValue (valPlus (valFromType (letype),
1969 valFromType (retype)));
1971 ic = newiCode ('+', left, right);
1973 IC_RESULT (ic) = newiTempOperand (resType, 1);
1974 IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
1976 /* if left or right is a float then support
1978 if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
1983 return IC_RESULT (ic);
1987 /*-----------------------------------------------------------------*/
1988 /* aggrToPtr - changes an aggregate to pointer to an aggregate */
1989 /*-----------------------------------------------------------------*/
1991 aggrToPtr (sym_link * type, bool force)
1997 if (IS_PTR (type) && !force)
2000 etype = getSpec (type);
2004 /* if the output class is generic */
2005 if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER)
2006 DCL_PTR_CONST (ptype) = port->mem.code_ro;
2008 /* if the variable was declared a constant */
2009 /* then the pointer points to a constant */
2010 if (IS_CONSTANT (etype))
2011 DCL_PTR_CONST (ptype) = 1;
2013 /* the variable was volatile then pointer to volatile */
2014 if (IS_VOLATILE (etype))
2015 DCL_PTR_VOLATILE (ptype) = 1;
2019 /*-----------------------------------------------------------------*/
2020 /* geniCodeArray2Ptr - array to pointer */
2021 /*-----------------------------------------------------------------*/
2023 geniCodeArray2Ptr (operand * op)
2025 sym_link *optype = operandType (op);
2026 sym_link *opetype = getSpec (optype);
2028 /* set the pointer depending on the storage class */
2029 if ((DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2030 DCL_PTR_CONST (optype) = port->mem.code_ro;
2033 /* if the variable was declared a constant */
2034 /* then the pointer points to a constant */
2035 if (IS_CONSTANT (opetype))
2036 DCL_PTR_CONST (optype) = 1;
2038 /* the variable was volatile then pointer to volatile */
2039 if (IS_VOLATILE (opetype))
2040 DCL_PTR_VOLATILE (optype) = 1;
2046 /*-----------------------------------------------------------------*/
2047 /* geniCodeArray - array access */
2048 /*-----------------------------------------------------------------*/
2050 geniCodeArray (operand * left, operand * right,int lvl)
2053 sym_link *ltype = operandType (left);
2057 if (IS_PTR (ltype->next) && left->isaddr)
2059 left = geniCodeRValue (left, FALSE);
2061 return geniCodeDerefPtr (geniCodeAdd (left, right,lvl),lvl);
2064 right = geniCodeMultiply (right,
2065 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2067 /* we can check for limits here */
2068 if (isOperandLiteral (right) &&
2071 (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2073 werror (E_ARRAY_BOUND);
2074 right = operandFromLit (0);
2077 ic = newiCode ('+', left, right);
2079 IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2080 !IS_AGGREGATE (ltype->next) &&
2081 !IS_PTR (ltype->next))
2082 ? ltype : ltype->next), 0);
2084 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
2086 return IC_RESULT (ic);
2089 /*-----------------------------------------------------------------*/
2090 /* geniCodeStruct - generates intermediate code for structres */
2091 /*-----------------------------------------------------------------*/
2093 geniCodeStruct (operand * left, operand * right, bool islval)
2096 sym_link *type = operandType (left);
2097 sym_link *etype = getSpec (type);
2099 symbol *element = getStructElement (SPEC_STRUCT (etype),
2100 right->operand.symOperand);
2102 /* add the offset */
2103 ic = newiCode ('+', left, operandFromLit (element->offset));
2105 IC_RESULT (ic) = newiTempOperand (element->type, 0);
2107 /* preserve the storage & output class of the struct */
2108 /* as well as the volatile attribute */
2109 retype = getSpec (operandType (IC_RESULT (ic)));
2110 SPEC_SCLS (retype) = SPEC_SCLS (etype);
2111 SPEC_OCLS (retype) = SPEC_OCLS (etype);
2112 SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2114 if (IS_PTR (element->type))
2115 setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2117 IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2121 return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2124 /*-----------------------------------------------------------------*/
2125 /* geniCodePostInc - generate int code for Post increment */
2126 /*-----------------------------------------------------------------*/
2128 geniCodePostInc (operand * op)
2132 sym_link *optype = operandType (op);
2134 operand *rv = (IS_ITEMP (op) ?
2135 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2137 sym_link *rvtype = operandType (rv);
2140 /* if this is not an address we have trouble */
2143 werror (E_LVALUE_REQUIRED, "++");
2147 rOp = newiTempOperand (rvtype, 0);
2148 OP_SYMBOL(rOp)->noSpilLoc = 1;
2151 OP_SYMBOL(rv)->noSpilLoc = 1;
2153 geniCodeAssign (rOp, rv, 0);
2155 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2156 if (IS_FLOAT (rvtype))
2157 ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2159 ic = newiCode ('+', rv, operandFromLit (size));
2161 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2164 geniCodeAssign (op, result, 0);
2170 /*-----------------------------------------------------------------*/
2171 /* geniCodePreInc - generate code for preIncrement */
2172 /*-----------------------------------------------------------------*/
2174 geniCodePreInc (operand * op)
2177 sym_link *optype = operandType (op);
2178 operand *rop = (IS_ITEMP (op) ?
2179 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2181 sym_link *roptype = operandType (rop);
2187 werror (E_LVALUE_REQUIRED, "++");
2192 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2193 if (IS_FLOAT (roptype))
2194 ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2196 ic = newiCode ('+', rop, operandFromLit (size));
2197 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2201 return geniCodeAssign (op, result, 0);
2204 /*-----------------------------------------------------------------*/
2205 /* geniCodePostDec - generates code for Post decrement */
2206 /*-----------------------------------------------------------------*/
2208 geniCodePostDec (operand * op)
2212 sym_link *optype = operandType (op);
2214 operand *rv = (IS_ITEMP (op) ?
2215 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2217 sym_link *rvtype = operandType (rv);
2220 /* if this is not an address we have trouble */
2223 werror (E_LVALUE_REQUIRED, "--");
2227 rOp = newiTempOperand (rvtype, 0);
2228 OP_SYMBOL(rOp)->noSpilLoc = 1;
2231 OP_SYMBOL(rv)->noSpilLoc = 1;
2233 geniCodeAssign (rOp, rv, 0);
2235 size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2236 if (IS_FLOAT (rvtype))
2237 ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2239 ic = newiCode ('-', rv, operandFromLit (size));
2241 IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2244 geniCodeAssign (op, result, 0);
2250 /*-----------------------------------------------------------------*/
2251 /* geniCodePreDec - generate code for pre decrement */
2252 /*-----------------------------------------------------------------*/
2254 geniCodePreDec (operand * op)
2257 sym_link *optype = operandType (op);
2258 operand *rop = (IS_ITEMP (op) ?
2259 geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2261 sym_link *roptype = operandType (rop);
2267 werror (E_LVALUE_REQUIRED, "--");
2272 size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2273 if (IS_FLOAT (roptype))
2274 ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2276 ic = newiCode ('-', rop, operandFromLit (size));
2277 IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2281 return geniCodeAssign (op, result, 0);
2285 /*-----------------------------------------------------------------*/
2286 /* geniCodeBitwise - gen int code for bitWise operators */
2287 /*-----------------------------------------------------------------*/
2289 geniCodeBitwise (operand * left, operand * right,
2290 int oper, sym_link * resType)
2294 left = geniCodeCast (resType, left, TRUE);
2295 right = geniCodeCast (resType, right, TRUE);
2297 ic = newiCode (oper, left, right);
2298 IC_RESULT (ic) = newiTempOperand (resType, 0);
2301 return IC_RESULT (ic);
2304 /*-----------------------------------------------------------------*/
2305 /* geniCodeAddressOf - gens icode for '&' address of operator */
2306 /*-----------------------------------------------------------------*/
2308 geniCodeAddressOf (operand * op)
2312 sym_link *optype = operandType (op);
2313 sym_link *opetype = getSpec (optype);
2315 /* lvalue check already done in decorateType */
2316 /* this must be a lvalue */
2317 /* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2318 /* werror (E_LVALUE_REQUIRED,"&"); */
2323 p->class = DECLARATOR;
2325 /* set the pointer depending on the storage class */
2326 if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2327 DCL_PTR_CONST (p) = port->mem.code_ro;
2329 /* make sure we preserve the const & volatile */
2330 if (IS_CONSTANT (opetype))
2331 DCL_PTR_CONST (p) = 1;
2333 if (IS_VOLATILE (opetype))
2334 DCL_PTR_VOLATILE (p) = 1;
2336 p->next = copyLinkChain (optype);
2338 /* if already a temp */
2341 setOperandType (op, p);
2346 /* other wise make this of the type coming in */
2347 ic = newiCode (ADDRESS_OF, op, NULL);
2348 IC_RESULT (ic) = newiTempOperand (p, 1);
2349 IC_RESULT (ic)->isaddr = 0;
2351 return IC_RESULT (ic);
2353 /*-----------------------------------------------------------------*/
2354 /* setOClass - sets the output class depending on the pointer type */
2355 /*-----------------------------------------------------------------*/
2357 setOClass (sym_link * ptr, sym_link * spec)
2359 switch (DCL_TYPE (ptr))
2362 SPEC_OCLS (spec) = data;
2366 SPEC_OCLS (spec) = generic;
2370 SPEC_OCLS (spec) = xdata;
2374 SPEC_OCLS (spec) = code;
2378 SPEC_OCLS (spec) = idata;
2382 SPEC_OCLS (spec) = xstack;
2386 SPEC_OCLS (spec) = eeprom;
2395 /*-----------------------------------------------------------------*/
2396 /* geniCodeDerefPtr - dereference pointer with '*' */
2397 /*-----------------------------------------------------------------*/
2399 geniCodeDerefPtr (operand * op,int lvl)
2401 sym_link *rtype, *retype;
2402 sym_link *optype = operandType (op);
2404 /* if this is a pointer then generate the rvalue */
2405 if (IS_PTR (optype))
2407 if (IS_TRUE_SYMOP (op))
2410 op = geniCodeRValue (op, TRUE);
2413 op = geniCodeRValue (op, TRUE);
2416 /* now get rid of the pointer part */
2417 if (isLvaluereq(lvl) && IS_ITEMP (op))
2419 retype = getSpec (rtype = copyLinkChain (optype));
2423 retype = getSpec (rtype = copyLinkChain (optype->next));
2426 /* if this is a pointer then outputclass needs 2b updated */
2427 if (IS_PTR (optype))
2428 setOClass (optype, retype);
2430 op->isGptr = IS_GENPTR (optype);
2432 /* if the pointer was declared as a constant */
2433 /* then we cannot allow assignment to the derefed */
2434 if (IS_PTR_CONST (optype))
2435 SPEC_CONST (retype) = 1;
2437 op->isaddr = (IS_PTR (rtype) ||
2438 IS_STRUCT (rtype) ||
2443 if (!isLvaluereq(lvl))
2444 op = geniCodeRValue (op, TRUE);
2446 setOperandType (op, rtype);
2451 /*-----------------------------------------------------------------*/
2452 /* geniCodeUnaryMinus - does a unary minus of the operand */
2453 /*-----------------------------------------------------------------*/
2455 geniCodeUnaryMinus (operand * op)
2458 sym_link *optype = operandType (op);
2460 if (IS_LITERAL (optype))
2461 return operandFromLit (-floatFromVal (op->operand.valOperand));
2463 ic = newiCode (UNARYMINUS, op, NULL);
2464 IC_RESULT (ic) = newiTempOperand (optype, 0);
2466 return IC_RESULT (ic);
2469 /*-----------------------------------------------------------------*/
2470 /* geniCodeLeftShift - gen i code for left shift */
2471 /*-----------------------------------------------------------------*/
2473 geniCodeLeftShift (operand * left, operand * right)
2477 ic = newiCode (LEFT_OP, left, right);
2478 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2480 return IC_RESULT (ic);
2483 /*-----------------------------------------------------------------*/
2484 /* geniCodeRightShift - gen i code for right shift */
2485 /*-----------------------------------------------------------------*/
2487 geniCodeRightShift (operand * left, operand * right)
2491 ic = newiCode (RIGHT_OP, left, right);
2492 IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2494 return IC_RESULT (ic);
2497 /*-----------------------------------------------------------------*/
2498 /* geniCodeLogic- logic code */
2499 /*-----------------------------------------------------------------*/
2501 geniCodeLogic (operand * left, operand * right, int op)
2505 sym_link *rtype = operandType (right);
2506 sym_link *ltype = operandType (left);
2508 /* left is integral type and right is literal then
2509 check if the literal value is within bounds */
2510 if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2512 checkConstantRange(ltype,
2513 OP_VALUE(right), "compare operation", 1);
2516 ctype = usualBinaryConversions (&left, &right);
2518 ic = newiCode (op, left, right);
2519 IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2521 /* if comparing float
2522 and not a '==' || '!=' || '&&' || '||' (these
2524 if (IS_FLOAT(ctype) &&
2532 return IC_RESULT (ic);
2535 /*-----------------------------------------------------------------*/
2536 /* geniCodeUnary - for a a generic unary operation */
2537 /*-----------------------------------------------------------------*/
2539 geniCodeUnary (operand * op, int oper)
2541 iCode *ic = newiCode (oper, op, NULL);
2543 IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2545 return IC_RESULT (ic);
2548 /*-----------------------------------------------------------------*/
2549 /* geniCodeConditional - geniCode for '?' ':' operation */
2550 /*-----------------------------------------------------------------*/
2552 geniCodeConditional (ast * tree,int lvl)
2555 symbol *falseLabel = newiTempLabel (NULL);
2556 symbol *exitLabel = newiTempLabel (NULL);
2557 operand *cond = ast2iCode (tree->left,lvl+1);
2558 operand *true, *false, *result;
2560 ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
2564 true = ast2iCode (tree->right->left,lvl+1);
2566 /* move the value to a new Operand */
2567 result = newiTempOperand (operandType (true), 0);
2568 geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
2570 /* generate an unconditional goto */
2571 geniCodeGoto (exitLabel);
2573 /* now for the right side */
2574 geniCodeLabel (falseLabel);
2576 false = ast2iCode (tree->right->right,lvl+1);
2577 geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
2579 /* create the exit label */
2580 geniCodeLabel (exitLabel);
2585 /*-----------------------------------------------------------------*/
2586 /* geniCodeAssign - generate code for assignment */
2587 /*-----------------------------------------------------------------*/
2589 geniCodeAssign (operand * left, operand * right, int nosupdate)
2592 sym_link *ltype = operandType (left);
2593 sym_link *rtype = operandType (right);
2595 if (!left->isaddr && !IS_ITEMP (left))
2597 werror (E_LVALUE_REQUIRED, "assignment");
2601 /* left is integral type and right is literal then
2602 check if the literal value is within bounds */
2603 if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
2605 checkConstantRange(ltype,
2606 OP_VALUE(right), "= operation", 0);
2609 /* if the left & right type don't exactly match */
2610 /* if pointer set then make sure the check is
2611 done with the type & not the pointer */
2612 /* then cast rights type to left */
2614 /* first check the type for pointer assignement */
2615 if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
2616 compareType (ltype, rtype) < 0)
2618 if (compareType (ltype->next, rtype) < 0)
2619 right = geniCodeCast (ltype->next, right, TRUE);
2621 else if (compareType (ltype, rtype) < 0)
2622 right = geniCodeCast (ltype, right, TRUE);
2624 /* if left is a true symbol & ! volatile
2625 create an assignment to temporary for
2626 the right & then assign this temporary
2627 to the symbol this is SSA . isn't it simple
2628 and folks have published mountains of paper on it */
2629 if (IS_TRUE_SYMOP (left) &&
2630 !isOperandVolatile (left, FALSE) &&
2631 isOperandGlobal (left))
2635 if (IS_TRUE_SYMOP (right))
2636 sym = OP_SYMBOL (right);
2637 ic = newiCode ('=', NULL, right);
2638 IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
2639 SPIL_LOC (right) = sym;
2643 ic = newiCode ('=', NULL, right);
2644 IC_RESULT (ic) = left;
2647 /* if left isgptr flag is set then support
2648 routine will be required */
2652 ic->nosupdate = nosupdate;
2656 /*-----------------------------------------------------------------*/
2657 /* geniCodeSEParms - generate code for side effecting fcalls */
2658 /*-----------------------------------------------------------------*/
2660 geniCodeSEParms (ast * parms,int lvl)
2665 if (parms->type == EX_OP && parms->opval.op == PARAM)
2667 geniCodeSEParms (parms->left,lvl);
2668 geniCodeSEParms (parms->right,lvl);
2672 /* hack don't like this but too lazy to think of
2674 if (IS_ADDRESS_OF_OP (parms))
2675 parms->left->lvalue = 1;
2677 if (IS_CAST_OP (parms) &&
2678 IS_PTR (parms->ftype) &&
2679 IS_ADDRESS_OF_OP (parms->right))
2680 parms->right->left->lvalue = 1;
2682 parms->opval.oprnd =
2683 geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2685 parms->type = EX_OPERAND;
2688 /*-----------------------------------------------------------------*/
2689 /* geniCodeParms - generates parameters */
2690 /*-----------------------------------------------------------------*/
2692 geniCodeParms (ast * parms, int *stack, sym_link * fetype, symbol * func,int lvl)
2700 /* if this is a param node then do the left & right */
2701 if (parms->type == EX_OP && parms->opval.op == PARAM)
2703 geniCodeParms (parms->left, stack, fetype, func,lvl);
2704 geniCodeParms (parms->right, stack, fetype, func,lvl);
2708 /* get the parameter value */
2709 if (parms->type == EX_OPERAND)
2710 pval = parms->opval.oprnd;
2713 /* maybe this else should go away ?? */
2714 /* hack don't like this but too lazy to think of
2716 if (IS_ADDRESS_OF_OP (parms))
2717 parms->left->lvalue = 1;
2719 if (IS_CAST_OP (parms) &&
2720 IS_PTR (parms->ftype) &&
2721 IS_ADDRESS_OF_OP (parms->right))
2722 parms->right->left->lvalue = 1;
2724 pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2727 /* if register parm then make it a send */
2728 if (((parms->argSym && IS_REGPARM (parms->argSym->etype)) ||
2729 IS_REGPARM (parms->etype)) && !func->hasVargs)
2731 ic = newiCode (SEND, pval, NULL);
2736 /* now decide whether to push or assign */
2737 if (!(options.stackAuto || IS_RENT (fetype)))
2741 operand *top = operandFromSymbol (parms->argSym);
2742 geniCodeAssign (top, pval, 1);
2746 sym_link *p = operandType (pval);
2748 ic = newiCode (IPUSH, pval, NULL);
2750 /* update the stack adjustment */
2751 *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2758 /*-----------------------------------------------------------------*/
2759 /* geniCodeCall - generates temp code for calling */
2760 /*-----------------------------------------------------------------*/
2762 geniCodeCall (operand * left, ast * parms,int lvl)
2766 sym_link *type, *etype;
2769 if (!IS_FUNC(OP_SYMBOL(left)->type) &&
2770 !IS_CODEPTR(OP_SYMBOL(left)->type)) {
2771 werror (E_FUNCTION_EXPECTED);
2775 /* take care of parameters with side-effecting
2776 function calls in them, this is required to take care
2777 of overlaying function parameters */
2778 geniCodeSEParms (parms,lvl);
2780 /* first the parameters */
2781 geniCodeParms (parms, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
2783 /* now call : if symbol then pcall */
2784 if (IS_OP_POINTER (left) || IS_ITEMP(left))
2785 ic = newiCode (PCALL, left, NULL);
2787 ic = newiCode (CALL, left, NULL);
2789 IC_ARGS (ic) = left->operand.symOperand->args;
2790 type = copyLinkChain (operandType (left)->next);
2791 etype = getSpec (type);
2792 SPEC_EXTR (etype) = 0;
2793 IC_RESULT (ic) = result = newiTempOperand (type, 1);
2797 /* stack adjustment after call */
2798 ic->parmBytes = stack;
2803 /*-----------------------------------------------------------------*/
2804 /* geniCodeReceive - generate intermediate code for "receive" */
2805 /*-----------------------------------------------------------------*/
2807 geniCodeReceive (value * args)
2809 /* for all arguments that are passed in registers */
2813 if (IS_REGPARM (args->etype))
2815 operand *opr = operandFromValue (args);
2817 symbol *sym = OP_SYMBOL (opr);
2820 /* we will use it after all optimizations
2821 and before liveRange calculation */
2822 if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
2825 if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
2826 options.stackAuto == 0 &&
2827 /* !TARGET_IS_DS390) */
2828 (!(options.model == MODEL_FLAT24)) )
2833 opl = newiTempOperand (args->type, 0);
2835 sym->reqv->key = sym->key;
2836 OP_SYMBOL (sym->reqv)->key = sym->key;
2837 OP_SYMBOL (sym->reqv)->isreqv = 1;
2838 OP_SYMBOL (sym->reqv)->islocal = 0;
2839 SPIL_LOC (sym->reqv) = sym;
2843 ic = newiCode (RECEIVE, NULL, NULL);
2844 currFunc->recvSize = getSize (sym->etype);
2845 IC_RESULT (ic) = opr;
2853 /*-----------------------------------------------------------------*/
2854 /* geniCodeFunctionBody - create the function body */
2855 /*-----------------------------------------------------------------*/
2857 geniCodeFunctionBody (ast * tree,int lvl)
2864 /* reset the auto generation */
2870 func = ast2iCode (tree->left,lvl+1);
2871 fetype = getSpec (operandType (func));
2873 savelineno = lineno;
2874 lineno = OP_SYMBOL (func)->lineDef;
2875 /* create an entry label */
2876 geniCodeLabel (entryLabel);
2877 lineno = savelineno;
2879 /* create a proc icode */
2880 ic = newiCode (FUNCTION, func, NULL);
2881 /* if the function has parmas then */
2882 /* save the parameters information */
2883 ic->argLabel.args = tree->values.args;
2884 ic->lineno = OP_SYMBOL (func)->lineDef;
2888 /* for all parameters that are passed
2889 on registers add a "receive" */
2890 geniCodeReceive (tree->values.args);
2892 /* generate code for the body */
2893 ast2iCode (tree->right,lvl+1);
2895 /* create a label for return */
2896 geniCodeLabel (returnLabel);
2898 /* now generate the end proc */
2899 ic = newiCode (ENDFUNCTION, func, NULL);
2904 /*-----------------------------------------------------------------*/
2905 /* geniCodeReturn - gen icode for 'return' statement */
2906 /*-----------------------------------------------------------------*/
2908 geniCodeReturn (operand * op)
2912 /* if the operand is present force an rvalue */
2914 op = geniCodeRValue (op, FALSE);
2916 ic = newiCode (RETURN, op, NULL);
2920 /*-----------------------------------------------------------------*/
2921 /* geniCodeIfx - generates code for extended if statement */
2922 /*-----------------------------------------------------------------*/
2924 geniCodeIfx (ast * tree,int lvl)
2927 operand *condition = ast2iCode (tree->left,lvl+1);
2930 /* if condition is null then exit */
2934 condition = geniCodeRValue (condition, FALSE);
2936 cetype = getSpec (operandType (condition));
2937 /* if the condition is a literal */
2938 if (IS_LITERAL (cetype))
2940 if (floatFromVal (condition->operand.valOperand))
2942 if (tree->trueLabel)
2943 geniCodeGoto (tree->trueLabel);
2949 if (tree->falseLabel)
2950 geniCodeGoto (tree->falseLabel);
2957 if (tree->trueLabel)
2959 ic = newiCodeCondition (condition,
2964 if (tree->falseLabel)
2965 geniCodeGoto (tree->falseLabel);
2969 ic = newiCodeCondition (condition,
2976 ast2iCode (tree->right,lvl+1);
2979 /*-----------------------------------------------------------------*/
2980 /* geniCodeJumpTable - tries to create a jump table for switch */
2981 /*-----------------------------------------------------------------*/
2983 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
2985 int min = 0, max = 0, t, cnt = 0;
2992 if (!tree || !caseVals)
2995 /* the criteria for creating a jump table is */
2996 /* all integer numbers between the maximum & minimum must */
2997 /* be present , the maximum value should not exceed 255 */
2998 min = max = (int) floatFromVal (vch = caseVals);
2999 sprintf (buffer, "_case_%d_%d",
3000 tree->values.switchVals.swNum,
3002 addSet (&labels, newiTempLabel (buffer));
3004 /* if there is only one case value then no need */
3005 if (!(vch = vch->next))
3010 if (((t = (int) floatFromVal (vch)) - max) != 1)
3012 sprintf (buffer, "_case_%d_%d",
3013 tree->values.switchVals.swNum,
3015 addSet (&labels, newiTempLabel (buffer));
3021 /* if the number of case statements <= 2 then */
3022 /* it is not economical to create the jump table */
3023 /* since two compares are needed for boundary conditions */
3024 if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
3027 if (tree->values.switchVals.swDefault)
3028 sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3030 sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3032 falseLabel = newiTempLabel (buffer);
3034 /* so we can create a jumptable */
3035 /* first we rule out the boundary conditions */
3036 /* if only optimization says so */
3037 if (!optimize.noJTabBoundary)
3039 sym_link *cetype = getSpec (operandType (cond));
3040 /* no need to check the lower bound if
3041 the condition is unsigned & minimum value is zero */
3042 if (!(min == 0 && SPEC_USIGN (cetype)))
3044 boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3045 ic = newiCodeCondition (boundary, falseLabel, NULL);
3049 /* now for upper bounds */
3050 boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3051 ic = newiCodeCondition (boundary, falseLabel, NULL);
3055 /* if the min is not zero then we no make it zero */
3058 cond = geniCodeSubtract (cond, operandFromLit (min));
3059 setOperandType (cond, UCHARTYPE);
3062 /* now create the jumptable */
3063 ic = newiCode (JUMPTABLE, NULL, NULL);
3064 IC_JTCOND (ic) = cond;
3065 IC_JTLABELS (ic) = labels;
3070 /*-----------------------------------------------------------------*/
3071 /* geniCodeSwitch - changes a switch to a if statement */
3072 /*-----------------------------------------------------------------*/
3074 geniCodeSwitch (ast * tree,int lvl)
3077 operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3078 value *caseVals = tree->values.switchVals.swVals;
3079 symbol *trueLabel, *falseLabel;
3081 /* if we can make this a jump table */
3082 if (geniCodeJumpTable (cond, caseVals, tree))
3083 goto jumpTable; /* no need for the comparison */
3085 /* for the cases defined do */
3089 operand *compare = geniCodeLogic (cond,
3090 operandFromValue (caseVals),
3093 sprintf (buffer, "_case_%d_%d",
3094 tree->values.switchVals.swNum,
3095 (int) floatFromVal (caseVals));
3096 trueLabel = newiTempLabel (buffer);
3098 ic = newiCodeCondition (compare, trueLabel, NULL);
3100 caseVals = caseVals->next;
3105 /* if default is present then goto break else break */
3106 if (tree->values.switchVals.swDefault)
3107 sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3109 sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3111 falseLabel = newiTempLabel (buffer);
3112 geniCodeGoto (falseLabel);
3115 ast2iCode (tree->right,lvl+1);
3118 /*-----------------------------------------------------------------*/
3119 /* geniCodeInline - intermediate code for inline assembler */
3120 /*-----------------------------------------------------------------*/
3122 geniCodeInline (ast * tree)
3126 ic = newiCode (INLINEASM, NULL, NULL);
3127 IC_INLINE (ic) = tree->values.inlineasm;
3131 /*-----------------------------------------------------------------*/
3132 /* geniCodeArrayInit - intermediate code for array initializer */
3133 /*-----------------------------------------------------------------*/
3135 geniCodeArrayInit (ast * tree, operand *array)
3139 if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3140 ic = newiCode (ARRAYINIT, array, NULL);
3141 IC_ARRAYILIST (ic) = tree->values.constlist;
3143 operand *left=newOperand(), *right=newOperand();
3144 left->type=right->type=SYMBOL;
3145 OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3146 OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3147 ic = newiCode (ARRAYINIT, left, right);
3152 /*-----------------------------------------------------------------*/
3153 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
3154 /* particular case. Ie : assigning or dereferencing array or ptr */
3155 /*-----------------------------------------------------------------*/
3156 set * lvaluereqSet = NULL;
3157 typedef struct lvalItem
3164 /*-----------------------------------------------------------------*/
3165 /* addLvaluereq - add a flag for lvalreq for current ast level */
3166 /*-----------------------------------------------------------------*/
3167 void addLvaluereq(int lvl)
3169 lvalItem * lpItem = (lvalItem *)Safe_calloc (1, sizeof (lvalItem));
3172 addSetHead(&lvaluereqSet,lpItem);
3175 /*-----------------------------------------------------------------*/
3176 /* delLvaluereq - del a flag for lvalreq for current ast level */
3177 /*-----------------------------------------------------------------*/
3181 lpItem = getSet(&lvaluereqSet);
3182 if(lpItem) free(lpItem);
3184 /*-----------------------------------------------------------------*/
3185 /* clearLvaluereq - clear lvalreq flag */
3186 /*-----------------------------------------------------------------*/
3187 void clearLvaluereq()
3190 lpItem = peekSet(lvaluereqSet);
3191 if(lpItem) lpItem->req = 0;
3193 /*-----------------------------------------------------------------*/
3194 /* getLvaluereq - get the last lvalreq level */
3195 /*-----------------------------------------------------------------*/
3196 int getLvaluereqLvl()
3199 lpItem = peekSet(lvaluereqSet);
3200 if(lpItem) return lpItem->lvl;
3203 /*-----------------------------------------------------------------*/
3204 /* isLvaluereq - is lvalreq valid for this level ? */
3205 /*-----------------------------------------------------------------*/
3206 int isLvaluereq(int lvl)
3209 lpItem = peekSet(lvaluereqSet);
3210 if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3214 /*-----------------------------------------------------------------*/
3215 /* ast2iCode - creates an icodeList from an ast */
3216 /*-----------------------------------------------------------------*/
3218 ast2iCode (ast * tree,int lvl)
3220 operand *left = NULL;
3221 operand *right = NULL;
3224 /* set the global variables for filename & line number */
3226 filename = tree->filename;
3228 lineno = tree->lineno;
3230 block = tree->block;
3232 scopeLevel = tree->level;
3234 if (tree->type == EX_VALUE)
3235 return operandFromValue (tree->opval.val);
3237 if (tree->type == EX_LINK)
3238 return operandFromLink (tree->opval.lnk);
3240 /* if we find a nullop */
3241 if (tree->type == EX_OP &&
3242 (tree->opval.op == NULLOP ||
3243 tree->opval.op == BLOCK))
3245 ast2iCode (tree->left,lvl+1);
3246 ast2iCode (tree->right,lvl+1);
3250 /* special cases for not evaluating */
3251 if (tree->opval.op != ':' &&
3252 tree->opval.op != '?' &&
3253 tree->opval.op != CALL &&
3254 tree->opval.op != IFX &&
3255 tree->opval.op != LABEL &&
3256 tree->opval.op != GOTO &&
3257 tree->opval.op != SWITCH &&
3258 tree->opval.op != FUNCTION &&
3259 tree->opval.op != INLINEASM)
3262 if (IS_ASSIGN_OP (tree->opval.op) ||
3263 IS_DEREF_OP (tree) ||
3264 (tree->opval.op == '&' && !tree->right) ||
3265 tree->opval.op == PTR_OP)
3268 if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3269 (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3272 left = operandFromAst (tree->left,lvl);
3274 if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3275 left = geniCodeRValue (left, TRUE);
3279 left = operandFromAst (tree->left,lvl);
3281 if (tree->opval.op == INC_OP ||
3282 tree->opval.op == DEC_OP)
3285 right = operandFromAst (tree->right,lvl);
3290 right = operandFromAst (tree->right,lvl);
3294 /* now depending on the type of operand */
3295 /* this will be a biggy */
3296 switch (tree->opval.op)
3299 case '[': /* array operation */
3301 //sym_link *ltype = operandType (left);
3302 //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3303 left = geniCodeRValue (left, FALSE);
3304 right = geniCodeRValue (right, TRUE);
3307 return geniCodeArray (left, right,lvl);
3309 case '.': /* structure dereference */
3310 if (IS_PTR (operandType (left)))
3311 left = geniCodeRValue (left, TRUE);
3313 left = geniCodeRValue (left, FALSE);
3315 return geniCodeStruct (left, right, tree->lvalue);
3317 case PTR_OP: /* structure pointer dereference */
3320 pType = operandType (left);
3321 left = geniCodeRValue (left, TRUE);
3323 setOClass (pType, getSpec (operandType (left)));
3326 return geniCodeStruct (left, right, tree->lvalue);
3328 case INC_OP: /* increment operator */
3330 return geniCodePostInc (left);
3332 return geniCodePreInc (right);
3334 case DEC_OP: /* decrement operator */
3336 return geniCodePostDec (left);
3338 return geniCodePreDec (right);
3340 case '&': /* bitwise and or address of operator */
3342 { /* this is a bitwise operator */
3343 left = geniCodeRValue (left, FALSE);
3344 right = geniCodeRValue (right, FALSE);
3345 return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3348 return geniCodeAddressOf (left);
3350 case '|': /* bitwise or & xor */
3352 return geniCodeBitwise (geniCodeRValue (left, FALSE),
3353 geniCodeRValue (right, FALSE),
3358 return geniCodeDivision (geniCodeRValue (left, FALSE),
3359 geniCodeRValue (right, FALSE));
3362 return geniCodeModulus (geniCodeRValue (left, FALSE),
3363 geniCodeRValue (right, FALSE));
3366 return geniCodeMultiply (geniCodeRValue (left, FALSE),
3367 geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3369 return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3373 return geniCodeSubtract (geniCodeRValue (left, FALSE),
3374 geniCodeRValue (right, FALSE));
3376 return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3380 return geniCodeAdd (geniCodeRValue (left, FALSE),
3381 geniCodeRValue (right, FALSE),lvl);
3383 return geniCodeRValue (left, FALSE); /* unary '+' has no meaning */
3386 return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3387 geniCodeRValue (right, FALSE));
3390 return geniCodeRightShift (geniCodeRValue (left, FALSE),
3391 geniCodeRValue (right, FALSE));
3393 return geniCodeCast (operandType (left),
3394 geniCodeRValue (right, FALSE), FALSE);
3400 return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3404 operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3405 setOperandType (op, UCHARTYPE);
3416 return geniCodeLogic (geniCodeRValue (left, FALSE),
3417 geniCodeRValue (right, FALSE),
3420 return geniCodeConditional (tree,lvl);
3423 return operandFromLit (getSize (tree->right->ftype));
3427 sym_link *rtype = operandType (right);
3428 sym_link *ltype = operandType (left);
3429 if (IS_PTR (rtype) && IS_ITEMP (right)
3430 && right->isaddr && compareType (rtype->next, ltype) == 1)
3431 right = geniCodeRValue (right, TRUE);
3433 right = geniCodeRValue (right, FALSE);
3435 geniCodeAssign (left, right, 0);
3440 geniCodeAssign (left,
3441 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3443 geniCodeRValue (right, FALSE),FALSE), 0);
3447 geniCodeAssign (left,
3448 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3450 geniCodeRValue (right, FALSE)), 0);
3453 geniCodeAssign (left,
3454 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3456 geniCodeRValue (right, FALSE)), 0);
3459 sym_link *rtype = operandType (right);
3460 sym_link *ltype = operandType (left);
3461 if (IS_PTR (rtype) && IS_ITEMP (right)
3462 && right->isaddr && compareType (rtype->next, ltype) == 1)
3463 right = geniCodeRValue (right, TRUE);
3465 right = geniCodeRValue (right, FALSE);
3468 return geniCodeAssign (left,
3469 geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3475 sym_link *rtype = operandType (right);
3476 sym_link *ltype = operandType (left);
3477 if (IS_PTR (rtype) && IS_ITEMP (right)
3478 && right->isaddr && compareType (rtype->next, ltype) == 1)
3480 right = geniCodeRValue (right, TRUE);
3484 right = geniCodeRValue (right, FALSE);
3487 geniCodeAssign (left,
3488 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3494 geniCodeAssign (left,
3495 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3497 geniCodeRValue (right, FALSE)), 0);
3500 geniCodeAssign (left,
3501 geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3503 geniCodeRValue (right, FALSE)), 0);
3506 geniCodeAssign (left,
3507 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3509 geniCodeRValue (right, FALSE),
3511 operandType (left)), 0);
3514 geniCodeAssign (left,
3515 geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3517 geniCodeRValue (right, FALSE),
3519 operandType (left)), 0);
3522 geniCodeAssign (left,
3523 geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3525 geniCodeRValue (right, FALSE),
3527 operandType (left)), 0);
3529 return geniCodeRValue (right, FALSE);
3532 return geniCodeCall (ast2iCode (tree->left,lvl+1),
3535 geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3536 return ast2iCode (tree->right,lvl+1);
3539 geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3540 return ast2iCode (tree->right,lvl+1);
3543 geniCodeFunctionBody (tree,lvl);
3547 geniCodeReturn (right);
3551 geniCodeIfx (tree,lvl);
3555 geniCodeSwitch (tree,lvl);
3559 geniCodeInline (tree);
3563 geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
3570 /*-----------------------------------------------------------------*/
3571 /* reverseICChain - gets from the list and creates a linkedlist */
3572 /*-----------------------------------------------------------------*/
3579 while ((loop = getSet (&iCodeChain)))
3591 /*-----------------------------------------------------------------*/
3592 /* iCodeFromAst - given an ast will convert it to iCode */
3593 /*-----------------------------------------------------------------*/
3595 iCodeFromAst (ast * tree)
3597 returnLabel = newiTempLabel ("_return");
3598 entryLabel = newiTempLabel ("_entry");
3600 return reverseiCChain ();